SPL入門: Splunk検索の基本から実践まで

Shunku

Splunkは世界で最も広く使われているログ分析プラットフォームです。その心臓部にあるのが**SPL(Search Processing Language)**です。SPLを使いこなせるかどうかで、Splunkから得られる価値は大きく変わります。

この記事では、SPLの基本から実践的なクエリまで、具体例とともに解説します。

SPLとは

SPL(Search Processing Language)は、Splunkがインデックス化したデータを検索・分析するための言語です。UnixのパイプラインとSQLの概念を組み合わせた設計になっており、直感的にデータを絞り込み、変換、集計できます。

flowchart LR
    subgraph Pipeline["SPLパイプライン"]
        A["検索"] --> B["フィルタ"]
        B --> C["変換"]
        C --> D["集計"]
        D --> E["表示"]
    end
    style Pipeline fill:#3b82f6,color:#fff

SPLの特徴は以下の通りです:

  • パイプライン処理: コマンドを | で繋いでデータを順次処理
  • 時系列最適化: タイムスタンプベースの検索が高速
  • 140以上のコマンド: 統計、変換、可視化まで幅広くカバー

基本構文

検索の基本形

SPLクエリは「検索語」から始まり、パイプ(|)でコマンドを連結します。

index=web_logs status=500 | stats count by uri | sort -count | head 10

このクエリは以下を実行します:

  1. web_logsインデックスからstatus=500のイベントを検索
  2. uriごとにカウントを集計
  3. カウントの降順でソート
  4. 上位10件を表示

検索語(Search Terms)

検索の最初の部分では、対象データを絞り込みます。

# インデックス指定
index=main

# キーワード検索
error OR failed

# フィールド値の指定
status=404
host="web-server-01"

# ワイルドカード
source="/var/log/*.log"

# 否定
NOT status=200

# 時間範囲(相対)
earliest=-24h latest=now

重要: index=*は全インデックスを検索するため非常に遅くなります。常に具体的なインデックスを指定しましょう。

時間範囲の指定

Splunkは時系列データに最適化されているため、時間範囲の指定は検索パフォーマンスに大きく影響します。

# 相対時間
earliest=-1h          # 1時間前から
earliest=-7d@d        # 7日前の0時から
earliest=@d           # 今日の0時から

# 絶対時間
earliest="2026-02-01:00:00:00"
latest="2026-02-05:23:59:59"

# スナップ演算子(@)
earliest=-1d@d        # 昨日の0時
earliest=-1w@w        # 先週の始まり

必須コマンド5選

1. stats - 統計集計

statsはSPLで最も重要なコマンドです。データをグループ化して統計を計算します。

# 基本的なカウント
index=web_logs | stats count

# フィールドでグループ化
index=web_logs | stats count by status

# 複数の統計関数
index=web_logs
| stats count, avg(response_time) as avg_time, max(response_time) as max_time by uri

# よく使う統計関数
# count    - イベント数
# sum      - 合計
# avg      - 平均
# min/max  - 最小/最大
# dc       - ユニーク数(distinct count)
# values   - ユニーク値のリスト
# latest   - 最新の値

2. eval - フィールド計算

evalは新しいフィールドを作成したり、既存フィールドを変換します。

# 新しいフィールドの作成
index=web_logs
| eval response_sec = response_time / 1000

# 条件分岐
index=web_logs
| eval status_category = case(
    status < 300, "success",
    status < 400, "redirect",
    status < 500, "client_error",
    true(), "server_error"
)

# 文字列操作
index=web_logs
| eval domain = lower(host)
| eval short_uri = substr(uri, 1, 50)

# 日時操作
index=web_logs
| eval hour = strftime(_time, "%H")
| eval day_of_week = strftime(_time, "%A")

evalの便利な関数:

関数 説明
if(条件, 真, 偽) 条件分岐 if(status=200, "OK", "Error")
case(条件1, 値1, ...) 複数条件分岐 上記参照
coalesce(a, b, ...) 最初の非null値 coalesce(user, "anonymous")
len(str) 文字列長 len(message)
replace(str, regex, new) 置換 replace(uri, "\d+", "N")
mvcount(field) 多値フィールドの要素数 mvcount(tags)

3. timechart - 時系列グラフ

timechartは時間軸でデータを集計し、グラフ表示に適した形式で出力します。

# 時間ごとのイベント数
index=web_logs | timechart count

# 1時間ごとのステータスコード別カウント
index=web_logs | timechart span=1h count by status

# 平均レスポンスタイム(5分間隔)
index=web_logs | timechart span=5m avg(response_time) as avg_response

