Skip to content

Commit 71e83ef

Browse files
authored
Merge branch 'main' into main
2 parents 3cb4da1 + eb8e456 commit 71e83ef

File tree

5 files changed

+66
-7
lines changed

5 files changed

+66
-7
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
5656
([#2474](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2474))
5757
- `opentelemetry-instrumentation-elasticsearch` Improved support for version 8
5858
([#2420](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2420))
59+
- `opentelemetry-instrumentation-elasticsearch` Disabling instrumentation with native OTel support enabled
60+
([#2524](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2524))
5961
- `opentelemetry-instrumentation-asyncio` Check for __name__ attribute in the coroutine
6062
([#2521](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2521))
6163
- `opentelemetry-util-http` Preserve brackets around literal IPv6 hosts ([#2552](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2552))
6264

65+
6366
## Version 1.24.0/0.45b0 (2024-03-28)
6467

6568
### Added

instrumentation/opentelemetry-instrumentation-elasticsearch/src/opentelemetry/instrumentation/elasticsearch/__init__.py

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,15 @@
1616
This library allows tracing HTTP elasticsearch made by the
1717
`elasticsearch <https://elasticsearch-py.readthedocs.io/en/master/>`_ library.
1818
19+
.. warning::
20+
The elasticsearch package got native OpenTelemetry support since version
21+
`8.13 <https://www.elastic.co/guide/en/elasticsearch/client/python-api/current/release-notes.html#rn-8-13-0>`_.
22+
To avoid duplicated tracing this instrumentation disables itself if it finds an elasticsearch client
23+
that has OpenTelemetry support enabled.
24+
25+
Please be aware that the two libraries may use a different semantic convention, see
26+
`elasticsearch documentation <https://www.elastic.co/guide/en/elasticsearch/client/python-api/current/opentelemetry.html>`_.
27+
1928
Usage
2029
-----
2130
@@ -54,7 +63,7 @@ def response_hook(span: Span, response: dict)
5463
5564
for example:
5665
57-
.. code: python
66+
.. code-block: python
5867
5968
from opentelemetry.instrumentation.elasticsearch import ElasticsearchInstrumentor
6069
import elasticsearch
@@ -81,6 +90,7 @@ def response_hook(span, response):
8190
"""
8291

8392
import re
93+
import warnings
8494
from logging import getLogger
8595
from os import environ
8696
from typing import Collection
@@ -197,6 +207,16 @@ def _wrap_perform_request(
197207
):
198208
# pylint: disable=R0912,R0914
199209
def wrapper(wrapped, _, args, kwargs):
210+
# if wrapped elasticsearch has native OTel instrumentation just call the wrapped function
211+
otel_span = kwargs.get("otel_span")
212+
if otel_span and otel_span.otel_span:
213+
warnings.warn(
214+
"Instrumentation disabled, relying on elasticsearch native OTel support, see "
215+
"https://opentelemetry-python-contrib.readthedocs.io/en/latest/instrumentation/elasticsearch/elasticsearch.html",
216+
Warning,
217+
)
218+
return wrapped(*args, **kwargs)
219+
200220
method = url = None
201221
try:
202222
method, url, *_ = args
@@ -249,6 +269,11 @@ def normalize_kwargs(k, v):
249269
v = str(v)
250270
elif isinstance(v, elastic_transport.HttpHeaders):
251271
v = dict(v)
272+
elif isinstance(
273+
v, elastic_transport.OpenTelemetrySpan
274+
):
275+
# the transport Span is always a dummy one
276+
v = None
252277
return (k, v)
253278

254279
hook_kwargs = dict(

instrumentation/opentelemetry-instrumentation-elasticsearch/test-requirements-2.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
asgiref==3.7.2
22
attrs==23.2.0
33
Deprecated==1.2.14
4-
elasticsearch==8.12.1
5-
elasticsearch-dsl==8.12.0
6-
elastic-transport==8.12.0
4+
elasticsearch==8.13.1
5+
elasticsearch-dsl==8.13.1
6+
elastic-transport==8.13.0
77
importlib-metadata==6.11.0
88
iniconfig==2.0.0
99
packaging==23.2

instrumentation/opentelemetry-instrumentation-elasticsearch/tests/test_elasticsearch.py

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import elasticsearch.exceptions
2424
from elasticsearch import Elasticsearch
2525
from elasticsearch_dsl import Search
26+
from pytest import mark
2627

2728
import opentelemetry.instrumentation.elasticsearch
2829
from opentelemetry import trace
@@ -36,7 +37,7 @@
3637

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

39-
major_version = elasticsearch.VERSION[0]
40+
major_version, minor_version = elasticsearch.VERSION[:2]
4041

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

7172

7273
@mock.patch(helpers.perform_request_mock_path)
74+
@mock.patch.dict(
75+
os.environ, {"OTEL_PYTHON_INSTRUMENTATION_ELASTICSEARCH_ENABLED": "false"}
76+
)
7377
class TestElasticsearchIntegration(TestBase):
7478
search_attributes = {
7579
SpanAttributes.DB_SYSTEM: "elasticsearch",
@@ -110,7 +114,6 @@ def test_instrumentor(self, request_mock):
110114
span = spans_list[0]
111115

112116
# Check version and name in span's instrumentation info
113-
# self.assertEqualSpanInstrumentationInfo(span, opentelemetry.instrumentation.elasticsearch)
114117
self.assertEqualSpanInstrumentationInfo(
115118
span, opentelemetry.instrumentation.elasticsearch
116119
)
@@ -475,6 +478,7 @@ def request_hook(span, method, url, kwargs):
475478
"headers": {
476479
"accept": "application/vnd.elasticsearch+json; compatible-with=8"
477480
},
481+
"otel_span": None,
478482
}
479483
elif major_version == 7:
480484
expected_kwargs = {
@@ -607,3 +611,30 @@ def test_bulk(self, request_mock):
607611
self.assertEqualSpanInstrumentationInfo(
608612
span, opentelemetry.instrumentation.elasticsearch
609613
)
614+
615+
@mark.skipif(
616+
(major_version, minor_version) < (8, 13),
617+
reason="Native OTel since elasticsearch 8.13",
618+
)
619+
@mock.patch.dict(
620+
os.environ,
621+
{"OTEL_PYTHON_INSTRUMENTATION_ELASTICSEARCH_ENABLED": "true"},
622+
)
623+
def test_instrumentation_is_disabled_if_native_support_enabled(
624+
self, request_mock
625+
):
626+
request_mock.return_value = helpers.mock_response("{}")
627+
628+
es = get_elasticsearch_client(hosts=["http://localhost:9200"])
629+
es.index(
630+
index="sw",
631+
id=1,
632+
**normalize_arguments(body={"name": "adam"}, doc_type="_doc"),
633+
)
634+
635+
spans_list = self.get_finished_spans()
636+
self.assertEqual(len(spans_list), 1)
637+
span = spans_list[0]
638+
639+
# Check that name in span's instrumentation info is not from this instrumentation
640+
self.assertEqual(span.instrumentation_info.name, "elasticsearch-api")

tox.ini

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ envlist =
9292
; below mean these dependencies are being used:
9393
; 0: elasticsearch-dsl==6.4.0 elasticsearch==6.8.2
9494
; 1: elasticsearch-dsl==7.4.1 elasticsearch==7.17.9
95-
; 2: elasticsearch-dsl>=8.0,<8.13 elasticsearch>=8.0,<8.13
95+
; 2: elasticsearch-dsl==8.13.1 elasticsearch==8.13.1
9696
py3{8,9,10,11}-test-instrumentation-elasticsearch-{0,1,2}
9797
pypy3-test-instrumentation-elasticsearch-{0,1,2}
9898
lint-instrumentation-elasticsearch

0 commit comments

Comments
 (0)