Skip to content

Commit a322a0a

Browse files
flask: add http.target and http.route to metric attributes (#2621)
1 parent 6594cdf commit a322a0a

File tree

3 files changed

+29
-4
lines changed

3 files changed

+29
-4
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
99

1010
### Added
1111

12+
- `opentelemetry-instrumentation-flask` Add `http.route` and `http.target` to metric attributes
13+
([#2621](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2621))
1214
- `opentelemetry-instrumentation-sklearn` Deprecated the sklearn instrumentation
1315
([#2708](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2708))
1416
- `opentelemetry-instrumentation-pyramid` Record exceptions raised when serving a request

instrumentation/opentelemetry-instrumentation-flask/src/opentelemetry/instrumentation/flask/__init__.py

+15
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,7 @@ def response_hook(span: Span, status: str, response_headers: List):
266266
)
267267
from opentelemetry.instrumentation.utils import _start_internal_or_server_span
268268
from opentelemetry.metrics import get_meter
269+
from opentelemetry.semconv.attributes.http_attributes import HTTP_ROUTE
269270
from opentelemetry.semconv.metrics import MetricInstruments
270271
from opentelemetry.semconv.metrics.http_metrics import (
271272
HTTP_SERVER_REQUEST_DURATION,
@@ -340,12 +341,16 @@ def _wrapped_app(wrapped_app_environ, start_response):
340341
)
341342

342343
active_requests_counter.add(1, active_requests_count_attrs)
344+
request_route = None
343345

344346
def _start_response(status, response_headers, *args, **kwargs):
345347
if flask.request and (
346348
excluded_urls is None
347349
or not excluded_urls.url_disabled(flask.request.url)
348350
):
351+
nonlocal request_route
352+
request_route = flask.request.url_rule
353+
349354
span = flask.request.environ.get(_ENVIRON_SPAN_KEY)
350355

351356
propagator = get_global_response_propagator()
@@ -388,13 +393,23 @@ def _start_response(status, response_headers, *args, **kwargs):
388393
duration_attrs_old = otel_wsgi._parse_duration_attrs(
389394
attributes, _HTTPStabilityMode.DEFAULT
390395
)
396+
397+
if request_route:
398+
duration_attrs_old[SpanAttributes.HTTP_TARGET] = str(
399+
request_route
400+
)
401+
391402
duration_histogram_old.record(
392403
max(round(duration_s * 1000), 0), duration_attrs_old
393404
)
394405
if duration_histogram_new:
395406
duration_attrs_new = otel_wsgi._parse_duration_attrs(
396407
attributes, _HTTPStabilityMode.HTTP
397408
)
409+
410+
if request_route:
411+
duration_attrs_new[HTTP_ROUTE] = str(request_route)
412+
398413
duration_histogram_new.record(
399414
max(duration_s, 0), duration_attrs_new
400415
)

instrumentation/opentelemetry-instrumentation-flask/tests/test_programmatic.py

+12-4
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,12 @@ def expected_attributes_new(override_attributes):
8585
return default_attributes
8686

8787

88+
_server_duration_attrs_old_copy = _server_duration_attrs_old.copy()
89+
_server_duration_attrs_old_copy.append("http.target")
90+
91+
_server_duration_attrs_new_copy = _server_duration_attrs_new.copy()
92+
_server_duration_attrs_new_copy.append("http.route")
93+
8894
_expected_metric_names_old = [
8995
"http.server.active_requests",
9096
"http.server.duration",
@@ -95,11 +101,11 @@ def expected_attributes_new(override_attributes):
95101
]
96102
_recommended_metrics_attrs_old = {
97103
"http.server.active_requests": _server_active_requests_count_attrs_old,
98-
"http.server.duration": _server_duration_attrs_old,
104+
"http.server.duration": _server_duration_attrs_old_copy,
99105
}
100106
_recommended_metrics_attrs_new = {
101107
"http.server.active_requests": _server_active_requests_count_attrs_new,
102-
"http.server.request.duration": _server_duration_attrs_new,
108+
"http.server.request.duration": _server_duration_attrs_new_copy,
103109
}
104110
_server_active_requests_count_attrs_both = (
105111
_server_active_requests_count_attrs_old
@@ -109,8 +115,8 @@ def expected_attributes_new(override_attributes):
109115
)
110116
_recommended_metrics_attrs_both = {
111117
"http.server.active_requests": _server_active_requests_count_attrs_both,
112-
"http.server.duration": _server_duration_attrs_old,
113-
"http.server.request.duration": _server_duration_attrs_new,
118+
"http.server.duration": _server_duration_attrs_old_copy,
119+
"http.server.request.duration": _server_duration_attrs_new_copy,
114120
}
115121

116122

@@ -570,6 +576,7 @@ def test_basic_metric_success(self):
570576
self.client.get("/hello/756")
571577
expected_duration_attributes = {
572578
"http.method": "GET",
579+
"http.target": "/hello/<int:helloid>",
573580
"http.host": "localhost",
574581
"http.scheme": "http",
575582
"http.flavor": "1.1",
@@ -595,6 +602,7 @@ def test_basic_metric_success_new_semconv(self):
595602
expected_duration_attributes = {
596603
"http.request.method": "GET",
597604
"url.scheme": "http",
605+
"http.route": "/hello/<int:helloid>",
598606
"network.protocol.version": "1.1",
599607
"http.response.status_code": 200,
600608
}

0 commit comments

Comments
 (0)