OpenTelemetry
OpenTelemetry 是用于生成、收集和导出遥测数据的厂商中立可观测性框架。opentelemetry 插件对网关请求进行插桩,并通过 OTLP/HTTP 将采样后的链路以二进制 Protobuf 格式导出到 OpenTelemetry Collector。Collector 可以处理链路并将其转发到兼容的可观测性后端。
示例
下面的示例将配置链路导出,并把链路标识符写入网关访问日志。
启用插件
在 API7 网关中,opentelemetry 默认可通过 Dashboard 和 Admin API 使用。对于 APISIX 部署,在配置使用该插件的路由前,请先在网关静态配置中加载该插件。
- Host or Docker
- Kubernetes (Helm)
对于 APISIX 宿主机或 Docker 部署,请保留 config.yaml 中现有插件列表,并加入 opentelemetry:
plugins:
# 保留当前网关使用的完整插件列表。
- opentelemetry
重新加载网关以使更改生效。
对于 APISIX Helm Chart,apisix.plugins 会替换已加载插件列表。请从当前网关使用的完整插件列表开始,并加入 opentelemetry:
apisix:
plugins:
# 保留当前网关使用的完整插件列表。
- opentelemetry
API7 网关 Helm 部署在本节不需要修改 Helm values,可继续配置插件元数据和路由。
使用 APISIX Helm Chart 应用 values 文件。请将 <chart-version> 替换为已安装版本所使用的 Chart 版本:
helm upgrade <release-name> <chart-name> \
--version <chart-version> \
-n <namespace> \
-f values.yaml
将链路发送到 OpenTelemetry Collector
以下示例将链路发送到一个会把详细跨度数据写入容器日志的 OpenTelemetry Collector。
下面的 Collector 配置使用未启用身份认证或 TLS 的 debug exporter。生产环境中,请保护 Collector 端点,并为可观测性后端配置 exporter。
启动适用于当前环境的 Collector:
- Docker
- Kubernetes
创建 Collector 配置:
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
Collector 清单使用固定名称 otel-collector-config 和 otel-collector。应用前请确认这些名称尚未使用,或在整个清单中一致地替换它们。
apiVersion: v1
kind: ConfigMap
metadata:
namespace: aic
name: otel-collector-config
data:
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]
---
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: aic
name: otel-collector
spec:
replicas: 1
selector:
matchLabels:
app: otel-collector
template:
metadata:
labels:
app: otel-collector
spec:
containers:
- name: otel-collector
image: ghcr.io/open-telemetry/opentelemetry-collector-releases/opentelemetry-collector:0.160.0
args:
- "--config=/conf/config.yaml"
ports:
- name: otlp-http
containerPort: 4318
- name: health
containerPort: 13133
readinessProbe:
httpGet:
path: /
port: health
volumeMounts:
- name: config
mountPath: /conf
volumes:
- name: config
configMap:
name: otel-collector-config
---
apiVersion: v1
kind: Service
metadata:
namespace: aic
name: otel-collector
spec:
selector:
app: otel-collector
ports:
- name: otlp-http
port: 4318
targetPort: otlp-http
应用清单:
kubectl apply -f otel-collector.yaml
等待 Deployment 可用:
kubectl rollout status -n aic deployment/otel-collector
下面的配置选项卡将 APISIX Admin API 和 ADC 与 Docker Collector 配对,将 Ingress Controller 与 Kubernetes Collector 配对。对于 API7 网关,请使用 ADC,或按照配置分布式追踪完成托管 Admin API 工作流。若采用其它部署组合,请将地址替换为网关可访问的 OTLP/HTTP 端点。
使用 Collector 地址配置插件元数据:
- APISIX Admin API
- ADC
- Ingress Controller
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"
}
}'
将插件元数据添加到现有 ADC 配置中,使其它插件元数据保持在期望状态:
plugin_metadata:
opentelemetry:
resource:
service.name: APISIX
collector:
address: "otel-collector:4318"
预览插件元数据协调结果,确认其中没有非预期的更新或删除:
adc diff -f adc.yaml --include-resource-type plugin_metadata
同步已审查的配置:
adc sync -f adc.yaml --include-resource-type plugin_metadata
在现有完整的 GatewayProxy 清单中保持 spec.provider 和其它所有字段不变,然后添加或更新以下片段:
spec:
pluginMetadata:
opentelemetry:
resource:
service.name: APISIX
collector:
address: "otel-collector.aic.svc.cluster.local:4318"
通过常规 Kubernetes 或 GitOps 工作流应用完整清单。例如:
kubectl apply -f gateway-proxy.yaml
service.name 资源属性用于在链路后端中标识网关。请将 APISIX 替换为当前部署使用的服务名称。
创建一个带有 opentelemetry 插件的路由:
示例使用固定标识符 otel-tracing-route 和 httpbin。应用配置前,请确认这些标识符尚未使用,或在所有配置中一致地替换它们。
- APISIX Admin API
- ADC
- Ingress Controller
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
}
}
}'
将服务添加到现有 ADC 配置中,使其它服务保持在期望状态:
services:
- name: httpbin
routes:
- uris:
- /anything
name: otel-tracing-route
plugins:
opentelemetry:
sampler:
name: always_on
upstream:
type: roundrobin
nodes:
- host: httpbin.org
port: 80
weight: 1
预览服务协调结果,确认其中没有非预期的更新或删除:
adc diff -f adc.yaml --include-resource-type service
同步已审查的配置。资源类型过滤器也会让插件元数据保持不变:
adc sync -f adc.yaml --include-resource-type service
Kubernetes 路由清单使用固定名称,包括 httpbin-external-domain、otel-plugin-config 和 otel-route。请确认这些名称尚未使用,或在所选清单中一致地替换它们。
- Gateway API
- APISIX CRD
apiVersion: v1
kind: Service
metadata:
namespace: aic
name: httpbin-external-domain
spec:
type: ExternalName
externalName: httpbin.org
---
apiVersion: apisix.apache.org/v1alpha1
kind: PluginConfig
metadata:
namespace: aic
name: otel-plugin-config
spec:
plugins:
- name: opentelemetry
config:
sampler:
name: always_on
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: aic
name: otel-route
spec:
parentRefs:
- name: apisix
rules:
- matches:
- path:
type: PathPrefix
value: /anything
filters:
- type: ExtensionRef
extensionRef:
group: apisix.apache.org
kind: PluginConfig
name: otel-plugin-config
backendRefs:
- name: httpbin-external-domain
port: 80
apiVersion: apisix.apache.org/v2
kind: ApisixUpstream
metadata:
namespace: aic
name: httpbin-external-domain
spec:
ingressClassName: apisix
externalNodes:
- type: Domain
name: httpbin.org
---
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: aic
name: otel-route
spec:
ingressClassName: apisix
http:
- name: otel-route
match:
paths:
- /anything
upstreams:
- name: httpbin-external-domain
plugins:
- name: opentelemetry
enable: true
config:
sampler:
name: always_on
将配置应用到集群:
kubectl apply -f otel-ic.yaml
本示例中的 always_on 采样器会追踪每个请求。生产流量应选择符合所需链路覆盖率和开销的采样策略。
发送请求到该路由:
curl "http://127.0.0.1:9080/anything"
你应该收到 HTTP/1.1 200 OK 响应。
等待跨度导出,然后查看当前环境中的 Collector 日志:
- Docker
- Kubernetes
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
trace_ready=false
for attempt in $(seq 1 20); do
if kubectl logs --since=1m -n aic deployment/otel-collector | \
grep -q 'Name.*GET /anything'; then
trace_ready=true
break
fi
sleep 1
done
[ "$trace_ready" = true ]
kubectl logs --since=1m -n aic deployment/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:根据请求跨度上下文生成的 W3Ctraceparent值opentelemetry_trace_id:请求跨度的链路 IDopentelemetry_span_id:请求跨度的 Span ID
更新插件元数据以填充这些变量,同时保留 Collector 配置:
- APISIX Admin API
- ADC
- Ingress Controller
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
}'
更新现有 ADC 配置中的 opentelemetry 条目,同时保留其它插件元数据:
plugin_metadata:
opentelemetry:
resource:
service.name: APISIX
collector:
address: "otel-collector:4318"
set_ngx_var: true
预览插件元数据协调结果,确认其中没有非预期的删除:
adc diff -f adc.yaml --include-resource-type plugin_metadata
同步已审查的配置:
adc sync -f adc.yaml --include-resource-type plugin_metadata
在现有完整的 GatewayProxy 清单中保留 Collector 配置,并添加 set_ngx_var:
spec:
pluginMetadata:
opentelemetry:
resource:
service.name: APISIX
collector:
address: "otel-collector.aic.svc.cluster.local:4318"
set_ngx_var: true
通过常规 Kubernetes 或 GitOps 工作流应用完整清单。例如:
kubectl apply -f gateway-proxy.yaml
根据网关的部署方式配置访问日志格式。
- Host or Docker
- Kubernetes (Helm)
在网关配置文件中新增或更新以 下配置,以使用 opentelemetry 插件变量:
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
重新加载网关以使配置更改生效。
对于 Helm 部署,请更新用于渲染网关访问日志格式的 values,并保留 values 文件中的其他配置。
对于 APISIX Helm Chart,设置以下 values:
apisix:
nginx:
logs:
enableAccessLog: true
accessLogFormat: '{"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"}'
accessLogFormatEscape: json
对于 API7 网关 Helm Chart,设置以下 values:
logs:
enableAccessLog: true
accessLogFormat: '{"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"}'
accessLogFormatEscape: json
然后使用当前网关 release 对应的 Chart 应用 values 文件。请将 <chart-version> 替换为已安装版本使用的 Chart 版本:
helm upgrade <release-name> <chart-name> \
--version <chart-version> \
-n <namespace> \
-f values.yaml
通过已启用追踪的路由发送请求:
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"}