← back to Wine Finder Next
app/api/monitoring/performance/route.ts
110 lines
// Performance Monitoring Dashboard API
// GET /api/monitoring/performance
import { NextRequest, NextResponse } from 'next/server';
import { perfMonitor, queryCache } from '@/lib/membershipDatabase.optimized';
import { getTimingStats } from '@/lib/apiOptimization';
import { getConnectionPool } from '@/lib/connectionPool';
export async function GET(request: NextRequest) {
const { searchParams } = new URL(request.url);
const operation = searchParams.get('operation');
try {
// Get database operation metrics
const dbMetrics = {
'bottle.getAll': perfMonitor.getAverageTime('bottle.getAll'),
'bottle.getById': perfMonitor.getAverageTime('bottle.getById'),
'bottle.create': perfMonitor.getAverageTime('bottle.create'),
'bottle.update': perfMonitor.getAverageTime('bottle.update'),
'unit.getByBottleId': perfMonitor.getAverageTime('unit.getByBottleId'),
'unit.getByOwnerId': perfMonitor.getAverageTime('unit.getByOwnerId'),
'vote.getActive': perfMonitor.getAverageTime('vote.getActive'),
'vote.cast': perfMonitor.getAverageTime('vote.cast'),
'marketplace.getActive': perfMonitor.getAverageTime('marketplace.getActive')
};
// Get API endpoint metrics
const apiMetrics = {
'bottles.GET': getTimingStats('bottles.GET'),
'bottles.POST': getTimingStats('bottles.POST')
};
// Get cache statistics
const cacheStats = queryCache.getStats();
// Get connection pool stats (if available)
let poolStats = null;
try {
poolStats = getConnectionPool().getDetailedStats();
} catch (e) {
// Pool might not be initialized
}
// Memory usage
const memoryUsage = process.memoryUsage();
const response = {
timestamp: new Date().toISOString(),
database: {
operations: dbMetrics,
slowQueries: Object.entries(dbMetrics)
.filter(([_, time]) => time > 50)
.map(([op, time]) => ({ operation: op, avgTime: time }))
},
api: {
endpoints: apiMetrics,
slowEndpoints: Object.entries(apiMetrics)
.filter(([_, stats]) => stats && stats.avg > 100)
.map(([endpoint, stats]) => ({ endpoint, ...stats }))
},
cache: {
size: cacheStats.size,
totalHits: cacheStats.totalHits,
averageHits: cacheStats.avgHits,
hitRate: cacheStats.totalHits > 0
? ((cacheStats.totalHits / (cacheStats.totalHits + cacheStats.size)) * 100).toFixed(2)
: 0
},
connectionPool: poolStats,
memory: {
heapUsed: Math.round(memoryUsage.heapUsed / 1024 / 1024),
heapTotal: Math.round(memoryUsage.heapTotal / 1024 / 1024),
rss: Math.round(memoryUsage.rss / 1024 / 1024),
external: Math.round(memoryUsage.external / 1024 / 1024)
},
uptime: Math.round(process.uptime()),
nodeVersion: process.version
};
return NextResponse.json(response, {
headers: {
'Cache-Control': 'no-store, max-age=0'
}
});
} catch (error) {
return NextResponse.json(
{ error: 'Failed to fetch performance metrics' },
{ status: 500 }
);
}
}
// Clear metrics
export async function DELETE(request: NextRequest) {
try {
perfMonitor.clearMetrics();
queryCache.invalidate();
return NextResponse.json({
success: true,
message: 'Performance metrics cleared'
});
} catch (error) {
return NextResponse.json(
{ error: 'Failed to clear metrics' },
{ status: 500 }
);
}
}