diff --git a/CHANGELOG.md b/CHANGELOG.md index 977f4eea8f..588ae40664 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +### Added + +- Add `OTEL_PYTHON_HTTP_SERVER_REQUEST_DURATION_SERVER_ATTRIBUTES_ENABLED` flag to add + `server.address` and `server.port` for `http.server.request.duration` + ([#2597](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2597)) +- Add `OTEL_PYTHON_HTTP_SERVER_ACTIVE_REQUESTS_COUNT_SERVER_ATTRIBUTES_ENABLED` flag to add + `server.address` and `server.port` for `http.server.active_requests` + ([#2597](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2597)) - `opentelemetry-instrumentation-fastapi` Add autoinstrumentation mechanism tests. ([#2860](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2860)) diff --git a/instrumentation/opentelemetry-instrumentation-asgi/src/opentelemetry/instrumentation/asgi/__init__.py b/instrumentation/opentelemetry-instrumentation-asgi/src/opentelemetry/instrumentation/asgi/__init__.py index d25ca41017..e5fbdee542 100644 --- a/instrumentation/opentelemetry-instrumentation-asgi/src/opentelemetry/instrumentation/asgi/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-asgi/src/opentelemetry/instrumentation/asgi/__init__.py @@ -210,9 +210,9 @@ def client_response_hook(span: Span, scope: dict[str, Any], message: dict[str, A _OpenTelemetryStabilitySignalType, _report_new, _report_old, - _server_active_requests_count_attrs_new, + _server_active_requests_count_attrs_new_effective, _server_active_requests_count_attrs_old, - _server_duration_attrs_new, + _server_duration_attrs_new_effective, _server_duration_attrs_old, _set_http_flavor_version, _set_http_host_server, @@ -965,7 +965,7 @@ def _parse_duration_attrs( return _filter_semconv_duration_attrs( req_attrs, _server_duration_attrs_old, - _server_duration_attrs_new, + _server_duration_attrs_new_effective(), sem_conv_opt_in_mode, ) @@ -976,6 +976,6 @@ def _parse_active_request_count_attrs( return _filter_semconv_active_request_count_attr( req_attrs, _server_active_requests_count_attrs_old, - _server_active_requests_count_attrs_new, + _server_active_requests_count_attrs_new_effective(), sem_conv_opt_in_mode, ) diff --git a/instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/middleware/otel_middleware.py b/instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/middleware/otel_middleware.py index 667d6f1091..ff308ccf5f 100644 --- a/instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/middleware/otel_middleware.py +++ b/instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/middleware/otel_middleware.py @@ -28,9 +28,9 @@ _HTTPStabilityMode, _report_new, _report_old, - _server_active_requests_count_attrs_new, + _server_active_requests_count_attrs_new_effective, _server_active_requests_count_attrs_old, - _server_duration_attrs_new, + _server_duration_attrs_new_effective, _server_duration_attrs_old, ) from opentelemetry.instrumentation.propagators import ( @@ -455,7 +455,7 @@ def _parse_duration_attrs( return _filter_semconv_duration_attrs( req_attrs, _server_duration_attrs_old, - _server_duration_attrs_new, + _server_duration_attrs_new_effective(), sem_conv_opt_in_mode, ) @@ -466,6 +466,6 @@ def _parse_active_request_count_attrs( return _filter_semconv_active_request_count_attr( req_attrs, _server_active_requests_count_attrs_old, - _server_active_requests_count_attrs_new, + _server_active_requests_count_attrs_new_effective(), sem_conv_opt_in_mode, ) diff --git a/instrumentation/opentelemetry-instrumentation-flask/tests/test_programmatic.py b/instrumentation/opentelemetry-instrumentation-flask/tests/test_programmatic.py index 4458daae21..6f4cb7c344 100644 --- a/instrumentation/opentelemetry-instrumentation-flask/tests/test_programmatic.py +++ b/instrumentation/opentelemetry-instrumentation-flask/tests/test_programmatic.py @@ -20,6 +20,8 @@ from opentelemetry import trace from opentelemetry.instrumentation._semconv import ( + OTEL_PYTHON_HTTP_SERVER_ACTIVE_REQUESTS_COUNT_SERVER_ATTRIBUTES_ENABLED, + OTEL_PYTHON_HTTP_SERVER_REQUEST_DURATION_SERVER_ATTRIBUTES_ENABLED, OTEL_SEMCONV_STABILITY_OPT_IN, _OpenTelemetrySemanticConventionStability, _server_active_requests_count_attrs_new, @@ -514,22 +516,25 @@ def test_flask_metrics_new_semconv(self): self.assertTrue(len(scope_metric.metrics) != 0) 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) - self.assertAlmostEqual( - duration_s, point.sum, places=2 - ) - histogram_data_point_seen = True - if isinstance(point, NumberDataPoint): - number_data_point_seen = True - for attr in point.attributes: - self.assertIn( - attr, - _recommended_metrics_attrs_new[metric.name], - ) + with self.subTest(metric=metric.name): + 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) + self.assertAlmostEqual( + duration_s, point.sum, places=2 + ) + histogram_data_point_seen = True + if isinstance(point, NumberDataPoint): + number_data_point_seen = True + for attr in point.attributes: + self.assertIn( + attr, + _recommended_metrics_attrs_new[ + metric.name + ], + ) self.assertTrue(number_data_point_seen and histogram_data_point_seen) def test_flask_metric_values(self): @@ -615,6 +620,35 @@ def test_basic_metric_success_new_semconv(self): expected_requests_count_attributes, ) + @patch.dict( + "os.environ", + { + OTEL_PYTHON_HTTP_SERVER_REQUEST_DURATION_SERVER_ATTRIBUTES_ENABLED: "1", + OTEL_PYTHON_HTTP_SERVER_ACTIVE_REQUESTS_COUNT_SERVER_ATTRIBUTES_ENABLED: "1", + }, + ) + def test_basic_metric_success_new_semconv_server_address(self): + self.client.get("/hello/756") + expected_duration_attributes = { + "http.request.method": "GET", + "url.scheme": "http", + "http.route": "/hello/", + "network.protocol.version": "1.1", + "http.response.status_code": 200, + "server.address": "localhost", + "server.port": 80, + } + expected_requests_count_attributes = { + "http.request.method": "GET", + "url.scheme": "http", + "server.address": "localhost", + "server.port": 80, + } + self._assert_basic_metric( + expected_duration_attributes, + expected_requests_count_attributes, + ) + def test_basic_metric_nonstandard_http_method_success(self): self.client.open("/hello/756", method="NONSTANDARD") expected_duration_attributes = { diff --git a/instrumentation/opentelemetry-instrumentation-wsgi/src/opentelemetry/instrumentation/wsgi/__init__.py b/instrumentation/opentelemetry-instrumentation-wsgi/src/opentelemetry/instrumentation/wsgi/__init__.py index c0384d594b..75b4c279a9 100644 --- a/instrumentation/opentelemetry-instrumentation-wsgi/src/opentelemetry/instrumentation/wsgi/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-wsgi/src/opentelemetry/instrumentation/wsgi/__init__.py @@ -222,9 +222,9 @@ def response_hook(span: Span, environ: WSGIEnvironment, status: str, response_he _OpenTelemetryStabilitySignalType, _report_new, _report_old, - _server_active_requests_count_attrs_new, + _server_active_requests_count_attrs_new_effective, _server_active_requests_count_attrs_old, - _server_duration_attrs_new, + _server_duration_attrs_new_effective, _server_duration_attrs_old, _set_http_flavor_version, _set_http_method, @@ -454,7 +454,7 @@ def _parse_active_request_count_attrs( return _filter_semconv_active_request_count_attr( req_attrs, _server_active_requests_count_attrs_old, - _server_active_requests_count_attrs_new, + _server_active_requests_count_attrs_new_effective(), sem_conv_opt_in_mode, ) @@ -465,7 +465,7 @@ def _parse_duration_attrs( return _filter_semconv_duration_attrs( req_attrs, _server_duration_attrs_old, - _server_duration_attrs_new, + _server_duration_attrs_new_effective(), sem_conv_opt_in_mode, ) diff --git a/opentelemetry-instrumentation/src/opentelemetry/instrumentation/_semconv.py b/opentelemetry-instrumentation/src/opentelemetry/instrumentation/_semconv.py index c4e720fd04..1136a1c3bb 100644 --- a/opentelemetry-instrumentation/src/opentelemetry/instrumentation/_semconv.py +++ b/opentelemetry-instrumentation/src/opentelemetry/instrumentation/_semconv.py @@ -47,6 +47,13 @@ from opentelemetry.semconv.trace import SpanAttributes from opentelemetry.trace.status import Status, StatusCode +OTEL_PYTHON_HTTP_SERVER_ACTIVE_REQUESTS_COUNT_SERVER_ATTRIBUTES_ENABLED = ( + "OTEL_PYTHON_HTTP_SERVER_ACTIVE_REQUESTS_COUNT_SERVER_ATTRIBUTES_ENABLED" +) +OTEL_PYTHON_HTTP_SERVER_REQUEST_DURATION_SERVER_ATTRIBUTES_ENABLED = ( + "OTEL_PYTHON_HTTP_SERVER_REQUEST_DURATION_SERVER_ATTRIBUTES_ENABLED" +) + # These lists represent attributes for metrics that are currently supported _client_duration_attrs_old = [ @@ -90,6 +97,14 @@ URL_SCHEME, ] +_server_duration_attrs_new_with_server_attributes = ( + _server_duration_attrs_new + + [ + SERVER_ADDRESS, + SERVER_PORT, + ] +) + _server_active_requests_count_attrs_old = [ SpanAttributes.HTTP_METHOD, SpanAttributes.HTTP_HOST, @@ -101,9 +116,37 @@ _server_active_requests_count_attrs_new = [ HTTP_REQUEST_METHOD, URL_SCHEME, - # TODO: Support SERVER_ADDRESS AND SERVER_PORT ] +_server_active_requests_count_attrs_new_with_server_attributes = ( + _server_active_requests_count_attrs_new + + [ + SERVER_ADDRESS, + SERVER_PORT, + ] +) + + +def _server_active_requests_count_attrs_new_effective(): + return ( + _server_active_requests_count_attrs_new_with_server_attributes + if os.environ.get( + OTEL_PYTHON_HTTP_SERVER_ACTIVE_REQUESTS_COUNT_SERVER_ATTRIBUTES_ENABLED + ) + else _server_active_requests_count_attrs_new + ) + + +def _server_duration_attrs_new_effective(): + return ( + _server_duration_attrs_new_with_server_attributes + if os.environ.get( + OTEL_PYTHON_HTTP_SERVER_REQUEST_DURATION_SERVER_ATTRIBUTES_ENABLED + ) + else _server_duration_attrs_new + ) + + OTEL_SEMCONV_STABILITY_OPT_IN = "OTEL_SEMCONV_STABILITY_OPT_IN"