Skip to content

tengine是否支持nginx-otel插件 #2019

Description

@xiaojifan

我们想要接OpenTelemetry对tengine进行链路追踪,tengine是否支持nginx-otel插件?

Activity

  1. drawing commented on Mar 24, 2026

    @drawing
    Collaborator

    目前 tengine 官方尚未直接集成 nginx-otel 插件。nginx-otel 是一个独立的 Nginx 模块,理论上可以通过以下方式集成到 tengine:

    1. 源码编译集成: 将 nginx-otel 模块作为第三方模块编译进 tengine

      ./configure --add-module=/path/to/nginx-otel
    2. 动态模块加载 (如果 tengine 版本支持):

      load_module modules/ngx_http_otel_module.so;

    需要注意的是:

    • 确保 nginx-otel 版本与 tengine 的 Nginx 基础版本兼容
    • tengine 的一些定制模块可能与 otel 插件存在冲突,需要测试验证

    如果你有具体的集成需求或遇到问题,可以提供更多细节,我们可以协助排查。

  2. lianglli commented on Aug 1, 2026

    @lianglli
    Member

    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 源码目录后编译。几个已知的注意点:

    1. 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,在版本号上是满足的。
    2. Tengine 默认开启 -Werror,第三方模块常会因为告警编译失败。可以临时加 --with-cc-opt="-Wno-error" 规避,但请把编译告警看一遍,其中可能就包含结构体或原型不匹配的线索。
    3. 编译完成后至少要做:tengine -t 配置校验、带真实流量的压测、观察是否产生 core dump。
    4. 尚未验证的交互点: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 支持排进后续版本(可能形式是提供官方兼容性验证结论,或直接内置一个模块):

    1. 是否必须由 Tengine 自身通过 OTLP 上报 span,还是透传 trace 上下文即可满足;
    2. 是否使用 HTTP/3(xquic)、mod_dubbo、multi_upstream 等 Tengine 特有能力;
    3. 部署形态是独立网关还是 Ingress,用的是官方包还是自行编译;
    4. 期望的后端是 OTel Collector、Jaeger 还是其它。

    如果你已经在 Tengine 上试过编译 nginx-otel,无论成功还是失败,也欢迎把 configure 参数和报错贴上来,这对我们评估很有帮助。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions