mirror of
https://github.com/open-telemetry/opentelemetry-python-contrib.git
synced 2025-08-01 09:13:23 +08:00
elasticsearch: don't produce spans if native elasticsearch support is enabled (#2524)
This commit is contained in:

committed by
GitHub

parent
65b4f850a0
commit
eb8e45695e
@ -54,10 +54,13 @@ 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))
|
([#2474](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2474))
|
||||||
- `opentelemetry-instrumentation-elasticsearch` Improved support for version 8
|
- `opentelemetry-instrumentation-elasticsearch` Improved support for version 8
|
||||||
([#2420](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2420))
|
([#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))
|
||||||
- `opentelemetry-instrumentation-asyncio` Check for __name__ attribute in the coroutine
|
- `opentelemetry-instrumentation-asyncio` Check for __name__ attribute in the coroutine
|
||||||
([#2521](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2521))
|
([#2521](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2521))
|
||||||
- `opentelemetry-util-http` Preserve brackets around literal IPv6 hosts ([#2552](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2552))
|
- `opentelemetry-util-http` Preserve brackets around literal IPv6 hosts ([#2552](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2552))
|
||||||
|
|
||||||
|
|
||||||
## Version 1.24.0/0.45b0 (2024-03-28)
|
## Version 1.24.0/0.45b0 (2024-03-28)
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
@ -16,6 +16,15 @@
|
|||||||
This library allows tracing HTTP elasticsearch made by the
|
This library allows tracing HTTP elasticsearch made by the
|
||||||
`elasticsearch <https://elasticsearch-py.readthedocs.io/en/master/>`_ library.
|
`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, see
|
||||||
|
`elasticsearch documentation <https://www.elastic.co/guide/en/elasticsearch/client/python-api/current/opentelemetry.html>`_.
|
||||||
|
|
||||||
Usage
|
Usage
|
||||||
-----
|
-----
|
||||||
|
|
||||||
@ -54,7 +63,7 @@ def response_hook(span: Span, response: dict)
|
|||||||
|
|
||||||
for example:
|
for example:
|
||||||
|
|
||||||
.. code: python
|
.. code-block: python
|
||||||
|
|
||||||
from opentelemetry.instrumentation.elasticsearch import ElasticsearchInstrumentor
|
from opentelemetry.instrumentation.elasticsearch import ElasticsearchInstrumentor
|
||||||
import elasticsearch
|
import elasticsearch
|
||||||
@ -81,6 +90,7 @@ API
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import re
|
import re
|
||||||
|
import warnings
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
from os import environ
|
from os import environ
|
||||||
from typing import Collection
|
from typing import Collection
|
||||||
@ -197,6 +207,16 @@ def _wrap_perform_request(
|
|||||||
):
|
):
|
||||||
# pylint: disable=R0912,R0914
|
# pylint: disable=R0912,R0914
|
||||||
def wrapper(wrapped, _, args, kwargs):
|
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(
|
||||||
|
"Instrumentation disabled, relying on elasticsearch native OTel support, see "
|
||||||
|
"https://opentelemetry-python-contrib.readthedocs.io/en/latest/instrumentation/elasticsearch/elasticsearch.html",
|
||||||
|
Warning,
|
||||||
|
)
|
||||||
|
return wrapped(*args, **kwargs)
|
||||||
|
|
||||||
method = url = None
|
method = url = None
|
||||||
try:
|
try:
|
||||||
method, url, *_ = args
|
method, url, *_ = args
|
||||||
@ -249,6 +269,11 @@ def _wrap_perform_request(
|
|||||||
v = str(v)
|
v = str(v)
|
||||||
elif isinstance(v, elastic_transport.HttpHeaders):
|
elif isinstance(v, elastic_transport.HttpHeaders):
|
||||||
v = dict(v)
|
v = dict(v)
|
||||||
|
elif isinstance(
|
||||||
|
v, elastic_transport.OpenTelemetrySpan
|
||||||
|
):
|
||||||
|
# the transport Span is always a dummy one
|
||||||
|
v = None
|
||||||
return (k, v)
|
return (k, v)
|
||||||
|
|
||||||
hook_kwargs = dict(
|
hook_kwargs = dict(
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
asgiref==3.7.2
|
asgiref==3.7.2
|
||||||
attrs==23.2.0
|
attrs==23.2.0
|
||||||
Deprecated==1.2.14
|
Deprecated==1.2.14
|
||||||
elasticsearch==8.12.1
|
elasticsearch==8.13.1
|
||||||
elasticsearch-dsl==8.12.0
|
elasticsearch-dsl==8.13.1
|
||||||
elastic-transport==8.12.0
|
elastic-transport==8.13.0
|
||||||
importlib-metadata==6.11.0
|
importlib-metadata==6.11.0
|
||||||
iniconfig==2.0.0
|
iniconfig==2.0.0
|
||||||
packaging==23.2
|
packaging==23.2
|
||||||
|
@ -23,6 +23,7 @@ import elasticsearch
|
|||||||
import elasticsearch.exceptions
|
import elasticsearch.exceptions
|
||||||
from elasticsearch import Elasticsearch
|
from elasticsearch import Elasticsearch
|
||||||
from elasticsearch_dsl import Search
|
from elasticsearch_dsl import Search
|
||||||
|
from pytest import mark
|
||||||
|
|
||||||
import opentelemetry.instrumentation.elasticsearch
|
import opentelemetry.instrumentation.elasticsearch
|
||||||
from opentelemetry import trace
|
from opentelemetry import trace
|
||||||
@ -36,7 +37,7 @@ from opentelemetry.trace import StatusCode
|
|||||||
|
|
||||||
from . import sanitization_queries # pylint: disable=no-name-in-module
|
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:
|
if major_version == 8:
|
||||||
from . import helpers_es8 as helpers # pylint: disable=no-name-in-module
|
from . import helpers_es8 as helpers # pylint: disable=no-name-in-module
|
||||||
@ -70,6 +71,9 @@ def get_elasticsearch_client(*args, **kwargs):
|
|||||||
|
|
||||||
|
|
||||||
@mock.patch(helpers.perform_request_mock_path)
|
@mock.patch(helpers.perform_request_mock_path)
|
||||||
|
@mock.patch.dict(
|
||||||
|
os.environ, {"OTEL_PYTHON_INSTRUMENTATION_ELASTICSEARCH_ENABLED": "false"}
|
||||||
|
)
|
||||||
class TestElasticsearchIntegration(TestBase):
|
class TestElasticsearchIntegration(TestBase):
|
||||||
search_attributes = {
|
search_attributes = {
|
||||||
SpanAttributes.DB_SYSTEM: "elasticsearch",
|
SpanAttributes.DB_SYSTEM: "elasticsearch",
|
||||||
@ -110,7 +114,6 @@ class TestElasticsearchIntegration(TestBase):
|
|||||||
span = spans_list[0]
|
span = spans_list[0]
|
||||||
|
|
||||||
# Check version and name in span's instrumentation info
|
# Check version and name in span's instrumentation info
|
||||||
# self.assertEqualSpanInstrumentationInfo(span, opentelemetry.instrumentation.elasticsearch)
|
|
||||||
self.assertEqualSpanInstrumentationInfo(
|
self.assertEqualSpanInstrumentationInfo(
|
||||||
span, opentelemetry.instrumentation.elasticsearch
|
span, opentelemetry.instrumentation.elasticsearch
|
||||||
)
|
)
|
||||||
@ -475,6 +478,7 @@ class TestElasticsearchIntegration(TestBase):
|
|||||||
"headers": {
|
"headers": {
|
||||||
"accept": "application/vnd.elasticsearch+json; compatible-with=8"
|
"accept": "application/vnd.elasticsearch+json; compatible-with=8"
|
||||||
},
|
},
|
||||||
|
"otel_span": None,
|
||||||
}
|
}
|
||||||
elif major_version == 7:
|
elif major_version == 7:
|
||||||
expected_kwargs = {
|
expected_kwargs = {
|
||||||
@ -607,3 +611,30 @@ class TestElasticsearchIntegration(TestBase):
|
|||||||
self.assertEqualSpanInstrumentationInfo(
|
self.assertEqualSpanInstrumentationInfo(
|
||||||
span, opentelemetry.instrumentation.elasticsearch
|
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
tox.ini
2
tox.ini
@ -92,7 +92,7 @@ envlist =
|
|||||||
; below mean these dependencies are being used:
|
; below mean these dependencies are being used:
|
||||||
; 0: elasticsearch-dsl==6.4.0 elasticsearch==6.8.2
|
; 0: elasticsearch-dsl==6.4.0 elasticsearch==6.8.2
|
||||||
; 1: elasticsearch-dsl==7.4.1 elasticsearch==7.17.9
|
; 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
|
||||||
py3{8,9,10,11}-test-instrumentation-elasticsearch-{0,1,2}
|
py3{8,9,10,11}-test-instrumentation-elasticsearch-{0,1,2}
|
||||||
pypy3-test-instrumentation-elasticsearch-{0,1,2}
|
pypy3-test-instrumentation-elasticsearch-{0,1,2}
|
||||||
lint-instrumentation-elasticsearch
|
lint-instrumentation-elasticsearch
|
||||||
|
Reference in New Issue
Block a user