mcpField
K
kubesense-alerts

kubesense-alerts

github.com/kubesense-aiクラウド・DevOps3114 回インストール4 日前に更新
リポジトリ

kubesense-alerts について

KubeSense のアラートを確認・作成するためのスキルです。発火中のインスタンス、ルール定義、履歴を区別し、検証付き MCP ツールまたはレビュー可能なインポート JSON による作成を案内します。

主な機能

  1. 01発火中のアラートとルール定義の確認
  2. 02アラート詳細と履歴の確認
  3. 03過去のアラート調査の検索
  4. 04検証付き単一ルールの作成
  5. 05インポート JSON の準備と検証

活用シーン

  1. 01発火したアラートと履歴の調査
  2. 02アラートが慢性的か新規かの確認
  3. 03MCP ツールによる単一ルールの作成
  4. 04一括インポートの準備や検証

MCP 対応

MCP クライアントが KubeSense のアラートツールを使い、アラート、ルール、詳細、履歴、通知チャネル、調査記録を照会する方法を案内します。検証付きの `create-alert` と `validate-alert-json` ツールについても説明します。

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/kubesense-ai/kubesense-mcp-skills --skill kubesense-alerts

インストール後、Claude Code で/kubesense-alertsを入力して読み込まれたか確認します。

同梱ファイルreferences/datadog-migration.mdreferences/import-json.md

詳細

KubeSense Alerts

混同しないでください。これらは別々の 2 つの作業です。

  • アラートの確認 — 何が発火しているか、何がしきい値を超えたか、慢性的なものかを確認します。MCP ツール呼び出しのみで行います。
  • アラートの作成 — create-alert MCP ツール(検証済みの単一ルール)または JSON のインポート(UI で確認可能、一括登録に対応)を使います。

使い分け

ユーザーの質問…実行すること
「今、何が発火していますか?」list-active-alerts
「どんなアラートがありますか/自分で作成したアラートはありますか?」list-alert-rules(created_by には get-current-user も使用)
「このアラートが発火しました — 何が壊れましたか?」対象範囲の get-alert-details を実行し、その後 kubesense-infra で変更とインフラストラクチャの障害を確認します
「このアラートは不安定ですか、それとも新しいものですか?」get-alert-history
「以前にこの問題の根本原因が特定されていますか?」find-investigation-for-alert
「…したときにアラートを作成して」(単一ルール、エージェントが適用)create-alert MCP ツール
「…のアラート JSON を作成して」/複数のルール/移行JSON をインポート → references/import-json.md
「これらの Datadog モニターを移行して」references/datadog-migration.md
「なぜ発火したのに誰にも通知されなかったのですか?」まず通知チャネルの間隔を確認し、次に メンテナンスウィンドウ が該当するか確認します
「これらのルールをリスト/フォルダーにまとめて」UI でのみグループ化できます — MCP のインターフェースはないため、推測せずその旨を伝えます
ルール JSON を手作業で作成し、検証したい渡す前に validate-alert-json を実行します
「エラーバジェット」、「バーンレート」、「99.9% を達成できていますか」kubesense-slo — バーンレートのルールは手書きではなく、SLO の alert_types から生成されます

アラートの確認

ツール対象
list-active-alertsネイティブストアから取得した、現在発火中の時系列データをルールのメタデータと結合して表示します。フィルター:from_time/to_time、fingerprint、acknowledged、assignee、include_resolved。
list-alerts外部の Alertmanager — ラベルのみで、ルール設定はありません。別のデータソースです。特に Alertmanager の状態やサイレンスを確認したい場合を除き、list-active-alerts を使用してください。
list-alert-rules無効化されたものや発火していないものも含む、ルールの定義を表示します。新しいものから順に並びます。フィルター:enabled、state、severity、query_type、search、created_by。
get-alert-details1 つのルールの完全な設定(query_config、条件、しきい値)と発火中のインスタンスを表示します。調査はここから始めてください。
get-alert-history発火/解決の遷移を新しいものから順に表示します — 慢性的なものか新しいものかを確認できます。
find-investigation-for-alert最も新しい完了済みの AI 調査とその根本原因を表示します。found=false は正常な状態であり、エラーではありません。
list-notification-channels有効なチャネルのみを表示します:id、name、type。

手作業で作成したルール JSON の確認

ルールドキュメントを自分で組み立てた場合 — JSON のインポート、移植した Datadog モニター、編集したエクスポートなど — ユーザーに渡す前に validate-alert-json で検証してください。このツールは何も保存せず、すべての問題を一度に報告します。

# valid=false findings=2
path                        rule                 message
/query_config/0/queryMode   shape                value must be one of 'builder', 'code'
/metric_query_label         metric_query_label   names query "A", but the rule's queries are labelled "B"

