From 3e0ba7dd3cf4bf0bc8b5ae325368705e2d949454 Mon Sep 17 00:00:00 2001 From: GonzaloGuasch Date: Wed, 19 Jun 2024 11:43:03 -0300 Subject: [PATCH 01/15] add metric attribute --- CHANGELOG.md | 2 ++ .../instrumentation/flask/__init__.py | 26 ++++++++++++++++--- .../tests/test_programmatic.py | 9 ++++--- 3 files changed, 31 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dff32bafca..9f7b01f4b2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- `opentelemetry-instrumentation-flask` Add http route to metric attributes + ([#2506](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2506)) - `opentelemetry-sdk-extension-aws` Register AWS resource detectors under the `opentelemetry_resource_detector` entry point ([#2382](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2382)) 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 f2e0ee34cc..616850959f 100644 --- a/instrumentation/opentelemetry-instrumentation-flask/src/opentelemetry/instrumentation/flask/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-flask/src/opentelemetry/instrumentation/flask/__init__.py @@ -251,7 +251,6 @@ 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 ( - _METRIC_ATTRIBUTES_SERVER_DURATION_NAME, _get_schema_url, _HTTPStabilityMode, _OpenTelemetrySemanticConventionStability, @@ -268,6 +267,9 @@ def response_hook(span: Span, status: str, response_headers: List): from opentelemetry.instrumentation.utils import _start_internal_or_server_span from opentelemetry.metrics import get_meter from opentelemetry.semconv.metrics import MetricInstruments +from opentelemetry.semconv.metrics.http_metrics import ( + HTTP_SERVER_REQUEST_DURATION, +) from opentelemetry.semconv.trace import SpanAttributes from opentelemetry.util.http import ( get_excluded_urls, @@ -282,6 +284,7 @@ def response_hook(span: Span, status: str, response_headers: List): _ENVIRON_ACTIVATION_KEY = "opentelemetry-flask.activation_key" _ENVIRON_REQCTX_REF_KEY = "opentelemetry-flask.reqctx_ref_key" _ENVIRON_TOKEN = "opentelemetry-flask.token" +_ENVIRON_REQUEST_ROUTE_KEY = "request-route_key" _excluded_urls_from_env = get_excluded_urls("FLASK") @@ -344,6 +347,11 @@ def _start_response(status, response_headers, *args, **kwargs): excluded_urls is None or not excluded_urls.url_disabled(flask.request.url) ): + if flask.request.url_rule: + wrapped_app_environ[_ENVIRON_REQUEST_ROUTE_KEY] = str( + flask.request.url_rule + ) + span = flask.request.environ.get(_ENVIRON_SPAN_KEY) propagator = get_global_response_propagator() @@ -386,6 +394,12 @@ def _start_response(status, response_headers, *args, **kwargs): duration_attrs_old = otel_wsgi._parse_duration_attrs( attributes, _HTTPStabilityMode.DEFAULT ) + + if wrapped_app_environ.get(_ENVIRON_REQUEST_ROUTE_KEY, None): + duration_attrs_old[SpanAttributes.HTTP_ROUTE] = ( + wrapped_app_environ.get(_ENVIRON_REQUEST_ROUTE_KEY) + ) + duration_histogram_old.record( max(round(duration_s * 1000), 0), duration_attrs_old ) @@ -393,6 +407,12 @@ def _start_response(status, response_headers, *args, **kwargs): duration_attrs_new = otel_wsgi._parse_duration_attrs( attributes, _HTTPStabilityMode.HTTP ) + + if wrapped_app_environ.get(_ENVIRON_REQUEST_ROUTE_KEY, None): + duration_attrs_new[SpanAttributes.HTTP_ROUTE] = ( + wrapped_app_environ.get(_ENVIRON_REQUEST_ROUTE_KEY) + ) + duration_histogram_new.record( max(duration_s, 0), duration_attrs_new ) @@ -553,7 +573,7 @@ def __init__(self, *args, **kwargs): duration_histogram_new = None if _report_new(_InstrumentedFlask._sem_conv_opt_in_mode): duration_histogram_new = meter.create_histogram( - name=_METRIC_ATTRIBUTES_SERVER_DURATION_NAME, + name=HTTP_SERVER_REQUEST_DURATION, unit="s", description="measures the duration of the inbound HTTP request", ) @@ -684,7 +704,7 @@ def instrument_app( duration_histogram_new = None if _report_new(sem_conv_opt_in_mode): duration_histogram_new = meter.create_histogram( - name=_METRIC_ATTRIBUTES_SERVER_DURATION_NAME, + name=HTTP_SERVER_REQUEST_DURATION, unit="s", description="measures the duration of the inbound HTTP request", ) diff --git a/instrumentation/opentelemetry-instrumentation-flask/tests/test_programmatic.py b/instrumentation/opentelemetry-instrumentation-flask/tests/test_programmatic.py index d30a100b0e..3f16764a76 100644 --- a/instrumentation/opentelemetry-instrumentation-flask/tests/test_programmatic.py +++ b/instrumentation/opentelemetry-instrumentation-flask/tests/test_programmatic.py @@ -20,7 +20,6 @@ from opentelemetry import trace from opentelemetry.instrumentation._semconv import ( - _SPAN_ATTRIBUTES_ERROR_TYPE, OTEL_SEMCONV_STABILITY_OPT_IN, _OpenTelemetrySemanticConventionStability, _server_active_requests_count_attrs_new, @@ -40,6 +39,7 @@ NumberDataPoint, ) from opentelemetry.sdk.resources import Resource +from opentelemetry.semconv.attributes.error_attributes import ERROR_TYPE from opentelemetry.semconv.trace import SpanAttributes from opentelemetry.test.wsgitestutil import WsgiTestBase from opentelemetry.util.http import ( @@ -379,7 +379,7 @@ def test_internal_error_new_semconv(self): SpanAttributes.URL_PATH: "/hello/500", SpanAttributes.HTTP_ROUTE: "/hello/", SpanAttributes.HTTP_RESPONSE_STATUS_CODE: 500, - _SPAN_ATTRIBUTES_ERROR_TYPE: "500", + ERROR_TYPE: "500", SpanAttributes.URL_SCHEME: "http", } ) @@ -405,7 +405,7 @@ def test_internal_error_both_semconv(self): { SpanAttributes.URL_PATH: "/hello/500", SpanAttributes.HTTP_RESPONSE_STATUS_CODE: 500, - _SPAN_ATTRIBUTES_ERROR_TYPE: "500", + ERROR_TYPE: "500", SpanAttributes.URL_SCHEME: "http", } ) @@ -459,6 +459,7 @@ def test_exclude_lists_from_explicit(self): self.assertEqual(len(span_list), 1) def test_flask_metrics(self): + _server_duration_attrs_old.append("http.route") start = default_timer() self.client.get("/hello/123") self.client.get("/hello/321") @@ -570,6 +571,7 @@ def test_basic_metric_success(self): self.client.get("/hello/756") expected_duration_attributes = { "http.method": "GET", + "http.route": "/hello/", "http.host": "localhost", "http.scheme": "http", "http.flavor": "1.1", @@ -597,6 +599,7 @@ def test_basic_metric_success_new_semconv(self): expected_duration_attributes = { "http.request.method": "GET", "url.scheme": "http", + "http.route": "/hello/", "network.protocol.version": "1.1", "http.response.status_code": 200, } From 86fe2e6940ae2c7b4ecb3144b8eb34099d7abd43 Mon Sep 17 00:00:00 2001 From: GonzaloGuasch Date: Mon, 24 Jun 2024 17:57:11 -0300 Subject: [PATCH 02/15] Update changelog && change variable in test --- CHANGELOG.md | 2 +- .../tests/test_programmatic.py | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9f7b01f4b2..0caa0fc346 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,7 +22,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added -- `opentelemetry-instrumentation-flask` Add http route to metric attributes +- `opentelemetry-instrumentation-flask` Add `http.route` to metric attributes ([#2506](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2506)) - `opentelemetry-sdk-extension-aws` Register AWS resource detectors under the `opentelemetry_resource_detector` entry point diff --git a/instrumentation/opentelemetry-instrumentation-flask/tests/test_programmatic.py b/instrumentation/opentelemetry-instrumentation-flask/tests/test_programmatic.py index 3f16764a76..f2508f6dfa 100644 --- a/instrumentation/opentelemetry-instrumentation-flask/tests/test_programmatic.py +++ b/instrumentation/opentelemetry-instrumentation-flask/tests/test_programmatic.py @@ -85,6 +85,9 @@ def expected_attributes_new(override_attributes): return default_attributes +_server_duration_attrs_old_copy = _server_duration_attrs_old.copy() +_server_duration_attrs_old_copy.append("http.route") + _expected_metric_names_old = [ "http.server.active_requests", "http.server.duration", @@ -95,7 +98,7 @@ def expected_attributes_new(override_attributes): ] _recommended_metrics_attrs_old = { "http.server.active_requests": _server_active_requests_count_attrs_old, - "http.server.duration": _server_duration_attrs_old, + "http.server.duration": _server_duration_attrs_old_copy, } _recommended_metrics_attrs_new = { "http.server.active_requests": _server_active_requests_count_attrs_new, @@ -109,7 +112,7 @@ def expected_attributes_new(override_attributes): ) _recommended_metrics_attrs_both = { "http.server.active_requests": _server_active_requests_count_attrs_both, - "http.server.duration": _server_duration_attrs_old, + "http.server.duration": _server_duration_attrs_old_copy, "http.server.request.duration": _server_duration_attrs_new, } From fc48830e29996fce9cfe4de0cfa086ff704f6e72 Mon Sep 17 00:00:00 2001 From: GonzaloGuasch Date: Mon, 24 Jun 2024 20:25:45 -0300 Subject: [PATCH 03/15] Remove append from test --- .../tests/test_programmatic.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/instrumentation/opentelemetry-instrumentation-flask/tests/test_programmatic.py b/instrumentation/opentelemetry-instrumentation-flask/tests/test_programmatic.py index f2508f6dfa..1d56a841e2 100644 --- a/instrumentation/opentelemetry-instrumentation-flask/tests/test_programmatic.py +++ b/instrumentation/opentelemetry-instrumentation-flask/tests/test_programmatic.py @@ -462,7 +462,6 @@ def test_exclude_lists_from_explicit(self): self.assertEqual(len(span_list), 1) def test_flask_metrics(self): - _server_duration_attrs_old.append("http.route") start = default_timer() self.client.get("/hello/123") self.client.get("/hello/321") @@ -587,6 +586,7 @@ def test_basic_metric_success(self): "http.method": "GET", "http.host": "localhost", "http.scheme": "http", + "http.flavor": "1.1", "http.server_name": "localhost", "net.host.name": "localhost", From b2c8849b9eec08450c42dbb9a2c5352f8b3818e5 Mon Sep 17 00:00:00 2001 From: GonzaloGuasch Date: Mon, 24 Jun 2024 20:38:48 -0300 Subject: [PATCH 04/15] Change to new HTTP_ROUTE semconv & linter fix --- .../instrumentation/flask/__init__.py | 14 +++++++------- .../tests/test_programmatic.py | 1 - 2 files changed, 7 insertions(+), 8 deletions(-) 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 616850959f..996004aa7f 100644 --- a/instrumentation/opentelemetry-instrumentation-flask/src/opentelemetry/instrumentation/flask/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-flask/src/opentelemetry/instrumentation/flask/__init__.py @@ -266,11 +266,11 @@ def response_hook(span: Span, status: str, response_headers: List): ) from opentelemetry.instrumentation.utils import _start_internal_or_server_span from opentelemetry.metrics import get_meter +from opentelemetry.semconv.attributes.http_attributes import HTTP_ROUTE from opentelemetry.semconv.metrics import MetricInstruments from opentelemetry.semconv.metrics.http_metrics import ( HTTP_SERVER_REQUEST_DURATION, ) -from opentelemetry.semconv.trace import SpanAttributes from opentelemetry.util.http import ( get_excluded_urls, parse_excluded_urls, @@ -284,7 +284,7 @@ def response_hook(span: Span, status: str, response_headers: List): _ENVIRON_ACTIVATION_KEY = "opentelemetry-flask.activation_key" _ENVIRON_REQCTX_REF_KEY = "opentelemetry-flask.reqctx_ref_key" _ENVIRON_TOKEN = "opentelemetry-flask.token" -_ENVIRON_REQUEST_ROUTE_KEY = "request-route_key" +_ENVIRON_REQUEST_ROUTE_KEY = "opentelemetry-flask.request-route_key" _excluded_urls_from_env = get_excluded_urls("FLASK") @@ -396,8 +396,8 @@ def _start_response(status, response_headers, *args, **kwargs): ) if wrapped_app_environ.get(_ENVIRON_REQUEST_ROUTE_KEY, None): - duration_attrs_old[SpanAttributes.HTTP_ROUTE] = ( - wrapped_app_environ.get(_ENVIRON_REQUEST_ROUTE_KEY) + duration_attrs_old[HTTP_ROUTE] = wrapped_app_environ.get( + _ENVIRON_REQUEST_ROUTE_KEY ) duration_histogram_old.record( @@ -409,8 +409,8 @@ def _start_response(status, response_headers, *args, **kwargs): ) if wrapped_app_environ.get(_ENVIRON_REQUEST_ROUTE_KEY, None): - duration_attrs_new[SpanAttributes.HTTP_ROUTE] = ( - wrapped_app_environ.get(_ENVIRON_REQUEST_ROUTE_KEY) + duration_attrs_new[HTTP_ROUTE] = wrapped_app_environ.get( + _ENVIRON_REQUEST_ROUTE_KEY ) duration_histogram_new.record( @@ -443,7 +443,7 @@ def _before_request(): if flask.request.url_rule: # For 404 that result from no route found, etc, we # don't have a url_rule. - attributes[SpanAttributes.HTTP_ROUTE] = flask.request.url_rule.rule + attributes[HTTP_ROUTE] = flask.request.url_rule.rule span, token = _start_internal_or_server_span( tracer=tracer, span_name=span_name, diff --git a/instrumentation/opentelemetry-instrumentation-flask/tests/test_programmatic.py b/instrumentation/opentelemetry-instrumentation-flask/tests/test_programmatic.py index 1d56a841e2..d84c8b345b 100644 --- a/instrumentation/opentelemetry-instrumentation-flask/tests/test_programmatic.py +++ b/instrumentation/opentelemetry-instrumentation-flask/tests/test_programmatic.py @@ -586,7 +586,6 @@ def test_basic_metric_success(self): "http.method": "GET", "http.host": "localhost", "http.scheme": "http", - "http.flavor": "1.1", "http.server_name": "localhost", "net.host.name": "localhost", From 6633306e0b8d9a92672ec8a501ceb3e79a753e96 Mon Sep 17 00:00:00 2001 From: GonzaloGuasch Date: Mon, 1 Jul 2024 11:56:16 -0300 Subject: [PATCH 05/15] Update changelog --- CHANGELOG.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aace8e7fc2..3544d7c456 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## Unreleased - +- `opentelemetry-instrumentation-flask` Add `http.route` to metric attributes + ([#2621](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2621)) - `opentelemetry-instrumentation-aws-lambda` Bugfix: AWS Lambda event source key incorrect for SNS in instrumentation library. ([#2612](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2612)) - `opentelemetry-instrumentation-system-metrics` Permit to use psutil 6.0+. @@ -61,8 +62,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added -- `opentelemetry-instrumentation-flask` Add `http.route` to metric attributes - ([#2506](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2506)) - `opentelemetry-sdk-extension-aws` Register AWS resource detectors under the `opentelemetry_resource_detector` entry point ([#2382](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2382)) From 36f20785acd15ab846b635bbe23cc615db9aeac5 Mon Sep 17 00:00:00 2001 From: GonzaloGuasch Date: Mon, 1 Jul 2024 15:44:12 -0300 Subject: [PATCH 06/15] Update changelog --- CHANGELOG.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3544d7c456..48d043cd87 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,15 +6,14 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## Unreleased -- `opentelemetry-instrumentation-flask` Add `http.route` to metric attributes - ([#2621](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2621)) - `opentelemetry-instrumentation-aws-lambda` Bugfix: AWS Lambda event source key incorrect for SNS in instrumentation library. ([#2612](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2612)) - `opentelemetry-instrumentation-system-metrics` Permit to use psutil 6.0+. ([#2630](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2630)) ### Added - +- `opentelemetry-instrumentation-flask` Add `http.route` to metric attributes + ([#2621](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2621)) - `opentelemetry-instrumentation-pyramid` Record exceptions raised when serving a request ([#2622](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2622)) - `opentelemetry-sdk-extension-aws` Add AwsXrayLambdaPropagator From 335657eeccd82e1be8d0a24880042fa8b8af0442 Mon Sep 17 00:00:00 2001 From: GonzaloGuasch Date: Thu, 11 Jul 2024 17:26:33 -0300 Subject: [PATCH 07/15] Update CHANGELOG.md --- CHANGELOG.md | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1b8352c56a..c6eefcfeca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,16 +6,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## Unreleased -- `opentelemetry-instrumentation-django` Handle exceptions from request/response hooks - ([#2153](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2153)) -- `opentelemetry-instrumentation-asyncio` instrumented `asyncio.wait_for` properly raises `asyncio.TimeoutError` as expected - ([#2637](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2637)) -- `opentelemetry-instrumentation-aws-lambda` Bugfix: AWS Lambda event source key incorrect for SNS in instrumentation library. - ([#2612](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2612)) -- `opentelemetry-instrumentation-system-metrics` Permit to use psutil 6.0+. - ([#2630](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2630)) ### Added + - `opentelemetry-instrumentation-flask` Add `http.route` to metric attributes ([#2621](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2621)) - `opentelemetry-instrumentation-pyramid` Record exceptions raised when serving a request From 304c88be5a34c538c7c77c5ac0550327d87bd382 Mon Sep 17 00:00:00 2001 From: GonzaloGuasch Date: Wed, 17 Jul 2024 17:56:13 -0300 Subject: [PATCH 08/15] Add http.target in metric attribute --- CHANGELOG.md | 2 +- .../opentelemetry/instrumentation/flask/__init__.py | 9 +++++++++ .../tests/test_programmatic.py | 10 ++++++++-- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4538084e8d..35b8b5fb31 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added -- `opentelemetry-instrumentation-flask` Add `http.route` to metric attributes +- `opentelemetry-instrumentation-flask` Add `http.route` and `http.target` to metric attributes ([#2621](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2621)) - `opentelemetry-instrumentation-pyramid` Record exceptions raised when serving a request ([#2622](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2622)) 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 f11b177539..0426e1ba05 100644 --- a/instrumentation/opentelemetry-instrumentation-flask/src/opentelemetry/instrumentation/flask/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-flask/src/opentelemetry/instrumentation/flask/__init__.py @@ -266,6 +266,9 @@ def response_hook(span: Span, status: str, response_headers: List): ) from opentelemetry.instrumentation.utils import _start_internal_or_server_span from opentelemetry.metrics import get_meter +from opentelemetry.semconv._incubating.attributes.http_attributes import ( + HTTP_TARGET, +) from opentelemetry.semconv.attributes.http_attributes import HTTP_ROUTE from opentelemetry.semconv.metrics import MetricInstruments from opentelemetry.semconv.metrics.http_metrics import ( @@ -399,6 +402,9 @@ def _start_response(status, response_headers, *args, **kwargs): duration_attrs_old[HTTP_ROUTE] = wrapped_app_environ.get( _ENVIRON_REQUEST_ROUTE_KEY ) + duration_attrs_old[HTTP_TARGET] = wrapped_app_environ.get( + _ENVIRON_REQUEST_ROUTE_KEY + ) duration_histogram_old.record( max(round(duration_s * 1000), 0), duration_attrs_old @@ -412,6 +418,9 @@ def _start_response(status, response_headers, *args, **kwargs): duration_attrs_new[HTTP_ROUTE] = wrapped_app_environ.get( _ENVIRON_REQUEST_ROUTE_KEY ) + duration_attrs_new[HTTP_TARGET] = wrapped_app_environ.get( + _ENVIRON_REQUEST_ROUTE_KEY + ) duration_histogram_new.record( max(duration_s, 0), duration_attrs_new diff --git a/instrumentation/opentelemetry-instrumentation-flask/tests/test_programmatic.py b/instrumentation/opentelemetry-instrumentation-flask/tests/test_programmatic.py index 7ffc3c4a59..8f4d979e07 100644 --- a/instrumentation/opentelemetry-instrumentation-flask/tests/test_programmatic.py +++ b/instrumentation/opentelemetry-instrumentation-flask/tests/test_programmatic.py @@ -87,6 +87,10 @@ def expected_attributes_new(override_attributes): _server_duration_attrs_old_copy = _server_duration_attrs_old.copy() _server_duration_attrs_old_copy.append("http.route") +_server_duration_attrs_old_copy.append("http.target") + +_server_duration_attrs_new_copy = _server_duration_attrs_new.copy() +_server_duration_attrs_new_copy.append("http.target") _expected_metric_names_old = [ "http.server.active_requests", @@ -102,7 +106,7 @@ def expected_attributes_new(override_attributes): } _recommended_metrics_attrs_new = { "http.server.active_requests": _server_active_requests_count_attrs_new, - "http.server.request.duration": _server_duration_attrs_new, + "http.server.request.duration": _server_duration_attrs_new_copy, } _server_active_requests_count_attrs_both = ( _server_active_requests_count_attrs_old @@ -113,7 +117,7 @@ def expected_attributes_new(override_attributes): _recommended_metrics_attrs_both = { "http.server.active_requests": _server_active_requests_count_attrs_both, "http.server.duration": _server_duration_attrs_old_copy, - "http.server.request.duration": _server_duration_attrs_new, + "http.server.request.duration": _server_duration_attrs_new_copy, } @@ -574,6 +578,7 @@ def test_basic_metric_success(self): expected_duration_attributes = { "http.method": "GET", "http.route": "/hello/", + "http.target": "/hello/", "http.host": "localhost", "http.scheme": "http", "http.flavor": "1.1", @@ -600,6 +605,7 @@ def test_basic_metric_success_new_semconv(self): "http.request.method": "GET", "url.scheme": "http", "http.route": "/hello/", + "http.target": "/hello/", "network.protocol.version": "1.1", "http.response.status_code": 200, } From 7d3c15045e1fe713ac0cf1cd67f7b26f2477f89f Mon Sep 17 00:00:00 2001 From: GonzaloGuasch Date: Thu, 18 Jul 2024 12:55:14 -0300 Subject: [PATCH 09/15] http.target in old sem metric attribute --- .../src/opentelemetry/instrumentation/flask/__init__.py | 6 ------ .../tests/test_programmatic.py | 5 +---- 2 files changed, 1 insertion(+), 10 deletions(-) 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 0426e1ba05..ddd8065a2b 100644 --- a/instrumentation/opentelemetry-instrumentation-flask/src/opentelemetry/instrumentation/flask/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-flask/src/opentelemetry/instrumentation/flask/__init__.py @@ -399,9 +399,6 @@ def _start_response(status, response_headers, *args, **kwargs): ) if wrapped_app_environ.get(_ENVIRON_REQUEST_ROUTE_KEY, None): - duration_attrs_old[HTTP_ROUTE] = wrapped_app_environ.get( - _ENVIRON_REQUEST_ROUTE_KEY - ) duration_attrs_old[HTTP_TARGET] = wrapped_app_environ.get( _ENVIRON_REQUEST_ROUTE_KEY ) @@ -418,9 +415,6 @@ def _start_response(status, response_headers, *args, **kwargs): duration_attrs_new[HTTP_ROUTE] = wrapped_app_environ.get( _ENVIRON_REQUEST_ROUTE_KEY ) - duration_attrs_new[HTTP_TARGET] = wrapped_app_environ.get( - _ENVIRON_REQUEST_ROUTE_KEY - ) duration_histogram_new.record( max(duration_s, 0), duration_attrs_new diff --git a/instrumentation/opentelemetry-instrumentation-flask/tests/test_programmatic.py b/instrumentation/opentelemetry-instrumentation-flask/tests/test_programmatic.py index 8f4d979e07..4458daae21 100644 --- a/instrumentation/opentelemetry-instrumentation-flask/tests/test_programmatic.py +++ b/instrumentation/opentelemetry-instrumentation-flask/tests/test_programmatic.py @@ -86,11 +86,10 @@ def expected_attributes_new(override_attributes): _server_duration_attrs_old_copy = _server_duration_attrs_old.copy() -_server_duration_attrs_old_copy.append("http.route") _server_duration_attrs_old_copy.append("http.target") _server_duration_attrs_new_copy = _server_duration_attrs_new.copy() -_server_duration_attrs_new_copy.append("http.target") +_server_duration_attrs_new_copy.append("http.route") _expected_metric_names_old = [ "http.server.active_requests", @@ -577,7 +576,6 @@ def test_basic_metric_success(self): self.client.get("/hello/756") expected_duration_attributes = { "http.method": "GET", - "http.route": "/hello/", "http.target": "/hello/", "http.host": "localhost", "http.scheme": "http", @@ -605,7 +603,6 @@ def test_basic_metric_success_new_semconv(self): "http.request.method": "GET", "url.scheme": "http", "http.route": "/hello/", - "http.target": "/hello/", "network.protocol.version": "1.1", "http.response.status_code": 200, } From d1c747ef9d5e6b78a7d4c9126614a336fc73ef77 Mon Sep 17 00:00:00 2001 From: GonzaloGuasch Date: Thu, 18 Jul 2024 13:04:18 -0300 Subject: [PATCH 10/15] Change http.target to SpanAttributes.HTTP_TARGET --- .../src/opentelemetry/instrumentation/flask/__init__.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) 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 ddd8065a2b..f008ae11f0 100644 --- a/instrumentation/opentelemetry-instrumentation-flask/src/opentelemetry/instrumentation/flask/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-flask/src/opentelemetry/instrumentation/flask/__init__.py @@ -266,14 +266,12 @@ def response_hook(span: Span, status: str, response_headers: List): ) from opentelemetry.instrumentation.utils import _start_internal_or_server_span from opentelemetry.metrics import get_meter -from opentelemetry.semconv._incubating.attributes.http_attributes import ( - HTTP_TARGET, -) from opentelemetry.semconv.attributes.http_attributes import HTTP_ROUTE from opentelemetry.semconv.metrics import MetricInstruments from opentelemetry.semconv.metrics.http_metrics import ( HTTP_SERVER_REQUEST_DURATION, ) +from opentelemetry.semconv.trace import SpanAttributes from opentelemetry.util.http import ( get_excluded_urls, parse_excluded_urls, @@ -399,10 +397,9 @@ def _start_response(status, response_headers, *args, **kwargs): ) if wrapped_app_environ.get(_ENVIRON_REQUEST_ROUTE_KEY, None): - duration_attrs_old[HTTP_TARGET] = wrapped_app_environ.get( - _ENVIRON_REQUEST_ROUTE_KEY + duration_attrs_old[SpanAttributes.HTTP_TARGET] = ( + wrapped_app_environ.get(_ENVIRON_REQUEST_ROUTE_KEY) ) - duration_histogram_old.record( max(round(duration_s * 1000), 0), duration_attrs_old ) From 93daa359fb537aa3707d04a585fecd39666efa76 Mon Sep 17 00:00:00 2001 From: GonzaloGuasch Date: Thu, 18 Jul 2024 17:20:42 -0300 Subject: [PATCH 11/15] Change http.route to SpanAttributes.HTTP_ROUTE --- .../src/opentelemetry/instrumentation/flask/__init__.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) 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 f008ae11f0..e09dba456f 100644 --- a/instrumentation/opentelemetry-instrumentation-flask/src/opentelemetry/instrumentation/flask/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-flask/src/opentelemetry/instrumentation/flask/__init__.py @@ -266,7 +266,6 @@ def response_hook(span: Span, status: str, response_headers: List): ) from opentelemetry.instrumentation.utils import _start_internal_or_server_span from opentelemetry.metrics import get_meter -from opentelemetry.semconv.attributes.http_attributes import HTTP_ROUTE from opentelemetry.semconv.metrics import MetricInstruments from opentelemetry.semconv.metrics.http_metrics import ( HTTP_SERVER_REQUEST_DURATION, @@ -409,8 +408,8 @@ def _start_response(status, response_headers, *args, **kwargs): ) if wrapped_app_environ.get(_ENVIRON_REQUEST_ROUTE_KEY, None): - duration_attrs_new[HTTP_ROUTE] = wrapped_app_environ.get( - _ENVIRON_REQUEST_ROUTE_KEY + duration_attrs_new[SpanAttributes.HTTP_ROUTE] = ( + wrapped_app_environ.get(_ENVIRON_REQUEST_ROUTE_KEY) ) duration_histogram_new.record( @@ -443,7 +442,7 @@ def _before_request(): if flask.request.url_rule: # For 404 that result from no route found, etc, we # don't have a url_rule. - attributes[HTTP_ROUTE] = flask.request.url_rule.rule + attributes[SpanAttributes.HTTP_ROUTE] = flask.request.url_rule.rule span, token = _start_internal_or_server_span( tracer=tracer, span_name=span_name, From 588199ddda38c82f450670b878548ff8ff3a1692 Mon Sep 17 00:00:00 2001 From: GonzaloGuasch Date: Fri, 19 Jul 2024 12:44:21 -0300 Subject: [PATCH 12/15] Change HTTP_ROUTE import module --- .../src/opentelemetry/instrumentation/flask/__init__.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) 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 e09dba456f..c4937fcee6 100644 --- a/instrumentation/opentelemetry-instrumentation-flask/src/opentelemetry/instrumentation/flask/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-flask/src/opentelemetry/instrumentation/flask/__init__.py @@ -266,6 +266,7 @@ def response_hook(span: Span, status: str, response_headers: List): ) from opentelemetry.instrumentation.utils import _start_internal_or_server_span from opentelemetry.metrics import get_meter +from opentelemetry.semconv.attributes.http_attributes import HTTP_ROUTE from opentelemetry.semconv.metrics import MetricInstruments from opentelemetry.semconv.metrics.http_metrics import ( HTTP_SERVER_REQUEST_DURATION, @@ -408,8 +409,8 @@ def _start_response(status, response_headers, *args, **kwargs): ) if wrapped_app_environ.get(_ENVIRON_REQUEST_ROUTE_KEY, None): - duration_attrs_new[SpanAttributes.HTTP_ROUTE] = ( - wrapped_app_environ.get(_ENVIRON_REQUEST_ROUTE_KEY) + duration_attrs_new[HTTP_ROUTE] = wrapped_app_environ.get( + _ENVIRON_REQUEST_ROUTE_KEY ) duration_histogram_new.record( From cea918d2161f6f151d2946b6583d72f14cab509d Mon Sep 17 00:00:00 2001 From: GonzaloGuasch Date: Fri, 19 Jul 2024 17:03:13 -0300 Subject: [PATCH 13/15] Change env variable to nonlocal var --- .../instrumentation/flask/__init__.py | 20 ++++++++----------- 1 file changed, 8 insertions(+), 12 deletions(-) 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 c4937fcee6..8ec9b3c7f2 100644 --- a/instrumentation/opentelemetry-instrumentation-flask/src/opentelemetry/instrumentation/flask/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-flask/src/opentelemetry/instrumentation/flask/__init__.py @@ -285,7 +285,6 @@ def response_hook(span: Span, status: str, response_headers: List): _ENVIRON_ACTIVATION_KEY = "opentelemetry-flask.activation_key" _ENVIRON_REQCTX_REF_KEY = "opentelemetry-flask.reqctx_ref_key" _ENVIRON_TOKEN = "opentelemetry-flask.token" -_ENVIRON_REQUEST_ROUTE_KEY = "opentelemetry-flask.request-route_key" _excluded_urls_from_env = get_excluded_urls("FLASK") @@ -342,6 +341,7 @@ def _wrapped_app(wrapped_app_environ, start_response): ) active_requests_counter.add(1, active_requests_count_attrs) + request_route = None def _start_response(status, response_headers, *args, **kwargs): if flask.request and ( @@ -349,9 +349,8 @@ def _start_response(status, response_headers, *args, **kwargs): or not excluded_urls.url_disabled(flask.request.url) ): if flask.request.url_rule: - wrapped_app_environ[_ENVIRON_REQUEST_ROUTE_KEY] = str( - flask.request.url_rule - ) + nonlocal request_route + request_route = str(flask.request.url_rule) span = flask.request.environ.get(_ENVIRON_SPAN_KEY) @@ -396,10 +395,9 @@ def _start_response(status, response_headers, *args, **kwargs): attributes, _HTTPStabilityMode.DEFAULT ) - if wrapped_app_environ.get(_ENVIRON_REQUEST_ROUTE_KEY, None): - duration_attrs_old[SpanAttributes.HTTP_TARGET] = ( - wrapped_app_environ.get(_ENVIRON_REQUEST_ROUTE_KEY) - ) + if request_route: + duration_attrs_old[SpanAttributes.HTTP_TARGET] = request_route + duration_histogram_old.record( max(round(duration_s * 1000), 0), duration_attrs_old ) @@ -408,10 +406,8 @@ def _start_response(status, response_headers, *args, **kwargs): attributes, _HTTPStabilityMode.HTTP ) - if wrapped_app_environ.get(_ENVIRON_REQUEST_ROUTE_KEY, None): - duration_attrs_new[HTTP_ROUTE] = wrapped_app_environ.get( - _ENVIRON_REQUEST_ROUTE_KEY - ) + if request_route: + duration_attrs_new[HTTP_ROUTE] = request_route duration_histogram_new.record( max(duration_s, 0), duration_attrs_new From 122ca57936242b1144256ed76b36837a92351e87 Mon Sep 17 00:00:00 2001 From: GonzaloGuasch Date: Fri, 19 Jul 2024 20:23:09 -0300 Subject: [PATCH 14/15] change flask variable str method --- .../src/opentelemetry/instrumentation/flask/__init__.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) 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 8ec9b3c7f2..db81c731f5 100644 --- a/instrumentation/opentelemetry-instrumentation-flask/src/opentelemetry/instrumentation/flask/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-flask/src/opentelemetry/instrumentation/flask/__init__.py @@ -350,7 +350,7 @@ def _start_response(status, response_headers, *args, **kwargs): ): if flask.request.url_rule: nonlocal request_route - request_route = str(flask.request.url_rule) + request_route = flask.request.url_rule span = flask.request.environ.get(_ENVIRON_SPAN_KEY) @@ -396,7 +396,9 @@ def _start_response(status, response_headers, *args, **kwargs): ) if request_route: - duration_attrs_old[SpanAttributes.HTTP_TARGET] = request_route + duration_attrs_old[SpanAttributes.HTTP_TARGET] = str( + request_route + ) duration_histogram_old.record( max(round(duration_s * 1000), 0), duration_attrs_old @@ -407,7 +409,7 @@ def _start_response(status, response_headers, *args, **kwargs): ) if request_route: - duration_attrs_new[HTTP_ROUTE] = request_route + duration_attrs_new[HTTP_ROUTE] = str(request_route) duration_histogram_new.record( max(duration_s, 0), duration_attrs_new From c4cc8b3d3c27c4999b300971977504ea194b049d Mon Sep 17 00:00:00 2001 From: GonzaloGuasch Date: Fri, 19 Jul 2024 21:22:33 -0300 Subject: [PATCH 15/15] remove if in flask.request.url_rule --- .../src/opentelemetry/instrumentation/flask/__init__.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) 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 db81c731f5..9bc5e85a12 100644 --- a/instrumentation/opentelemetry-instrumentation-flask/src/opentelemetry/instrumentation/flask/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-flask/src/opentelemetry/instrumentation/flask/__init__.py @@ -348,9 +348,8 @@ def _start_response(status, response_headers, *args, **kwargs): excluded_urls is None or not excluded_urls.url_disabled(flask.request.url) ): - if flask.request.url_rule: - nonlocal request_route - request_route = flask.request.url_rule + nonlocal request_route + request_route = flask.request.url_rule span = flask.request.environ.get(_ENVIRON_SPAN_KEY)