用 SPL 查询、租户与登录、上传 CSV、图表与仪表盘

Osmanthe 开发预览版 · 2026-10-11 · 返回文档目录

1. 直接用 Splunk SPL 搜索

不用学新语言。搜索页查询框左边有 SPL / LogsQL 切换,默认就是 SPL。像在 Splunk 里一样写,例如:

index=demo level=error | stats count by service | sort -count

网关会把 SPL 翻译成底层引擎(VictoriaLogs)的 LogsQL 再执行。每次搜索下方都可以展开「对应的 LogsQL」,看到实际执行的查询;结果和你在 Splunk 里预期的一样,翻译不了的写法会直接报错并说明原因,不会悄悄返回不同的结果。

点搜索框旁的「语法」,有十几个常用例子,点一下就能直接搜。

先试这几个(用 demo 租户的账号登录,时间选“最近 7 天”)

index、sourcetype 是怎么来的

2. 支持哪些命令和函数

下表每一行的例子都在演示数据上实际跑过。

命令例子说明
搜索条件index=demo timeout NOT level=info关键词、短语、field=value、!=、> >= < <=、通配符 *、AND / OR / NOT、括号、IN (...)
earliest / latestearliest=-1d@d latest=@d和页面上选的时间范围取交集;支持 -15m、-1h、-7d,以及 @d、@h、@w1、@mon、@q、@y 取整(按手机时区)
where| where duration_ms>1000 AND like(http.path, "/api/cart%")比较、AND/OR/NOT,函数 isnull、isnotnull、like、match、searchmatch、cidrmatch
stats| stats count, avg(duration_ms) as avg, max(duration_ms) as max by service见下面的统计函数
eventstats| eventstats avg(duration_ms) as svc_avg by service统计结果加到每一行,原始事件保留
streamstats / accum| streamstats count as n by host累计统计,按当前顺序算(原始事件默认从新到旧,和 Splunk 一致);不支持 window=
metadata / eventcount| metadata type=hosts index=demo写在最前面;metadata 支持 hosts、sources、sourcetypes
tstats| tstats count where index=* by host写在最前面;where 后面是普通搜索条件,by 支持 _time span=1h;不支持 from datamodel=
timechart| timechart span=1h count by service不写 span 会按时间范围自动选;by 的系列默认只保留总和最大的 10 个,其余合成 OTHER(limit=0 不限,useother=f 直接去掉;OTHER 只支持 count、sum、avg、min、max,dc 等函数要加 useother=f 或 limit=0)
chart| chart count over service by level交叉表,可画堆叠柱状图;by 的系列同样默认保留 10 个;span=10 可把 over 的数字字段分成区间
top / rare| top limit=5 error.type也支持 countfield=
sort| sort -count- 降序,+ 升序,多个字段
head / tail| head 20
table / fields| table _time, service, _rawfields - x 去掉字段
rename| rename service as svc
dedup| dedup error.type每个值保留最新一条
eval| eval lvl=case(http.status_code>=500, "5xx", http.status_code>=400, "4xx", true(), "ok")if、case(含 true() 兜底)、coalesce、len、lower、upper、round、abs、floor、ceil、tostring、tonumber、replace、substr、trim、split、now、四则运算、字符串拼接 .(同一个表达式里不能既算数又拼接,分两次 eval)
rex| rex "user=(?<uid>\w+)"支持 field=;mode=sed 支持 "s/正则/替换/g"
regex| regex host!="^test-"按正则保留或排除事件,区分大小写
extract / kv| extract | stats count by user从正文自动提取 key=value
replace| replace "*.local" WITH "*" IN host整值替换,支持 * 通配
makemv / mvexpand| makemv delim="," tags | mvexpand tags拆成多值,再展开成多行
strcat / rangemap / addtotals| rangemap field=duration_ms fast=0-200 slow=201-100000addtotals 需要写出字段名
reverse| reverse原始事件改成从旧到新
spath| spath input=payload展开 JSON 字段
fillnull| fillnull value=0 bytes
bin / bucket| bin _time span=6h | stats count by _time
lookup| lookup http_status.csv status OUTPUT desc AS status_desc用查找表补字段,见 第 6 节
inputlookup| inputlookup http_status where status>=400写在最前面,按文件顺序列出查找表;支持 start=、max=。写在中间要加 append=t,把表的行接到前面结果的后面
outputlookup... | stats count by host | outputlookup hosts.csv把结果存成查找表;append=t 追加。和 Splunk 一样后面可以接命令,结果原样往下传。只在点「搜索」时执行,API 要用 POST

统计函数(stats、timechart、chart 通用)

