Skip to content

[Discussion] Elasticsearch correlation gap: Spans (Java Agent) and Metrics (Collector) cannot correlate for self-managed clusters #19376

Closed

Description

@vagrawal-newrelic

Is your feature request related to a problem? Please describe.

When you monitor a self-managed Elasticsearch cluster with OpenTelemetry, the tracing spans and the metrics don't currently meet in the middle, and there's no clean way to join them without manual work.

The two signals identify the cluster differently:

  • The Collector's elasticsearchreceiver identifies a cluster by elasticsearch.cluster.name, because that's what Elasticsearch's monitoring APIs report.
  • The Java agent produces spans for the operations the application actually performs — _search, _bulk, and so on. Elasticsearch doesn't return the cluster name in the responses to those operations, so the cluster name never lands on the span.

The result is that the metric has a cluster name and the span doesn't, so there's no shared key to correlate a service's calls with the cluster they hit.

This looks structural rather than a misconfiguration:

  • The agent is passive by design — it records the operations the application makes and doesn't issue its own calls to learn about the cluster. That's the correct default, but it means the cluster identity is only ever observed if the application itself happens to query the cluster's info endpoints, which most applications never do.
  • Managed/hosted Elasticsearch carries extra metadata on its responses that lets the cluster name reach the span, so hosted users may never see this gap. Self-managed deployments get none of that, and self-managed is likely a large share of real-world usage.

Anyone running self-managed Elasticsearch who wants to see which service is calling which cluster, or to scope dashboards and alerts per cluster, runs into this.

Describe the solution you'd like

I would like to propose introducing opt-in active discovery for the Elasticsearch instrumentation.

Specifically, an explicit, off-by-default configuration flag (e.g., otel.instrumentation.elasticsearch.experimental.active-discovery=true) that permits the Java agent to make a single, lightweight HTTP GET / call at client initialization to retrieve the cluster_name.

The execution flow would look like this:

  1. Trigger: The application initializes an Elasticsearch client (e.g., RestClient or ElasticsearchClient).
  2. Discovery Call: If the opt-in flag is enabled, the instrumentation intercepts the initialization and makes a single GET / request against the configured Elasticsearch endpoint.
  3. Extraction: The agent parses the standard JSON response to extract the cluster_name field.
  4. Caching & Injection: The agent caches this string in memory, tethered to that specific client instance. For all subsequent data-plane operations (_search, _bulk, etc.) made by that client, the agent automatically injects elasticsearch.cluster.name (or db.elasticsearch.cluster.name) into the span attributes.

Because it is strictly opt-in, it respects the default passive nature of the agent for standard users. For users running self-managed clusters who enable it, it guarantees the cluster identity is present on every span, matching the Collector's metrics perfectly.

Describe alternatives you've considered

  • Picking the cluster name up passively from a normal request. In principle, the name could reach a span if the application queried the cluster's root endpoint. In practice, applications mostly just search and write, so if the app never asks the cluster about itself, there is nothing to observe.
  • Correlating on network identity (server.address) in the OpenTelemetry Collector. It is conceptually possible to use a transform to align the metric's host/port with the span's server.address. However, this breaks as soon as there is a load balancer, proxy, or container network in the path, which describes most production setups. The IPs and hostnames simply won't match on both sides.
  • Manual logical tagging (e.g., db.namespace). We could manually inject a hardcoded tag via environment variables on both the APM side and the Collector side to force a match. However, APM and Infrastructure are usually managed by entirely different teams. Forcing siloed teams to coordinate and maintain hardcoded strings across their respective configurations is organizational friction and defeats the purpose of "out-of-the-box" observability.

Additional context

This is a case where the passive-instrumentation model and the way a backend's identity is exposed don't line up, and the correlation between an OTel APM agent and the matching OTel Collector receiver quietly degrades for self-managed users. I'd appreciate the maintainers' read on introducing an opt-in GET / initialization call to bridge this gap.

Tip

React with 👍 to help prioritize this issue. Please use comments to provide useful context, avoiding +1 or me too, to help us triage it. Learn more here.

Activity

  1. laurit commented on Aug 4, 2026

    @laurit
    Contributor

    co.elastic.clients:elasticsearch-java contains built-in instrumentations since 8.10 so for ElasticsearchClient you may need to take this up with elastic folks cc @AlexanderWert.

  2. trask commented on Aug 4, 2026

    @trask
    Member
  3. vagrawal-newrelic commented on Aug 4, 2026

    @vagrawal-newrelic
    Author

    Thanks @laurit and @trask (and @jackshirazi @SylvainJuge @JonasKunz for taking a look)
    I've opened the same request against that repo, with the specifics of what's
    currently captured vs. missing: (elastic/elasticsearch-java#1304)

    Leaving this issue open/linked in case there's a piece that still belongs here (e.g.
    if any coordination with the OTel semantic-conventions side is needed), but the actual
    implementation would live in elasticsearch-java. Will report back here once there's
    movement on that side.

  4. SylvainJuge commented on Sep 14, 2026

    @SylvainJuge
    Contributor

    We can now close this as there isn't anything left to do in instrumentation

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestneeds triageNew issue that requires triage

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions