タイトルままの話。
GCP では各プロダクトで出力したログが Cloud Logging に集約されて、横断的に見たり検索したりできて大変便利。フィルタして BigQuery に流し込めるのも最高オブ最高。仕事が楽になるっていうのはこういうことやで。
ただ、プロダクトごとにログコレクタの挙動が異なっていて微妙な気持ちになることがあるし、大抵 undocumented なんだよね。
特に、標準出力に JSON 文字列を書いた場合の挙動が
- AppEngine は stdout & stderr に構造化ログを書けることがドキュメントに書いてある
- Cloud Functions はドキュメントに書いていなくて、挙動もランタイムによってまちまち
- 大抵
textPayload
に JSON 文字列がそのまま入っていた
- 大抵
- Cloud Run は最近書かれるようになった? 前はなかった気が...
Cloud Functions の話をすると、2020/2 以前の Node10 Runtime で JSON を書いた場合は textPayload
として扱われていたものが、ある日からパースされるようになっていて、構造も Google.Protobuf.WellKnownTypes.Valueになってしまったりする(こういうのを Release Note に入れないのが GCP の良くないところだと思う)。
JSON を stdout に出力することで、Cloud Logging にこう書かれていたものが
{ "textPayload": "{\"runtime\":\"nodejs10\",\"key\":\"value\",\"array\":[1,2,3]}", }
ある日こういう構造になる
{ "jsonPayload": { "fields": { "array": { "Kind": { "ListValue": { "values": [ { "Kind": { "NumberValue": 1 } }, { "Kind": { "NumberValue": 2 } }, { "Kind": { "NumberValue": 3 } } ] } } }, "key": { "Kind": { "StringValue": "value" } }, "runtime": { "Kind": { "StringValue": "nodejs10" } } } } }
この構造は誰が嬉しいのか謎だけど、textPayload
を期待して BigQuery に転送していた人が、この jsonPayload
に変わったことで、ある日いきなり数百のカラムに直面して破滅してしまうという事件があった。かわいそう。
もちろん、Cloud Functions から狙った構造でログを書きたい場合は Cloud Logging クライアントライブラリを使うべきで、大抵そうしているんだけど、The Twelve-Factor App XI. ログ的にも、実行環境への依存を減らす面でも、stdout に書いて済むならそうしたい。実装も簡単になる。
昨晩、前述の Issueの Status が Fixed に更新されたので、大喜びで各ランタイムで動作確認をした。
cloud-functions-playground/write-json-stdout at master · pokutuna/cloud-functions-playground
僕が確認できた範囲ではこういう感じ
runtime | field |
---|---|
nodejs8 | textPayload |
nodejs10 | jsonPayload |
nodejs12 | jsonPayload |
go111 | jsonPayload |
go113 | jsonPayload |
python37 | textPayload |
python38 | jsonPayload |
java11 | jsonPayload |
Google.Protobuf.WellKnownTypes.Value のような構造に変換されることもなくなり、元の JSON の構造のまま jsonPayload
として保存されるようになっていた。deprecated な nodejs8 がそのままなのは分かるけど、python37 はなんでだろうね。
ともあれこれで大抵のランタイムで Cloud Functions においても構造化ログをクライアントライブラリなしで書けるようになった。
たぶん特殊フィールドも動いて { "logging.googleapis.com/trace": ... }
等のフィールドを標準出力に書けば trace として拾われると思うし、ちょっとしたログの検索もしやすくなる。
まあちゃんとしたい場合は依然クライアントライブラリを使うべきなので、サボりたい時に便利って感じなんですが...