Skip to content

Commit adee7a2

Browse files
authored
Merge branch 'main' into aiohttp-server-instrumentation
2 parents 74fece8 + 256d8ce commit adee7a2

File tree

5 files changed

+55
-5
lines changed

5 files changed

+55
-5
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

88
## Unreleased
9+
- `opentelemetry-instrumentation-asgi` Add `http.server.request.size` metric
10+
([#1867](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1867))
911

1012
### Fixed
1113

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

+15
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,11 @@ def __init__(
511511
unit="By",
512512
description="measures the size of HTTP response messages (compressed).",
513513
)
514+
self.server_request_size_histogram = self.meter.create_histogram(
515+
name=MetricInstruments.HTTP_SERVER_REQUEST_SIZE,
516+
unit="By",
517+
description="Measures the size of HTTP request messages (compressed).",
518+
)
514519
self.active_requests_counter = self.meter.create_up_down_counter(
515520
name=MetricInstruments.HTTP_SERVER_ACTIVE_REQUESTS,
516521
unit="requests",
@@ -603,6 +608,16 @@ async def __call__(self, scope, receive, send):
603608
self.server_response_size_histogram.record(
604609
self.content_length_header, duration_attrs
605610
)
611+
request_size = asgi_getter.get(scope, "content-length")
612+
if request_size:
613+
try:
614+
request_size_amount = int(request_size[0])
615+
except ValueError:
616+
pass
617+
else:
618+
self.server_request_size_histogram.record(
619+
request_size_amount, duration_attrs
620+
)
606621
if token:
607622
context.detach(token)
608623

instrumentation/opentelemetry-instrumentation-asgi/tests/test_asgi_middleware.py

+7-1
Original file line numberDiff line numberDiff line change
@@ -47,16 +47,19 @@
4747
"http.server.active_requests",
4848
"http.server.duration",
4949
"http.server.response.size",
50+
"http.server.request.size",
5051
]
5152
_recommended_attrs = {
5253
"http.server.active_requests": _active_requests_count_attrs,
5354
"http.server.duration": _duration_attrs,
5455
"http.server.response.size": _duration_attrs,
56+
"http.server.request.size": _duration_attrs,
5557
}
5658

5759

5860
async def http_app(scope, receive, send):
5961
message = await receive()
62+
scope["headers"] = [(b"content-length", b"128")]
6063
assert scope["type"] == "http"
6164
if message.get("type") == "http.request":
6265
await send(
@@ -99,6 +102,7 @@ async def error_asgi(scope, receive, send):
99102
assert isinstance(scope, dict)
100103
assert scope["type"] == "http"
101104
message = await receive()
105+
scope["headers"] = [(b"content-length", b"128")]
102106
if message.get("type") == "http.request":
103107
try:
104108
raise ValueError
@@ -592,6 +596,8 @@ def test_basic_metric_success(self):
592596
)
593597
elif metric.name == "http.server.response.size":
594598
self.assertEqual(1024, point.sum)
599+
elif metric.name == "http.server.request.size":
600+
self.assertEqual(128, point.sum)
595601
elif isinstance(point, NumberDataPoint):
596602
self.assertDictEqual(
597603
expected_requests_count_attributes,
@@ -630,7 +636,7 @@ async def target_asgi(scope, receive, send):
630636
expected_target,
631637
)
632638
assertions += 1
633-
self.assertEqual(assertions, 2)
639+
self.assertEqual(assertions, 3)
634640

635641
def test_no_metric_for_websockets(self):
636642
self.scope = {

instrumentation/opentelemetry-instrumentation-fastapi/tests/test_fastapi_instrumentation.py

+17-2
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
"http.server.active_requests",
4646
"http.server.duration",
4747
"http.server.response.size",
48+
"http.server.request.size",
4849
]
4950
_recommended_attrs = {
5051
"http.server.active_requests": _active_requests_count_attrs,
@@ -53,6 +54,10 @@
5354
*_duration_attrs,
5455
SpanAttributes.HTTP_TARGET,
5556
},
57+
"http.server.request.size": {
58+
*_duration_attrs,
59+
SpanAttributes.HTTP_TARGET,
60+
},
5661
}
5762

5863

@@ -251,16 +256,26 @@ def test_basic_metric_success(self):
251256

252257
def test_basic_post_request_metric_success(self):
253258
start = default_timer()
254-
self._client.post("/foobar")
259+
response = self._client.post(
260+
"/foobar",
261+
json={"foo": "bar"},
262+
)
255263
duration = max(round((default_timer() - start) * 1000), 0)
264+
response_size = int(response.headers.get("content-length"))
265+
request_size = int(response.request.headers.get("content-length"))
256266
metrics_list = self.memory_metrics_reader.get_metrics_data()
257267
for metric in (
258268
metrics_list.resource_metrics[0].scope_metrics[0].metrics
259269
):
260270
for point in list(metric.data.data_points):
261271
if isinstance(point, HistogramDataPoint):
262272
self.assertEqual(point.count, 1)
263-
self.assertAlmostEqual(duration, point.sum, delta=30)
273+
if metric.name == "http.server.duration":
274+
self.assertAlmostEqual(duration, point.sum, delta=30)
275+
elif metric.name == "http.server.response.size":
276+
self.assertEqual(response_size, point.sum)
277+
elif metric.name == "http.server.request.size":
278+
self.assertEqual(request_size, point.sum)
264279
if isinstance(point, NumberDataPoint):
265280
self.assertEqual(point.value, 0)
266281

instrumentation/opentelemetry-instrumentation-starlette/tests/test_starlette_instrumentation.py

+14-2
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,13 @@
5050
"http.server.active_requests",
5151
"http.server.duration",
5252
"http.server.response.size",
53+
"http.server.request.size",
5354
]
5455
_recommended_attrs = {
5556
"http.server.active_requests": _active_requests_count_attrs,
5657
"http.server.duration": _duration_attrs,
5758
"http.server.response.size": _duration_attrs,
59+
"http.server.request.size": _duration_attrs,
5860
}
5961

6062

@@ -165,19 +167,29 @@ def test_basic_post_request_metric_success(self):
165167
"http.scheme": "http",
166168
"http.server_name": "testserver",
167169
}
168-
self._client.post("/foobar")
170+
response = self._client.post(
171+
"/foobar",
172+
json={"foo": "bar"},
173+
)
169174
duration = max(round((default_timer() - start) * 1000), 0)
175+
response_size = int(response.headers.get("content-length"))
176+
request_size = int(response.request.headers.get("content-length"))
170177
metrics_list = self.memory_metrics_reader.get_metrics_data()
171178
for metric in (
172179
metrics_list.resource_metrics[0].scope_metrics[0].metrics
173180
):
174181
for point in list(metric.data.data_points):
175182
if isinstance(point, HistogramDataPoint):
176183
self.assertEqual(point.count, 1)
177-
self.assertAlmostEqual(duration, point.sum, delta=30)
178184
self.assertDictEqual(
179185
dict(point.attributes), expected_duration_attributes
180186
)
187+
if metric.name == "http.server.duration":
188+
self.assertAlmostEqual(duration, point.sum, delta=30)
189+
elif metric.name == "http.server.response.size":
190+
self.assertEqual(response_size, point.sum)
191+
elif metric.name == "http.server.request.size":
192+
self.assertEqual(request_size, point.sum)
181193
if isinstance(point, NumberDataPoint):
182194
self.assertDictEqual(
183195
expected_requests_count_attributes,

0 commit comments

Comments
 (0)