0Pricing
Node.js Backend Development Bootcamp · 강의

애플리케이션 메트릭 노출 및 RED 방법

Prometheus 형식으로 요청률, 오류 및 지속 시간 메트릭을 게시하고 의미 있는 SLI를 정의합니다.

애플리케이션 메트릭 노출 및 RED 방법은(는) CoddyKit의 무료 Node.js Backend Development Bootcamp 강의입니다. 이것은 4개 중 3번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Node.js Backend Development Bootcamp 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Node.js Backend Development Bootcamp 강의에는 총 4개의 강의가 포함되어 있습니다.

이 강의의 일부는 아직 번역되지 않았으며 영어로 표시됩니다.

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.

자주 묻는 질문

“애플리케이션 메트릭 노출 및 RED 방법” 강의는 무료인가요?

네 — “애플리케이션 메트릭 노출 및 RED 방법” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Node.js Backend Development Bootcamp 강의 전체를 잠금 해제할 수 있습니다. Node.js Backend Development Bootcamp 강의에는 총 4개의 강의가 포함되어 있습니다.

“애플리케이션 메트릭 노출 및 RED 방법”에서 뭘 배우나요?

Prometheus 형식으로 요청률, 오류 및 지속 시간 메트릭을 게시하고 의미 있는 SLI를 정의합니다. 브라우저에서 직접 실행하는 실습 코드로 Node.js Backend Development Bootcamp을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

Node.js Backend Development Bootcamp을(를) 시작하는 데 경험이 필요한가요?

사전 경험은 필요하지 않습니다. CoddyKit의 Node.js Backend Development Bootcamp은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 3번째 강의입니다.

“애플리케이션 메트릭 노출 및 RED 방법” 강의는 얼마나 걸리나요?

대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.

이 Node.js Backend Development Bootcamp 강의에서 코드를 작성하고 실행할 수 있나요?

네. 모든 Node.js Backend Development Bootcamp 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. 상관관계 ID를 활용한 구조화된 로깅
  2. OpenTelemetry 스팬을 활용한 분산 추적
  3. 애플리케이션 메트릭 노출 및 RED 방법
  4. AsyncLocalStorage를 활용한 컨텍스트 전파
← Node.js Backend Development Bootcamp(으)로 돌아가기