OneUptime OpenTelemetry 接入指南:OTLP 日志、指标与追踪的全链路集成
2026/9/18 11:45:33 网站建设 项目流程

OneUptime OpenTelemetry 接入指南:OTLP 日志、指标与追踪的全链路集成

【免费下载链接】oneuptimeComplete open-source monitoring and observability platform.项目地址: https://gitcode.com/GitHub_Trending/on/oneuptime

本文基于 OneUptime 官方文档App/FeatureSet/Docs/Content/en/telemetry/open-telemetry.md展开,覆盖从创建遥测摄取密钥(Telemetry Ingestion Token)、配置应用侧 OTEL 环境变量、到使用 OpenTelemetry Collector 中转上报的完整接入流程,并结合仓库源码深入解析 OTLP 接收端点、鉴权中间件与"从日志中提取异常"的底层实现,帮助你在生产环境中把日志(Logs)、指标(Metrics)、追踪(Traces)三类信号稳定地接入 OneUptime。

第一步:创建 Telemetry Ingestion Token

接入的前提是拥有一个 OneUptime 项目下的遥测摄取密钥:

  1. 注册 OneUptime 账号并创建 Project;
  2. 在导航栏点击 "Products",进入 "Project Settings";
  3. 在 Telemetry Ingestion Key 页面点击 "Create Ingestion Key" 创建 token;
  4. 创建完成后点击 "View" 查看完整 token 值(后续所有上报配置都要用到它)。

服务端如何消费这个 token?所有 OTLP 请求都会先经过 TelemetryIngest 鉴权中间件,它按以下优先级读取三个请求头:

x-oneuptime-token → x-oneuptime-service-token → x-oneuptime-ingestion-key

源码中(Common/Server/Middleware/TelemetryIngest.ts)可以看到几个关键设计:

  • 缺失或无效 token 一律返回 401。这是刻意为之:OTLP 规范将 401 定义为"不可重试",合规的 SDK/Collector 会直接记录错误而非重试风暴;如果静默返回 200,客户端会以为数据已落库,而用户面对的却是空仪表盘;
  • token 本身不会被写入日志——摄取密钥是秘密凭证,日志中只保留请求元数据以便关联排查;
  • 中间件一次查询即解析出完整的 key 策略(TelemetryIngestionKeyPolicy),依次检查:密钥是否被禁用(返回 403,区别于 401,方便区分"贴错了 key"与"key 被人关掉了")、密钥是否过期(返回 401)、是否超出每分钟请求数限制(返回 429 并携带Retry-After头);
  • 认证通过后将projectId与解析出的 key 策略挂到请求对象上,下游处理器无需再次解析 token。

此外,OTelIngest 路由文件 还暴露了一个专门用于诊断的端点:

# 验证你的 token 是否真正可用(不产生任何摄取行为) curl -H "x-oneuptime-token: YOUR_TOKEN" https://oneuptime.com/otlp/v1/validate
  • 返回200 { valid: true, projectId, keyType, isEnabled, isExpired }表示 token 可被接受;
  • 返回401 { valid: false, ... }会附带具体原因:token 不存在/已吊销、已被禁用、已过期,甚至会在你误用了 Browser 型密钥时明确提示"collector/agent 应使用 Server 型密钥"。

这个端点对排查安装脚本或 Collector 部署问题非常有用——安装脚本可以在启动前主动询问"我的 token 是否被接受",而不必等到遥测数据 401 才发现问题。

第二步:配置应用侧 OpenTelemetry 上报

OneUptime 使用 OpenTelemetry 收集应用日志,官方文档列出了受支持的 SDK 语言矩阵:C++、Go、Java、JavaScript/TypeScript/NodeJS/Browser、Python、Ruby、PHP、Erlang、Rust、.NET/C#、Swift。各语言的 SDK 配置方式遵循 OpenTelemetry 官方对应语言的 instrumentation 文档,这里不再重复外链;核心是配置好 OTLP 导出器后,按下面三个环境变量接入 OneUptime:

环境变量说明
OTEL_EXPORTER_OTLP_HEADERSx-oneuptime-token=YOUR_ONEUPTIME_SERVICE_TOKEN鉴权 token,即第一步创建的摄取密钥
OTEL_EXPORTER_OTLP_ENDPOINThttps://oneuptime.com/otlp云端 OTLP HTTP 端点
OTEL_SERVICE_NAMENAME_OF_YOUR_SERVICE服务名,用于在 OneUptime 中归属遥测数据

完整示例(bash):

export OTEL_EXPORTER_OTLP_HEADERS=x-oneuptime-token=9c8806e0-a4aa-11ee-be95-010d5967b068 export OTEL_EXPORTER_OTLP_ENDPOINT=https://oneuptime.com/otlp export OTEL_SERVICE_NAME=my-service

