Observability — metrics, logs, and traces.
1const promClient = require("prom-client");2const pino = require("pino");3const { NodeTracerProvider } = require("@opentelemetry/sdk-trace-node");45// Metrics6const metrics = {7 httpRequestDuration: new promClient.Histogram({8 name: "http_request_duration_seconds",9 help: "Duration of HTTP requests",10 labelNames: ["method", "route", "status"],11 buckets: [0.1, 0.5, 1, 2, 5],12 }),13 activeConnections: new promClient.Gauge({14 name: "active_connections",15 help: "Number of active connections",16 }),17 errorRate: new promClient.Counter({18 name: "errors_total",19 help: "Total errors",20 labelNames: ["type"],21 }),22};2324// Logging25const logger = pino({26 level: "info",27 formatters: {28 level: (label) => ({ level: label }),29 },30});3132// Middleware33app.use((req, res, next) => {34 const start = Date.now();35 metrics.activeConnections.inc();3637 res.on("finish", () => {38 const duration = (Date.now() - start) / 1000;39 metrics.httpRequestDuration40 .labels(req.method, req.route?.path || "unknown", res.statusCode)41 .observe(duration);42 metrics.activeConnections.dec();4344 logger.info({45 method: req.method,46 url: req.url,47 status: res.statusCode,48 duration,49 });50 });5152 next();53});5455// Metrics endpoint56app.get("/metrics", async (req, res) => {57 res.setHeader("Content-Type", promClient.register.contentType);58 res.end(await promClient.register.metrics());59});