Sending OpenTelemetry traces to Elastic APM connects vendor-neutral instrumentation to the Elastic service inventory and trace waterfall. The common cloud path is to point an OTLP-capable SDK or Collector at the Elastic Cloud Managed OTLP endpoint and authenticate it with an API key that can write APM events.
Elastic Cloud Managed OTLP accepts application telemetry from SDKs and Collectors without a separate APM Server. Self-managed, ECE, and ECK clusters need an exposed OTLP-compatible gateway such as the EDOT Collector, because the managed endpoint is not available for those deployment types.
The sample service name checkout-api and trace operation GET /checkout keep the smoke test easy to find in Kibana. Replace the endpoint and API key with values from the Elastic setup screen, keep credentials out of source control, and confirm the generated trace ID in Observability → Applications before reusing the same settings for a production service.
Endpoint: https://checkout-prod.ingest.us-east-1.aws.elastic.cloud
Use the Ingest or Managed OTLP endpoint, not the Elasticsearch or Kibana endpoint. Elastic Cloud Hosted deployments need version 9.0 or later for the managed endpoint.
{
"otlp_writer": {
"applications": [
{
"application": "apm",
"resources": ["*"],
"privileges": ["event:write"]
}
]
}
}
Kibana and the OpenTelemetry setup wizard return the encoded key value. Keep the space after ApiKey when building the OTLP authorization header.
export OTEL_SERVICE_NAME="checkout-api" export OTEL_EXPORTER_OTLP_ENDPOINT="https://checkout-prod.ingest.us-east-1.aws.elastic.cloud" export OTEL_EXPORTER_OTLP_HEADERS="Authorization=ApiKey <encoded-api-key>" export OTEL_EXPORTER_OTLP_PROTOCOL="http/protobuf" export OTEL_TRACES_EXPORTER="otlp"
For OTLP/HTTP, OpenTelemetry SDKs send trace payloads to /v1/traces under the base endpoint.
$ python3 -m venv .otel-elastic-test
$ . .otel-elastic-test/bin/activate
$ python -m pip install opentelemetry-api opentelemetry-sdk opentelemetry-exporter-otlp-proto-http
import os from opentelemetry import trace from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter from opentelemetry.sdk.resources import Resource from opentelemetry.sdk.trace import TracerProvider from opentelemetry.sdk.trace.export import BatchSpanProcessor service_name = os.getenv("OTEL_SERVICE_NAME", "checkout-api") resource = Resource.create( { "service.name": service_name, "service.version": "1.0.0", "deployment.environment": "production", } ) provider = TracerProvider(resource=resource) provider.add_span_processor(BatchSpanProcessor(OTLPSpanExporter())) trace.set_tracer_provider(provider) tracer = trace.get_tracer("checkout-smoke") with tracer.start_as_current_span("GET /checkout") as span: span.set_attribute("http.request.method", "GET") span.set_attribute("url.path", "/checkout") span.set_attribute("http.response.status_code", 200) context = span.get_span_context() trace_id = f"{context.trace_id:032x}" span_id = f"{context.span_id:016x}" provider.shutdown() print(f"sent trace_id={trace_id} span_id={span_id} service.name={service_name}")
$ python send-checkout-trace.py sent trace_id=38857d40a5630e48dd3e4836ce5bfd31 span_id=ace2ff3f218a58eb service.name=checkout-api
The command exits after the OTLP exporter flushes the span. Authentication failures usually mean the header is missing ApiKey, the key was copied incorrectly, or the key lacks apm event:write privilege.
The service can take a minute to appear. Open the service and look for the printed trace ID or the GET /checkout operation in a trace sample.
Related: How to check an APM service in Kibana
$ python -m checkout_service
Use the command that normally starts the service for the chosen language or runtime. The service process must inherit the OTLP endpoint, authorization header, and service name.
$ deactivate $ rm -rf .otel-elastic-test send-checkout-trace.py