Skip to main content

ログ取得ツール

僕たちがAIに「昨日どうだった?」って聞くためにやったこと (1)

このサーバにはいくつかの役割が与えられている。まあこのページの世の中への提供もその一つ。最近はAIの餌になるだけだが。そんな中で、ほとんど放置にも近かった管理系のタスク。これをどうにかしたかった。どういうイメージかというと、、、

claude codeを起動して、

最近調子どう?

って聞いたら

  • 最近の主要なログを確認
  • 最近のメトリクス情報を確認
  • どんなだったかサマリを作って返してくる

という世界を作りたかった。タイムレンジは適当にプロンプトで与える。去年の同じ時期と比べて今年はどうよ? でもいいわけだし。

どうすればいいのか。LLMがログとメトリクスにアクセスできればいい。

実際のところ、データソース…ログやメトリクス情報は完璧ではないにしろ、ある程度保存されるようにしてある。今まで見てなかっただけで。これにLLMからアクセスする手段を作る。つまりMCPサーバだ。

そうこうしているうちに私(わたなべ)はduckdbにMCPサーバがついていて、.parquetファイルにLLMがクエリを投げられるようにできるということを知った。ログを解析して、特定のパターンを持つログを特定のスキーマに入れた.parquetファイルを作っていけば、duckdbで効率的にクエリを投げてサクサク理解が進むというわけだ。これは理想の世界に近づける。というわけで、僕たち(sonnetとopus、あとお手伝いのわたなべ)は日々ログを.parquetに変換する部分のコードを書くことにしたのだった。

.parquetファイルというはなかなか優秀で、カラム型で1ファイルに保存してくれるし、圧縮にも対応している。カラム型だからそもそも圧縮が効きやすい上に、圧縮したままクエリをかけられる。duckdbはローカルファイルの.parquetにもWebサーバ上の.parquetにもs3にある.parquetにもそのままアクセスできる(すごい!)。とりあえず圧縮アルゴリズムはzstdを採用してみた。元々ログファイルはxz -9で圧縮しあったので、それよりは少しサイズが増えちゃうけど、アクセス速度は段違いになる。全部読み込まずに済むから、トークン消費にも優しい。いいことずくめじゃないか。

余談だがxzはあの事件で確かにケチはついたけど、圧縮がかなり最強レベルで効くので、私はいまだに重宝している。

それで、.parquetへの変換さえ済ませれば、duckdbのmcpサーバをコンテナで上げて、そいつに.parquetファイルのあるディレクトリを見せればいい。あるいはS3に置いてローカルのduckdbからクエリをかける、でも行けるはず。LLMにはファイル名とスキーマ構成だけスキルで言い聞かせれば、あとは勝手にクエリを作ってログを探してくれるという目論見だ。とりあえず僕たちはスムーズな変換を目指し、そして変換後のファイルを扱うサブコマンドを書いた。書く日々を送った。

まだ余談だが(何度か述べたことがあるが)私は開発にはclaude codeでsuperpowersを使っている。superpowersはトークンを爆食いする代わりに失敗率が低いフレームワークだ。つまりトークン(MTok…メガって言うのかな最近のノリだと)がものすごい勢いで消費されて、1つの機能の実装は5時間分のトークンにギリギリ収まらないくらいになる。だから短期間でソフトウェアを書くことができるかどうかは、まさに金次第だ。

僕たちはsyslog形式というのはとても良いものだと思っているんだけど、欠点もあるにはある。例えば割と最近のサーバでもデフォルトの設定だと「年」の情報が入っていなかったりする。そんなタイムスタンプ形式が、ありえるのがsyslog。しょうがないので「直近の過去日」を推測させたり、変換コマンドにオプションをつけて年の情報がないタイムスタンプの場合に補完する年を指定できるようにしたり。うーむ。あとはapacheのCLFとかそういうよくあるログフォーマットに対応するプリセットをつけたり、なんやかやした。…これらの機能の実装にそれぞれに5時間以上かかる。トークン。

実際はAWSにはすでにそういうサービスがあるし、例えばpandasでjsonlをparquetに変換することもできる。まあログを.parquetにしようというのは、よくある話なんですよ。なんでそれを自分で書いたんだって話は、まあ私は指示を出してトークンを溶かしてただけだし、OSSを探して設定ファイルを作るのと労力に大した違いがない時代…だからできたことだな。時間さえかければ。

ここまでの成果物: https://github.com/wtnb75/logidx