Elasticsearch OTLP/HTTP endpoint

The Elasticsearch OTLP/HTTP endpoint is a native ingest API, like the bulk API. It accepts OpenTelemetry Protocol (OTLP) requests on the same host and port as the other Elasticsearch APIs, under the /_otlp path, and writes the records to data streams as they are received. The endpoint does not run the elasticapm processor or elasticapm connector: traces are not enriched, no aggregated APM metrics are produced, and APM views that depend on them, such as the service inventory and service map, stay empty.

The intended client for this endpoint is a gateway Collector, not an application. How you send OpenTelemetry data to Elasticsearch depends on your deployment type:

  • On Elastic Cloud Hosted and Elastic Cloud Serverless, use the Elastic Cloud Managed OTLP Endpoint rather than /_otlp. The Elastic Cloud Managed OTLP Endpoint is a separate ingestion host, and it enriches traces and produces aggregated APM metrics.
  • On self-managed, Elastic Cloud Enterprise, and Elastic Cloud on Kubernetes deployments, send application data to an Elastic Agent in Gateway mode. The gateway runs the elasticapm processor and connector, then writes the enriched result to Elasticsearch, either to /_otlp or through the Elasticsearch exporter.

The Elasticsearch OTLP/HTTP endpoint exposes three signal-specific paths:

Signal Path Availability
Metrics /_otlp/v1/metrics
Logs /_otlp/v1/logs
Traces /_otlp/v1/traces

/_otlp/v1/traces stores spans as they are received: it does not run the elasticapm processor or connector, so traces ingested through it are not enriched and produce no aggregated APM metrics.

Important

Elasticsearch only supports OTLP/HTTP, not OTLP/gRPC.

For most users, one of the following higher-level ingestion paths is recommended:

Deployment Recommended ingestion path
Elastic Cloud Hosted and Serverless Elastic Cloud Managed OTLP Endpoint
Elastic Cloud Enterprise, Elastic Cloud on Kubernetes, and self-managed Elastic Agent in Gateway mode, which runs the elasticapm processor and connector before writing to Elasticsearch

Use Elastic Cloud Managed OTLP Endpoint if it's available in your deployment, even when an application can target the Elasticsearch OTLP endpoint directly.

For an overview of the recommended OpenTelemetry-based ingestion architecture, refer to the Elastic OpenTelemetry reference architecture.

Use the Elasticsearch OTLP endpoint directly only in the following cases:

  • You operate a self-managed OpenTelemetry Collector gateway that runs the elasticapm processor and connector, and you prefer the OTLP/HTTP exporter over the Elasticsearch exporter to send data from the gateway to Elasticsearch. The Elasticsearch exporter writes through the bulk API and the OTLP/HTTP exporter writes to /_otlp. Run the elasticapm processor and connector in the gateway pipeline before whichever exporter you choose.
  • You build a development-only setup in which an application SDK sends OTLP data straight to the cluster. Traces sent this way are stored without elasticapm enrichment or aggregated APM metrics, so the APM views that depend on them stay empty.
Warning

Don't send telemetry from applications or pods directly to /_otlp. As with the bulk API, each client opens its own connections to Elasticsearch and sends its own small batches. Many direct clients mean many connections and many small requests, which Elasticsearch handles less efficiently than a few connections carrying larger batches.

Send telemetry to a gateway Collector or to the Elastic Cloud Managed OTLP Endpoint instead. A gateway Collector combines data from many clients into larger batches and writes them to /_otlp over a small number of connections. This limit is about the number of connections to Elasticsearch, not the number of applications you monitor.

Compared to the bulk API, ingesting through OTLP offers:

  • Improved ingestion performance, especially for payloads with many resource attributes.
  • Simplified mapping: data streams, index templates, dimensions, and metrics are derived dynamically from OTLP metadata. There's no need to set them up manually.

Authenticate to the Elasticsearch OTLP endpoint with an API key.

On Elastic Cloud Hosted and Serverless, send OTLP data to the Elastic Cloud Managed OTLP Endpoint instead of to /_otlp, and authenticate with an API key as described in Elastic Cloud Managed OTLP Endpoint authentication.

On self-managed, Elastic Cloud Enterprise, and Elastic Cloud on Kubernetes deployments, refer to the API key documentation for your deployment type for instructions on how to create one:

The API key needs create_doc and auto_configure privileges on the data stream patterns it writes to. create_doc allows writing documents without overwriting existing ones. auto_configure allows the endpoint to create the target data streams on first write.

The minimum index patterns depend on which signals you ingest:

Signals ingested Required names patterns
Metrics metrics-*
Logs logs-*
Traces traces-*, logs-*
All three metrics-*, logs-*, traces-*

Traces ingestion also writes span events to logs-* data streams, so it requires both patterns.

For example, an API key role descriptor that allows ingesting all three signals:

{
  "indices": [
    {
      "names": ["logs-*", "metrics-*", "traces-*"],
      "privileges": ["create_doc", "auto_configure"]
    }
  ]
}
		

To send data from an OpenTelemetry Collector to an Elasticsearch OTLP endpoint, configure the OTLP/HTTP exporter:

exporters:
  otlphttp/elasticsearch:
    endpoint: <es_endpoint>/_otlp
    headers:
      Authorization: "ApiKey <api_key>"
    sending_queue:
      enabled: true
      sizer: bytes
      queue_size: 50_000_000
      block_on_overflow: true
      batch:
        flush_timeout: 1s
        min_size: 1_000_000
        max_size: 4_000_000
