关于 spl-to-apl
SPL to APL Translator 是帮助日志分析人员将 Splunk SPL 查询改写为 Axiom APL 的参考技能,涵盖命令、函数、时间筛选及常见查询模式。
主要功能
- 01映射 SPL 命令与 APL 运算符
- 02提供统计与字段转换示例
- 03说明时间范围的显式写法
- 04列出正则、JSON 与数组转换方式
- 05提示类型转换和 JOIN 限制
适用场景
- 01迁移 Splunk 搜索到 Axiom
- 02将 SPL 时间图表改写为 APL 汇总
- 03转换正则提取、子查询或关联查询
安装
复制下面的命令,在终端中运行。
$
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 为预览功能: 限制为 50k 行,仅支持 inner/innerunique/leftouter
- cidrmatch 参数顺序相反: SPL
cidrmatch(cidr, ip)→ APLipv4_is_in_range(ip, cidr)
核心命令映射
| SPL | APL | 说明 |
|---|---|---|
search index=... | ['dataset'] | 数据集替代索引 |
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_ | 两步操作 |
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' |
case(c1,v1,...) | case(c1,v1,...,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 中会变为隐式默认值。
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)
Join 数据集
# 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 "..." | 最慢 |
优先使用 has 而非 contains(单词边界匹配速度更快)。区分大小写时使用 _cs 变体(速度更快)。
参考
reference/command-mapping.md— 完整命令列表reference/function-mapping.md— 完整函数列表reference/examples.md— 完整查询转换示例- APL 文档:https://axiom.co/docs/apl/introduction
评论
支持 Markdown