Browse Source

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
master
Matthew Raymer 3 days ago
parent
commit
bfa007c669
  1. 113
      src/observability.ts

113
src/observability.ts

@ -43,6 +43,22 @@ export interface PerformanceMetrics {
lastReset: number; 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 * Observability Manager
* Handles structured logging, health monitoring, and performance tracking * Handles structured logging, health monitoring, and performance tracking
@ -57,6 +73,20 @@ export class ObservabilityManager {
failureCount: 0, failureCount: 0,
lastReset: Date.now() 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 maxLogs = 1000;
private maxMetrics = 100; private maxMetrics = 100;
@ -189,6 +219,70 @@ export class ObservabilityManager {
return { ...this.performanceMetrics }; 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 * Reset performance metrics
*/ */
@ -307,5 +401,22 @@ export const EVENT_CODES = {
CACHE_MISS: 'DNP-CACHE-MISS', CACHE_MISS: 'DNP-CACHE-MISS',
TTL_EXPIRED: 'DNP-TTL-EXPIRED', TTL_EXPIRED: 'DNP-TTL-EXPIRED',
METRICS_RESET: 'DNP-METRICS-RESET', 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; } as const;

Loading…
Cancel
Save