managarten/packages/shared-nestjs-metrics/src/metrics.module.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

79 lines
1.9 KiB
TypeScript

import { Module, DynamicModule, MiddlewareConsumer, NestModule } from '@nestjs/common';
import { MetricsService, MetricsServiceOptions } from './metrics.service';
import { MetricsMiddleware } from './metrics.middleware';
import { MetricsController } from './metrics.controller';
export interface MetricsModuleOptions extends MetricsServiceOptions {
/**
* Path for metrics endpoint (default: '/metrics')
*/
path?: string;
/**
* Paths to exclude from metrics collection
*/
excludePaths?: string[];
/**
* Whether to register the metrics endpoint controller (default: true)
*/
registerController?: boolean;
}
@Module({})
export class MetricsModule implements NestModule {
private static options: MetricsModuleOptions = {};
/**
* Register the metrics module with options
*
* @example
* ```typescript
* import { MetricsModule } from '@manacore/shared-nestjs-metrics';
*
* @Module({
* imports: [
* MetricsModule.register({
* prefix: 'myapp_',
* defaultLabels: { app: 'my-backend' },
* }),
* ],
* })
* export class AppModule {}
* ```
*/
static register(options: MetricsModuleOptions = {}): DynamicModule {
MetricsModule.options = options;
const providers = [
{
provide: MetricsService,
useFactory: () => new MetricsService(options),
},
MetricsMiddleware,
];
const controllers = options.registerController !== false ? [MetricsController] : [];
return {
module: MetricsModule,
controllers,
providers,
exports: [MetricsService],
global: true,
};
}
configure(consumer: MiddlewareConsumer) {
const excludePaths = MetricsModule.options.excludePaths || [];
const metricsPath = MetricsModule.options.path || '/metrics';
// Always exclude the metrics endpoint itself
const allExcludePaths = [...excludePaths, metricsPath];
consumer
.apply(MetricsMiddleware)
.exclude(...allExcludePaths)
.forRoutes('*');
}
}