diff --git a/ecosystem.config.cjs b/ecosystem.config.cjs index bd07dbb..35864f0 100644 --- a/ecosystem.config.cjs +++ b/ecosystem.config.cjs @@ -39,6 +39,8 @@ module.exports = { // Worker aktivieren/deaktivieren QUEUE_ENABLE_EMAIL: 'true', QUEUE_ENABLE_PDF: 'true', + QUEUE_ENABLE_MONITORING: 'true', + MONITORING_SNAPSHOT_INTERVAL: '60000', // PDF-spezifische Optionen PDF_OUTPUT_DIR: '/tmp/payload-pdfs', // PDF_GENERATION_DISABLED: 'true', // Für Tests diff --git a/scripts/run-queue-worker.ts b/scripts/run-queue-worker.ts index 552ab9c..b8e9175 100644 --- a/scripts/run-queue-worker.ts +++ b/scripts/run-queue-worker.ts @@ -43,6 +43,9 @@ async function main() { const ENABLE_RETENTION_SCHEDULER = process.env.QUEUE_ENABLE_RETENTION_SCHEDULER !== 'false' const ENABLE_YOUTUBE_UPLOAD_WORKER = process.env.QUEUE_ENABLE_YOUTUBE_UPLOAD !== 'false' + // Monitoring (optional) + const ENABLE_MONITORING = process.env.QUEUE_ENABLE_MONITORING !== 'false' + console.log('='.repeat(50)) console.log('[QueueRunner] Starting queue workers...') console.log(`[QueueRunner] PID: ${process.pid}`) @@ -52,6 +55,7 @@ async function main() { console.log(`[QueueRunner] Retention Worker: ${ENABLE_RETENTION_WORKER ? 'enabled' : 'disabled'}`) console.log(`[QueueRunner] Retention Scheduler: ${ENABLE_RETENTION_SCHEDULER ? 'enabled' : 'disabled'}`) console.log(`[QueueRunner] YouTube Upload Worker: ${ENABLE_YOUTUBE_UPLOAD_WORKER ? 'enabled' : 'disabled'}`) + console.log(`[QueueRunner] Monitoring Collector: ${ENABLE_MONITORING ? 'enabled' : 'disabled'}`) console.log('='.repeat(50)) // Workers starten @@ -78,6 +82,15 @@ async function main() { startYouTubeUploadWorker() } + // Monitoring Snapshot Collector + if (ENABLE_MONITORING) { + const { startSnapshotCollector, stopSnapshotCollector } = await import('../src/lib/monitoring/snapshot-collector') + await startSnapshotCollector() + + // Store stop function for shutdown + ;(global as any).__stopSnapshotCollector = stopSnapshotCollector + } + // Graceful Shutdown async function shutdown(signal: string) { console.log(`\n[QueueRunner] Received ${signal}, shutting down gracefully...`) @@ -97,6 +110,9 @@ async function main() { if (ENABLE_YOUTUBE_UPLOAD_WORKER) { stopPromises.push(stopYouTubeUploadWorker()) } + if (ENABLE_MONITORING && (global as any).__stopSnapshotCollector) { + stopPromises.push((global as any).__stopSnapshotCollector()) + } await Promise.all(stopPromises) console.log('[QueueRunner] All workers stopped') diff --git a/src/lib/monitoring/snapshot-collector.ts b/src/lib/monitoring/snapshot-collector.ts new file mode 100644 index 0000000..5743563 --- /dev/null +++ b/src/lib/monitoring/snapshot-collector.ts @@ -0,0 +1,56 @@ +/** + * Snapshot Collector + * + * Periodische Metrik-Erfassung, laeuft im Queue-Worker PM2-Prozess. + * Sammelt alle 60s (konfigurierbar) System-Metriken und speichert + * sie in MonitoringSnapshots. Evaluiert dabei Alert-Regeln. + */ + +import { collectMetrics } from './monitoring-service.js' +import { AlertEvaluator } from './alert-evaluator.js' + +let interval: ReturnType | null = null +const alertEvaluator = new AlertEvaluator() + +export async function startSnapshotCollector(): Promise { + const INTERVAL = parseInt(process.env.MONITORING_SNAPSHOT_INTERVAL || '60000', 10) + console.log(`[SnapshotCollector] Starting (interval: ${INTERVAL}ms)`) + + // Run immediately once, then on interval + await collectAndSave() + + interval = setInterval(async () => { + await collectAndSave() + }, INTERVAL) +} + +async function collectAndSave(): Promise { + try { + const { getPayload } = await import('payload') + const config = (await import('@payload-config')).default + const payload = await getPayload({ config }) + + const metrics = await collectMetrics() + + await payload.create({ + collection: 'monitoring-snapshots', + data: { + timestamp: new Date().toISOString(), + ...metrics, + }, + }) + + // Evaluate alert rules against collected metrics + await alertEvaluator.evaluateRules(payload, metrics) + } catch (error) { + console.error('[SnapshotCollector] Error:', error) + } +} + +export async function stopSnapshotCollector(): Promise { + if (interval) { + clearInterval(interval) + interval = null + } + console.log('[SnapshotCollector] Stopped') +}