跳到主要内容

OpenTelemetry

OpenTelemetry 是用于生成、收集和导出遥测数据的厂商中立可观测性框架。opentelemetry 插件对网关请求进行插桩,并通过 OTLP/HTTP 将采样后的链路以二进制 Protobuf 格式导出到 OpenTelemetry Collector。Collector 可以处理链路并将其转发到兼容的可观测性后端。

示例​

下面的示例将配置链路导出,并把链路标识符写入网关访问日志。

启用插件​

在 API7 网关中,opentelemetry 默认可通过 Dashboard 和 Admin API 使用。对于 APISIX 部署,在配置使用该插件的路由前,请先在网关静态配置中加载该插件。

对于 APISIX 宿主机或 Docker 部署,请保留 config.yaml 中现有插件列表,并加入 opentelemetry:

config.yaml
plugins:
# 保留当前网关使用的完整插件列表。
- opentelemetry

重新加载网关以使更改生效。

将链路发送到 OpenTelemetry Collector​

以下示例将链路发送到一个会把详细跨度数据写入容器日志的 OpenTelemetry Collector。

本地评估环境

下面的 Collector 配置使用未启用身份认证或 TLS 的 debug exporter。生产环境中,请保护 Collector 端点,并为可观测性后端配置 exporter。

启动适用于当前环境的 Collector:

创建 Collector 配置:

otel-collector-config.yaml
receivers:
otlp:
protocols:
http:
endpoint: 0.0.0.0:4318

exporters:
debug:
verbosity: detailed

extensions:
health_check:
endpoint: 0.0.0.0:13133

service:
extensions: [health_check]
pipelines:
traces:
receivers: [otlp]
exporters: [debug]

将 GATEWAY_CONTAINER 设置为正在运行的 APISIX 或 API7 网关容器名称。创建专用网络并将网关接入该网络:

export GATEWAY_CONTAINER=replace-with-gateway-container-name

docker network create gateway-otel-net
docker network connect gateway-otel-net "$GATEWAY_CONTAINER"

在同一网络中启动 Collector,并且只在回环接口上公开其健康检查端点:

docker run -d --name otel-collector \
--network gateway-otel-net \
-p 127.0.0.1:13133:13133 \
-v "$PWD/otel-collector-config.yaml:/etc/otelcol/config.yaml:ro" \
ghcr.io/open-telemetry/opentelemetry-collector-releases/opentelemetry-collector:0.160.0

等待 Collector 就绪:

until curl -fsS "http://127.0.0.1:13133/" > /dev/null; do
sleep 1
done

下面的配置选项卡将 APISIX Admin API 和 ADC 与 Docker Collector 配对,将 Ingress Controller 与 Kubernetes Collector 配对。对于 API7 网关,请使用 ADC,或按照配置分布式追踪完成托管 Admin API 工作流。若采用其它部署组合,请将地址替换为网关可访问的 OTLP/HTTP 端点。

使用 Collector 地址配置插件元数据:

curl "http://127.0.0.1:9180/apisix/admin/plugin_metadata/opentelemetry" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"resource": {
"service.name": "APISIX"
},
"collector": {
"address": "otel-collector:4318"
}
}'

service.name 资源属性用于在链路后端中标识网关。请将 APISIX 替换为当前部署使用的服务名称。

创建一个带有 opentelemetry 插件的路由:

示例使用固定标识符 otel-tracing-route 和 httpbin。应用配置前,请确认这些标识符尚未使用,或在所有配置中一致地替换它们。

curl "http://127.0.0.1:9180/apisix/admin/routes/otel-tracing-route" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"uri": "/anything",
"plugins": {
"opentelemetry": {
"sampler": {
"name": "always_on"
}
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org": 1
}
}
}'

本示例中的 always_on 采样器会追踪每个请求。生产流量应选择符合所需链路覆盖率和开销的采样策略。

发送请求到该路由:

curl "http://127.0.0.1:9080/anything"

你应该收到 HTTP/1.1 200 OK 响应。

等待跨度导出,然后查看当前环境中的 Collector 日志:

trace_ready=false
for attempt in $(seq 1 20); do
if docker logs --since 1m otel-collector 2>&1 | \
grep -q 'Name.*GET /anything'; then
trace_ready=true
break
fi
sleep 1
done
[ "$trace_ready" = true ]

