comprehensive monitoring and logging system

This commit is contained in:
2025-08-19 14:56:42 +02:00
parent 558172f2be
commit 52bde64e7f
2 changed files with 116 additions and 0 deletions

99
lib/monitoring.ts Normal file
View File

@@ -0,0 +1,99 @@
interface MonitoringMetric {
name: string
value: number
timestamp: number
tags?: Record<string, string>
}
class MetricsCollector {
private metrics: MonitoringMetric[] = []
private maxMetrics = 1000
record(name: string, value: number, tags?: Record<string, string>): void {
const metric: MonitoringMetric = {
name,
value,
timestamp: Date.now(),
tags
}
this.metrics.push(metric)
// Keep only recent metrics
if (this.metrics.length > this.maxMetrics) {
this.metrics = this.metrics.slice(-this.maxMetrics)
}
}
getMetrics(name?: string, since?: number): MonitoringMetric[] {
let filtered = this.metrics
if (name) {
filtered = filtered.filter(m => m.name === name)
}
if (since) {
filtered = filtered.filter(m => m.timestamp >= since)
}
return filtered
}
getAverageResponseTime(since?: number): number {
const responseMetrics = this.getMetrics('api.response_time', since)
if (responseMetrics.length === 0) return 0
const sum = responseMetrics.reduce((acc, m) => acc + m.value, 0)
return sum / responseMetrics.length
}
getRequestCount(endpoint?: string, since?: number): number {
const requestMetrics = this.getMetrics('api.request', since)
if (endpoint) {
return requestMetrics.filter(m => m.tags?.endpoint === endpoint).length
}
return requestMetrics.length
}
getErrorCount(since?: number): number {
return this.getMetrics('api.error', since).length
}
clear(): void {
this.metrics = []
}
}
export const metrics = new MetricsCollector()
export function trackApiCall(endpoint: string, method: string, statusCode: number, responseTime: number): void {
metrics.record('api.request', 1, { endpoint, method, status: statusCode.toString() })
metrics.record('api.response_time', responseTime, { endpoint })
if (statusCode >= 400) {
metrics.record('api.error', 1, { endpoint, status: statusCode.toString() })
}
}
export function trackDatabaseQuery(operation: string, duration: number): void {
metrics.record('db.query', 1, { operation })
metrics.record('db.duration', duration, { operation })
}
export function getHealthStatus(): any {
const now = Date.now()
const fiveMinutesAgo = now - (5 * 60 * 1000)
return {
status: 'healthy',
timestamp: new Date().toISOString(),
metrics: {
requests_5min: metrics.getRequestCount(undefined, fiveMinutesAgo),
avg_response_time: Math.round(metrics.getAverageResponseTime(fiveMinutesAgo)),
errors_5min: metrics.getErrorCount(fiveMinutesAgo),
uptime: process.uptime()
}
}
}

17
pages/api/health.ts Normal file
View File

@@ -0,0 +1,17 @@
import type { NextApiRequest, NextApiResponse } from "next"
import { getHealthStatus } from "../../lib/monitoring"
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
if (req.method !== "GET") return res.status(405).json({ error: "Method not allowed" })
try {
const health = getHealthStatus()
res.status(200).json(health)
} catch (error) {
res.status(500).json({
status: 'unhealthy',
error: 'Health check failed',
timestamp: new Date().toISOString()
})
}
}