Skip to main content
This lesson builds a small dummy Flask application to demonstrate where and how to add Prometheus instrumentation. The focus is on adding metrics to capture HTTP activity, not on Flask itself. We’ll start with a minimal app, add a Prometheus counter, then show two ways to expose metrics: a separate metrics port and mounting metrics on the same Flask process.

Prerequisites

  • Python 3.x
  • pip
  • Flask
  • prometheus_client
Install Flask (if needed) and the 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

Use start_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.
Once running, you can fetch metrics with curl:
Example output (truncated):

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:
This makes metrics available at 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’s before_request:
Use labels to capture method and endpoint (be cautious with cardinality):
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 /metrics on the same port as the Flask app.
    • Useful in environments that restrict ports or when a single port is required.
Summary comparison: 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

Watch Video