世界を動かす技術を、日本語で。

テラバイトのCIログをLLMに与えました

概要

  • CIログ解析エージェント が数秒で不安定なテストの原因を特定
  • ClickHouse を活用し、月単位・数十億行のログをミリ秒単位で検索
  • SQLインターフェース を通じてLLMが自由に調査クエリを生成
  • データ圧縮・カラム設計・スロットリング で高速・効率的な運用を実現
  • GitHub API制限 を考慮した堅牢なデータ取得・処理パイプライン構築

エージェントによるCIログ調査の全体像

  • エージェント は、CIログ全履歴・全テスト・全ビルドの情報を数秒で調査
  • 毎週 約15億行のCIログ70万件のジョブ を取り込み
  • 全データを ClickHouse に35:1で圧縮保存し、ミリ秒単位でクエリ可能
  • エージェントは SQLインターフェース を通じて独自のクエリを生成
    • 事前定義クエリや固定APIではなく、 自由度の高い質問 が可能
  • LLMは SQL の生成が得意で、自然言語から柔軟なデータ探索を実現

クエリ対象と利用パターン

  • 主なクエリ対象
    • Job metadata: CIジョブごとのメタデータ(失敗率・成功率・開始時刻など)
      • 利用割合: 63%
    • Raw log lines: ログ行単位の生データ(エラー出力・初出時刻・頻度分析など)
      • 利用割合: 37%
  • エージェントは 1セッション平均4.4クエリ を発行し、広く調査→深掘りの流れ
  • 重い調査 では1セッションで 数十億行 までスキャン

データ構造と圧縮戦略

  • 全ログ行に48カラムのメタデータ を付与(コミットSHA、PRタイトル、ジョブ名等)
  • 従来の正規化ではJOINが必要だが、 ClickHouseのカラム型+非正規化 でJOIN不要
  • 繰り返し値の多いカラム は劇的に圧縮され、ストレージ効率が大幅向上
    • 例: commit_message301:1 で圧縮
  • 生ログ664GiB+全カラムで5.31TiB (非圧縮)が、 154GiB まで圧縮
  • 1ログ行あたり21バイト (全48カラム含む)という高効率

ストレージ内訳と圧縮率

  • line_content(ログテキスト)ts(タイムスタンプ)line_number がストレージの半分以上を占有
  • 繰り返しの多いメタデータカラムはほぼ無料に近い容量
  • 主要カラムごとの圧縮率・ディスク使用量
    • line_content: 53.2GiB、12.5:1
    • job_name: 8.2GiB、48:1
    • runner_labels: 3.8GiB、52:1

高速なクエリ性能の工夫

  • 主キー設計 で物理的に(org, ts, repository, run_id, ...)順に並べ、範囲外データのスキップを実現
  • スキップインデックス (bloom filter、ngram filter)で不要データの読み飛ばし
  • マテリアライズドビュー で集計済みデータを事前生成
  • 非同期インサート で高スループットを確保
  • クエリ遅延
    • Job metadata: 中央20ms
    • Raw log lines: 中央110ms(最大でも数十秒で完了)

GitHub API制限とリアルタイム性の維持

  • GitHub APIの1時間あたり15,000リクエスト制限 に対応
  • インジェストとエージェントのAPI利用 を分離し、 インジェストは1秒あたり約3リクエスト に制限
    • 4,000リクエスト/時 をエージェント用に確保
  • スロットリング導入前 はAPI制限に頻繁に到達し、データ遅延が問題化
  • スロットリング導入後 は安定して P95で5分以内の遅延、通常は数秒でデータが利用可能

耐障害性・バースト吸収

  • Inngest を活用した耐障害性の高い実行エンジン
    • レートリミット到達時は 状態を保存して一時停止、復帰時は即再開
    • 再試行や重複排除の複雑さを排除
  • CIアクティビティのバースト にも対応
    • キューが膨らんでも、処理レートは一定で安定運用
    • 一時的に遅延が発生しても、すぐに回復

まとめ:エージェントによるCIログ解析基盤の特徴

  • 膨大なCIログをリアルタイム・高効率で保存・検索
  • LLM+SQLインターフェース の組み合わせによる柔軟なトラブルシューティング
  • ClickHouseのカラム型DB+非正規化+圧縮 による圧倒的なストレージ効率
  • GitHub APIレート制限下での安定・高速なデータ取得
  • 耐障害性・バースト吸収力 を持つ実行基盤による高可用性システム

