diff --git a/.changelog/4718.changed b/.changelog/4718.changed new file mode 100644 index 0000000000..190c17a7d2 --- /dev/null +++ b/.changelog/4718.changed @@ -0,0 +1 @@ +opentelemetry-instrumentation-urllib3: remove multiple calls to sanitize_method \ No newline at end of file diff --git a/instrumentation/opentelemetry-instrumentation-urllib3/benchmark-requirements.txt b/instrumentation/opentelemetry-instrumentation-urllib3/benchmark-requirements.txt new file mode 100644 index 0000000000..5ddc9d46f4 --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-urllib3/benchmark-requirements.txt @@ -0,0 +1,5 @@ +mocket==3.14.1 +pytest-benchmark==4.0.0 +-e opentelemetry-instrumentation +-e util/opentelemetry-util-http +-e instrumentation/opentelemetry-instrumentation-urllib3 diff --git a/instrumentation/opentelemetry-instrumentation-urllib3/benchmarks/test_benchmark_sanitize_method.py b/instrumentation/opentelemetry-instrumentation-urllib3/benchmarks/test_benchmark_sanitize_method.py new file mode 100644 index 0000000000..e320e3aa84 --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-urllib3/benchmarks/test_benchmark_sanitize_method.py @@ -0,0 +1,43 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +import pytest +import urllib3 +from mocket import Mocketizer +from mocket.mocks.mockhttp import Entry + +from opentelemetry.instrumentation.urllib3 import URLLib3Instrumentor +from opentelemetry.sdk.trace import TracerProvider +from opentelemetry.sdk.trace.export import SimpleSpanProcessor +from opentelemetry.sdk.trace.export.in_memory_span_exporter import ( + InMemorySpanExporter, +) + +_URL = "http://mock/status/200" + + +@pytest.fixture(name="connection_pool") +def _connection_pool_fixture(): + exporter = InMemorySpanExporter() + provider = TracerProvider() + provider.add_span_processor(SimpleSpanProcessor(exporter)) + URLLib3Instrumentor().instrument(tracer_provider=provider) + pool = urllib3.HTTPConnectionPool("mock", port=80) + with Mocketizer(): + Entry.single_register( + Entry.GET, _URL, body="Hello!", match_querystring=False + ) + yield pool + URLLib3Instrumentor().uninstrument() + + +def test_instrumented_urlopen( + benchmark, connection_pool: urllib3.HTTPConnectionPool +): + def run(): + Entry.single_register( + Entry.GET, _URL, body="Hello!", match_querystring=False + ) + connection_pool.urlopen("GET", "/status/200") + + benchmark(run) diff --git a/instrumentation/opentelemetry-instrumentation-urllib3/src/opentelemetry/instrumentation/urllib3/__init__.py b/instrumentation/opentelemetry-instrumentation-urllib3/src/opentelemetry/instrumentation/urllib3/__init__.py index ab5660cc74..4728c09ba6 100644 --- a/instrumentation/opentelemetry-instrumentation-urllib3/src/opentelemetry/instrumentation/urllib3/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-urllib3/src/opentelemetry/instrumentation/urllib3/__init__.py @@ -406,11 +406,10 @@ def _uninstrument(self, **kwargs): _uninstrument() -def _get_span_name(method: str) -> str: - method = sanitize_method(method.strip()) - if method == "_OTHER": - method = "HTTP" - return method +def _get_span_name(sanitized_method: str) -> str: + if sanitized_method == "_OTHER": + return "HTTP" + return sanitized_method # pylint: disable=too-many-locals,too-many-positional-arguments @@ -457,13 +456,14 @@ def instrumented_urlopen(wrapped, instance, args, kwargs): # avoid modifying original headers on inject headers = headers.copy() if headers is not None else {} - span_name = _get_span_name(method) + sanitized_method = sanitize_method(method) + span_name = _get_span_name(sanitized_method) span_attributes = {} _set_http_method( span_attributes, method, - sanitize_method(method), + sanitized_method, sem_conv_opt_in_mode, ) _set_http_url(span_attributes, url, sem_conv_opt_in_mode) @@ -519,6 +519,7 @@ def instrumented_urlopen(wrapped, instance, args, kwargs): instance, response, method, + sanitized_method, sem_conv_opt_in_mode, ) @@ -625,6 +626,7 @@ def _set_metric_attributes( instance: urllib3.connectionpool.HTTPConnectionPool, response: urllib3.response.HTTPResponse, method: str, + sanitized_method: str, sem_conv_opt_in_mode: _StabilityMode = _StabilityMode.DEFAULT, ) -> None: _set_http_host_client( @@ -634,7 +636,7 @@ def _set_metric_attributes( _set_http_method( metric_attributes, method, - sanitize_method(method), + sanitized_method, sem_conv_opt_in_mode, ) _set_http_net_peer_name_client( diff --git a/tox.ini b/tox.ini index f8315f4650..b59c469210 100644 --- a/tox.ini +++ b/tox.ini @@ -202,6 +202,7 @@ envlist = pypy3-test-instrumentation-logging lint-instrumentation-logging benchmark-instrumentation-logging + benchmark-instrumentation-urllib3 ; opentelemetry-exporter-richconsole py3{10,11,12,13,14}-test-exporter-richconsole @@ -691,6 +692,7 @@ deps = logging: {[testenv]test_deps} logging: -r {toxinidir}/instrumentation/opentelemetry-instrumentation-logging/test-requirements.txt benchmark-instrumentation-logging: -r {toxinidir}/instrumentation/opentelemetry-instrumentation-logging/benchmark-requirements.txt + benchmark-instrumentation-urllib3: -r {toxinidir}/instrumentation/opentelemetry-instrumentation-urllib3/benchmark-requirements.txt aiohttp-client: {[testenv]test_deps} aiohttp-client: -r {toxinidir}/instrumentation/opentelemetry-instrumentation-aiohttp-client/test-requirements.txt @@ -893,6 +895,7 @@ commands = test-instrumentation-logging: pytest {toxinidir}/instrumentation/opentelemetry-instrumentation-logging/tests {posargs} lint-instrumentation-logging: sh -c "cd instrumentation && pylint --rcfile ../.pylintrc opentelemetry-instrumentation-logging" benchmark-instrumentation-logging: pytest {toxinidir}/instrumentation/opentelemetry-instrumentation-logging/benchmarks {posargs} --benchmark-json=instrumentation-logging-benchmark.json + benchmark-instrumentation-urllib3: pytest {toxinidir}/instrumentation/opentelemetry-instrumentation-urllib3/benchmarks {posargs} --benchmark-json=instrumentation-urllib3-benchmark.json test-instrumentation-mysql: pytest {toxinidir}/instrumentation/opentelemetry-instrumentation-mysql/tests {posargs} lint-instrumentation-mysql: sh -c "cd instrumentation && pylint --rcfile ../.pylintrc opentelemetry-instrumentation-mysql"