spl-to-apl について
SPL to APL Translatorは、Splunk SPLクエリをAxiom APLに書き換えるログ分析担当者向けのリファレンススキルです。コマンドや関数の対応、時間範囲、一般的なクエリパターンを扱います。
主な機能
- 01SPLコマンドとAPL演算子の対応表
- 02集計とフィールド変換の例
- 03明示的な時間範囲の構文説明
- 04正規表現、JSON、配列の変換一覧
- 05型変換ルールとJOINの制限
活用シーン
- 01Splunk検索をAxiomへ移行
- 02SPLのタイムチャートをAPL集計に書き換え
- 03正規表現抽出、サブクエリ、JOINの変換
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ axiomhq/ skills --skill spl-to-aplインストール後、Claude Code で/spl-to-aplを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
README.md.meta/2026-01-28-schema-read-findings.mdcases.tsDESIGN-NOTES.mdspl-to-apl.eval.tsreference/command-mapping.mddataset-schemas.mdexamples.mdfunction-mapping.mdtests/test-queries.md詳細
SPL から APL への変換
型安全性: status などのフィールドは文字列として保存されていることがよくあります。数値比較を行う前に、必ず型変換してください。toint(status) >= 500 のようにします。status >= 500 ではありません。
重要な違い
- APL では時間範囲を明示します: SPL の時間ピッカーは変換されないため、
where _time between (ago(1h) .. now())を追加してください。 - 構造: SPL の
index=... | commandは、APL の['dataset'] | operatorに相当します。 - Join はプレビュー機能です: 5 万行に制限され、inner/innerunique/leftouter のみ使用できます。
- cidrmatch の引数の順序が逆です: SPL の
cidrmatch(cidr, ip)は、APL のipv4_is_in_range(ip, cidr)に相当します。
主なコマンドの対応
| SPL | APL | 説明 |
|---|---|---|
search index=... | ['dataset'] | index の代わりにデータセットを指定します |
search field=value | where field == "value" | where を明示します |
where | where | 同じです |
stats | summarize | 集計構文が異なります |
eval | extend | フィールドを作成/変更します |
table / fields | project | 列を選択します |
fields - | project-away | 列を削除します |
rename x as y | project-rename y = x | 名前を変更します |
sort / sort - | order by ... asc/desc | 並べ替えます |
head N | take N | 行数を制限します |
top N field | summarize count() by field | top N by count_ | 2 段階で処理します |
dedup field | summarize arg_max(_time, *) by field | 最新の値を保持します |
rex | parse または extract() | 正規表現で抽出します |
join | join | プレビュー機能 |
append | union | データセットを結合します |
mvexpand | mv-expand | 配列を展開します |
timechart span=X | summarize ... by bin(_time, X) | 手動でビン分割します |
rare N field | summarize count() by field | order by count_ asc | take N | 下位 N 件を取得します |
spath | parse_json() または json['path'] | JSON にアクセスします |
transaction | 直接相当するものはありません | summarize と make_list を使用します |
完全な対応表:reference/command-mapping.md
Stats → Summarize
# SPL
| stats count by status
# APL
| summarize count() by status
主な関数の対応
| SPL | APL |
|---|---|
count | count() |
count(field) | countif(isnotnull(field)) |
dc(field) | dcount(field) |
avg/sum/min/max | 同じです |
median(field) | percentile(field, 50) |
perc95(field) | percentile(field, 95) |
first/last | arg_min/arg_max(_time, field) |
list(field) | make_list(field) |
values(field) | make_set(field) |
条件付きカウントのパターン
# SPL
| stats count(eval(status>=500)) as errors by host
# APL
| summarize errors = countif(status >= 500) by host
関数の完全な一覧:reference/function-mapping.md
Eval → Extend
# SPL
| eval new_field = old_field * 2
# APL
| extend new_field = old_field * 2
主な関数の対応
| SPL | APL | 説明 |
|---|---|---|
if(c, t, f) | iff(c, t, f) | 'f' が 2 つあります |
case(c1,v1,...) | case(c1,v1,...,default) | default が必要です |
len(str) | strlen(str) | |
lower/upper | tolower/toupper | |
substr | substring | APL では 0 から始まります |
replace | replace_string | |
tonumber | toint/tolong/toreal | 型を明示します |
match(s,r) | s matches regex "r" | 演算子です |
split(s, d) | split(s, d) | 同じです |
mvjoin(mv, d) | strcat_array(arr, d) | 配列を結合します |
mvcount(mv) | array_length(arr) | 配列の長さを取得します |
Case 文のパターン
# SPL
| eval level = case(
status >= 500, "error",
status >= 400, "warning",
1==1, "ok"
)
# APL
| extend level = case(
status >= 500, "error",
status >= 400, "warning",
"ok"
)
注:SPL の 1==1 による全件一致条件は、APL では暗黙の default になります。
Rex → Parse/Extract
# SPL
| rex field=message "user=(?<username>\w+)"
# APL - parse with regex
| parse kind=regex message with @"user=(?P<username>\w+)"
# APL - extract function
| extend username = extract("user=(\\w+)", 1, message)
シンプルなパターン(正規表現なし)
# SPL
| rex field=uri "^/api/(?<version>v\d+)/(?<endpoint>\w+)"
# APL
| parse uri with "/api/" version "/" endpoint
時間の扱い
SPL の時間ピッカーは変換されません。必ず時間範囲を明示してください。
# SPL (time picker: Last 24 hours)
index=logs
# APL
['logs'] | where _time between (ago(24h) .. now())
Timechart の変換
# SPL
| timechart span=5m count by status
# APL
| summarize count() by bin(_time, 5m), status
よく使うパターン
エラー率の計算
# SPL
| stats count(eval(status>=500)) as errors, count as total by host
| eval error_rate = errors/total*100
# APL
| summarize errors = countif(status >= 500), total = count() by host
| extend error_rate = toreal(errors) / total * 100
サブクエリ(サブサーチ)
# SPL
index=logs [search index=errors | fields user_id | format]
# APL
let error_users = ['errors'] | where _time between (ago(1h) .. now()) | distinct user_id;
['logs']
| where _time between (ago(1h) .. now())
| where user_id in (error_users)
データセットの結合
# SPL
| join user_id [search index=users | fields user_id, name]
# APL
| join kind=inner (['users'] | project user_id, name) on user_id
Transaction のようなグループ化
# SPL
| transaction session_id maxspan=30m
# APL (no direct equivalent — reconstruct with summarize)
| summarize
start_time = min(_time),
end_time = max(_time),
events = make_list(pack("time", _time, "action", action)),
duration = max(_time) - min(_time)
by session_id
| where duration <= 30m
文字列マッチングのパフォーマンス
| SPL | APL | 速度 |
|---|---|---|
field="value" | field == "value" | 最速 |
field="*value*" | field contains "value" | 中程度 |
field="value*" | field startswith "value" | 高速 |
match(field, regex) | field matches regex "..." | 最も遅い |
contains より has を優先してください(単語境界でのマッチングのほうが高速です)。大文字と小文字を区別する場合は、より高速な _cs 版を使用してください。
リファレンス
reference/command-mapping.md— コマンドの完全な一覧reference/function-mapping.md— 関数の完全な一覧reference/examples.md— クエリ変換の完全な例- APL ドキュメント:https://axiom.co/docs/apl/introduction
コメント
Markdown 対応