opentelemetry c++ sdk 编译失败主因是未启用 trace 组件,需显式开启 -dbuild_otlp_exporter=on 等开关,并链接 opentelemetry_trace 和 opentelemetry_resources 库;grpc 中 context 传递须手动解析/注入 traceparent;otlp 连接需注意协议、证书及 collector 配置匹配;span 生命周期管理不当易致 crash 或丢 span。

OpenTelemetry C++ SDK 编译失败:找不到 opentelemetry::sdk::trace::Processor
直接原因是 OpenTelemetry C++ SDK 默认不启用 trace 组件,CMake 构建时没开开关。它不像 Java 或 Go 那样“装完就能用”,C++ 版本必须显式启用子模块。
- 构建时加
-DBUILD_OTLP_EXPORTER=ON -DWITH_ZLIB=ON -DWITH_GRPC=ON -DWITH_PROMETHEUS=OFF(GRPC是 OTLP/gRPC 导出必需的) - 确保系统已安装
grpc和protobuf开发包(Ubuntu 上是libgrpc-dev libprotobuf-dev) - 头文件路径容易错:不是
#include "opentelemetry/sdk/trace/processor.h",而是#include "opentelemetry/sdk/trace/simple_processor.h"或batch_span_processor.h—— 前者不依赖后台线程,适合初调;后者需手动管理线程生命周期 - 链接时漏掉
opentelemetry_trace和opentelemetry_resources库会报 undefined reference,尤其opentelemetry_resources容易被忽略
如何在 gRPC 微服务里自动注入 trace context
OpenTelemetry C++ 没有类似 Java 的自动拦截器,gRPC client/server 端的 context 传递得自己埋点。关键不是“加 tracer”,而是“在哪取、在哪塞”。
- server 端:从
ServerContext::client_metadata()读traceparent字段,用opentelemetry::trace::SpanContext::FromTraceParentHeader()解析 - client 端:调用前往
ClientContext::AddMetadata()写入traceparent,格式必须严格符合 W3C Trace Context 规范(如"00-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-01") - 别依赖
Tracer::StartSpan()自动关联 parent —— 它默认 parent 是空的,必须显式传入SpanContext构造StartSpanOptions - 如果用的是异步 gRPC,metadata 读写要在
AsyncServerStreaming等回调里做,不能在 handler 外围直接操作ServerContext
OTLP exporter 连不上 collector:常见配置陷阱
错误信息通常是 Failed to connect to endpoint 或 Deadline Exceeded,90% 不是网络问题,而是协议/证书/路径没对齐。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- endpoint 地址要带协议:gRPC 用
http://localhost:4317(注意是http,不是https;OpenTelemetry C++ 的 grpc::Channel 不默认启 TLS) - 如果 collector 开了 TLS(比如用
https://collector.example.com:4317),C++ client 必须提供根证书路径:otlp::OtlpGrpcExporterOptions::ssl_credentials_options.pem_root_certs - HTTP exporter 更简单但限制多:只支持 JSON 格式,且必须设
url = "http://localhost:4318/v1/traces"—— 少/v1/traces就静默失败 - collector 配置要匹配:Jaeger receiver 不收 OTLP,必须配
otlp:接收器;同时 exporter 要配logging:或jaeger:,否则 span 丢了也没提示
Span 生命周期管理不当导致 crash 或内存泄漏
C++ 里 Span 是值语义对象,但背后绑着 SDK 的资源池和线程安全队列。乱 hold、乱 copy、乱提前结束,很容易踩 double-free 或 use-after-free。
- 不要把
opentelemetry::trace::Span存成类成员变量或全局变量 —— 它不是线程安全的 handle,且析构时会触发 finish 流程 - 避免跨线程传递 Span 对象本身;如需在线程间延续 trace,只传
SpanContext,新线程用它 start 新 Span - 使用
std::shared_ptr<:trace::tracer></:trace::tracer>管理 tracer 生命周期,确保 tracer 活着的时间比所有 Span 都长;SDK shutdown 顺序必须是:先停 exporter,再 shutdown tracer provider,最后清理全局资源 - 如果用了
BatchSpanProcessor,记得调用ForceFlush()再 shutdown,否则最后一小批 span 可能永远发不出去
最麻烦的从来不是“怎么加 tracing”,而是“怎么让每个 span 都有 parent、每个 service 都不丢 context、每个 exporter 都不卡死”。这些细节不写进日志,也不报错,只在 trace 查看器里显示为断链或空白。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










