kmuto’s blog

はてな社でMackerel CREをやっています。料理と旅行といろんなIT技術

OpenTelemetryメトリックをTSVに書き出すツール「hikaemetric」を作ってみた

OpenTelemetryメトリックを後からスプレッドシートなどで集計・分析したいときに、オブザーバビリティプラットフォームではクエリを書く必要があったり、あるいはそもそもダウンロードができなかったりと、話が大げさになることがある。

コレクターでFile Exporterを使ってJSONで書き出し、あとでプログラムでがんばってCSV/TSV化する手もなくはないが、手間ではあるし、「そもそもそのプログラムで集計・分析すればいいのでは…?」というオチになってしまいそうだ。

ということで、メトリックを受けてTSVに書き出すツール「hikaemetric(控えメトリック)」を作ってみた。

github.com

使い方

hikaemetricは、OTLPメトリックをHTTP/Protobuf形式で受け取り、TSVファイルに書き出すツールである。OpenTelemetryコレクターから本来の投稿先のほかにhikaemetricにも送るようにすることで、スプレッドシートで解析しやすいTSVファイルが書き出される。

Releases でLinuxパッケージやmacOS、Windowsのバイナリを提供しているので、これをダウンロードする。

実行する hikaemetric コマンドにはいくつかオプションを用意している。

  • -port <ポート番号>:OTLP HTTP受信ポート。デフォルトは14318
  • -output <出力フォルダ>:TSVファイルを書き出すフォルダ。デフォルトは.(カレントフォルダ)
  • -resource-attrs <属性1>,<属性2>,...:TSVに含めるリソース属性の名前(カンマ区切り)。デフォルトは指定なし
  • -attrs <属性1>,<属性2>,...:TSVに含める属性の名前(カンマ区切り)。デフォルトは指定なし
  • -timezone <タイムゾーン>:タイムスタンプおよびファイルローテーションのタイムゾーン(Asia/Tokyoなど)。デフォルトはシステムローカル時刻

たとえば出力はoutフォルダに置き、リソース属性host.nameと属性methodstatus_codeをTSVに含めるには、以下のように実行する。

hikaemetric -output out -resource-attrs host.name,service.version -attrs method,status_code

OpenTelemetryコレクターのexportersでは、本来のエクスポート先のほかにhikaemetricにも投稿するようにパイプラインを設定する。

...

exporters:
  otlp_http/platform:
    endpoint: https://your-platform.example.com
  otlp_http/hikae:
    endpoint: http://localhost:14318

service:
  pipelines:
    metrics:
      exporters: [otlp_http/platform, otlp_http/hikae]

hikaemetricがメトリックを受け取ると、メトリックの投稿時刻情報に基づいて<サービス名前空間>-<サービス名>-YYYYMMDD.tsv (サービス名前空間の設定がないときにはサービス名-YYYYMMDD.tsv)のファイルが生成され、以降追記されていく。以下はproduction-api-20260830.tsvとして作成されたファイルの例だ。

timestamp name    type    value   unit    resource.host.name  resource.service.version    method  status_code
2026-08-30T15:14:21+09:00   system.cpu.usage    gauge   48.61767752 %   api-01          
2026-08-30T15:14:21+09:00   runtime.goroutines  gauge   36  1   api-01          
2026-08-30T15:14:21+09:00   http.requests.total counter 4543    1   api-01      DELETE  400
2026-08-30T15:14:21+09:00   http.request.duration   histogram   {"count":115,"sum":404.3074716587114,"bucket_counts":[0,13,43,19,31,9],"boundaries":[5,10,25,50,100]}   ms  api-01      POST    
2026-08-30T15:14:21+09:00   http.request.size   exponential_histogram   {"count":62,"sum":101.10702257825294,"zero_count":3,"scale":3,"positive":{"offset":1,"bucket_counts":[18,17,16,11]},"negative":{"offset":0,"bucket_counts":[1,3]}}  By  api-01          
2026-08-30T15:14:21+09:00   rpc.server.duration summary 5443.124979 ms  api-01          

実装の面白どころ

ヒストグラム値の表現の割り切り

counterやgaugeのように1つの値しか入らない型はシンプルに表現できる。しかし、OpenTelemetryメトリックには複数値を持つ「ヒストグラム」と「Exponentialヒストグラム」という型もあり、これらはTSV上で綺麗に表現することは困難である。

少し悩んだものの、TSVで集計・分析したいという場面でこのヒストグラムが対象になっていることはない気がするし、「必要な情報は入れておくのでそちらでがんばってくれ」として、JSON形式文字列を数値の代わりに入れることにした。

{"count":115,"sum":404.3074716587114,"bucket_counts":[0,13,43,19,31,9],"boundaries":[5,10,25,50,100]}

属性の明示選択

メトリックに含まれているリソース属性と属性については、「全部を列に入れても嬉しいことはさほどないのでは?」という推測で、明に選択したものだけを取り込むようにしている。もし属性名に,やら空白やらが入っていたときにどうするかはいったん考慮外とした。リソース属性と属性は理論上同じ名前を付け得るので、リソース属性側にはresource.というプリフィクスが凡例ヘッダに付いている。

時刻の判定

タイムスタンプやローテーションなど、時刻の管理については若干トリッキーなことをしている。

タイムゾーンがUTC(世界協定時)で動いているOSで取り込んでも、日本のサービスであれば分析はJST(日本時間・UTC+9)でやりたいことが一般的だろう。そのため、デフォルトはシステム定義のローカル時刻を参照するとして、タイムスタンプとローテーションに使うタイムゾーンについてはtimezoneオプションで調整できるようにした。

また、日付が変わってファイルをローテーションしたものの、前日の投稿時刻でのメトリックが到着する可能性もある。保存先を投稿時刻の日にするか受信時刻の日にするかは考えどころだが、投稿時刻を尊重するほうが期待する動作と考えて、都度メトリックの投稿時刻を解析して該当日のファイルに書き出すようにした(順序の調整はさすがに無理なので、あとでソートしてもらおう)。効率のためにファイルハンドルはキャッシングしている。

Claude Codeとの対話

設計は手で書いてClaude Codeとグリルしながら詰めていき、コーディングはほぼ全部Claude Codeにやらせ、特におかしなところはなさそうだった。GitHub Actionsまわりは「これを参考に」としていたものが古くて、「Node.js 20 is deprecated.」のアクション警告が出てしまっていた。全体を最新にするよう指示して対処した。

一番時間がかかったのがいつものようにツールのネーミングなのだが、AI対話の結果、「メトリックを本編とは別にひっそり記録して控えておくもの」という意図で名付けている。

まとめ

オブザーバビリティプラットフォームのメトリック機能では痒いところに手が届かない!という場面に特化した割り切ったツールではあるが、手慣れたExcelなりGoogleスプレッドシートなりで分析したい方々向けにはけっこう便利なものになったのではと思う。

ご意見・ご要望などあればissueでご連絡ください。

github.com