consistently use of suppress_instrumentation utils (#2590)

This commit is contained in:
Emídio Neto
2024-06-14 13:53:28 -03:00
committed by GitHub
parent 881a179e3b
commit 6be205e604
9 changed files with 125 additions and 45 deletions

View File

@ -23,6 +23,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
([#2538](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2538)) ([#2538](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2538))
- Add Python 3.12 support - Add Python 3.12 support
([#2572](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2572)) ([#2572](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2572))
- `opentelemetry-instrumentation-aiohttp-server`, `opentelemetry-instrumentation-httpx` Ensure consistently use of suppress_instrumentation utils
([#2590](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2590))
## Version 1.25.0/0.46b0 (2024-05-31) ## Version 1.25.0/0.46b0 (2024-05-31)

View File

@ -19,12 +19,14 @@ from typing import Dict, List, Tuple, Union
from aiohttp import web from aiohttp import web
from multidict import CIMultiDictProxy from multidict import CIMultiDictProxy
from opentelemetry import context, metrics, trace from opentelemetry import metrics, trace
from opentelemetry.context import _SUPPRESS_HTTP_INSTRUMENTATION_KEY
from opentelemetry.instrumentation.aiohttp_server.package import _instruments from opentelemetry.instrumentation.aiohttp_server.package import _instruments
from opentelemetry.instrumentation.aiohttp_server.version import __version__ from opentelemetry.instrumentation.aiohttp_server.version import __version__
from opentelemetry.instrumentation.instrumentor import BaseInstrumentor from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
from opentelemetry.instrumentation.utils import http_status_to_status_code from opentelemetry.instrumentation.utils import (
http_status_to_status_code,
is_http_instrumentation_enabled,
)
from opentelemetry.propagate import extract from opentelemetry.propagate import extract
from opentelemetry.propagators.textmap import Getter from opentelemetry.propagators.textmap import Getter
from opentelemetry.semconv.metrics import MetricInstruments from opentelemetry.semconv.metrics import MetricInstruments
@ -191,10 +193,8 @@ getter = AiohttpGetter()
@web.middleware @web.middleware
async def middleware(request, handler): async def middleware(request, handler):
"""Middleware for aiohttp implementing tracing logic""" """Middleware for aiohttp implementing tracing logic"""
if ( if not is_http_instrumentation_enabled() or _excluded_urls.url_disabled(
context.get_value("suppress_instrumentation") request.url.path
or context.get_value(_SUPPRESS_HTTP_INSTRUMENTATION_KEY)
or _excluded_urls.url_disabled(request.url.path)
): ):
return await handler(request) return await handler(request)

View File

@ -23,6 +23,7 @@ from opentelemetry import trace as trace_api
from opentelemetry.instrumentation.aiohttp_server import ( from opentelemetry.instrumentation.aiohttp_server import (
AioHttpServerInstrumentor, AioHttpServerInstrumentor,
) )
from opentelemetry.instrumentation.utils import suppress_http_instrumentation
from opentelemetry.semconv.trace import SpanAttributes from opentelemetry.semconv.trace import SpanAttributes
from opentelemetry.test.globals_test import reset_trace_globals from opentelemetry.test.globals_test import reset_trace_globals
from opentelemetry.test.test_base import TestBase from opentelemetry.test.test_base import TestBase
@ -64,16 +65,25 @@ async def default_handler(request, status=200):
return aiohttp.web.Response(status=status) return aiohttp.web.Response(status=status)
@pytest.fixture(name="suppress")
def fixture_suppress():
return False
@pytest_asyncio.fixture(name="server_fixture") @pytest_asyncio.fixture(name="server_fixture")
async def fixture_server_fixture(tracer, aiohttp_server): async def fixture_server_fixture(tracer, aiohttp_server, suppress):
_, memory_exporter = tracer _, memory_exporter = tracer
AioHttpServerInstrumentor().instrument() AioHttpServerInstrumentor().instrument()
app = aiohttp.web.Application() app = aiohttp.web.Application()
app.add_routes([aiohttp.web.get("/test-path", default_handler)]) app.add_routes([aiohttp.web.get("/test-path", default_handler)])
if suppress:
with suppress_http_instrumentation():
server = await aiohttp_server(app) server = await aiohttp_server(app)
else:
server = await aiohttp_server(app)
yield server, app yield server, app
memory_exporter.clear() memory_exporter.clear()
@ -128,3 +138,18 @@ async def test_status_code_instrumentation(
f"http://{server.host}:{server.port}{url}" f"http://{server.host}:{server.port}{url}"
== span.attributes[SpanAttributes.HTTP_URL] == span.attributes[SpanAttributes.HTTP_URL]
) )
@pytest.mark.asyncio
@pytest.mark.parametrize("suppress", [True])
async def test_suppress_instrumentation(
tracer, server_fixture, aiohttp_client
):
_, memory_exporter = tracer
server, _ = server_fixture
assert len(memory_exporter.get_finished_spans()) == 0
client = await aiohttp_client(server)
await client.get("/test-path")
assert len(memory_exporter.get_finished_spans()) == 0

View File

@ -196,11 +196,13 @@ from types import TracebackType
import httpx import httpx
from opentelemetry import context
from opentelemetry.instrumentation.httpx.package import _instruments from opentelemetry.instrumentation.httpx.package import _instruments
from opentelemetry.instrumentation.httpx.version import __version__ from opentelemetry.instrumentation.httpx.version import __version__
from opentelemetry.instrumentation.instrumentor import BaseInstrumentor from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
from opentelemetry.instrumentation.utils import http_status_to_status_code from opentelemetry.instrumentation.utils import (
http_status_to_status_code,
is_http_instrumentation_enabled,
)
from opentelemetry.propagate import inject from opentelemetry.propagate import inject
from opentelemetry.semconv.trace import SpanAttributes from opentelemetry.semconv.trace import SpanAttributes
from opentelemetry.trace import SpanKind, TracerProvider, get_tracer from opentelemetry.trace import SpanKind, TracerProvider, get_tracer
@ -347,7 +349,7 @@ class SyncOpenTelemetryTransport(httpx.BaseTransport):
httpx.Response, httpx.Response,
]: ]:
"""Add request info to span.""" """Add request info to span."""
if context.get_value("suppress_instrumentation"): if not is_http_instrumentation_enabled():
return self._transport.handle_request(*args, **kwargs) return self._transport.handle_request(*args, **kwargs)
method, url, headers, stream, extensions = _extract_parameters( method, url, headers, stream, extensions = _extract_parameters(
@ -438,7 +440,7 @@ class AsyncOpenTelemetryTransport(httpx.AsyncBaseTransport):
httpx.Response, httpx.Response,
]: ]:
"""Add request info to span.""" """Add request info to span."""
if context.get_value("suppress_instrumentation"): if not is_http_instrumentation_enabled():
return await self._transport.handle_async_request(*args, **kwargs) return await self._transport.handle_async_request(*args, **kwargs)
method, url, headers, stream, extensions = _extract_parameters( method, url, headers, stream, extensions = _extract_parameters(

View File

@ -21,12 +21,13 @@ import httpx
import respx import respx
import opentelemetry.instrumentation.httpx import opentelemetry.instrumentation.httpx
from opentelemetry import context, trace from opentelemetry import trace
from opentelemetry.instrumentation.httpx import ( from opentelemetry.instrumentation.httpx import (
AsyncOpenTelemetryTransport, AsyncOpenTelemetryTransport,
HTTPXClientInstrumentor, HTTPXClientInstrumentor,
SyncOpenTelemetryTransport, SyncOpenTelemetryTransport,
) )
from opentelemetry.instrumentation.utils import suppress_http_instrumentation
from opentelemetry.propagate import get_global_textmap, set_global_textmap from opentelemetry.propagate import get_global_textmap, set_global_textmap
from opentelemetry.sdk import resources from opentelemetry.sdk import resources
from opentelemetry.semconv.trace import SpanAttributes from opentelemetry.semconv.trace import SpanAttributes
@ -191,14 +192,9 @@ class BaseTestCases:
) )
def test_suppress_instrumentation(self): def test_suppress_instrumentation(self):
token = context.attach( with suppress_http_instrumentation():
context.set_value("suppress_instrumentation", True)
)
try:
result = self.perform_request(self.URL) result = self.perform_request(self.URL)
self.assertEqual(result.text, "Hello!") self.assertEqual(result.text, "Hello!")
finally:
context.detach(token)
self.assert_span(num_spans=0) self.assert_span(num_spans=0)
@ -512,15 +508,10 @@ class BaseTestCases:
def test_suppress_instrumentation_new_client(self): def test_suppress_instrumentation_new_client(self):
HTTPXClientInstrumentor().instrument() HTTPXClientInstrumentor().instrument()
token = context.attach( with suppress_http_instrumentation():
context.set_value("suppress_instrumentation", True)
)
try:
client = self.create_client() client = self.create_client()
result = self.perform_request(self.URL, client=client) result = self.perform_request(self.URL, client=client)
self.assertEqual(result.text, "Hello!") self.assertEqual(result.text, "Hello!")
finally:
context.detach(token)
self.assert_span(num_spans=0) self.assert_span(num_spans=0)
HTTPXClientInstrumentor().uninstrument() HTTPXClientInstrumentor().uninstrument()

View File

@ -37,6 +37,10 @@ from opentelemetry.trace.propagation.tracecontext import (
propagator = TraceContextTextMapPropagator() propagator = TraceContextTextMapPropagator()
_SUPPRESS_INSTRUMENTATION_KEY_PLAIN = (
"suppress_instrumentation" # Set for backward compatibility
)
def extract_attributes_from_object( def extract_attributes_from_object(
obj: any, attributes: Sequence[str], existing: Dict[str, str] = None obj: any, attributes: Sequence[str], existing: Dict[str, str] = None
@ -161,9 +165,10 @@ def _python_path_without_directory(python_path, directory, path_separator):
def is_instrumentation_enabled() -> bool: def is_instrumentation_enabled() -> bool:
if context.get_value(_SUPPRESS_INSTRUMENTATION_KEY): return not (
return False context.get_value(_SUPPRESS_INSTRUMENTATION_KEY)
return True or context.get_value(_SUPPRESS_INSTRUMENTATION_KEY_PLAIN)
)
def is_http_instrumentation_enabled() -> bool: def is_http_instrumentation_enabled() -> bool:
@ -188,7 +193,9 @@ def _suppress_instrumentation(*keys: str) -> Iterable[None]:
@contextmanager @contextmanager
def suppress_instrumentation() -> Iterable[None]: def suppress_instrumentation() -> Iterable[None]:
"""Suppress instrumentation within the context.""" """Suppress instrumentation within the context."""
with _suppress_instrumentation(_SUPPRESS_INSTRUMENTATION_KEY): with _suppress_instrumentation(
_SUPPRESS_INSTRUMENTATION_KEY, _SUPPRESS_INSTRUMENTATION_KEY_PLAIN
):
yield yield

View File

@ -15,10 +15,20 @@
import unittest import unittest
from http import HTTPStatus from http import HTTPStatus
from opentelemetry.context import (
_SUPPRESS_HTTP_INSTRUMENTATION_KEY,
_SUPPRESS_INSTRUMENTATION_KEY,
get_current,
get_value,
)
from opentelemetry.instrumentation.sqlcommenter_utils import _add_sql_comment from opentelemetry.instrumentation.sqlcommenter_utils import _add_sql_comment
from opentelemetry.instrumentation.utils import ( from opentelemetry.instrumentation.utils import (
_python_path_without_directory, _python_path_without_directory,
http_status_to_status_code, http_status_to_status_code,
is_http_instrumentation_enabled,
is_instrumentation_enabled,
suppress_http_instrumentation,
suppress_instrumentation,
) )
from opentelemetry.trace import StatusCode from opentelemetry.trace import StatusCode
@ -186,3 +196,47 @@ class TestUtils(unittest.TestCase):
) )
self.assertEqual(commented_sql_without_semicolon, "Select 1") self.assertEqual(commented_sql_without_semicolon, "Select 1")
def test_is_instrumentation_enabled_by_default(self):
self.assertTrue(is_instrumentation_enabled())
self.assertTrue(is_http_instrumentation_enabled())
def test_suppress_instrumentation(self):
with suppress_instrumentation():
self.assertFalse(is_instrumentation_enabled())
self.assertFalse(is_http_instrumentation_enabled())
self.assertTrue(is_instrumentation_enabled())
self.assertTrue(is_http_instrumentation_enabled())
def test_suppress_http_instrumentation(self):
with suppress_http_instrumentation():
self.assertFalse(is_http_instrumentation_enabled())
self.assertTrue(is_instrumentation_enabled())
self.assertTrue(is_instrumentation_enabled())
self.assertTrue(is_http_instrumentation_enabled())
def test_suppress_instrumentation_key(self):
self.assertIsNone(get_value(_SUPPRESS_INSTRUMENTATION_KEY))
self.assertIsNone(get_value("suppress_instrumentation"))
with suppress_instrumentation():
ctx = get_current()
self.assertIn(_SUPPRESS_INSTRUMENTATION_KEY, ctx)
self.assertIn("suppress_instrumentation", ctx)
self.assertTrue(get_value(_SUPPRESS_INSTRUMENTATION_KEY))
self.assertTrue(get_value("suppress_instrumentation"))
self.assertIsNone(get_value(_SUPPRESS_INSTRUMENTATION_KEY))
self.assertIsNone(get_value("suppress_instrumentation"))
def test_suppress_http_instrumentation_key(self):
self.assertIsNone(get_value(_SUPPRESS_HTTP_INSTRUMENTATION_KEY))
with suppress_http_instrumentation():
ctx = get_current()
self.assertIn(_SUPPRESS_HTTP_INSTRUMENTATION_KEY, ctx)
self.assertTrue(get_value(_SUPPRESS_HTTP_INSTRUMENTATION_KEY))
self.assertIsNone(get_value(_SUPPRESS_HTTP_INSTRUMENTATION_KEY))

View File

@ -5,6 +5,11 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## Unreleased
- Ensure consistently use of suppress_instrumentation utils
([#2590](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2590))
## Version 0.1.5 (2024-05-16) ## Version 0.1.5 (2024-05-16)
- Ignore vm detector if already in other rps - Ignore vm detector if already in other rps

View File

@ -17,12 +17,7 @@ from logging import getLogger
from urllib.error import URLError from urllib.error import URLError
from urllib.request import Request, urlopen from urllib.request import Request, urlopen
from opentelemetry.context import ( from opentelemetry.instrumentation.utils import suppress_instrumentation
_SUPPRESS_INSTRUMENTATION_KEY,
attach,
detach,
set_value,
)
from opentelemetry.sdk.resources import Resource, ResourceDetector from opentelemetry.sdk.resources import Resource, ResourceDetector
from opentelemetry.semconv.resource import ( from opentelemetry.semconv.resource import (
CloudPlatformValues, CloudPlatformValues,
@ -46,7 +41,7 @@ class AzureVMResourceDetector(ResourceDetector):
def detect(self) -> "Resource": def detect(self) -> "Resource":
attributes = {} attributes = {}
if not _can_ignore_vm_detect(): if not _can_ignore_vm_detect():
token = attach(set_value(_SUPPRESS_INSTRUMENTATION_KEY, True)) with suppress_instrumentation():
metadata_json = _get_azure_vm_metadata() metadata_json = _get_azure_vm_metadata()
if not metadata_json: if not metadata_json:
return Resource(attributes) return Resource(attributes)
@ -54,7 +49,6 @@ class AzureVMResourceDetector(ResourceDetector):
attributes[attribute_key] = _get_attribute_from_metadata( attributes[attribute_key] = _get_attribute_from_metadata(
metadata_json, attribute_key metadata_json, attribute_key
) )
detach(token)
return Resource(attributes) return Resource(attributes)