0Pricing
Node.js Backend Development Bootcamp · Leçon

Exposer les métriques de l’application et la méthode RED

Publiez les métriques de débit, d’erreurs et de durée au format Prometheus et définissez des SLI pertinents.

Exposer les métriques de l’application et la méthode RED est une leçon Node.js Backend Development Bootcamp gratuite sur CoddyKit. Ceci est la leçon 3 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage Node.js Backend Development Bootcamp, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours Node.js Backend Development Bootcamp comprend 4 leçons au total.

Certaines parties de cette leçon n'ont pas encore été traduites et s'affichent en anglais.

Why Metrics Matter

Logs tell you what happened in a single request. Metrics tell you how your whole service is behaving right now and over time. They are cheap to store, aggregate well, and power dashboards and alerts.

A metric is a numeric measurement sampled over time. In a Node.js backend you typically export metrics in Prometheus text format over an HTTP endpoint (conventionally /metrics). Prometheus scrapes that endpoint every few seconds and stores the time series.

  • Counter — only goes up (total requests, total errors).
  • Gauge — goes up and down (active connections, queue depth).
  • Histogram — buckets observations (request durations) to compute quantiles.

The Prometheus Text Format

Before wiring up libraries, it helps to see what the /metrics endpoint actually returns. Each line is metric_name{label="value"} number. The # HELP and # TYPE comment lines describe each metric.

Labels let one metric name carry many dimensions (per route, per status code). Below is a tiny generator that builds this exposition format by hand so you can see exactly what Prometheus parses.

function renderMetrics(samples) {
  const lines = [
    '# HELP http_requests_total Total HTTP requests',
    '# TYPE http_requests_total counter',
  ];
  for (const s of samples) {
    const labels = Object.entries(s.labels)
      .map(([k, v]) => k + '="' + v + '"')
      .join(',');
    lines.push('http_requests_total{' + labels + '} ' + s.value);
  }
  return lines.join('\n');
}

const out = renderMetrics([
  { labels: { method: 'GET', route: '/users', status: '200' }, value: 1024 },
  { labels: { method: 'GET', route: '/users', status: '500' }, value: 7 },
]);
console.log(out);

Introducing the RED Method

The RED method is a focused recipe for monitoring request-driven services. For every service you track three signals:

  • R — Rate: requests per second the service is handling.
  • E — Errors: rate of failed requests (typically HTTP 5xx, sometimes 4xx).
  • D — Duration: distribution of how long requests take (latency).

RED is the request-side complement to USE (Utilization, Saturation, Errors) which targets resources like CPU and disk. For an HTTP API, RED maps almost perfectly onto user-facing experience: throughput, failure rate, and latency.

The elegant part: all three derive from instrumenting just one thing — the request lifecycle.

Installing prom-client

In Node.js the de-facto library is prom-client. It manages a registry of metrics and renders them in Prometheus format. It also ships default metrics (event loop lag, heap usage, GC) that you enable with one call.

Create a single shared registry so every part of your app registers into the same place.

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

const register = new client.Registry();
register.setDefaultLabels({ app: 'orders-api' });

// Node.js runtime metrics: event loop lag, heap, GC, fd count...
client.collectDefaultMetrics({ register });

module.exports = { client, register };

R — A Counter for Request Rate

Rate is not stored directly. You store a monotonic counter of total requests, and Prometheus computes the per-second rate at query time with rate(http_requests_total[1m]).

Give the counter labels for method, route, and status_code. Crucially, use the route template (/users/:id) and not the raw URL (/users/42) — otherwise every id becomes a new time series and your cardinality explodes.

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

const httpRequestsTotal = new client.Counter({
  name: 'http_requests_total',
  help: 'Total number of HTTP requests',
  labelNames: ['method', 'route', 'status_code'],
});

// On each finished request:
httpRequestsTotal.inc({
  method: 'GET',
  route: '/users/:id',   // template, NOT /users/42
  status_code: '200',
});

D — A Histogram for Duration

Duration needs a histogram so you can compute percentiles (p50, p95, p99). A histogram counts observations into predefined buckets (upper bounds in seconds). Choose buckets that span your expected latency range.

A histogram automatically exposes three series per label set: _bucket, _sum, and _count. From _sum and _count you also get the average; from _bucket you estimate quantiles with histogram_quantile().

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

const httpRequestDuration = new client.Histogram({
  name: 'http_request_duration_seconds',
  help: 'HTTP request duration in seconds',
  labelNames: ['method', 'route', 'status_code'],
  // Tuned for a typical web API (5ms .. 5s)
  buckets: [0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5],
});

// Observe a completed request that took 0.137s
httpRequestDuration.observe(
  { method: 'GET', route: '/users/:id', status_code: '200' },
  0.137
);

One Middleware to Capture R, E, and D

The whole point of RED is that a single piece of instrumentation feeds all three signals. An Express-style middleware starts a timer, lets the request run, then on res.finish records the count and duration with the status code as a label.

Errors need no separate metric — they are just the counter filtered by status_code=~"5.." at query time. This is framework code (Express), so treat it as a reference pattern rather than a standalone program.

