Repository navigation
tengine是否支持nginx-otel插件 #2019
Description
Activity
目前 tengine 官方尚未直接集成 nginx-otel 插件。nginx-otel 是一个独立的 Nginx 模块,理论上可以通过以下方式集成到 tengine:
-
源码编译集成: 将 nginx-otel 模块作为第三方模块编译进 tengine
./configure --add-module=/path/to/nginx-otel
-
动态模块加载 (如果 tengine 版本支持):
load_module modules/ngx_http_otel_module.so;
需要注意的是:
- 确保 nginx-otel 版本与 tengine 的 Nginx 基础版本兼容
- tengine 的一些定制模块可能与 otel 插件存在冲突,需要测试验证
如果你有具体的集成需求或遇到问题,可以提供更多细节,我们可以协助排查。
-
Tengine 没有内置 nginx-otel(ngx_otel_module),也没有对它做过官方兼容性验证。更重要的是,请不要把针对官方 nginx 编译的预编译 ngx_otel_module.so 直接 load_module 到 Tengine 上,这是不安全的。用 Tengine 源码自行编译成动态模块在机制上可行,但目前属于「用户自行验证」的范畴,我们不提供兼容性保证。
下面说明原因、可行路径和当前的替代方案。
一、为什么不能直接用预编译的 .so
Tengine 3.2.0 的核心已同步到 nginx 1.31.3,动态模块机制是完整保留的:
- configure 支持 --with-compat(auto/options),NGX_MODULE_SIGNATURE 校验机制未做改动(src/core/ngx_module.h)。
- 官方发布包(rpm / deb / apk)在编译时就带了 --with-compat,并指定了 --modules-path=$libdir/tengine/modules(packages/build/configure-args.sh)。也就是说 load_module 指令本身在官方包上是可用的。
问题出在结构体布局。Tengine 在核心结构体中插入了一批默认开启的定制字段,例如 ngx_http_request_s 里就有 T_NGX_VARS、T_NGX_RET_CACHE、T_HTTP_UPSTREAM_TIMEOUT_VAR、T_NGX_HTTP_STAT_TIME、T_NGX_HTTP_SYSGUARD、T_NGX_MULTI_UPSTREAM、T_NGX_XQUIC 等条件成员(见 src/http/ngx_http_request.h,宏在 auto/modules 中无条件启用)。这些宏不参与 NGX_MODULE_SIGNATURE 的计算。
后果是最坏的一种组合:签名校验会通过,模块能被加载起来,但模块编译时看到的字段偏移和 Tengine 运行时的实际布局不一致,于是它读写的是错位的内存。表现不是启动时明确报错,而是运行一段时间后随机 segfault、或者取到脏数据、日志字段错乱。这种问题在压测和线上都很难定位。
因此以下来源的 .so 都不要混用到 Tengine 上:nginx.org 官方仓库的 nginx-module-otel、各 Linux 发行版打包的 otel 模块、NGINX Plus 提供的模块包。反过来也一样,Tengine 编译出的动态模块不要装到官方 nginx 上。
判断方法:先执行 tengine -V 看运行中二进制的完整 configure 参数。任何动态模块都必须用同一份源码、同一套 configure 参数编译出来,才允许加载。
二、如果确实要用,可行路径(需自行验证)
在同一台机器上准备与运行中二进制完全一致的 Tengine 源码和 configure 参数,追加 --add-dynamic-module 指向 nginx-otel 源码目录后编译。几个已知的注意点:
- nginx-otel 是 C++ 实现,依赖 gRPC / protobuf / opentelemetry-cpp,官方推荐走它自带的 CMake 流程,而该流程内部会去调用 nginx 的 configure。需要把源码路径指向 Tengine 源码树;如果它的 CMake 对目录名或版本号有断言,可能需要绕过,改成在 Tengine 源码树里直接用 --add-dynamic-module 编译模块目录。支持的 nginx 版本下限请以 nginx-otel 官方 README 为准,Tengine 3.2.0 对应的核心版本是 1.31.3,在版本号上是满足的。
- Tengine 默认开启 -Werror,第三方模块常会因为告警编译失败。可以临时加 --with-cc-opt="-Wno-error" 规避,但请把编译告警看一遍,其中可能就包含结构体或原型不匹配的线索。
- 编译完成后至少要做:tengine -t 配置校验、带真实流量的压测、观察是否产生 core dump。
- 尚未验证的交互点:Tengine 特有的链路 otel 模块并不认识,包括 multi_upstream、dubbo、xquic(HTTP/3)。如果你的场景开启了 xquic 或 mod_dubbo,我们不建议在生产环境上这么用。
三、当前可用的替代方案
如果目标只是「拿到链路追踪和指标」,不必依赖 otel 模块本身,下面几条都是 Tengine 自带能力:
- traceparent 透传与埋点:ngx_http_lua_module 是内置模块,可以在 rewrite / header_filter / log 阶段生成或透传 W3C traceparent 头,把 span 的实际上报交给下游服务或本机的 OTel Collector。这是改动最小、风险最低的做法。
- 日志转 span / metrics:用 $request_id 作为全链路 ID,配合 log_format 输出结构化访问日志,再由 OTel Collector 的 filelog receiver 采集转换。Tengine 额外提供了阶段耗时相关变量(T_NGX_HTTP_STAT_TIME、T_NGX_SSL_HANDSHAKE_TIME、T_NGX_REQUEST_START_TIME 等),可以直接打进日志。
- 指标:ngx_http_reqstat_module 可以输出按维度聚合的 QPS、延迟、状态码等,采集成本比逐请求 span 低很多。
- 如果整体架构里已经有 sidecar 或 mesh 层,把 tracing 放在那一层通常比在网关内做更省事。
四、需求收集
如果你有明确的落地诉求,欢迎在这个 issue 里补充场景信息,我们据此评估是否把 otel 支持排进后续版本(可能形式是提供官方兼容性验证结论,或直接内置一个模块):
- 是否必须由 Tengine 自身通过 OTLP 上报 span,还是透传 trace 上下文即可满足;
- 是否使用 HTTP/3(xquic)、mod_dubbo、multi_upstream 等 Tengine 特有能力;
- 部署形态是独立网关还是 Ingress,用的是官方包还是自行编译;
- 期望的后端是 OTel Collector、Jaeger 还是其它。
如果你已经在 Tengine 上试过编译 nginx-otel,无论成功还是失败,也欢迎把 configure 参数和报错贴上来,这对我们评估很有帮助。
我们想要接OpenTelemetry对tengine进行链路追踪,tengine是否支持nginx-otel插件?