mirror of
https://github.com/complexcaresolutions/cms.c2sgmbh.git
synced 2026-03-17 17:24:12 +00:00
feat(monitoring): add shared types for monitoring system
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
c7fd95d3da
commit
214e2ddde8
2 changed files with 241 additions and 0 deletions
148
src/lib/monitoring/types.ts
Normal file
148
src/lib/monitoring/types.ts
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
// === System Health ===
|
||||
export interface SystemHealth {
|
||||
cpuUsagePercent: number
|
||||
memoryUsedMB: number
|
||||
memoryTotalMB: number
|
||||
memoryUsagePercent: number
|
||||
diskUsedGB: number
|
||||
diskTotalGB: number
|
||||
diskUsagePercent: number
|
||||
loadAvg1: number
|
||||
loadAvg5: number
|
||||
uptime: number // seconds
|
||||
}
|
||||
|
||||
// === Service Statuses ===
|
||||
export type ServiceStatusType = 'online' | 'warning' | 'offline'
|
||||
|
||||
export interface ProcessStatus {
|
||||
status: ServiceStatusType
|
||||
pid: number
|
||||
memoryMB: number
|
||||
uptimeSeconds: number
|
||||
restarts: number
|
||||
}
|
||||
|
||||
export interface PostgresqlStatus {
|
||||
status: ServiceStatusType
|
||||
connections: number
|
||||
maxConnections: number
|
||||
latencyMs: number
|
||||
}
|
||||
|
||||
export interface PgBouncerStatus {
|
||||
status: ServiceStatusType
|
||||
activeConnections: number
|
||||
waitingClients: number
|
||||
poolSize: number
|
||||
}
|
||||
|
||||
export interface RedisStatus {
|
||||
status: ServiceStatusType
|
||||
memoryUsedMB: number
|
||||
connectedClients: number
|
||||
opsPerSec: number
|
||||
}
|
||||
|
||||
export interface ServiceStatuses {
|
||||
payload: ProcessStatus
|
||||
queueWorker: ProcessStatus
|
||||
postgresql: PostgresqlStatus
|
||||
pgbouncer: PgBouncerStatus
|
||||
redis: RedisStatus
|
||||
}
|
||||
|
||||
// === External Statuses ===
|
||||
export interface SmtpStatus {
|
||||
status: ServiceStatusType
|
||||
lastCheck: string // ISO date
|
||||
responseTimeMs: number
|
||||
}
|
||||
|
||||
export type OAuthStatusType = 'ok' | 'expiring_soon' | 'expired' | 'error'
|
||||
|
||||
export interface OAuthTokenStatus {
|
||||
status: OAuthStatusType
|
||||
tokensTotal: number
|
||||
tokensExpiringSoon: number
|
||||
tokensExpired: number
|
||||
}
|
||||
|
||||
export interface CronJobStatus {
|
||||
lastRun: string // ISO date
|
||||
status: 'ok' | 'failed' | 'unknown'
|
||||
}
|
||||
|
||||
export interface CronStatuses {
|
||||
communitySync: CronJobStatus
|
||||
tokenRefresh: CronJobStatus
|
||||
youtubeSync: CronJobStatus
|
||||
}
|
||||
|
||||
export interface ExternalStatuses {
|
||||
smtp: SmtpStatus
|
||||
metaOAuth: OAuthTokenStatus
|
||||
youtubeOAuth: OAuthTokenStatus
|
||||
cronJobs: CronStatuses
|
||||
}
|
||||
|
||||
// === Performance ===
|
||||
export interface PerformanceMetrics {
|
||||
avgResponseTimeMs: number
|
||||
p95ResponseTimeMs: number
|
||||
p99ResponseTimeMs: number
|
||||
errorRate: number // 0-1
|
||||
requestsPerMinute: number
|
||||
}
|
||||
|
||||
// === Full Snapshot ===
|
||||
export interface SystemMetrics {
|
||||
timestamp: string // ISO date
|
||||
system: SystemHealth
|
||||
services: ServiceStatuses
|
||||
external: ExternalStatuses
|
||||
performance: PerformanceMetrics
|
||||
}
|
||||
|
||||
// === SSE Events (discriminated union) ===
|
||||
export type MonitoringEvent =
|
||||
| { type: 'health'; data: SystemHealth }
|
||||
| { type: 'service'; data: Partial<ServiceStatuses> }
|
||||
| { type: 'alert'; data: AlertEvent }
|
||||
| { type: 'log'; data: LogEvent }
|
||||
| { type: 'performance'; data: PerformanceMetrics }
|
||||
|
||||
export interface AlertEvent {
|
||||
id: string
|
||||
ruleId: string
|
||||
metric: string
|
||||
value: number
|
||||
threshold: number
|
||||
severity: AlertSeverity
|
||||
message: string
|
||||
timestamp: string
|
||||
}
|
||||
|
||||
export interface LogEvent {
|
||||
id: string
|
||||
level: LogLevel
|
||||
source: LogSource
|
||||
message: string
|
||||
timestamp: string
|
||||
context?: Record<string, unknown>
|
||||
}
|
||||
|
||||
// === Enums as union types ===
|
||||
export type AlertCondition = 'gt' | 'lt' | 'eq' | 'gte' | 'lte'
|
||||
export type AlertSeverity = 'warning' | 'error' | 'critical'
|
||||
export type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'fatal'
|
||||
export type LogSource = 'payload' | 'queue-worker' | 'cron' | 'email' | 'oauth' | 'sync'
|
||||
|
||||
// === Performance Tracker Entry ===
|
||||
export interface PerformanceEntry {
|
||||
timestamp: number // Date.now()
|
||||
method: string
|
||||
path: string
|
||||
statusCode: number
|
||||
durationMs: number
|
||||
}
|
||||
93
tests/unit/monitoring/types.test.ts
Normal file
93
tests/unit/monitoring/types.test.ts
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
import { describe, it, expect } from 'vitest'
|
||||
import type {
|
||||
SystemMetrics,
|
||||
MonitoringEvent,
|
||||
AlertCondition,
|
||||
LogLevel,
|
||||
LogSource,
|
||||
} from '@/lib/monitoring/types'
|
||||
|
||||
describe('Monitoring Types', () => {
|
||||
it('SystemMetrics has all required sections', () => {
|
||||
const metrics: SystemMetrics = {
|
||||
timestamp: new Date().toISOString(),
|
||||
system: {
|
||||
cpuUsagePercent: 23,
|
||||
memoryUsedMB: 4200,
|
||||
memoryTotalMB: 8192,
|
||||
memoryUsagePercent: 51.3,
|
||||
diskUsedGB: 30,
|
||||
diskTotalGB: 50,
|
||||
diskUsagePercent: 60,
|
||||
loadAvg1: 0.5,
|
||||
loadAvg5: 0.8,
|
||||
uptime: 1209600,
|
||||
},
|
||||
services: {
|
||||
payload: {
|
||||
status: 'online',
|
||||
pid: 1234,
|
||||
memoryMB: 512,
|
||||
uptimeSeconds: 86400,
|
||||
restarts: 0,
|
||||
},
|
||||
queueWorker: {
|
||||
status: 'online',
|
||||
pid: 5678,
|
||||
memoryMB: 256,
|
||||
uptimeSeconds: 86400,
|
||||
restarts: 0,
|
||||
},
|
||||
postgresql: { status: 'online', connections: 12, maxConnections: 50, latencyMs: 2 },
|
||||
pgbouncer: { status: 'online', activeConnections: 8, waitingClients: 0, poolSize: 20 },
|
||||
redis: { status: 'online', memoryUsedMB: 48, connectedClients: 5, opsPerSec: 120 },
|
||||
},
|
||||
external: {
|
||||
smtp: {
|
||||
status: 'online',
|
||||
lastCheck: new Date().toISOString(),
|
||||
responseTimeMs: 180,
|
||||
},
|
||||
metaOAuth: { status: 'ok', tokensTotal: 2, tokensExpiringSoon: 1, tokensExpired: 0 },
|
||||
youtubeOAuth: { status: 'ok', tokensTotal: 3, tokensExpiringSoon: 0, tokensExpired: 0 },
|
||||
cronJobs: {
|
||||
communitySync: { lastRun: new Date().toISOString(), status: 'ok' },
|
||||
tokenRefresh: { lastRun: new Date().toISOString(), status: 'ok' },
|
||||
youtubeSync: { lastRun: new Date().toISOString(), status: 'ok' },
|
||||
},
|
||||
},
|
||||
performance: {
|
||||
avgResponseTimeMs: 120,
|
||||
p95ResponseTimeMs: 350,
|
||||
p99ResponseTimeMs: 800,
|
||||
errorRate: 0.02,
|
||||
requestsPerMinute: 45,
|
||||
},
|
||||
}
|
||||
|
||||
expect(metrics.system.cpuUsagePercent).toBe(23)
|
||||
expect(metrics.services.payload.status).toBe('online')
|
||||
expect(metrics.external.smtp.status).toBe('online')
|
||||
expect(metrics.performance.avgResponseTimeMs).toBe(120)
|
||||
})
|
||||
|
||||
it('MonitoringEvent types are exhaustive', () => {
|
||||
const events: MonitoringEvent['type'][] = ['health', 'service', 'alert', 'log', 'performance']
|
||||
expect(events).toHaveLength(5)
|
||||
})
|
||||
|
||||
it('AlertCondition covers all comparison operators', () => {
|
||||
const conditions: AlertCondition[] = ['gt', 'lt', 'eq', 'gte', 'lte']
|
||||
expect(conditions).toHaveLength(5)
|
||||
})
|
||||
|
||||
it('LogLevel covers all severity levels', () => {
|
||||
const levels: LogLevel[] = ['debug', 'info', 'warn', 'error', 'fatal']
|
||||
expect(levels).toHaveLength(5)
|
||||
})
|
||||
|
||||
it('LogSource covers all system components', () => {
|
||||
const sources: LogSource[] = ['payload', 'queue-worker', 'cron', 'email', 'oauth', 'sync']
|
||||
expect(sources).toHaveLength(6)
|
||||
})
|
||||
})
|
||||
Loading…
Reference in a new issue