Hateburo: kazeburo hatenablog

SRE / 運用系小姑 / Goを書くPerl Monger

JSONL ログから柔軟にメトリクスを生成する ― mackerel-plugin-jsonl を作った話

この記事はMackerelアドベントカレンダー2025 15日目の記事です。

qiita.com

今年作ったmackerel-pluginの紹介として、mackerel-plugin-jsonl を紹介します。

リポジトリ: github.com

このプラグインは、JSON Lines(JSONL)形式のログを読み取り、「複数の」任意のキーを集計して Mackerel のカスタムメトリクスとして送信するためのものです。 サーバローカルに蓄積される JSON ログを手軽に可視化したい、あるいはアクセスログ解析の代替として使いたい、というニーズがあるのではないかとふと思い、開発しました。

JSON ログがスタンダードになった今、ローカルでメトリクス化する選択肢

近年、アプリケーションのログ出力形式としてはJSON形式が事実上の標準となっています。 構造化されているため扱いやすく、クラウド基盤においても解析しやすいため、コンテナ環境・マイクロサービス環境では特に一般的です。

さくらのクラウドで今年リリースしたモニタリングスイートなどの「ログの収集・保管・検索・分析サービス」を活用するケースが増えています。こうしたサービスを使えば集中管理ができ、運用効率も良くなります。

cloud.sakura.ad.jp

一方で、さまざまな要件から依然としてサーバ上のログをその場で集計してメトリクス化したいという場面もあります。

mackerel-plugin-axslog のパフォーマンス、そして汎用化

以前、LTSVとJSON形式のWebサーバのアクセスログを読み取り Mackerel メトリクスを生成するプラグイン mackerel-plugin-axslog を開発しています。

github.com

axslogはアクセスログ特有の形式に特化したため、導入は簡単でかつ、パフォーマンスは高くなっています。しかし、汎用性は高くありません。

kazeburo.hatenablog.com

汎用的な JSON を扱える mackerel-plugin-json をfluentbitの監視に利用した際に、これは便利だと感動し、 「ログを行単位で処理できる JSONL 版があれば、もっと使いやすいはずだ」 というアイディアが生まれ、今回 JSONL に特化したメトリクス生成プラグインを作りました

cohalz.co

mackerel-plugin-jsonl の特徴

mackerel-plugin-jsonl は以下のような特徴を持っています。

1. JSON Lines(JSONL)形式のログ読み取りに特化

各行が JSON であるログ形式にシンプルに対応できます。 例:

{"status":200,"latency":34,"path":"/api/users"}
{"status":500,"latency":123,"path":"/api/users"}

2. 任意のキーを抽出し集計可能

設定ファイルで、どのキーをメトリクス化するか指定できます。

  • カウンタとして集計
  • 数値フィールドの合計/平均などの簡易集計
  • ステータスコード別のカウントなどにも対応

3. 軽量でシンプルな動作

ログを tail しながら集計し、Mackerel Agent 経由でメトリクスを送信します。

4. mackerel-plugin-json と異なるユースケースに最適化

JSON ファイルの全体構造を扱うのではなく、“ログ行単位の処理” を行います。

使い方

最も簡単な使い方は、以下のようにプラグインを実行し、ログファイルを指定するだけです。

インストール

$mkr plugin install kazeburo/mackerel-plugin-jsonl

基本的な実行例

./mackerel-plugin-jsonl \
    --key-name status \
    --json-key status \
    --aggregator group_by \
    --key-name latency \
    --json-key latency \
    --aggregator percentile \
    --log-file /path/to/your.log \
    --prefix jsonl

上記例では、

  • status の値ごとに件数をカウント
  • latency を数値として読み取り、合計・平均をメトリクスとして生成

といった処理を行うことができます。

一般的なJSON形式のWebサーバのアクセスログの例

ほぼaxslogと同じ動きをする例です

% /path/to/mackerel-plugin-jsonl --prefix json --log-file json.log \
  -k total.count -j time -a count \
  -k status -j 'status|replace("^(?:([1235])\d{2}|(4)(?:[0-8]\d|9[0-8]))$","${1}${2}xx")|have("2xx","3xx","4xx","499","5xx")' -a group_by_with_percentage \
  -k latency -j reqtime -a percentile

以上を実行すると、以下のアウトプットが得られます