各 path は、修正対象の値を示す JSON Pointer です。valid=true になるまで繰り返してください。

これは ワイヤードキュメント — query_config、threshold_operator、frequency_type を含むエクスポート/インポート形式 — を検証します。create-alert の引数には使用しません。このツールは入力を独自に検証し、同じ指摘内容で拒否します。

重要

「自分が作成したアラートはどれですか?」 — get-current-user を呼び出し、その username を created_by として渡してください。保存された作成者情報はユーザー名です。メールアドレスでは一致しません。 この 2 つの値は異なることがよくあります。

フィンガープリントは、ルールの発火中の時系列(1 つの名前空間/ポッド/ワークロード)を識別します。特定のインスタンスに絞って get-alert-details/get-alert-history を呼び出すには渡し、ルール全体を対象にする場合は省略してください。

障害から復旧しなくても、アラートを「発火中」から外せます

発火中の系列に対する人間の操作は 2 つあり、それぞれ意味が異なります。

意味「発火中」のまま通知
確認「対応中です」はい二重に抑制されます。下記を参照してください
解決「対応済みです」いいえ今回の違反に限り抑制されます

解決すると、現在の違反は終了します。系列が違反しなくなると、エンジンはすぐにフラグを解除するため、その後に実際に再び違反した場合は通常どおり通知されます。ミュートではありません。

確認すると、独立した 2 つの仕組みによって抑制されます。最大 7 日間の Alertmanager のサイレンスと、データベースのフラグが設定されている間は送信を完全にスキップするエンジン側のチェックです。このフラグに有効期限はありません。 1 週間後に通知が自動的に再開すると伝えてはいけません。アラートが解決するか、状態が変動するか、誰かが確認を取り消すまで再開しません。

重要

MCP の出力だけでは、手動解決と実際の復旧を区別できません。手動で解決した系列には ends_at が追加され、復旧した系列とまったく同じように list-active-alerts から除外されます。そのため、include_resolved だけを根拠に「14:02 に復旧しました」と結論づけてはいけません。アラートが終了したと伝えてください。既知の問題があるものが正常に戻った理由をユーザーが尋ねている場合は、両者を区別できるアラートの詳細ページを案内してください。

アラートを作成する — どちらの方法を使いますか?

create-alert MCP ツールJSON のインポート
1 回の呼び出しで作成するルール数1 つ1 つまたは複数(一括)
フィールド名fields/group_by_fields は自動変換されます。カタログのラベルが優先され、次にストレージ名が使われます。where は厳密で、カタログのラベルのみ使用できますエンジン独自の用語に合わせて、名前を正確に指定する必要があります
検証事前に実施され、再試行に使える具体的なエラーが返されますインポート時にサーバー側で実施されます
適用するのはエージェント(書き込みツール。承認が必要です)ユーザー(UI 内)
最適な用途ユーザーが今すぐ作成したい単一のルールレビュー可能な出力、複数のルール、移行

単一のルールには、create-alert を優先してください。エンジン独自のバリデーターに照らしてフィールド名を解決するため、エンジンが拒否する名前を出力しません。ユーザーが「JSON」を求めている場合、作成前に内容を確認したい場合、または複数のモニターを移行する場合は、インポート用 JSON を優先してください。

create-alert
{
  "signal": "traces",
  "name": "Checkout p95 latency high",
  "description": "p95 above 500ms for 5 minutes",
  "where": "service = checkout",
  "value_operation": "p95",
  "fields": [ { "field": "duration" } ],
  "group_by_fields": [ { "field": "workload" } ],
  "threshold_operator": "greater_than",
  "threshold_value": 500000000,
  "severity": "warning",
  "notification_channels": [1],
  "time_window": "5m",
  "evaluation_interval": "1m"
}
  • signal:metrics | logs | traces。
  • metrics → promql を指定します。logs/traces → where(search-logs 構文)と value_operation を指定します。row_count 以外の場合は fields も必要です。
  • ここでの value_operation はクエリツールより選択肢が限られます。row_count、unique_count、avg、sum、min、max のみで、パーセンタイルは使えません。p95 レイテンシのルールには、インポート用 JSON を使用してください。
  • 必須項目:name、threshold_operator、threshold_value、notification_channels。
  • デフォルト値:severity=warning、threshold_frequency=at_least_once、evaluation_interval=1m、time_window=5m。
  • threshold_operator には、ここでは above/below も指定できます(インポート用 JSON では指定できません)。ルールの作成前に正規化されるため、above は greater_than として、below は less_than として保存されます。そのため、ルールを読み戻すと、送信した値ではなく正規の値が返されます。正規の名前がわかっている場合は、そちらを優先してください。
