@texagon/nestjs-health
Version:
A comprehensive health monitoring package for NestJS applications with metrics and Kubernetes-ready health checks
101 lines (83 loc) • 3 kB
text/typescript
import { Injectable, Logger } from "@nestjs/common";
import {
HealthCheckError,
HealthIndicator,
HealthIndicatorResult,
} from "@nestjs/terminus";
import * as os from "os";
interface SystemHealth {
memoryHealthy: boolean;
diskHealthy: boolean;
cpuHealthy: boolean;
serviceHealthy: boolean;
}
()
export class HealthService extends HealthIndicator {
private readonly logger = new Logger(HealthService.name);
private isShuttingDown = false;
// Thresholds for health checks
private readonly memoryThreshold = 0.9; // 90% memory usage is considered unhealthy
private readonly cpuThreshold = 0.95; // 95% CPU usage is considered unhealthy
private readonly uptimeMinThreshold = 10; // System should be up for at least 10 seconds
constructor() {
super();
process.on("SIGTERM", () => {
this.logger.log(
"SIGTERM received, marking service as unhealthy for graceful shutdown",
);
this.isShuttingDown = true;
});
}
async isHealthy(): Promise<HealthIndicatorResult> {
// Check multiple aspects of system health
const health = await this.checkSystemHealth();
// Only consider unhealthy if service is shutting down or multiple checks fail
const isHealthy =
health.serviceHealthy && (health.memoryHealthy || health.cpuHealthy);
const result = this.getStatus("service", isHealthy, {
version: process.env.npm_package_version || "0.0.1",
timestamp: new Date().toISOString(),
memoryHealthy: health.memoryHealthy,
cpuHealthy: health.cpuHealthy,
diskHealthy: health.diskHealthy,
});
if (isHealthy) {
return result;
}
throw new HealthCheckError("Health check failed", result);
}
/**
* Performs multiple health checks on the system
*/
private async checkSystemHealth(): Promise<SystemHealth> {
// Check if service is in shutdown state
const serviceHealthy = !this.isShuttingDown;
// Check memory usage
const memoryUsage = process.memoryUsage();
const totalMemory = os.totalmem();
const memoryHealthy = memoryUsage.rss / totalMemory < this.memoryThreshold;
// Check CPU load
const cpuLoad = os.loadavg()[0] / os.cpus().length;
const cpuHealthy = cpuLoad < this.cpuThreshold;
// For now, assume disk is healthy (we don't have direct disk checks here)
const diskHealthy = true;
return {
memoryHealthy,
cpuHealthy,
diskHealthy,
serviceHealthy,
};
}
async checkDependencies(): Promise<HealthIndicatorResult> {
const isHealthy = true;
return this.getStatus("dependencies", isHealthy);
}
async getMemoryStats(): Promise<HealthIndicatorResult> {
const memoryUsage = process.memoryUsage();
return this.getStatus("memory", true, {
heapUsed: Math.round(memoryUsage.heapUsed / 1024 / 1024) + "MB",
heapTotal: Math.round(memoryUsage.heapTotal / 1024 / 1024) + "MB",
rss: Math.round(memoryUsage.rss / 1024 / 1024) + "MB",
});
}
}