diff --git a/CHANGELOG.md b/CHANGELOG.md index 4da62257af..6cb4e01a38 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `opentelemetry-instrumentation-fastapi`: fix wrapping of middlewares ([#3012](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3012)) +- `opentelemetry-instrumentation-flask`: proper bucket boundaries in stable semconv http duration + ([#3523](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3523)) - `opentelemetry-instrumentation-django`: proper bucket boundaries in stable semconv http duration ([#3524](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3524)) - `opentelemetry-instrumentation-grpc`: support non-list interceptors diff --git a/instrumentation/opentelemetry-instrumentation-flask/src/opentelemetry/instrumentation/flask/__init__.py b/instrumentation/opentelemetry-instrumentation-flask/src/opentelemetry/instrumentation/flask/__init__.py index 40618bfeda..12db5b9a68 100644 --- a/instrumentation/opentelemetry-instrumentation-flask/src/opentelemetry/instrumentation/flask/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-flask/src/opentelemetry/instrumentation/flask/__init__.py @@ -257,6 +257,7 @@ def response_hook(span: Span, status: str, response_headers: List): import opentelemetry.instrumentation.wsgi as otel_wsgi from opentelemetry import context, trace from opentelemetry.instrumentation._semconv import ( + HTTP_DURATION_HISTOGRAM_BUCKETS_NEW, _get_schema_url, _OpenTelemetrySemanticConventionStability, _OpenTelemetryStabilitySignalType, @@ -583,6 +584,7 @@ def __init__(self, *args, **kwargs): name=HTTP_SERVER_REQUEST_DURATION, unit="s", description="Duration of HTTP server requests.", + explicit_bucket_boundaries_advisory=HTTP_DURATION_HISTOGRAM_BUCKETS_NEW, ) active_requests_counter = meter.create_up_down_counter( name=MetricInstruments.HTTP_SERVER_ACTIVE_REQUESTS, @@ -716,6 +718,7 @@ def instrument_app( name=HTTP_SERVER_REQUEST_DURATION, unit="s", description="Duration of HTTP server requests.", + explicit_bucket_boundaries_advisory=HTTP_DURATION_HISTOGRAM_BUCKETS_NEW, ) active_requests_counter = meter.create_up_down_counter( name=MetricInstruments.HTTP_SERVER_ACTIVE_REQUESTS, diff --git a/instrumentation/opentelemetry-instrumentation-flask/tests/test_programmatic.py b/instrumentation/opentelemetry-instrumentation-flask/tests/test_programmatic.py index e6bc8202df..afcf750e0e 100644 --- a/instrumentation/opentelemetry-instrumentation-flask/tests/test_programmatic.py +++ b/instrumentation/opentelemetry-instrumentation-flask/tests/test_programmatic.py @@ -20,6 +20,7 @@ from opentelemetry import trace from opentelemetry.instrumentation._semconv import ( + HTTP_DURATION_HISTOGRAM_BUCKETS_NEW, OTEL_SEMCONV_STABILITY_OPT_IN, _OpenTelemetrySemanticConventionStability, _server_active_requests_count_attrs_new, @@ -522,6 +523,10 @@ def test_flask_metrics_new_semconv(self): self.assertAlmostEqual( duration_s, point.sum, places=1 ) + self.assertEqual( + point.explicit_bounds, + HTTP_DURATION_HISTOGRAM_BUCKETS_NEW, + ) histogram_data_point_seen = True if isinstance(point, NumberDataPoint): number_data_point_seen = True @@ -552,8 +557,12 @@ def test_flask_metric_values(self): self.assertEqual(point.value, 0) def _assert_basic_metric( - self, expected_duration_attributes, expected_requests_count_attributes + self, + expected_duration_attributes, + expected_requests_count_attributes, + expected_histogram_explicit_bounds=None, ): + # pylint: disable=too-many-nested-blocks metrics_list = self.memory_metrics_reader.get_metrics_data() for resource_metric in metrics_list.resource_metrics: for scope_metrics in resource_metric.scope_metrics: @@ -564,6 +573,11 @@ def _assert_basic_metric( expected_duration_attributes, dict(point.attributes), ) + if expected_histogram_explicit_bounds is not None: + self.assertEqual( + expected_histogram_explicit_bounds, + point.explicit_bounds, + ) self.assertEqual(point.count, 1) elif isinstance(point, NumberDataPoint): self.assertDictEqual( @@ -613,6 +627,7 @@ def test_basic_metric_success_new_semconv(self): self._assert_basic_metric( expected_duration_attributes, expected_requests_count_attributes, + expected_histogram_explicit_bounds=HTTP_DURATION_HISTOGRAM_BUCKETS_NEW, ) def test_basic_metric_nonstandard_http_method_success(self): @@ -654,6 +669,7 @@ def test_basic_metric_nonstandard_http_method_success_new_semconv(self): self._assert_basic_metric( expected_duration_attributes, expected_requests_count_attributes, + expected_histogram_explicit_bounds=HTTP_DURATION_HISTOGRAM_BUCKETS_NEW, ) @patch.dict( @@ -679,6 +695,7 @@ def test_basic_metric_nonstandard_http_method_allowed_success_new_semconv( self._assert_basic_metric( expected_duration_attributes, expected_requests_count_attributes, + expected_histogram_explicit_bounds=HTTP_DURATION_HISTOGRAM_BUCKETS_NEW, ) def test_metric_uninstrument(self):