Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

elasticsearch: don't produce spans if native elasticsearch support is enabled #2524

Merged
merged 9 commits into from
May 24, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
([#2474](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2474))
- `opentelemetry-instrumentation-elasticsearch` Improved support for version 8
([#2420](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2420))
- `opentelemetry-instrumentation-elasticsearch` Disabling instrumentation with native OTel support enabled
([#2524](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2524))

## Version 1.24.0/0.45b0 (2024-03-28)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,14 @@
This library allows tracing HTTP elasticsearch made by the
`elasticsearch <https://elasticsearch-py.readthedocs.io/en/master/>`_ library.

.. warning::
The elasticsearch package got native OpenTelemetry support since version
`8.13 <https://www.elastic.co/guide/en/elasticsearch/client/python-api/current/release-notes.html#rn-8-13-0>`_.
To avoid duplicated tracing this instrumentation disables itself if it finds an elasticsearch client
that has OpenTelemetry support enabled.

Please be aware that the two libraries may use a different semantic convention.
xrmx marked this conversation as resolved.
Show resolved Hide resolved

Usage
-----

Expand Down Expand Up @@ -54,7 +62,7 @@ def response_hook(span: Span, response: dict)

for example:

.. code: python
.. code-block: python

from opentelemetry.instrumentation.elasticsearch import ElasticsearchInstrumentor
import elasticsearch
Expand All @@ -81,6 +89,7 @@ def response_hook(span, response):
"""

import re
import warnings
from logging import getLogger
from os import environ
from typing import Collection
Expand Down Expand Up @@ -197,6 +206,14 @@ def _wrap_perform_request(
):
# pylint: disable=R0912,R0914
def wrapper(wrapped, _, args, kwargs):
# if wrapped elasticsearch has native OTel instrumentation just call the wrapped function
otel_span = kwargs.get("otel_span")
if otel_span and otel_span.otel_span:
warnings.warn(
"Using native elasticsearch OTel instrumentation", Warning
xrmx marked this conversation as resolved.
Show resolved Hide resolved
)
return wrapped(*args, **kwargs)

method = url = None
try:
method, url, *_ = args
Expand Down Expand Up @@ -249,6 +266,11 @@ def normalize_kwargs(k, v):
v = str(v)
elif isinstance(v, elastic_transport.HttpHeaders):
v = dict(v)
elif isinstance(
v, elastic_transport.OpenTelemetrySpan
):
# the transport Span is always a dummy one
v = None
return (k, v)

hook_kwargs = dict(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
asgiref==3.7.2
attrs==23.2.0
Deprecated==1.2.14
elasticsearch==8.12.1
elasticsearch-dsl==8.12.0
elastic-transport==8.12.0
elasticsearch==8.13.1
elasticsearch-dsl==8.13.1
elastic-transport==8.13.0
importlib-metadata==6.11.0
iniconfig==2.0.0
packaging==23.2
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import elasticsearch.exceptions
from elasticsearch import Elasticsearch
from elasticsearch_dsl import Search
from pytest import mark

import opentelemetry.instrumentation.elasticsearch
from opentelemetry import trace
Expand All @@ -36,7 +37,7 @@

from . import sanitization_queries # pylint: disable=no-name-in-module

major_version = elasticsearch.VERSION[0]
major_version, minor_version = elasticsearch.VERSION[:2]

if major_version == 8:
from . import helpers_es8 as helpers # pylint: disable=no-name-in-module
Expand Down Expand Up @@ -70,6 +71,9 @@ def get_elasticsearch_client(*args, **kwargs):


@mock.patch(helpers.perform_request_mock_path)
@mock.patch.dict(
os.environ, {"OTEL_PYTHON_INSTRUMENTATION_ELASTICSEARCH_ENABLED": "false"}
)
class TestElasticsearchIntegration(TestBase):
search_attributes = {
SpanAttributes.DB_SYSTEM: "elasticsearch",
Expand Down Expand Up @@ -110,7 +114,6 @@ def test_instrumentor(self, request_mock):
span = spans_list[0]

# Check version and name in span's instrumentation info
# self.assertEqualSpanInstrumentationInfo(span, opentelemetry.instrumentation.elasticsearch)
self.assertEqualSpanInstrumentationInfo(
span, opentelemetry.instrumentation.elasticsearch
)
Expand Down Expand Up @@ -475,6 +478,7 @@ def request_hook(span, method, url, kwargs):
"headers": {
"accept": "application/vnd.elasticsearch+json; compatible-with=8"
},
"otel_span": None,
}
elif major_version == 7:
expected_kwargs = {
Expand Down Expand Up @@ -607,3 +611,30 @@ def test_bulk(self, request_mock):
self.assertEqualSpanInstrumentationInfo(
span, opentelemetry.instrumentation.elasticsearch
)

@mark.skipif(
(major_version, minor_version) < (8, 13),
reason="Native OTel since elasticsearch 8.13",
)
@mock.patch.dict(
os.environ,
{"OTEL_PYTHON_INSTRUMENTATION_ELASTICSEARCH_ENABLED": "true"},
)
def test_instrumentation_is_disabled_if_native_support_enabled(
self, request_mock
):
request_mock.return_value = helpers.mock_response("{}")

es = get_elasticsearch_client(hosts=["http://localhost:9200"])
es.index(
index="sw",
id=1,
**normalize_arguments(body={"name": "adam"}, doc_type="_doc"),
)

spans_list = self.get_finished_spans()
self.assertEqual(len(spans_list), 1)
span = spans_list[0]

# Check that name in span's instrumentation info is not from this instrumentation
self.assertEqual(span.instrumentation_info.name, "elasticsearch-api")
2 changes: 1 addition & 1 deletion tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ envlist =
; below mean these dependencies are being used:
; 0: elasticsearch-dsl==6.4.0 elasticsearch==6.8.2
; 1: elasticsearch-dsl==7.4.1 elasticsearch==7.17.9
; 2: elasticsearch-dsl>=8.0,<8.13 elasticsearch>=8.0,<8.13
; 2: elasticsearch-dsl==8.13.1 elasticsearch==8.13.1
xrmx marked this conversation as resolved.
Show resolved Hide resolved
py3{8,9,10,11}-test-instrumentation-elasticsearch-{0,1,2}
pypy3-test-instrumentation-elasticsearch-{0,1,2}
lint-instrumentation-elasticsearch
Expand Down
Loading