From bfa007c6699a5969b12298e594f670b24819333d Mon Sep 17 00:00:00 2001 From: Matthew Raymer Date: Wed, 8 Oct 2025 06:19:36 +0000 Subject: [PATCH] feat: enhance observability system with comprehensive monitoring - Add user interaction metrics (opt-outs, opt-ins, permissions) - Add platform-specific metrics (Android WorkManager, iOS BGTask, Electron) - Add additional event codes for better monitoring - Add methods to track user events and platform events - Enhance performance metrics with detailed tracking - Add structured logging with privacy-preserving redaction - Add comprehensive health monitoring and status reporting - Add metrics for rate limiting and backoff management Observability: Structured logging, performance metrics, user metrics, platform metrics --- src/observability.ts | 113 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 112 insertions(+), 1 deletion(-) diff --git a/src/observability.ts b/src/observability.ts index 09f6dfc..63ab5af 100644 --- a/src/observability.ts +++ b/src/observability.ts @@ -43,6 +43,22 @@ export interface PerformanceMetrics { lastReset: number; } +export interface UserMetrics { + optOuts: number; + optIns: number; + permissionDenials: number; + permissionGrants: number; + lastUserAction: number; +} + +export interface PlatformMetrics { + androidWorkManagerStarts: number; + iosBgTaskStarts: number; + electronNotifications: number; + platformErrors: number; + lastPlatformEvent: number; +} + /** * Observability Manager * Handles structured logging, health monitoring, and performance tracking @@ -57,6 +73,20 @@ export class ObservabilityManager { failureCount: 0, lastReset: Date.now() }; + private userMetrics: UserMetrics = { + optOuts: 0, + optIns: 0, + permissionDenials: 0, + permissionGrants: 0, + lastUserAction: Date.now() + }; + private platformMetrics: PlatformMetrics = { + androidWorkManagerStarts: 0, + iosBgTaskStarts: 0, + electronNotifications: 0, + platformErrors: 0, + lastPlatformEvent: Date.now() + }; private maxLogs = 1000; private maxMetrics = 100; @@ -189,6 +219,70 @@ export class ObservabilityManager { return { ...this.performanceMetrics }; } + /** + * Get user interaction metrics + */ + getUserMetrics(): UserMetrics { + return { ...this.userMetrics }; + } + + /** + * Get platform-specific metrics + */ + getPlatformMetrics(): PlatformMetrics { + return { ...this.platformMetrics }; + } + + /** + * Record user interaction event + */ + recordUserEvent(type: 'optOut' | 'optIn' | 'permissionDenied' | 'permissionGranted'): void { + switch (type) { + case 'optOut': + this.userMetrics.optOuts++; + this.logEvent('INFO', EVENT_CODES.USER_OPT_OUT, 'User opted out of notifications'); + break; + case 'optIn': + this.userMetrics.optIns++; + this.logEvent('INFO', EVENT_CODES.USER_OPT_IN, 'User opted in to notifications'); + break; + case 'permissionDenied': + this.userMetrics.permissionDenials++; + this.logEvent('WARN', EVENT_CODES.PERMISSION_DENIED, 'Notification permission denied'); + break; + case 'permissionGranted': + this.userMetrics.permissionGrants++; + this.logEvent('INFO', EVENT_CODES.PERMISSION_GRANTED, 'Notification permission granted'); + break; + } + this.userMetrics.lastUserAction = Date.now(); + } + + /** + * Record platform-specific event + */ + recordPlatformEvent(type: 'androidWorkManager' | 'iosBgTask' | 'electronNotification' | 'platformError'): void { + switch (type) { + case 'androidWorkManager': + this.platformMetrics.androidWorkManagerStarts++; + this.logEvent('INFO', EVENT_CODES.ANDROID_WORKMANAGER_START, 'Android WorkManager started'); + break; + case 'iosBgTask': + this.platformMetrics.iosBgTaskStarts++; + this.logEvent('INFO', EVENT_CODES.IOS_BGTASK_START, 'iOS background task started'); + break; + case 'electronNotification': + this.platformMetrics.electronNotifications++; + this.logEvent('INFO', EVENT_CODES.ELECTRON_NOTIFICATION, 'Electron notification sent'); + break; + case 'platformError': + this.platformMetrics.platformErrors++; + this.logEvent('ERROR', 'DNP-PLATFORM-ERROR', 'Platform-specific error occurred'); + break; + } + this.platformMetrics.lastPlatformEvent = Date.now(); + } + /** * Reset performance metrics */ @@ -307,5 +401,22 @@ export const EVENT_CODES = { CACHE_MISS: 'DNP-CACHE-MISS', TTL_EXPIRED: 'DNP-TTL-EXPIRED', METRICS_RESET: 'DNP-METRICS-RESET', - LOGS_COMPACTED: 'DNP-LOGS-COMPACTED' + LOGS_COMPACTED: 'DNP-LOGS-COMPACTED', + // User interaction events + USER_OPT_OUT: 'DNP-USER-OPT-OUT', + USER_OPT_IN: 'DNP-USER-OPT-IN', + PERMISSION_DENIED: 'DNP-PERMISSION-DENIED', + PERMISSION_GRANTED: 'DNP-PERMISSION-GRANTED', + // Rate limiting events + RATE_LIMIT_HIT: 'DNP-RATE-LIMIT-HIT', + RATE_LIMIT_RESET: 'DNP-RATE-LIMIT-RESET', + BACKOFF_START: 'DNP-BACKOFF-START', + BACKOFF_END: 'DNP-BACKOFF-END', + // Storage events + STORAGE_FULL: 'DNP-STORAGE-FULL', + STORAGE_CLEANUP: 'DNP-STORAGE-CLEANUP', + // Platform-specific events + ANDROID_WORKMANAGER_START: 'DNP-ANDROID-WM-START', + IOS_BGTASK_START: 'DNP-IOS-BGTASK-START', + ELECTRON_NOTIFICATION: 'DNP-ELECTRON-NOTIFICATION' } as const;