Skip to content

feat(integrations): Add Elasticsearch integration#6793

Open
VihaanAgarwal wants to merge 1 commit into
getsentry:masterfrom
VihaanAgarwal:feat/elasticsearch-integration
Open

feat(integrations): Add Elasticsearch integration#6793
VihaanAgarwal wants to merge 1 commit into
getsentry:masterfrom
VihaanAgarwal:feat/elasticsearch-integration

Conversation

@VihaanAgarwal

Copy link
Copy Markdown

Description

Adds an ElasticsearchIntegration for elasticsearch-py, which #932 has been collecting requests for since 2020.

Both the sync and the async client funnel every API call through their class's perform_request, so the integration patches those two methods and covers the whole API surface with one seam. Each call gets a db span plus a query breadcrumb.

Design notes, happy to change any of these:

  • Spans are named after the API endpoint (search, bulk, indices.refresh) using the endpoint_id the client passes to perform_request since 8.12. On older clients the span name falls back to METHOD /path. Attributes are an include-list: db.system, db.operation, server.address/server.port, url.path, http.request.method, and db.elasticsearch.path_parts.* for the index/document id path parameters, following the OpenTelemetry Elasticsearch conventions.
  • The request body is only attached (as db.query.text) when send_default_pii is enabled, since search bodies routinely contain user data. Same treatment as query params in the other DB integrations.
  • server.address/server.port are only set when the client has exactly one configured node. With multiple nodes, only the transport layer knows which node actually served a request (it can also retry across nodes), so anything set at the client layer would be a guess.
  • The nested http.client spans from the stdlib integration are left alone. That matches how the HTTP-based AI integrations behave and keeps transport retries visible.
  • Minimum supported version is 8.0 (the 7.x client has been EOL for a while). The wrapper tolerates the pre-8.12 perform_request signature, which the test matrix verifies against 8.0.1.
  • Span streaming is supported, mirroring the clickhouse-driver integration.

Tests run against a real Elasticsearch single node like the other DB suites, so this also adds an elasticsearch service container to the DBs test group and wires up populate_tox/split_tox_gh_actions, with the generated tox.ini and workflow changes included. For local runs:

docker run -d -p 9200:9200 -e discovery.type=single-node -e xpack.security.enabled=false \
    docker.elastic.co/elasticsearch/elasticsearch:9.1.4

I'll follow up with the sentry-docs PR once this ships in a release.

Issues

Instrument the elasticsearch-py sync and async clients through
BaseClient.perform_request, which every API method funnels through.
Creates db spans named after the API endpoint, adds query breadcrumbs,
gates request bodies behind send_default_pii, and supports span
streaming.

Tests run against a real Elasticsearch node like the other DB suites,
so the DBs CI group gains an elasticsearch service container.
@VihaanAgarwal VihaanAgarwal requested a review from a team as a code owner July 9, 2026 20:46

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Want reviews to match your repository better? Bugbot Learning can learn team-specific rules from PR activity. A team admin can enable Learning in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 63524c4. Configure here.

try:
yield
finally:
span.end()

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Streamed spans miss error status

Medium Severity

When span streaming is enabled, _es_span ends the span with span.end() instead of exiting via the context manager. That path never sets SpanStatus.ERROR on exceptions, so failed Elasticsearch calls are recorded as successful spans.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 63524c4. Configure here.

Comment on lines +132 to +135
try:
yield
finally:
span.end()

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Bug: A failing Elasticsearch streaming operation does not mark its Sentry span as an error because span.end() is used instead of a with statement.
Severity: MEDIUM

Suggested Fix

Replace the try...finally block with a with sentry_sdk.start_span(...) as span: block for the streaming operation. This will ensure the span's __exit__ method is invoked with exception details, allowing it to correctly set the span status to 'error' upon failure.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.

Location: sentry_sdk/integrations/elasticsearch.py#L132-L135

Potential issue: When an Elasticsearch operation fails in the streaming path, the
associated Sentry span's status remains 'ok' instead of being set to 'error'. This
occurs because the code uses a `try...finally` block where `span.end()` is called in the
`finally` clause. The `span.end()` method does not receive information about exceptions
from the `try` block. In contrast, the non-streaming path correctly uses a `with
sentry_sdk.start_span(...)` block, which ensures the span's `__exit__` method is called
with exception details, allowing the status to be set correctly on failure.

Did we get this right? 👍 / 👎 to inform future reviews.

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.

Integration for elasticsearch

1 participant