Exporting telemetry from the OpenTelemetry Collector with OTLP forwards data from one Collector pipeline to another Collector, gateway, or vendor endpoint using OpenTelemetry's native protocol. Use this when applications send telemetry to a nearby Collector, but routing, batching, filtering, or final backend delivery happens somewhere else.
The exporter is declared under exporters and becomes active only when a service pipeline lists it. Current Collector configuration examples use otlp_grpc for the gRPC exporter, where the endpoint is a host and port such as otel-gateway:4317 rather than an HTTP URL.
The smoke test uses a local receiving Collector and an upstream Collector that prints received spans with the debug exporter. Plaintext gRPC is acceptable for the local proof because tls.insecure is explicit, but shared or production traffic should use verified TLS, credentials, network policy, and exporter retry settings before the pipeline carries real telemetry.
Related: How to configure an OTLP receiver in the OpenTelemetry Collector
Related: How to test OpenTelemetry Collector pipelines with the debug exporter
Related: How to secure OTLP traffic with TLS in the OpenTelemetry Collector
Related: How to configure retry and queue settings in the OpenTelemetry Collector
receivers: otlp: protocols: grpc: endpoint: 0.0.0.0:4317 exporters: debug: verbosity: detailed service: pipelines: traces: receivers: [otlp] exporters: [debug]
The upstream Collector represents the gateway or backend side of the handoff. The debug exporter is only for proving the export path before replacing the destination with the real backend.
$ otelcol validate --config=gateway.yaml
No output with a zero exit status means the file parsed and the referenced receiver, exporter, and pipeline are available in the Collector distribution.
$ otelcol --config=gateway.yaml 2026-06-18T07:31:12.859Z info Starting GRPC server component=otlp endpoint=[::]:4317 2026-06-18T07:31:12.859Z info Everything is ready. Begin running and processing data.
receivers: otlp: protocols: http: endpoint: 0.0.0.0:4318 exporters: otlp_grpc: endpoint: otel-gateway:4317 tls: insecure: true service: pipelines: traces: receivers: [otlp] exporters: [otlp_grpc]
tls.insecure: true disables transport verification for the local smoke test. Use TLS settings and credentials that match the upstream endpoint before exposing the exporter across a shared network.
The otlp_grpc exporter sends the trace pipeline to otel-gateway:4317. Add matching metrics or logs pipelines only for signals that should be forwarded to the same destination.
Tool: OpenTelemetry Collector Config Generator
$ otelcol validate --config=agent.yaml
$ otelcol --config=agent.yaml 2026-06-18T07:31:13.119Z info Starting HTTP server component=otlp endpoint=[::]:4318 2026-06-18T07:31:13.119Z info Everything is ready. Begin running and processing data.
{
"resourceSpans": [
{
"resource": {
"attributes": [
{
"key": "service.name",
"value": {
"stringValue": "checkout-api"
}
}
]
},
"scopeSpans": [
{
"scope": {
"name": "manual-otlp-export"
},
"spans": [
{
"traceId": "5b8efff798038103d269b633813fc60c",
"spanId": "eee19b7ec3c1b174",
"name": "otlp-export-smoke",
"kind": 1,
"startTimeUnixNano": "1717260000000000000",
"endTimeUnixNano": "1717260001000000000"
}
]
}
]
}
]
}
$ curl --silent --show-error --include --request POST http://127.0.0.1:4318/v1/traces \
--header 'Content-Type: application/json' \
--data @trace.json
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 21
{"partialSuccess":{}}
The 200 OK response confirms that the local Collector accepted the trace. The upstream log check confirms that the otlp_grpc exporter forwarded it.
$ journalctl -u otelcol-gateway --since "5 minutes ago"
Jun 18 07:31:15 host otelcol-gateway[1234]: Traces component=debug signal=traces resource_spans=1 spans=1
Resource attributes:
-> service.name: Str(checkout-api)
InstrumentationScope manual-otlp-export
Span #0
Trace ID : 5b8efff798038103d269b633813fc60c
ID : eee19b7ec3c1b174
Name : otlp-export-smoke
Status code : Unset
If the upstream Collector is running in the foreground, read the same debug exporter output from that terminal instead of journalctl. For a Docker test, use the gateway container logs.
$ rm trace.json
Stop the foreground Collectors with Ctrl+C when the local test is finished. Keep the exporter configuration only after replacing the local endpoint, plaintext TLS mode, and debug destination with the intended upstream settings.