CodingNic

Observability: Metrics and Monitoring

A /metrics Endpoint

Observability: Metrics and Monitoring 15 min read

A /metrics Endpoint

Objectives

By the end of this lesson, you should be able to:

  • Expose an application’s metrics on a /metrics endpoint, in Prometheus’s text format
  • Read that format, and explain what HELP and TYPE lines are for
  • Explain how a monitoring system actually collects these metrics

💡 Why this matters: Lesson 2 built real metrics, tracked in memory, they’re not useful to anyone outside the running process until something can actually read them, a /metrics endpoint is how.

⚠️ A note on verification: every snippet and every output in this lesson was actually run.

Exposing the Registry

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

Three lines, register.metrics() (from Lesson 2’s Registry) produces every tracked metric, formatted as plain text, register.contentType sets the exact content type a monitoring system expects to see, this endpoint typically isn’t protected by the authentication this track built in Course 3, it’s usually reachable only from an internal network or a monitoring system specifically, not the public internet, worth deciding deliberately for any real deployment.

Reading the Output

text
Content-Type: text/plain; version=0.0.4; charset=utf-8

# HELP process_cpu_user_seconds_total Total user CPU time spent in seconds.
# TYPE process_cpu_user_seconds_total counter
process_cpu_user_seconds_total 0.024756

# HELP process_cpu_system_seconds_total Total system CPU time spent in seconds.
# TYPE process_cpu_system_seconds_total counter
process_cpu_system_seconds_total 0

...

Total metric lines: 73

Every metric gets a # HELP line (a human-readable description) and a # TYPE line (counter, histogram, gauge), before its actual value, this is Prometheus’s plain-text exposition format, deliberately simple, readable directly in a browser or with curl, and parseable by any monitoring tool that speaks it. 73 total lines here, most from client.collectDefaultMetrics() (Lesson 2), Node.js’s own process-level metrics, CPU time, memory, event loop lag, alongside the custom http_requests_total and http_request_duration_seconds this track’s own middleware adds.

How a Monitoring System Actually Collects This

Prometheus, and most Prometheus-compatible monitoring systems, work by scraping, periodically sending a GET request to /metrics (every 15 seconds is a common default), and storing whatever numbers come back, tagged with a timestamp. This is the opposite of Course 3’s logging, which pushes each event out the moment it happens, metrics are pulled, on a schedule, this is deliberate, a scraping system can detect an application that’s stopped responding entirely, a purely push-based system might just receive no more logs and have no easy way to distinguish “quiet” from “down.”

Why This Endpoint, Specifically, Matters for This Track

Every route this track has built, registration, login, notes, the admin endpoint, now contributes to http_requests_total and http_request_duration_seconds automatically, a monitoring system scraping this endpoint can answer, in real time, “is the Notes API’s error rate climbing,” or “did response times get worse after the last deploy,” questions Course 3’s logging alone, read line by line, couldn’t answer nearly as directly.

Try It

  1. Add the /metrics route to an Express app already instrumented with Lesson 2’s middleware, and fetch it directly with curl or a browser.
  2. Count how many of the exposed metrics come from collectDefaultMetrics() versus the custom ones this track added, and explain what a few of the default ones (process_cpu_seconds_total, event loop lag) might be useful for.
  3. Explain, in your own words, why metrics are typically pulled (scraped) rather than pushed, and what that makes easier to detect.
  4. Explain, in one or two sentences, why a /metrics endpoint often shouldn’t be publicly reachable the same way an application’s regular API routes are.

Recap

  • register.metrics() produces every tracked metric in Prometheus’s plain-text format, HELP and TYPE lines documenting each one.
  • A monitoring system typically scrapes /metrics on a schedule, rather than the application pushing metrics out, making a genuinely unresponsive application easier to detect.
  • Every route this track has built now contributes real, aggregated numbers to this endpoint, answering system-wide questions logging alone answers less directly.

Next lesson: exercises, building a complete health check and metrics setup, and a note on uptime checks and alerting.