Skip to content

Capture the Elasticsearch cluster name on OpenTelemetry spans from response headers - #1319

Merged
l-trotta merged 3 commits into
elastic:mainfrom
vagrawal-newrelic:feature/otel-cluster-name-discovery
Sep 9, 2026
Merged

l-trotta merged 3 commits into
elastic:mainfrom
vagrawal-newrelic:feature/otel-cluster-name-discovery

Conversation

@vagrawal-newrelic

@vagrawal-newrelic vagrawal-newrelic commented Aug 17, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Records the Elasticsearch cluster name on the client's OpenTelemetry spans as db.elasticsearch.cluster.name, read from the response headers. This gives spans an address-independent cluster identity, so telemetry can be correlated to the right cluster even behind a load balancer, proxy or node list — where server.address doesn't identify the cluster.

Resolves #1304.

What it does

In OpenTelemetryForElasticsearch, once the HTTP response is received, the cluster name is read from the response headers and stamped on the span, in this order of precedence:

  1. X-Found-Handling-Cluster — set by the Elastic Cloud proxy (canonical, globally-unique cluster id).
  2. Elastic-Cluster-Name — emitted by self-managed Elasticsearch when http.headers.cluster_name.enabled: true is set (added in Add cluster name header for onprem elasticsearch#157191, available in 9.6+).

If neither header is present, the attribute is simply not set. The capture is automatic (no configuration), makes no extra request, and never affects the actual request.

Why headers

Data-plane responses (_search, _bulk, …) never return cluster_name, and server.address reflects whichever node / load balancer / proxy the transport happened to hit — not the cluster's own identity. Reading the value the cluster itself stamps on the response is address-independent and works across all deployment topologies. This mirrors how the .NET client populates db.elasticsearch.cluster.name.

Testing

Extended OpenTelemetryForElasticsearchTest with full scenario coverage:

  • X-Found-Handling-Cluster only → captured
  • Elastic-Cluster-Name only → captured
  • both present → X-Found-Handling-Cluster wins (precedence)
  • neither present → attribute not set
  • empty X-Found-Handling-Cluster → falls back to Elastic-Cluster-Name
  • both headers empty → attribute not set

./gradlew check passes (checkstyle + tests).

Note

This replaces the earlier draft on this branch, which used an opt-in GET / active-discovery approach. Now that the server-side Elastic-Cluster-Name header has merged (elastic/elasticsearch#157191), the self-managed case is covered passively by a header too — so the active-discovery machinery is no longer needed, and the change is just the header read.

@cla-checker-service

cla-checker-service Bot commented Aug 17, 2026 •

Copy link
Copy Markdown

💚 CLA has been signed

@vagrawal-newrelic
vagrawal-newrelic force-pushed the feature/otel-cluster-name-discovery branch from effcdda to 85ae4b3 Compare September 8, 2026 16:24
@vagrawal-newrelic vagrawal-newrelic changed the title Capture the Elasticsearch cluster name on spans via a pluggable provider Capture the Elasticsearch cluster name on OpenTelemetry spans from response headers Sep 8, 2026
@vagrawal-newrelic
vagrawal-newrelic force-pushed the feature/otel-cluster-name-discovery branch 5 times, most recently from 873235a to e41949b Compare September 9, 2026 06:34
…se headers

Read the cluster name from the response headers and stamp it as db.elasticsearch.cluster.name on every client span: prefer the Elastic Cloud proxy header (X-Found-Handling-Cluster), and fall back to the Elastic-Cluster-Name header emitted by self-managed clusters (opt-in via http.headers.cluster_name.enabled). The capture is address-independent, so it survives load balancers and proxies, and needs no extra request.
Cover all scenarios in OpenTelemetryForElasticsearchTest: cloud header (X-Found-Handling-Cluster) only, on-prem header (Elastic-Cluster-Name) only, both present (cloud preferred), neither present, empty cloud header falling back to on-prem, and both headers empty (attribute not stamped).
@vagrawal-newrelic
vagrawal-newrelic force-pushed the feature/otel-cluster-name-discovery branch from e41949b to b558573 Compare September 9, 2026 06:48
@vagrawal-newrelic
vagrawal-newrelic marked this pull request as ready for review September 9, 2026 07:31
Comment on lines +63 to +69
## Capturing the {{es}} cluster name [opentelemetry-cluster-name]

The built-in instrumentation automatically records the `db.elasticsearch.cluster.name` span attribute when {{es}} includes the cluster name in its response headers. You do not need to configure the client.

To capture this attribute in self-managed {{es}} (version 9.6 and later), set `http.headers.cluster_name.enabled` to `true` on your cluster.


Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: we should document the difference between the on-prem and cloud value

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@l-trotta Thanks for the feedback! updated the docs to spell out the value in each case: the canonical globally-unique cluster id on Elastic Cloud (X-Found-Handling-Cluster) vs the configured cluster.name on self-managed (Elastic-Cluster-Name). Thanks!

Describe the db.elasticsearch.cluster.name span attribute captured from the X-Found-Handling-Cluster (Elastic Cloud) and Elastic-Cluster-Name (self-managed) response headers.
@vagrawal-newrelic
vagrawal-newrelic force-pushed the feature/otel-cluster-name-discovery branch from b558573 to dcc45b5 Compare September 9, 2026 10:46

@l-trotta l-trotta left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thank you so much! LGTM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add opt-in active discovery of cluster name to OpenTelemetry For Elasticsearch instrumentation.

2 participants