このシステムにより、 エンジニアは手作業でログを追うことなく、AIエージェントによる即時の根本原因特定 が可能。 CIの信頼性向上・開発体験の最適化 を強力に支援。

Hackerたちの意見

これは、スプリントに組み込めることを期待して社内で共有するHNの投稿の一つだね。

でも、実際に効果あるの?ログ分析にLLMを使ったことがあるけど、理由を幻覚することが多かったよ。ログによっては、原因と結果の距離がコンテキストよりも大きくなることがあるし、問題が悪化する時は複数の障害が同時に発生してることが多いからね。それに、無害な問題でも怖いエラーが出たりするし。

他のタスクと同じように、できるよ。ただの魔法じゃないから、エージェントの仕事を楽にするために、良い指示やツール、環境を与える必要がある。これって人間の生活を楽にするのと全く同じことだよ。この投稿は、特定のタスクに対してこうする一つの方法を示すケーススタディだね。今週、Aiを使って開発ボックスの長年の問題の根本原因を見つけたよ。Gemini Deep Researchにいくつかのログと技術スタックを渡したら、基盤となる相互作用の説明やデバッグコマンド、最も可能性の高い修正方法が返ってきた。まさにその通りで、GDRは完全に理解していない問題のデバッグツールとしては最高の一つだよ。もし興味があれば、ちょっとしたお知らせなんだけど、問題はDockerとTailscaleがIPテーブルの更新で競合していて、稀に(開発者が一人、数週間に一度)DockerのDNSが壊れちゃうことだった。修正方法は、NetworkManagerでDocker管理のインターフェースを無視すること。そうすればTailscaleがそれらに対して何かをしようとしなくなるんだ。

Mendralの共同創設者だよ。私たちは、このインフラを作ってエージェントがフレークテストのようなCIの問題を検出して修正できるようにしたんだ。ログを観察するのは異常を検出するのに役立つけど、エージェントがPRを開いた後に修正を確認するためにもそれを使ってるよ(長時間のコーディングセッションを行って、修正を確認して必要に応じてCIを再実行する、すべて同じエージェントのループ内でね)。だから、うまくいってるよ。実際に運用中の顧客もいるし。

投稿者だよ。はい、実際にすごくうまくいってるよ。1) 最新のモデルはこれに関しては劇的に良くなってる。Sonnet 4.5から品質が大幅に改善されたのを感じたよ。2) コンテキストの問題は本当だね。これを解決するために、ログを読み取って親エージェントのコンテキストに関連する部分だけを返すサブエージェントを使ってるんだ。

正直、最近のモデルを使えば、こういうタスクはかなり可能だよ。今は、モデルを正しく使っているかどうかにほとんど依存してるね。

自動テストのためにログを解析してデバッグを早める取り組みを進めてるよ。これがすごく難しいんだ。主に、情報ログの中でも大量の誤検知や古いノイズがあるからね。犯人を追跡するのも難しいことがあって、コンテナAのエラーがコンテナBの実際の障害によって引き起こされることもあるし、それがさらに全く別の何か(ハードウェアの問題を含む)に依存していることもある。要するに、LLMを使ってログを解析し、実際の問題を検出する確実な方法は、ログの可読性と精度にほぼ完全に依存しているんだ。もしログが十分に良ければ、人間もデバッグをもっと早く、信頼性高くできるしね :) でも、実際にはログを読む人とそれをコーディングする人がほとんど交わらないから、問題は残ったままなんだよね。

うん、これを作っている時に経験したこととすごく似てるね。今はフレークテストのようなものに本当にうまく機能するCIログに集中してるけど、すぐにインフラログにも範囲を広げる予定だよ。

ログの目的についての期待が多すぎて、みんなが同じ理解に達するのは難しいと思います。その一方で、統計は期待が少なくて、ログから統計に信号を移すのはずっと小さな戦いです。全てを教えてくれるわけではないけど、教えてくれることはあいまいさが少ないです。時間が経つにつれて、みんなが自動的にSplunkを引き合いに出すのをやめて、代わりにGrafanaを使うようになりました。