# 複数メトリクスの同時表示
index=web_logs
| timechart span=1h count as requests, avg(response_time) as avg_time
flowchart TB
    subgraph timechart["timechartの動作"]
        A["生ログ"] --> B["時間バケットに分割"]
        B --> C["バケットごとに集計"]
        C --> D["時系列テーブル出力"]
    end
    style timechart fill:#8b5cf6,color:#fff

4. table / fields - 出力フィールドの制御

tableは指定したフィールドだけをテーブル形式で表示します。

# 特定フィールドのみ表示
index=web_logs
| table _time, host, uri, status, response_time

# fieldsで不要なフィールドを除外
index=web_logs
| fields - _raw, _cd, _indextime

# renameでフィールド名を変更
index=web_logs
| rename response_time as "Response Time (ms)", status as "HTTP Status"
| table _time, host, uri, "HTTP Status", "Response Time (ms)"

5. where / search - フィルタリング

パイプライン途中でデータをフィルタリングします。

# whereは式評価(計算フィールドにも使える)
index=web_logs
| eval response_sec = response_time / 1000
| where response_sec > 5

# searchはキーワード検索
index=web_logs
| stats count by uri, status
| search status=500

# whereの比較演算子
| where response_time > 1000
| where status >= 400 AND status < 500
| where like(uri, "/api/%")
| where match(user_agent, "(?i)bot")

実践例

例1: エラー分析ダッシュボード

Webサーバーのエラーを分析するクエリセット。

# HTTPステータスコードの分布
index=web_logs earliest=-24h
| eval status_group = case(
    status < 300, "2xx Success",
    status < 400, "3xx Redirect",
    status < 500, "4xx Client Error",
    true(), "5xx Server Error"
)
| stats count by status_group
| sort status_group
# エラーが多いエンドポイントTop10
index=web_logs status>=400 earliest=-24h
| stats count as errors by uri
| sort -errors
| head 10
# 時間帯別エラー率
index=web_logs earliest=-24h
| timechart span=1h
    count(eval(status>=400)) as errors,
    count as total
| eval error_rate = round(errors / total * 100, 2)
| fields _time, errors, total, error_rate

例2: パフォーマンス分析

レスポンスタイムの分析。

# パーセンタイル分析
index=web_logs earliest=-1h
| stats
    avg(response_time) as avg,
    median(response_time) as p50,
    perc95(response_time) as p95,
    perc99(response_time) as p99,
    max(response_time) as max
| eval avg = round(avg, 2)
# 遅いリクエストの特定
index=web_logs earliest=-1h
| where response_time > 3000
| table _time, host, uri, response_time, status
| sort -response_time

例3: ユーザー行動分析

# アクティブユーザー数(日次)
index=web_logs earliest=-7d
| timechart span=1d dc(user_id) as unique_users

# ユーザーごとのセッション分析
index=web_logs user_id=* earliest=-24h
| stats
    count as page_views,
    dc(uri) as unique_pages,
    min(_time) as first_access,
    max(_time) as last_access
    by user_id
| eval session_duration = last_access - first_access
| eval session_minutes = round(session_duration / 60, 1)
| table user_id, page_views, unique_pages, session_minutes
| sort -page_views

パフォーマンスのベストプラクティス

SPLクエリを最適化するための重要なポイントです。

1. 時間範囲を絞る

# 悪い例: 全期間検索
index=web_logs status=500

# 良い例: 時間範囲を指定
index=web_logs status=500 earliest=-24h latest=now

2. できるだけ早くフィルタリング

# 悪い例: 集計後にフィルタ
index=web_logs | stats count by status | search status=500

# 良い例: 検索時にフィルタ
index=web_logs status=500 | stats count

3. fieldsで不要なフィールドを除外

# 大量のフィールドを持つログの場合
index=web_logs earliest=-1h
| fields _time, host, uri, status, response_time
| stats avg(response_time) by host

4. statsはtransactionより高速

# 遅い: transaction
index=web_logs | transaction session_id | stats count

# 速い: stats
index=web_logs | stats count, values(uri) as pages by session_id | stats count

まとめ

コマンド 用途
stats 統計集計 stats count, avg(field) by group
eval フィールド計算 eval new_field = field1 + field2
timechart 時系列集計 timechart span=1h count by status
table フィールド選択 table _time, host, status
where 条件フィルタ where response_time > 1000
sort ソート sort -count (降順)
head/tail 件数制限 head 10
rename フィールド名変更 rename field as "新しい名前"
dedup 重複除去 dedup host, uri

SPLは奥が深く、140以上のコマンドがありますが、この記事で紹介した5つのコマンド(stats, eval, timechart, table, where)を使いこなせれば、ほとんどのユースケースに対応できます。

参考リンク