Connect a Node App to Prometheus
Learn how to connect a Node application to Prometheus using Docker Compose. We will go over the Node prom-client library, how to set up a metrics endpoint, etc.
Table of Contents 📖
- Prometheus
- Environment Variables
- Node Project
- Prometheus Configuration
- Dockerizing
- Docker Compose Services
- Starting the Application
Prometheus
Prometheus is desiged to capture metrics by scraping an HTTP endpoint, known as a metrics endpoint. Metrics endpoints are the standard way for an application to expose metrics. Prometheus will periodically scrape a provided HTTP endpoint and store the data. We can then query the data to get an idea of what is going on in the application.
Environment Variables
PROJECT_NAME=PROMETHEUS_DEMO
NODE_CONTAINER_NAME=node-c
NODE_PORT=9001
PROMETHEUS_CONTAINER_NAME=prometheus-c
PROMETHEUS_PORT=9090
SUCCESS: Port 9090 is Prometheus's default port.
Node Project
npm init es6 -y
npm i prom-client
npm i nodemon -D
"main": "./src/server.js",
...
"scripts": {
"start": "nodemon ."
},
INFO: The prom-client package is a Prometheus client for Node. We will use it to connect to our Prometheus server.
import http from 'http';
import url from 'url';
import client from 'prom-client';
const NODE_CONTAINER_NAME = process.env.NODE_CONTAINER_NAME;
const NODE_PORT = process.env.NODE_PORT;
// The registry where the metrics will be registered.
// A registry is a list of metrics that the Prometheus client is collecting.
const register = new client.Registry();
// Adds a static label to every metric emitted by the registry
register.setDefaultLabels({
app: 'my-node-app'
});
// There are some default metrics recommended by Prometheus. They can
// be collected by calling collectDefaultMetrics()
client.collectDefaultMetrics({register});
const server = http.createServer(async (req, res) => {
const route = url.parse(req.url).pathname;
console.log(`${req.method} ${route}`);
if (route === '/metrics') {
res.setHeader('Content-Type', register.contentType)
// To expose the metrics, respond to Prometheus's scrape requests
// with the result of register.metrics()
const metrics = await register.metrics()
res.end(metrics)
}
});
server.listen(NODE_PORT, NODE_CONTAINER_NAME, () => {
console.log(`Server running at http://${NODE_CONTAINER_NAME}:${NODE_PORT}/`);
});
Prometheus Configuration
global:
scrape_interval: 5s
scrape_configs:
- job_name: my-node-app
static_configs:
- targets:
- node-c:9001
- global - Specifies the global configuration. Supplied parameters are valid in all configuration contexts.
- scrape_interval - How frequently to scrape the targets. Default is 1 minute.
- scrape_configs - List of scrape configurations.
- job_name - The job name assigned to the scraped metrics.
- static_configs - Used to specify a list of targets.
- targets - List of targets to scrape. Takes the host:port format. Note that this is the name of our Node Docker container in the Docker network.
Dockerizing
FROM prom/prometheus
COPY --chmod=755 entrypoint.sh .
ENTRYPOINT ./entrypoint.sh
/bin/prometheus --config.file=/etc/prometheus/prometheus.yml --storage.tsdb.path=/prometheus --web.console.libraries=/usr/share/prometheus/console_libraries --web.console.templates=/usr/share/prometheus/consoles
WARNING: The above entrypoint.sh script is actually the default entrypoint.sh script for the Prometheus image. We are explicitly defining it here so we can see how to swap out configuration files for different environments i.e. production and development.
FROM node:22-alpine
WORKDIR /server
COPY package*.json .
RUN npm i
CMD ["npm", "start"]
Docker Compose Services
name: ${PROJECT_NAME}
services:
server:
pull_policy: build
image: node-i
container_name: ${NODE_CONTAINER_NAME}
env_file: .env
build:
context: server
dockerfile: Dockerfile
volumes:
- ./server:/server
- server-node-modules:/server/node_modules
ports:
- ${NODE_PORT}:${NODE_PORT}
prometheus:
pull_policy: build
image: prometheus-i
container_name: ${PROMETHEUS_CONTAINER_NAME}
env_file: .env
build:
context: prometheus
dockerfile: Dockerfile
volumes:
- ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml
ports:
- ${PROMETHEUS_PORT}:${PROMETHEUS_PORT}
volumes:
server-node-modules:
name: server-node-modules
Starting the Application
docker compose up
After running the application, visit localhost:9090 to see the Prometheus dashboard. We can then query for metrics and get an idea of what is going on in the application.