Skip to content

Commit e622709

Browse files
author
Paweł Kędzia
committed
Merge branch 'features/metrics'
2 parents c3f5739 + 2723f05 commit e622709

File tree

1 file changed

+77
-0
lines changed

1 file changed

+77
-0
lines changed

llm_router_api/core/metrics.py

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
IS_PROMETHEUS_AVAILABLE = False
1818
try:
1919
from prometheus_client import (
20+
Gauge,
2021
Counter,
2122
Histogram,
2223
generate_latest,
@@ -25,6 +26,7 @@
2526

2627
IS_PROMETHEUS_AVAILABLE = True
2728
except ImportError:
29+
Gauge = None
2830
Counter = None
2931
Histogram = None
3032
generate_latest = None
@@ -126,6 +128,52 @@ def _prepare_request_hooks(self):
126128
"http_request_duration_seconds",
127129
"Histogram of request latency (seconds)",
128130
["method", "endpoint"],
131+
buckets=(0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10),
132+
)
133+
134+
self.REQUEST_IN_PROGRESS = Gauge(
135+
"http_requests_in_progress",
136+
"Number of HTTP requests currently being processed.",
137+
)
138+
139+
self.REQUEST_EXCEPTIONS = Counter(
140+
"http_request_exceptions_total",
141+
"Total number of HTTP requests that resulted in an exception (5xx status).",
142+
["method", "endpoint"],
143+
)
144+
145+
self.REQUEST_SIZE = Histogram(
146+
"http_request_size_bytes",
147+
"Size of HTTP request bodies in bytes.",
148+
["method", "endpoint"],
149+
buckets=(
150+
100,
151+
500,
152+
1_000,
153+
5_000,
154+
10_000,
155+
50_000,
156+
100_000,
157+
500_000,
158+
1_000_000,
159+
),
160+
)
161+
162+
self.RESPONSE_SIZE = Histogram(
163+
"http_response_size_bytes",
164+
"Size of HTTP response bodies in bytes.",
165+
["method", "endpoint", "http_status"],
166+
buckets=(
167+
100,
168+
500,
169+
1_000,
170+
5_000,
171+
10_000,
172+
50_000,
173+
100_000,
174+
500_000,
175+
1_000_000,
176+
),
129177
)
130178

131179
def _register_request_hooks(self):
@@ -142,6 +190,15 @@ def _register_request_hooks(self):
142190
@self.flask_app.before_request
143191
def _start_timer():
144192
request.start_time = time.time()
193+
# Increment in‑progress gauge
194+
self.REQUEST_IN_PROGRESS.inc()
195+
196+
# Record request size if a body is present
197+
if request.content_length:
198+
self.REQUEST_SIZE.labels(
199+
method=request.method,
200+
endpoint=request.path,
201+
).observe(request.content_length)
145202

146203
@self.flask_app.after_request
147204
def _record_metrics(response):
@@ -152,6 +209,26 @@ def _record_metrics(response):
152209
endpoint=request.path,
153210
).observe(elapsed)
154211

212+
# Record response size (Content‑Length header
213+
# may be missing for streamed responses)
214+
resp_length = response.calculate_content_length()
215+
if resp_length is not None:
216+
self.RESPONSE_SIZE.labels(
217+
method=request.method,
218+
endpoint=request.path,
219+
http_status=response.status_code,
220+
).observe(resp_length)
221+
222+
# Decrement in‑progress gauge
223+
self.REQUEST_IN_PROGRESS.dec()
224+
225+
# Count exceptions (5xx)
226+
if 500 <= response.status_code < 600:
227+
self.REQUEST_EXCEPTIONS.labels(
228+
method=request.method,
229+
endpoint=request.path,
230+
).inc()
231+
155232
self.REQUEST_COUNT.labels(
156233
method=request.method,
157234
endpoint=request.path,

0 commit comments

Comments
 (0)