開発本部 認証連携チームでエンジニアをしている、id:ruru8net です。
これはClassi developers Advent Calendar 2021の9日目の記事です。
昨日の記事はこちらです。
Hardening 2021 Active Fault 参加レポート - 桐生あんずです
以前のClassi Advent Calender 2019では新卒が入社半年で社内サービスをリリースしてエンジニア楽しいってなったお話を書かせていただきましたが、あれから2年の間に業務の中で様々な経験をし、さらに知識やスキルを身につけていくことができました。
今日はその中でも自分が担当しているサービスの、バッチ監視の仕組みを考えたので紹介させてください。
背景
担当チームでは毎日深夜2時にDBからデータを削除するバッチを動かしています。
他にも社内では様々なバッチが動いていますが、これらを監視する仕組みは社内で確立されていませんでした。
そのためサービス稼働に影響の少ないバッチは実行中に問題があったり、そもそも実行されていなかったりしても検知されず、見過ごされてしまうことが多かったです。
弊社ではサービスの監視にDatadogを使用しているため、この監視体制にそのままバッチの監視を組み込むことでバッチの監視ができていない状態を是正したいと考えました。
前提
バッチファイル
Ruby on Railsを使い、rake taskとして実行させています。
バッチの仕組み
Amazon EventBridgeにてECS Fargateのタスクを起動させ、実行しています。これは既にdatadog-agentコンテナが動いている前提です。datadog-agentコンテナの設定方法は以下のURLを参考にしました。
https://docs.datadoghq.com/ja/integrations/ecs_fargate
使用する監視、通知ツール
- Datadog
- Slack
監視したいこと
バッチ実行において監視したいことは以下です。
定期的な実行の成功と失敗
- バッチ実行中に例外が発生した場合の検知
- バッチ実行用のタスクの起動自体がされなかった場合の検知
- 例外を発生せずに何らかの理由でバッチ実行のコンテナが終了してしまった場合の検知
実行時間の異常
今回は定期的な実行の成功と失敗をメインとして、
バッチ実行中に例外が発生した場合の検知
- →発生した例外をDatadog Eventとしてエラーを送信。DatadogのMonitorにてエラー通知を監視するMonitorを作成しエラーが送られてきた場合はslackにアラートを送信する。
バッチの起動自体がされなかった場合の検知
- →バッチ実行の成功をDatadog Eventとして送信。DatadogのMonitorにて成功通知を監視するMonitorを作成し、成功通知が送られてこなかった場合はSlackにアラートを送信する。
という監視の仕組みを作っていきます。
手順
1. dogstatsd-rubyを使ってバッチのスクリプトファイルにDatadogへEventを送信するよう書く
DatadogにEventを送信する方法は4つあります。
- Custom Agent Check
- DogStatsD
- Datadog API
今回のようにsidecarコンテナとしてdatadog-agentを起動させているのであればDogStatsDを使ってEventを送るのがやりやすいと思います。
今回はRubyで書いているので基本的にはDatadogのドキュメントに書いてあるExampleと、使用するgemであるdogstatsd-rubyのドキュメントを参考にコードを書きました。 docs.datadoghq.com github.com
▽作成したバッチのスクリプトファイル
require 'datadog/statsd' task batch: :environment do begin begin # バッチの実行時間を計測 execution_time = Benchmark.measure do ### # 実行処理内容は省略 ### end statsd = Datadog::Statsd.new(logger: logger, single_thread: true, buffer_max_pool_size: 1) begin # バッチの実行が完了したら成功Eventを送る statsd.event( 'データを削除するバッチ', # Eventのタイトル "バッチ実行時間 #{execution_time.real}s", # 好きな内容をメッセージとして送れる alert_type: 'success', tags: ['env: development', 'service:rails-app'] # タグを指定 ) rescue => e logger.error e ensure statsd.close() end rescue => e begin # バッチ実行中に問題が発生した場合はエラーEventを送る statsd = Datadog::Statsd.new(logger: logger, single_thread: true, buffer_max_pool_size: 1) statsd.event( 'データを削除するバッチ', "#{e.class}:#{e.message}", alert_type: 'error', tags: ['env: development', 'service:rails-app'] ) logger.info 'Datadogへのエラー通知送信完了' rescue => e logger.error e ensure statsd.close() end end end end def logger Rails.logger end
解説
statsd = Datadog::Statsd.new(logger: logger, single_thread: true, buffer_max_pool_size: 1)
statsdのインスタンスを作成します。
dogstatd-rubyのバージョンや必要に応じてオプションをつけてください。
https://github.com/DataDog/dogstatsd-ruby#migrating-from-v4x-to-v5x https://www.rubydoc.info/github/DataDog/dogstatsd-ruby/Datadog/Statsd
begin # バッチの実行が完了したら成功Eventを送る statsd.event( 'データを削除するバッチ', # Eventのタイトル "バッチ実行時間 #{execution_time.real}s", # 好きな内容をメッセージとして送れる alert_type: 'success', tags: ['env: development', 'service:rails-app'] # タグを指定 ) rescue => e logger.error e ensure statsd.close() end
eventメソッドが取れるパラメータやオプションはこちらに書いてあります。 www.rubydoc.info
またドキュメントに書いてある通り、DogStatsDのクライアントが不要になった時には適切に破棄をするためにstatsd.close()
します。
2.バッチを走らせてeventがDatadogに送られているかを確認する
https://app.datadoghq.com/event/stream にてeventの一覧が確認できます。
左上の検索欄に、eventのタイトルやタグで検索ができます。
このときの検索で、eventが一意に絞り込めるようなタイトル、タグをつけるようにしてください。
またメッセージの内容も一緒に出力されます。
ですので、ここに実行時間や、実行完了したときに欲しい情報を出力させておくと確認がしやすいです。
event例
状態 | |
---|---|
成功時 | ![]() |
例外発生時 | ![]() |
3. Datadog Monitorを作成する
Monitors > + New Monitor > Event を選択します。
するとMonitor作成画面になります。今回は「バッチ実行中に例外が発生した場合の検知」と「バッチの起動自体がされなかった場合の検知」をする2つのMonitorを作成します。
バッチ実行中に例外が発生した場合の検知
エラーeventのみを絞り込むように設定し、alert conditionsをセットします。今回は24時間に一回動くバッチのため、24hours
を選択、また1つでもエラーeventを受け取ったらalertとして発火させたいのでAlert Thresholdを1にしています。
バッチの起動自体がされなかった場合の検知
成功eventのみを絞り込むように設定します。
またeventをカウントする期間を24hours
にしてしまうと、前回のeventからきっかり24時間以内にeventが来ないとalertとなってしまうので、余裕を持たせるために25hours
にしておきます。
対象期間1つも成功eventがない場合はバッチの起動がされなかったとみなしalertを送るように、Alert Thresholdを1にします。
③で通知させたい先のslackチャンネル(slack-{チャンネル名}
となっているもの)を選択します。
(DatadogとSlack連携のセットアップはこちら
https://docs.datadoghq.com/ja/integrations/slack/?tab=slackapplicationus)
④ではslackに投稿する際のテンプレートを作成します。
ここでは色々な変数やMarkdownが使えます。
4. Monitorで設定した通りにslackに通知が来ることを確認
Monitor作成時の右下にあるTest Notifications
で確認ができます。
下のようにSlackに通知が送られるようになりました。
バッチ実行中にエラーが発生した場合の通知 | バッチの実行確認ができなかった場合の通知 |
---|---|
![]() |
![]() |
おわりに
実装について
DogstatsDによるEvent送信はバッチ処理中への埋め込みがしやすくとても使いやすかったです。
またバッチに限らず監視の仕組みを考える時にはまず、「何を監視したいのか」を整理するのがとても大事だなと思います。
今回は実行の監視のみしかできていませんが、今後は実行時間がかかり過ぎていた場合にalertを発報できるような仕組みも監視の項目に入れていきたいです。
(現状はeventのメッセージに対してMonitorを作成する方法が見つからず、別の方法を模索中です。)
監視の仕組み構築について
社内で確立されていなかったバッチの監視に対して、この仕組みを社内展開することができ、他のチームの人たちからも喜んでいただけたので嬉しかったです。
自分のチームだけでなく他のチームにとっても役に立つような仕組みづくりというのを意識して今後も頑張っていきたいです。
明日のClassi developers Advent Calendar 2021の担当はTomoya Namekawaさんです。お楽しみに。