@qrvey/health-checker
Version:
 
1 lines • 25.3 kB
Source Map (JSON)
{"version":3,"sources":["../../src/registry.ts","../../src/services/gateways/systemStatusGateway.service.ts","../../src/services/cache/redisHealthChecker.service.ts","../../src/utils/logger.ts","../../src/utils/requireEnv.ts","../../src/utils/constants.ts","../../src/services/database/postgresqlHealthChecker.service.ts","../../src/services/event-broker/rabbitmqHealthChecker.service.ts","../../src/utils/checkersMap.ts","../../src/utils/withTimeout.ts","../../src/services/healthCheck.service.ts"],"names":["timestamp","closeConnection","FetchService"],"mappings":"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","sourcesContent":["import { Dependency } from './types';\n\nconst registered: Set<Dependency> = new Set();\n\nexport function registerHealthCheck(\n dependency: Dependency | Dependency[],\n): void {\n const deps = Array.isArray(dependency) ? dependency : [dependency];\n deps.forEach((d) => registered.add(d));\n}\n\nexport function getRegisteredHealthChecks(): Dependency[] {\n return Array.from(registered);\n}\n\nexport function clearRegistry(): void {\n registered.clear();\n}\n","import { FetchService } from '@qrvey/fetch';\nimport { HealthCheckResult } from '../../types';\nimport { SystemStatusGatewayPayload } from '../../interfaces/';\n\nexport class SystemStatusGateway {\n static async getHealthReport(\n body: SystemStatusGatewayPayload,\n ): Promise<HealthCheckResult> {\n const endpoint = `/api/system/v1/status`;\n const data = await FetchService.post(endpoint, body, {\n privateDomain: true,\n useApiKey: true,\n });\n\n return data as unknown as Promise<HealthCheckResult>;\n }\n}\n","import { IHealthChecker } from '../../interfaces/healthChecker.interface';\nimport { Dependency } from '../../types';\nimport { createClient, RedisClientType } from 'redis';\nimport { requireEnv } from '../../utils/requireEnv';\nimport logger from '../../utils/logger';\nimport { DEFAULT_HEALTH_CHECK_TIMEOUT } from '../../utils/constants';\n\nfunction createRedisClient(): RedisClientType {\n const redisUrl = requireEnv('REDIS_URL');\n return createClient({\n url: redisUrl,\n socket: {\n connectTimeout: DEFAULT_HEALTH_CHECK_TIMEOUT,\n },\n });\n}\n\nasync function connectAndPing(client: RedisClientType): Promise<void> {\n await client.connect();\n await client.ping();\n}\n\nasync function closeConnection(client: RedisClientType): Promise<void> {\n try {\n await client.quit();\n } catch (error) {\n logger.warn(\n '[RedisHealthChecker] Failed to close Redis connection',\n error,\n );\n }\n}\n\nexport const RedisHealthChecker: IHealthChecker = {\n dependency: 'cache' as Dependency,\n\n async check() {\n const client = createRedisClient();\n\n try {\n await connectAndPing(client);\n\n if (process.env.NODE_ENV === 'test') {\n logger.info('[RedisHealthCheck] check executed successfully');\n }\n } catch (error) {\n logger.error('[RedisHealthChecker] Connection failed', error);\n throw error;\n } finally {\n await closeConnection(client);\n }\n },\n};\n","import {\n createLogger,\n format,\n transports,\n Logger as WinstonLogger,\n} from 'winston';\n\nconst { combine, timestamp, printf, colorize } = format;\n\nconst logFormat = printf(({ level, message, timestamp }) => {\n return `${timestamp} [${level}]: ${message}`;\n});\n\nconst baseLogger: WinstonLogger = createLogger({\n level: 'info',\n format: combine(\n timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }),\n colorize(),\n logFormat,\n ),\n transports: [new transports.Console()],\n});\n\nfunction formatMessage(context: string, data?: unknown): string {\n if (!data) return context;\n\n let detail = '';\n if (data instanceof Error) {\n detail = data.stack || data.message;\n } else if (typeof data === 'object') {\n try {\n detail = JSON.stringify(data);\n } catch {\n detail = '[Unserializable object]';\n }\n } else {\n detail = String(data);\n }\n\n return `${context} ${detail}`;\n}\n\nconst logger = {\n info: (msg: string, data?: unknown) =>\n baseLogger.info(formatMessage(msg, data)),\n warn: (msg: string, data?: unknown) =>\n baseLogger.warn(formatMessage(msg, data)),\n error: (msg: string, data?: unknown) =>\n baseLogger.error(formatMessage(msg, data)),\n debug: (msg: string, data?: unknown) =>\n baseLogger.debug(formatMessage(msg, data)),\n};\n\nexport default logger;\n","import logger from '../utils/logger';\n\nexport function requireEnv(varName: string): string {\n const value = process.env[varName];\n if (!value) {\n logger.error(`[HealthCheck] Missing env variable: ${varName}`);\n throw new Error(\n `[HealthCheck] Missing required environment variable: ${varName}`,\n );\n }\n return value;\n}\n","import { HealthStatus } from '../types';\n\nexport const DEFAULT_HEALTH_CHECK_TIMEOUT = 5_000;\n\nexport const OK: HealthStatus = 'OK';\nexport const FAILED: HealthStatus = 'FAILED';\nexport const DEFAULT_HEALTH_STATUS = OK;\n\nexport const SYSTEM_STATUS_GATEWAY_CONTEXT = 'system_status_gateway';\n","import { IHealthChecker } from '../../interfaces/healthChecker.interface';\nimport { Dependency } from '../../types';\nimport { requireEnv } from '../../utils/requireEnv';\nimport { Client } from 'pg';\nimport logger from '../../utils/logger';\n\nconst PG_ENV_VAR = 'MULTIPLATFORM_PG_CONNECTION_STRING';\n\nasync function connectAndQuery(client: Client): Promise<void> {\n await client.connect();\n await client.query('SELECT 1');\n}\n\nasync function closeConnection(client: Client): Promise<void> {\n try {\n await client.end();\n } catch (error) {\n logger.warn(\n '[PostgreSQLHealthChecker] Failed to close connection',\n error,\n );\n }\n}\n\nexport const PostgreSQLHealthChecker: IHealthChecker = {\n dependency: 'database' as Dependency,\n\n async check() {\n const connectionString = requireEnv(PG_ENV_VAR);\n const client = new Client({ connectionString });\n\n try {\n await connectAndQuery(client);\n\n if (process.env.NODE_ENV === 'test') {\n logger.info(\n '[PostgreSQLHealthChecker] check executed successfully',\n );\n }\n } catch (error) {\n logger.error(\n '[PostgreSQLHealthChecker] Failed to connect or query',\n error,\n );\n throw error;\n } finally {\n await closeConnection(client);\n }\n },\n};\n","/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport { IHealthChecker } from '../../interfaces/healthChecker.interface';\nimport { Dependency, EventBrokerHealthCheckerResult } from '../../types';\nimport { requireEnv } from '../../utils/requireEnv';\nimport logger from '../../utils/logger';\nimport { IEventBrokerParams } from '../../interfaces';\nimport { FetchService } from '@qrvey/fetch';\nimport { OK } from '../../utils/constants';\n\nfunction getRabbitCredentials() {\n const user = requireEnv('RABBITMQ_USER');\n const pass = requireEnv('RABBITMQ_PASSWORD');\n return { user, pass };\n}\n\nexport function getRabbitHttpHost(): string {\n const raw = requireEnv('RABBITMQ_HTTP_HOST');\n const url = new URL(raw);\n const basePath = url.pathname.replace(/\\/$/, '');\n return `${url.protocol}//${url.host}${basePath}`;\n}\n\nfunction buildRabbitHttpConfig() {\n const { user, pass } = getRabbitCredentials();\n const basicAuth = Buffer.from(`${user}:${pass}`).toString('base64');\n const authHeader = `Basic ${basicAuth}`;\n\n return {\n baseDomain: getRabbitHttpHost(),\n authHeader,\n };\n}\n\nasync function ping(): Promise<void> {\n const { baseDomain, authHeader } = buildRabbitHttpConfig();\n const res = await fetch(`${baseDomain}/api/overview`, {\n headers: { Authorization: authHeader },\n });\n\n if (!res.ok) {\n throw new Error(\n `[RabbitMQHealthChecker] Management API ping failed: ${res.statusText}`,\n );\n }\n}\n\nfunction listConsumers(): Promise<any> {\n const { baseDomain, authHeader } = buildRabbitHttpConfig();\n return FetchService.get('/api/consumers', {\n baseDomain,\n headers: { Authorization: authHeader },\n });\n}\n\nasync function getConsumersSet(): Promise<Set<string>> {\n return new Set(\n (await listConsumers()).map(\n (c: any) => `${c?.consumer_tag ?? ''}::${c?.queue?.name ?? ''}`,\n ),\n );\n}\n\nasync function validateQueues(\n queues: string[],\n consumerTag: string,\n consumersSet: Set<string>,\n): Promise<void> {\n const missingQueues = queues.filter(\n (queue) => !consumersSet.has(`${consumerTag}::${queue}`),\n );\n\n if (missingQueues.length > 0) {\n throw new Error(\n `[RabbitMQHealthChecker] Missing subscriptions for queues: ${missingQueues.join(\n ', ',\n )} for consumerTag ${consumerTag}`,\n );\n }\n}\n\nasync function handleConsumersCheck(\n param: IEventBrokerParams | undefined,\n metadata: EventBrokerHealthCheckerResult['metadata'],\n): Promise<void> {\n const shouldLoadConsumers =\n param?.queues?.length || param?.returnConsumersSet;\n\n if (!shouldLoadConsumers) return;\n\n const consumersSet = param?.consumersSet ?? (await getConsumersSet());\n\n if (param?.queues?.length) {\n const consumerTag = param.hostName ?? requireEnv('HOSTNAME');\n await validateQueues(param.queues, consumerTag, consumersSet);\n }\n\n if (param?.returnConsumersSet) {\n metadata.consumersSet = consumersSet;\n }\n}\n\nasync function performCheck(\n param?: IEventBrokerParams,\n): Promise<EventBrokerHealthCheckerResult> {\n const metadata: EventBrokerHealthCheckerResult['metadata'] = {};\n\n if (!param?.omitPing) await ping();\n\n await handleConsumersCheck(param, metadata);\n\n if (process.env.NODE_ENV === 'test') {\n logger.info('[RabbitMQHealthChecker] check executed successfully');\n }\n\n return { status: OK, metadata };\n}\n\nexport const RabbitMQHealthChecker: IHealthChecker<EventBrokerHealthCheckerResult> =\n {\n dependency: 'eventBroker' as Dependency,\n\n async check(\n param?: IEventBrokerParams,\n ): Promise<EventBrokerHealthCheckerResult> {\n try {\n return await performCheck(param);\n } catch (error) {\n logger.error(\n '[RabbitMQHealthChecker] Health check failed',\n error,\n );\n throw error;\n }\n },\n };\n","import { CacheHealthChecker } from '../services/cache';\nimport { DatabaseHealthChecker } from '../services/database';\nimport { EventBrokerHealthChecker } from '../services/event-broker';\nimport { CheckerRegistry } from '../types';\n\nexport const checkersMap: CheckerRegistry = {\n cache: CacheHealthChecker,\n database: DatabaseHealthChecker,\n eventBroker: EventBrokerHealthChecker,\n};\n","import { DEFAULT_HEALTH_CHECK_TIMEOUT } from './constants';\nimport logger from './logger';\n\nexport function withTimeout<T>(\n context: string,\n healthCheckFn: Promise<T>,\n ms: number = DEFAULT_HEALTH_CHECK_TIMEOUT,\n): Promise<T> {\n return new Promise((resolve, reject) => {\n const timeoutId = setTimeout(() => {\n const message = `[${context}] HealthChecker timeout after ${ms}ms`;\n logger.error(message);\n reject(new Error(message));\n }, ms);\n\n healthCheckFn\n .then((value) => {\n clearTimeout(timeoutId);\n resolve(value);\n })\n .catch((error) => {\n clearTimeout(timeoutId);\n reject(error);\n });\n });\n}\n\nexport async function withTimeoutAndTiming(\n context: string,\n healthCheckPromise: Promise<void | { metadata?: Record<string, unknown> }>,\n ms: number = DEFAULT_HEALTH_CHECK_TIMEOUT,\n): Promise<{ durationMs: number; metadata?: Record<string, unknown> }> {\n const start = Date.now();\n const result = await withTimeout(context, healthCheckPromise, ms);\n const durationMs = Date.now() - start;\n\n const maybeMetadata = (result as any)?.metadata;\n return {\n durationMs,\n metadata: typeof maybeMetadata === 'object' ? maybeMetadata : undefined,\n };\n}\n","import { getRegisteredHealthChecks } from '../registry';\nimport {\n Dependency,\n DependencyHealthCheckerParams,\n HealthCheckerParams,\n HealthCheckResult,\n DependencyHealthDetail,\n} from '../types';\nimport { SystemStatusGatewayPayload } from '../interfaces';\n\nimport { SystemStatusGateway } from './gateways/systemStatusGateway.service';\nimport { checkersMap } from '../utils/checkersMap';\nimport { OK, FAILED, SYSTEM_STATUS_GATEWAY_CONTEXT } from '../utils/constants';\nimport logger from '../utils/logger';\nimport { withTimeout, withTimeoutAndTiming } from '../utils/withTimeout';\n\nexport class HealthCheckService {\n static async check(\n dependencies: Dependency[],\n params: HealthCheckerParams = {},\n ): Promise<HealthCheckResult> {\n const selectedDependencies = resolveDependencies(dependencies);\n if (!params.force) {\n const result = await tryFetchRemoteHealthReport(\n selectedDependencies,\n params,\n );\n if (result) return result;\n }\n\n const results = await runDependencyChecks(selectedDependencies, params);\n return buildDetails(selectedDependencies, results);\n }\n}\n\nfunction resolveDependencies(\n dependencies?: Dependency[],\n skip?: string[],\n): Dependency[] {\n const all = dependencies ?? getRegisteredHealthChecks();\n return skip ? all.filter((dep) => !skip.includes(dep)) : all;\n}\n\nasync function runDependencyChecks(\n dependencies: Dependency[],\n params: HealthCheckerParams = {},\n): Promise<\n PromiseSettledResult<{\n durationMs?: number;\n metadata?: Record<string, unknown>;\n }>[]\n> {\n return Promise.allSettled(\n dependencies.map(async (dep) => {\n const checker = checkersMap[dep];\n if (!checker) {\n const msg = `[HealthCheckService] No checker found for dependency \"${dep}\"`;\n logger.error(msg);\n return Promise.reject(new Error(msg));\n }\n\n const depParams = params as Partial<\n Record<Dependency, DependencyHealthCheckerParams>\n >;\n const dependencyParam = depParams[dep] ?? {};\n\n const mergedParam: DependencyHealthCheckerParams = {\n ...dependencyParam,\n hostName: params.hostName,\n };\n\n try {\n return await withTimeoutAndTiming(\n dep,\n checker.check(mergedParam),\n );\n } catch (err) {\n logger.error(`[${dep}] HealthChecker threw an error`, err);\n return Promise.reject(err);\n }\n }),\n );\n}\n\nasync function tryFetchRemoteHealthReport(\n dependencies: Dependency[],\n params: HealthCheckerParams,\n): Promise<HealthCheckResult | null> {\n try {\n const { skip = [], force = false, eventBroker = {}, hostName } = params;\n\n const body: SystemStatusGatewayPayload = {\n dependencies,\n service: hostName ?? (process.env.HOSTNAME || 'unknown'),\n skip,\n force,\n params: {\n eventBroker,\n },\n };\n\n const result = await withTimeout(\n SYSTEM_STATUS_GATEWAY_CONTEXT,\n SystemStatusGateway.getHealthReport(body),\n );\n return result;\n } catch (err) {\n const message =\n err instanceof Error\n ? err.message\n : 'Unknown error during remote check';\n logger.warn(\n `[HealthCheckService] Remote health check fallback triggered: ${message}`,\n );\n return null;\n }\n}\n\nexport function buildDetails(\n dependencies: Dependency[],\n results: PromiseSettledResult<{\n durationMs?: number;\n metadata?: Record<string, unknown>;\n }>[],\n): HealthCheckResult {\n const details = {} as Record<Dependency, DependencyHealthDetail>;\n let hasFailure = false;\n\n for (let i = 0; i < dependencies.length; i++) {\n const dep = dependencies[i];\n const result = results[i];\n\n if (result.status === 'fulfilled') {\n details[dep] = {\n status: OK,\n durationMs: result.value.durationMs,\n metadata: result.value.metadata ?? {},\n };\n } else {\n details[dep] = {\n status: FAILED,\n durationMs: result.reason?.durationMs ?? 0,\n };\n hasFailure = true;\n }\n }\n\n return {\n status: hasFailure ? FAILED : OK,\n details,\n };\n}\n"]}