LLM分析用のログを減らすツールを作ったよ(https://github.com/ascii766164696D/log-mcp)。ログにはあまり興味深くない情報が多く含まれてるから、コンテキストが汚れちゃうんだよね。そこで、TF-IDF分類器とGPU上のBERTモデルを使って、ログ行をさらに分類して、LLMモデルに渡すべきログの数を減らすアプローチを取ったんだ。モデルの合計サイズは50MBで、分類器はRustで書かれてるから、1M行/秒以上の速度で分類できるよ。単純なgrepでは見逃しがちな興味深いケースも見つけられるし、約90GBのログでトレーニングしたよ。モデルを再トレーニングするためのスクリプトも提供してる(https://github.com/ascii766164696D/log-mcp/tree/main/scripts)。これはClaude Code CLIと一緒に使うことを想定してるから、ログファイルを読み込む代わりにこれらのツールを使えるんだ。

Mendralの共同創設者で、投稿の著者です。これは面白いアプローチですね。問題提起には完全に同意します。LLMがコンテキストウィンドウの制約でエラーや致命的なものをフィルタリングしなければならない場合、重要な情報を見逃してしまいますからね。私たちは別のアプローチを取りました。メインエージェント(opus 4.6)が「ログリサーチ」の仕事をサブエージェント(haiku 4.5、速くて安い)に振り分けるんです。サブエージェントは大量のログを読み込んで、関連する部分だけを親エージェントに返します。これがコーディングエージェント(例:Claude Code)がやっていることと同じです。ただし、サブエージェントはgrepやread、tailを使う代わりに、普通のSQLを使います。

https://github.com/dx-tooling/platform-problem-monitoring-co... も有用なアプローチがあるかもしれません。ログ行のパターンを見つけて、「これらの500行は技術的には全て異なるけど、同じことを言っている」といった要約を提供してくれます。

高度に圧縮された表現で何か面白いことができると思いますか?CLPは169倍の圧縮率を達成できるみたいです: https://github.com/y-scope/clp https://www.uber.com/blog/reducing-logging-cost-by-two-order...

最初の印象としては、実際に興味深いユニークな行がほんの数行しかないのに、10TBのログがあるってことですね。だから「わあ、すごいビッグデータだね」とは思わず、「1-10^-6の精度があっても、偽陽性に圧倒されてるんじゃない?」とか「パパがトークン代を払ってくれてることを願ってるよ」と思います。

そうですね、これが私のログデータに関する経験です。実際に気にするのは、クエリごとにO(10)行くらいで、通常は何らかの相関IDで関連付けられています。検索する代わりに、物事をカウントして要約している感じですね。その場合、実際にカウントすることが重要です ;)。ただ、この部分では--もう一度読まないといけないかも--LLMの「インターフェース」がログデータに対してClickHouseに対するクエリだという印象を受けました。クエリが適切に制限された結果を返し、クエリが暴走しなければ、両方の懸念に対処できるかもしれませんね?

Mendralの共同創設者で、投稿の著者です。あなたの意見に同意しますし、他のコメントでもどうやってやっているか説明しました。要約すると: - 調査が必要な何かが起こる - メイン(Opus)エージェントが集中した計画を立ててサブエージェント(Haiku)を生み出す - 彼らはClickHouseのクエリを使って、関連するログの部分だけを取得し、要約やパターンを返します。これは手動でやることと同じです。何かが起こったときに10TBのログを全部読むわけじゃないから、計画を立てて、いくつかのタブを開いて、狭い範囲で集中した検索を始めるんです。

あの投稿は完全にLLMが生成したみたいだね。要するに、印象的に聞こえる数字のリストを自慢してるだけ。もし一貫したストーリーがあるなら、かなり隠れてるよ。

SQLはずっと俺のお気に入りの「弾丸を込めた銃」APIだね。RLSと役割ベースの認証のコントロールプレーンがあって、データ辞書があれば、LLMが重い作業をやってくれるデータエクスプローラーとのチャットインタラクションは簡単だよ。

100%そうだね、LLMには関連するトレーニングデータがたくさんあるし。

複雑な分散システムのログファイルを分析するために、20のリアルタイムコンポーネントのプロローグルールをたくさん作ったんだ。問題や根本原因を見つけるのにすごく役立ったよ。2008年頃の話だけど、LLMがそんなに役立つなんて信じられない。コンポーネントが変わったりログラインを追加したりすると、ルールを一つ編集するだけで済むけど、LLMだと新しいログが数週間必要で、再トレーニングにも数週間かかるし、H100の高予算も必要だよ。

猿に口紅を塗ったみたいな記事だね。

これはRAGがうまくいったいい例だね。一般的なトレーニングに頼らず、ドメイン特化のデータをLLMに与えてる。ただ、CIログの信号対雑音比は厳しいよね。埋め込みの前に重複排除やフィルタリングをどうやって処理したのか気になるな。俺の経験では、その前処理ステップがリトリーバルの質を決めるんだよ。