複数のクエリと数式

比率(エラー率、全体に占める割合、あるクエリを別のクエリで割った値)を使う場合でも、インポート経由にする必要はなくなりました。単一クエリ用のフラットなフィールドの代わりにqueriesを渡し、最後のエントリにexpressionを指定します。

{
  "signal": "traces",
  "name": "Checkout 5xx rate above 5%",
  "queries": [
    {"label": "A", "where": "status_code LIKE \"5__\"", "value_operation": "row_count",
     "group_by_fields": [{"field": "workload"}]},
    {"label": "B", "where": "", "value_operation": "row_count",
     "group_by_fields": [{"field": "workload"}]},
    {"label": "C", "expression": "A / B * 100"}
  ],
  "threshold_operator": "greater_than",
  "threshold_value": 5,
  "notification_channels": [1]
}
  • queriesとフラットなフィールド(promql、where、value_operation、fields、 group_by_fields)は相互に排他的です。queriesを渡す場合は、すべてをその中に指定します。
  • labelのデフォルトは、位置に応じてA、B、Cとなります。使用できるのはアルファベットのみで、クエリは最大26個です。
  • 数式エントリにはexpressionだけを指定し、それ以外は指定しません。また、参照できるのは前に記載されたクエリだけです。
  • 数式以外のクエリはすべて、ルールの単一のsignalに対して実行されます。ログとメトリクスを混在させることはできません。
  • **グループ化した入力では、同じフィールドでグループ化する必要があります。**エンジンはそのキーで時系列を照合するため、異なる方法でグループ化された2つの入力はキーが一致しません。 create-alertは事前にこれを拒否し、両方のグループ化を示します。ルールを作成してから疑問に思うことはありません。
  • **グループ化していない入力は例外です。これは意図された動作です。**グループ化されていない単一の時系列がグループ化された時系列にブロードキャストされます。これはまさに「このワークロードが全体に占める割合」を求める方法です。Aはworkloadでグループ化し、Bはグループ化せず、しきい値をA / B * 100にします。
  • インポートJSON経由では、同じ不一致はチェックされません。拒否されることなく、結合結果は空になり、空の結果は正常と判定されます。ルールはただ何も出さなくなります。これが、create-alertを使って複数クエリのルールを作成する理由です。
  • しきい値は数式に適用されます。複数のクエリがあり、数式がない場合は、しきい値を適用するクエリをthreshold_queryで指定します。
  • queries内の"where": ""は受け付けられます。「すべて」を分母にするためです。一方、フィルターのない単一クエリのルールは拒否されます。

重要

whereで指定できるのはカタログラベルだけです。return_codeではなくstatus_code、pod_nameではなくinstanceを指定します。ストレージ列を指定すると、名前で拒否されます。

field "return_code" is a storage column; use the catalog label "status_code" instead

これは、後述する、保存済みおよびインポートされたルールに適用される語彙とは逆です。そちらではreturn_codeが正しく、serviceは正しくありません。同じルールでも、エンジンに渡される方法によって語彙が2種類あります。fieldsとgroup_by_fieldsは柔軟で、create-alertはまずカタログラベルを試し、次にストレージ名を試すため、どちらでも使用できます。whereではこの変換は行われません。

ツールの説明にある例にはこの問題があります。whereにreturn_codeを指定しており、同じツールの背後にあるバリデーターによって拒否されます。この例をコピーしないでください。

ここではパーセンタイルはまだ指定できません。value_operationにp95がないため、p95レイテンシのルールは引き続きインポートJSONで作成する必要があります。

labelsを指定すると、ルールと、そのルールが発火させるすべてのアラートに追加のラベルが付与されます。ラベルはルーティングに使われ、{{placeholders}}で展開されます。下記を参照してください。

警告

最初にlist-notification-channelsを呼び出してください。notification_channelsは必須で、実在するチャネルIDを含める必要があります。存在しないIDを指定すると、ルールの作成自体が失敗します。チャネルが存在しない場合は、Settingsで作成する必要があることをユーザーに伝えてください。ルールを黙って作成してはいけません。ルールが発火しても、誰にも通知されないためです。

これは書き込みツールです。呼び出す前に、これから作成するものを正確に伝えてください。

拒否された場合

ルールは保存される前にワイヤーコントラクトと照合されるため、拒否された場合は該当するフィールドが正確に示されます。

invalid alert: /query_config/0/queryMode: value must be one of 'builder', 'code'

各指摘には、ツールが作成したルール内のJSON Pointerと、問題の内容が示されます。修正して再度呼び出してください。見た目よりも手間のかからないやり取りであり、問題なく保存されても何も評価されないルールを作るより、はるかに手軽です。

