OneUptime Syslog 摄取指南:通过 HTTPS 将 RFC3164/RFC5424 日志统一接入可观测平台
【免费下载链接】oneuptimeComplete open-source monitoring and observability platform.项目地址: https://gitcode.com/GitHub_Trending/on/oneuptime
导读
OneUptime 的 OpenTelemetry 摄取服务原生支持 Syslog 负载:任何能产生 RFC3164 或 RFC5424 消息的网络设备、Linux 主机或 Kubernetes 边缘节点,都可以通过一条 HTTPS POST 请求把日志直接送入 OneUptime,由服务端自动解析优先级(priority)、设施(facility)、严重级别(severity)、结构化数据(structured data)与消息正文,最终以可搜索的日志形式落库。读完本文,你将掌握 Syslog 摄取的端点协议、三种请求内容类型、curl 快速验证、rsyslog/Fluent Bit 的转发配置,以及 OneUptime 在服务端如何解析与归并这些日志。
本文对应的官方文档为 App/FeatureSet/Docs/Content/es/telemetry/syslog.md,仓库内全部实现证据均可从该文档链接的源码路径回溯验证。
Syslog 摄取的总体工作方式
Syslog 是网络设备与遗留系统事实上的日志标准,但传统上依赖 UDP 514 端口、明文传输且没有统一检索能力。OneUptime 的处理思路不是搭建新的 Syslog 收集器,而是让现有的 Syslog 生态通过 HTTPS 把消息转发到一个专用摄取端点:
POST https://oneuptime.com/syslog/v1/logs- 使用 OneUptime 云服务时保持
oneuptime.com;自托管(self-hosted)部署时替换为你自己的 OneUptime 主机名。 - 每个请求必须携带
x-oneuptime-token请求头,其值来自项目的摄取令牌。
从路由注册到存储,整条链路可以在 App/FeatureSet/Telemetry/API/Syslog.ts 中看到:该路由先经过TelemetryIngestionDisabled中间件(全局开关),再被标记为ProductType.Logs(日志产品),随后通过TelemetryIngest.forSurface(TelemetryIngestSurface.Syslog)完成令牌鉴权,最后进入SyslogIngestService.ingestSyslog处理。
鉴权中间件:令牌如何被校验
Common/Server/Middleware/TelemetryIngest.ts 实现了摄取令牌的统一校验逻辑,Syslog 与 OTLP、Fluent 等摄取面共用同一套规则:
- 依次尝试
x-oneuptime-token、x-oneuptime-service-token、x-oneuptime-ingestion-key三个请求头,取第一个存在的值; - 令牌缺失或无效时返回HTTP 401(不可重试语义,避免采集端重试风暴);
- 令牌被禁用时返回HTTP 403;
- 令牌过期时返回HTTP 401;
- 支持按令牌配置的每分钟请求数限流,超限返回HTTP 429并附带
Retry-After头(Redis 计数器不可用时采用 fail-open 策略,保证生产遥测不因基础设施抖动而中断); - Browser 类型的令牌只允许访问白名单内的摄取面(Syslog 不在其中),因此 Syslog 摄取必须使用Server 类型的摄取令牌。
异步队列与批量落库
请求到达后,服务端先立即返回空成功响应,随后把整个请求体放入队列异步处理(见 App/FeatureSet/Telemetry/Services/Queue/SyslogQueueService.ts)。队列消费者在 SyslogIngestService.ts 的processSyslogAsync中逐条解析、构造日志行,并按TELEMETRY_LOG_FLUSH_BATCH_SIZE(见 App/FeatureSet/Telemetry/Config.ts)成批交给共享的 fan-in writer 写入 ClickHouse。写入采用 ack-after-flush 语义:只有当包含本批次数据的批次真正落到 ClickHouse 后,任务才算成功,否则由 BullMQ 重试,保证大流量下不丢日志。
前提条件
接入前需要准备:
- 遥测摄取令牌(Telemetry ingestion token):在项目设置(Ajustes del proyecto)→ 遥测与 APM(Telemetría y APM)→ 摄取密钥(Claves de Ingesta)中创建,并复制其值作为
x-oneuptime-token请求头。注意必须使用Server 类型密钥。 - Syslog 转发器:任何能发送 HTTP POST 的工具均可,例如
curl、通过omhttp模块的rsyslog、或带 HTTP 目标插件的syslog-ng。 - 服务名(可选):设置
x-oneuptime-service-name请求头可以把收到的日志归并到指定遥测服务名下。省略时,服务端按APP-NAME→hostname→ 默认值Syslog的顺序回退解析(对应源码中的DEFAULT_SERVICE_NAME)。
请求体格式与内容类型
请求体支持换行分隔的 Syslog 字符串或包含messages数组的 JSON 负载,RFC3164(BSD)与 RFC5424 格式均被支持。以下是一个 JSON 请求体示例:
{ "messages": [ "<34>1 2025-03-02T14:48:05.003Z web-01 nginx 7421 ID47 [env@32473 host=\"web-01\"] 502 on /api/login", "<13>Feb 5 17:32:18 db-01 postgres[2419]: connection received from 10.0.0.12" ] }三种受支持的内容类型
| 内容类型 | 说明 |
|---|---|
application/json | 推荐使用;负载为含messages数组的 JSON 对象 |
text/plain | 换行分隔的消息文本 |
application/octet-stream | 原始负载;同时接受 Gzip 压缩(Content-Encoding: gzip) |
从源码看,服务端的normalizeMessages对三种形态都做了兼容:字符串按\r?\n拆行并 trim;Buffer先按 UTF-8 解码再走字符串分支;对象形态除了messages数组外,还接受message字段或syslog字段(字符串或数组)。空请求体会被拒绝并返回HTTP 400。
单请求上限与突发处理
官方文档说明:每个请求最多聚合1,000 行Syslog 日志;更大的突发会被放入队列异步处理,不会因请求过大而丢弃。
快速验证:curl 发送示例
使用curl在几秒内完成端到端验证:
curl \ -X POST https://oneuptime.com/syslog/v1/logs \ -H "Content-Type: application/json" \ -H "x-oneuptime-token: YOUR_TELEMETRY_KEY" \ -H "x-oneuptime-service-name: production-web" \ -d '{ "messages": [ "<34>1 2025-03-02T14:48:05.003Z web-01 nginx 7421 ID47 [env@32473 host=\"web-01\"] 502 on /api/login" ] }'请求返回 200 空响应即表示已被接收(实际解析与入库在队列中异步完成)。自托管时把主机名替换为你的部署地址。
从 rsyslog 转发
rsyslog 是 Linux 发行版默认的日志守护进程,通过omhttp输出模块即可完成转发。
1. 安装 HTTP 输出模块
sudo apt-get install rsyslog-omhttp2. 添加转发目标
在/etc/rsyslog.d/oneuptime.conf中配置:
module(load="omhttp") template(name="OneUptimeJson" type="list") { constant(value="{\"messages\":[\"") property(name="rawmsg") constant(value="\"]}") } action( type="omhttp" server="oneuptime.com" serverport="443" usehttps="on" endpoint="/syslog/v1/logs" header="Content-Type: application/json" header="x-oneuptime-token: YOUR_TELEMETRY_KEY" header="x-oneuptime-service-name: rsyslog-demo" template="OneUptimeJson" )3. 重启 rsyslog
sudo systemctl restart rsyslog典型使用场景
场景一:网络与安全设备
绝大多数网络设备(Palo Alto、Fortinet、Cisco ASA、Juniper、pfSense 等)仍只通过 syslog 暴露配置变更、ACL 访问与威胁检测事件。既可以把现有 syslog relay 直接指向 OneUptime,也可以保留内部 relay、再通过 HTTPS 转发到 OneUptime:
# rsyslog 片段:把消息聚合成 JSON 后发布到 OneUptime module(load="omhttp") template(name="OneUptimeJSON" type="list") { constant(value="{\"messages\":[\"") property(name="rawmsg") constant(value="\"]}") } action( type="omhttp" server="oneuptime.com" serverport="443" usehttps="on" endpoint="/syslog/v1/logs" header="Content-Type: application/json" header="x-oneuptime-token: <TOKEN>" header="x-oneuptime-service-name: perimeter-firewall" template="OneUptimeJSON" )场景二:Linux 服务器与 cron 任务
大量 cron 作业与遗留守护进程只通过 kernel/syslog 服务记录日志。转发/var/log/syslog或 journald 条目可以把运维足迹集中到一处。systemd 主机可以依赖 journald → syslog 桥接:
# /etc/rsyslog.d/oneuptime.conf module(load="imjournal" StateFile="imjournal.state") module(load="omhttp") action( type="omhttp" server="oneuptime.com" serverport="443" usehttps="on" endpoint="/syslog/v1/logs" header="Content-Type: application/json" header="x-oneuptime-token: <TOKEN>" header="x-oneuptime-service-name: linux-fleet" template="OneUptimeJSON" )由于 OneUptime 会映射严重级别代码,你可以针对syslog.severity.name = "error"配置告警,或用syslog.hostname进行切分,快速隔离产生噪音的机器。
场景三:Kubernetes 入口控制器与边缘节点
如果已经在用 Fluent Bit 或 Fluentd 收集容器日志,可以保留它们,同时为边缘主机或硬件设备加一个轻量 syslog sink。Fluent Bit 的syslog输入与 HTTP 输出组合如下:
[INPUT] Name syslog Mode tcp Listen 0.0.0.0 Port 5140 [OUTPUT] Name http Match * Host oneuptime.com Port 443 URI /syslog/v1/logs Format json json_date_key time Header Content-Type application/json Header x-oneuptime-token <TOKEN> Header x-oneuptime-service-name edge-ingress tls On这样可以在不另起一套日志栈的前提下,把裸金属 worker 或硬件负载均衡器的 syslog 一并接入。
场景四:合规归档
需要为 PCI 或 SOX 保留防火墙日志时,直接把日志送入 OneUptime,对该遥测服务设置较长保留策略,再从单一位置导出到冷存储,无需从多个 syslog relay 分别导出。
服务端解析:PRI、RFC5424 与 RFC3164
OneUptime 的 Syslog 解析器位于 App/FeatureSet/Telemetry/Utils/SyslogParser.ts,其设计原则在测试文件 App/Tests/Telemetry/SyslogParser.test.ts 中有明确说明:
- 绝不丢行:任何无法理解的报文都必须把原文完整保留在
message字段中(宁可让运维看到畸形行,也不能让它消失); - 绝不臆造字段:发送方没有提供的 hostname 或 appName 不会凭空生成,RFC 中的 NILVALUE
-会被解析为undefined而不是字面量字符串。
PRI 解码
解析器先匹配行首的<优先级>标记(正则^<(\d{1,3})>),然后按标准公式拆分:
severity = priority % 8(严重级别:低 3 位)facility = Math.floor(priority / 8)(设施:其余高位)
测试用例验证了关键边界:<34>解码为 facility 4、severity 2;<0>是紧急内核消息(facility 0、severity 0);<191>是最大的单字节 PRI(facility 23、severity 7);<13>对应 user facility 的 notice(facility 1、severity 5);而超过三位数字(如<1234>)或非数字(如<abc>)不会被当作 PRI,整行原样保留在message中。
RFC 5424 解析
RFC 5424 报文形如VERSION SP TIMESTAMP SP HOSTNAME SP APP-NAME SP PROCID SP MSGID SP STRUCTURED-DATA SP MSG。解析器把报文按空白拆成 7 个 token,依次提取版本号、时间戳、主机名、应用名、进程 ID、消息 ID 和结构化数据区;NILVALUE-一律转为undefined,时间戳由OneUptimeDate.parseRfc5424Timestamp解析。结构化数据区(一个或多个[SD-ID PARAM="value"]块)通过括号深度匹配解析,支持嵌套多个 SD 元素。
RFC 3164 解析
RFC 3164(BSD)报文形如TIMESTAMP SP HOSTNAME SP TAG[PROCID]: MSG。解析器用正则^(\w{3}\s+\d{1,2}\s+\d{2}:\d{2}:\d{2})\s+(\S+)\s+(.*)$匹配时间戳、主机名与剩余部分,再从剩余部分中分离出tag[procId]:结构:带方括号的 tag 解析出 appName 与 procId,否则整个 tag 视为 appName。
第三种情况:两者皆非
当报文既不符合 RFC 5424 也不符合 RFC 3164 时,解析器仍返回一个对象,把priority、facility、severity(若存在 PRI)以及整行原文放入message,确保任何设备产出的行都不会丢失。
解析后的属性与严重级别映射
写入日志记录的属性
SyslogIngestService.ts 的buildAttributes方法为每条日志附加以下syslog.*属性:
syslog.priority、syslog.facility.code、syslog.facility.namesyslog.severity.code、syslog.severity.namesyslog.hostname、syslog.appName、syslog.processId、syslog.messageIdsyslog.version(RFC 5424 版本号,存在时)syslog.structured.raw与syslog.structured.<SD-ID>.<param>(RFC5424 结构化数据被扁平化为点分属性键)syslog.raw(原始消息,用于溯源)
这些属性会同步写入日志行的attributeKeys索引,因此可以直接在遥测 → 日志(Telemetría → Registros)浏览器中进行搜索与过滤。
严重级别映射表
服务端通过SYSLOG_TO_OTEL_SEVERITY映射表把 syslog 的 8 级严重级别转换为 OpenTelemetry 日志严重级别(数字 + 文本):
| Syslog 严重级别(代码) | OTel 严重级别文本 | OTel 严重级别数字 |
|---|---|---|
| 0 emergency / 1 alert | Fatal | 23 |
| 2 critical / 3 error | Error | 19 |
| 4 warning | Warning | 13 |
| 5 notice / 6 informational | Information | 9 |
| 7 debug | Debug | 5 |
未携带 PRI 的报文映射为Unspecified(数字 0)。设施与严重级别的可读名称分别来自SYSLOG_FACILITY_LABELS(kernel、user、mail、system、security、local0–local7 等 24 个标准设施)与SYSLOG_SEVERITY_LABELS(emergency、alert、critical、error、warning、notice、informational、debug)两个常量表,越界值统一返回unknown。
服务名解析优先级
resolveServiceName的优先级依次为:请求头x-oneuptime-service-name→ 解析出的APP-NAME→ 解析出的hostname→ 默认值Syslog。服务名用于查找或自动创建对应的遥测服务,因此一个项目下所有来自同一应用的 syslog 日志会自动归并到同一个服务实体。
与 OTLP 路径一致的日志处理管线
Syslog 摄取与 OTLP 摄取共享同一套日志处理阶段(见processSyslogAsync中对LogPipelineService、LogDropFilterService、LogScrubRuleService的调用,顺序与 OtelLogsIngestService.ts 一致):先按配置的 drop filter 判断是否丢弃整行,再执行敏感数据脱敏(scrub),最后经 Log Pipeline 处理器加工。这意味着你在项目中配置的日志管道、丢弃规则与脱敏规则对 syslog 来源同样生效。每处理 500 条消息会让出一次事件循环(EventLoop.yieldToEventLoop),避免长批量阻塞 Node.js 主线程。
故障排查
- HTTP 401 或结果为空:确认
x-oneuptime-token请求头所属项目正是接收日志的项目,且令牌未被禁用或过期;Syslog 面不接受 Browser 类型令牌,请使用 Server 类型摄取密钥。 - 没有日志出现:确认请求体确实包含 syslog 行;空请求体会被拒绝并返回 HTTP 400。
- 服务名不符合预期:显式设置
x-oneuptime-service-name请求头覆盖默认的检测逻辑(APP-NAME → hostname →Syslog)。 - 突发流量较大:每个请求最多聚合 1,000 行;更大的突发会自动进入队列异步处理。日志入库采用 ack-after-flush 语义,落库失败的任务会由队列重试,不会静默丢失。
总结
Syslog 摄取把 OneUptime 的日志能力延伸到了网络设备、遗留系统和边缘主机:一端是任何能发 HTTP POST 的转发器(curl、rsyslog、syslog-ng、Fluent Bit),另一端是 OneUptime 的/syslog/v1/logs端点。服务端在 SyslogParser.ts 完成 PRI 解码与双 RFC 格式解析,在 SyslogIngestService.ts 完成属性构建、严重级别映射、日志管线处理与异步批量落库。配合遥测 → 日志浏览器中的搜索能力、保留策略与告警规则,你可以在不新建日志采集栈的前提下,把分散在各处的 syslog 汇聚为可检索、可告警、可归档的统一日志视图。
【免费下载链接】oneuptimeComplete open-source monitoring and observability platform.项目地址: https://gitcode.com/GitHub_Trending/on/oneuptime
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考