mirror of
https://github.com/open-telemetry/opentelemetry-python-contrib.git
synced 2025-07-30 13:43:03 +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))
|
||||
- `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))
|
||||
- `opentelemetry-instrumentation-asyncio` Check for __name__ attribute in the coroutine
|
||||
([#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))
|
||||
|
||||
|
||||
## Version 1.24.0/0.45b0 (2024-03-28)
|
||||
|
||||
### Added
|
||||
|
@ -16,6 +16,15 @@
|
||||
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, see
|
||||
`elasticsearch documentation <https://www.elastic.co/guide/en/elasticsearch/client/python-api/current/opentelemetry.html>`_.
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
@ -54,7 +63,7 @@ def response_hook(span: Span, response: dict)
|
||||
|
||||
for example:
|
||||
|
||||
.. code: python
|
||||
.. code-block: python
|
||||
|
||||
from opentelemetry.instrumentation.elasticsearch import ElasticsearchInstrumentor
|
||||
import elasticsearch
|
||||
@ -81,6 +90,7 @@ API
|
||||
"""
|
||||
|
||||
import re
|
||||
import warnings
|
||||
from logging import getLogger
|
||||
from os import environ
|
||||
from typing import Collection
|
||||
@ -197,6 +207,16 @@ 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(
|
||||
"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
|
||||
try:
|
||||
method, url, *_ = args
|
||||
@ -249,6 +269,11 @@ def _wrap_perform_request(
|
||||
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(
|
||||
|
@ -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
|
||||
|
@ -23,6 +23,7 @@ import elasticsearch
|
||||
import elasticsearch.exceptions
|
||||
from elasticsearch import Elasticsearch
|
||||
from elasticsearch_dsl import Search
|
||||
from pytest import mark
|
||||
|
||||
import opentelemetry.instrumentation.elasticsearch
|
||||
from opentelemetry import trace
|
||||
@ -36,7 +37,7 @@ from opentelemetry.trace import StatusCode
|
||||
|
||||
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
|
||||
@ -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",
|
||||
@ -110,7 +114,6 @@ class TestElasticsearchIntegration(TestBase):
|
||||
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
|
||||
)
|
||||
@ -475,6 +478,7 @@ class TestElasticsearchIntegration(TestBase):
|
||||
"headers": {
|
||||
"accept": "application/vnd.elasticsearch+json; compatible-with=8"
|
||||
},
|
||||
"otel_span": None,
|
||||
}
|
||||
elif major_version == 7:
|
||||
expected_kwargs = {
|
||||
@ -607,3 +611,30 @@ class TestElasticsearchIntegration(TestBase):
|
||||
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
tox.ini
2
tox.ini
@ -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
|
||||
py3{8,9,10,11}-test-instrumentation-elasticsearch-{0,1,2}
|
||||
pypy3-test-instrumentation-elasticsearch-{0,1,2}
|
||||
lint-instrumentation-elasticsearch
|
||||
|
Reference in New Issue
Block a user