自托管(Self-Hosted)场景:如果你自行部署 OneUptime,将OTEL_EXPORTER_OTLP_ENDPOINT改为你自托管实例的 OTLP 端点,例如http(s)://YOUR-ONEUPTIME-HOST/otlp

从源码结构看,端点并不是一个笼统的/otlp,而是标准 OTLP 四类信号路径,在 OTelIngest.ts 中分别注册为四个 POST 路由:

路由信号类型处理服务
/otlp/v1/traces分布式追踪OtelTracesIngestService
/otlp/v1/metrics指标OtelMetricsIngestService
/otlp/v1/logs日志OtelLogsIngestService
/otlp/v1/profiles持续性能分析OtelProfilesIngestService

每个路由的中间件链是固定的:TelemetryIngestionDisabled(全局摄取开关)→parseBody(解析 Protobuf/JSON 负载)→ 摄取指标中间件(按信号记录计数、耗时与负载字节数)→getProductTypeTelemetryIngest.forSurface(...)鉴权 → 各信号摄取服务。数据进入系统后交给队列异步落库,/otlp/queue/stats/otlp/queue/size/otlp/queue/failed三个内部端点(需集群密钥授权)可用于观察队列积压与失败任务。

应用启动后,你可以在 OneUptime 的 Telemetry 页面看到对应服务的日志、指标与追踪数据。

通过 OpenTelemetry Collector 中转上报

除了应用直连,更常见的生产架构是让应用先把遥测数据发给本地 OpenTelemetry Collector,再由 Collector 转发到 OneUptime。文档给出的完整示例配置如下:

receivers: otlp: protocols: grpc: endpoint: 0.0.0.0:4317 http: endpoint: 0.0.0.0:4318 exporters: # Export over HTTP otlphttp: endpoint: "https://oneuptime.com/otlp" # Requires use JSON encoder insted of default Proto(buf) encoding: json headers: "Content-Type": "application/json" "x-oneuptime-token": "ONEUPTIME_TOKEN" # Your OneUptime token service: pipelines: traces: receivers: [otlp] exporters: [otlphttp] metrics: receivers: [otlp] exporters: [otlphttp] logs: receivers: [otlp] exporters: [otlphttp]

配置要点解析:

  • receivers.otlp同时监听 gRPC(4317)与 HTTP(4318)两个标准 OTLP 端口,应用侧 SDK 两种协议均可直投 Collector;
  • 导出器使用otlphttp,且必须设置encoding: jsonContent-Type: application/json)——这是文档中特别强调的一点,因为 OneUptime 的 HTTP 摄取端点在该链路上要求 JSON 编码,而非 Collector 默认的 Protobuf;
  • headers中的x-oneuptime-token与直连模式使用同一个请求头,Collector 只是中转者,鉴权规则完全一致(见上文中间件解析,x-oneuptime-service-tokenx-oneuptime-ingestion-key两个别名头同样有效);
  • 三条 pipeline(traces / metrics / logs)共用同一个otlphttp导出器,实现一份 token 配置覆盖三类信号。

