DEV Community

Cover image for πŸ›°οΈ Observability Practices with Prometheus and Grafana Monitoring a Node.js API
Daleska
Daleska

Posted on

πŸ›°οΈ Observability Practices with Prometheus and Grafana Monitoring a Node.js API

πŸ“Œ Introduction

In today's cloud-native and microservices-based systems, observability has become a critical component for ensuring system health and performance. While traditional monitoring focuses on known failure scenarios, observability empowers teams to explore the unknown by collecting telemetry data like metrics, logs, and traces.

This article walks through a real-world implementation of observability using Prometheus and Grafana to monitor a simple Node.js API. We'll explore how to instrument the application, export metrics, collect them with Prometheus, and visualize them in Grafana.

By the end of this guide, you will have:

  • A running Node.js REST API that exposes useful metrics
  • Prometheus configured to scrape those metrics
  • Grafana visualizing system behavior in real time

🧠 What is Observability?

Observability answers the question: β€œWhat’s going on inside my system?”

It relies on three fundamental pillars:

Pillar Description
Metrics Numeric representation of data over time (e.g., CPU usage)
Logs Text records of events (e.g., errors, requests)
Traces Track request flow across distributed services

Unlike basic uptime monitoring, observability helps answer why something is wrong, not just what is wrong.


🧰 Tools and Technologies Used

  • Node.js + Express: Lightweight web server to simulate an API
  • prom-client: Prometheus client library for Node.js
  • Prometheus: Time-series database that scrapes and stores metrics
  • Grafana: Visualization tool for dashboards and alerts
  • Docker + Docker Compose: To containerize and orchestrate services
  • GitHub: For source code versioning and sharing

βš™οΈ System Architecture

User
|
v
Node.js API (Express)
|
└── /metrics (prom-client)
|
Prometheus
|
Grafana


πŸ› οΈ Step-by-Step Implementation

1️⃣ Setting up the Node.js API

1.1 Install dependencies

npm init -y
npm install express prom-client

Enter fullscreen mode Exit fullscreen mode

1.2 API Code (index.js)

const express = require('express');
const client = require('prom-client');
const app = express();

// Enable collection of default metrics like memory usage, CPU, etc.
client.collectDefaultMetrics();

const httpRequestDurationMicroseconds = new client.Histogram({
  name: 'http_request_duration_ms',
  help: 'Duration of HTTP requests in ms',
  labelNames: ['method', 'route', 'code'],
  buckets: [50, 100, 300, 500, 750, 1000, 2000]
});

app.use((req, res, next) => {
  const start = Date.now();
  res.on('finish', () => {
    const duration = Date.now() - start;
    httpRequestDurationMicroseconds
      .labels(req.method, req.route?.path || req.path, res.statusCode)
      .observe(duration);
  });
  next();
});

app.get('/hello', (req, res) => {
  res.send('Hello, observability world!');
});

app.get('/metrics', async (req, res) => {
  res.set('Content-Type', client.register.contentType);
  res.end(await client.register.metrics());
});

app.listen(3000, () => {
  console.log('Server listening on http://localhost:3000');
});

Enter fullscreen mode Exit fullscreen mode

2️⃣ Prometheus Configuration

1.1 Create a file named prometheus.yml:

global:
  scrape_interval: 5s

scrape_configs:
  - job_name: 'nodeapp'
    static_configs:
      - targets: ['nodeapp:3000']
Enter fullscreen mode Exit fullscreen mode

Prometheus will now scrape metrics from /metrics every 5 seconds.

3️⃣ Dockerizing Everything

Dockerfile

FROM node:18
WORKDIR /app
COPY . .
RUN npm install
CMD ["node", "index.js"]
Enter fullscreen mode Exit fullscreen mode

docker-compose.yml

version: '3.8'

services:
  nodeapp:
    build: .
    ports:
      - "3000:3000"

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

  grafana:
    image: grafana/grafana
    ports:
      - "3001:3000"
Enter fullscreen mode Exit fullscreen mode

4️⃣ Running the Project

Start everything with:

docker-compose up --build
Enter fullscreen mode Exit fullscreen mode

Then, go to:

`http://localhost:3000/hello β†’ API endpoint

http://localhost:3000/metrics β†’ Raw Prometheus metrics

http://localhost:9090 β†’ Prometheus dashboard

http://localhost:3001 β†’ Grafana (login: admin/admin)`

You can find the full source code and instructions here:

πŸ”— GitHub Repo

Top comments (0)