typescriptadvanced

Application Metrics Collection

Collect and expose application metrics like request counts, latency histograms, and custom gauges.

typescript
// Simple metrics collection (Prometheus-compatible output)

class Counter {
  private value = 0;
  constructor(public name: string, public help: string) {}
  inc(n = 1) { this.value += n; }
  get() { return this.value; }
  reset() { this.value = 0; }
  toPrometheus() { return `# HELP ${this.name} ${this.help}\n# TYPE ${this.name} counter\n${this.name} ${this.value}`; }
}

class Gauge {
  private value = 0;
  constructor(public name: string, public help: string) {}
  set(v: number) { this.value = v; }
  inc(n = 1) { this.value += n; }
  dec(n = 1) { this.value -= n; }
  get() { return this.value; }
  toPrometheus() { return `# HELP ${this.name} ${this.help}\n# TYPE ${this.name} gauge\n${this.name} ${this.value}`; }
}

class Histogram {
  private values: number[] = [];
  private sum = 0;
  private count = 0;
  constructor(public name: string, public help: string, public buckets: number[]) {}

  observe(value: number) {
    this.values.push(value);
    this.sum += value;
    this.count++;
  }

  toPrometheus() {
    const sorted = [...this.buckets].sort((a, b) => a - b);
    let lines = `# HELP ${this.name} ${this.help}\n# TYPE ${this.name} histogram\n`;
    for (const b of sorted) {
      const count = this.values.filter(v => v <= b).length;
      lines += `${this.name}_bucket{le="${b}"} ${count}\n`;
    }
    lines += `${this.name}_bucket{le="+Inf"} ${this.count}\n`;
    lines += `${this.name}_sum ${this.sum}\n`;
    lines += `${this.name}_count ${this.count}`;
    return lines;
  }
}

// Registry
class MetricsRegistry {
  private metrics: (Counter | Gauge | Histogram)[] = [];

  counter(name: string, help: string) { const m = new Counter(name, help); this.metrics.push(m); return m; }
  gauge(name: string, help: string) { const m = new Gauge(name, help); this.metrics.push(m); return m; }
  histogram(name: string, help: string, buckets = [5, 10, 25, 50, 100, 250, 500, 1000]) {
    const m = new Histogram(name, help, buckets);
    this.metrics.push(m);
    return m;
  }

  expose() { return this.metrics.map(m => m.toPrometheus()).join('\n\n'); }
}

// Usage
const registry = new MetricsRegistry();
const httpRequests = registry.counter('http_requests_total', 'Total HTTP requests');
const activeConnections = registry.gauge('active_connections', 'Active connections');
const responseTime = registry.histogram('http_response_time_ms', 'Response time in ms');

// Simulate traffic
httpRequests.inc();
httpRequests.inc();
activeConnections.set(5);
responseTime.observe(12);
responseTime.observe(45);
responseTime.observe(230);

// GET /metrics endpoint
console.log(registry.expose());

Use Cases

  • Prometheus metrics endpoint
  • Application performance monitoring
  • SLA tracking

Tags

Related Snippets

Similar patterns you can reuse in the same workflow.