失敗には、意味の異なる2種類があります。invalid alert: …は、あなたが修正する必要があります。failed to create alert rule: …はサーバーの問題なので、再試行せずに報告してください。

フィールド名 — 異なる語彙

重要

アラートエンジンが受け付けるフィールドセットは、クエリツールとは異なります。MCP クエリカタログのラベル(type、instance、service、node)は、ここですべて有効とは限りません。ここでは、次の3種類の語彙が使われます。

  1. クエリツール(analyze-logs、search-traces)— カタログのラベルのみ。
  2. アラートのグループ化フィールド/値フィールド — ラベルとストレージ名の混在。厳密に検証されます。
  3. アラートのフィルターキー — グループ化フィールドのセットに、追加のストレージ名オーバーレイを加えたもの。
ログ — グループ化フィールドと値フィールド(19個、正確)
instance  workload  namespace  cluster  pod  container  node
pod_name  container_name  level  format  host  body_length
region  app_version  customer_identifier  source
service  env_type

どちらの表記も使える点に注意してください。podとpod_name、containerとcontainer_name、nodeとhost、instanceです。重要度はここではlevelであり、クエリツールのtypeではありません。

serviceとenv_typeが受け付けられるようになったのは最近です(KUBE-2638)。ログカタログでは、存在当初からグループ化のドロップダウンに両方が表示されていましたが、エンジンは受け付けていなかったため、どちらを選んでもルールの作成に失敗していました。現在も拒否するインストール環境がある場合は、修正前のものです。代わりにworkloadでグループ化してください。

ログのフィルターキー = 上記19個 に加えて env、node_name、body。

メモ

bodyはフィルターキーであり、ディメンションではありません。 raw_filters: {"body": ["timeout"]}は受け付けられますが、グループ化フィールドまたは値フィールドとしてのbodyは、意図的に引き続き拒否されます。メッセージテキストでグループ化すると、行ごとに系列が分かれてしまい、集計できないためです。数値フィールドはbody_lengthであり、別のフィールドです。

保存方法により、次の2つの点が影響します。bodyフィルターを指定すると生テーブルが強制されます(ロールアップにはこのカラムがありません)。そのため、評価ごとに全件スキャンが必要になります。負荷の高いテナントで24時間のウィンドウに設定する前に、この点をはっきり伝えておく価値があります。また、bodyに対する単独のILIKEは、トークン検索に書き換えられます。SQLでは完全一致となり、実際のログ行には一致しなかったためです。トークン検索では大文字と小文字が区別されず、英数字以外の文字で分割されます。そのため、hasAnyTokensの「誤検知」はインデックスに内在するものであり、不具合ではありません。誤検知が起こることを想定し、アラートのバグとして報告しないでください。

pattern_idは受け付けられません。ロールアップにしか存在しないため、これを使ったルールは、クエリが生テーブルにフォールバックした時点で機能しなくなります。

トレース — グループ化フィールドと値フィールド(40個、正確)

カタログの28個のラベル:

status  protocol  source  role  status_code  namespace  method
workload  container  region  app_version  resource  server  client
server_namespace  client_namespace  node  operation_name
partner_cluster  customer_identifier  duration  duration_quantile
duration_avg  pod  instance  cluster  return_code  app_service

…に加えて12個のストレージ名があります。これが、ウェブアプリがトレースのグループ化フィールドとして実際に保存するものです。

container_name  pod_name  node_name  kind  subtype  protocol_type
clustered_resource  perspective_namespace  perspective_workload
env_type  app_db  issue_reason

以前は最初のリストにあるフィールドしかグループ化に使用できなかったため、UIが提示するグループ化可能なトレースフィールド27個のうち12個が保存時に拒否されていました。これもKUBE-2638によるものです。また、古い注記では拒否されるとされていたissue_reasonが現在は受け付けられる理由でもあります。

トレースのフィルターキー = 上記40個 に加えて is_external、app_name、partner_namespace、partner_workload。

したがってトレースでは、カタログ名とストレージ名の両方が、フィルターキーとしてもグループ化フィールドとしても使えます(status_codeとreturn_code、resourceとclustered_resource、methodとsubtype)。

警告

トレースではserviceは受け付けられません。app_serviceを使ってください。 クエリツールで優先されるラベルは、アラートエンジンのトレース側には存在せず、拒否メッセージにもその旨が表示されます(ログでは逆に、serviceが受け付けられます)。ログでは、node_nameはフィルター専用です。ディメンションのカラム名はhostです。

is_attribute: trueとマークされたフィールドは、空のフィルターキー、advanced_query、または@で始まるフィルターキーと同様、検証を完全にスキップします。

