comprehensive monitoring and logging system
This commit is contained in:
99
lib/monitoring.ts
Normal file
99
lib/monitoring.ts
Normal 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
17
pages/api/health.ts
Normal 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()
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user