count、count(eval(条件))、dc(distinct_count)、sum、avg(mean)、min、max、median、stdev、perc95 / p95 / perc99(任意百分位)、values、list、earliest(_time)、latest(_time)、first(_time)、last(_time)。first/last 取当前顺序里第一行/最后一行的时间(原始事件默认从新到旧),行不是按 _time 排的时候会报错(inputlookup append=t 接上表的行之后也算,要先 sort _time)。eventstats、streamstats 只能用 count、sum、avg、min、max 和 earliest/latest/first/last(_time),其他函数(dc、median、perc、values、list、stdev、count(eval()))会报错,可以先用 stats 算出来。

暂不支持(会明确报错)

Splunk 的 100 多个命令逐个列在 SPL 命令覆盖清单 里,每个都标了“已支持 / 部分支持 / 计划做 / 不打算做”。最常用的几个还没做的是:transaction、join / append 和子搜索、makeresults、xyseries / transpose、convert。

在别的产品里用 SPL 语法有没有法律风险,见 法律风险梳理。

3. 和 Splunk 不一样的地方

4. 租户、账号和登录

一台服务器可以给很多客户用,每个客户是一个租户。租户的数据单独存放(VictoriaLogs 里各自的 account_id),查询里写什么都看不到别的租户的数据。打开首页先看到的是登录页,没登录什么也看不到。

三种人,按这个顺序出场:

  1. 超级管理员(平台方,账号 superadmin):登录后只看到「租户」页。在那里新建租户,同时填好它的管理员用户名和初始密码,设配额;新建后页面给出这个租户写日志用的 API Key 和接入地址,交给客户。还可以改配额、停用/恢复租户、给租户加管理员或重设管理员密码(客户的管理员忘了密码时)。超级管理员看不到任何租户的数据。
  2. 租户管理员(比如店主):用超级管理员给的账号登录,在「用户与 Key」里给员工开账号、决定每人能看哪些 index,查看和新建/删除写日志用的 API Key,看自己的配额和今天的用量。
  3. 普通用户(员工):用管理员给的账号登录,只能看分给他的 index。

用户登录和 index 权限

每个人都用用户名和密码登录。管理员能看整个租户,普通用户只看分给他的 index。

  1. 管理员登录后点上方的「用户与 Key」。
  2. 在「添加用户」里填用户名、初始密码(至少 8 位)、角色和能看的 index(逗号分开;下面会列出已有的 index,点一下就加进去)。
  3. 把用户名和密码告诉对方。对方在首页登录,页面上方显示「名字(角色)· 租户」,下面写着他能看哪些 index。

5. 上传 CSV 建立索引

相当于 Splunk 的「添加数据 → 上传」。

  1. 点顶部「上传数据」,选文件(.csv、.tsv、.txt,或者 .gz 压缩包)。
  2. 页面会先在本地预览前 5 行,自动识别分隔符、编码和时间列。中文 Excel 导出的 GBK 编码也能识别。
  3. 填 index 和 sourcetype(相当于 Splunk 的索引名和来源类型),确认时间列和时区。
  4. 点「上传并建立索引」,完成后点「搜索这些数据」直接跳到搜索页。

每一行变成一条事件,每一列变成一个字段,可以直接 | stats sum(金额) by 城市。整行文本也能做关键词搜索。文件边上传边写入,不受内存限制,单个文件上限 2GB(解压后)。时间解析失败的行会用上传时间,并在结果里告诉你有多少行。

用命令行上传:

curl -X POST --data-binary @orders.csv \
  -H 'Authorization: Splunk demo-key-change-me' \
  'https://你的地址/api/v1/upload/csv?index=sales&sourcetype=orders&tz=%2B08:00'

可选参数:time_field(指定时间列的字段名,空字符串表示用上传时间;source 等保留名会改成 csv_source,重名列会加 _N 后缀)、time_col(按列号指定时间列,从 1 开始,和 time_field 二选一)、tz(无时区的时间按哪个时区算)、delimiter(, ; tab |)、encoding(utf-8 或 gbk;不写时按文件里第一段中文等非英文字节自动判断)。文件里有和编码对不上的字节时,上传会失败并指出是第几行,不会存成乱码。

6. 查找表(lookup)

查找表是一张 CSV 对照表,用来给事件补字段。例如日志里只有 status=404,对照表里写着 404 对应 “Not Found”,查询时就能多出一列说明。

上传和管理

  1. 点「上传数据」,在下面的「查找表」里选 CSV 文件,填表名(不填就用文件名),点「上传查找表」。第一行是表头,同名上传会覆盖。某一行的列数比表头多(多出的格子不是空的)会报错并指出是第几行,原来的表不变。
  2. 列表里可以「查看」(打开 | inputlookup 表名)、「下载」、「删除」。
  3. 查找表按租户隔离,别的租户看不到也用不了。http_status.csv 和 http_status 指的是同一张表。