不正なフィールド名の場合に起きること

インポート時に、ルールは 400 とフィールドごとのメッセージとともに拒否されます。

query A (traces): group-by field "issue_reason" is not accepted by the alert engine
and would freeze the rule — not supported by the alert engine

このガードがあるのは、これによって防げる評価時の動作があるためです。エンジンが解決できない名前があると、評価のたびにエラーになり、その後エンジンはルールの現在の状態を維持します。新しいルールは何も通知せず、一度発火したルールはその状態で固定され、解決されません。また、しきい値を編集しても反映されません。しきい値を確認する前にクエリがエラーになるためです。

インポート時の許可リストは、エンジンの許可リストを手作業で反映したもので、自動的な差分チェックはありません。そのため、検証には通るのに発火しないルールは、これに該当している可能性があると考え、条件チャートで確認してください。

ルールが気付かないうちに変わる落とし穴

落とし穴結果
groupBy の項目に field、type、is_attribute のいずれかがないgroupBy 全体が空になります — ルールはラベルごとではなく、単一のグローバル系列として発火します
value_operation が数値(例:p95)で、fields がない、または不正気付かないうちに row_count に降格します — レイテンシールールが件数ルールになります
数値演算で fields[].type が文字どおり "float" ではない同様に降格します
unit: "ns" / "percent" / "short"有効な値ではないため、気付かないうちに auto になります。nanoseconds、percentage、number を使用してください
frequency_type: "always" のみを指定気付かないうちに at_least_once に降格します — threshold_frequency: "always" も送る必要があります
単一ルールのインポートで notification_channel_ids: [] を指定エディターでは 1 つ以上のチャンネルが必要です。ユーザーは**「作成」をクリックできません**
手書きの unified_filter ブロックインポート時には読み込まれず、気付かないうちに破棄されます
他の raw_filters キーと一緒に advanced_query を指定advanced_query は単独で指定する必要があり、他のすべてのフィルターキーは削除されます
query_config の項目に label キーを指定無視されます — ラベルはインデックス順に割り当てられます(インデックス 0 → A、1 → B)
pagerduty / jsm / datadog_oncall にルーティングされたルールで send_resolved: false を指定警告とともに拒否されます。 解決済みペイロードはそこでインシデントをクローズするためのものなので、これを抑制するとインシデントが永久に未解決のままになります
削除済みのルールを同じ名前で再作成し、「復元」しようとする削除は論理削除です。古いルールは履歴を保持したまま削除状態になります。過去のイベントがない新しいルールが作成されます

「作成」をクリックする前に、インポートエディターの条件チャートで値を確認するよう、必ずユーザーに伝えてください。

通知の動作

発火したルールが実際にどの程度の頻度で通知するかは、ルールよりも主にチャンネルによって決まります。

設定設定場所動作
group_intervalチャンネル内容が変化したグループを Alertmanager が再評価するまでの時間です。デフォルトは短く、グループ化されたルールでは系列が追加・削除されるたびに内容が変化します。「なぜほぼ評価のたびに通知されるのか」という疑問への答えは、通常 repeat_interval ではなくこれです。
repeat_intervalチャンネル変化のない発火中のグループが再通知される頻度です。group_interval による通知が止まった後にのみ効果があります。通常は数時間です。
send_resolvedチャンネルチャンネルが復旧を通知するかどうかです。
send_resolvedルールチャンネル設定をルールごとに上書きします。省略するとチャンネル設定を引き継ぎます — これは、この設定が追加される前のすべてのルールの動作です。

group_wait と group_by は意図的に公開していません。誤った設定をすると、通知が減るのではなく、通知が届かなくなります。

ルールで send_resolved: false を指定する場合

「新しい台帳が作成された」「デプロイが開始された」など、発火時に通知し、復旧時には何も通知しない情報提供用ルールで、専用チャンネルを用意したくない場合に使用します。拒否されるケースについては、「ルールが気付かないうちに変わる落とし穴」の表を参照してください。

send_count は通知件数ではありません

実際に送信する評価ごとに 1 ずつ増えるため、おおよそ発火継続時間 ÷ evaluation_interval になります。1m ルールで 2 日間アラートが発火すると、約 3000 と表示されます。「3000 回ページ通知が届いた」と報告してはいけません。実際に人が通知を受け取った回数は、上記のチャネルの通知間隔によって制限されます。

