OpenTelemetry export¶
The native_observability_otel submodule provides the OTLP push exporter. It is part of the INTEGRATIONS preset (drush no:preset:integrations), which also enables native_observability_eca_bridge.
Routes¶
| Route | Path | Permission |
|---|---|---|
native_observability_otel.settings |
/admin/config/development/native-observability/settings/otel |
administer native observability otel |
OTLP settings¶
NativeObservabilityOtelSettingsForm configures the push-side exporter: enable/disable, the OTLP HTTP endpoint, request timeout, service name/namespace/version, and additional HTTP headers sent on every export request. Current defaults are documented in Configuration.
The Prometheus scrape endpoint and its bearer token live in the separate native_observability_export module; see Prometheus and Elastic export.
Exporter plugins¶
Exporters implement ExporterInterface and are discovered through the NativeObservabilityExporter attribute (namespace Drupal\native_observability_otel\Plugin\NativeObservabilityExporter), managed by ExporterManager and exposed through the native_observability_otel.exporter_registry service. Three plugins ship with the module:
| Plugin ID | Class | Role |
|---|---|---|
opentelemetry |
OpenTelemetryExporter |
Pushes each completed request trace to the configured OTLP HTTP endpoint |
prometheus |
PrometheusExporter |
No-op export(). Registers Prometheus in the plugin list because scraping is pull-based, not pushed by this subsystem |
null_exporter |
NullExporter |
No-op exporter used to validate exporter discovery |
OpenTelemetryTraceSubscriber always resolves the opentelemetry plugin ID through the registry; there is no settings field to switch the active exporter. The plugin type exists as an extension point: a custom module can register an additional NativeObservabilityExporter plugin and call it through ExporterRegistry::get() or ExporterRegistry::getAvailableExporters().
flowchart LR
A[kernel.response] --> B[OpenTelemetryTraceSubscriber]
B --> C{Own route excluded?}
C -- yes --> Z[No export]
C -- no --> D[ExporterRegistry.get 'opentelemetry']
D --> E{Exporter available?}
E -- no, disabled or empty endpoint --> Z
E -- yes --> F[OpenTelemetryPayloadBuilder]
F --> G[POST OTLP endpoint]
OTLP bearer token¶
When the collector requires authentication, generate and store the collector token with Drush:
drush native_observability:token:generate otlp
# alias:
drush no:token:generate otlp
The command prints the generated value once and stores it in the state key native_observability_otel.otlp_bearer_token. OpenTelemetryExporter reads it and sends Authorization: Bearer <token> on every OTLP export request. The token field on the settings form is write-only: an empty submission keeps the current token, and the sentinel value __clear__ removes it. For collectors that expect a different header name, use the Additional HTTP headers field instead.
Example target: OTLP collector or Tempo¶
drush config:set native_observability_otel.settings endpoint 'http://collector:4318/v1/traces' -y
drush config:set native_observability_otel.settings enabled true -y
A Grafana Alloy collector forwarding to Tempo needs a matching OTLP HTTP receiver, for example a otelcol.receiver.otlp block listening on 4318 with the http protocol enabled, exporting to otelcol.exporter.otlp pointed at Tempo's gRPC or HTTP ingest port.