Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 47 additions & 2 deletions backend/src/common/monitoring/metrics.service.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { Injectable, Logger } from '@nestjs/common';
import { Counter, Histogram, Registry } from 'prom-client';
import { Counter, Histogram, Registry, Gauge } from 'prom-client';
import { DataSource } from 'typeorm';
import { Optional } from '@nestjs/common';

@Injectable()
export class MetricsService {
Expand All @@ -14,13 +16,16 @@ export class MetricsService {
// Database metrics
private dbQueryDuration: Histogram;
private dbConnectionStatus: Counter;
private dbPoolActiveConnections: Gauge;
private dbPoolIdleConnections: Gauge;
private dbPoolWaitingQueries: Gauge;

// Application metrics
private certificateIssued: Counter;
private certificateVerified: Counter;
private authenticationAttempts: Counter;

constructor() {
constructor(@Optional() private readonly dataSource?: DataSource) {
this.registry = new Registry();

// Initialize HTTP metrics
Expand Down Expand Up @@ -60,6 +65,46 @@ export class MetricsService {
registers: [this.registry],
});

this.dbPoolActiveConnections = new Gauge({
name: 'db_pool_active_connections',
help: 'Number of active database connections in the pool',
registers: [this.registry],
collect: () => {
const pool = (this.dataSource?.driver as any)?.master;
if (
pool &&
typeof pool.totalCount === 'number' &&
typeof pool.idleCount === 'number'
) {
this.dbPoolActiveConnections.set(pool.totalCount - pool.idleCount);
}
},
});

this.dbPoolIdleConnections = new Gauge({
name: 'db_pool_idle_connections',
help: 'Number of idle database connections in the pool',
registers: [this.registry],
collect: () => {
const pool = (this.dataSource?.driver as any)?.master;
if (pool && typeof pool.idleCount === 'number') {
this.dbPoolIdleConnections.set(pool.idleCount);
}
},
});

this.dbPoolWaitingQueries = new Gauge({
name: 'db_pool_waiting_queries',
help: 'Number of queued queries waiting for a database connection',
registers: [this.registry],
collect: () => {
const pool = (this.dataSource?.driver as any)?.master;
if (pool && typeof pool.waitingCount === 'number') {
this.dbPoolWaitingQueries.set(pool.waitingCount);
}
},
});

// Initialize Application metrics
this.certificateIssued = new Counter({
name: 'certificate_issued_total',
Expand Down