Grafana Tempo’s OTLP receivers are the gateway for your traces, and they’re surprisingly flexible, accepting data over both gRPC and HTTP.

Here’s Tempo receiving traces from an OpenTelemetry SDK running in a Python application:

from opentelemetry import trace, sdk
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
from opentelemetry.sdk.trace.resource import Resource
from opentelemetry.sdk.resources import SERVICE_NAME

# Configure the service name
resource = Resource(attributes={SERVICE_NAME: "my-python-app"})

# Initialize tracer
tracer_provider = sdk.trace.TracerProvider(resource=resource)
trace.set_tracer_provider(tracer_provider)

# Configure OTLP exporter (adjust host/port as needed for your Tempo setup)
# For gRPC:
otlp_exporter = OTLPSpanExporter(endpoint="localhost:4317")
# For HTTP:
# otlp_exporter = OTLPSpanExporter(endpoint="localhost:4318", insecure=True) # Use insecure=True for HTTP/1.1

# Add span processor to send spans to Tempo
span_processor = BatchSpanProcessor(otlp_exporter)
tracer_provider.add_span_processor(span_processor)

# Get a tracer and record a span
tracer = trace.get_tracer(__name__)

with tracer.start_as_current_span("my-operation"):
    print("Doing some work...")
    # Simulate work
    import time
    time.sleep(0.1)
    print("Work done.")

print("Trace sent to Tempo.")

This code snippet demonstrates how an OpenTelemetry SDK, in this case Python, can be configured to send trace data to Tempo. The OTLPSpanExporter is the key component, which can be pointed to Tempo’s OTLP gRPC endpoint (defaulting to port 4317) or its OTLP HTTP endpoint (defaulting to port 4318). The BatchSpanProcessor ensures that spans are collected and sent efficiently.

Tempo’s OTLP receivers are designed to be highly interoperable, acting as a compliant endpoint for the OpenTelemetry Protocol (OTLP). This means any application instrumented with an OpenTelemetry SDK, regardless of the language or framework, can send trace data to Tempo without needing specific Tempo agents or adapters. The protocol itself handles the serialization and transmission of trace data, making it a standardized way to get telemetry into your backend. Tempo listens on two primary ports for OTLP: 4317 for gRPC and 4318 for HTTP. Internally, Tempo uses these receivers to decode the OTLP messages and store the trace data. The choice between gRPC and HTTP often comes down to network infrastructure and preference; gRPC is generally more performant due to its use of Protocol Buffers and HTTP/2, while HTTP offers broader compatibility and easier debugging in some environments.

The magic behind Tempo’s OTLP ingestion lies in its ability to parse the OTLP protobuf messages. When data arrives via gRPC or HTTP, Tempo deserializes these messages, extracts the trace information (spans, trace IDs, span IDs, attributes, etc.), and then associates this data with its storage backend. It’s not just a dumb pipe; Tempo actively processes the OTLP structure to organize and index the traces for efficient querying later. The receivers are configured within Tempo’s tempo.yaml file, typically under the ingester or distributor sections depending on your deployment topology. For example, a basic configuration might look like this:

ingester:
  otlp:
    grpc:
      listen_addr: 0.0.0.0:4317
    http:
      listen_addr: 0.0.0.0:4318

This configuration tells Tempo to bind its OTLP gRPC receiver to all interfaces on port 4317 and its OTLP HTTP receiver to all interfaces on port 4318. These are the ports your OpenTelemetry SDKs will target.

What most people don’t realize is that the OTLP receiver in Tempo isn’t just passively listening; it actively performs validation and initial processing. It checks for malformed OTLP messages, ensures basic structural integrity, and can even perform some initial attribute manipulation or filtering if configured. This means that by the time the data hits Tempo’s internal storage, it’s already been somewhat standardized and validated by the OTLP receiver itself, simplifying downstream processing and ensuring data quality.

Understanding the OTLP receivers is crucial for setting up a robust tracing pipeline, as they are the first point of contact for all your trace data.

Want structured learning?

Take the full Tempo course →