fix: use singleton pattern and force nodejs runtime for metrics route

- Add runtime = 'nodejs' to ensure Node.js environment
- Add dynamic = 'force-dynamic' to prevent static optimization
- Use singleton pattern to avoid duplicate metric registration
- Add error logging for debugging

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
soufiane 2025-11-25 16:24:33 +01:00
parent 5f2f71e539
commit d636578761

View File

@ -1,30 +1,55 @@
import { NextResponse } from 'next/server';
import client from 'prom-client';
// Create a Registry to register the metrics
const register = new client.Registry();
// Force Node.js runtime for this route
export const runtime = 'nodejs';
export const dynamic = 'force-dynamic';
// Add default metrics (CPU, memory, etc.)
client.collectDefaultMetrics({ register });
// Singleton pattern to avoid duplicate metric registration
const globalForProm = globalThis as unknown as {
promRegistry: client.Registry | undefined;
metricsInitialized: boolean | undefined;
};
// Custom metrics
const httpRequestsTotal = new client.Counter({
name: 'http_requests_total',
help: 'Total number of HTTP requests',
labelNames: ['method', 'path', 'status'],
registers: [register],
});
function getRegistry(): client.Registry {
if (!globalForProm.promRegistry) {
globalForProm.promRegistry = new client.Registry();
}
return globalForProm.promRegistry;
}
const httpRequestDuration = new client.Histogram({
name: 'http_request_duration_seconds',
help: 'Duration of HTTP requests in seconds',
labelNames: ['method', 'path'],
buckets: [0.1, 0.3, 0.5, 0.7, 1, 3, 5, 7, 10],
registers: [register],
});
function initializeMetrics(register: client.Registry) {
if (globalForProm.metricsInitialized) {
return;
}
// Add default metrics (CPU, memory, etc.)
client.collectDefaultMetrics({ register });
// Custom metrics
new client.Counter({
name: 'http_requests_total',
help: 'Total number of HTTP requests',
labelNames: ['method', 'path', 'status'],
registers: [register],
});
new client.Histogram({
name: 'http_request_duration_seconds',
help: 'Duration of HTTP requests in seconds',
labelNames: ['method', 'path'],
buckets: [0.1, 0.3, 0.5, 0.7, 1, 3, 5, 7, 10],
registers: [register],
});
globalForProm.metricsInitialized = true;
}
export async function GET() {
try {
const register = getRegistry();
initializeMetrics(register);
const metrics = await register.metrics();
return new NextResponse(metrics, {
status: 200,
@ -33,6 +58,7 @@ export async function GET() {
},
});
} catch (error) {
console.error('Metrics error:', error);
return NextResponse.json({ error: 'Failed to get metrics' }, { status: 500 });
}
}