Implement Prometheus metrics endpoint (P2.16)
Add comprehensive metrics collection for production monitoring: - src/lib/metrics.ts: prom-client based metrics library with custom counters, gauges, and histograms for Garmin sync, email, and decision engine - GET /api/metrics: Prometheus-format endpoint for scraping - Integration into garmin-sync cron: sync duration, success/failure counts, active users gauge - Integration into email.ts: daily and warning email counters - Integration into decision-engine.ts: decision type counters Custom metrics implemented: - phaseflow_garmin_sync_total (counter with status label) - phaseflow_garmin_sync_duration_seconds (histogram) - phaseflow_email_sent_total (counter with type label) - phaseflow_decision_engine_calls_total (counter with decision label) - phaseflow_active_users (gauge) 33 new tests (18 library + 15 route), bringing total to 586 tests. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
49
src/lib/metrics.ts
Normal file
49
src/lib/metrics.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
// ABOUTME: Prometheus metrics collection module for production monitoring.
|
||||
// ABOUTME: Exposes counters, gauges, and histograms for Garmin sync, email, and decision engine.
|
||||
|
||||
import * as promClient from "prom-client";
|
||||
|
||||
// Create a new registry for our application metrics
|
||||
export const metricsRegistry = new promClient.Registry();
|
||||
|
||||
// Collect default Node.js metrics (heap, event loop, etc.)
|
||||
promClient.collectDefaultMetrics({ register: metricsRegistry });
|
||||
|
||||
// Custom metric: Garmin sync operations counter
|
||||
export const garminSyncTotal = new promClient.Counter({
|
||||
name: "phaseflow_garmin_sync_total",
|
||||
help: "Total number of Garmin sync operations",
|
||||
labelNames: ["status"] as const,
|
||||
registers: [metricsRegistry],
|
||||
});
|
||||
|
||||
// Custom metric: Garmin sync duration histogram
|
||||
export const garminSyncDuration = new promClient.Histogram({
|
||||
name: "phaseflow_garmin_sync_duration_seconds",
|
||||
help: "Duration of Garmin sync operations in seconds",
|
||||
buckets: [0.1, 0.5, 1, 2, 5, 10],
|
||||
registers: [metricsRegistry],
|
||||
});
|
||||
|
||||
// Custom metric: Email sent counter
|
||||
export const emailSentTotal = new promClient.Counter({
|
||||
name: "phaseflow_email_sent_total",
|
||||
help: "Total number of emails sent",
|
||||
labelNames: ["type"] as const,
|
||||
registers: [metricsRegistry],
|
||||
});
|
||||
|
||||
// Custom metric: Decision engine calls counter
|
||||
export const decisionEngineCallsTotal = new promClient.Counter({
|
||||
name: "phaseflow_decision_engine_calls_total",
|
||||
help: "Total number of decision engine calls",
|
||||
labelNames: ["decision"] as const,
|
||||
registers: [metricsRegistry],
|
||||
});
|
||||
|
||||
// Custom metric: Active users gauge
|
||||
export const activeUsersGauge = new promClient.Gauge({
|
||||
name: "phaseflow_active_users",
|
||||
help: "Number of users with activity in the last 24 hours",
|
||||
registers: [metricsRegistry],
|
||||
});
|
||||
Reference in New Issue
Block a user