Skip to main content

OpenTelemetry

The opentelemetry plugin instruments APISIX and sends traces to OpenTelemetry collector based on the OpenTelemetry specification, in binary-encoded OTLP over HTTP.

Examples

The examples below demonstrate how you can work with the opentelemetry plugin for different scenarios.

Enable opentelemetry Plugin

In API7 Gateway, opentelemetry is available in Dashboard and Admin API by default. For APISIX deployments, load the plugin in the gateway static configuration before configuring routes that use it.

For APISIX host or Docker deployments, keep the existing plugin list in config.yaml and add opentelemetry:

config.yaml
plugins:
# Keep the complete plugin list used by your gateway.
- opentelemetry

Reload the gateway for changes to take effect.

Send Traces to OpenTelemetry

The following example demonstrates how to trace requests to a route and send traces to OpenTelemetry.

Start an OpenTelemetry collector instance:

docker run -d --name otel-collector -p 4318:4318 otel/opentelemetry-collector-contrib

The collector should start listening on 127.0.0.1:4318 (Docker) or otel-collector.aic.svc.cluster.local:4318 (Kubernetes). Configure the plugin metadata to set the collector address:

curl "http://127.0.0.1:9180/apisix/admin/plugin_metadata/opentelemetry" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"collector": {
"address": "127.0.0.1:4318"
}
}'

Create a route with opentelemetry plugin:

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

Send a request to the route:

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

You should receive an HTTP/1.1 200 OK response.

In OpenTelemetry collector's log, you should see information similar to the following:

2024-02-18T17:14:03.825Z 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(e34673e24631)
-> service.name: Str(APISIX)
ScopeSpans #0
ScopeSpans SchemaURL:
InstrumentationScope opentelemetry-lua
Span #0
Trace ID : fbd0a38d4ea4a128ff1a688197bc58b0
Parent ID :
ID : af3dc7642104748a
Name : GET /anything
Kind : Server
Start time : 2024-02-18 17:14:03.763244032 +0000 UTC
End time : 2024-02-18 17:14:03.920229888 +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/7.64.1)
-> apisix.route_id: Str(otel-tracing-route)
-> apisix.route_name: Empty()
-> apisix.response_source: Str(upstream)
-> http.route: Str(/anything)
-> http.status_code: Int(200)
{"kind": "exporter", "data_type": "traces", "name": "debug"}

To visualize these traces, you can export your telemetry to backend services, such as Zipkin and Prometheus. See exporters for more details.

In API7 Enterprise from version 3.9.10 and APISIX from version 3.17.0, each request span includes an apisix.response_source attribute that classifies the origin of the HTTP response:

  • apisix — the response was generated by APISIX itself, such as a plugin rejection, authentication failure, or route-not-found error.
  • nginx — the response was generated by the NGINX proxy layer, such as a connection refused or upstream timeout error.
  • upstream — the response came from the actual upstream service.

This attribute enables more precise error attribution in trace analysis, for example, distinguishing gateway-side rejections from real upstream errors.

Using Trace Variables in Logging

The following example demonstrates how to configure the opentelemetry plugin to set the following built-in variables, which can be used in logger plugins or access logs:

  • opentelemetry_context_traceparent: trace parent ID
  • opentelemetry_trace_id: trace ID of the current span
  • opentelemetry_span_id: span ID of the current span

Configure the plugin metadata to set set_ngx_var as true:

curl "http://127.0.0.1:9180/apisix/admin/plugin_metadata/opentelemetry" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"set_ngx_var": true
}'

After the OpenTelemetry collector is available, configure the gateway according to how it was deployed.

Add or update this section in the gateway configuration file to use the opentelemetry plugin variables:

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

access_log_format: customize the access log format to use the opentelemetry plugin variables.

Reload the gateway for configuration changes to take effect.

You should see access log entries similar to the following when you generate requests:

{"time": "18/Feb/2024:15:09:00 +0000","opentelemetry_context_traceparent": "00-fbd0a38d4ea4a128ff1a688197bc58b0-8f4b9d9970a02629-01","opentelemetry_trace_id": "fbd0a38d4ea4a128ff1a688197bc58b0","opentelemetry_span_id": "af3dc7642104748a","remote_addr": "172.10.0.1"}
API7.ai Logo

The digital world is connected by APIs,
API7.ai exists to make APIs more efficient, reliable, and secure.

Sign up for API7 newsletter

Product

API7 Gateway

SOC2 Type IIISO 27001HIPAAGDPRRed Herring

Copyright © APISEVEN PTE. LTD 2019 – 2026. Apache, Apache APISIX, APISIX, and associated open source project names are trademarks of the Apache Software Foundation