service:
  pipelines:
    logs:
      exporters: [otlphttp/elasticsearch]
      receivers: ...
    traces:
      exporters: [otlphttp/elasticsearch]
      receivers: ...
    metrics:
      exporters: [otlphttp/elasticsearch]
      receivers: ...
		
  1. Sizes the queue and batches by uncompressed bytes.
  2. Limits the queue to 50 MB of uncompressed data. Increasing this value can absorb longer Elasticsearch outages or traffic bursts, but also increases Collector memory usage.
  3. Controls the uncompressed batch size sent to Elasticsearch. In this example, batches are sent at 1 MB and capped at 4 MB. Larger batches reduce request overhead, but increase peak memory usage and the amount of data retried after a failed request.

The exporter appends the signal-specific path (/v1/logs, /v1/traces, /v1/metrics) to the configured endpoint.

To ingest enriched traces and aggregated APM metrics, run the elasticapm processor and connector in the pipeline before this exporter, as Elastic Agent in Gateway mode does.

These values are starting points for a gateway Collector. Tune them for your workload and Collector resources. They are local to each Collector instance and don't increase Elasticsearch ingest capacity. If many applications need to send telemetry, scale out the gateway Collector instead of sending directly from each application.

Supported compression values are gzip (the OTLP/HTTP exporter default) and none.

In development-only setups, you can send data from a custom application by pointing the OTLP/HTTP exporter of an OpenTelemetry language SDK at the corresponding Elasticsearch OTLP endpoint path. Traces sent this way are stored without elasticapm enrichment or aggregated APM metrics, so the APM views that depend on them stay empty. In production, point SDKs at a gateway Collector or at the Elastic Cloud Managed OTLP Endpoint.

Note

Only encoding: proto is supported, which the OTLP/HTTP exporter uses by default.

By default, records are written to the following data streams:

Signal Default data stream
Logs logs-generic.otel-default
Traces traces-generic.otel-default
Metrics metrics-generic.otel-default

For more about how OTLP metrics are stored as time series data streams, refer to Ingest metrics into a TSDS using the OTLP/HTTP endpoint.

The target data stream name follows the pattern <type>-<dataset>.otel-<namespace>. You can influence dataset and namespace by setting attributes on your data:

  • Set data_stream.dataset and/or data_stream.namespace as attributes. Precedence: data point or log record attribute, then scope attribute, then resource attribute.
  • Otherwise, if the scope name contains /receiver/<somereceiver>, data_stream.dataset is set to the receiver name.
  • Otherwise, data_stream.dataset falls back to generic and data_stream.namespace falls back to default.

Examples:

Signal Attributes or scope name Target data stream
Logs data_stream.dataset: nginx.access, data_stream.namespace: prod logs-nginx.access.otel-prod
Traces data_stream.dataset: checkout, data_stream.namespace: staging traces-checkout.otel-staging
Metrics Scope name contains /receiver/hostmetrics, no data_stream.* attributes metrics-hostmetrics.otel-default
Metrics No matching attributes or receiver scope name metrics-generic.otel-default

You can configure how OTLP histogram metrics are mapped using the xpack.otel_data.histogram_field_type cluster setting. Valid values are:

  • histogram (default on ): Map histograms as T-Digests using the histogram field type
  • exponential_histogram (default on ): Map histograms as exponential histograms using the exponential_histogram field type

The setting is dynamic and can be updated at runtime:

				PUT /_cluster/settings
					{
  "persistent" : {
    "xpack.otel_data.histogram_field_type" : "exponential_histogram"
  }
}
		

Because both histogram and exponential_histogram support coerce, changing this setting dynamically does not risk mapping conflicts or ingestion failures.

This setting only applies to metrics ingested through the Elasticsearch OTLP endpoint. Documents ingested using the bulk API (for example through the Elasticsearch exporter for the OpenTelemetry Collector) are not affected.

The OTLP endpoint preserves the temporality of ingested metrics and stores it in a temporality dimension. This allows Elasticsearch to correctly interpret counter and histogram values during ES|QL time series queries and downsampling.

The temporality dimension is set automatically based on the OTLP AggregationTemporality of each metric data point. No additional configuration is needed.

Note that cumulative temporality for histograms is only supported if xpack.otel_data.histogram_field_type is set to exponential_histogram (which is the default).

  • Trace enrichment and APM metrics: The endpoint does not run the elasticapm processor or connector. Traces are stored as received, no aggregated APM metrics are produced, and the APM views that depend on them, such as the service inventory and service map, stay empty. For the full APM experience, send traces to the Elastic Cloud Managed OTLP Endpoint or through an Elastic Agent in Gateway mode.
  • Delivery guarantees: Elasticsearch can only acknowledge an OTLP request as a whole, not on a per-record basis. If part of a request fails, the client retries the entire batch, which can produce duplicate logs or trace spans. Metrics are not affected because metric points written to time series data streams are deduplicated based on their dimensions and timestamp.
  • Profiles: Profiles are not supported. To ingest profiles, use a distribution of the OpenTelemetry Collector that includes the Elasticsearch exporter, such as Elastic Agent.
  • Exemplars: Exemplars are not supported yet.