docker logs --since 1m otel-collector

日志应包含类似以下的跨度信息:

2026-09-15T06:44:59.753Z info ResourceSpans #0
Resource SchemaURL:
Resource attributes:
-> telemetry.sdk.language: Str(lua)
-> telemetry.sdk.name: Str(opentelemetry-lua)
-> telemetry.sdk.version: Str(0.1.1)
-> hostname: Str(9b3ccdfa09dc)
-> service.name: Str(APISIX)
ScopeSpans #0
ScopeSpans SchemaURL:
InstrumentationScope opentelemetry-lua
Span #0
Trace ID : 224f7d84b4f77125b22f5d9a601021dc
Parent ID :
ID : c5597cecf6ba7128
Name : GET /anything
Kind : Server
Start time : 2026-09-15 06:44:52.040692992 +0000 UTC
End time : 2026-09-15 06:44:53.746045952 +0000 UTC
Status code : Unset
Status message :
Attributes:
-> net.host.name: Str(127.0.0.1)
-> http.method: Str(GET)
-> http.scheme: Str(http)
-> http.target: Str(/anything)
-> http.user_agent: Str(curl/8.7.1)
-> http.request.method: Str(GET)
-> url.scheme: Str(http)
-> url.path: Str(/anything)
-> user_agent.original: Str(curl/8.7.1)
-> apisix.route_id: Str(otel-tracing-route)
-> apisix.route_name: Empty()
-> http.route: Str(/anything)
-> apisix.response_source: Str(upstream)
-> http.status_code: Int(200)
-> http.response.status_code: Int(200)

要可视化链路,请为 Collector 配置 Jaeger、Zipkin 或 Grafana Tempo 等追踪后端的 exporter。可用选项请参阅 OpenTelemetry exporter 文档。

apisix.response_source 属性自 API7 企业版 3.9.10 和 APISIX 3.17.0 起提供,用于分类 HTTP 响应来源:

  • apisix:响应由网关生成,例如插件拒绝、身份认证失败或未找到路由。
  • nginx:响应由 NGINX 代理层生成,例如连接被拒绝或上游超时。
  • upstream:响应来自上游服务。

此属性可在追踪分析中实现更精确的错误归因,例如区分网关侧拒绝和真实的上游错误。

在日志中使用链路变量​

本示例沿用将链路发送到 OpenTelemetry Collector中配置的 Collector 和 /anything 路由。

插件可以填充以下内置变量,供日志插件和访问日志使用:

  • opentelemetry_context_traceparent:根据请求跨度上下文生成的 W3C traceparent 值
  • opentelemetry_trace_id:请求跨度的链路 ID
  • opentelemetry_span_id:请求跨度的 Span ID

更新插件元数据以填充这些变量,同时保留 Collector 配置:

curl "http://127.0.0.1:9180/apisix/admin/plugin_metadata/opentelemetry" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"resource": {
"service.name": "APISIX"
},
"collector": {
"address": "otel-collector:4318"
},
"set_ngx_var": true
}'

根据网关的部署方式配置访问日志格式。

在网关配置文件中新增或更新以下配置,以使用 opentelemetry 插件变量:

config.yaml
nginx_config:
http:
enable_access_log: true
access_log_format: '{"time": "$time_iso8601","opentelemetry_context_traceparent": "$opentelemetry_context_traceparent","opentelemetry_trace_id": "$opentelemetry_trace_id","opentelemetry_span_id": "$opentelemetry_span_id","remote_addr": "$remote_addr"}'
access_log_format_escape: json

重新加载网关以使配置更改生效。

通过已启用追踪的路由发送请求:

curl "http://127.0.0.1:9080/anything"

你应该看到类似以下的访问日志条目:

{"time": "2026-09-15T07:03:11+00:00","opentelemetry_context_traceparent": "00-d5698166ff3e63b6717fa57d8aebcce0-12b2f5c59eb9d2e3-01","opentelemetry_trace_id": "d5698166ff3e63b6717fa57d8aebcce0","opentelemetry_span_id": "12b2f5c59eb9d2e3","remote_addr": "192.168.158.1"}