1717IS_PROMETHEUS_AVAILABLE = False
1818try :
1919 from prometheus_client import (
20+ Gauge ,
2021 Counter ,
2122 Histogram ,
2223 generate_latest ,
2526
2627 IS_PROMETHEUS_AVAILABLE = True
2728except 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