Prerequisites
- Python 3.x
- pip
- Flask
- prometheus_client
1. Basic Flask app
A minimal API with one route. This is the starting point before adding instrumentation.2. Install the Prometheus client for Python
Install the official Prometheus Python client (if you haven’t already):3. Creating a simple counter metric
Define a Counter metric. Follow Prometheus naming conventions: lowercase, underscores, and a clear help string.4. Instrumenting a route by incrementing the counter
Manually increment the counter inside the route handler:5. Expose metrics on a separate port using the built-in HTTP server
Usestart_http_server(port) to expose metrics on a separate port (common pattern for simple setups). This serves metrics at the root path, e.g. http://127.0.0.1:8000/metrics.
6. Exposing metrics via the Flask process (same port)
If you prefer metrics to be available on the same port as your Flask application, mount the Prometheus WSGI app at/metrics using DispatcherMiddleware:
http://<host>:<flask_port>/metrics.
7. Adding more routes
As your API grows, you might add several endpoints. Here are examples that also increment the counter (manual increments shown):8. Making instrumentation less repetitive
Manually incrementing inside every handler works but is repetitive and error-prone. Use a centralized hook (middleware-style) to count requests once for all routes. Simple global counter increment with Flask’sbefore_request:
Use lowercase, underscore-separated names for Prometheus naming conventions. Be careful with label cardinality: using high-cardinality labels (such as full request paths with many unique IDs) can cause performance and storage problems. Prefer stable labels (method, named endpoint, status) over raw paths containing IDs. See Prometheus instrumentation best practices for more on labels and cardinality: https://prometheus.io/docs/practices/instrumentation/.
9. Which approach to choose?
- start_http_server (separate port)
- Simple and language-agnostic for exposing metrics from a process.
- Works well when you can open a second port for scraping.
- make_wsgi_app + DispatcherMiddleware (same port)
- Exposes
/metricson the same port as the Flask app. - Useful in environments that restrict ports or when a single port is required.
- Exposes
Either approach is valid — the key is placing instrumentation where it reliably captures the events you care about. For HTTP request counts, a centralized hook (middleware /
before_request) is usually preferable to adding manual increments in each handler.
References
- Prometheus Python client documentation
- Prometheus instrumentation best practices
- Flask documentation
- Werkzeug DispatcherMiddleware