function metricsMiddleware(req, res, next) {
  const end = httpRequestDuration.startTimer({ method: req.method });

  res.on('finish', () => {
    // req.route?.path gives the template, e.g. '/users/:id'
    const route = (req.route && req.route.path) || req.path;
    const labels = {
      method: req.method,
      route,
      status_code: String(res.statusCode),
    };
    httpRequestsTotal.inc(labels);
    end(labels); // stops timer and records duration with these labels
  });

  next();
}

app.use(metricsMiddleware);

Exposing the /metrics Endpoint

Prometheus pulls metrics, so you must expose them over HTTP. Add a GET /metrics route that returns register.metrics() with the correct content type. This is the endpoint you list as a scrape target in prometheus.yml.

Keep this endpoint internal (bind to a private interface or protect it) — it can leak operational detail and is a tempting DoS target.

const { register } = require('./metrics');

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

// prometheus.yml scrape config:
// scrape_configs:
//   - job_name: 'orders-api'
//     scrape_interval: 15s
//     static_configs:
//       - targets: ['orders-api:3000']

Querying RED with PromQL

Once data is flowing, you express each RED signal as a PromQL query for dashboards and alerts:

  • Rate: sum(rate(http_requests_total[5m])) by (route)
  • Errors (ratio): sum(rate(http_requests_total{status_code=~"5.."}[5m])) / sum(rate(http_requests_total[5m]))
  • Duration (p95): histogram_quantile(0.95, sum(rate(http_request_duration_seconds_bucket[5m])) by (le))

Note the error ratio is a fraction of total requests, not a raw count. An error rate of 0.02 means 2% of requests failed — far more meaningful than "40 errors" with no denominator.

From Metrics to SLIs and SLOs

A Service Level Indicator (SLI) is a precisely defined measure of service health, usually expressed as good events / valid events. RED metrics are exactly the raw material for SLIs:

  • Availability SLI: non-5xx responses / total responses.
  • Latency SLI: requests faster than 300ms / total requests.

A Service Level Objective (SLO) is a target for an SLI over a window, e.g. "99.9% of requests succeed over 30 days." The complement of the SLO is your error budget (0.1%), which tells you how much failure you can tolerate before you must stop shipping features and fix reliability.

Computing a Latency SLI From Buckets

A latency SLI like "fraction of requests under 300ms" comes straight from histogram bucket counts: take the cumulative count in the le="0.3" bucket and divide by the total count. Here is a standalone simulation of that computation over two scrape samples.

// Cumulative bucket counts from a histogram, le = upper bound (seconds)
const sample = {
  total: 10000,
  buckets: {
    '0.1': 6000,
    '0.3': 9700,  // 9700 requests finished within 300ms
    '1.0': 9990,
    '+Inf': 10000,
  },
};

function latencySLI(s, thresholdLabel) {
  const good = s.buckets[thresholdLabel];
  return good / s.total;
}

const sli = latencySLI(sample, '0.3');
console.log('Latency SLI (<300ms): ' + (sli * 100).toFixed(2) + '%');
console.log('Meets 99% SLO? ' + (sli >= 0.99));

Quick Check

Test your understanding of cardinality and the RED method.

Recap

You can now expose meaningful application metrics in Prometheus format and reason about them with the RED method.

  • Counter, Gauge, Histogram are the core metric types; prom-client manages a registry and renders the exposition format.
  • RED = Rate, Errors, Duration — all three fall out of instrumenting the request lifecycle once, in a single middleware.
  • Rate comes from a counter via rate(); Errors are that counter filtered by status_code=~"5.."; Duration comes from a histogram via histogram_quantile().
  • Always label by route template, never raw URLs, to control cardinality.
  • Expose metrics at /metrics and let Prometheus scrape it; keep the endpoint internal.
  • Turn RED metrics into SLIs (good/valid events), set SLOs, and track your error budget.

Questions Fréquemment Posées

La leçon « Exposer les métriques de l’application et la méthode RED » est-elle gratuite ?

Oui — le texte complet de « Exposer les métriques de l’application et la méthode RED » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours Node.js Backend Development Bootcamp, passe à CoddyKit PRO. Le cours Node.js Backend Development Bootcamp comprend 4 leçons au total.

Qu'est-ce que j'apprendrai dans « Exposer les métriques de l’application et la méthode RED » ?

Publiez les métriques de débit, d’erreurs et de durée au format Prometheus et définissez des SLI pertinents. Tu pratiques Node.js Backend Development Bootcamp avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.

Dois-je avoir de l'expérience pour commencer Node.js Backend Development Bootcamp ?

Aucune expérience préalable n'est requise. Node.js Backend Development Bootcamp sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 3 sur 4.

Combien de temps prend la leçon « Exposer les métriques de l’application et la méthode RED » ?

La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.

Peux-tu écrire et exécuter du code dans cette leçon Node.js Backend Development Bootcamp ?

Oui. Chaque leçon Node.js Backend Development Bootcamp inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.

Toutes les leçons de ce cours

  1. Journalisation structurée avec identifiants de corrélation
  2. Traçage distribué avec les intervalles OpenTelemetry
  3. Exposer les métriques de l’application et la méthode RED
  4. Propagation du contexte avec AsyncLocalStorage
← Retour à Node.js Backend Development Bootcamp