MonitorService.ts

Fixed hardcoded environment variables and simplified configuration by removing unnecessary serviceVersion parameter

MonitorService.tsv2.0.011.6 KB
MonitorService.ts(typescript)
1/**
2 * Monitor Service - Adapted from UCM pattern for application monitoring
3 * 
4 * This service provides comprehensive application monitoring capabilities including
5 * performance metrics, health checks, system statistics, and resource monitoring.
6 * 
7 */
8
9import { BaseService, ServiceMetadata } from "@/core/interfaces/BaseService";
10import { ILogger } from "@/core/logging/ILogger";
11
12/**
13 * Token usage information for AI API calls
14 */
15export interface TokenUsage {
16  promptTokens: number;
17  completionTokens: number;
18  totalTokens: number;
19}
20
21/**
22 * User-related events for tracking user behavior
23 */
24export enum UserEventType {
25  Registered = 'User.Registered',
26  EmailVerified = 'User.EmailVerified',
27  LoggedIn = 'User.LoggedIn',
28  LoginSuccessful = 'User.LoginSuccessful',
29  LoginFailed = 'User.LoginFailed',
30  PasswordChanged = 'User.PasswordChanged',
31  ProfileUpdated = 'User.ProfileUpdated',
32  AccountDeleted = 'User.AccountDeleted'
33}
34
35/**
36 * System-related events for tracking operational metrics
37 */
38export enum SystemEventType {
39  ServiceStarted = 'System.ServiceStarted',
40  ServiceStopped = 'System.ServiceStopped',
41  HealthCheckPassed = 'System.HealthCheckPassed',
42  HealthCheckFailed = 'System.HealthCheckFailed',
43  ConfigurationChanged = 'System.ConfigurationChanged',
44  QuotaExceeded = 'System.QuotaExceeded',
45  QuotaWarning = 'System.QuotaWarning',
46  WorkerStarted = 'System.WorkerStarted',
47  WorkerStopped = 'System.WorkerStopped',
48  JobEnqueued = 'System.JobEnqueued',
49  EmailSent = 'System.EmailSent'
50}
51
52/**
53 * Security-related events for tracking security incidents
54 */
55export enum SecurityEventType {
56  LoginAttemptFailed = 'Security.LoginAttemptFailed',
57  PasswordResetRequested = 'Security.PasswordResetRequested',
58  PasswordResetCompleted = 'Security.PasswordResetCompleted',
59  SuspiciousActivity = 'Security.SuspiciousActivity',
60  UnauthorizedAccess = 'Security.UnauthorizedAccess',
61  AccountLocked = 'Security.AccountLocked',
62  AccountUnlocked = 'Security.AccountUnlocked',
63  AdminActionPerformed = 'Security.AdminActionPerformed',
64  EmailVerificationFailed = 'Security.EmailVerificationFailed',
65  AuthenticationFailed = 'Authentication.Failed',
66  AuthenticationSuccess = 'Authentication.Success',
67  AuthorizationFailed = 'Authorization.Failed',
68  AdminAccess = 'Admin.Access',
69  AdminSessionTimeout = 'Admin.SessionTimeout',
70  RateLimitExceeded = 'RateLimit.Exceeded'
71}
72
73/**
74 * Monitor service interface for tracking events and telemetry
75 * Provides centralized monitoring and alerting capabilities
76 */
77export interface IMonitorService {
78  /**
79   * Track any custom event with arbitrary parameters
80   * @param eventName - The name of the event (use dot notation: Category.Action)
81   * @param params - Event parameters and metadata
82   */
83  onEvent(eventName: string, params: any): Promise<void>;
84  
85  /**
86   * Track user-related events
87   * @param event - The user event type
88   * @param userId - The user ID associated with the event
89   * @param details - Additional event details
90   */
91  onUserEvent(event: UserEventType, userId: string, details?: any): Promise<void>;
92  
93  /**
94   * Track system-related events
95   * @param event - The system event type
96   * @param details - Event details and metadata
97   */
98  onSystemEvent(event: SystemEventType, details: any): Promise<void>;
99  
100  /**
101   * Track security-related events
102   * @param event - The security event type
103   * @param userId - The user ID associated with the event (if applicable)
104   * @param details - Security event details
105   */
106  onSecurityEvent(event: SecurityEventType, userId: string, details: any): Promise<void>;
107  
108  /**
109   * Track AI token usage for cost monitoring
110   * @param model - The AI model used (e.g., 'gpt-4', 'gpt-3.5-turbo')
111   * @param tokens - Token usage information
112   * @param jobId - The job ID associated with the usage
113   * @param userId - The user ID who initiated the request (optional)
114   */
115  onCostEvent(model: string, tokens: TokenUsage, jobId: string, userId?: string): Promise<void>;
116  
117  /**
118   * Check if the monitoring service is healthy and connected
119   * @returns True if healthy
120   */
121  isHealthy(): Promise<boolean>;
122  
123  /**
124   * Initialize the monitoring service
125   * @param config - Optional configuration
126   */
127  initialize(config?: Record<string, any>): Promise<void>;
128  
129  /**
130   * Gracefully shutdown the monitoring service
131   */
132  destroy(): Promise<void>;
133}
134
135/**
136 * Monitoring configuration interface
137 */
138export interface TokenTrackingConfig {
139  dailyTokenLimit: number;
140  warningThresholdPercent: number;
141}
142
143export interface MonitoringConfig {
144  enabled: boolean;
145  serviceName: string;
146  tokenTracking?: TokenTrackingConfig;
147}
148
149/**
150 * Monitor service for tracking events and telemetry
151 * 
152 * Features:
153 * - Custom event tracking
154 * - Cost event usage monitoring
155 * - Security event tracking
156 * - System health monitoring
157 * - Structured logging with event correlation
158 * - Console-based implementation for simplicity
159 * - Extendable with your own telemetry client.
160 * 
161 * Perfect for:
162 * - Applications requiring event monitoring
163 * - AI applications needing token usage tracking
164 * - Security-conscious systems
165 * - Multi-service architectures
166 */
167export class MonitorService extends BaseService implements IMonitorService {
168  private config: MonitoringConfig;
169  private enabled: boolean;
170  private initialized: boolean = false;
171
172  static readonly metadata: ServiceMetadata = {
173    name: 'MonitorService',
174    displayName: 'Simple Monitor',
175    description: 'Simple monitoring and event tracking service with console output',
176    contract: 'IMonitorService',
177    implementation: 'Console',
178    version: '2.0.0',
179    contractVersion: '1.0.0',
180    
181    features: [
182      'Custom event tracking', 
183      'Token usage monitoring',
184      'Security event tracking',
185      'System health monitoring',
186      'Structured logging'
187    ],
188    
189    limitations: [
190      'Console output only',
191      'No persistent storage of metrics'
192    ],
193    
194    dependencies: {
195      services: []
196    },
197    
198    requirements: {
199      configuration: {
200        required: [],
201        optional: ['MONITORING_ENABLED', 'MONITORING_DAILY_TOKEN_LIMIT', 'MONITORING_WARNING_THRESHOLD']
202      }
203    },
204    
205    recommendations: {
206      idealFor: [
207        'Applications requiring simple event monitoring',
208        'Development and staging environments',
209        'Security event logging'
210      ],
211      acceptableFor: [
212        'Small to medium production applications'
213      ],
214      notRecommendedFor: [
215        'High-frequency event logging requiring aggregation'
216      ]
217    },
218    
219    configurationSchema: {
220      MONITORING_ENABLED: {
221        type: 'boolean',
222        default: true,
223        description: 'Enable or disable monitoring'
224      },
225      MONITORING_DAILY_TOKEN_LIMIT: {
226        type: 'number',
227        default: 500000,
228        description: 'Daily token usage limit for warnings'
229      },
230      MONITORING_WARNING_THRESHOLD: {
231        type: 'number',
232        default: 80,
233        description: 'Warning threshold percentage of daily limit'
234      }
235    }
236  };
237
238  constructor(config: MonitoringConfig, private logger: ILogger) {
239    super();
240    this.config = config;
241    this.enabled = config.enabled;
242    
243    this.logger.debug('MonitorService initialized', {
244      enabled: this.enabled,
245      serviceName: config.serviceName,
246      dailyTokenLimit: config.tokenTracking?.dailyTokenLimit
247    });
248  }
249
250  /**
251   * Initialize the monitoring service
252   */
253  public async initialize(_config?: Record<string, any>): Promise<void> {
254    if (!this.enabled) {
255      this.logger.info('Monitoring is disabled, skipping initialization');
256      return;
257    }
258
259    try {
260      this.initialized = true;
261      this.logger.info('Monitor service initialized successfully');
262    } catch (error) {
263      this.logger.error('Failed to initialize Monitor service', error instanceof Error ? error : new Error(String(error)));
264      // Continue without monitoring but mark as initialized for logging
265      this.initialized = true;
266    }
267  }
268
269  /**
270   * Track any custom event
271   */
272  public async onEvent(eventName: string, params: any): Promise<void> {
273    if (!this.enabled) return;
274    if (!this.initialized) {
275      this.logger.warn('MonitorService is not initialized, skipping event tracking');
276      return;
277    }
278    
279    try {
280      const eventData = {
281        eventName,
282        timestamp: new Date().toISOString(),
283        environment: process.env.NODE_ENV || 'development',
284        ...params
285      };
286
287      // Log event details
288      this.logger.info(`Event: ${eventName}`, eventData);
289    } catch (error) {
290      this.logger.error('Failed to track event', error instanceof Error ? error : new Error(String(error)), {
291        eventName,
292        error: error instanceof Error ? error.message : String(error)
293      });
294    }
295  }
296
297  /**
298   * Track user events
299   */
300  public async onUserEvent(event: UserEventType, userId: string, details?: any): Promise<void> {
301    await this.onEvent(event, {
302      userId,
303      ...details,
304      category: 'User'
305    });
306  }
307
308  /**
309   * Track system events
310   */
311  public async onSystemEvent(event: SystemEventType, details: any): Promise<void> {
312    await this.onEvent(event, {
313      ...details,
314      category: 'System'
315    });
316  }
317
318  /**
319   * Track security events
320   */
321  public async onSecurityEvent(event: SecurityEventType, userId: string, details: any): Promise<void> {
322    await this.onEvent(event, {
323      userId,
324      ...details,
325      category: 'Security',
326      severity: 'Warning' // Security events are always important
327    });
328  }
329
330  /**
331   * Track AI token usage for monitoring (without cost calculation)
332   */
333  public async onCostEvent(model: string, tokens: TokenUsage, jobId: string, userId?: string): Promise<void> {
334    // Track individual usage event
335    await this.onEvent('AI.TokensUsed', {
336      model,
337      promptTokens: tokens.promptTokens,
338      completionTokens: tokens.completionTokens,
339      totalTokens: tokens.totalTokens,
340      jobId,
341      userId,
342      category: 'TokenUsage'
343    });
344
345    // Check if approaching daily limits and warn
346    await this.checkTokenLimits(tokens.totalTokens);
347  }
348
349  /**
350   * Check token usage against daily limits and send warnings
351   */
352  private async checkTokenLimits(tokensUsed: number): Promise<void> {
353    if (!this.config.tokenTracking?.dailyTokenLimit) return;
354
355    const { dailyTokenLimit, warningThresholdPercent } = this.config.tokenTracking;
356    
357    // TODO: In a real implementation, you would:
358    // 1. Get today's total token usage from database or cache
359    // 2. Calculate percentage of daily limit used
360    // 3. Send appropriate events
361    
362    // For now, just log what would happen
363    this.logger.debug('Token limit check', {
364      tokensUsed,
365      dailyLimit: dailyTokenLimit,
366      warningThreshold: warningThresholdPercent
367    });
368  }
369
370  /**
371   * Check if monitoring service is healthy
372   */
373  public async isHealthy(): Promise<boolean> {
374    try {
375      if (!this.enabled) return true; // Disabled service is considered healthy
376      
377      // Test that we can track a health check event
378      await this.onEvent('System.HealthCheck', {
379        service: 'MonitorService',
380        healthy: true
381      });
382      
383      return true;
384    } catch (error) {
385      this.logger.error('Monitor service health check failed', error instanceof Error ? error : new Error(String(error)));
386      return false;
387    }
388  }
389
390  /**
391   * Get service metadata
392   */
393  public getMetadata(): ServiceMetadata {
394    return MonitorService.metadata;
395  }
396
397  /**
398   * Gracefully shutdown the monitoring service
399   */
400  public async destroy(): Promise<void> {
401    try {
402      this.logger.info('MonitorService destroyed successfully');
403    } catch (error) {
404      this.logger.error('Error during MonitorService destruction', error instanceof Error ? error : new Error(String(error)));
405    }
406  }
407}

Metadata

Path
utaba/main/services/monitoring/MonitorService.ts
Namespace
utaba/main/services/monitoring
Author
utaba
Category
services
Technology
typescript
Contract Version
2.0.0
MIME Type
application/typescript
Published
19-Jul-2025
Last Updated
19-Jul-2025