命令行上传(要管理员登录,TOKEN 是 POST /api/v1/login 返回的 token,API Key 不行):

curl -X PUT --data-binary @http_status.csv \
  -H "X-API-Key: $TOKEN" \
  'https://你的地址/api/v1/lookups/http_status'

写法

写法结果
| lookup http_status status OUTPUT desc用事件的 status 去匹配表里的 status 列,把 desc 列加到事件上。事件里原来的 desc 会被覆盖;匹配不到时 desc 被清空
| lookup http_status status OUTPUTNEW desc只给还没有 desc 的事件补上,已有的不动
| lookup http_status status不写 OUTPUT:表里除匹配列以外的所有列都加上(覆盖)
| lookup users uid AS user_id OUTPUT name AS owner, dept表里的列名和事件字段名不一样时用 AS;可以写多个匹配列,全部相等才算匹配
| inputlookup users where dept=web写在搜索最前面(和 Splunk 一样以 | 开头),直接看表的内容,可以接其他命令,例如 | stats count by dept。不受页面时间范围影响,租户里还没有日志也能用。输入 | inputlookup 后会自动提示表名
index=web | stats count by host | inputlookup append=t web_hosts先列出搜索结果,再把表的行按文件顺序接在后面,后面的命令(例如 | stats sum(count) by host)对两部分一起算。接在普通事件后面时,事件仍按从新到旧排在前面,表的行(没有时间)排在最后。可以连着接多张表,按写的顺序排;之后的 head、tail、reverse、dedup、fields、table 都按这个顺序处理。也支持 where、start=、max=
index=web | stats count by host | outputlookup web_hosts把搜索结果存成查找表(覆盖);append=t 追加到原表后面;override_if_empty=f 没有结果时保留原表
index=web | stats count by host | outputlookup web_hosts | where count>100outputlookup 后面接命令:表里存的是全部主机,页面上只显示 count>100 的

改几行

和 Splunk 的 CSV 查找表一样,有两种改法,写法不变:

不同的是保存方式:网关把每张表逐行存在数据库(SQLite)里,保存时先和原表比对,只写入新增、修改、删除的那几行,其余行不动。所以 50 万行的表改一行,只写一行。上传结果和搜索页状态栏会显示「改动 N 行」。下载拿到的仍是 CSV。只有改了表头(加列、删列、改列名)时才会整表重写。

匹配规则和 Splunk 的 CSV 查找表默认设置一样:整值相等、区分大小写;表里空着的格子算没有值;一个值匹配多行时得到多值(按表里的顺序,最多 1000 行)。

为什么快

查找发生在存储引擎里:网关只取出这次查询用到的列,按匹配列合并好,随查询一起交给 VictoriaLogs,在那边做哈希关联,再接着做后面的 stats 等命令。所以 | lookup ... | stats count by 新字段 扫几百万条事件也不用把事件传回网关。实测 660 万条事件关联 1000 行的表约 0.15 秒,关联 10 万行的表约 1 秒。查找表不写进日志库,不受日志保留期影响,也不会出现在普通搜索结果里。

限制

7. 图表和仪表盘

凡是统计类查询(stats、timechart、chart、top、rare),结果会自动画图,图表上方可以切换:

仪表盘

8. 怎样超越 Splunk:后续计划

先把 Splunk 用户最常用的部分做到“搬过来就能用”,再在 Splunk 做得不好的地方拉开差距。下面是建议的顺序,你挑优先级:

第一步:模仿到位

  1. 补 SPL 命令:transaction、join/append 子搜索、makeresults、xyseries/transpose(eventstats、streamstats 已做好)。
  2. 仪表盘存到服务端、可分享,能导入 Splunk 的 Simple XML 仪表盘。
  3. 保存的搜索和告警(定时跑 SPL,超阈值发 Telegram / 邮件 / Webhook)。
  4. 账号、角色、Key 管理页面。

第二步:超越

  1. 成本:存储压缩比和查询速度已经实测比 ClickHouse、OpenObserve 好;按量计费可以比 Splunk 便宜一个数量级。
  2. OpenTelemetry 原生:Splunk 接 OTel 要绕一层,这里直接收,trace_id 可以一键串起一次请求的所有日志。
  3. 自然语言查询:用中文说「过去一小时支付服务的错误按类型统计」,自动生成 SPL,并显示出来让你核对。
  4. 迁移工具:导入 Splunk 的保存搜索、仪表盘和告警,自动翻译并对比结果。
  5. 手机体验:Splunk 手机端很弱,这里所有页面都按手机竖屏设计。