2020import pytest_asyncio
2121from multidict import CIMultiDict
2222
23- from opentelemetry import metrics as metrics_api
24- from opentelemetry import trace as trace_api
2523from opentelemetry .instrumentation ._semconv import (
2624 HTTP_DURATION_HISTOGRAM_BUCKETS_NEW ,
2725 OTEL_SEMCONV_STABILITY_OPT_IN ,
7371from opentelemetry .semconv .attributes .user_agent_attributes import (
7472 USER_AGENT_ORIGINAL ,
7573)
76- from opentelemetry .test .globals_test import (
77- reset_metrics_globals ,
78- reset_trace_globals ,
79- )
8074from opentelemetry .test .test_base import TestBase
8175from opentelemetry .util ._importlib_metadata import entry_points
8276from opentelemetry .util .http import (
@@ -103,33 +97,24 @@ def __repr__(self):
10397 TRACE = "TRACE"
10498
10599
106- @pytest .fixture (name = "tracer " , scope = "function" )
107- def fixture_tracer ():
100+ @pytest .fixture (name = "test_base " , scope = "function" )
101+ def fixture_test_base ():
108102 test_base = TestBase ()
103+ test_base .setUp ()
104+ try :
105+ yield test_base
106+ finally :
107+ test_base .tearDown ()
109108
110- tracer_provider , memory_exporter = test_base .create_tracer_provider ()
111-
112- reset_trace_globals ()
113- trace_api .set_tracer_provider (tracer_provider )
114-
115- yield tracer_provider , memory_exporter
116109
117- reset_trace_globals ()
118- memory_exporter .clear ()
110+ @pytest .fixture (name = "tracer" , scope = "function" )
111+ def fixture_tracer (test_base : TestBase ):
112+ return test_base .tracer_provider , test_base .memory_exporter
119113
120114
121115@pytest .fixture (name = "meter" , scope = "function" )
122- def fixture_meter ():
123- test_base = TestBase ()
124-
125- meter_provider , memory_reader = test_base .create_meter_provider ()
126-
127- reset_metrics_globals ()
128- metrics_api .set_meter_provider (meter_provider )
129-
130- yield meter_provider , memory_reader
131-
132- reset_metrics_globals ()
116+ def fixture_meter (test_base : TestBase ):
117+ return test_base .meter_provider , test_base .memory_metrics_reader
133118
134119
135120async def default_handler (request , status = 200 ):
@@ -143,7 +128,7 @@ def fixture_suppress():
143128
144129@pytest_asyncio .fixture (name = "server_fixture" )
145130async def fixture_server_fixture (tracer , aiohttp_server , suppress ):
146- tracer_provider , memory_exporter = tracer
131+ tracer_provider , _ = tracer
147132
148133 AioHttpServerInstrumentor ().instrument (tracer_provider = tracer_provider )
149134
@@ -157,8 +142,6 @@ async def fixture_server_fixture(tracer, aiohttp_server, suppress):
157142
158143 yield server , app
159144
160- memory_exporter .clear ()
161-
162145 AioHttpServerInstrumentor ().uninstrument ()
163146
164147
@@ -179,31 +162,27 @@ def test_checking_instrumentor_pkg_installed():
179162 ],
180163)
181164async def test_status_code_instrumentation (
182- tracer ,
183- meter ,
165+ test_base : TestBase ,
184166 server_fixture ,
185167 aiohttp_client ,
186168 url ,
187169 expected_method ,
188170 expected_status_code ,
189171):
190- _ , memory_exporter = tracer
191- _ , metrics_reader = meter
192172 server , _ = server_fixture
193173
194- assert len (memory_exporter .get_finished_spans ()) == 0
195- metrics = _get_sorted_metrics ( metrics_reader . get_metrics_data () )
174+ assert len (test_base .get_finished_spans ()) == 0
175+ metrics = test_base . get_sorted_metrics ( )
196176 assert len (metrics ) == 0
197177
198178 client = await aiohttp_client (server )
199179 await client .get (url )
200180
201- assert len (memory_exporter .get_finished_spans ()) == 1
202- metrics = _get_sorted_metrics ( metrics_reader . get_metrics_data () )
181+ assert len (test_base .get_finished_spans ()) == 1
182+ metrics = test_base . get_sorted_metrics ( )
203183 assert len (metrics ) == 2
204184
205- [span ] = memory_exporter .get_finished_spans ()
206-
185+ [span ] = test_base .get_finished_spans ()
207186 assert expected_method .value == span .attributes [HTTP_METHOD ]
208187 assert expected_status_code == span .attributes [HTTP_STATUS_CODE ]
209188 assert url == span .attributes [HTTP_TARGET ]
@@ -212,23 +191,22 @@ async def test_status_code_instrumentation(
212191@pytest .mark .asyncio
213192@pytest .mark .parametrize ("suppress" , [True ])
214193async def test_suppress_instrumentation (
215- tracer , server_fixture , aiohttp_client
194+ test_base : TestBase , server_fixture , aiohttp_client
216195):
217- _ , memory_exporter = tracer
218196 server , _ = server_fixture
219- assert len (memory_exporter .get_finished_spans ()) == 0
197+ assert len (test_base .get_finished_spans ()) == 0
220198
221199 client = await aiohttp_client (server )
222200 await client .get ("/test-path" )
223201
224- assert len (memory_exporter .get_finished_spans ()) == 0
202+ assert len (test_base .get_finished_spans ()) == 0
225203
226204
227205@pytest .mark .asyncio
228- async def test_remove_sensitive_params (tracer , aiohttp_server , monkeypatch ):
206+ async def test_remove_sensitive_params (
207+ test_base : TestBase , aiohttp_server , monkeypatch
208+ ):
229209 """Test that sensitive information in URLs is properly redacted."""
230- _ , memory_exporter = tracer
231-
232210 # Use old semconv to test HTTP_URL redaction
233211 monkeypatch .setenv (
234212 OTEL_SEMCONV_STABILITY_OPT_IN , _StabilityMode .DEFAULT .value
@@ -257,7 +235,7 @@ async def handler(request):
257235 assert await response .text () == "hello"
258236
259237 # Verify redaction in span attributes
260- spans = memory_exporter .get_finished_spans ()
238+ spans = test_base .get_finished_spans ()
261239 assert len (spans ) == 1
262240
263241 span = spans [0 ]
@@ -270,16 +248,13 @@ async def handler(request):
270248
271249 # Clean up
272250 AioHttpServerInstrumentor ().uninstrument ()
273- memory_exporter .clear ()
274251
275252
276253@pytest .mark .asyncio
277254async def test_remove_sensitive_params_new (
278- tracer , aiohttp_server , monkeypatch
255+ test_base : TestBase , aiohttp_server , monkeypatch
279256):
280257 """Test URL handling with new semantic conventions (no redaction for URL_PATH/URL_QUERY)."""
281- _ , memory_exporter = tracer
282-
283258 # Use new semconv
284259 monkeypatch .setenv (
285260 OTEL_SEMCONV_STABILITY_OPT_IN , _StabilityMode .HTTP .value
@@ -308,7 +283,7 @@ async def handler(request):
308283 assert await response .text () == "hello"
309284
310285 # Verify span attributes with new semconv
311- spans = memory_exporter .get_finished_spans ()
286+ spans = test_base .get_finished_spans ()
312287 assert len (spans ) == 1
313288
314289 span = spans [0 ]
@@ -320,21 +295,6 @@ async def handler(request):
320295
321296 # Clean up
322297 AioHttpServerInstrumentor ().uninstrument ()
323- memory_exporter .clear ()
324-
325-
326- def _get_sorted_metrics (metrics_data ):
327- resource_metrics = metrics_data .resource_metrics if metrics_data else []
328-
329- all_metrics = []
330- for metrics in resource_metrics :
331- for scope_metrics in metrics .scope_metrics :
332- all_metrics .extend (scope_metrics .metrics )
333-
334- return sorted (
335- all_metrics ,
336- key = lambda m : m .name ,
337- )
338298
339299
340300@pytest .mark .asyncio
@@ -343,12 +303,9 @@ def _get_sorted_metrics(metrics_data):
343303 ["OTEL_PYTHON_AIOHTTP_SERVER_EXCLUDED_URLS" , "OTEL_PYTHON_EXCLUDED_URLS" ],
344304)
345305async def test_excluded_urls (
346- tracer , meter , aiohttp_server , monkeypatch , env_var
306+ test_base : TestBase , aiohttp_server , monkeypatch , env_var
347307):
348308 """Test that excluded env vars are taken into account."""
349- _ , memory_exporter = tracer
350- _ , metrics_reader = meter
351-
352309 monkeypatch .setenv (env_var , "/status/200" )
353310 AioHttpServerInstrumentor ().instrument ()
354311
@@ -367,10 +324,10 @@ async def handler(request):
367324 assert response .status == 200
368325 assert await response .text () == "hello"
369326
370- spans = memory_exporter .get_finished_spans ()
327+ spans = test_base .get_finished_spans ()
371328 assert len (spans ) == 0
372329
373- metrics = _get_sorted_metrics ( metrics_reader . get_metrics_data () )
330+ metrics = test_base . get_sorted_metrics ( )
374331 assert len (metrics ) == 0
375332
376333 AioHttpServerInstrumentor ().uninstrument ()
@@ -415,25 +372,11 @@ async def test_non_global_tracer_provider(
415372 )
416373
417374
418- def _get_sorted_metrics (metrics_data ):
419- resource_metrics = metrics_data .resource_metrics if metrics_data else []
420-
421- all_metrics = []
422- for metrics in resource_metrics :
423- for scope_metrics in metrics .scope_metrics :
424- all_metrics .extend (scope_metrics .metrics )
425-
426- return sorted (
427- all_metrics ,
428- key = lambda m : m .name ,
429- )
430-
431-
432375@pytest .mark .asyncio
433- async def test_custom_request_headers (tracer , aiohttp_server , monkeypatch ):
376+ async def test_custom_request_headers (
377+ test_base : TestBase , aiohttp_server , monkeypatch
378+ ):
434379 # pylint: disable=too-many-locals
435- _ , memory_exporter = tracer
436-
437380 monkeypatch .setenv (
438381 OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SANITIZE_FIELDS ,
439382 ".*my-secret.*" ,
@@ -466,7 +409,7 @@ async def handler(request):
466409 assert response .status == 200
467410 assert await response .text () == "hello"
468411
469- spans = memory_exporter .get_finished_spans ()
412+ spans = test_base .get_finished_spans ()
470413 assert len (spans ) == 1
471414
472415 span = spans [0 ]
@@ -489,9 +432,9 @@ async def handler(request):
489432
490433
491434@pytest .mark .asyncio
492- async def test_custom_response_headers (tracer , aiohttp_server , monkeypatch ):
493- _ , memory_exporter = tracer
494-
435+ async def test_custom_response_headers (
436+ test_base : TestBase , aiohttp_server , monkeypatch
437+ ):
495438 monkeypatch .setenv (
496439 OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SANITIZE_FIELDS ,
497440 ".*my-secret.*" ,
@@ -526,7 +469,7 @@ async def handler(request):
526469 assert response .status == 200
527470 assert await response .text () == "hello"
528471
529- spans = memory_exporter .get_finished_spans ()
472+ spans = test_base .get_finished_spans ()
530473 assert len (spans ) == 1
531474
532475 span = spans [0 ]
@@ -553,10 +496,8 @@ async def handler(request):
553496# pylint: disable=too-many-locals
554497@pytest .mark .asyncio
555498async def test_semantic_conventions_metrics_old_default (
556- tracer , meter , aiohttp_server , monkeypatch
499+ test_base : TestBase , aiohttp_server , monkeypatch
557500):
558- _ , memory_exporter = tracer
559- _ , metrics_reader = meter
560501 monkeypatch .setenv (
561502 OTEL_SEMCONV_STABILITY_OPT_IN , _StabilityMode .DEFAULT .value
562503 )
@@ -573,7 +514,7 @@ async def test_semantic_conventions_metrics_old_default(
573514 url , headers = {"User-Agent" : "test-agent" }
574515 ) as response :
575516 assert response .status == 200
576- spans = memory_exporter .get_finished_spans ()
517+ spans = test_base .get_finished_spans ()
577518 assert len (spans ) == 1
578519 span = spans [0 ]
579520
@@ -604,7 +545,7 @@ async def test_semantic_conventions_metrics_old_default(
604545 assert NETWORK_PROTOCOL_VERSION not in span .attributes
605546 assert HTTP_RESPONSE_STATUS_CODE not in span .attributes
606547
607- metrics = _get_sorted_metrics ( metrics_reader . get_metrics_data () )
548+ metrics = test_base . get_sorted_metrics ( )
608549 expected_metric_names = [
609550 "http.server.active_requests" ,
610551 "http.server.duration" ,
@@ -629,10 +570,8 @@ async def test_semantic_conventions_metrics_old_default(
629570# pylint: disable=too-many-locals
630571@pytest .mark .asyncio
631572async def test_semantic_conventions_metrics_new (
632- tracer , meter , aiohttp_server , monkeypatch
573+ test_base : TestBase , meter , aiohttp_server , monkeypatch
633574):
634- _ , memory_exporter = tracer
635- _ , metrics_reader = meter
636575 monkeypatch .setenv (
637576 OTEL_SEMCONV_STABILITY_OPT_IN , _StabilityMode .HTTP .value
638577 )
@@ -649,7 +588,7 @@ async def test_semantic_conventions_metrics_new(
649588 url , headers = {"User-Agent" : "test-agent" }
650589 ) as response :
651590 assert response .status == 200
652- spans = memory_exporter .get_finished_spans ()
591+ spans = test_base .get_finished_spans ()
653592 assert len (spans ) == 1
654593 span = spans [0 ]
655594
@@ -680,7 +619,7 @@ async def test_semantic_conventions_metrics_new(
680619 assert HTTP_FLAVOR not in span .attributes
681620 assert HTTP_STATUS_CODE not in span .attributes
682621
683- metrics = _get_sorted_metrics ( metrics_reader . get_metrics_data () )
622+ metrics = test_base . get_sorted_metrics ( )
684623 expected_metric_names = [
685624 "http.server.active_requests" ,
686625 "http.server.request.duration" ,
@@ -714,10 +653,8 @@ async def test_semantic_conventions_metrics_new(
714653# pylint: disable=too-many-statements
715654@pytest .mark .asyncio
716655async def test_semantic_conventions_metrics_both (
717- tracer , meter , aiohttp_server , monkeypatch
656+ test_base : TestBase , meter , aiohttp_server , monkeypatch
718657):
719- _ , memory_exporter = tracer
720- _ , metrics_reader = meter
721658 monkeypatch .setenv (
722659 OTEL_SEMCONV_STABILITY_OPT_IN , _StabilityMode .HTTP_DUP .value
723660 )
@@ -734,7 +671,7 @@ async def test_semantic_conventions_metrics_both(
734671 url , headers = {"User-Agent" : "test-agent" }
735672 ) as response :
736673 assert response .status == 200
737- spans = memory_exporter .get_finished_spans ()
674+ spans = test_base .get_finished_spans ()
738675 assert len (spans ) == 1
739676 span = spans [0 ]
740677
@@ -764,7 +701,7 @@ async def test_semantic_conventions_metrics_both(
764701 assert span .attributes .get (HTTP_RESPONSE_STATUS_CODE ) == 200
765702 assert span .attributes .get (HTTP_ROUTE ) == "default_handler"
766703
767- metrics = _get_sorted_metrics ( metrics_reader . get_metrics_data () )
704+ metrics = test_base . get_sorted_metrics ( )
768705 assert len (metrics ) == 3 # Both duration metrics + active requests
769706 server_active_requests_count_attrs_both = list (
770707 _server_active_requests_count_attrs_old
0 commit comments