@ahmedhegazee/nestjs-telescope
Version:
Advanced observability and monitoring solution for NestJS applications with ML-powered analytics, enterprise features, and production-ready scaling
305 lines • 13 kB
JavaScript
;
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 __param = (this && this.__param) || function (paramIndex, decorator) {
return function (target, key) { decorator(target, key, paramIndex); }
};
var HealthController_1;
Object.defineProperty(exports, "__esModule", { value: true });
exports.HealthController = void 0;
const common_1 = require("@nestjs/common");
const swagger_1 = require("@nestjs/swagger");
const telescope_service_1 = require("../services/telescope.service");
const metrics_service_1 = require("../services/metrics.service");
const resilient_bridge_service_1 = require("../../devtools/bridge/resilient-bridge.service");
let HealthController = HealthController_1 = class HealthController {
constructor(telescopeService, metricsService, resilientBridge, config) {
this.telescopeService = telescopeService;
this.metricsService = metricsService;
this.resilientBridge = resilientBridge;
this.config = config;
this.logger = new common_1.Logger(HealthController_1.name);
this.startTime = Date.now();
}
async getHealth() {
const timestamp = new Date();
const uptime = Date.now() - this.startTime;
try {
const telescopeHealth = await this.checkTelescopeHealth();
const metricsHealth = await this.checkMetricsHealth();
const bridgeHealth = await this.checkBridgeHealth();
const storageHealth = await this.checkStorageHealth();
const metrics = this.metricsService.getMetrics();
const bridgeMetrics = this.resilientBridge.getStreamMetrics();
const circuitBreakers = this.resilientBridge.getCircuitBreakerStatus();
const services = {
telescope: telescopeHealth,
metrics: metricsHealth,
bridge: bridgeHealth,
storage: storageHealth
};
const overallStatus = this.determineOverallStatus(services);
return {
status: overallStatus,
timestamp,
uptime,
version: process.env.npm_package_version || '1.0.0',
services,
metrics: {
totalEntries: metrics.totalEntries,
errorRate: metrics.errorRate,
averageProcessingTime: metrics.averageProcessingTime,
throughput: metrics.throughput
},
circuitBreakers
};
}
catch (error) {
this.logger.error('Health check failed:', error);
return {
status: 'unhealthy',
timestamp,
uptime,
version: process.env.npm_package_version || '1.0.0',
services: {
telescope: { status: 'unhealthy', message: 'Health check failed', lastChecked: timestamp },
metrics: { status: 'unhealthy', message: 'Health check failed', lastChecked: timestamp },
bridge: { status: 'unhealthy', message: 'Health check failed', lastChecked: timestamp },
storage: { status: 'unhealthy', message: 'Health check failed', lastChecked: timestamp }
},
metrics: {
totalEntries: 0,
errorRate: 100,
averageProcessingTime: 0,
throughput: 0
}
};
}
}
async getDetailedHealth() {
const basicHealth = await this.getHealth();
const comprehensiveStatus = this.resilientBridge.getComprehensiveStatus();
const performanceReport = this.metricsService.getPerformanceReport();
return {
...basicHealth,
diagnostics: {
bridge: comprehensiveStatus.bridge,
circuitBreakers: comprehensiveStatus.circuitBreakers,
streamMetrics: comprehensiveStatus.streamMetrics,
configuration: comprehensiveStatus.configuration,
performanceReport
}
};
}
async getMetrics() {
const metrics = this.metricsService.getMetrics();
const streamMetrics = this.resilientBridge.getStreamMetrics();
const performanceReport = this.metricsService.getPerformanceReport();
return {
timestamp: new Date(),
uptime: Date.now() - this.startTime,
metrics,
streamMetrics,
performanceReport
};
}
async getCircuitBreakers() {
const circuitBreakers = this.resilientBridge.getCircuitBreakerStatus();
const bridgeHealth = this.resilientBridge.getHealthStatus();
return {
timestamp: new Date(),
circuitBreakers,
bridgeHealth
};
}
async checkTelescopeHealth() {
try {
const isEnabled = this.config.enabled;
const watchers = this.config.watchers || {};
const activeWatchers = Object.keys(watchers).filter(key => {
const watcher = watchers[key];
return typeof watcher === 'boolean' ? watcher : watcher?.enabled === true;
});
if (!isEnabled) {
return {
status: 'degraded',
message: 'Telescope is disabled',
lastChecked: new Date()
};
}
return {
status: 'healthy',
message: `${activeWatchers.length} watchers active`,
details: { activeWatchers },
lastChecked: new Date()
};
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
return {
status: 'unhealthy',
message: `Telescope check failed: ${errorMessage}`,
lastChecked: new Date()
};
}
}
async checkMetricsHealth() {
try {
const metrics = this.metricsService.getMetrics();
const performanceReport = this.metricsService.getPerformanceReport();
if (!performanceReport.status.isHealthy) {
return {
status: 'degraded',
message: 'Performance issues detected',
details: { alerts: performanceReport.status.alerts },
lastChecked: new Date()
};
}
return {
status: 'healthy',
message: `${metrics.totalEntries} entries processed`,
details: {
errorRate: metrics.errorRate.toFixed(2),
throughput: metrics.throughput.toFixed(2)
},
lastChecked: new Date()
};
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
return {
status: 'unhealthy',
message: `Metrics check failed: ${errorMessage}`,
lastChecked: new Date()
};
}
}
async checkBridgeHealth() {
try {
const bridgeHealth = this.resilientBridge.getHealthStatus();
if (!bridgeHealth.isHealthy) {
return {
status: 'degraded',
message: 'Bridge issues detected',
details: { issues: bridgeHealth.issues },
lastChecked: new Date()
};
}
return {
status: 'healthy',
message: 'Bridge operating normally',
details: {
circuitBreakers: Object.keys(bridgeHealth.circuitBreakers).length,
lastHealthCheck: bridgeHealth.lastHealthCheckAt
},
lastChecked: new Date()
};
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
return {
status: 'unhealthy',
message: `Bridge check failed: ${errorMessage}`,
lastChecked: new Date()
};
}
}
async checkStorageHealth() {
try {
const storageConfig = this.config.storage;
if (!storageConfig) {
return {
status: 'unhealthy',
message: 'Storage not configured',
lastChecked: new Date()
};
}
const circuitBreakers = this.resilientBridge.getCircuitBreakerStatus();
const storageBreaker = circuitBreakers.storage;
if (storageBreaker && storageBreaker.state === 'open') {
return {
status: 'unhealthy',
message: 'Storage circuit breaker open',
details: { circuitBreaker: storageBreaker },
lastChecked: new Date()
};
}
return {
status: 'healthy',
message: `Storage driver: ${storageConfig.driver}`,
details: {
driver: storageConfig.driver,
batchEnabled: storageConfig.batch?.enabled || false
},
lastChecked: new Date()
};
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
return {
status: 'unhealthy',
message: `Storage check failed: ${errorMessage}`,
lastChecked: new Date()
};
}
}
determineOverallStatus(services) {
const statuses = Object.values(services).map(service => service.status);
if (statuses.includes('unhealthy')) {
return 'unhealthy';
}
if (statuses.includes('degraded')) {
return 'degraded';
}
return 'healthy';
}
};
exports.HealthController = HealthController;
__decorate([
(0, common_1.Get)(),
(0, swagger_1.ApiOperation)({ summary: 'Get overall health status' }),
(0, swagger_1.ApiResponse)({ status: 200, description: 'Health check successful' }),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", Promise)
], HealthController.prototype, "getHealth", null);
__decorate([
(0, common_1.Get)('detailed'),
(0, swagger_1.ApiOperation)({ summary: 'Get detailed health status with full diagnostics' }),
(0, swagger_1.ApiResponse)({ status: 200, description: 'Detailed health check successful' }),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", Promise)
], HealthController.prototype, "getDetailedHealth", null);
__decorate([
(0, common_1.Get)('metrics'),
(0, swagger_1.ApiOperation)({ summary: 'Get performance metrics' }),
(0, swagger_1.ApiResponse)({ status: 200, description: 'Metrics retrieved successfully' }),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", Promise)
], HealthController.prototype, "getMetrics", null);
__decorate([
(0, common_1.Get)('circuit-breakers'),
(0, swagger_1.ApiOperation)({ summary: 'Get circuit breaker status' }),
(0, swagger_1.ApiResponse)({ status: 200, description: 'Circuit breaker status retrieved successfully' }),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", Promise)
], HealthController.prototype, "getCircuitBreakers", null);
exports.HealthController = HealthController = HealthController_1 = __decorate([
(0, swagger_1.ApiTags)('Health'),
(0, common_1.Controller)('telescope/health'),
__param(3, (0, common_1.Inject)('TELESCOPE_CONFIG')),
__metadata("design:paramtypes", [telescope_service_1.TelescopeService,
metrics_service_1.MetricsService,
resilient_bridge_service_1.ResilientBridgeService, Object])
], HealthController);
//# sourceMappingURL=health.controller.js.map