managarten/packages/shared-nestjs-metrics/src/metrics.middleware.ts
Till-JS 6d86a08d63 feat: add monitoring dashboard (Prometheus + Grafana + Umami + Admin)
Phase 1: Infrastructure
- Add docker/prometheus/prometheus.yml with scrape configs for all services
- Add docker/grafana/provisioning for auto-configured datasources
- Add docker/grafana/dashboards (system-overview, backends-docker)
- Update docker-compose.macmini.yml with monitoring services:
  - prometheus, grafana, node-exporter, cadvisor
  - postgres-exporter, redis-exporter, umami
- Add grafana.mana.how and analytics.mana.how to Caddyfile

Phase 2: Backend Metrics
- Create packages/shared-nestjs-metrics with:
  - MetricsModule (auto /metrics endpoint)
  - MetricsService (Counter, Histogram, Gauge helpers)
  - MetricsMiddleware (auto HTTP request tracking)

Phase 3: Umami Web Analytics
- Add Umami tracking scripts to all landing pages
- Add Umami tracking scripts to all web apps
- Create scripts/mac-mini/setup-umami-db.sh

Phase 4: Admin Dashboard (ManaCore Web)
- Add admin routes: /admin, /admin/users, /admin/system
- Create StatCard, QuickLinks, UserTable components
- Add Admin link to navigation

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-23 15:31:39 +01:00

35 lines
1 KiB
TypeScript

import { Injectable, NestMiddleware } from '@nestjs/common';
import { Request, Response, NextFunction } from 'express';
import { MetricsService } from './metrics.service';
@Injectable()
export class MetricsMiddleware implements NestMiddleware {
constructor(private readonly metricsService: MetricsService) {}
use(req: Request, res: Response, next: NextFunction): void {
// Skip metrics endpoint itself to avoid recursion
if (req.path === '/metrics') {
return next();
}
const startTime = Date.now();
const method = req.method;
// Track in-flight requests
this.metricsService.incrementInFlight(method);
// Hook into response finish
res.on('finish', () => {
const duration = Date.now() - startTime;
const status = res.statusCode;
const path = req.route?.path || req.path;
// Record metrics
this.metricsService.incrementHttpRequests(method, path, status);
this.metricsService.observeHttpDuration(method, path, status, duration);
this.metricsService.decrementInFlight(method);
});
next();
}
}