@ahmedhegazee/nestjs-telescope
Version:
Advanced observability and monitoring solution for NestJS applications with ML-powered analytics, enterprise features, and production-ready scaling
152 lines • 5.92 kB
JavaScript
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var MetricsService_1;
Object.defineProperty(exports, "__esModule", { value: true });
exports.MetricsService = void 0;
const common_1 = require("@nestjs/common");
const rxjs_1 = require("rxjs");
const operators_1 = require("rxjs/operators");
let MetricsService = MetricsService_1 = class MetricsService {
constructor() {
this.logger = new common_1.Logger(MetricsService_1.name);
this.batchResults = new rxjs_1.Subject();
this.startTime = Date.now();
this.metrics = {
totalEntries: 0,
totalBatches: 0,
successfulBatches: 0,
failedBatches: 0,
averageProcessingTime: 0,
throughput: 0,
errorRate: 0,
uptime: 0
};
this.processingTimes = [];
this.maxProcessingTimesSamples = 1000;
this.errorCount = 0;
this.setupMetricsStream();
}
setupMetricsStream() {
this.batchResults
.pipe((0, operators_1.scan)((acc, result) => this.updateMetrics(acc, result), this.metrics), (0, operators_1.share)())
.subscribe(metrics => {
this.metrics = metrics;
this.logger.debug('Metrics updated:', metrics);
});
(0, rxjs_1.interval)(1000).pipe((0, operators_1.map)(() => Date.now() - this.startTime)).subscribe(uptime => {
this.metrics.uptime = uptime;
});
}
recordBatchProcessing(result) {
this.batchResults.next(result);
this.processingTimes.push(result.duration);
if (this.processingTimes.length > this.maxProcessingTimesSamples) {
this.processingTimes.shift();
}
if (!result.success) {
this.errorCount++;
}
}
updateMetrics(current, result) {
const totalBatches = current.totalBatches + 1;
const successfulBatches = current.successfulBatches + (result.success ? 1 : 0);
const failedBatches = current.failedBatches + (result.success ? 0 : 1);
const totalEntries = current.totalEntries + result.processed;
const averageProcessingTime = this.processingTimes.length > 0
? this.processingTimes.reduce((sum, time) => sum + time, 0) / this.processingTimes.length
: 0;
const elapsedSeconds = (Date.now() - this.startTime) / 1000;
const throughput = elapsedSeconds > 0 ? totalEntries / elapsedSeconds : 0;
const errorRate = totalBatches > 0 ? (failedBatches / totalBatches) * 100 : 0;
return {
totalEntries,
totalBatches,
successfulBatches,
failedBatches,
averageProcessingTime,
throughput,
errorRate,
uptime: current.uptime
};
}
getMetrics() {
return { ...this.metrics };
}
getStreamMetrics() {
return {
entriesInQueue: 0,
errorCount: this.errorCount,
averageProcessingTime: this.metrics.averageProcessingTime,
throughput: this.metrics.throughput,
isProcessing: true,
subscriptions: 0,
lastProcessedAt: this.processingTimes.length > 0 ? new Date() : undefined
};
}
getErrorCount() {
return this.errorCount;
}
getAverageProcessingTime() {
return this.metrics.averageProcessingTime;
}
getThroughput() {
return this.metrics.throughput;
}
getUptime() {
return this.metrics.uptime;
}
getMetricsStream() {
return this.batchResults.pipe((0, operators_1.scan)((acc, result) => this.updateMetrics(acc, result), this.metrics), (0, operators_1.startWith)(this.metrics));
}
reset() {
this.metrics = {
totalEntries: 0,
totalBatches: 0,
successfulBatches: 0,
failedBatches: 0,
averageProcessingTime: 0,
throughput: 0,
errorRate: 0,
uptime: 0
};
this.processingTimes = [];
this.errorCount = 0;
}
getPerformanceReport() {
const alerts = [];
if (this.metrics.errorRate > 5) {
alerts.push(`High error rate: ${this.metrics.errorRate.toFixed(2)}%`);
}
if (this.metrics.averageProcessingTime > 5000) {
alerts.push(`High average processing time: ${this.metrics.averageProcessingTime.toFixed(2)}ms`);
}
if (this.metrics.throughput < 10) {
alerts.push(`Low throughput: ${this.metrics.throughput.toFixed(2)} entries/second`);
}
return {
metrics: this.getMetrics(),
samples: {
processingTimes: [...this.processingTimes],
recentBatches: this.processingTimes.length
},
status: {
isHealthy: alerts.length === 0,
alerts
}
};
}
};
exports.MetricsService = MetricsService;
exports.MetricsService = MetricsService = MetricsService_1 = __decorate([
(0, common_1.Injectable)(),
__metadata("design:paramtypes", [])
], MetricsService);
//# sourceMappingURL=metrics.service.js.map