kql
KQL (Kibana Query Language) 包括的技術ガイド
本記事は AI (Claude Opus 4.6) によって生成されました。 生成日: 2026-04-11
目次
- はじめに
- Elasticsearch クエリ言語群における KQL の位置づけ
- 基本構文
- 比較演算子・等値演算子・ワイルドカード
- 論理演算子
- フィールド存在チェック
- ネストフィールドクエリ
- マルチフィールドワイルドカード
- 日付範囲クエリ
- 特殊文字のエスケープ
- 注意事項: マルチバリューフィールドの範囲クエリ制限
- KQL が使用可能な場所
- KQL vs Lucene 比較
- 実践的ユースケース
- まとめ
1. はじめに
1.1 KQL とは何か
KQL (Kibana Query Language) は、Kibana においてデータをフィルタリングするための専用クエリ言語である。Elasticsearch に蓄積されたログ、メトリクス、トレースなどの膨大なデータを、直感的かつ効率的に絞り込むことを目的として設計されている。
KQL の最大の特徴は「フィルタリング専用言語」であるという点にある。Elasticsearch の Query DSL や ES|QL のように集計やソートを行う機能は持たず、「どのドキュメントを表示するか」というフィルタリングに特化している。この設計思想により、KQL は非常にシンプルで習得しやすい構文を実現している。
1.2 KQL の設計哲学
KQL が設計された背景には、以下の課題があった。
- Lucene クエリ構文の複雑さ: Lucene は強力だが、構文の癖が多く、初学者にとって直感的ではなかった
- オートコンプリートのサポート: 既存のクエリ言語では、効果的なオートコンプリート(自動補完)機能を実装するのが困難だった
- ネストフィールドの扱い: Elasticsearch のネスト型フィールドを直感的にクエリする手段が必要だった
これらの課題を解決するために、KQL は以下の設計原則に基づいて開発された。
| 設計原則 | 説明 |
|---|---|
| シンプルさ | 最小限の構文で最大限の表現力を実現 |
| 直感性 | 自然言語に近い記述が可能 |
| オートコンプリート対応 | フィールド名・値の自動補完が容易に実装可能 |
| ネストサポート | ネスト型フィールドに対するクエリを第一級でサポート |
| フィルタリング特化 | 集計やソートを排除し、フィルタリングに専念 |
1.3 KQL を使うメリット
# KQL の記述例 - 非常にシンプルで読みやすい
status: 500 and http.request.method: GET
# 同等の Lucene クエリ - KQL よりも構文を意識する必要がある
status:500 AND http.request.method:GET
# 同等の Query DSL (JSON) - 冗長だがプログラマブル
{
"bool": {
"must": [
{ "match": { "status": 500 } },
{ "match": { "http.request.method": "GET" } }
]
}
}
上記の例からわかるように、KQL は人間が読み書きしやすい構文を持っている。特に、Kibana の検索バーに直接入力するユースケースにおいて、その簡潔さが大きな利点となる。
2. Elasticsearch クエリ言語群における KQL の位置づけ
2.1 Elasticsearch のクエリ言語一覧
Elasticsearch エコシステムには、複数のクエリ言語が存在する。それぞれの言語は異なる目的・ユースケースに特化している。
| 言語 | 用途 | 実行場所 | 特徴 |
|---|---|---|---|
| KQL | フィルタリング | Kibana UI | シンプル、オートコンプリート対応 |
| Lucene | フィルタリング + スコアリング | Kibana UI / API | 正規表現、ファジー検索、近接検索が可能 |
| Query DSL | 全機能クエリ | REST API (JSON) | 最も柔軟、プログラマブル |
| ES|QL | クエリ + 集計 + 変換 | Kibana UI / API | SQL ライクなパイプライン構文 |
| EQL | イベント相関分析 | API / Security | 時系列イベントのシーケンスマッチ |
2.2 各言語の使い分けフローチャート
[データを探索・フィルタリングしたい]
|
+-- Kibana UI で素早く絞り込みたい
| |
| +-- シンプルなフィルタ条件 --> KQL
| +-- 正規表現・ファジー検索が必要 --> Lucene
| +-- 集計・変換も行いたい --> ES|QL
|
+-- API からプログラマブルにクエリしたい
| |
| +-- 全文検索 + 集計 --> Query DSL
| +-- SQL ライクに記述 --> ES|QL
|
+-- セキュリティイベントの相関分析 --> EQL
2.3 KQL の適用範囲
KQL は以下の場面で利用される。
- Discover: ログ探索の主要なフィルタリング手段
- Dashboard: ダッシュボード上部のフィルタバー
- Alerting: アラートルールのフィルタ条件
- Security (SIEM): セキュリティイベントの絞り込み
- Observability: APM、Uptime、Metrics Explorer のフィルタ
KQL は、Kibana の「フィルタバー」(検索バー) が表示されるほぼすべての画面で利用可能であり、Kibana ユーザーにとって最も頻繁に触れるクエリ言語と言える。
3. 基本構文
3.1 フリーテキスト検索
KQL の最もシンプルな形は、フリーテキスト検索である。フィールド名を指定せず、検索語のみを入力する。
error
この場合、KQL はデフォルトフィールド (通常は全フィールド) に対して error を含むドキュメントを検索する。Kibana のインデックスパターン設定で検索対象フィールドが制御される。
複数語のフリーテキスト検索:
connection timeout
スペースで区切られた複数の語は、暗黙的に OR で結合される。つまり、上記は connection または timeout のいずれかを含むドキュメントにマッチする。
重要: フリーテキスト検索における複数語のデフォルト結合は OR であることに注意。AND ではない。
3.2 フィールド指定検索
特定のフィールドに対して値を検索するには、フィールド名: 値 の形式を使う。
status: 200
http.request.method: GET
host.name: web-server-01
フィールド名と値の間のコロン : の前後にはスペースを入れても入れなくてもよい。ただし、可読性のためにコロンの後にスペースを入れることが推奨される。
# 以下はすべて同じ意味
status:200
status: 200
status : 200
3.3 フレーズ検索
複数語のフレーズ (語順を維持した検索) を行うには、ダブルクォーテーションで囲む。
message: "connection timed out"
このクエリは、message フィールドに connection timed out というフレーズ (語順含む) が含まれるドキュメントにマッチする。
フレーズ検索とフリーテキスト検索の違い:
# フレーズ検索 - "connection timed out" という語順でマッチ
message: "connection timed out"
# 個別の語の OR 検索 - connection OR timed OR out のいずれか
message: connection timed out
注意: クォーテーションなしの複数語は各語が OR で結合されるため、意図しない結果になりやすい。特定のフレーズを検索する場合は必ずクォーテーションを使うこと。
3.4 テキストフィールドとキーワードフィールド
Elasticsearch では、文字列フィールドは通常 text 型と keyword 型 (またはその両方) でマッピングされる。KQL の挙動はフィールドの型によって異なる。
| フィールド型 | KQL の挙動 | 例 |
|---|---|---|
text | アナライズ済みトークンに対してマッチ | message: error は "An error occurred" にマッチ |
keyword | 完全一致 | status.keyword: "404 Not Found" は完全一致のみ |
text + keyword (マルチフィールド) | text 型として検索 (部分マッチ) | 自動的に text 型フィールドが使われる |
# text フィールドの場合 - 部分マッチ
message: error
# "An error occurred in the application" にマッチ
# keyword フィールドの場合 - 完全一致
http.response.status_code: 404
# 数値型は常に完全一致
# keyword 型文字列 - 完全一致が必要
agent.keyword: "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"
3.5 数値フィールドの検索
数値フィールドに対しては、等値検索が直感的に行える。
http.response.status_code: 200
response_time: 1500
bytes: 0
数値の範囲検索については、比較演算子のセクションで詳述する。
3.6 ブール値の検索
ブール型フィールドに対しては、true または false を指定する。
event.outcome: true
tls.established: false
4. 比較演算子・等値演算子・ワイルドカード
4.1 等値演算子
KQL における等値演算子はコロン : である。
# 等値検索
status: 200
http.request.method: POST
host.name: "production-web-01"
注意: KQL には「等しくない (!=)」演算子は存在しない。否定には
NOTキーワードを使用する。
# 等しくないドキュメントを検索
NOT status: 200
NOT http.request.method: POST
4.2 比較演算子
数値型および日付型のフィールドに対して、以下の比較演算子が使用可能である。
| 演算子 | 意味 | 例 |
|---|---|---|
> | より大きい | bytes > 1000 |
>= | 以上 | bytes >= 1000 |
< | より小さい | response_time < 500 |
<= | 以下 | response_time <= 500 |
数値の比較例:
# レスポンスタイムが 1000ms を超えるリクエスト
response_time > 1000
# ステータスコードが 400 以上 (クライアントエラー + サーバーエラー)
http.response.status_code >= 400
# 転送バイト数が 0 のリクエスト
bytes <= 0
# ステータスコードが 200 未満
http.response.status_code < 200
範囲の組み合わせ:
# 400 以上 500 未満 (クライアントエラーのみ)
http.response.status_code >= 400 and http.response.status_code < 500
# レスポンスタイムが 500ms から 2000ms の間
response_time >= 500 and response_time <= 2000
4.3 ワイルドカード
KQL では、値の部分にワイルドカード * を使用できる。* は任意の 0 文字以上の文字列にマッチする。
# "error" で始まるメッセージ
message: error*
# "timeout" で終わるメッセージ
message: *timeout
# "connect" を含むメッセージ
message: *connect*
# 特定のプレフィックスを持つホスト名
host.name: web-*
# 特定のパターンにマッチするパス
url.path: /api/v*/users
ワイルドカードの使用上の注意:
| パターン | 説明 | パフォーマンス影響 |
|---|---|---|
value* | 前方一致 | 低い (効率的) |
*value | 後方一致 | 高い (全走査が必要) |
*value* | 部分一致 | 高い (全走査が必要) |
val*ue | 中間ワイルドカード | 中程度 |
パフォーマンスのヒント: 前方一致 (
value*) は最も効率的なワイルドカードパターンである。後方一致 (*value) や部分一致 (*value*) はインデックスの全走査が必要になるため、大量データに対しては応答時間が長くなる可能性がある。
ワイルドカードが使えない場面:
- フィールド名の途中 (ただしマルチフィールドワイルドカードは例外。セクション 8 参照)
- 比較演算子と組み合わせた場合 (
bytes > *は無効)
5. 論理演算子
5.1 AND 演算子
2 つの条件が両方とも真である場合にマッチする。
status: 200 and http.request.method: GET
and は大文字・小文字を区別しない。AND, and, And のいずれも使用可能である。ただし、慣例的に小文字の and または大文字の AND が使われる。
# 複数条件の AND
status: 200 and http.request.method: GET and url.path: /api/*
5.2 OR 演算子
2 つの条件のいずれかが真である場合にマッチする。
status: 200 or status: 201
# 複数ステータスコードのいずれか
status: 200 or status: 201 or status: 204
5.3 NOT 演算子
条件を否定する。
NOT status: 200
NOT http.request.method: DELETE
NOT は他の演算子と組み合わせて使用できる。
# 200 以外で、かつ GET リクエスト
NOT status: 200 and http.request.method: GET
# エラーを含まないメッセージ
NOT message: error
5.4 演算子の優先順位
KQL における演算子の優先順位は以下の通りである。
| 優先順位 | 演算子 | 説明 |
|---|---|---|
| 1 (最高) | NOT | 否定 |
| 2 | AND / and | 論理積 |
| 3 (最低) | OR / or | 論理和 |
この優先順位は一般的なプログラミング言語と同様であり、NOT が最も強く結合し、次に AND、最後に OR となる。
優先順位の例:
# 以下のクエリ:
status: 200 or status: 201 and http.request.method: GET
# は、以下のように解釈される (AND が OR より先に評価される):
status: 200 or (status: 201 and http.request.method: GET)
# 意図が「200 または 201 のステータスで、かつ GET リクエスト」の場合:
(status: 200 or status: 201) and http.request.method: GET
5.5 括弧によるグルーピング
括弧 () を使って、評価順序を明示的に制御できる。
# 括弧で OR グループを先に評価
(status: 200 or status: 201) and http.request.method: GET
# 複雑な条件の組み合わせ
(host.name: web-* or host.name: api-*) and (status >= 500 or response_time > 5000)
# ネストした括弧
((status: 500 or status: 502) and host.name: web-*) or (status: 503 and host.name: api-*)
実践的な例 - 障害調査のクエリ:
# 本番環境のWebサーバーで発生したサーバーエラー (直近)
(
host.name: prod-web-* or host.name: prod-api-*
)
and (
http.response.status_code >= 500
)
and (
NOT http.response.status_code: 503
)
上記のクエリは以下を意味する:
- 本番のWebサーバーまたはAPIサーバー
- HTTP ステータスコードが 500 以上 (サーバーエラー)
- ただし 503 (Service Unavailable) は除外
6. フィールド存在チェック
6.1 基本的な存在チェック
特定のフィールドが存在する (値が設定されている) ドキュメントを検索するには、ワイルドカード * を値として使用する。
# error フィールドが存在するドキュメント
error: *
# user.name フィールドが存在するドキュメント
user.name: *
# tls.version フィールドが存在するドキュメント
tls.version: *
6.2 フィールドが存在しないドキュメントの検索
NOT と組み合わせることで、フィールドが存在しないドキュメントを検索できる。
# error フィールドが存在しないドキュメント
NOT error: *
# user.name が未設定のドキュメント
NOT user.name: *
6.3 実践的な使用例
# エラーフィールドが存在し、かつステータスが 500 系のドキュメント
error: * and http.response.status_code >= 500
# スタックトレースが含まれるエラーログ
error.stack_trace: * and log.level: error
# TLS バージョンが記録されていないリクエスト (非 TLS 通信の可能性)
NOT tls.version: * and event.category: network
# ユーザーエージェントが欠落しているリクエスト (Bot の可能性)
NOT user_agent.original: * and http.request.method: *
活用のヒント: フィールド存在チェックは、データ品質の監視やマッピングの問題を発見するのに非常に有用である。想定されるフィールドが欠落しているドキュメントを定期的にチェックすることで、パーシングの問題やデータパイプラインの障害を早期に発見できる。
7. ネストフィールドクエリ
7.1 ネストフィールドとは
Elasticsearch の nested 型は、オブジェクトの配列において各オブジェクトの関連性を保持するためのマッピング型である。通常の object 型では配列内のオブジェクトの関連性が失われるが、nested 型を使うことで各オブジェクトの内部フィールド間の関連性が維持される。
例: ユーザーリストの nested マッピング
{
"mappings": {
"properties": {
"users": {
"type": "nested",
"properties": {
"first": { "type": "keyword" },
"last": { "type": "keyword" }
}
}
}
}
}
サンプルドキュメント:
{
"users": [
{ "first": "Alice", "last": "White" },
{ "first": "Bob", "last": "Black" }
]
}
7.2 KQL でのネストフィールドクエリ構文
KQL では、ネストフィールドに対して波括弧 {} を使ったクエリ構文を提供している。
users:{ first: "Alice" and last: "White" }
このクエリは、users 配列内の同一オブジェクトに first: "Alice" かつ last: "White" があるドキュメントにマッチする。
7.3 ネストクエリと通常クエリの違い
# ネストクエリ (KQL) - 同一オブジェクト内でのマッチ
users:{ first: "Alice" and last: "White" }
# --> Alice White が存在するドキュメントにマッチ
# --> Alice Black + Bob White の組み合わせにはマッチしない
# 通常のクエリ (nested 構文なし) - クロスオブジェクトマッチの可能性
users.first: "Alice" and users.last: "White"
# --> nested 型の場合でも、KQL は自動的にネストクエリに変換する
# --> ただし、object 型の場合はクロスオブジェクトマッチが発生する可能性がある
7.4 ネストクエリの実践例
# 特定のファーストネームとラストネームの組み合わせ
users:{ first: "Alice" and last: "White" }
# ネスト内での OR
users:{ first: "Alice" or first: "Bob" }
# ネスト内での NOT
users:{ first: "Alice" and NOT last: "Black" }
# 複数レベルのネスト (items.variants がネスト型の場合)
items:{ name: "Widget" and variants:{ color: "red" and size: "large" } }
7.5 ネストクエリの注意点
| 注意点 | 説明 |
|---|---|
| マッピング依存 | フィールドが nested 型でマッピングされている必要がある |
| パフォーマンス | ネストクエリは通常のクエリより計算コストが高い |
| 自動検出 | KQL はフィールドのマッピングを検出し、nested 型の場合は自動的にネストクエリに変換する |
| 波括弧構文 | 明示的なネストクエリ構文を使うことで、意図を明確にできる |
8. マルチフィールドワイルドカード
8.1 フィールド名でのワイルドカード
KQL では、フィールド名の部分にワイルドカード * を使用して、複数のフィールドを一度にクエリできる。
# datastream で始まるすべてのフィールドを検索
datastream.*: logs
# http.request で始まるフィールド
http.request.*: POST
# すべてのフィールドで検索 (フリーテキスト検索と同等)
*: error
8.2 マルチフィールドワイルドカードの実践例
# すべての host 関連フィールドで特定の値を検索
host.*: "production-web-01"
# すべての URL 関連フィールドで "/api" を含むものを検索
url.*: */api/*
# すべての error 関連フィールドが存在するドキュメント
error.*: *
# メトリクス系フィールドの横断検索
system.cpu.*: *
8.3 ECS (Elastic Common Schema) との組み合わせ
ECS を採用している環境では、マルチフィールドワイルドカードが特に有用である。
# すべての source 関連フィールド (source.ip, source.port, source.geo.* 等)
source.*: 192.168.*
# すべての destination 関連フィールド
destination.*: 10.0.*
# すべての event 関連フィールド
event.*: authentication
# すべての process 関連フィールド
process.*: nginx
# すべての geo 関連フィールド (任意の親フィールド配下)
*.geo.country_name: Japan
8.4 注意点
- マルチフィールドワイルドカードは多くのフィールドに展開されるため、パフォーマンスに影響する可能性がある
- インデックスパターンに多数のフィールドがある場合は、可能な限り具体的なフィールド名を指定することが推奨される
- ワイルドカードはフィールド名のドット区切りの各部分で使用可能 (
*.geo.*: Japan)
9. 日付範囲クエリ
9.1 基本的な日付クエリ
日付フィールドに対して比較演算子を使用する。
# 2 週間前より新しいドキュメント
@timestamp < now-2w
# 過去 24 時間のドキュメント
@timestamp >= now-24h
# 特定の日付以降
@timestamp >= "2026-01-01"
# 特定の日付範囲
@timestamp >= "2026-01-01" and @timestamp < "2026-02-01"
9.2 日付数学 (Date Math) 表現
KQL は Elasticsearch の日付数学表現をサポートしている。
| 表現 | 意味 |
|---|---|
now | 現在時刻 |
now-1h | 1 時間前 |
now-24h | 24 時間前 |
now-1d | 1 日前 |
now-7d | 7 日前 |
now-2w | 2 週間前 |
now-1M | 1 ヶ月前 |
now-1y | 1 年前 |
now/d | 今日の開始 (日の切り捨て) |
now/w | 今週の開始 |
now/M | 今月の開始 |
9.3 日付範囲の実践例
# 直近 1 時間のエラーログ
@timestamp >= now-1h and log.level: error
# 今週のアクセスログ
@timestamp >= now/w and event.category: web
# 過去 30 日間の認証失敗
@timestamp >= now-30d and event.action: "authentication_failure"
# 特定の時間帯 (メンテナンスウィンドウ)
@timestamp >= "2026-03-15T02:00:00" and @timestamp < "2026-03-15T06:00:00"
# 先月のデータ
@timestamp >= now-1M/M and @timestamp < now/M
9.4 日付フォーマット
KQL で日付を直接指定する場合、以下のフォーマットが使用可能である。
# ISO 8601 フォーマット
@timestamp >= "2026-04-01T00:00:00"
@timestamp >= "2026-04-01T00:00:00Z"
@timestamp >= "2026-04-01T00:00:00+09:00"
# 日付のみ (時刻は 00:00:00 として扱われる)
@timestamp >= "2026-04-01"
ベストプラクティス: タイムゾーンが重要な場合は、常にタイムゾーン情報を含む ISO 8601 フォーマットを使用すること。タイムゾーンを省略した場合、Kibana の設定タイムゾーンが適用される。
10. 特殊文字のエスケープ
10.1 KQL の特殊文字一覧
KQL において特別な意味を持つ文字は以下の通りである。
| 文字 | 用途 | エスケープ方法 |
|---|---|---|
\ | エスケープ文字 | \\ |
( | グルーピング開始 | \( |
) | グルーピング終了 | \) |
: | フィールド・値の区切り | \: |
< | 比較演算子 | \< |
> | 比較演算子 | \> |
" | フレーズ検索の区切り | \" |
* | ワイルドカード | \* |
{ | ネストクエリ開始 | \{ |
} | ネストクエリ終了 | \} |
10.2 エスケープの実践例
# コロンを含む値の検索
message: "Error\: connection refused"
# 括弧を含む値の検索
message: "function\(\) failed"
# アスタリスクをリテラルとして検索
message: "file\*.log"
# バックスラッシュを含むパスの検索
file.path: "C\:\\Users\\admin\\Documents"
# ダブルクォートを含む値
message: "received \"invalid\" response"
10.3 クォーテーション内のエスケープ
ダブルクォーテーションで囲んだフレーズ内では、バックスラッシュとダブルクォーテーションのみがエスケープ対象である。
# フレーズ内のダブルクォーテーション
message: "user said \"hello\""
# フレーズ内のバックスラッシュ
file.path: "C:\\Windows\\System32"
10.4 エスケープが不要な場面
フレーズ検索 (ダブルクォーテーション内) では、\ と " 以外の特殊文字はエスケープ不要である。
# フレーズ内のコロンはエスケープ不要
message: "timestamp: 2026-04-01"
# フレーズ内の括弧はエスケープ不要
message: "func() returned error"
# フレーズ内のアスタリスクはエスケープ不要
message: "file*.log"
11. 注意事項: マルチバリューフィールドの範囲クエリ制限
11.1 マルチバリューフィールドとは
Elasticsearch では、1 つのフィールドに複数の値を持つドキュメントが存在しうる。
{
"tags": ["critical", "production", "web"],
"ports": [80, 443, 8080]
}
11.2 範囲クエリの制限
マルチバリューフィールドに対して範囲クエリを使用する場合、直感に反する結果が返される場合がある。
例: ports フィールドに [80, 443, 8080] が含まれるドキュメント
# このクエリ:
ports > 100 and ports < 200
# 直感的には「100 ~ 200 の範囲のポートを持つドキュメント」を期待するが、
# 実際にはマッチしてしまう可能性がある。
# 理由: ports > 100 は 443 や 8080 があるためマッチし、
# ports < 200 は 80 があるためマッチする。
# つまり、同じ値が両条件を満たす必要はない。
11.3 この制限が発生する理由
Elasticsearch の内部では、範囲クエリは各条件を独立に評価する。マルチバリューフィールドの場合:
ports > 100は、いずれかの値が 100 より大きければマッチports < 200は、いずれかの値が 200 より小さければマッチANDで結合しても、同一の値が両条件を満たす必要はない
| ドキュメント | ports 値 | ports > 100 | ports < 200 | AND 結果 | 直感的な期待 |
|---|---|---|---|---|---|
| Doc A | [80, 443, 8080] | true (443, 8080) | true (80) | true | false |
| Doc B | [150] | true | true | true | true |
| Doc C | [80] | false | true | false | false |
11.4 回避策
この制限を回避する方法として、以下が挙げられる。
- Query DSL の使用:
scriptクエリを使って、同一値に対する範囲条件を記述する - データ設計の見直し: 可能であれば、マルチバリューフィールドを避ける設計にする
- ES|QL の使用: ES|QL の
MV_EXPANDコマンドでマルチバリューを展開してからフィルタする - Scripted field: Runtime field や Scripted field で事前にフィルタロジックを記述する
実務上の留意点: この制限は、ネットワークログのポート番号やタグのようなマルチバリューフィールドで範囲クエリを使う際に問題になりやすい。等値チェック (
ports: 443) では問題は発生しない。
12. KQL が使用可能な場所
12.1 Discover
Discover は KQL が最も頻繁に使用される場所である。
# Discover でのログ探索例
log.level: error and service.name: payment-api
# 特定の時間帯の特定ユーザーのアクティビティ
user.name: "admin" and event.category: authentication
# 特定の HTTP エラーのトラブルシューティング
http.response.status_code: 502 and url.path: /api/checkout
Discover での KQL 活用ポイント:
- フィルタバーに直接入力
- オートコンプリート (フィールド名・値の候補) が利用可能
- 保存済み検索 (Saved Search) として保存可能
- タイムピッカーと組み合わせて時間範囲を限定
12.2 Dashboard
ダッシュボードのフィルタバーで KQL を使用すると、すべてのパネル (ビジュアライゼーション) に対してフィルタが適用される。
# ダッシュボード全体を特定のサービスでフィルタ
service.name: checkout-service
# 特定の環境に絞り込み
service.environment: production
# 特定のリージョンのメトリクスのみ表示
cloud.region: "ap-northeast-1"
12.3 Alerting
アラートルールのフィルタ条件として KQL を使用する。
# サーバーエラーのアラート条件
http.response.status_code >= 500 and service.name: critical-api
# ディスク使用率のアラート
system.filesystem.used.pct >= 0.9 and host.name: prod-*
# 認証失敗のアラート
event.action: "authentication_failure" and source.ip: *
12.4 Security (SIEM)
Elastic Security では、検出ルールやタイムラインでの調査に KQL が使用される。
# 不審なプロセス実行の検出
process.name: powershell.exe and process.args: "-encodedcommand"
# ブルートフォース攻撃の兆候
event.action: "authentication_failure" and source.ip: *
# ラテラルムーブメントの検出
event.category: authentication and NOT source.ip: 10.0.*
# マルウェア通信の疑い (既知の C2 ポート)
destination.port: 4444 and network.direction: outbound
# 特権昇格の監視
event.action: "user_privilege_change" and user.name: *
12.5 Observability
APM、Uptime、Metrics Explorer で KQL を使用する。
# APM - 遅いトランザクションの調査
transaction.duration.us > 5000000 and service.name: web-app
# APM - 特定のエンドポイントのエラー
transaction.result: "HTTP 5xx" and url.path: /api/*
# Uptime - 特定のモニターのフィルタ
monitor.name: "Production API Health Check"
# Metrics Explorer - 特定ホストのメトリクス
host.name: prod-web-* and system.cpu.user.pct > 0.8
# Logs - 特定のコンテナのログ
container.name: payment-service and log.level: (error or warn)
12.6 KQL 対応箇所のまとめ
| Kibana 機能 | KQL 対応 | 主な用途 |
|---|---|---|
| Discover | 対応 | ログ探索、トラブルシューティング |
| Dashboard | 対応 | ダッシュボード全体のフィルタリング |
| Lens (ビジュアライゼーション) | 対応 | 個別パネルのフィルタ |
| Alerting | 対応 | アラートルールの条件定義 |
| Security - Detection Rules | 対応 | 脅威検出ルール |
| Security - Timeline | 対応 | インシデント調査 |
| Observability - APM | 対応 | トランザクション分析 |
| Observability - Uptime | 対応 | 監視対象のフィルタ |
| Observability - Metrics Explorer | 対応 | メトリクスの絞り込み |
| Maps | 対応 | 地理データのフィルタ |
| Canvas | 部分対応 | データソースのフィルタ |
| REST API (直接) | 非対応 | Query DSL または ES|QL を使用 |
13. KQL vs Lucene 比較
13.1 概要比較
Kibana のフィルタバーでは、KQL と Lucene クエリ構文のいずれかを選択できる。それぞれの特徴を比較する。
| 比較項目 | KQL | Lucene |
|---|---|---|
| 学習コスト | 低い | 中程度 |
| オートコンプリート | 完全対応 | 非対応 |
| ネストフィールド | ネイティブ対応 | 非対応 (Query DSL 必要) |
| 正規表現 | 非対応 | 対応 (/regex/) |
| ファジー検索 | 非対応 | 対応 (term~2) |
| 近接検索 | 非対応 | 対応 ("term1 term2"~5) |
| ブースティング | 非対応 | 対応 (term^2) |
| 範囲検索 | 演算子 (>, < 等) | ブラケット ([1 TO 10]) |
| フィールド存在 | field: * | _exists_: field |
| デフォルト結合 | OR (フリーテキスト) | OR |
| 構文エラーの扱い | 明確なエラーメッセージ | 暗黙的にフォールバック |
13.2 構文比較表
| 操作 | KQL | Lucene |
|---|---|---|
| フリーテキスト検索 | error | error |
| フィールド検索 | status: 200 | status:200 |
| フレーズ検索 | message: "timed out" | message:"timed out" |
| AND 条件 | a: 1 and b: 2 | a:1 AND b:2 |
| OR 条件 | a: 1 or a: 2 | a:1 OR a:2 |
| NOT 条件 | NOT status: 200 | NOT status:200 または -status:200 |
| 範囲 (数値) | bytes > 1000 | bytes:>1000 または bytes:[1000 TO *] |
| 範囲 (両端) | bytes >= 100 and bytes <= 200 | bytes:[100 TO 200] |
| ワイルドカード | message: err* | message:err* |
| フィールド存在 | field: * | _exists_:field |
| 正規表現 | 非対応 | message:/err[or]+/ |
| ファジー検索 | 非対応 | message:errro~2 |
| 近接検索 | 非対応 | message:"quick fox"~5 |
| ブースト | 非対応 | title:error^2 |
| ネストクエリ | user:{ first: "Alice" } | 非対応 |
| グルーピング | (a or b) and c | (a OR b) AND c |
13.3 KQL を選ぶべき場面
- Kibana UI で日常的なログ探索を行う場合
- オートコンプリートを活用したい場合
- ネストフィールドをクエリする必要がある場合
- チーム内にクエリ言語の経験が少ないメンバーがいる場合
- シンプルなフィルタ条件で十分な場合
13.4 Lucene を選ぶべき場面
- 正規表現を使ったパターンマッチが必要な場合
- ファジー検索 (タイポ許容検索) が必要な場合
- 近接検索 (2 つの語が一定距離内に出現する検索) が必要な場合
- 検索スコアのブースティングが必要な場合
- 既に Lucene 構文に習熟している場合
13.5 切り替え方法
Kibana のフィルタバーでは、言語の切り替えが可能である。
- フィルタバーの右端にある「KQL」ボタンをクリック
- ドロップダウンから「Lucene」を選択
- (またはその逆)
注意: KQL と Lucene ではクエリ構文が異なるため、切り替え時には既存のクエリを書き換える必要がある。
14. 実践的ユースケース
14.1 Web アプリケーションのトラブルシューティング
シナリオ: 本番環境で 502 エラーが増加している
# Step 1: 502 エラーの全体像を確認
http.response.status_code: 502
# Step 2: 特定のサービスに絞り込み
http.response.status_code: 502 and service.name: frontend-proxy
# Step 3: 特定のパスを確認
http.response.status_code: 502 and url.path: /api/v2/*
# Step 4: アップストリームの情報を確認
http.response.status_code: 502 and upstream.name: *
# Step 5: 特定のホストに集中していないか確認
http.response.status_code: 502 and host.name: prod-web-*
# Step 6: エラーメッセージの内容を確認
http.response.status_code: 502 and message: *timeout*
14.2 セキュリティインシデント調査
シナリオ: 不正アクセスの疑い
# Step 1: 認証失敗の確認
event.action: "authentication_failure" and source.ip: "203.0.113.50"
# Step 2: 同一 IP からの全アクティビティ
source.ip: "203.0.113.50"
# Step 3: 認証成功もあるか確認
event.action: "authentication_success" and source.ip: "203.0.113.50"
# Step 4: 攻撃対象のユーザーを特定
event.action: "authentication_failure" and source.ip: "203.0.113.50" and user.name: *
# Step 5: 同じ時間帯の他の不審な活動
source.ip: "203.0.113.50" and (
event.action: "authentication_failure" or
event.action: "file_access" or
event.action: "process_created"
)
# Step 6: 横展開 (ラテラルムーブメント) の確認
source.ip: 10.* and user.name: "compromised_user" and event.category: authentication
14.3 パフォーマンスモニタリング
シナリオ: レスポンスタイムの劣化調査
# Step 1: 遅いリクエストの特定 (5 秒以上)
transaction.duration.us > 5000000
# Step 2: サービス別の絞り込み
transaction.duration.us > 5000000 and service.name: checkout-api
# Step 3: エンドポイント別の絞り込み
transaction.duration.us > 5000000 and transaction.name: "POST /api/checkout"
# Step 4: 特定のユーザーに影響があるか
transaction.duration.us > 5000000 and user.id: *
# Step 5: データベースクエリが原因か
span.type: db and span.duration.us > 3000000
# Step 6: 外部サービス呼び出しが原因か
span.type: external and span.destination.service.name: payment-gateway
14.4 インフラストラクチャ監視
シナリオ: ディスク使用率の監視
# 使用率 80% 以上のホスト
system.filesystem.used.pct >= 0.8
# 特定のマウントポイント
system.filesystem.used.pct >= 0.8 and system.filesystem.mount_point: "/data"
# 本番環境のみ
system.filesystem.used.pct >= 0.8 and host.name: prod-*
# CPU 使用率とメモリ使用率の同時監視
(system.cpu.total.pct > 0.9 or system.memory.used.pct > 0.9) and host.name: prod-*
# プロセスレベルの監視
system.process.cpu.total.pct > 0.5 and process.name: java
14.5 Kubernetes 環境のログ調査
# 特定の Namespace のログ
kubernetes.namespace: production
# CrashLoopBackOff のポッドを調査
kubernetes.pod.status.phase: "Failed" or message: "CrashLoopBackOff"
# OOMKilled のイベント
message: "OOMKilled" and kubernetes.namespace: production
# 特定の Deployment のログ
kubernetes.labels.app: payment-service and log.level: error
# Init Container の失敗
kubernetes.container.name: init-* and (log.level: error or log.level: fatal)
# 特定のノードの問題
kubernetes.node.name: "node-pool-a-*" and log.level: (error or warn)
14.6 日次運用レポートのためのクエリ
# 過去 24 時間のエラー総数 (Discover のグラフで確認)
log.level: error and @timestamp >= now-24h
# 過去 24 時間のサーバーエラーレスポンス
http.response.status_code >= 500 and @timestamp >= now-24h
# 過去 24 時間のデプロイメントイベント
event.action: "deployment" and @timestamp >= now-24h
# 過去 24 時間のスケーリングイベント
event.action: "scaling" and @timestamp >= now-24h
# 過去 24 時間の設定変更
event.category: "configuration" and @timestamp >= now-24h
14.7 決済システムの監視
# 決済失敗の監視
payment.status: "failed" and payment.amount > 0
# 高額決済の監視
payment.amount >= 100000 and payment.currency: "JPY"
# 特定の決済プロバイダーのエラー
payment.provider: "stripe" and payment.status: "failed"
# 不正決済の疑い
payment.status: "succeeded" and payment.fraud_score >= 0.8
# リトライが多い決済
payment.retry_count >= 3
# 3DS 認証の失敗
payment.three_ds.status: "failed" and payment.amount > 50000
14.8 アラートルールの設計パターン
# パターン 1: エラー率ベースのアラート
http.response.status_code >= 500 and service.name: critical-api
# パターン 2: レイテンシーベースのアラート
transaction.duration.us > 10000000 and service.name: checkout-api
# パターン 3: ログレベルベースのアラート
log.level: fatal and service.environment: production
# パターン 4: セキュリティイベントベースのアラート
event.action: "authentication_failure" and event.outcome: failure
# パターン 5: リソース使用率ベースのアラート
system.filesystem.used.pct >= 0.9 and host.name: prod-*
# パターン 6: ビジネスメトリクスベースのアラート
payment.status: "failed" and payment.error_code: "insufficient_funds"
15. まとめ
15.1 KQL の位置づけと強み
KQL (Kibana Query Language) は、Kibana エコシステムにおけるフィルタリング専用のクエリ言語である。シンプルさと直感性を重視して設計されており、以下の点で他のクエリ言語と差別化されている。
| 強み | 説明 |
|---|---|
| 学習コストの低さ | 最小限の構文で基本操作が可能 |
| オートコンプリート | フィールド名・値の自動補完が利用可能 |
| ネストサポート | 波括弧構文でネストフィールドをクエリ可能 |
| 幅広い適用箇所 | Discover, Dashboard, Alerting, Security, Observability で利用可能 |
| エラーメッセージ | 構文エラー時に明確なエラーメッセージを返す |
15.2 KQL チートシート
# 基本
field: value # フィールド検索
field: "phrase value" # フレーズ検索
error # フリーテキスト検索
# 演算子
field > 100 # より大きい
field >= 100 # 以上
field < 100 # より小さい
field <= 100 # 以下
# 論理
a: 1 and b: 2 # AND
a: 1 or a: 2 # OR
NOT a: 1 # NOT
(a: 1 or a: 2) and b: 3 # グルーピング
# ワイルドカード
field: val* # 前方一致
field: *val # 後方一致
field: *val* # 部分一致
# 存在チェック
field: * # フィールドが存在する
NOT field: * # フィールドが存在しない
# ネスト
nested_field:{ a: 1 and b: 2 } # ネストクエリ
# マルチフィールド
field.*: value # 複数フィールド検索
# 日付
@timestamp >= now-1h # 相対日付
@timestamp >= "2026-01-01" # 絶対日付
# エスケープ
field: "value with \"quotes\"" # ダブルクォーテーション
field: value\:with\:colons # コロン
15.3 KQL を使いこなすためのベストプラクティス
- 具体的なフィールド名を使う: フリーテキスト検索よりフィールド指定検索の方がパフォーマンスが良い
- 括弧を積極的に使う: 複雑な条件では、意図を明確にするために括弧を使う
- 前方一致ワイルドカードを優先する:
val*は*val*より効率的 - ECS フィールド名を活用する: 標準化されたフィールド名を使うことで、クエリの再利用性が向上する
- 保存済み検索を活用する: 頻繁に使うクエリは Saved Search として保存する
- タイムピッカーを適切に設定する: KQL の日付フィルタと Kibana のタイムピッカーを適切に組み合わせる
- マルチバリューフィールドの範囲クエリに注意する: セクション 11 の制限を理解する
- 正規表現が必要な場合は Lucene に切り替える: KQL の限界を認識し、適切なツールを選択する
15.4 次のステップ
KQL を習得した後、以下の技術を学ぶことで、Elasticsearch エコシステムでのデータ分析力をさらに向上させることができる。
- ES|QL: 集計・変換を含むパイプラインクエリ
- Query DSL: プログラマブルな API ベースのクエリ
- EQL: セキュリティイベントの相関分析
- Kibana Lens: ビジュアライゼーションの作成
- Elastic Agent / Fleet: データ収集パイプラインの構築
参考資料
- Kibana Query Language (公式ドキュメント)
- Elasticsearch Query DSL (公式ドキュメント)
- Elastic Common Schema (ECS)
- Lucene Query Syntax
本記事は AI によって生成されたものです。内容の正確性については公式ドキュメントを参照して確認してください。