これを単純な継続時間の指標として扱えない理由は、ほかに 2 つあります。

  • 承認済みの評価はカウントされません。 抑制チェックは送信前に戻り、カウンターを増やす upsert は送信処理の一部であるため、誰かが承認状態を保っている間、数値は増えません。
  • 発火エピソードごとの数値ではありません。 行はフィンガープリントをキーとしており、再発火すると starts_at はリセットされますが、send_count は加算されます。開始と終了を 5 回繰り返した一連のアラートには、5 回分の合計が記録されます。
承認

承認すると、その 1 回の発火インスタンスに対する通知が停止し、アラートは**「現在発火中」**のままになります。これは「対応中」という意味であり、「終了した」という意味ではありません。承認を解除すると、サイレンスが失効します。

抑制は独立した2 つの仕組みで行われますが、期限があるのはそのうち 1 つだけです。最長 7 日間に制限された Alertmanager のサイレンスと、データベースの acknowledged フラグが設定されている間、送信を完全にスキップするエンジン側のチェックです。このフラグに有効期限はありません。

そのため、1 週間後にページ通知が自動で再開すると説明してはいけません。通知が再開するのは、一連のアラートが解決するか、フラップするか、誰かが承認を解除したときです。次に実際に発火した際の upsert で、終了したエピソードのほかの情報とともに acknowledged がクリアされます。

トレースのレイテンシしきい値はナノ秒単位です

アラートエンジンは、ロールアップのパーセンタイルを含め、トレースの duration をナノ秒単位で読み取ります。

ユーザーの指定threshold_value
100ms100000000
250ms250000000
500ms500000000
1s1000000000

ns = ms × 1_000_000 です。"unit": "nanoseconds" を設定してください。

メモ

これは、duration の WHERE フィルターをミリ秒単位で指定するクエリツールとは異なります。アラートはナノ秒、クエリはミリ秒です。kubesense-traces を参照してください。

製品に付属する type-tracing スターターテンプレートでは、説明に「ms」と記載されている threshold: 500 を使用していますが、これは 500 ナノ秒です。コピーしないでください。

テキストフィルターとパターンフィルター

本文の単一マッチには、body を直接フィルターに指定します(raw_filters: {"body": ["timeout"]})。その場合のコストとマッチ方法については、ログフィールド一覧の下にある注記を確認してください。

単純なプレフィックス演算子では表現できない条件(2 つの語句を OR でつなぐ、本文テキストと別のフィールドを組み合わせる、ステータスコードのクラスを指定するなど)には、インポートでは unified_filter が機能しません。唯一機能する方法は、予約済みキー advanced_query に WHERE 文字列を指定することです。

"raw_filters": {
  "advanced_query": ["body SUBSTR_ILIKE \"timeout\" OR body SUBSTR_ILIKE \"connection refused\""]
}

ステータスコードのクラスでも同様に、return_code LIKE "5__" を使います(_ は 1 文字を表します。4__ は 4xx、40_ は 40x です)。advanced_query はほかのすべてのフィルターキーを置き換えるため、すべての条件を 1 つの文字列にまとめてください。

raw_filters の値では、単純なケース向けのプレフィックス演算子も使用できます。

プレフィックス操作例
なしIN{"level": ["ERROR"]}
-NOT IN{"return_code": ["-200"]}
> < >= <=比較{"duration": [">500000000"]}

これらのフィルター形式は扱いにくく、フィルターのバインドに失敗してもエラーが表示されず(その場合、ルールは何にもマッチしないのではなく、すべてにマッチします)、確実な方法は次のとおりです。Explorer の詳細クエリエディターで条件を作成し、アラートエディターに添付して、条件チャートで検証してからエクスポートします。

名前または説明のプレースホルダー

ルールの名前または説明にある{{...}}は、発火する系列ごとに展開されるため、1つのルールからグループごとにタイトルの異なるアラートが1つずつ生成されます。名前空間は2つあります。

ルール自体のラベル — グループ化キーと、ルールが持つlabelsです。各プレースホルダーは次の順序で解決されます。

  1. ラベルキーそのもの。 完全一致が常に優先されます。

  2. UIラベルの別名。 その列がこのアラートのラベルに含まれる場合に限ります。16個のフィールドは、グループ化のドロップダウンでは1つの名前で表示され、別の名前で保存されます。

    service→app_service   domain→cluster        resource→clustered_resource
    container→container_name  node→host         instance→pod_name
    type→level            status_code→return_code  method→subtype
    protocol→protocol_type  role→kind           reason→issue_reason
    primary_workload→perspective_workload   primary_namespace→perspective_namespace
    associate_workload→partner_workload     associate_namespace→partner_namespace
    

    これにより、ルール1で曖昧さが解消されます。serviceはログ固有のserviceとトレースのapp_serviceの両方に対するUIラベルですが、各ルールはそれぞれ自身の列を使って解決します。別名によって値が新たに作られることはありません。どちらでもグループ化していなければ、{{domain}}はそのまま表示されるため、タイプミスが空欄として気づかれずに表示されるのではなく、目に見える形で残ります。

  3. 属性と同じ名前。 属性topicでグループ化すると、保存キーは@topicですが、{{topic}}で解決されます。

