- Keep the cumulative total requests metric (
http_requests_total). - Add a metric that represents the number of concurrent requests currently being processed (a value that can increase and decrease).
For tracking concurrent requests, an up-down counter is the preferred choice because its value moves up and down relative to the previous state.
- Configures a MeterProvider with a console exporter.
- Creates a cumulative
http_requests_totalcounter (incremented when responses are sent). - Creates a
concurrent_requestsup-down counter (incremented at request start, decremented after response). - Uses Flask
before_requestandafter_requesthooks to manage the concurrent counter. - Adds a slow route to let you observe concurrent requests.
before_requestruns before Flask dispatches to the route handler. We incrementconcurrent_requeststhere (withrouteandmethodattributes) to indicate a request has started.after_requestruns after the route handler returns but before the response is sent. We decrementconcurrent_requestsand incrementhttp_requests_totalhere, so the total only counts completed responses.- The slow
POST /productsroute usestime.sleep(10)so you can make multiple concurrent requests and observeconcurrent_requestsrising while requests are still in-flight.
- Fast route:
- Slow route (takes ~10 seconds to return):
- Place the total requests increment in
after_requestso you count only completed responses. - Attach attributes like
routeandmethodwith each metric call to enable dimensional filtering and per-endpoint breakdowns. For example:{"route": request.path, "method": request.method}. - Export interval controls how often metrics are pushed to the exporter. In this example the reader is configured with
export_interval_millis=5000to export every 5 seconds. - If your application can raise exceptions during request handling, consider ensuring the decrement always runs (see warning below).
If a request handler raises an exception,
after_request may not always run. To guarantee the concurrent counter is decremented in all cases, consider using Flask’s teardown_request (which runs for both successful and failed requests) or ensure exception paths also decrement the up-down counter.
Links and references
- Flask documentation: https://flask.palletsprojects.com/
- OpenTelemetry Python metrics: https://opentelemetry.io/docs/instrumentation/python/
- OpenTelemetry metrics SDK: https://github.com/open-telemetry/opentelemetry-python