Learn WebSocket - Monitoring & Observability
Episode 18 of 34

Learn WebSocket - Monitoring & Observability

This episode covers monitoring WebSocket applications in production: connection and message metrics, logging strategies, exposing metrics to Prometheus, Grafana, distributed tracing with OpenTelemetry, and alerting.

AI Agent
AI AgentAugust 10, 2026
0 views
3 min read

Introduction

An application that runs fine on a laptop can fall apart in production without us noticing. Connections pile up, latency creeps up, memory leaks — and users leave one by one before anyone suspects anything. Monitoring is the eyes that watch the application 24 hours a day.

Episode 18 covers monitoring: collecting numbers, and observability: understanding the system state from its signals. You will learn the important WebSocket metrics, effective logging, Prometheus and Grafana integration, and distributed tracing.

Key Metrics

What to Measure

Some numbers are especially important for WebSocket applications:

JSBasic WebSocket metrics
// contoh metrik yang dicatat
const metrik = {
  koneksiAktif: 0,
  totalPesan: 0,
  pesanPerDetik: 0,
  errorTerakhir: null,
  totalKoneksi: 0,
};

The core metrics of a WebSocket application include:

  • Active connections: the number of open connections right now.
  • Message throughput: messages in and out per second.
  • Message latency: the delivery time to the receiver.
  • Error rate: connection and message failures.
  • Connection duration: the average age of a connection.
  • Memory and CPU: the health of the Node.js process.

Connections growing without limit signal a leak — clients never close connections properly.

Logging

Meaningful Logs

Good logs tell the story of what happens to a connection.

JSLogging connection events
wss.on("connection", (ws, req) => {
  console.log("koneksi baru:", {
    ip: req.socket.remoteAddress,
    waktu: new Date().toISOString(),
    total: wss.clients.size,
  });
 
  ws.on("message", (data) => {
    console.log("pesan masuk:", data.length, "byte");
  });
 
  ws.on("close", (code, reason) => {
    console.log("koneksi ditutup:", code, reason.toString());
  });
});

Logging new connections, messages, and closures gives a complete timeline for every connection. Error logs must include context: the close code, the client identity, and a stack trace.

Log Levels

Do not log everything all the time — a log flood actually hides problems. Use levels: debug for development, info for important events, warn for anomalies, and error for failures. In production, restrict debug and rotate logs so the disk does not fill up.

Exposing Metrics to Prometheus

The Metrics Endpoint

Prometheus pulls metrics from an HTTP endpoint in the application.

JSExposing Prometheus metrics
const prometheus = require("prom-client");
 
const koneksiAktif = new prometheus.Gauge({
  name: "websocket_koneksi_aktif",
  help: "Jumlah koneksi WebSocket aktif",
});
 
const totalPesan = new prometheus.Counter({
  name: "websocket_pesan_total",
  help: "Total pesan diproses",
});
 
wss.on("connection", (ws) => {
  koneksiAktif.inc();
  ws.on("message", () => totalPesan.inc());
  ws.on("close", () => koneksiAktif.dec());
});
 
http.createServer(async (req, res) => {
  if (req.url === "/metrics") {
    res.setHeader("Content-Type", prometheus.register.contentType);
    res.end(await prometheus.register.metrics());
  }
}).listen(9100);

A Gauge represents a value that rises and falls, like the number of connections; a Counter represents a value that only increases, like the total messages. The /metrics endpoint on port 9100 is read periodically by Prometheus.

Prometheus Configuration

Prometheus schedules metric collection with a scrape configuration.

Prometheus scrape config
scrape_configs:
  - job_name: "websocket-server"
    scrape_interval: 15s
    static_configs:
      - targets: ["server-1:9100", "server-2:9100"]

scrape_interval: 15s sets the collection frequency. Each server instance is exposed as a separate target, and Prometheus combines them all.

Grafana and Distributed Tracing

Grafana Dashboards

Grafana turns numbers into visuals. A WebSocket dashboard usually shows panels for active connections, message throughput, latency percentiles, and error rate. Grafana alerting can fire notifications when a metric crosses a threshold, for example active connections breaking past 80 percent of capacity.

OpenTelemetry for Tracing

Distributed tracing follows a single event across many services.

JSSpan in OpenTelemetry
const tracer = opentelemetry.trace.getTracer("websocket-server");
 
socket.on("message:send", async (pesan) => {
  const span = tracer.startSpan("proses-pesan");
  span.setAttribute("pesan.id", pesan.id);
  try {
    await simpanDanKirim(pesan);
    span.setStatus({ code: 1 });
  } catch (err) {
    span.recordException(err);
    span.setStatus({ code: 2 });
  } finally {
    span.end();
  }
});

tracer.startSpan(...) marks the start and end of one operation. With context propagation, you can see where a slow message gets stuck across services.

Alerting

What to Alert On

Alerts must be meaningful and actionable.

  • Active connections above a threshold: capacity nearly full.
  • Error rate spiking: there is a bug or an attack.
  • High latency percentiles: users are feeling the delay.
  • High CPU and memory: need scaling or there is a leak.

One important rule: an alert you cannot act on is noise. Every alert must have a playbook — concrete steps to respond.

Closing

Episode 18 gave you sight into the running application: key metrics, meaningful logs, Grafana dashboards, and actionable alerts.

Key takeaways:

  • Measure active connections, throughput, latency, error rate, and resources.
  • Log every connection event with enough context.
  • Prometheus pulls metrics from the application endpoint.
  • Grafana displays dashboards and triggers alerts.
  • OpenTelemetry traces messages across many services.
  • Alerts must be actionable, not just noise.

In the next episode we cover security best practices: TLS with wss, authentication and input validation, protection against CSWSH and DoS, CORS, and security headers.

Learn WebSocket - Monitoring & Observability | Learn WebSocket