構造化ログのタイムスタンプ形式

みんなtai64nを使おう。と言いたいところだけれど、サポートしてるところが見当たらないのでナシだ。

個人的に好きなのはナノ秒単位のUnixタイムスタンプだ。 OpenTelemetryのOTLPでもナノ秒タイムスタンプを使っている。

  "logRecords": [
    {
      "timeUnixNano": "1544712660300000000",

(opentelemetry-protoのexample より)

しかし、これはスキーマが厳密に定義されているOTLPだからこそできる事であって、普通にJSON linesのログをあちこちで扱うには問題がある。

  • レコード名が "time" や "timestamp" だとナノ秒なのかマイクロ秒なのかわかりにくい
  • そもそも人間はUnixタイムスタンプを読めるようにできていない

整数の代わりに実数を使えば、精度はマイクロ秒に落ちてしまうものの、単位が秒だと自然に判断できるので前者の問題は解決できそうに思える。しかし、DataDogの場合はUnix epochからのミリ秒をタイムスタンプとして採用しているので、カスタマイズが必要になる。

https://docs.datadoghq.com/logs/log_configuration/pipelines/?tab=date#date-attribute

BigQueryの場合はフィールドをタイムスタンプ型だと指定すると秒単位の実数として扱うようだ。Unixミリ秒のサポートは見つからない。

Loading JSON data from Cloud Storage  |  BigQuery  |  Google Cloud

UnixタイムスタンプもあきらめてISO8601を使えば、サービスによる精度の解釈違いも起きないし、JSONを直接人間が読む時も読みやすくなる。日付と時間の区切りはTよりもスペースの方が読みやすいので "YYYY-MM-DD hh:mm:ss.ssssssZ" 形式にしても良いだろう。

ログ管理ツールは運用メンバーのタイムゾーンが多様である前提で作られていることが多いのでUIから表示するタイムゾーンを選べるし、BigQueryでも "+0900" をつけていてもUTCに変換して取り込まれるそうだ。それでも運用チームが日本ローカルでメンバーがJSONをそのまま読む機会が多いなら、ローカルタイムを使って末尾に"+0900"をつけるのでもいいだろう。

dev.classmethod.jp

このブログに乗せているコードは引用を除き CC0 1.0 で提供します。