Grafana + Prometheus

Saturday, Nov 15, 2025| Tags: perl, python, Grafana, Promotheus

DISCLAIMER: Image is generated using ChatGPT.


1. What is Grafana?

2. What is Prometheus?

3. Docker Setup

4. Test Environment

5. Datasource

6. Dashboard


What is Grafana?


Grafana is an open-source analytics and visualisation platform. It lets you create dashboards that visualise data from various sources such as:

- Prometheus (metrics and monitoring)
- InfluxDB (time-series data)
- Elasticsearch
- PostgreSQL / MySQL etc.

It’s very popular for monitoring servers, containers, applications especially when paired with Prometheus.

You can find more information here: https://grafana.com


What is Prometheus?


Prometheus is an open-source systems monitoring and alerting toolkit originally built at SoundCloud. It’s now a graduated project of the Cloud Native Computing Foundation (CNCF) which means it’s a mature, production-ready tool used by thousands of companies worldwide.

Prometheus is the metrics collection and storage system that:

- Scrapes metrics from your applications (Perl app, Python app) and infrastructure (node-exporter)
- Stores the metrics in a time-series database
- Provides a query language (PromQL) to analyse the metrics
- Serves the metrics to Grafana for visualisation

Prometheus Server pulls metrics from your applications every 5 seconds (as configured in the prometheus.yml).

You can find more information here: https://prometheus.io


Docker Setup


Docker is the ideal choice for setting up Grafana and Prometheus in one container.

.
├── docker-compose.yml
├── perl-app
│   ├── Dockerfile
│   └── app.pl
├── prometheus.yml
└── python-app
    ├── Dockerfile
    └── app.py

Here we will create two applications one in Perl and another in Python.


File: perl-app/app.pl

#!/usr/bin/env perl

use strict;
use warnings;
use Prometheus::Tiny;
use Mojolicious::Lite;

my $prom = Prometheus::Tiny->new;

$prom->declare(
    'http_requests_total',
    help => 'Total HTTP requests',
    type => 'counter'
);

get '/' => sub {
    my $c = shift;
    $prom->inc('http_requests_total');
    $c->render(text => "Hello from Perl!\n");
};

get '/metrics' => sub {
    my $c = shift;
    $c->render(text => $prom->format, format => 'txt');
};

app->start('daemon', '-l', 'http://*:7000');

File: python-app/app.py

#!/usr/bin/env python

import os
os.environ['PROMETHEUS_DISABLE_CREATED_SERIES'] = '1'

from flask import Flask, Response
from prometheus_client import Counter, generate_latest, CollectorRegistry

app = Flask(__name__)

registry = CollectorRegistry()
http_requests_total = Counter('http_requests_total', 'Total HTTP requests', registry=registry)

@app.route('/')
def hello():
    http_requests_total.inc()
    return "Hello from Python!\n"

@app.route('/metrics')
def metrics():
    return Response(generate_latest(registry), mimetype='text/plain')

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8000)

It’s now time to create Dockerfile for each of the applications.


File: perl-app/Dockerfile

FROM perl:5.38
RUN cpanm Mojolicious Prometheus::Tiny --notest
WORKDIR /app
COPY app.pl /app/
EXPOSE 7000
CMD ["perl", "app.pl"]

File: python-app/Dockerfile

FROM python:3.11-slim
RUN pip install flask prometheus_client
WORKDIR /app
COPY app.py /app/
EXPOSE 8000
CMD ["python", "app.py"]

Let’s create configuration file for Prometheus.


File: prometheus.yml

global:
  scrape_interval: 5s

scrape_configs:
  - job_name: 'prometheus'
    static_configs:
      - targets: ['prometheus:9090']

  - job_name: 'perl-app'
    static_configs:
      - targets: ['perl-app:7000']

  - job_name: 'python-app'
    static_configs:
      - targets: ['python-app:8000']

Finally create the docker compose configuration file.


File: docker-compose.yml

version: '3'

services:
  grafana:
    image: grafana/grafana
    container_name: grafana
    ports:
      - "3000:3000"
    depends_on:
      - prometheus
    environment:
      - GF_SECURITY_ADMIN_USER=admin
      - GF_SECURITY_ADMIN_PASSWORD=admin
    networks:
      - monitoring

  prometheus:
    image: prom/prometheus
    container_name: prometheus
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
    ports:
      - "9090:9090"
    networks:
      - monitoring

  perl-app:
    build: ./perl-app
    container_name: perl-app
    ports:
      - "7000:7000"
    networks:
      - monitoring

  python-app:
    build: ./python-app
    container_name: python-app
    ports:
      - "8000:8000"
    networks:
      - monitoring

networks:
  monitoring:
    driver: bridge

Start the container now:


$ docker-compose up -d
Creating network "grafana_monitoring" with driver "bridge"
Creating prometheus ... done
Creating python-app ... done
Creating perl-app   ... done
Creating grafana    ... done

Check the status of containers:


$ docker-compose ps
   Name                 Command               State                    Ports
----------------------------------------------------------------------------------------------
grafana      /run.sh                          Up      0.0.0.0:3000->3000/tcp,:::3000->3000/tcp
perl-app     perl app.pl                      Up      0.0.0.0:7000->7000/tcp,:::7000->7000/tcp
prometheus   /bin/prometheus --config.f ...   Up      0.0.0.0:9090->9090/tcp,:::9090->9090/tcp
python-app   python app.py                    Up      0.0.0.0:8000->8000/tcp,:::8000->8000/tcp

Test Environment


Time to test the Perl and Python applications:


$ curl http://localhost:7000
Hello from Perl!

$ curl http://localhost:8000
Hello from Python!

Inspecting the perl app logs:


$ docker-compose logs perl-app

Similarly for python app logs:


$ docker-compose logs python-app

Now fetch the metrics from Perl application:


$ curl http://localhost:7000/metrics
# HELP http_requests_total Total HTTP requests
# TYPE http_requests_total counter
http_requests_total 1

From Python application this time:


$ curl http://localhost:8000/metrics
# HELP http_requests_total Total HTTP requests
# TYPE http_requests_total counter
http_requests_total 1.0

Let’s check all the targets state in Prometheus: http://localhost:9090/targets

You should have all the state UP.



The Grafana should be accessible here: http://localhost:3000/

The default credentials: admin/admin.



Datasource


Goto Grafana homepage and click the tile Add your first data source.

You should now see something like below:



Now select Prometheus from the list and then you should get this:



Here, you enter the Prometheus server URL as http://prometheus:9090.

And then click Save & test button.


Dashboard


Go back to Grafana home page and click the tile: Create your first dashboard.

You should have this page now:



Click the button Add visualisation and you get this page:



Select the data source: prometheus

You then see this page:



For perl app, we will try this query.

Enter Metrics browser: http_requests_total{job="perl-app"}

Click Run queries

Click Save dashboard

Add another panel for python app similarly.

Enter Metrics browser: http_requests_total{job="python-app"}

Click Run queries

Click Save dashboard

Then you should have this page.




Happy Hacking !!!

SO WHAT DO YOU THINK ?

If you have any suggestions or ideas then please do share with us.

Contact with me