Skip to content

ログ

ログは L1 スタックの Loki 側です。メトリクスと同じデータプレーンの形に 従います:edge は HTTPS で Loki に直接プッシュし、manager はクエリのみ します。

データプレーン

text
edge:
  ongrid-edge agent
    └─ plugin: promtail (subprocess)
        ├─ tails /var/log/syslog, /var/log/messages, journald
        └─ remote write HTTPS → loki:3100

                                     ▼ /loki/api/v1/query_range
                              ┌───────────────┐
                              │  manager:     │
                              │   - alert     │
                              │   - LLM tools │
                              └───────────────┘

ADR-015 プラグインランタイム

promtail は edge エージェントのプラグインランタイム下でサブプロセスと して走ります。エージェントがライフサイクルを監督します —— クラッシュ時 再起動、シャットダウン時 drain、エージェントと同じ systemd journal に ログ。operator から見れば 2 つではなく 1 つの systemd サービスです。

以前の代替案(「promtail を静的リンク Go ライブラリとしてベンダリング」) は、Loki クライアントのアップグレードのたびに edge エージェントの 再リリースが必要になるため却下されました。サブプロセスがそれらを切り 離します。

設定

エッジごとの promtail 設定は biz/edge/plugin_config.go がサーバー側で描画し、プラグイン起動時に制御トンネル経由でプッシュ ダウンします。system_settings.loki.url を参照するので、admin が URL を 変更してもエージェントを再ビルドせず伝播します。

デフォルトの tail セット:

ソースLoki ラベル
/var/log/syslog/var/log/messagesjob=node-sysloghost=<edge-name>
systemd journald(全 unit)job=systemd-journalhost=<edge-name>unit=<svc>

カスタム tail は SPA の /edges/<id>/logs/sources ページから追加します —— 同じ system_settings.loki.* 名前空間に書き込みます。

データプレーンの分割

ADR-014:テレメトリは直接、コントロールはトンネル経由。ログでこれは:

  • promtail HTTPS POST → loki:3100/loki/api/v1/push(直接)。
  • ✅ Loki HTTPS GET ← manager /loki/api/v1/query_range(直接)。
  • ❌ ログは geminio コントロールトンネルを通りません。

理由:トンネルはプロセス内マルチプレクサで、ログバーストを流すと取り込み スパイク時にコントロール RPC(RCA ツール呼び出し、WebSSH I/O)が飢餓 状態になりました。データプレーンを分離すれば noisy-neighbour 問題が 解決し、nginx が両半分の公開表面(TLS、レート制限、認証)を均一に 所有できます。

アラート種別

ログ駆動のルール種別は 2 つ —— どちらも Phase-B、どちらも evaluators_phaseB.go にあります。

log_match

count_over_time(<stream_selector> |~ <line_filter> [window]) <op> threshold が少なくとも 1 つの行列エントリを返したときに発火します。

json
{
  "kind": "log_match",
  "scope_type": "global",
  "conditions_json": {
    "stream_selector": "{job=\"systemd-journal\",unit=\"nginx.service\"}",
    "line_filter": "(?i)5\\d{2}",
    "window": "5m",
    "operator": ">=",
    "threshold": 50
  }
}

line_filter はオプションです —— 空のときルールはストリーム内のすべての 行をカウントします。クエリは rules.go:733compileLogMatchRule により tick ごとに構築されます。

log_volume

v1 では log_match と同じエンジン(現在ウィンドウのカウント vs 絶対 しきい値)です。仕様のオリジナルの「前ウィンドウとの比率」セマンティクス は保留中 —— 2 つの LogQL クエリ + Go 側の除算が必要です。絶対形式が すでに「ログが N を超えてスパイク」という一般的なユースケースをカバー しています。

スペック列は ratio_op / ratio_threshold(前方互換のため保持)で、 コンパイラがこれらを operator / threshold にマップします。

ツール

search_logs / query_logql

LLM 向けログ検索。2 つの登録パスが 1 つのエクゼキュータを指します。

  • query_logql —— 生 LogQL のパススルー。ペルソナが正確にどのストリーム をクエリすべきか分かるとき、investigator worker が使用。
  • search_logs —— チャット UI のクイックアクションに公開される フレンドリーなラッパー。フリーテキストクエリ + サービス名を取る。

スキーマ + エクゼキュータは query_logql_basetool.go にあります。基底クライアント:internal/pkg/logquery

両方ともグローバルな ONGRID_LOG_QUERY_URL 環境変数(デフォルト http://loki:3100)を尊重し、edge がプッシュに使うのと同じ nginx レイヤーから認証を継承します。

host_tail_file

スキル側のログプローブ —— manager ではなく edge で動きます。Loki に 取り込まれたビューではなく 生ファイル(例:journald にない /var/log/ongrid-edge.log)が必要なときに使います。ScopeHost、 edge_id が必要。dispatch モデルは スキル を参照。

関連