Sending Telemetry with OpenTelemetry's OTLP Exporter
Configure the OTLP exporter, choose gRPC or HTTP, and verify telemetry reaches your collector.
29 Jan 2026, 00:04 UTC

The missing spans problem
You add tracing to a service, redeploy, and open your observability backend. The dashboard is empty. The instrumentation code looks correct, and the application logs show no errors. What is missing is usually a verification step at the export layer: telemetry is being generated, but it never reaches a collector.
OpenTelemetry’s OTLP exporter is the officially supported protocol for sending traces, metrics, and logs to a collector. OTLP, or OpenTelemetry Protocol, packages telemetry into a single wire format so one exporter can handle multiple signal types. A collector is a standalone process that receives telemetry, applies sampling or filtering, and forwards it to a backend. This post explains how to configure the OTLP exporter, choose between gRPC and HTTP/JSON, and confirm that spans actually arrive.
What OTLP does and does not guarantee
OTLP standardizes the payload and transport, but it does not guarantee delivery by itself. The SDK’s batch span processor holds spans in memory and sends them in batches, which reduces network overhead compared with sending one request per span. W3C Trace Context is the built-in header format that lets a trace ID flow across service boundaries without extra code. Resource attributes are key-value tags—such as service.name and deployment.environment—attached to every telemetry item so you can filter by service or environment later.
OTLP does not encrypt traffic automatically. Whether encryption is used depends on the transport configuration and the collector’s settings.
gRPC versus HTTP/JSON
Most language SDKs offer OTLP over gRPC and over HTTP/JSON. The choice is mostly operational:
| Transport | Default port | Best suited for | Production consideration |
|---|---|---|---|
| gRPC with protobuf | 4317 | High-throughput services inside a trusted network | Enable TLS; some load balancers need explicit gRPC support |
| HTTP/JSON | 4318 | Sidecars, restricted firewalls, and quick debugging | Larger payloads and slightly higher CPU than binary protobuf |
Worked example: exporting spans from Python
This example assumes an OpenTelemetry Python SDK that includes the OTLP gRPC exporter package. Run the script from a terminal on the host where your application runs. Normal user permissions are sufficient; the only network requirement is outbound access to the collector port.
Install the exporter package before running:
pip install opentelemetry-sdk opentelemetry-exporter-otlp-proto-grpc
Then create a small script. Placeholders such as localhost:4317 should match your collector’s endpoint.
from opentelemetry import trace
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
from opentelemetry.sdk.resources import Resource
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
resource = Resource(attributes={
"service.name": "order-api",
"service.version": "1.0.0",
"deployment.environment": "staging",
})
provider = TracerProvider(resource=resource)
trace.set_tracer_provider(provider)
exporter = OTLPSpanExporter(endpoint="localhost:4317", insecure=True)
provider.add_span_processor(BatchSpanProcessor(exporter))
tracer = trace.get_tracer(__name__)
with tracer.start_as_current_span("checkout"):
# application work here
pass
Run the script:
python otlp_example.py
Verification: start an OpenTelemetry Collector locally with an OTLP receiver enabled, then run the script. Check the collector logs for successful export requests and confirm the span appears in the collector UI or backend. If the span does not appear, check the endpoint, firewall rules, and whether the collector is listening on the expected port. A wrong endpoint often causes silent data loss: the application logs no error, and no span arrives.
Risk: insecure=True disables TLS. Use it only for local testing. In production, configure TLS and authentication according to your collector’s documentation.
Limitations and what to monitor
- Batching reduces network calls but holds spans in memory. At very high span volume, monitor the application heap for pressure from the export queue.
- Misconfigured endpoints drop telemetry silently. Always verify with a local collector before relying on production export.
- gRPC traffic may be blocked or buffered by corporate proxies that do not understand HTTP/2. HTTP/JSON can be easier to route through standard middleboxes.
- Package names and API details vary by language SDK. Consult the documentation for the SDK version you use.
Rollback
Because adding an exporter changes what telemetry leaves the process, rollback is simple: remove the OTLPSpanExporter and BatchSpanProcessor lines, or unset the OTEL_EXPORTER_OTLP_ENDPOINT environment variable. The application returns to producing telemetry without exporting it.
Checklist before deploying
- Choose gRPC for internal throughput or HTTP/JSON for restrictive networks.
- Set the endpoint and enable TLS in production.
- Run a local collector and confirm a test span arrives.
- Monitor export queue size and memory usage under load.
OTLP is the pragmatic default for OpenTelemetry export, but it is not a set-and-forget setting. A five-minute verification with a local collector prevents hours of wondering why your traces are missing.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.