← 文档目录

Osmanthe 网关:怎么测试、怎么接 OpenTelemetry

2026-10-10 · 第一版骨架 · Rust 网关 + VictoriaLogs v1.53.0

一句话:Rust 网关已经能跑。它同时接收 Splunk HEC 和 OpenTelemetry(OTLP,支持 HTTP 和 gRPC)两种写入,数据按 API Key 分租户存进 VictoriaLogs,并提供带租户隔离的搜索接口和一个简单网页。测试分四层:cargo test 单元测试、tools/smoke_test.sh 端到端检查、tests/regression/ 回归测试、telemetrygen / hec_replay.py 压测。任何改动上线前都要跑 bash tools/check_all.sh,前三层全部通过才算完成。

1. 现在能做什么

采集端                                Osmanthe 网关 (Rust)                 存储
Splunk UF / Fluent Bit / Vector ──► HEC  /services/collector/*  ┐
OTel SDK / OTel Collector ────────► OTLP/HTTP  /v1/logs         ├─► LogStore 接口 ─► VictoriaLogs
OTel SDK / OTel Collector ────────► OTLP/gRPC  :4317            │   (租户 = AccountID/ProjectID)
浏览器 / 脚本 ─────────────────────► 搜索 /api/v1/search (LogsQL) ┘

2. 现在就能看

打开 https://coding.lab.sigmax-group.com,用 demo 租户的账号登录(没有的话让超级管理员在「租户」页给 demo 设一个管理员),时间范围选“全部”,然后点搜索。里面已经有今天测试写进去的约 570 万条日志。

可以试试这些查询:

更多写法和搜索页用法见 搜索页用法与 LogsQL 速查(2026-10-11 新增)。

换成 other-key-change-me 再搜,只能看到另一个租户自己的几条测试数据,这就是租户隔离。

这个地址前面有一层密码保护,所以外部机器的采集端暂时没法直接往里发数据。要让真实客户接入,需要另外开一个公网入口(建议走 HTTPS,只放行 HEC 和 OTLP 路径),这一步还没做。

3. 四层测试

规则:每个功能、每次修改都必须通过全部回归测试。一条命令跑完格式检查、clippy、单元测试、冒烟测试和回归测试:

docker compose -p coding -f deploy/docker-compose.yml up -d --build gateway   # 先部署新代码
bash tools/check_all.sh

最后一行出现 CHECK_ALL PASSED 才算通过。

第 1 层:单元测试和接口测试(不需要启动 VictoriaLogs)

cargo test
cargo clippy --all-targets -- -D warnings

一共 38 个测试,包括 HEC 解析和 Splunk 错误码、时间戳精度、OTLP 的 JSON 和 protobuf 转换、鉴权、gzip、内存存储下的租户隔离、SPL 翻译。CI 配置在 .github/workflows/ci.yml,推到 GitHub 后自动运行。

第 2 层:端到端冒烟测试(真实 VictoriaLogs)

docker compose -p coding -f deploy/docker-compose.yml up -d --build
docker compose -p coding -f deploy/docker-compose.yml --profile loadgen up -d otel-collector   # 可选
bash tools/smoke_test.sh

脚本会跑 20 项检查:HEC 的 event、raw、gzip 三种写法,OTLP 的 HTTP JSON 和 gRPC(用官方 telemetrygen),经过真实 OTel Collector 转发的写入,搜索,坏查询,没带 Key 或 Key 错误,以及两个方向的租户隔离。每项都会核对存进去的条数是否一条不差。今天的结果:20/20 通过。

第 3 层:回归测试(真实 VictoriaLogs)

bash tests/regression/run.sh            # 全部用例
bash tests/regression/run.sh '' 001     # 只跑名字里带 001 的用例

每修好一个 bug,就在 tests/regression/cases/ 下加一个用例文件,编号递增,文件开头写明日期、现象、原因和对应的单元测试。用例自己写入带唯一标记的数据(index=regtest),不依赖演示数据,所以随时可以重复跑。修复前先确认新用例会失败,修复后再确认通过。

编号问题检查什么
001上面「匹配 X 条事件」和 stats count 对不上(2026-10-11)开始时间不在整点时,hits 总数、柱状图各柱之和、stats count 三者相等;覆盖 SPL 和 LogsQL、多种分桶、只有开始时间的情况
002全角竖线 | 查询没反应(2026-10-11)全角 | ( ) = 写的 SPL 和半角写法结果一样

回归测试写入的数据很少(每次几条),都在 index=regtest 下,搜索时加 index!=regtest 可以排除。

第 4 层:压测

OpenTelemetry 写入:用官方工具 telemetrygen

docker run --rm --network coding_default \
  ghcr.io/open-telemetry/opentelemetry-collector-contrib/telemetrygen:latest \
  logs --otlp-endpoint gateway:4317 --otlp-insecure \
  --otlp-header 'authorization="Bearer demo-key-change-me"' \
  --duration 60s --rate 0 --workers 6 --batch-size 1000 --service load-test

改成走 HTTP:加上 --otlp-http,并把地址换成 gateway:8080。

真实日志:用 tools/hec_replay.py 流式回放,原始日志不落盘

# 客户给的压缩样本,边解压边发,100G 的 VPS 也能回放远超 100G 的日志
zstd -dc 客户样本.log.zst | python3 tools/hec_replay.py \
  --token demo-key-change-me --sourcetype nginx --concurrency 8

# 没有真实数据时,用带高基数字段(IP、用户、trace_id)的模拟数据
python3 tools/hec_replay.py --generate 5000000 --token demo-key-change-me

这个脚本只用 Python 标准库,也能直接对着真的 Splunk HEC 跑,方便同一份数据横向对比(前提是 Splunk 许可允许,之前已经说过这一点)。

看结果

今天的初步数据(仅供参考)

场景结果说明
OTLP/gRPC,telemetrygen,6 个 worker,15 秒约 35.9 万条/秒,发 538.2 万条,存 538.2 万条telemetrygen 的每条日志很短,所以条数高、字节数低;压测工具、网关和 VictoriaLogs 挤在同一台 6 核机器上
HEC,hec_replay.py 模拟 nginx 日志约 8.9 万条/秒(20 MB/s),30 万条全部存入瓶颈在 Python 发送端,不在网关
经 OTel Collector 转发(gzip)发 4959 条,存 4959 条功能验证,没有压测
网关内存约 27 MB压测之后的读数

这些数字只能说明链路是通的,并且网关不是瓶颈,不能拿去对外宣传。要得到正式数字,需要把压测工具放到另一台机器上,用真实日志测。

4. OpenTelemetry 怎么接

OpenTelemetry 现在很流行,所以 OTLP 和 HEC 一样,是网关的一等入口。客户一般有三种接法:

方式 A:应用 SDK 直接发(最简单)

几乎所有语言的 OTel SDK 都认这几个标准环境变量,不用改代码:

OTEL_EXPORTER_OTLP_LOGS_ENDPOINT=https://你的域名/v1/logs
OTEL_EXPORTER_OTLP_LOGS_PROTOCOL=http/protobuf
OTEL_EXPORTER_OTLP_HEADERS=authorization=Bearer%20<key>
OTEL_SERVICE_NAME=checkout

方式 B:OTel Collector 做采集代理(生产推荐)

应用先发给本机或集群内的 Collector,由 Collector 负责批量、压缩、重试和排队,再转发给我们。用 filelog 采集日志文件也是走这一路。示例配置见 deploy/otel-collector.yaml,关键部分如下:

receivers:
  filelog:                       # 采集日志文件
    include: [/var/log/app/*.log]
  otlp:                          # 接收应用 SDK 发来的数据
    protocols: { grpc: {}, http: {} }
processors:
  batch: { send_batch_size: 2000, timeout: 1s }
exporters:
  otlphttp/osmanthe:
    endpoint: https://你的域名     # 会自动拼上 /v1/logs
    compression: gzip
    headers: { authorization: "Bearer <key>" }
service:
  pipelines:
    logs: { receivers: [filelog, otlp], processors: [batch], exporters: [otlphttp/osmanthe] }

方式 C:Kubernetes

用官方 Helm chart 把 Collector 部署成 DaemonSet,在每个节点上采集容器日志,exporter 的写法和方式 B 一样。

OTLP 字段怎么存

OTLP 字段存成
body_msg(结构化的 body 会转成 JSON 文本)
timeUnixNano,没有就用 observedTimeUnixNano_time,纳秒精度
resource 和 log 的 attributes原样作为字段,比如 service.name、http.status_code;嵌套的 map 用点号展开
severityText / severityNumberseverity(只有数字时自动换算成 INFO、ERROR 等)、severity_number
traceId / spanIdtrace_id / span_id(十六进制),以后可以和链路追踪打通
service.name、host.name、k8s.namespace.name 等作为 VictoriaLogs 的 stream 字段,按服务和主机过滤会更快;在配置文件 [otlp].stream_fields 里修改

5. Splunk 客户怎么迁移

采集端只改地址和 token,其他都不用动:

# Fluent Bit
[OUTPUT]
    Name         splunk
    Host         你的域名
    Port         443
    TLS          On
    Splunk_Token <key>

# Vector
[sinks.osmanthe]
type = "splunk_hec_logs"
endpoint = "https://你的域名"
default_token = "<key>"
encoding.codec = "json"

HEC 的 event、raw、health 三个接口都实现了,错误码和 Splunk 一致(比如 2 表示缺少 token,4 表示 token 无效,6 表示数据格式错误)。目前还不支持 indexer acknowledgement(useACK)。

6. 拿到客户真实数据后怎么测

  1. 让客户给一份脱敏的压缩样本,最好是 1 到 10 GB 的 zst 或 gz 文件。
  2. 用 hec_replay.py 流式灌进去。如果客户用的是 OTel,就用 Collector 的 filelog 去读这份文件。
  3. 记录下面这张表,它会直接用于定价和容量规划:
指标怎么得到用来做什么
压缩比原始字节数 ÷ /vlogs 的磁盘占用算每 GB 的存储成本,进而定价
写入吞吐回放脚本的 MB/s,加上 /metrics每台机器能承载多少客户
客户常用查询的延迟搜索接口返回的 took_ms体验是否比 Splunk 好
高基数字段查询按 trace_id、user_id 精确查找排障场景是否够快
是否丢数据发送条数和 stats count() 对比必须为 0

7. 还没做的和风险