@ahmedhegazee/nestjs-telescope
Version:
Advanced observability and monitoring solution for NestJS applications with ML-powered analytics, enterprise features, and production-ready scaling
187 lines (186 loc) • 5.25 kB
TypeScript
import { OnModuleInit, OnModuleDestroy } from '@nestjs/common';
import { TelescopeService } from '../../core/services/telescope.service';
import { JobWatcherConfig } from './job-watcher.config';
import { Observable } from 'rxjs';
export interface JobContext {
id: string;
jobId: string;
queueName: string;
jobName: string;
timestamp: Date;
status: JobStatus;
priority: number;
data?: any;
options?: any;
result?: any;
error?: any;
startTime?: Date;
endTime?: Date;
duration?: number;
attempts: number;
maxAttempts: number;
delay?: number;
progress?: number;
progressData?: any;
performance?: {
cpuUsage?: number;
memoryUsage?: number;
executionTime?: number;
queueWaitTime?: number;
};
traceId?: string;
requestId?: string;
userId?: string;
sessionId?: string;
workerId?: string;
workerName?: string;
queueStats?: {
waiting: number;
active: number;
completed: number;
failed: number;
delayed: number;
paused: number;
};
}
export declare enum JobStatus {
WAITING = "waiting",
ACTIVE = "active",
COMPLETED = "completed",
FAILED = "failed",
DELAYED = "delayed",
PAUSED = "paused",
STALLED = "stalled",
CANCELLED = "cancelled"
}
export interface JobMetrics {
totalJobs: number;
completedJobs: number;
failedJobs: number;
activeJobs: number;
waitingJobs: number;
delayedJobs: number;
stalledJobs: number;
averageExecutionTime: number;
averageWaitTime: number;
slowJobs: number;
jobsPerMinute: number;
jobsPerHour: number;
failureRate: number;
throughput: number;
queuesByStatus: Record<string, number>;
queuesByType: Record<string, number>;
activeWorkers: number;
busyWorkers: number;
idleWorkers: number;
topFailedJobs: Array<{
jobName: string;
queueName: string;
failureCount: number;
lastFailure: Date;
avgExecutionTime: number;
}>;
topSlowJobs: Array<{
jobName: string;
queueName: string;
avgExecutionTime: number;
executionCount: number;
lastExecution: Date;
}>;
healthScore: number;
healthStatus: 'healthy' | 'warning' | 'critical';
trends: {
lastHour: JobTrendData;
lastDay: JobTrendData;
lastWeek: JobTrendData;
};
}
export interface JobTrendData {
totalJobs: number;
completedJobs: number;
failedJobs: number;
averageExecutionTime: number;
change: number;
changePercent: number;
peak: number;
}
export interface JobAlert {
id: string;
type: 'failure_rate' | 'slow_jobs' | 'queue_size' | 'stalled_jobs' | 'worker_health';
severity: 'low' | 'medium' | 'high' | 'critical';
message: string;
timestamp: Date;
data: any;
acknowledged: boolean;
resolvedAt?: Date;
queueName?: string;
jobName?: string;
}
export interface QueueHealth {
queueName: string;
status: 'healthy' | 'warning' | 'critical';
score: number;
issues: string[];
recommendations: string[];
metrics: {
totalJobs: number;
processingRate: number;
failureRate: number;
averageWaitTime: number;
stalledJobs: number;
};
}
export declare class JobWatcherService implements OnModuleInit, OnModuleDestroy {
private readonly telescopeService;
private readonly logger;
private readonly config;
private readonly destroy$;
private readonly metricsSubject;
private readonly alertsSubject;
private readonly jobContextSubject;
private jobHistory;
private queueMetrics;
private workerMetrics;
private activeJobs;
private currentMetrics;
private alertHistory;
private executionTimes;
private waitTimes;
private failureHistory;
constructor(telescopeService: TelescopeService, jobWatcherConfig: JobWatcherConfig);
onModuleInit(): Promise<void>;
onModuleDestroy(): void;
private initializeMetrics;
private initializeTrendData;
trackJob(context: JobContext): void;
private shouldExcludeJob;
private addToHistory;
private updateActiveJobs;
private updateMetrics;
private trackFailure;
private calculateAverage;
private updateRates;
private updateTopJobs;
private updateHealthScore;
private createTelescopeEntry;
private sanitizeJobData;
private generateTags;
private checkAlerts;
private createAlert;
private correlateJob;
private startPeriodicProcessing;
private updateTrends;
private calculateTrend;
private cleanupOldData;
getMetrics(): JobMetrics;
getMetricsStream(): Observable<JobMetrics>;
getAlertsStream(): Observable<JobAlert>;
getJobStream(): Observable<JobContext>;
getRecentJobs(limit?: number): JobContext[];
getJobsByQueue(queueName: string, limit?: number): JobContext[];
getJobsByStatus(status: JobStatus, limit?: number): JobContext[];
getQueueHealth(queueName?: string): QueueHealth | QueueHealth[];
private calculateQueueHealth;
acknowledgeAlert(alertId: string): boolean;
getConfig(): JobWatcherConfig;
}