From 14d8181efc93d9194d9314bf4d50b7637cd9bdd4 Mon Sep 17 00:00:00 2001 From: Anuraag Agrawal Date: Fri, 23 Jan 2026 14:20:13 +0900 Subject: [PATCH 1/2] fastapi: use test_base to fetch metrics for assertions or filter locally --- .../tests/test_fastapi_instrumentation.py | 107 +++++++----------- 1 file changed, 43 insertions(+), 64 deletions(-) diff --git a/instrumentation/opentelemetry-instrumentation-fastapi/tests/test_fastapi_instrumentation.py b/instrumentation/opentelemetry-instrumentation-fastapi/tests/test_fastapi_instrumentation.py index d60b169fec..fe124aee4d 100644 --- a/instrumentation/opentelemetry-instrumentation-fastapi/tests/test_fastapi_instrumentation.py +++ b/instrumentation/opentelemetry-instrumentation-fastapi/tests/test_fastapi_instrumentation.py @@ -530,12 +530,13 @@ def test_fastapi_metrics(self): histogram_data_point_seen = False self.assertTrue(len(metrics_list.resource_metrics) == 1) for resource_metric in metrics_list.resource_metrics: - self.assertTrue(len(resource_metric.scope_metrics) == 1) - for scope_metric in resource_metric.scope_metrics: - self.assertEqual( - scope_metric.scope.name, - "opentelemetry.instrumentation.fastapi", - ) + scope_metrics = [ + sm + for sm in resource_metric.scope_metrics + if sm.scope.name == "opentelemetry.instrumentation.fastapi" + ] + self.assertTrue(len(scope_metrics) == 1) + for scope_metric in scope_metrics: self.assertTrue(len(scope_metric.metrics) == 3) for metric in scope_metric.metrics: self.assertIn(metric.name, _expected_metric_names_old) @@ -562,13 +563,13 @@ def test_fastapi_metrics_new_semconv(self): histogram_data_point_seen = False self.assertTrue(len(metrics_list.resource_metrics) == 1) for resource_metric in metrics_list.resource_metrics: - self.assertTrue(len(resource_metric.scope_metrics) == 1) - for scope_metric in resource_metric.scope_metrics: - self.assertEqual( - scope_metric.scope.name, - "opentelemetry.instrumentation.fastapi", - ) - self.assertTrue(len(scope_metric.metrics) == 3) + scope_metrics = [ + sm + for sm in resource_metric.scope_metrics + if sm.scope.name == "opentelemetry.instrumentation.fastapi" + ] + self.assertTrue(len(scope_metrics) == 1) + for scope_metric in scope_metrics: for metric in scope_metric.metrics: self.assertIn(metric.name, _expected_metric_names_new) data_points = list(metric.data.data_points) @@ -594,13 +595,13 @@ def test_fastapi_metrics_both_semconv(self): histogram_data_point_seen = False self.assertTrue(len(metrics_list.resource_metrics) == 1) for resource_metric in metrics_list.resource_metrics: - self.assertTrue(len(resource_metric.scope_metrics) == 1) - for scope_metric in resource_metric.scope_metrics: - self.assertEqual( - scope_metric.scope.name, - "opentelemetry.instrumentation.fastapi", - ) - self.assertTrue(len(scope_metric.metrics) == 5) + scope_metrics = [ + sm + for sm in resource_metric.scope_metrics + if sm.scope.name == "opentelemetry.instrumentation.fastapi" + ] + self.assertTrue(len(scope_metrics) == 1) + for scope_metric in scope_metrics: for metric in scope_metric.metrics: self.assertIn(metric.name, _expected_metric_names_both) data_points = list(metric.data.data_points) @@ -638,10 +639,8 @@ def test_basic_metric_success(self): HTTP_FLAVOR: "1.1", HTTP_SERVER_NAME: "testserver", } - metrics_list = self.memory_metrics_reader.get_metrics_data() - for metric in ( - metrics_list.resource_metrics[0].scope_metrics[0].metrics - ): + metrics = self.get_sorted_metrics() + for metric in metrics: for point in list(metric.data.data_points): if isinstance(point, HistogramDataPoint): self.assertDictEqual( @@ -672,10 +671,8 @@ def test_basic_metric_success_new_semconv(self): HTTP_REQUEST_METHOD: "GET", URL_SCHEME: "https", } - metrics_list = self.memory_metrics_reader.get_metrics_data() - for metric in ( - metrics_list.resource_metrics[0].scope_metrics[0].metrics - ): + metrics = self.get_sorted_metrics() + for metric in metrics: for point in list(metric.data.data_points): if isinstance(point, HistogramDataPoint): self.assertDictEqual( @@ -729,10 +726,8 @@ def test_basic_metric_success_both_semconv(self): HTTP_REQUEST_METHOD: "GET", URL_SCHEME: "https", } - metrics_list = self.memory_metrics_reader.get_metrics_data() - for metric in ( - metrics_list.resource_metrics[0].scope_metrics[0].metrics - ): + metrics = self.get_sorted_metrics() + for metric in metrics: for point in list(metric.data.data_points): if isinstance(point, HistogramDataPoint): self.assertEqual(point.count, 1) @@ -803,10 +798,8 @@ def test_basic_metric_nonstandard_http_method_success(self): HTTP_FLAVOR: "1.1", HTTP_SERVER_NAME: "testserver", } - metrics_list = self.memory_metrics_reader.get_metrics_data() - for metric in ( - metrics_list.resource_metrics[0].scope_metrics[0].metrics - ): + metrics = self.get_sorted_metrics() + for metric in metrics: for point in list(metric.data.data_points): if isinstance(point, HistogramDataPoint): self.assertDictEqual( @@ -837,10 +830,8 @@ def test_basic_metric_nonstandard_http_method_success_new_semconv(self): HTTP_REQUEST_METHOD: "_OTHER", URL_SCHEME: "https", } - metrics_list = self.memory_metrics_reader.get_metrics_data() - for metric in ( - metrics_list.resource_metrics[0].scope_metrics[0].metrics - ): + metrics = self.get_sorted_metrics() + for metric in metrics: for point in list(metric.data.data_points): if isinstance(point, HistogramDataPoint): self.assertDictEqual( @@ -894,10 +885,8 @@ def test_basic_metric_nonstandard_http_method_success_both_semconv(self): HTTP_REQUEST_METHOD: "_OTHER", URL_SCHEME: "https", } - metrics_list = self.memory_metrics_reader.get_metrics_data() - for metric in ( - metrics_list.resource_metrics[0].scope_metrics[0].metrics - ): + metrics = self.get_sorted_metrics() + for metric in metrics: for point in list(metric.data.data_points): if isinstance(point, HistogramDataPoint): self.assertEqual(point.count, 1) @@ -955,10 +944,8 @@ def test_basic_post_request_metric_success(self): duration = max(round((default_timer() - start) * 1000), 0) response_size = int(response.headers.get("content-length")) request_size = int(response.request.headers.get("content-length")) - metrics_list = self.memory_metrics_reader.get_metrics_data() - for metric in ( - metrics_list.resource_metrics[0].scope_metrics[0].metrics - ): + metrics = self.get_sorted_metrics() + for metric in metrics: for point in list(metric.data.data_points): if isinstance(point, HistogramDataPoint): self.assertEqual(point.count, 1) @@ -980,10 +967,8 @@ def test_basic_post_request_metric_success_new_semconv(self): duration_s = max(default_timer() - start, 0) response_size = int(response.headers.get("content-length")) request_size = int(response.request.headers.get("content-length")) - metrics_list = self.memory_metrics_reader.get_metrics_data() - for metric in ( - metrics_list.resource_metrics[0].scope_metrics[0].metrics - ): + metrics = self.get_sorted_metrics() + for metric in metrics: for point in list(metric.data.data_points): if isinstance(point, HistogramDataPoint): self.assertEqual(point.count, 1) @@ -1008,10 +993,8 @@ def test_basic_post_request_metric_success_both_semconv(self): duration_s = max(default_timer() - start, 0) response_size = int(response.headers.get("content-length")) request_size = int(response.request.headers.get("content-length")) - metrics_list = self.memory_metrics_reader.get_metrics_data() - for metric in ( - metrics_list.resource_metrics[0].scope_metrics[0].metrics - ): + metrics = self.get_sorted_metrics() + for metric in metrics: for point in list(metric.data.data_points): if isinstance(point, HistogramDataPoint): self.assertEqual(point.count, 1) @@ -1036,10 +1019,8 @@ def test_metric_uninstrument_app(self): self._client.get("/foobar") self._instrumentor.uninstrument_app(self._app) self._client.get("/foobar") - metrics_list = self.memory_metrics_reader.get_metrics_data() - for metric in ( - metrics_list.resource_metrics[0].scope_metrics[0].metrics - ): + metrics = self.get_sorted_metrics() + for metric in metrics: for point in list(metric.data.data_points): if isinstance(point, HistogramDataPoint): self.assertEqual(point.count, 1) @@ -1053,10 +1034,8 @@ def test_metric_uninstrument(self): self._instrumentor.uninstrument() self._client.get("/foobar") - metrics_list = self.memory_metrics_reader.get_metrics_data() - for metric in ( - metrics_list.resource_metrics[0].scope_metrics[0].metrics - ): + metrics = self.get_sorted_metrics() + for metric in metrics: for point in list(metric.data.data_points): if isinstance(point, HistogramDataPoint): self.assertEqual(point.count, 1) From 9b7c01cfb825c7cfb65548bd15beec7e70dc8f2d Mon Sep 17 00:00:00 2001 From: Anuraag Agrawal Date: Thu, 29 Jan 2026 16:04:28 +0900 Subject: [PATCH 2/2] Pass scope --- .../tests/test_fastapi_instrumentation.py | 142 +++++++----------- 1 file changed, 57 insertions(+), 85 deletions(-) diff --git a/instrumentation/opentelemetry-instrumentation-fastapi/tests/test_fastapi_instrumentation.py b/instrumentation/opentelemetry-instrumentation-fastapi/tests/test_fastapi_instrumentation.py index fe124aee4d..21275366e2 100644 --- a/instrumentation/opentelemetry-instrumentation-fastapi/tests/test_fastapi_instrumentation.py +++ b/instrumentation/opentelemetry-instrumentation-fastapi/tests/test_fastapi_instrumentation.py @@ -151,6 +151,9 @@ def matches(self, scope: Scope) -> tuple[Match, Scope]: return super().matches(scope) +SCOPE = "opentelemetry.instrumentation.fastapi" + + class TestBaseFastAPI(TestBase): def _create_app(self): app = self._create_fastapi_app() @@ -454,7 +457,7 @@ def test_instrument_app_with_instrument(self): self.assertIn("GET /foobar", span.name) self.assertEqual( span.instrumentation_scope.name, - "opentelemetry.instrumentation.fastapi", + SCOPE, ) def test_uninstrument_app(self): @@ -525,97 +528,66 @@ def test_fastapi_metrics(self): self._client.get("/foobar") self._client.get("/foobar") self._client.get("/foobar") - metrics_list = self.memory_metrics_reader.get_metrics_data() number_data_point_seen = False histogram_data_point_seen = False - self.assertTrue(len(metrics_list.resource_metrics) == 1) - for resource_metric in metrics_list.resource_metrics: - scope_metrics = [ - sm - for sm in resource_metric.scope_metrics - if sm.scope.name == "opentelemetry.instrumentation.fastapi" - ] - self.assertTrue(len(scope_metrics) == 1) - for scope_metric in scope_metrics: - self.assertTrue(len(scope_metric.metrics) == 3) - for metric in scope_metric.metrics: - self.assertIn(metric.name, _expected_metric_names_old) - data_points = list(metric.data.data_points) - self.assertEqual(len(data_points), 1) - for point in data_points: - if isinstance(point, HistogramDataPoint): - self.assertEqual(point.count, 3) - histogram_data_point_seen = True - if isinstance(point, NumberDataPoint): - number_data_point_seen = True - for attr in point.attributes: - self.assertIn( - attr, _recommended_attrs_old[metric.name] - ) + metrics = self.get_sorted_metrics(SCOPE) + self.assertTrue(len(metrics) == 3) + for metric in metrics: + self.assertIn(metric.name, _expected_metric_names_old) + data_points = list(metric.data.data_points) + self.assertEqual(len(data_points), 1) + for point in data_points: + if isinstance(point, HistogramDataPoint): + self.assertEqual(point.count, 3) + histogram_data_point_seen = True + if isinstance(point, NumberDataPoint): + number_data_point_seen = True + for attr in point.attributes: + self.assertIn(attr, _recommended_attrs_old[metric.name]) self.assertTrue(number_data_point_seen and histogram_data_point_seen) def test_fastapi_metrics_new_semconv(self): self._client.get("/foobar") self._client.get("/foobar") self._client.get("/foobar") - metrics_list = self.memory_metrics_reader.get_metrics_data() number_data_point_seen = False histogram_data_point_seen = False - self.assertTrue(len(metrics_list.resource_metrics) == 1) - for resource_metric in metrics_list.resource_metrics: - scope_metrics = [ - sm - for sm in resource_metric.scope_metrics - if sm.scope.name == "opentelemetry.instrumentation.fastapi" - ] - self.assertTrue(len(scope_metrics) == 1) - for scope_metric in scope_metrics: - for metric in scope_metric.metrics: - self.assertIn(metric.name, _expected_metric_names_new) - data_points = list(metric.data.data_points) - self.assertEqual(len(data_points), 1) - for point in data_points: - if isinstance(point, HistogramDataPoint): - self.assertEqual(point.count, 3) - histogram_data_point_seen = True - if isinstance(point, NumberDataPoint): - number_data_point_seen = True - for attr in point.attributes: - self.assertIn( - attr, _recommended_attrs_new[metric.name] - ) + metrics = self.get_sorted_metrics(SCOPE) + self.assertTrue(len(metrics) == 3) + for metric in metrics: + self.assertIn(metric.name, _expected_metric_names_new) + data_points = list(metric.data.data_points) + self.assertEqual(len(data_points), 1) + for point in data_points: + if isinstance(point, HistogramDataPoint): + self.assertEqual(point.count, 3) + histogram_data_point_seen = True + if isinstance(point, NumberDataPoint): + number_data_point_seen = True + for attr in point.attributes: + self.assertIn(attr, _recommended_attrs_new[metric.name]) self.assertTrue(number_data_point_seen and histogram_data_point_seen) def test_fastapi_metrics_both_semconv(self): self._client.get("/foobar") self._client.get("/foobar") self._client.get("/foobar") - metrics_list = self.memory_metrics_reader.get_metrics_data() number_data_point_seen = False histogram_data_point_seen = False - self.assertTrue(len(metrics_list.resource_metrics) == 1) - for resource_metric in metrics_list.resource_metrics: - scope_metrics = [ - sm - for sm in resource_metric.scope_metrics - if sm.scope.name == "opentelemetry.instrumentation.fastapi" - ] - self.assertTrue(len(scope_metrics) == 1) - for scope_metric in scope_metrics: - for metric in scope_metric.metrics: - self.assertIn(metric.name, _expected_metric_names_both) - data_points = list(metric.data.data_points) - self.assertEqual(len(data_points), 1) - for point in data_points: - if isinstance(point, HistogramDataPoint): - self.assertEqual(point.count, 3) - histogram_data_point_seen = True - if isinstance(point, NumberDataPoint): - number_data_point_seen = True - for attr in point.attributes: - self.assertIn( - attr, _recommended_attrs_both[metric.name] - ) + metrics = self.get_sorted_metrics(SCOPE) + self.assertTrue(len(metrics) == 5) + for metric in metrics: + self.assertIn(metric.name, _expected_metric_names_both) + data_points = list(metric.data.data_points) + self.assertEqual(len(data_points), 1) + for point in data_points: + if isinstance(point, HistogramDataPoint): + self.assertEqual(point.count, 3) + histogram_data_point_seen = True + if isinstance(point, NumberDataPoint): + number_data_point_seen = True + for attr in point.attributes: + self.assertIn(attr, _recommended_attrs_both[metric.name]) self.assertTrue(number_data_point_seen and histogram_data_point_seen) def test_basic_metric_success(self): @@ -639,7 +611,7 @@ def test_basic_metric_success(self): HTTP_FLAVOR: "1.1", HTTP_SERVER_NAME: "testserver", } - metrics = self.get_sorted_metrics() + metrics = self.get_sorted_metrics(SCOPE) for metric in metrics: for point in list(metric.data.data_points): if isinstance(point, HistogramDataPoint): @@ -671,7 +643,7 @@ def test_basic_metric_success_new_semconv(self): HTTP_REQUEST_METHOD: "GET", URL_SCHEME: "https", } - metrics = self.get_sorted_metrics() + metrics = self.get_sorted_metrics(SCOPE) for metric in metrics: for point in list(metric.data.data_points): if isinstance(point, HistogramDataPoint): @@ -726,7 +698,7 @@ def test_basic_metric_success_both_semconv(self): HTTP_REQUEST_METHOD: "GET", URL_SCHEME: "https", } - metrics = self.get_sorted_metrics() + metrics = self.get_sorted_metrics(SCOPE) for metric in metrics: for point in list(metric.data.data_points): if isinstance(point, HistogramDataPoint): @@ -798,7 +770,7 @@ def test_basic_metric_nonstandard_http_method_success(self): HTTP_FLAVOR: "1.1", HTTP_SERVER_NAME: "testserver", } - metrics = self.get_sorted_metrics() + metrics = self.get_sorted_metrics(SCOPE) for metric in metrics: for point in list(metric.data.data_points): if isinstance(point, HistogramDataPoint): @@ -830,7 +802,7 @@ def test_basic_metric_nonstandard_http_method_success_new_semconv(self): HTTP_REQUEST_METHOD: "_OTHER", URL_SCHEME: "https", } - metrics = self.get_sorted_metrics() + metrics = self.get_sorted_metrics(SCOPE) for metric in metrics: for point in list(metric.data.data_points): if isinstance(point, HistogramDataPoint): @@ -885,7 +857,7 @@ def test_basic_metric_nonstandard_http_method_success_both_semconv(self): HTTP_REQUEST_METHOD: "_OTHER", URL_SCHEME: "https", } - metrics = self.get_sorted_metrics() + metrics = self.get_sorted_metrics(SCOPE) for metric in metrics: for point in list(metric.data.data_points): if isinstance(point, HistogramDataPoint): @@ -944,7 +916,7 @@ def test_basic_post_request_metric_success(self): duration = max(round((default_timer() - start) * 1000), 0) response_size = int(response.headers.get("content-length")) request_size = int(response.request.headers.get("content-length")) - metrics = self.get_sorted_metrics() + metrics = self.get_sorted_metrics(SCOPE) for metric in metrics: for point in list(metric.data.data_points): if isinstance(point, HistogramDataPoint): @@ -967,7 +939,7 @@ def test_basic_post_request_metric_success_new_semconv(self): duration_s = max(default_timer() - start, 0) response_size = int(response.headers.get("content-length")) request_size = int(response.request.headers.get("content-length")) - metrics = self.get_sorted_metrics() + metrics = self.get_sorted_metrics(SCOPE) for metric in metrics: for point in list(metric.data.data_points): if isinstance(point, HistogramDataPoint): @@ -993,7 +965,7 @@ def test_basic_post_request_metric_success_both_semconv(self): duration_s = max(default_timer() - start, 0) response_size = int(response.headers.get("content-length")) request_size = int(response.request.headers.get("content-length")) - metrics = self.get_sorted_metrics() + metrics = self.get_sorted_metrics(SCOPE) for metric in metrics: for point in list(metric.data.data_points): if isinstance(point, HistogramDataPoint): @@ -1019,7 +991,7 @@ def test_metric_uninstrument_app(self): self._client.get("/foobar") self._instrumentor.uninstrument_app(self._app) self._client.get("/foobar") - metrics = self.get_sorted_metrics() + metrics = self.get_sorted_metrics(SCOPE) for metric in metrics: for point in list(metric.data.data_points): if isinstance(point, HistogramDataPoint): @@ -1034,7 +1006,7 @@ def test_metric_uninstrument(self): self._instrumentor.uninstrument() self._client.get("/foobar") - metrics = self.get_sorted_metrics() + metrics = self.get_sorted_metrics(SCOPE) for metric in metrics: for point in list(metric.data.data_points): if isinstance(point, HistogramDataPoint):