json.total.count        4800000.000000  1760339314
json.status.3xx 684256.000000   1760339314
json.status.4xx 1370792.000000  1760339314
json.status.499 344392.000000   1760339314
json.status.5xx 1031020.000000  1760339314
json.status.2xx 1369540.000000  1760339314
json.status_percentage.2xx      28.532083       1760339314
json.status_percentage.3xx      14.255333       1760339314
json.status_percentage.4xx      28.558167       1760339314
json.status_percentage.499      7.174833        1760339314
json.status_percentage.5xx      21.479583       1760339314
json.latency.mean       0.030000        1760339314
json.latency.p99        0.030000        1760339314
json.latency.p90        0.030000        1760339314
json.latency.p95        0.030000        1760339314

集計方式と変換関数

集計方式

--aggregator で渡す集計の方式は以下の種類を指定できます。

  • count : 対象となるキーが存在する行をカウントします
    • 例: json.total.count 80000.000000 1760281381
  • group_by : 指定したキーの値ごとに件数を集計します。
    • 例: json.status.2xx 24769.733333 1760281381
  • group_by_with_percentage : group_byの各値ごとの割合(%)も出力します。
    • 例: json.status_percentage.5xx 23.139667 1760281381
  • percentile : 指定した数値キーのパーセンタイル(mean, p90, p95, p99)を出力します。
    • 例: json.latency.p95 0.030000 1760281381

値に関する変換関数

--json-key には値までのパスに加えてパイプ(|)区切りで変換関数を指定できます。

例: foo.bar|tolower|replace('a','b')|trimspace

利用可能な関数:

  • tolower : 小文字化
  • toupper : 大文字化
  • trimspace : 前後の空白を除去
  • replace('pattern','repl') : 正規表現で置換
  • have('key1','key2','key3') : 初期状態のキーのリスト。集計した値がない時に 0 で結果を生成できます

例:

--json-key "user.name|trimspace|tolower"
--json-key "message|replace('error','warn')"

パフォーマンス

大量のログを高速に扱えるよう、mackerel-plugin-jsonlはパフォーマンスも意識して作成しています。

JSONの処理には、buger/jsonparser を利用しています。このライブラリはJSONの中から指定したキーの値を取り出すことを目的としており、高速に動作します。axslogのJSON処理にも使っています。

github.com

120万行のアクセスログに対して実行したところ、0.5秒以下で処理が完了しており、axslogと同等の性能を備えています。

jsonlのdemoディレクトリに含まれるベンチマークの実行例(Macbook Pro M3で実行)

-rw-r--r--  1 m-nagano  staff   318M Dec 13 22:56 json.log
json.total.count    5142857.142857  1765634191
json.status.2xx 1468487.142857  1765634191
json.status.3xx 737027.142857   1765634191
json.status.4xx 1468530.000000  1765634191
json.status.499 366360.000000   1765634191
json.status.5xx 1102452.857143  1765634191
json.status_percentage.499  7.123667    1765634191
json.status_percentage.5xx  21.436583   1765634191
json.status_percentage.2xx  28.553917   1765634191
json.status_percentage.3xx  14.331083   1765634191
json.status_percentage.4xx  28.554750   1765634191
json.latency.mean   0.030000    1765634191
json.latency.p90    0.030000    1765634191
json.latency.p95    0.030000    1765634191
json.latency.p99    0.030000    1765634191

real    0m0.461s
user    0m0.389s
sys 0m0.041s

axslogのdemoに含まれるJSONログのベンチマーク結果(環境は同じ)

-rw-r--r--  1 m-nagano  staff   318M Dec 13 23:09 json.log
2025/12/13 23:09:57 Analysis start logFile:json.log lastPos:2780 Size:333602780
2025/12/13 23:09:58 Analysis completed logFile:json.log startPos:2780 endPos:333602780 Rows:1200000
axslog.latency_json.average 0.030000    1765634998
axslog.latency_json.99_percentile   0.030000    1765634998
axslog.latency_json.95_percentile   0.030000    1765634998
axslog.latency_json.90_percentile   0.030000    1765634998
axslog.access_ratio_json.1xx_percentage 0.000000    1765634998
axslog.access_ratio_json.2xx_percentage 100.000000  1765634998
axslog.access_ratio_json.3xx_percentage 0.000000    1765634998
axslog.access_ratio_json.4xx_percentage 0.000000    1765634998
axslog.access_ratio_json.499_percentage 0.000000    1765634998
axslog.access_ratio_json.5xx_percentage 0.000000    1765634998

real    0m0.468s
user    0m0.400s
sys 0m0.050s

まとめ

mackerel-plugin-jsonl の紹介をしました。

残念ながらまだ自分のみているサービスでの利用はない(DNSのサービスで使おうと考えてます!)のですが、さくらのクラウドの開発運用の現場で利用されており、「便利」との評価もいただいています。ぜひ機会があれば使っていただけると嬉しいです!