【実務で即使える】Splunk SPL文法完全ガイド - コード詳細解説版
1. 基本構文:indexからのデータ取得
# ===== 基本的なindex検索 =====
index=web_logs # web_logsというインデックスからデータを取得
sourcetype=access_combined # アクセスログの形式で絞り込み
| head 100 # 結果を100件に制限(パイプで処理を連結)
うさうさポイント🐰: |(パイプ)は料理の工程みたいなもの。材料(データ)→切る→煮る→盛り付けの順番!
2. 時間範囲の指定
# ===== 相対時間での検索 =====
index=main # mainインデックスを対象
earliest=-24h # 24時間前から
latest=now # 現在時刻まで
# ===== 絶対時間での検索 =====
index=main # mainインデックスを対象
earliest="01/15/2026:00:00:00" # 2026年1月15日0時から
latest="01/15/2026:23:59:59" # 2026年1月15日23時59分59秒まで
# ===== 時刻の切り捨て(@記号) =====
earliest=-1d@d # 昨日の0時0分0秒から(@dで日の開始時刻に切り捨て)
latest=@d # 今日の0時0分0秒まで(つまり昨日1日分)
earliest=-7d@d # 7日前の0時0分0秒から
latest=@d # 今日の0時0分0秒まで(過去7日間)
earliest=-1h@h # 1時間前の0分0秒から(@hで時の開始時刻に切り捨て)
latest=now # 現在時刻まで
3. フィールド検索とフィルタリング
# ===== 完全一致検索 =====
index=app_logs # app_logsインデックスから
status=200 # statusフィールドが200のものだけ
index=app_logs # app_logsインデックスから
user="yukiko.ishiguro@example.com" # userフィールドが完全一致
# ===== 部分一致検索(ワイルドカード) =====
index=app_logs # app_logsインデックスから
error=*timeout* # errorフィールドに"timeout"を含む(前後に何でもOK)
index=app_logs # app_logsインデックスから
url="*/api/*" # urlフィールドに"/api/"を含む
# ===== AND条件(スペース区切り) =====
index=main # mainインデックスから
status=500 # statusが500で
method=POST # かつmethodがPOST
# ===== OR条件(括弧で囲む) =====
index=main # mainインデックスから
(status=500 OR status=502 OR status=503) # statusが500か502か503のいずれか
# ===== NOT条件(除外) =====
index=main # mainインデックスから
status=200 # statusが200で
NOT user=admin # userがadminでないもの
4. 統計コマンド(Stats Commands)
# ===== 基本的な集計 =====
index=web_logs # web_logsインデックスから
| stats # 統計処理を開始
count # 件数をカウント
by status # statusフィールドごとにグループ化
# ===== 複数の統計関数を組み合わせ =====
index=web_logs # web_logsインデックスから
| stats # 統計処理を開始
count as total_requests, # 件数を total_requests という名前で集計
avg(response_time) as avg_time, # response_timeの平均を avg_time という名前で計算
max(response_time) as max_time, # response_timeの最大値を max_time として取得
min(response_time) as min_time, # response_timeの最小値を min_time として取得
sum(bytes) as total_bytes # bytesの合計を total_bytes として計算
by host # hostごとにグループ化
# ===== 時系列グラフ用の集計 =====
index=web_logs # web_logsインデックスから
| timechart # 時系列チャート用の統計処理
span=1h # 1時間ごとに集計(spanで時間間隔を指定)
count # 件数をカウント
by status # statusごとに分類
うさうさポイント🐰: statsは「集計レジ」、timechartは「売上グラフを時間軸で作る機械」だと思ってね!
5. データ変換と加工
# ===== evalでフィールド計算 =====
index=app_logs # app_logsインデックスから
| eval # フィールド計算を開始
response_time_ms=response_time*1000 # response_timeを1000倍してミリ秒に変換
| eval # 続けて別の計算(複数のevalを連結可能)
status_category=case( # case文で条件分岐
status>=200 AND status<300, # 200番台なら
"Success", # "Success"を設定
status>=400 AND status<500, # 400番台なら
"Client Error", # "Client Error"を設定
status>=500, # 500番台以上なら
"Server Error", # "Server Error"を設定
1=1, # それ以外(常に真)なら
"Other" # "Other"を設定
)
# ===== rexで正規表現抽出 =====
index=web_logs # web_logsインデックスから
| rex # 正規表現抽出を開始
field=url # urlフィールドから抽出
"\/api\/(?<api_version>v\d+)\/(?<endpoint>\w+)"
# /api/v1/users のような形式から
# (?<api_version>v\d+) → "v1"を api_version フィールドに抽出
# (?<endpoint>\w+) → "users"を endpoint フィールドに抽出
# ===== whereで条件フィルタ =====
index=app_logs # app_logsインデックスから
| stats # まず統計処理
avg(response_time) as avg_time # 平均応答時間を計算
by endpoint # エンドポイントごと
| where avg_time > 1.0 # 平均応答時間が1.0秒を超えるものだけ残す
6. テーブル整形とソート
# ===== 表示フィールドの選択 =====
index=web_logs # web_logsインデックスから
| table # テーブル形式で表示
_time, # タイムスタンプ
host, # ホスト名
status, # ステータスコード
url, # URL
response_time # 応答時間
# ===== ソート(並び替え) =====
index=app_logs # app_logsインデックスから
| stats count by user # ユーザーごとに件数を集計
| sort -count # 件数で降順ソート(-は降順、なしは昇順)
| head 10 # 上位10件のみ表示
# ===== フィールド名の変更 =====
index=web_logs # web_logsインデックスから
| stats # 統計処理
count as リクエスト数, # count を「リクエスト数」に改名
avg(response_time) as 平均応答時間 # avg(response_time)を「平均応答時間」に改名
7. 実務パターン集
パターン1: エラー率の監視
index=app_logs # app_logsインデックスから
| stats # 統計処理を開始
count as total, # 全件数をtotalとして集計
count(eval(status>=500)) as errors # status>=500の件数をerrorsとして集計
# eval()内の条件に一致するものだけカウント
| eval # 計算処理
error_rate=round(errors/total*100, 2) # エラー率を計算(百分率、小数点2桁)
# round()で四捨五入
パターン2: トップN抽出
index=web_logs # web_logsインデックスから
| stats count by url # URLごとにアクセス数を集計
| sort -count # 件数で降順ソート(多い順)
| head 20 # 上位20件のみ取得
| rename # フィールド名を変更
url as "アクセスURL", # urlを「アクセスURL」に
count as "アクセス数" # countを「アクセス数」に
パターン3: 時間帯別の傾向分析
index=app_logs # app_logsインデックスから
| eval # フィールド計算
hour=strftime(_time, "%H") # タイムスタンプから時(00-23)を抽出
# strftime()で時刻をフォーマット変換
| stats # 統計処理
avg(response_time) as avg_response, # 平均応答時間を計算
count as requests # リクエスト数を集計
by hour # 時間帯(hour)ごとにグループ化
| sort hour # 時間順にソート(0時から23時まで)
パターン4: 異常検知(閾値超え)
index=system_logs # system_logsインデックスから
| stats # 統計処理
avg(cpu_usage) as avg_cpu # CPU使用率の平均を計算
by host # ホストごと
| where avg_cpu > 80 # 平均CPU使用率が80%を超えるものだけ
| eval # アラートレベルを計算
alert_level=case( # 条件分岐で判定
avg_cpu>90, # 90%超なら
"Critical", # 「Critical - 即対応」
avg_cpu>80, # 80%超なら(既に90%超は除外済み)
"Warning" # 「Warning - 要注意」
)
パターン5: セキュリティイベントの検知
index=security_logs # security_logsインデックスから
earliest=-5m # 直近5分間のデータ
| search # 追加の検索条件
(action=login AND result=failed) # ログイン失敗、または
OR # あるいは
(action=unauthorized_access) # 不正アクセス
| stats # 統計処理
count as event_count, # イベント数を集計
values(user) as users, # 関与したユーザーのリスト(重複なし)
values(src_ip) as source_ips # 送信元IPのリスト(重複なし)
by action # アクションタイプごと
| where event_count > 5 # 5回以上発生したもののみ
8. パフォーマンス最適化
# ===== Good Practice(推奨) =====
index=main # インデックスを明示
sourcetype=access # ソースタイプも指定
earliest=-1h # 時間範囲を限定(1時間)
| search status=500 # 早い段階でフィルタリング
| stats count by host # 必要な統計のみ
# ===== フィールドを明示的に選択 =====
index=main # インデックスを指定
| fields # フィールドを選択
_time, # タイムスタンプ
host, # ホスト
status, # ステータス
response_time # 応答時間(これら4つのみ処理対象)
| stats # 統計処理
avg(response_time) # 平均応答時間を計算
by host # ホストごと
# ===== Bad Practice(非推奨) =====
index=main # 全データ取得(時間範囲なし→遅い)
| stats # すべてのフィールドで統計
count # 集計してから
by sourcetype, status, host # 複数軸でグループ化(重い)
| search status=500 # 最後にフィルタ(遅い!早めにやるべき)
最適化の鉄則🐰:
- 🥕 材料(データ)は最初に選ぶ(index, 時間範囲)
- 🥕 不要な野菜(フィールド)は早めに捨てる
- 🥕 大きな鍋(統計処理)の前に下ごしらえ(フィルタ)
【Splunk】ダッシュボード構築の実践的テクニック
1. 基本的なダッシュボードXML
<dashboard>
<!-- ダッシュボード全体の設定 -->
<label>リアルタイム監視ダッシュボード</label>
<!-- ダッシュボードのタイトル -->
<description>システム全体のステータスを監視</description>
<!-- ダッシュボードの説明文 -->
<!-- 行(横方向のレイアウト) -->
<row>
<!-- パネル1: エラー数の推移 -->
<panel>
<title>エラー数推移(1時間)</title>
<!-- パネルのタイトル -->
<chart>
<!-- グラフタイプのビジュアライゼーション -->
<search>
<!-- 検索クエリ -->
<query>
<!-- SPL検索文 -->
index=app_logs <!-- app_logsから -->
level=ERROR <!-- エラーレベルのみ -->
earliest=-1h <!-- 1時間前から -->
| timechart <!-- 時系列グラフ用集計 -->
span=5m <!-- 5分間隔 -->
count <!-- 件数をカウント -->
by host <!-- ホストごとに分類 -->
</query>
<earliest>-1h</earliest>
<!-- 検索の開始時刻(1時間前) -->
<latest>now</latest>
<!-- 検索の終了時刻(現在) -->
</search>
<!-- グラフの表示オプション -->
<option name="charting.chart">line</option>
<!-- グラフタイプ: 折れ線グラフ -->
<option name="charting.axisY.minimumNumber">0</option>
<!-- Y軸の最小値を0に設定 -->
<option name="charting.legend.placement">bottom</option>
<!-- 凡例を下部に配置 -->
</chart>
</panel>
</row>
</dashboard>
2. KPIダッシュボード
<row>
<!-- シングルバリュー(単一値)表示 -->
<panel>
<title>総リクエスト数</title>
<single>
<!-- シングルバリュータイプ -->
<search>
<query>
index=web_logs <!-- web_logsから -->
earliest=-24h <!-- 24時間分 -->
| stats count <!-- 件数を集計 -->
| eval count=tostring(count, "commas")
<!-- 数値をカンマ区切りの文字列に変換(例: 1234567 → 1,234,567) -->
</query>
</search>
<option name="numberPrecision">0</option>
<!-- 小数点以下の桁数: 0桁(整数表示) -->
<option name="underLabel">過去24時間</option>
<!-- 数値の下に表示するラベル -->
<option name="rangeColors">["0x65A637","0x6DB7C6","0xF7BC38","0xF58F39","0xD93F3C"]</option>
<!-- レンジごとの色設定(緑→青→黄→橙→赤) -->
</single>
</panel>
<!-- エラー率のKPI -->
<panel>
<title>エラー率</title>
<single>
<search>
<query>
index=app_logs <!-- app_logsから -->
earliest=-1h <!-- 1時間分 -->
| stats <!-- 統計処理 -->
count as total, <!-- 総数 -->
count(eval(status>=500)) as errors
<!-- status>=500の件数(サーバーエラー) -->
| eval error_rate=round((errors/total)*100, 2)
<!-- エラー率を計算: (エラー数/総数)×100、小数点2桁 -->
| fields error_rate <!-- error_rateフィールドのみ表示 -->
</query>
</search>
<option name="unit">%</option>
<!-- 単位を%で表示 -->
<option name="rangeValues">[0,1,5]</option>
<!-- 閾値: 0-1%(緑)、1-5%(黄)、5%以上(赤) -->
<option name="rangeColors">["0x65A637","0xF7BC38","0xD93F3C"]</option>
<!-- 緑、黄、赤の色設定 -->
</single>
</panel>
</row>
3. インタラクティブ機能(ドリルダウン)
<panel>
<title>ホスト別エラー数(クリックで詳細表示)</title>
<table>
<search>
<query>
index=app_logs <!-- app_logsから -->
level=ERROR <!-- エラーのみ -->
earliest=-1h <!-- 1時間分 -->
| stats count by host <!-- ホストごとに集計 -->
| sort -count <!-- 降順ソート -->
</query>
</search>
<!-- ドリルダウン設定 -->
<drilldown>
<!-- 行クリック時の動作 -->
<link target="_blank">
<!-- 新しいタブで開く -->
/app/search/search?q=
search index=app_logs level=ERROR host=$click.value$
<!-- クリックした行のhost値を $click.value$ で取得 -->
&earliest=-1h
<!-- &はXMLなので & とエスケープ -->
</link>
</drilldown>
</table>
</panel>
4. 動的フィルター(インプット)
<fieldset submitButton="true">
<!-- 検索ボタン付きのフィールドセット -->
<!-- 時間範囲ピッカー -->
<input type="time" token="time_range">
<!-- トークン名: time_range(他のパネルで使用可能) -->
<label>時間範囲</label>
<default>
<earliest>-24h</earliest>
<!-- デフォルト: 24時間前から -->
<latest>now</latest>
<!-- デフォルト: 現在まで -->
</default>
</input>
<!-- ドロップダウン選択 -->
<input type="dropdown" token="selected_host">
<!-- トークン名: selected_host -->
<label>ホスト選択</label>
<choice value="*">すべて</choice>
<!-- *はワイルドカード(全て選択) -->
<choice value="web01">web01</choice>
<choice value="web02">web02</choice>
<choice value="db01">db01</choice>
<default>*</default>
<!-- デフォルト値: すべて -->
</input>
<!-- テキスト入力 -->
<input type="text" token="search_keyword">
<label>検索キーワード</label>
<default>*</default>
<!-- デフォルト: ワイルドカード(全て) -->
</input>
</fieldset>
<!-- トークンを使用したパネル -->
<row>
<panel>
<title>フィルタ結果</title>
<table>
<search>
<query>
index=app_logs <!-- app_logsから -->
host=$selected_host$ <!-- トークンを$で囲んで使用 -->
$search_keyword$ <!-- キーワードで絞り込み -->
| stats count by level <!-- レベルごとに集計 -->
</query>
<earliest>$time_range.earliest$</earliest>
<!-- 時間範囲トークンの開始時刻 -->
<latest>$time_range.latest$</latest>
<!-- 時間範囲トークンの終了時刻 -->
</search>
</table>
</panel>
</row>
5. リアルタイムダッシュボード
<panel>
<title>リアルタイムエラー監視</title>
<chart>
<search>
<query>
index=app_logs <!-- app_logsから -->
level=ERROR <!-- エラーのみ -->
| timechart <!-- 時系列グラフ -->
span=10s <!-- 10秒間隔(リアルタイム用) -->
count <!-- 件数をカウント -->
</query>
<earliest>rt-5m</earliest>
<!-- リアルタイム検索: 5分前から(rtはreal-time) -->
<latest>rt</latest>
<!-- リアルタイム検索: 現在まで -->
<refresh>10s</refresh>
<!-- 10秒ごとに自動更新 -->
</search>
<option name="charting.chart">area</option>
<!-- エリアチャート(面グラフ) -->
<option name="refresh.display">progressbar</option>
<!-- 更新時にプログレスバーを表示 -->
</chart>
</panel>
6. カスタムCSS(見た目のカスタマイズ)
<dashboard stylesheet="custom_dashboard.css">
<!-- カスタムCSSファイルを読み込み -->
<label>カスタムデザインダッシュボード</label>
<row>
<panel id="critical_panel">
<!-- IDを付けてCSS適用可能にする -->
<title>Critical Alerts</title>
<single>
<search>
<query>
index=app_logs <!-- app_logsから -->
level=CRITICAL <!-- クリティカルレベル -->
earliest=-5m <!-- 5分以内 -->
| stats count <!-- 件数を集計 -->
</query>
</search>
</single>
</panel>
</row>
</dashboard>
custom_dashboard.css:
/* Critical パネルの背景色を赤に */
#critical_panel {
background-color: #ffebee; /* 薄い赤 */
border-left: 5px solid #d32f2f; /* 左に赤いボーダー */
}
/* パネルタイトルのスタイル */
.dashboard-panel > .dashboard-element > .panel-head {
background-color: #1976d2; /* 青色の背景 */
color: white; /* 白文字 */
font-weight: bold; /* 太字 */
padding: 10px; /* 内側の余白 */
}
/* シングルバリューの数値サイズ */
.single-value {
font-size: 48px !important; /* 数値を大きく */
font-weight: bold; /* 太字 */
}
【運用自動化】Splunkで実現する24時間監視体制
1. 基本的なアラート検索
# ===== エラー急増検知アラート =====
index=app_logs # app_logsインデックスから
level=ERROR # エラーレベルのみ
earliest=-5m # 直近5分間のデータ
| stats # 統計処理開始
count as error_count # エラー数をerror_countとして集計
by host # ホストごとにグループ化
| where error_count > 50 # 50件を超えるものだけ抽出
| eval # 重要度判定を計算
severity=case( # case文で条件分岐
error_count>100, # 100件超なら
"Critical", # "Critical"(緊急)
error_count>50, # 50件超なら
"Warning" # "Warning"(警告)
)
アラート設定(UI上):
- Schedule: Every 5 minutes(5分ごと実行)
- Time Range: -5m(直近5分)
- Trigger when: Number of Results > 0(結果が1件以上あれば発火)
2. 複雑な条件のアラート
# ===== 応答時間劣化検知 =====
index=web_logs # web_logsインデックスから
earliest=-10m # 直近10分間
| stats # 統計処理
avg(response_time) as avg_time, # 平均応答時間を計算
max(response_time) as max_time, # 最大応答時間を取得
count # リクエスト数も取得
by host # ホストごと
| where # 条件フィルタ
avg_time > 2.0 # 平均が2秒超、または
OR max_time > 5.0 # 最大が5秒超
| eval # アラート内容を生成
alert_message="Host: " . host .
", Avg: " . round(avg_time, 2) . "s" .
", Max: " . round(max_time, 2) . "s"
# 文字列を . で連結してメッセージ作成
# round()で小数点2桁に丸める
3. ログ出力停止検知
# ===== ログ出力停止の検知(ハートビート監視) =====
index=app_logs # app_logsインデックスから
earliest=-15m # 直近15分間
| stats count by host # ホストごとのログ件数を集計
| append # 結果に追加データを結合
[| inputlookup expected_hosts.csv]
# expected_hosts.csvから期待されるホストリストを読み込み
# サブサーチ([]で囲まれた部分)の結果を追加
| stats # 再度統計処理
sum(count) as log_count # ログ件数の合計
by host # ホストごと
| where # 条件チェック
log_count=0 # ログが0件、または
OR isnull(log_count) # ログ件数がnull(データなし)
| eval # アラートメッセージ作成
alert_type="No logs detected", # アラートタイプ
severity="High" # 重要度は高
expected_hosts.csv の中身:
host
web01
web02
db01
app01
4. セキュリティアラート
# ===== ログイン失敗の異常検知 =====
index=security_logs # security_logsから
earliest=-5m # 直近5分間
| search # 追加検索条件
(action=login AND result=failed) # ログイン失敗、または
OR # あるいは
(action=unauthorized_access) # 不正アクセス試行
| stats # 統計処理
count as event_count, # イベント数を集計
values(user) as users, # 関与したユーザー名(重複排除)
# values()はユニークな値のリストを返す
values(src_ip) as source_ips # 送信元IPアドレス(重複排除)
by action # アクションタイプごと
| where event_count > 5 # 5回以上発生したもののみ
| eval # 詳細メッセージ作成
alert_details="Action: " . action .
", Count: " . event_count .
", Users: " . users .
", IPs: " . source_ips
5. Webhook連携(Slack通知)
{
"text": "🚨 High Error Rate Alert",
"attachments": [
{
"color": "danger",
"fields": [
{
"title": "Host",
"value": "$result.host$",
"short": true
},
{
"title": "Error Count",
"value": "$result.error_count$",
"short": true
},
{
"title": "Severity",
"value": "$result.severity$",
"short": true
},
{
"title": "Detection Time",
"value": "$trigger_time$",
"short": true
},
{
"title": "Search Link",
"value": "<$results_link$|View Details>",
"short": false
}
],
"footer": "Splunk Alert System",
"ts": "$trigger_time_epoch$"
}
]
}
トークンの説明:
-
$result.host$→ 検索結果のhostフィールド値 -
$result.error_count$→ 検索結果のerror_countフィールド値 -
$trigger_time$→ アラート発火時刻 -
$results_link$→ Splunk検索結果へのリンク -
$trigger_time_epoch$→ Unix エポック時間
6. 自動復旧スクリプト
#!/bin/bash
# ===== auto_restart.sh =====
# Splunkアラートから呼び出される自動復旧スクリプト
# コマンドライン引数を変数に格納
HOST=$1 # 第1引数: ホスト名
SERVICE=$2 # 第2引数: サービス名
# ログファイルのパス
LOG_FILE="/var/log/splunk_auto_recovery.log"
# 現在時刻を取得
TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')
# ログに記録
echo "[$TIMESTAMP] Starting auto recovery for $SERVICE on $HOST" >> $LOG_FILE
# SSH経由でサービス再起動を実行
# -o StrictHostKeyChecking=no: ホストキーチェックをスキップ(自動化用)
ssh -o StrictHostKeyChecking=no $HOST "sudo systemctl restart $SERVICE"
# 再起動コマンドの終了ステータスをチェック
if [ $? -eq 0 ]; then
# 成功時(終了コード0)
echo "[$TIMESTAMP] Successfully restarted $SERVICE on $HOST" >> $LOG_FILE
# 成功通知メールを送信
echo "Service $SERVICE has been automatically restarted on $HOST at $TIMESTAMP" | \
mail -s "Auto Recovery Success: $SERVICE on $HOST" ops@example.com
else
# 失敗時(終了コード0以外)
echo "[$TIMESTAMP] Failed to restart $SERVICE on $HOST" >> $LOG_FILE
# 失敗通知メールを送信
echo "Failed to restart $SERVICE on $HOST at $TIMESTAMP. Manual intervention required." | \
mail -s "Auto Recovery FAILED: $SERVICE on $HOST" ops@example.com
fi
# 再起動後のステータス確認(5秒待機)
sleep 5
# サービスの状態を確認
STATUS=$(ssh $HOST "systemctl is-active $SERVICE")
echo "[$TIMESTAMP] Service status: $STATUS" >> $LOG_FILE
Splunkアラートアクション設定:
Script filename: auto_restart.sh
Script arguments: "$result.host$" "$result.service$"
7. メール通知テンプレート
Subject: [Splunk Alert] $name$ - $result.severity$
本文:
================================================================
Splunk自動監視システムからのアラート通知
================================================================
【アラート名】
$name$
【重要度】
$result.severity$
【検出時刻】
$trigger_time$
【検出内容】
ホスト: $result.host$
エラー数: $result.error_count$
エラーメッセージ: $result.error_message$
【詳細情報】
直近5分間で異常なエラー増加を検知しました。
通常時の平均: 10件/5分
現在の検出数: $result.error_count$件/5分
【対応手順】
1. 以下のリンクから詳細ログを確認
$results_link$
2. エラーの原因を特定
3. 必要に応じてサービス再起動
ssh $result.host$ "sudo systemctl restart app-service"
4. 復旧後、Slackの #ops-alerts チャンネルで報告
【エスカレーション】
30分以内に復旧しない場合:
- オンコールエンジニアに連絡: +81-90-XXXX-XXXX
- マネージャーに報告: manager@example.com
================================================================
Splunk Alert System - Powered by DX Team
================================================================
8. アラート抑制(Throttle)設定
# ===== 基本検索(アラート抑制前) =====
index=app_logs # app_logsから
level=ERROR # エラーのみ
earliest=-5m # 直近5分
| stats # 統計処理
count by host, error_type # ホストとエラータイプごと
| where count > 10 # 10件超のみ
Throttle設定(UI上):
Suppress triggering for: 1 hour
# 同じ条件で1時間以内に再発火しない
Suppress results containing field: host
# hostフィールドが同じ結果は抑制
# つまり、同じホストからのアラートは1時間に1回のみ
効果:
09:00 - web01でアラート発火 → 通知送信 ✅
09:15 - web01でアラート発火 → 抑制(通知なし) 🔇
09:30 - web01でアラート発火 → 抑制(通知なし) 🔇
09:45 - web02でアラート発火 → 通知送信 ✅(別ホストなのでOK)
10:01 - web01でアラート発火 → 通知送信 ✅(1時間経過したのでOK)
9. 複数条件の組み合わせアラート
# ===== 複合条件での異常検知 =====
index=app_logs # app_logsから
earliest=-5m # 直近5分
| stats # 統計処理
avg(response_time) as avg_time, # 平均応答時間
count(eval(status=500)) as error_count,
# status=500の件数(サーバーエラー)
count as total # 総リクエスト数
by host # ホストごと
| eval # アラート条件の評価
alert=case( # case文で複数条件判定
avg_time>2.0 AND error_count>10,
# 応答時間が遅い かつ エラーが多い
"Critical", # → Critical(最重要)
avg_time>1.5 OR error_count>5,
# 応答時間がやや遅い または エラーがやや多い
"Warning", # → Warning(警告)
1=1, # それ以外(常に真)
"Normal" # → Normal(正常)
)
| where # フィルタリング
alert IN ("Critical", "Warning")
# CriticalまたはWarningのみ抽出(Normalは除外)
| eval # 詳細メッセージ作成
details="Host: " . host .
" | Avg Time: " . round(avg_time, 2) . "s" .
" | Errors: " . error_count . "/" . total
10. 機械学習による異常検知
# ===== 過去の傾向から異常を検知 =====
index=app_logs # app_logsから
earliest=-7d # 過去7日分のデータ
| timechart # 時系列データ作成
span=1h # 1時間ごと
count # リクエスト数を集計
| predict # 予測アルゴリズム適用
count # countフィールドを予測
as predicted_count # 予測値をpredicted_countとして保存
algorithm=LLP # LLP(Local Linear Prediction)アルゴリズム使用
future_timespan=0 # 未来予測はしない(現在の異常検知のみ)
| eval # 偏差を計算
deviation=abs(count-predicted_count)
# 実測値と予測値の差の絶対値
| where # 異常判定
deviation > predicted_count*0.3
# 予測値の30%以上乖離していたら異常
| eval # アラートレベル判定
alert_level=case(
deviation > predicted_count*0.5,
# 50%以上の乖離
"Critical - 即対応",
deviation > predicted_count*0.3,
# 30-50%の乖離
"Warning - 要監視",
1=1, "Info" # それ以外
)
うさうさポイント🐰:
機械学習は「いつものパターン」を学習して、「いつもと違う」を見つける賢い子!
- 📊 過去7日間のデータで「普通の状態」を学習
- 🔍 今のデータが「普通」から30%以上離れてたらアラート
- 🎯 曜日や時間帯の変動も考慮してくれる