kubesense-logs について
kubesense-logs は、KubeSense MCP サーバー経由でログを扱うためのスキルです。個別行の取得と集計分析を使い分け、フィールド、条件式、ページングの制約を案内します。
主な機能
- 01ログフィールドカタログの確認
- 02個別ログ行の取得
- 03件数、傾向、パーセンタイルの集計
- 04カタログ名と WHERE 条件による絞り込み
- 05時間範囲ページングの制約説明
活用シーン
- 01ワークロードのエラーログ確認
- 02ワークロード別エラー件数の推移分析
- 03致命的エラーを記録した Pod 数の集計
- 04タイムアウトを含むログメッセージの検索
MCP 対応
このスキルには KubeSense MCP サーバーが必要で、ログフィールドカタログ、検索、分析ツールの呼び出し方を案内します。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ kubesense-ai/ kubesense-mcp-skills --skill kubesense-logsインストール後、Claude Code で/kubesense-logsを入力して読み込まれたか確認します。
詳細
KubeSense ログ
KubeSense MCP サーバーが必要です。接続、認証、共通の WHERE 句のリファレンスについては、kubesense-mcp を参照してください。ここにあるツールは、logs モジュールに対して RBAC を解決します。
ツール
| ツール | 使用する場面 | 戻り値 |
|---|---|---|
get-trace-or-log-fields (signal: "logs") | 必ず最初に使用 | 対象時間枠のフィールドカタログ |
search-logs | 個々のログ行を読みたい場合 | 最大 page_size 行(デフォルトは 10) |
analyze-logs | 件数、割合、傾向、パーセンタイルを知りたい場合 | 集計系列 |
合計を計算するために行を読み込むのは、最もよくある間違いです。 質問が「いくつあるか」「どのくらいの頻度か」「どれが最悪か」であれば、analyze-logs を使用してください。生の行をページ分割して取得するよりも、対象時間枠全体を一度の呼び出しで処理するほうが正確です。
フィールド名 — カタログのラベルのみ
サーバーは、すべての入力箇所(where、required_fields、group_by_fields、fields、sort_by)で、ストレージの列名を拒否し、次のエラーを返します。
field "pod_name" is a storage column; use the catalog label "instance" instead
| 概念 | 使用するラベル | ストレージ列(拒否) |
|---|---|---|
| ログの重要度 | type | level |
| Pod | instance | pod_name |
| コンテナ | container | container_name |
| ノード/ホスト | node | host |
| ワークロード | workload | — |
| 名前空間 | namespace | — |
| クラスター | cluster | — |
| ログメッセージ | body | — |
| ログ形式 | format | — |
| ソース | source | — |
| リージョン | region | — |
| アプリのバージョン | app_version | — |
| 環境 | env_type | — |
これは、get-trace-or-log-fields がログ用に公開する 13 個のフィールドのすべてです。
さらに 3 つのフィールドも解析されますが、検出結果には表示されません。timestamp、pattern_id、body_length です。
警告
ログには
serviceフィールドがありません。serviceが存在するのはトレースのみです(→app_service)。ログに対してservice = checkoutを指定すると、unknown field "service" for signal=logsが返されます。アプリケーション名にはworkloadを使用してください。ログでは
node、トレースではnode_nameです。 2 つのシグナルで異なります。ログではnode(→host)、トレースではnode_nameを使用します。シグナル間でフィールド名をそのまま使うと、確実に失敗します。
ログの列挙値は大文字です
type が受け付ける値は、ERROR、WARN、INFO、DEBUG、TRACE、FATAL、PANIC のみです。大文字と小文字は区別されるため、type = error は何も一致しません。
(トレースでは小文字の status = error を使用します。2 つのシグナルでは、フィールド名と大文字・小文字の両方が異なります。)
format が受け付ける値は、小文字の json、klog、nginx です。
メモ
大文字・小文字の確認には、
get-trace-or-log-fieldsのexample列ではなく、enum_values列を参照してください。例の生成機能では、typeを含む複数の列挙型フィールドが取得されず、空欄になります。enum_valuesは常に正しい値を返します。
WHERE 構文
type = ERROR AND namespace = production
type IN (ERROR, FATAL) AND workload = checkout
NOT (env_type = dev)
body ILIKE "%timeout%"
@user.id = abc-123
WHERE パーサーが実際に受け付ける演算子は、= != < > <= >= LIKE ILIKE
SUBSTR_ILIKE IN です。これらは AND / OR / NOT および括弧と組み合わせて使用できます。
警告
get-trace-or-log-fieldsのoperators列は、実際よりも多くの演算子を宣伝しています。HAS_TOKEN、HAS_ALL、HAS_ANY、LIKE_AND、ILIKE_LOG、IS_IP_ADDRESSは凡例に表示されていますが、 WHERE 文字列の構文としては使用できません。body HAS_TOKEN oomは解析に失敗します。 上記のリストを使用してください。
引用符の使用。 引用符なしの値に使用できるのは、英字、数字、_、.、- のみです。スラッシュ、
コロン、%、スペースを含む値は必ず二重引用符で囲んでください。
body ILIKE "%connection refused%" ✓
timestamp > "2026-07-30T10:00:00Z" ✓
body ILIKE %timeout% ✗ parse error
NOT IN はリーフとして解析されません。 NOT (namespace IN (kube-system, default)) のように記述してください。
属性は WHERE で @ プレフィックスを付けると、ログに対して正しく機能します。
@user.id = abc-123
@http.status_code > 400
属性で使用できる演算子は、= != IN < > <= >= LIKE ILIKE です。引用符で囲まれていない数値の属性値は数値に変換されるため、@latency > 100 は数値として比較されます。
警告
exist(@field)は両方のシグナルで機能しません。値を伴うEXIST演算子が出力され、バリデーターに拒否されます(operator "EXIST" takes no values (got 1))。機能する存在チェックはありません。代わりに具体的な値でフィルターしてください。
group_by_fields / fields / required_fields / sort_by には @ を付けません。代わりにフラグを設定してください。
{ "field": "user.id", "is_attribute": true }
search-logs
{
"from_time": "2026-07-30T10:00:00Z",
"to_time": "2026-07-30T11:00:00Z",
"where": "type = ERROR AND namespace = production",
"required_fields": [
{ "field": "instance", "is_attribute": false },
{ "field": "body", "is_attribute": false }
],
"page_size": 50
}
出力は TSV 形式です。# total_count=<N> error_count=<N> is_free_search=<bool> の行、ヘッダー行、続いてログごとに1行が出力されます。total_count は page_size を無視したウィンドウ全体の件数です。追加の結果があるかどうかは、受け取った行数と比較して確認してください。
ウィンドウベースのページネーション
page または offset パラメーターはありません。 ウィンドウは半開区間
(from_time <= timestamp < to_time)なので、to_time を狭めてページを取得します。
- 実際のウィンドウを指定してクエリを実行します。
- 返された行の
timestampの最小値を取得します。最後の行が最も古いとは限らないため、そう決めつけないでください。 - 同じ
from_timeとwhereを指定し、最小値をそのままコピーしてto_timeとして、再度呼び出します。 page_sizeより少ない行しか返されない場合、または結果が確定した場合に停止します。
タイムスタンプは、ミリ秒精度の RFC3339 UTC 形式です。セルの値をそのままコピーしてください。 秒単位に切り捨てると、その秒内の行を再取得したり、読み飛ばしたりします。
重要
ページ分割したスキャンは全件調査ではなくサンプルです。 行は
toStartOfHour(timestamp) DESC, cluster DESC, timestamp DESCの順に並びます。まず時間単位のバケット、 次にクラスターで並べられます。複数のクラスターにまたがって、1時間分の一致行がpage_sizeを超える場合、to_timeを進めると、スキャンがまだ到達していないクラスターの行を読み飛ばす可能性があります。すべての結果を 読み取るには、clustersを1つのクラスターに固定し、大きなpage_sizeを使用してください。 それ以外の場合は、ページ数を増やすよりpage_sizeを大きくし、集計が必要な場合は ページネーションよりanalyze-logsを優先してください。
is_free_search
body、trace_id、span_id、またはいずれかの属性を参照すると、クエリは事前集計済みのロールアップではなく、
生テーブルに送られます。速度は遅くなりますが、メッセージ本文を確認する唯一の方法です。この値は自動的に計算され、
出力ヘッダーに報告されます。列のみを対象にしたフィルターは、高速なロールアップ経路を維持します。
ここでの body ILIKE "…" は、サーバー側で本文テキストインデックスを使用するよう書き換えられます。
生 SQL にはこの書き換えは適用されないため、検索の条件上必要でない限り、メッセージ検索を execute-sql に移さないでください。
必要な場合は、kubesense-sql の Searching Log Text に従ってください。
analyze-logs
{
"from_time": "2026-07-30T10:00:00Z",
"to_time": "2026-07-30T11:00:00Z",
"query_type": "range",
"where": "type = ERROR",
"group_by_fields": [ { "field": "workload", "is_attribute": false } ],
"value_operation": "row_count",
"sort_direction": "DESC",
"limit": 10
}
query_type:時系列の場合はrange、系列ごとに1つの数値を返す場合はinstant。value_operation:row_count、unique_count、avg、sum、min、max、p50、p90、p95、p99。fieldsは、row_count以外のすべての演算の対象フィールドを指定します。 ポッドのunique_count→value_operation: "unique_count"、fields: [{"field": "instance"}]。limitはrangeクエリの系列数を制限します(最大値順の上位N件。デフォルトは20)。instantでは無視されます。
警告
value_operation: "count"は無効です。正しい名前はrow_countです。ツールスキーマの概要行には「Common: count, avg, …」とありますが、これは誤りです。
body は group_by_fields では使用できません(ロールアップテーブルに存在しません)。フィルター専用フィールドです。類似メッセージをグループ化する場合は、pattern_id でグループ化してください。
出力形式
クエリラベル("A")をキーとする列指向のJSONです。range の場合、共通の timestamps 配列(Unix秒)が1回だけ出力され、各系列には位置が対応する values 配列が含まれます(null はそのバケットにデータがないことを示します)。instant の場合、各系列にはスカラー値の value が含まれます。total_series/truncated は、上位N件の制限を適用する前に存在したゼロ以外の系列数を示します。
使用例
過去1時間のワークロードごとのエラー数を傾向として確認する
query_type: range、where: "type = ERROR"、
group_by_fields: [{"field":"workload"}]、value_operation: row_count
現時点で致命的なエラーを記録した個別のポッド数を確認する
query_type: instant、where: "type = FATAL"、value_operation: unique_count、
fields: [{"field":"instance"}]
実際のタイムアウトメッセージを読む
search-logs、where: 'body ILIKE "%timeout%" AND workload = checkout'、
required_fields: [{"field":"instance"},{"field":"body"}]、page_size: 50
エラー率をパーセンテージで確認する — 2つのクエリと数式が必要なため、
analyze-telemetry を使用してください。kubesense-mcp を参照してください。
ルール
- 最初に
get-trace-or-log-fieldsをsignal: "logs"とともに呼び出し、クエリに使用するものと同じ時間範囲を渡してください。属性キーは時間範囲ごとに異なります。 - カタログのラベルを使用してください:
type、instance、container、node。level、pod_name、container_name、hostは使用しないでください。 - ログに
serviceフィールドはありません。workloadを使用してください。 typeの値は大文字です(errorではなくERROR)。exampleではなく、enum_valuesから大文字・小文字を確認してください。/、:、%、またはスペースを含む値は引用符で囲んでください。x NOT IN (...)ではなく、NOT (x IN (...))を使用してください。= != < > <= >= LIKE ILIKE SUBSTR_ILIKE INのみを使用してください。案内されているトークン/インデックス演算子にはWHERE句の構文がありません。value_operationはcountではなくrow_countです。- 件数や傾向の確認には
analyze-logsを使用し、メッセージを読む場合に限りsearch-logsを使用してください。集計のためにページネーションを行わないでください。 - ページを進める際は、返されたタイムスタンプの最小値まで
to_timeを絞り込んでください。オフセットはありません。クラスターを固定しない限り、複数クラスターにまたがるページスキャンはサンプルとして扱ってください。 bodyはフィルター専用で、グループ化には使用できません。