自托管部署时,只需把endpoint换成你的自托管主机地址(如http://YOUR-ONEUPTIME-HOST/otlp)。另外,仓库根目录下的 OTelCollector 配置模板 是 OneUptime 自身部署中 Collector 的配置参考,可用于对比自托管拓扑。

从日志中提取异常(Exceptions from Logs)

OneUptime 不仅把日志当作文本存储,还会主动检测日志中的异常,并将其汇入与 Trace 错误相同的 Exceptions(Issues)视图。由于每条日志本身已经解析到具体的 service 或 host,日志来源的异常能自动归属到正确的资源;并且日志异常与 Trace 异常共享同一套指纹(fingerprint)分组——同一个错误如果同时被 trace 和 log 报告,会收敛为同一个 issue,避免重复计数。

文档定义了两条检测路径:

路径一:显式 exception 属性(推荐)。日志记录若携带 OpenTelemetry 标准的exception.typeexception.messageexception.stacktrace属性,会被直接转换为一条异常。主流日志集成(Java 的 Logback/Log4j appender、.NET 的 Serilog、Python logging instrumentation 等)在记录异常时都会自动填充这些属性,因此这条路径精准且与语言无关。

路径二:扫描日志正文中的堆栈。对于没有上述属性的 error/fatal 日志(例如原始 stdout、syslog、journald 采集的纯文本),OneUptime 会对正文做堆栈识别,覆盖 JavaScript、Python、Java、Go、Ruby、C#/.NET、PHP 等语言,并提取异常类型、消息与调用帧。前提是多行堆栈必须作为单条日志记录到达——如果你采集的是纯文本日志,需要在 Collector 侧启用 multiline 重组(可参考仓库内的 Host OpenTelemetry Collector 文档 中配置 multiline 处理器)。

这个能力默认开启。自托管场景下可通过环境变量关闭:

# 在 ingest 服务上设置,热禁用整个日志异常提取功能 TELEMETRY_LOG_EXCEPTION_EXTRACTION_ENABLED=false

该开关在 App/FeatureSet/Telemetry/Config.ts 中定义(默认值true,只有显式设为"false"才关闭),并在 OtelLogsIngestService.ts 的日志处理路径中检查,实现了对整条提取链路的快速熔断。

源码级实现细节(LogExceptionExtractor.ts):

  • 路径 A(属性提取)始终启用且开销最小:读取exception.stacktrace/exception.type/exception.message,任一存在即生成异常,并顺带解析exception.escaped;堆栈会进一步交由 StackTraceParser.ts 解析为结构化帧(parsed frames);
  • 路径 B(正文扫描)有多重热路径保护
    • 仅扫描severityNumber >= 17的日志(OTel 规范中 17–20 为 ERROR,21–24 为 FATAL),绝大多数低于该阈值的日志不会进入解析器;
    • 若日志同时携带traceIdspanId(说明它产生于一个被 instrumented 的 span 内),路径 B 会被抑制——span 异常路径才是这类异常的规范来源,抑制可避免重复计数(否则会同时膨胀 occurrenceCount 与异常监控窗口);路径 A 不受此抑制,因为显式的结构化异常记录是有意的;
    • 只解析正文前 16KB(一条干净的单记录堆栈约 150 帧,足以容纳),防止多 MB 的异常日志拖慢热路径;
    • 先用一条预编译的正则签名(覆盖 Python traceback 头、JS/Java 的at file:line帧、Gopanic:/goroutine头、PythonFile "...", line N、浏览器fn@url:line:col帧、以及SomethingException/SomethingError类型名)做廉价预筛,未命中则直接返回,避免运行更重的多语言解析器;
    • 要求至少解析出一个调用帧才认定为真实堆栈——只是文本中提到了 "...Error:" 的散文式日志会被拒之门外。
  • 存储侧截断:原始日志正文无上界(不同于 SDK 限长的 spanexception.stacktrace),因此写入 ClickHouse 的stackTrace列上限为 64KB,异常消息上限 1024 字符;
  • 提取永不抛错:整个抽取逻辑被包裹在 try/catch 中,任何解析失败都返回null,保证异常提取故障不会影响日志摄取主流程。

接入验证与排查清单

结合上文,一个可落地的验证顺序是:

  1. curl .../otlp/v1/validate确认 token 有效(valid: true且不是 Browser 型密钥);
  2. 直连或 Collector 方式发送一次测试遥测,观察 Collector/SDK 日志中是否出现 401(token 问题)或 429(限流,注意Retry-After头);
  3. 在 OneUptime Telemetry 页面确认对应OTEL_SERVICE_NAME的日志/指标/追踪数据到达;
  4. 若日志异常未出现在 Exceptions 视图,依次检查:日志级别是否达到 ERROR 以上、多行堆栈是否已重组为单条记录、自托管是否误关了TELEMETRY_LOG_EXCEPTION_EXTRACTION_ENABLED
  5. 自托管部署若怀疑摄取队列积压,可用集群密钥调用/otlp/queue/stats查看等待/失败任务数。

参考文件

文件作用
App/FeatureSet/Docs/Content/en/telemetry/open-telemetry.md本文主体依据的官方接入文档
App/FeatureSet/Telemetry/API/OTelIngest.tsOTLP 路由、token 校验端点与队列状态端点
Common/Server/Middleware/TelemetryIngest.ts摄取鉴权中间件(401/403/429 语义、限流、Origin 策略)
Common/Server/Utils/Telemetry/LogExceptionExtractor.ts日志异常提取的两条检测路径与性能保护
Common/Server/Utils/Telemetry/StackTraceParser.ts多语言堆栈帧解析
App/FeatureSet/Telemetry/Config.tsTELEMETRY_LOG_EXCEPTION_EXTRACTION_ENABLED开关定义
App/FeatureSet/Telemetry/Services/OtelLogsIngestService.ts日志摄取服务与提取开关的使用点
App/FeatureSet/Docs/Content/en/telemetry/host-otel-collector.md主机侧 Collector 部署与 multiline 配置参考

适用前提说明:端点地址https://oneuptime.com/otlp适用于 OneUptime 云服务;自托管部署时请以实际部署的主机地址替换。Collector 导出器需使用otlphttp+ JSON 编码(文档明确要求);gRPC 直投应用侧 Collector 不受此限制,因为该要求只作用于 Collector 到 OneUptime 的 HTTP 导出环节。

【免费下载链接】oneuptimeComplete open-source monitoring and observability platform.项目地址: https://gitcode.com/GitHub_Trending/on/oneuptime

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询