{{@topic}}も使用でき、同じ名前の通常のラベルがある場合に使います。topicと@topicの両方があると、{{topic}}では列(ルール1)の値が得られ、属性の値が得られるのは{{@topic}}だけです。区別のためにサフィックスが付いたグループ化キーでは、そのサフィックスもプレースホルダーに引き継がれます。同じ属性を型別または位置別に2回グループ化した場合は、{{status:float}}と{{status#0}}になります。

アラート自体の情報は、予約済みのAlert.プレフィックスの下にあります。

{{Alert.status}}  {{Alert.value}}  {{Alert.threshold}}  {{Alert.thresholdOperator}}
{{Alert.severity}}  {{Alert.timeWindow}}  {{Alert.frequency}}
{{Alert.startedAt}}  {{Alert.startsAt}}  {{Alert.endsAt}}
{{Alert.evaluatedFrom}}  {{Alert.evaluatedTo}}
  • プレフィックスは省略できず、単なる飾りでもありません。{{status}}だけでは最初にルールのラベルstatusが解決されるため、statusという属性でグループ化したルールでは、値ではなく「firing」と表示されていました。この名前空間により衝突がなくなります。どのグループ化でも、Alert.で始まるキーは生成されません。
  • {{Alert.status}}はfiring、resolved、no_dataのいずれかを表示します。表示用のテキストではなく、小文字のトークンです。
  • startedAt/endsAtはエピソードの範囲、evaluatedFrom/evaluatedToはクエリウィンドウの範囲を示します。 5分間のウィンドウで3時間発火しているルールの場合、エピソードは3時間、ウィンドウは5分です。そのため、エピソードから作成した「何が発火したかを見る」リンクでは、5分間の現象を説明するために3時間分のデータが表示されます。リンクにはevaluated*を使ってください。
  • 値が欠落している場合はno_valueと表示されます。 何も測定されなかった系列での{{Alert.value}}は、文字列のまま残るのではなく、トークンに置き換えられる唯一の情報です。作成者がこれをアラートの名前に入れることがあり、{{Alert.value}}がそのまま残るとSlackに送信されてしまうためです。正当な測定値である0.00とは意図的に区別されています。
  • 時刻が欠落している場合は、そのまま表示されます。 発火中のアラートで{{Alert.endsAt}}を指定すると、0001-01-01ではなく、{{Alert.endsAt}}そのものが表示されます。ウィンドウが不明な場合のevaluatedFrom/evaluatedToも同様です。

メンテナンスウィンドウ

Datadog 形式の計画ダウンタイムです。指定した範囲のアラート通知を一定期間ミュートします。また、alert_rule_engine#71 を適用しているデプロイでは、対応するワークフロートリガーも同時にミュートされます。発火時と解決時の両方が対象です。テレメトリは引き続き届き、ルールは引き続き評価され、アラートは引き続き発火・解決し、履歴も記録され、SLO の予算も消費されます。

読み取り時に重要な点があります。ミュートされたアラートは、list-active-alerts と get-alert-history では完全に通常どおりに見えます。発火中のアラートが誰にもページ通知しなかった理由をユーザーに尋ねられた場合、メンテナンスウィンドウが原因の候補です。ただし、MCP ツールでメンテナンスウィンドウを確認することはできません。そのことを伝え、アラート自体のデータから推測するのではなく、Alerts → Maintenance Windows を案内してください。

  • 範囲にはルール ID、ラベルマッチャー、またはその両方を指定します。Alertmanager と同じセマンティクスで、正規表現は文字列全体に一致し、存在しないラベルは空として扱われます。
  • scope_all を明示的に設定しない限り、範囲が空でも何もミュートされません。空欄のフォームで全体が遮断されることはありません。
  • スケジュールは一回限り、毎日、または毎週から選択します。壁時計時刻と IANA タイムゾーンとして保存されるため、「毎晩 01:00」は DST の変更後も 01:00 のままです。
  • 抑制には Alertmanager のサイレンスを使い、エンジンを停止するわけではありません。エンジンを停止すると resolve_timeout が発動し、誤った全解決通知がページ通知されます。

JSON のインポート

トップレベルのスキーマ全体、query_config の形式、すべての enum、一括インポート、およびメトリクス/ログ/トレース/数式ルールの動作確認済みの例については、 references/import-json.md を参照してください。

要点は次のとおりです。

  • フラットなフィールド(threshold_operator、threshold_value)と通常の期間文字列(*_prometheus_format ではなく "5m")を使います。breach_counting_window も同様です。これがインポート時に読み取られる名前です。POST ボディとエクスポートでは breach_counting_window_prometheus_format が使われます。両方を送信し、決して省略しないでください。_prometheus_format の名前だけを指定すると無視され、ルールは通知なしに5 分に設定されます。これは more_than_once だけでなく always にも適用されます。
  • ルールが 1 つの場合は、単一の JSON オブジェクトを使います。複数のルールの場合は、1 つの JSON 配列を使います。ドライランレビューを行って一括インポートします。ルールごとに個別のスニペットを出力してはいけません。
  • インポート時に enabled と query_type は無視されます。サーバーは enabled をハードコードし、最初のクエリの selectedMode からタイプを決定します。
  • Alerts → Alert Rules → Import JSON → レビュー → Create から適用します。ユーザーが確認するまで、何も書き込まれません。

インポート経由でアラートが作成されたと断言してはいけません。インポートと確認を行うのはユーザーです。

まず情報を確認する

メトリクス名、フィールド、チャンネル ID を決して推測で作り出してはいけません。

必要な情報呼び出すツール
メトリクス名get-available-metrics → get-metric-labels
ログ/トレースのフィールド名と値get-trace-or-log-fields
チャンネル IDlist-notification-channels
自分のユーザー名get-current-user

見慣れない形式のルールの場合は、既存の類似ルールをエクスポートして変更するようユーザーに依頼してください。これにより、query_config の形式が有効であることを確認できます。

MCP を使わない場合でも、上記の許可リストからログ/トレースのルールを生成できます(これらは推測ではなく正規のリストです)。ただし、PromQL のメトリクス名を作り出してはいけません。これらはクラスター固有です。ユーザーに尋ねるか、参照用ルールをエクスポートしてもらってください。

ルール

  1. ルールを出力する前に、すべてのメトリクス、フィールド、チャンネル ID を確認してください。
  2. クエリツールのカタログラベルではなく、アラートエンジンのフィールドリストを使用してください。type ではなく level、トレースでは service ではなく app_service です。body はフィルターできますが、グループ化には使用できません。
  3. 最初に list-notification-channels を実行してください。ID を捏造してはいけません。[] の場合、単一ルールのインポートはできません。
  4. トレースのレイテンシしきい値はナノ秒で指定し、unit: "nanoseconds" とします。
  5. groupBy の各エントリに3つのキーすべてを指定してください。指定しないと、グループ化は黙って無視されます。
  6. 数値の value_operation には、type: "float" の fields が必要です。指定しないと row_count に変わります。
  7. unit には、実際のフォーマッター値(nanoseconds、milliseconds、percentage、bytes、CPU、number、raw)を指定してください。
  8. テキスト/クラスのフィルターは unified_filter ではなく、raw_filters.advanced_query に指定してください。advanced_query を指定すると、他のすべてのフィルターキーが置き換えられます。
  9. クエリラベルは位置に基づきます。metric_query_label には、しきい値を適用するクエリを指定します(単一クエリ → A、数式 → 数式のラベル)。
  10. ルールが1つの場合はオブジェクト、複数の場合は1つの配列にします。どちらの場合も、コードブロックは1つだけにしてください。
  11. メトリクスの消失がインシデントとなる場合(ゲージ/ハートビート)に限り、no_data_state: "firing" を使用してください。カウント/レート/変化のルールでは使用しないでください。正常な期間の結果は0ではなく空になるため、firing を指定すると値0で誤発火します。normal を使用してください。
  12. more_than_once には breaches_count(2以上)が必要です。always には threshold_frequency も設定する必要があります。3つの頻度すべてで breach_counting_window が参照されます。more_than_once ではこの期間内の違反回数、always ではこの期間を通じた条件の成立、at_least_once ではこの期間内の解決状況が確認されます。指定しない場合、エンジンは time_window を使いますが、インポートはそこまで進みません。エディターが空欄を5分に設定するため、値を指定してください。
  13. name 内の {{field}} プレースホルダーは、グループ化キーまたはルールラベルに対して、発火した系列ごとに解決されます。たとえば workload でグループ化する場合は、"High latency {{workload}}" とします。一致するものがない場合はそのまま文字列として残るため、タイプミスに気付けます。アラート自体の情報を参照するには Alert. を付けてください。{{value}} ではなく {{Alert.value}} とします。
  14. 作成前に条件チャートを確認するようユーザーに伝えてください。また、create-alert が実際に ID を返していない限り、ルールが作成されたと主張してはいけません。

コメント