まとめ
- バッチ処理用のスクリプトとwebサーバー用のスクリプトを分けておくと開発が捗る
- 所定のJSONをSTDOUTかSTDERRに流すとError Reportingにエラーを通知できる
ソースコード
Githubでforkしたリポジトリで、上流の変更をマージしています。こちらの詳細は別記事のGithub上のリポジトリの操作を自動化するdockerコンテナにて。
webserver.rb
require 'webrick'
require 'json'
srv = WEBrick::HTTPServer.new({ :DocumentRoot => './',
:BindAddress => '0.0.0.0',
:Port => ENV['PORT'].to_i})
srv.mount_proc '/' do |req, res|
res.body = `sh -e ./main.sh 2>&1`
STDOUT.puts res.body
STDOUT.flush
if $? != 0
res.status = 500
STDERR.puts JSON.generate(
"@type": 'type.googleapis.com/google.devtools.clouderrorreporting.v1beta1.ReportedErrorEvent',
message: 'ジョブの実行に失敗しました'
)
STDERR.flush
end
end
trap("INT"){ srv.shutdown }
srv.start
-
gem install
をしなくて良いように、Rubyに標準で入っている機能を使っています - Google Cloud Runでは、コンテナの環境変数に、公開するポート番号がPORTで渡ってくるので、そのポート番号でサーバーを建てます
- STDOUT/STDERRへの出力はそのままだとバッファリングされたままHTTPリクエストの処理が終わって出力されない場合があるので、明示的にflushしてます(
STDOUT.sync = true
とかでも良い) - Google Cloud Runには、ログをJSON形式で出力すると、自動的に構造化ログとしてStackdriver Loggingに送ってくれる機能があります
- ログのJSONが所定の形式に従っていればエラーとみなしてError Reportingに報告してくれます
- ここでは
@type
の指定がそれに該当します - スタックトレースを
message
に含める方法もあるようですが、そちらは未検証です - Error ReportingにはアカウントのGMailアドレスに通知メールを送ってくれる機能があります
- そこから、GMailのメールフィルタ機能とSlackの転送用のメールアドレスを設定する機能を使って、Slackで通知を受け取るようにしています
- ここでは
- Rubyのシェル実行機能を使って、本体である
main.sh
の処理を起動しています- 終了ステータスを
$?
で取得しています
- 終了ステータスを
- 定時実行のトリガーはCloud Schedulerを使います
- Cloud Scheduler上ではHTTPステータスで成否を判断しているので、それにあわせてHTTPステータスを返すようにしています(エラー通知はログ経由で受け取っているので現状はあまり意味はありません)