Now that we have the development environment ready and containerised it is time to add some additional services to it. In this episode let’s create a metrics endpoint providing information on the API statistics as well as Prometheus container to monitor it.
For integration between Flask and Prometheus I am using Prometheus Flask exporter which allows us to create metrics endpoint in an easy way. In order to use it first you need to install it on your local machine by running the command:
pip3 install prometheus-flask-exporter
Once it’s installed also make sure to add the dependency to the application:
from prometheus_flask_exporter import PrometheusMetrics
When implementing PrometheusMetrics we get these measures out of the box:
- HTTP request duration
- Total number of HTTP requests
- Total number of uncaught exceptions when serving Flask requests
Simple implementation looks the following:
app = Flask(__name__)
metrics = PrometheusMetrics(app)
# static information as metric
metrics.info('app_info', 'Application info', version='1.0.3')
@app.route('/')
def main():
pass # requests tracked by default
@app.route('/skip')
@metrics.do_not_track()
def skip():
pass # default metrics are not collected
@app.route('/<item_type>')
@metrics.do_not_track()
@metrics.counter('invocation_by_type', 'Number of invocations by type',
labels={'item_type': lambda: request.view_args['type']})
def by_type(item_type):
pass # only the counter is collected, not the default metrics
@app.route('/long-running')
@metrics.gauge('in_progress', 'Long running requests in progress')
def long_running():
pass
@app.route('/status/<int:status>')
@metrics.do_not_track()
@metrics.summary('requests_by_status', 'Request latencies by status',
labels={'status': lambda r: r.status_code})
@metrics.histogram('requests_by_status_and_path', 'Request latencies by status and path',
labels={'status': lambda r: r.status_code, 'path': lambda: request.path})
def echo_status(status):
return 'Status: %s' % status, status
Let’s give it a try and call the endpoint:

As we can see it produces a lot of useful information. Beside the metrics I’ve already mentioned it even can give us some insight into performance of the application and our infrastructure (process_cpu_seconds_total, process_start_time_seconds, process_resident_memory_bytes) or split all http requests into different percentiles giving us info on slowest and median time needed to serve the requests.
Now that it’s in place let’s setup Prometheus so we can don’t have to call metrics endpoint every time we require information; instead we will use Prometheus to query the exact information we need.
First things first, let’s add another service in compose.yaml file:

We’ve named container Prometheus, specified location where the build file can be found (new directory called „mon”) and introduced port forwarding from 9090 in container (default for Prometheus) to 9091 on local machine. Of course let’s make sure to use the same docker network where all other containers are residing so we can reach them.
Before we prepare Dockerfile we need to prepare configuration that we are going to feed to Prometheus. You can find full documentation on this topic under this link. I am using scrape config, dedicated for interacting using HTTP method. You can see the config I am using below:

I have specified the default scrape interval to be every 15 seconds, the job name and target. I can use name of the service from Docker compose (api) and internal Flask port 5000 because both of those containers reside on the same network. I didn’t need to specify the specific endpoint, because Prometheus by default expects metrics endpoint to be published under /metrics.
Final thing left to do is to specify build file which is quite simple: we pull default Prometheus image and add our configuration file:

Let’s give it a try and rebuild the environment:
docker compose up
Now that Prometheus container is running we should be able to access it’s web console under localhost:909. Once there move to Status – Target health section:

We can see that the endpoint http://api:5000/metrics is being actively monitored (status UP). Let’s give it a try and query some specific information about the metrics in „Query” tab:
flask_http_request_created
This will give us a list of all HTTP requests sent to our application, just as presented on the screenshot below:

To get info on all available metrics use:
{__name__!=""}
That’s it for today’s tutorial! Thanks for joining me, in my next entry I will cover deploying said Prometheus container in Azure Container Apps.