@adalo/metrics 0.0.0-staging.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +14 -0
- package/.eslintignore +3 -0
- package/.eslintrc +61 -0
- package/.github/pull_request_template.md +14 -0
- package/.github/workflows/code-style.yml +29 -0
- package/.github/workflows/deploy-staging.yml +34 -0
- package/.github/workflows/deploy.yml +29 -0
- package/.github/workflows/tests.yml +17 -0
- package/.idea/codeStyles/Project.xml +101 -0
- package/.idea/codeStyles/codeStyleConfig.xml +5 -0
- package/.idea/git_toolbox_prj.xml +15 -0
- package/.idea/inspectionProfiles/Project_Default.xml +6 -0
- package/.idea/jsLibraryMappings.xml +6 -0
- package/.idea/prettier.xml +6 -0
- package/.idea/vcs.xml +6 -0
- package/.prettierrc +10 -0
- package/README-health.md +234 -0
- package/README.md +120 -0
- package/__tests__/metricsRedisClient.test.js +138 -0
- package/babel.config.js +20 -0
- package/lib/health/databaseChecker.d.ts +43 -0
- package/lib/health/databaseChecker.d.ts.map +1 -0
- package/lib/health/databaseChecker.js +189 -0
- package/lib/health/databaseChecker.js.map +1 -0
- package/lib/health/healthCheckCache.d.ts +59 -0
- package/lib/health/healthCheckCache.d.ts.map +1 -0
- package/lib/health/healthCheckCache.js +187 -0
- package/lib/health/healthCheckCache.js.map +1 -0
- package/lib/health/healthCheckClient.d.ts +124 -0
- package/lib/health/healthCheckClient.d.ts.map +1 -0
- package/lib/health/healthCheckClient.js +324 -0
- package/lib/health/healthCheckClient.js.map +1 -0
- package/lib/health/healthCheckUtils.d.ts +52 -0
- package/lib/health/healthCheckUtils.d.ts.map +1 -0
- package/lib/health/healthCheckUtils.js +129 -0
- package/lib/health/healthCheckUtils.js.map +1 -0
- package/lib/health/healthCheckWorker.d.ts +2 -0
- package/lib/health/healthCheckWorker.d.ts.map +1 -0
- package/lib/health/healthCheckWorker.js +70 -0
- package/lib/health/healthCheckWorker.js.map +1 -0
- package/lib/index.d.ts +10 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +105 -0
- package/lib/index.js.map +1 -0
- package/lib/metrics/baseMetricsClient.d.ts +174 -0
- package/lib/metrics/baseMetricsClient.d.ts.map +1 -0
- package/lib/metrics/baseMetricsClient.js +428 -0
- package/lib/metrics/baseMetricsClient.js.map +1 -0
- package/lib/metrics/metricsClient.d.ts +95 -0
- package/lib/metrics/metricsClient.d.ts.map +1 -0
- package/lib/metrics/metricsClient.js +239 -0
- package/lib/metrics/metricsClient.js.map +1 -0
- package/lib/metrics/metricsDatabaseClient.d.ts +74 -0
- package/lib/metrics/metricsDatabaseClient.d.ts.map +1 -0
- package/lib/metrics/metricsDatabaseClient.js +218 -0
- package/lib/metrics/metricsDatabaseClient.js.map +1 -0
- package/lib/metrics/metricsQueueRedisClient.d.ts +57 -0
- package/lib/metrics/metricsQueueRedisClient.d.ts.map +1 -0
- package/lib/metrics/metricsQueueRedisClient.js +277 -0
- package/lib/metrics/metricsQueueRedisClient.js.map +1 -0
- package/lib/metrics/metricsRedisClient.d.ts +71 -0
- package/lib/metrics/metricsRedisClient.d.ts.map +1 -0
- package/lib/metrics/metricsRedisClient.js +370 -0
- package/lib/metrics/metricsRedisClient.js.map +1 -0
- package/lib/redisUtils.d.ts +53 -0
- package/lib/redisUtils.d.ts.map +1 -0
- package/lib/redisUtils.js +140 -0
- package/lib/redisUtils.js.map +1 -0
- package/package.json +66 -0
- package/scripts/README.md +43 -0
- package/scripts/clearMetrics.js +6 -0
- package/src/health/databaseChecker.js +183 -0
- package/src/health/healthCheckCache.js +216 -0
- package/src/health/healthCheckClient.js +347 -0
- package/src/health/healthCheckUtils.js +125 -0
- package/src/health/healthCheckWorker.js +71 -0
- package/src/index.ts +9 -0
- package/src/metrics/baseMetricsClient.js +494 -0
- package/src/metrics/metricsClient.js +284 -0
- package/src/metrics/metricsDatabaseClient.js +236 -0
- package/src/metrics/metricsQueueRedisClient.js +352 -0
- package/src/metrics/metricsRedisClient.js +417 -0
- package/src/redisUtils.js +155 -0
- package/tsconfig.json +19 -0
- package/tsconfig.types.json +11 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"healthCheckClient.js","names":["createDatabasePool","runHealthCheck","closePool","require","getRedisClientType","REDIS_V4","IOREDIS","REDIS_V3","HealthCheckCache","readNumberEnv","name","raw","process","env","undefined","num","Number","isFinite","DEFAULT_HEALTH_CONFIG","checkIntervalMs","staleThresholdMs","checkTimeoutMs","maxDbConnectLatencyMs","SENSITIVE_PATTERNS","pattern","replacement","maskSensitiveData","text","masked","replace","HealthCheckClient","constructor","options","healthConfig","config","appName","BUILD_APP_NAME","prefixLogs","_refreshPromise","_databasePools","Map","_resources","resources","redisClient","_getRedisClientForCache","_redisClientType","_cache","cacheKey","_getEnv","resource","redisResource","find","r","client","_getPool","url","has","pool","type","set","get","_checkDatabase","status","error","timings","maxConnect","connectMs","err","healthCheckTimings","message","_checkRedis","pong","Promise","resolve","reject","ping","result","_performHealthCheckInternal","sortedResources","Object","keys","sort","reduce","acc","key","hasError","values","some","lastCheckAt","Date","now","isStale","_formatResult","cached","performHealthCheck","then","catch","getCachedResult","console","refreshCache","clearCache","healthHandler","req","res","json","statusCode","cleanup","clear","module","exports"],"sources":["../../src/health/healthCheckClient.js"],"sourcesContent":["const {\n createDatabasePool,\n runHealthCheck,\n closePool,\n} = require('./databaseChecker')\nconst {\n getRedisClientType,\n REDIS_V4,\n IOREDIS,\n REDIS_V3,\n} = require('../redisUtils')\nconst { HealthCheckCache } = require('./healthCheckCache')\n\n/**\n * @param {string} name\n * @returns {number | undefined}\n */\nfunction readNumberEnv(name) {\n const raw = process.env[name]\n if (raw == null || raw === '') return undefined\n const num = Number(raw)\n return Number.isFinite(num) ? num : undefined\n}\n\n/** @type {{ checkIntervalMs: number, staleThresholdMs: number, checkTimeoutMs: number, maxDbConnectLatencyMs: number }} */\nconst DEFAULT_HEALTH_CONFIG = {\n checkIntervalMs: 30_000,\n staleThresholdMs: 180_000,\n checkTimeoutMs: 15_000,\n maxDbConnectLatencyMs:\n readNumberEnv('HEALTH_DB_MAX_CONNECT_LATENCY_MS') ?? 1000,\n}\n\nconst SENSITIVE_PATTERNS = [\n {\n pattern:\n /(postgres(?:ql)?|mysql|mongodb|redis|amqp):\\/\\/([^:]+):([^@]+)@([^:/]+)(:\\d+)?\\/([^\\s?]+)/gi,\n replacement: '$1://***:***@***$5/***',\n },\n {\n pattern: /(\\w+):\\/\\/([^:]+):([^@]+)@([^\\s/]+)/gi,\n replacement: '$1://***:***@***',\n },\n {\n pattern:\n /(password|passwd|pwd|secret|token|api[_-]?key|auth[_-]?token)[\"\\s]*[:=][\"\\s]*([^\\s,}\"]+)/gi,\n replacement: '$1=***',\n },\n {\n pattern:\n /(database|table|schema|role|user|relation|column|index)\\s*[\"']([^\"']+)[\"']/gi,\n replacement: '$1 \"***\"',\n },\n {\n pattern: /\\b(\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})(:\\d+)?\\b/g,\n replacement: '***$2',\n },\n {\n pattern: /\\b(host|hostname|server)[\"\\s]*[:=][\"\\s]*([^\\s,}\"]+)/gi,\n replacement: '$1=***',\n },\n]\n\n/**\n * @param {string} text\n * @returns {string}\n */\nfunction maskSensitiveData(text) {\n if (!text || typeof text !== 'string') return text\n let masked = text\n for (const { pattern, replacement } of SENSITIVE_PATTERNS) {\n masked = masked.replace(pattern, replacement)\n }\n return masked\n}\n\n/**\n * @typedef {{ env: string, url?: string } | { env: string, client?: any }} HealthResource\n */\nclass HealthCheckClient {\n /**\n * @param {Object} options\n * @param {HealthResource[]} options.resources - Must include Redis resource with client\n * @param {Object} [options.config]\n * @param {string} [options.appName] - For cache key: healthcheck:${appName}\n * @param {string} [options.cacheKey] - Redis key (overrides appName)\n */\n constructor(options = {}) {\n this.healthConfig = { ...DEFAULT_HEALTH_CONFIG, ...options.config }\n this.appName =\n options.appName || process.env.BUILD_APP_NAME || 'unknown-app'\n\n this.prefixLogs = `[${this.appName}] [HealthCheck]`\n\n this._refreshPromise = null\n /** @type {Map<string, { pool: any, type: string }>} */\n this._databasePools = new Map()\n\n /** @type {HealthResource[]} */\n this._resources = options.resources || []\n\n const redisClient = this._getRedisClientForCache()\n if (redisClient) {\n this._redisClientType = getRedisClientType(redisClient)\n }\n\n this._cache = new HealthCheckCache({\n redisClient: redisClient || null,\n cacheKey: options.cacheKey,\n appName: this.appName,\n staleThresholdMs: this.healthConfig.staleThresholdMs,\n })\n }\n\n _getEnv(resource) {\n return resource.env ?? resource.name\n }\n\n _getRedisClientForCache() {\n const redisResource = this._resources.find(r => 'client' in r && r.client)\n return redisResource?.client || null\n }\n\n _getPool(env, url) {\n if (!this._databasePools.has(env)) {\n const { pool, type } = createDatabasePool(\n env,\n url,\n this.healthConfig.checkTimeoutMs\n )\n this._databasePools.set(env, { pool, type })\n }\n return this._databasePools.get(env)\n }\n\n async _checkDatabase(resource) {\n const env = this._getEnv(resource)\n const url = 'url' in resource ? resource.url : process.env[env]\n if (!url) {\n return { status: 'error', error: `Env ${env} not set` }\n }\n\n try {\n const { pool, type } = this._getPool(env, url)\n const timings = await runHealthCheck(pool, type)\n\n const maxConnect = this.healthConfig.maxDbConnectLatencyMs\n if (\n typeof maxConnect === 'number' &&\n Number.isFinite(maxConnect) &&\n timings?.connectMs != null &&\n timings.connectMs > maxConnect\n ) {\n return {\n status: 'error',\n error: `DB connect latency ${timings.connectMs}ms exceeds ${maxConnect}ms`,\n connectMs: timings.connectMs,\n }\n }\n\n return { status: 'ok', connectMs: timings.connectMs }\n } catch (err) {\n const timings = err?.healthCheckTimings\n return {\n status: 'error',\n error: maskSensitiveData(err.message),\n ...(timings && typeof timings === 'object'\n ? { connectMs: timings.connectMs }\n : {}),\n }\n }\n }\n\n async _checkRedis(resource) {\n const { client } = resource\n if (!client) return { status: 'ok' }\n\n try {\n let pong\n if (this._redisClientType === REDIS_V3) {\n pong = await new Promise((resolve, reject) => {\n client.ping((err, result) => {\n if (err) reject(err)\n else resolve(result)\n })\n })\n } else if (\n this._redisClientType === REDIS_V4 ||\n this._redisClientType === IOREDIS\n ) {\n pong = await client.ping()\n } else {\n return { status: 'error', error: 'Unknown Redis client type' }\n }\n\n return pong === 'PONG'\n ? { status: 'ok' }\n : { status: 'error', error: `Unexpected: ${pong}` }\n } catch (err) {\n return { status: 'error', error: maskSensitiveData(err.message) }\n }\n }\n\n async _performHealthCheckInternal() {\n const resources = {}\n\n for (const resource of this._resources) {\n const env = this._getEnv(resource)\n\n if ('client' in resource && resource.client) {\n resources[env] = await this._checkRedis(resource)\n } else {\n resources[env] = await this._checkDatabase(resource)\n }\n }\n\n const sortedResources = Object.keys(resources)\n .sort()\n .reduce((acc, key) => {\n acc[key] = resources[key]\n return acc\n }, {})\n\n const hasError = Object.values(resources).some(r => r.status === 'error')\n const lastCheckAt = Date.now()\n\n return {\n status: hasError ? 'error' : 'ok',\n lastCheckAt,\n resources: sortedResources,\n isStale: false,\n config: this.healthConfig,\n }\n }\n\n _formatResult(result, cached = false) {\n const isStale =\n !result.lastCheckAt ||\n Date.now() - result.lastCheckAt > this.healthConfig.staleThresholdMs\n\n return {\n ...result,\n isStale,\n status: isStale ? 'stale' : result.status,\n ...(isStale && {\n error:\n 'Health check data is stale, health-check worker may not be running. Resource statuses are unknown.',\n }),\n ...(cached && { cached: true }),\n }\n }\n\n async performHealthCheck() {\n if (this._refreshPromise) {\n return this._refreshPromise\n }\n\n this._refreshPromise = this._performHealthCheckInternal()\n .then(result => {\n this._refreshPromise = null\n return this._formatResult(result)\n })\n .catch(err => {\n this._refreshPromise = null\n throw err\n })\n\n return this._refreshPromise\n }\n\n async getCachedResult() {\n try {\n const cached = await this._cache.get()\n if (cached) return this._formatResult(cached)\n return null\n } catch (err) {\n console.error(`${this.prefixLogs} Failed to read from cache:`, err)\n return {\n status: 'error',\n lastCheckAt: null,\n resources: {},\n isStale: true,\n error:\n 'Redis unavailable, unable to read health status of other resources',\n config: this.healthConfig,\n }\n }\n }\n\n async refreshCache() {\n const result = await this._performHealthCheckInternal()\n await this._cache.set(result)\n return result\n }\n\n clearCache() {\n this._refreshPromise = null\n }\n\n healthHandler() {\n return async (req, res) => {\n try {\n const result = await this.getCachedResult()\n\n if (!result) {\n res.status(503).json({\n status: 'error',\n lastCheckAt: null,\n resources: {},\n isStale: true,\n error:\n 'No health check data yet, health-check worker may not be running',\n config: this.healthConfig,\n })\n return\n }\n\n const statusCode = result.status === 'ok' ? 200 : 503\n res.status(statusCode).json(result)\n } catch (err) {\n console.error(`${this.prefixLogs} Health check failed:`, err)\n res.status(503).json({\n status: 'error',\n lastCheckAt: null,\n resources: {},\n isStale: true,\n error:\n 'Redis unavailable, unable to read health status of other resources',\n config: this.healthConfig,\n })\n }\n }\n }\n\n async cleanup() {\n for (const [, { pool }] of this._databasePools) {\n try {\n await closePool(pool)\n } catch (err) {\n console.error(`${this.prefixLogs} Error closing database pool:`, err)\n }\n }\n this._databasePools.clear()\n }\n}\n\nmodule.exports = { HealthCheckClient, DEFAULT_HEALTH_CONFIG }\n"],"mappings":";;AAAA,MAAM;EACJA,kBAAkB;EAClBC,cAAc;EACdC;AACF,CAAC,GAAGC,OAAO,CAAC,mBAAmB,CAAC;AAChC,MAAM;EACJC,kBAAkB;EAClBC,QAAQ;EACRC,OAAO;EACPC;AACF,CAAC,GAAGJ,OAAO,CAAC,eAAe,CAAC;AAC5B,MAAM;EAAEK;AAAiB,CAAC,GAAGL,OAAO,CAAC,oBAAoB,CAAC;;AAE1D;AACA;AACA;AACA;AACA,SAASM,aAAaA,CAACC,IAAI,EAAE;EAC3B,MAAMC,GAAG,GAAGC,OAAO,CAACC,GAAG,CAACH,IAAI,CAAC;EAC7B,IAAIC,GAAG,IAAI,IAAI,IAAIA,GAAG,KAAK,EAAE,EAAE,OAAOG,SAAS;EAC/C,MAAMC,GAAG,GAAGC,MAAM,CAACL,GAAG,CAAC;EACvB,OAAOK,MAAM,CAACC,QAAQ,CAACF,GAAG,CAAC,GAAGA,GAAG,GAAGD,SAAS;AAC/C;;AAEA;AACA,MAAMI,qBAAqB,GAAG;EAC5BC,eAAe,EAAE,MAAM;EACvBC,gBAAgB,EAAE,OAAO;EACzBC,cAAc,EAAE,MAAM;EACtBC,qBAAqB,EACnBb,aAAa,CAAC,kCAAkC,CAAC,IAAI;AACzD,CAAC;AAED,MAAMc,kBAAkB,GAAG,CACzB;EACEC,OAAO,EACL,6FAA6F;EAC/FC,WAAW,EAAE;AACf,CAAC,EACD;EACED,OAAO,EAAE,uCAAuC;EAChDC,WAAW,EAAE;AACf,CAAC,EACD;EACED,OAAO,EACL,4FAA4F;EAC9FC,WAAW,EAAE;AACf,CAAC,EACD;EACED,OAAO,EACL,8EAA8E;EAChFC,WAAW,EAAE;AACf,CAAC,EACD;EACED,OAAO,EAAE,kDAAkD;EAC3DC,WAAW,EAAE;AACf,CAAC,EACD;EACED,OAAO,EAAE,uDAAuD;EAChEC,WAAW,EAAE;AACf,CAAC,CACF;;AAED;AACA;AACA;AACA;AACA,SAASC,iBAAiBA,CAACC,IAAI,EAAE;EAC/B,IAAI,CAACA,IAAI,IAAI,OAAOA,IAAI,KAAK,QAAQ,EAAE,OAAOA,IAAI;EAClD,IAAIC,MAAM,GAAGD,IAAI;EACjB,KAAK,MAAM;IAAEH,OAAO;IAAEC;EAAY,CAAC,IAAIF,kBAAkB,EAAE;IACzDK,MAAM,GAAGA,MAAM,CAACC,OAAO,CAACL,OAAO,EAAEC,WAAW,CAAC;EAC/C;EACA,OAAOG,MAAM;AACf;;AAEA;AACA;AACA;AACA,MAAME,iBAAiB,CAAC;EACtB;AACF;AACA;AACA;AACA;AACA;AACA;EACEC,WAAWA,CAACC,OAAO,GAAG,CAAC,CAAC,EAAE;IACxB,IAAI,CAACC,YAAY,GAAG;MAAE,GAAGf,qBAAqB;MAAE,GAAGc,OAAO,CAACE;IAAO,CAAC;IACnE,IAAI,CAACC,OAAO,GACVH,OAAO,CAACG,OAAO,IAAIvB,OAAO,CAACC,GAAG,CAACuB,cAAc,IAAI,aAAa;IAEhE,IAAI,CAACC,UAAU,GAAG,IAAI,IAAI,CAACF,OAAO,iBAAiB;IAEnD,IAAI,CAACG,eAAe,GAAG,IAAI;IAC3B;IACA,IAAI,CAACC,cAAc,GAAG,IAAIC,GAAG,CAAC,CAAC;;IAE/B;IACA,IAAI,CAACC,UAAU,GAAGT,OAAO,CAACU,SAAS,IAAI,EAAE;IAEzC,MAAMC,WAAW,GAAG,IAAI,CAACC,uBAAuB,CAAC,CAAC;IAClD,IAAID,WAAW,EAAE;MACf,IAAI,CAACE,gBAAgB,GAAGzC,kBAAkB,CAACuC,WAAW,CAAC;IACzD;IAEA,IAAI,CAACG,MAAM,GAAG,IAAItC,gBAAgB,CAAC;MACjCmC,WAAW,EAAEA,WAAW,IAAI,IAAI;MAChCI,QAAQ,EAAEf,OAAO,CAACe,QAAQ;MAC1BZ,OAAO,EAAE,IAAI,CAACA,OAAO;MACrBf,gBAAgB,EAAE,IAAI,CAACa,YAAY,CAACb;IACtC,CAAC,CAAC;EACJ;EAEA4B,OAAOA,CAACC,QAAQ,EAAE;IAChB,OAAOA,QAAQ,CAACpC,GAAG,IAAIoC,QAAQ,CAACvC,IAAI;EACtC;EAEAkC,uBAAuBA,CAAA,EAAG;IACxB,MAAMM,aAAa,GAAG,IAAI,CAACT,UAAU,CAACU,IAAI,CAACC,CAAC,IAAI,QAAQ,IAAIA,CAAC,IAAIA,CAAC,CAACC,MAAM,CAAC;IAC1E,OAAOH,aAAa,EAAEG,MAAM,IAAI,IAAI;EACtC;EAEAC,QAAQA,CAACzC,GAAG,EAAE0C,GAAG,EAAE;IACjB,IAAI,CAAC,IAAI,CAAChB,cAAc,CAACiB,GAAG,CAAC3C,GAAG,CAAC,EAAE;MACjC,MAAM;QAAE4C,IAAI;QAAEC;MAAK,CAAC,GAAG1D,kBAAkB,CACvCa,GAAG,EACH0C,GAAG,EACH,IAAI,CAACtB,YAAY,CAACZ,cACpB,CAAC;MACD,IAAI,CAACkB,cAAc,CAACoB,GAAG,CAAC9C,GAAG,EAAE;QAAE4C,IAAI;QAAEC;MAAK,CAAC,CAAC;IAC9C;IACA,OAAO,IAAI,CAACnB,cAAc,CAACqB,GAAG,CAAC/C,GAAG,CAAC;EACrC;EAEA,MAAMgD,cAAcA,CAACZ,QAAQ,EAAE;IAC7B,MAAMpC,GAAG,GAAG,IAAI,CAACmC,OAAO,CAACC,QAAQ,CAAC;IAClC,MAAMM,GAAG,GAAG,KAAK,IAAIN,QAAQ,GAAGA,QAAQ,CAACM,GAAG,GAAG3C,OAAO,CAACC,GAAG,CAACA,GAAG,CAAC;IAC/D,IAAI,CAAC0C,GAAG,EAAE;MACR,OAAO;QAAEO,MAAM,EAAE,OAAO;QAAEC,KAAK,EAAE,OAAOlD,GAAG;MAAW,CAAC;IACzD;IAEA,IAAI;MACF,MAAM;QAAE4C,IAAI;QAAEC;MAAK,CAAC,GAAG,IAAI,CAACJ,QAAQ,CAACzC,GAAG,EAAE0C,GAAG,CAAC;MAC9C,MAAMS,OAAO,GAAG,MAAM/D,cAAc,CAACwD,IAAI,EAAEC,IAAI,CAAC;MAEhD,MAAMO,UAAU,GAAG,IAAI,CAAChC,YAAY,CAACX,qBAAqB;MAC1D,IACE,OAAO2C,UAAU,KAAK,QAAQ,IAC9BjD,MAAM,CAACC,QAAQ,CAACgD,UAAU,CAAC,IAC3BD,OAAO,EAAEE,SAAS,IAAI,IAAI,IAC1BF,OAAO,CAACE,SAAS,GAAGD,UAAU,EAC9B;QACA,OAAO;UACLH,MAAM,EAAE,OAAO;UACfC,KAAK,EAAE,sBAAsBC,OAAO,CAACE,SAAS,cAAcD,UAAU,IAAI;UAC1EC,SAAS,EAAEF,OAAO,CAACE;QACrB,CAAC;MACH;MAEA,OAAO;QAAEJ,MAAM,EAAE,IAAI;QAAEI,SAAS,EAAEF,OAAO,CAACE;MAAU,CAAC;IACvD,CAAC,CAAC,OAAOC,GAAG,EAAE;MACZ,MAAMH,OAAO,GAAGG,GAAG,EAAEC,kBAAkB;MACvC,OAAO;QACLN,MAAM,EAAE,OAAO;QACfC,KAAK,EAAErC,iBAAiB,CAACyC,GAAG,CAACE,OAAO,CAAC;QACrC,IAAIL,OAAO,IAAI,OAAOA,OAAO,KAAK,QAAQ,GACtC;UAAEE,SAAS,EAAEF,OAAO,CAACE;QAAU,CAAC,GAChC,CAAC,CAAC;MACR,CAAC;IACH;EACF;EAEA,MAAMI,WAAWA,CAACrB,QAAQ,EAAE;IAC1B,MAAM;MAAEI;IAAO,CAAC,GAAGJ,QAAQ;IAC3B,IAAI,CAACI,MAAM,EAAE,OAAO;MAAES,MAAM,EAAE;IAAK,CAAC;IAEpC,IAAI;MACF,IAAIS,IAAI;MACR,IAAI,IAAI,CAAC1B,gBAAgB,KAAKtC,QAAQ,EAAE;QACtCgE,IAAI,GAAG,MAAM,IAAIC,OAAO,CAAC,CAACC,OAAO,EAAEC,MAAM,KAAK;UAC5CrB,MAAM,CAACsB,IAAI,CAAC,CAACR,GAAG,EAAES,MAAM,KAAK;YAC3B,IAAIT,GAAG,EAAEO,MAAM,CAACP,GAAG,CAAC,MACfM,OAAO,CAACG,MAAM,CAAC;UACtB,CAAC,CAAC;QACJ,CAAC,CAAC;MACJ,CAAC,MAAM,IACL,IAAI,CAAC/B,gBAAgB,KAAKxC,QAAQ,IAClC,IAAI,CAACwC,gBAAgB,KAAKvC,OAAO,EACjC;QACAiE,IAAI,GAAG,MAAMlB,MAAM,CAACsB,IAAI,CAAC,CAAC;MAC5B,CAAC,MAAM;QACL,OAAO;UAAEb,MAAM,EAAE,OAAO;UAAEC,KAAK,EAAE;QAA4B,CAAC;MAChE;MAEA,OAAOQ,IAAI,KAAK,MAAM,GAClB;QAAET,MAAM,EAAE;MAAK,CAAC,GAChB;QAAEA,MAAM,EAAE,OAAO;QAAEC,KAAK,EAAE,eAAeQ,IAAI;MAAG,CAAC;IACvD,CAAC,CAAC,OAAOJ,GAAG,EAAE;MACZ,OAAO;QAAEL,MAAM,EAAE,OAAO;QAAEC,KAAK,EAAErC,iBAAiB,CAACyC,GAAG,CAACE,OAAO;MAAE,CAAC;IACnE;EACF;EAEA,MAAMQ,2BAA2BA,CAAA,EAAG;IAClC,MAAMnC,SAAS,GAAG,CAAC,CAAC;IAEpB,KAAK,MAAMO,QAAQ,IAAI,IAAI,CAACR,UAAU,EAAE;MACtC,MAAM5B,GAAG,GAAG,IAAI,CAACmC,OAAO,CAACC,QAAQ,CAAC;MAElC,IAAI,QAAQ,IAAIA,QAAQ,IAAIA,QAAQ,CAACI,MAAM,EAAE;QAC3CX,SAAS,CAAC7B,GAAG,CAAC,GAAG,MAAM,IAAI,CAACyD,WAAW,CAACrB,QAAQ,CAAC;MACnD,CAAC,MAAM;QACLP,SAAS,CAAC7B,GAAG,CAAC,GAAG,MAAM,IAAI,CAACgD,cAAc,CAACZ,QAAQ,CAAC;MACtD;IACF;IAEA,MAAM6B,eAAe,GAAGC,MAAM,CAACC,IAAI,CAACtC,SAAS,CAAC,CAC3CuC,IAAI,CAAC,CAAC,CACNC,MAAM,CAAC,CAACC,GAAG,EAAEC,GAAG,KAAK;MACpBD,GAAG,CAACC,GAAG,CAAC,GAAG1C,SAAS,CAAC0C,GAAG,CAAC;MACzB,OAAOD,GAAG;IACZ,CAAC,EAAE,CAAC,CAAC,CAAC;IAER,MAAME,QAAQ,GAAGN,MAAM,CAACO,MAAM,CAAC5C,SAAS,CAAC,CAAC6C,IAAI,CAACnC,CAAC,IAAIA,CAAC,CAACU,MAAM,KAAK,OAAO,CAAC;IACzE,MAAM0B,WAAW,GAAGC,IAAI,CAACC,GAAG,CAAC,CAAC;IAE9B,OAAO;MACL5B,MAAM,EAAEuB,QAAQ,GAAG,OAAO,GAAG,IAAI;MACjCG,WAAW;MACX9C,SAAS,EAAEoC,eAAe;MAC1Ba,OAAO,EAAE,KAAK;MACdzD,MAAM,EAAE,IAAI,CAACD;IACf,CAAC;EACH;EAEA2D,aAAaA,CAAChB,MAAM,EAAEiB,MAAM,GAAG,KAAK,EAAE;IACpC,MAAMF,OAAO,GACX,CAACf,MAAM,CAACY,WAAW,IACnBC,IAAI,CAACC,GAAG,CAAC,CAAC,GAAGd,MAAM,CAACY,WAAW,GAAG,IAAI,CAACvD,YAAY,CAACb,gBAAgB;IAEtE,OAAO;MACL,GAAGwD,MAAM;MACTe,OAAO;MACP7B,MAAM,EAAE6B,OAAO,GAAG,OAAO,GAAGf,MAAM,CAACd,MAAM;MACzC,IAAI6B,OAAO,IAAI;QACb5B,KAAK,EACH;MACJ,CAAC,CAAC;MACF,IAAI8B,MAAM,IAAI;QAAEA,MAAM,EAAE;MAAK,CAAC;IAChC,CAAC;EACH;EAEA,MAAMC,kBAAkBA,CAAA,EAAG;IACzB,IAAI,IAAI,CAACxD,eAAe,EAAE;MACxB,OAAO,IAAI,CAACA,eAAe;IAC7B;IAEA,IAAI,CAACA,eAAe,GAAG,IAAI,CAACuC,2BAA2B,CAAC,CAAC,CACtDkB,IAAI,CAACnB,MAAM,IAAI;MACd,IAAI,CAACtC,eAAe,GAAG,IAAI;MAC3B,OAAO,IAAI,CAACsD,aAAa,CAAChB,MAAM,CAAC;IACnC,CAAC,CAAC,CACDoB,KAAK,CAAC7B,GAAG,IAAI;MACZ,IAAI,CAAC7B,eAAe,GAAG,IAAI;MAC3B,MAAM6B,GAAG;IACX,CAAC,CAAC;IAEJ,OAAO,IAAI,CAAC7B,eAAe;EAC7B;EAEA,MAAM2D,eAAeA,CAAA,EAAG;IACtB,IAAI;MACF,MAAMJ,MAAM,GAAG,MAAM,IAAI,CAAC/C,MAAM,CAACc,GAAG,CAAC,CAAC;MACtC,IAAIiC,MAAM,EAAE,OAAO,IAAI,CAACD,aAAa,CAACC,MAAM,CAAC;MAC7C,OAAO,IAAI;IACb,CAAC,CAAC,OAAO1B,GAAG,EAAE;MACZ+B,OAAO,CAACnC,KAAK,CAAC,GAAG,IAAI,CAAC1B,UAAU,6BAA6B,EAAE8B,GAAG,CAAC;MACnE,OAAO;QACLL,MAAM,EAAE,OAAO;QACf0B,WAAW,EAAE,IAAI;QACjB9C,SAAS,EAAE,CAAC,CAAC;QACbiD,OAAO,EAAE,IAAI;QACb5B,KAAK,EACH,oEAAoE;QACtE7B,MAAM,EAAE,IAAI,CAACD;MACf,CAAC;IACH;EACF;EAEA,MAAMkE,YAAYA,CAAA,EAAG;IACnB,MAAMvB,MAAM,GAAG,MAAM,IAAI,CAACC,2BAA2B,CAAC,CAAC;IACvD,MAAM,IAAI,CAAC/B,MAAM,CAACa,GAAG,CAACiB,MAAM,CAAC;IAC7B,OAAOA,MAAM;EACf;EAEAwB,UAAUA,CAAA,EAAG;IACX,IAAI,CAAC9D,eAAe,GAAG,IAAI;EAC7B;EAEA+D,aAAaA,CAAA,EAAG;IACd,OAAO,OAAOC,GAAG,EAAEC,GAAG,KAAK;MACzB,IAAI;QACF,MAAM3B,MAAM,GAAG,MAAM,IAAI,CAACqB,eAAe,CAAC,CAAC;QAE3C,IAAI,CAACrB,MAAM,EAAE;UACX2B,GAAG,CAACzC,MAAM,CAAC,GAAG,CAAC,CAAC0C,IAAI,CAAC;YACnB1C,MAAM,EAAE,OAAO;YACf0B,WAAW,EAAE,IAAI;YACjB9C,SAAS,EAAE,CAAC,CAAC;YACbiD,OAAO,EAAE,IAAI;YACb5B,KAAK,EACH,kEAAkE;YACpE7B,MAAM,EAAE,IAAI,CAACD;UACf,CAAC,CAAC;UACF;QACF;QAEA,MAAMwE,UAAU,GAAG7B,MAAM,CAACd,MAAM,KAAK,IAAI,GAAG,GAAG,GAAG,GAAG;QACrDyC,GAAG,CAACzC,MAAM,CAAC2C,UAAU,CAAC,CAACD,IAAI,CAAC5B,MAAM,CAAC;MACrC,CAAC,CAAC,OAAOT,GAAG,EAAE;QACZ+B,OAAO,CAACnC,KAAK,CAAC,GAAG,IAAI,CAAC1B,UAAU,uBAAuB,EAAE8B,GAAG,CAAC;QAC7DoC,GAAG,CAACzC,MAAM,CAAC,GAAG,CAAC,CAAC0C,IAAI,CAAC;UACnB1C,MAAM,EAAE,OAAO;UACf0B,WAAW,EAAE,IAAI;UACjB9C,SAAS,EAAE,CAAC,CAAC;UACbiD,OAAO,EAAE,IAAI;UACb5B,KAAK,EACH,oEAAoE;UACtE7B,MAAM,EAAE,IAAI,CAACD;QACf,CAAC,CAAC;MACJ;IACF,CAAC;EACH;EAEA,MAAMyE,OAAOA,CAAA,EAAG;IACd,KAAK,MAAM,GAAG;MAAEjD;IAAK,CAAC,CAAC,IAAI,IAAI,CAAClB,cAAc,EAAE;MAC9C,IAAI;QACF,MAAMrC,SAAS,CAACuD,IAAI,CAAC;MACvB,CAAC,CAAC,OAAOU,GAAG,EAAE;QACZ+B,OAAO,CAACnC,KAAK,CAAC,GAAG,IAAI,CAAC1B,UAAU,+BAA+B,EAAE8B,GAAG,CAAC;MACvE;IACF;IACA,IAAI,CAAC5B,cAAc,CAACoE,KAAK,CAAC,CAAC;EAC7B;AACF;AAEAC,MAAM,CAACC,OAAO,GAAG;EAAE/E,iBAAiB;EAAEZ;AAAsB,CAAC","ignoreList":[]}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @param {Object} options
|
|
3
|
+
* @param {{ env: string } | { env: string, url?: string } | { env: string, client?: any }}[] options.resources
|
|
4
|
+
* @param {string} [options.appName] - For cache key: healthcheck:${appName}
|
|
5
|
+
* @param {string} [options.cacheKey] - Redis key (overrides appName)
|
|
6
|
+
* @param {Object} [options.config]
|
|
7
|
+
* @param {string} [options.databaseUrl]
|
|
8
|
+
* @param {string} [options.databaseName]
|
|
9
|
+
* @param {Object<string, string>} [options.additionalDatabaseUrls]
|
|
10
|
+
* @returns {HealthCheckClient}
|
|
11
|
+
*/
|
|
12
|
+
export function createHealthCheckWorkerClient(options: Object): HealthCheckClient;
|
|
13
|
+
/**
|
|
14
|
+
* @param {Object} options
|
|
15
|
+
* @param {any} options.redisClient
|
|
16
|
+
* @param {string} [options.appName] - For cache key: healthcheck:${appName}
|
|
17
|
+
* @param {string} [options.cacheKey] - Redis key (e.g. 'health:database:status')
|
|
18
|
+
* @param {Object} [options.config]
|
|
19
|
+
* @returns {HealthCheckClient}
|
|
20
|
+
*/
|
|
21
|
+
export function createHealthCheckEndpointClient(options: {
|
|
22
|
+
redisClient: any;
|
|
23
|
+
appName?: string | undefined;
|
|
24
|
+
cacheKey?: string | undefined;
|
|
25
|
+
config?: Object | undefined;
|
|
26
|
+
}): HealthCheckClient;
|
|
27
|
+
/**
|
|
28
|
+
* @param {Object} options
|
|
29
|
+
* @param {any} options.redisClient
|
|
30
|
+
* @param {string} [options.cacheKey] - Redis key (e.g. 'health:database:status')
|
|
31
|
+
* @param {string} [options.appName] - For cache key: healthcheck:${appName}
|
|
32
|
+
* @param {Object} [options.config]
|
|
33
|
+
* @returns {(req: any, res: any) => Promise<void>}
|
|
34
|
+
*/
|
|
35
|
+
export function getHealthCheckStatus(options: {
|
|
36
|
+
redisClient: any;
|
|
37
|
+
cacheKey?: string | undefined;
|
|
38
|
+
appName?: string | undefined;
|
|
39
|
+
config?: Object | undefined;
|
|
40
|
+
}): (req: any, res: any) => Promise<void>;
|
|
41
|
+
/**
|
|
42
|
+
* @param {Object<string, string>} urls
|
|
43
|
+
* @returns {{ env: string, url: string }[]}
|
|
44
|
+
*/
|
|
45
|
+
export function additionalDatabaseUrlsToResources(urls: {
|
|
46
|
+
[x: string]: string;
|
|
47
|
+
}): {
|
|
48
|
+
env: string;
|
|
49
|
+
url: string;
|
|
50
|
+
}[];
|
|
51
|
+
import { HealthCheckClient } from "./healthCheckClient";
|
|
52
|
+
//# sourceMappingURL=healthCheckUtils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"healthCheckUtils.d.ts","sourceRoot":"","sources":["../../src/health/healthCheckUtils.js"],"names":[],"mappings":"AAaA;;;;;;;;;;GAUG;AACH,uDAVW,MAAM,GAQJ,iBAAiB,CA6C7B;AAED;;;;;;;GAOG;AACH;IANwB,WAAW,EAAxB,GAAG;IACc,OAAO;IACP,QAAQ;IACR,MAAM;IACrB,iBAAiB,CAiB7B;AAED;;;;;;;GAOG;AACH;IANwB,WAAW,EAAxB,GAAG;IACc,QAAQ;IACR,OAAO;IACP,MAAM;UACf,GAAG,OAAO,GAAG,KAAK,QAAQ,IAAI,CAAC,CAiBjD;AAnHD;;;GAGG;AACH;QAHkB,MAAM,GAAE,MAAM;IACnB;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,EAAE,CAO1C"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const {
|
|
4
|
+
HealthCheckClient
|
|
5
|
+
} = require('./healthCheckClient');
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @param {Object<string, string>} urls
|
|
9
|
+
* @returns {{ env: string, url: string }[]}
|
|
10
|
+
*/
|
|
11
|
+
function additionalDatabaseUrlsToResources(urls) {
|
|
12
|
+
if (!urls || typeof urls !== 'object') return [];
|
|
13
|
+
return Object.entries(urls).filter(([, url]) => url).map(([env, url]) => ({
|
|
14
|
+
env,
|
|
15
|
+
url
|
|
16
|
+
}));
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @param {Object} options
|
|
21
|
+
* @param {{ env: string } | { env: string, url?: string } | { env: string, client?: any }}[] options.resources
|
|
22
|
+
* @param {string} [options.appName] - For cache key: healthcheck:${appName}
|
|
23
|
+
* @param {string} [options.cacheKey] - Redis key (overrides appName)
|
|
24
|
+
* @param {Object} [options.config]
|
|
25
|
+
* @param {string} [options.databaseUrl]
|
|
26
|
+
* @param {string} [options.databaseName]
|
|
27
|
+
* @param {Object<string, string>} [options.additionalDatabaseUrls]
|
|
28
|
+
* @returns {HealthCheckClient}
|
|
29
|
+
*/
|
|
30
|
+
function createHealthCheckWorkerClient(options) {
|
|
31
|
+
const {
|
|
32
|
+
resources,
|
|
33
|
+
appName,
|
|
34
|
+
cacheKey,
|
|
35
|
+
config,
|
|
36
|
+
databaseUrl,
|
|
37
|
+
databaseName,
|
|
38
|
+
additionalDatabaseUrls
|
|
39
|
+
} = options;
|
|
40
|
+
let resourcesArray = Array.isArray(resources) ? resources : [];
|
|
41
|
+
if (resourcesArray.length === 0) {
|
|
42
|
+
resourcesArray = [];
|
|
43
|
+
if (databaseUrl) {
|
|
44
|
+
const url = databaseUrl || process.env.DATABASE_URL;
|
|
45
|
+
if (url) {
|
|
46
|
+
const env = databaseName || 'DATABASE_URL';
|
|
47
|
+
resourcesArray.push({
|
|
48
|
+
env,
|
|
49
|
+
url
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
const clusterResources = additionalDatabaseUrlsToResources(additionalDatabaseUrls || {});
|
|
54
|
+
resourcesArray.push(...clusterResources);
|
|
55
|
+
}
|
|
56
|
+
const redisResource = resourcesArray.find(r => 'client' in r && r.client);
|
|
57
|
+
if (!redisResource) {
|
|
58
|
+
throw new Error('resources must include Redis resource with client (e.g. { env: "REDIS_URL", client })');
|
|
59
|
+
}
|
|
60
|
+
return new HealthCheckClient({
|
|
61
|
+
resources: resourcesArray,
|
|
62
|
+
appName: appName || process.env.BUILD_APP_NAME || 'unknown-app',
|
|
63
|
+
cacheKey,
|
|
64
|
+
config
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* @param {Object} options
|
|
70
|
+
* @param {any} options.redisClient
|
|
71
|
+
* @param {string} [options.appName] - For cache key: healthcheck:${appName}
|
|
72
|
+
* @param {string} [options.cacheKey] - Redis key (e.g. 'health:database:status')
|
|
73
|
+
* @param {Object} [options.config]
|
|
74
|
+
* @returns {HealthCheckClient}
|
|
75
|
+
*/
|
|
76
|
+
function createHealthCheckEndpointClient(options) {
|
|
77
|
+
const {
|
|
78
|
+
redisClient,
|
|
79
|
+
appName,
|
|
80
|
+
cacheKey,
|
|
81
|
+
config
|
|
82
|
+
} = options;
|
|
83
|
+
if (!redisClient) {
|
|
84
|
+
throw new Error('redisClient is required for createHealthCheckEndpointClient');
|
|
85
|
+
}
|
|
86
|
+
return new HealthCheckClient({
|
|
87
|
+
resources: [{
|
|
88
|
+
env: 'REDIS_URL',
|
|
89
|
+
client: redisClient
|
|
90
|
+
}],
|
|
91
|
+
appName: appName || process.env.BUILD_APP_NAME || 'unknown-app',
|
|
92
|
+
cacheKey,
|
|
93
|
+
config
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* @param {Object} options
|
|
99
|
+
* @param {any} options.redisClient
|
|
100
|
+
* @param {string} [options.cacheKey] - Redis key (e.g. 'health:database:status')
|
|
101
|
+
* @param {string} [options.appName] - For cache key: healthcheck:${appName}
|
|
102
|
+
* @param {Object} [options.config]
|
|
103
|
+
* @returns {(req: any, res: any) => Promise<void>}
|
|
104
|
+
*/
|
|
105
|
+
function getHealthCheckStatus(options) {
|
|
106
|
+
const {
|
|
107
|
+
redisClient,
|
|
108
|
+
cacheKey,
|
|
109
|
+
appName,
|
|
110
|
+
config
|
|
111
|
+
} = options;
|
|
112
|
+
if (!redisClient) {
|
|
113
|
+
throw new Error('redisClient is required for getHealthCheckStatus');
|
|
114
|
+
}
|
|
115
|
+
const client = createHealthCheckEndpointClient({
|
|
116
|
+
redisClient,
|
|
117
|
+
cacheKey,
|
|
118
|
+
appName,
|
|
119
|
+
config
|
|
120
|
+
});
|
|
121
|
+
return client.healthHandler();
|
|
122
|
+
}
|
|
123
|
+
module.exports = {
|
|
124
|
+
createHealthCheckWorkerClient,
|
|
125
|
+
createHealthCheckEndpointClient,
|
|
126
|
+
getHealthCheckStatus,
|
|
127
|
+
additionalDatabaseUrlsToResources
|
|
128
|
+
};
|
|
129
|
+
//# sourceMappingURL=healthCheckUtils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"healthCheckUtils.js","names":["HealthCheckClient","require","additionalDatabaseUrlsToResources","urls","Object","entries","filter","url","map","env","createHealthCheckWorkerClient","options","resources","appName","cacheKey","config","databaseUrl","databaseName","additionalDatabaseUrls","resourcesArray","Array","isArray","length","process","DATABASE_URL","push","clusterResources","redisResource","find","r","client","Error","BUILD_APP_NAME","createHealthCheckEndpointClient","redisClient","getHealthCheckStatus","healthHandler","module","exports"],"sources":["../../src/health/healthCheckUtils.js"],"sourcesContent":["const { HealthCheckClient } = require('./healthCheckClient')\n\n/**\n * @param {Object<string, string>} urls\n * @returns {{ env: string, url: string }[]}\n */\nfunction additionalDatabaseUrlsToResources(urls) {\n if (!urls || typeof urls !== 'object') return []\n return Object.entries(urls)\n .filter(([, url]) => url)\n .map(([env, url]) => ({ env, url }))\n}\n\n/**\n * @param {Object} options\n * @param {{ env: string } | { env: string, url?: string } | { env: string, client?: any }}[] options.resources\n * @param {string} [options.appName] - For cache key: healthcheck:${appName}\n * @param {string} [options.cacheKey] - Redis key (overrides appName)\n * @param {Object} [options.config]\n * @param {string} [options.databaseUrl]\n * @param {string} [options.databaseName]\n * @param {Object<string, string>} [options.additionalDatabaseUrls]\n * @returns {HealthCheckClient}\n */\nfunction createHealthCheckWorkerClient(options) {\n const {\n resources,\n appName,\n cacheKey,\n config,\n databaseUrl,\n databaseName,\n additionalDatabaseUrls,\n } = options\n\n let resourcesArray = Array.isArray(resources) ? resources : []\n\n if (resourcesArray.length === 0) {\n resourcesArray = []\n\n if (databaseUrl) {\n const url = databaseUrl || process.env.DATABASE_URL\n if (url) {\n const env = databaseName || 'DATABASE_URL'\n resourcesArray.push({ env, url })\n }\n }\n\n const clusterResources = additionalDatabaseUrlsToResources(\n additionalDatabaseUrls || {}\n )\n resourcesArray.push(...clusterResources)\n }\n\n const redisResource = resourcesArray.find(r => 'client' in r && r.client)\n if (!redisResource) {\n throw new Error(\n 'resources must include Redis resource with client (e.g. { env: \"REDIS_URL\", client })'\n )\n }\n\n return new HealthCheckClient({\n resources: resourcesArray,\n appName: appName || process.env.BUILD_APP_NAME || 'unknown-app',\n cacheKey,\n config,\n })\n}\n\n/**\n * @param {Object} options\n * @param {any} options.redisClient\n * @param {string} [options.appName] - For cache key: healthcheck:${appName}\n * @param {string} [options.cacheKey] - Redis key (e.g. 'health:database:status')\n * @param {Object} [options.config]\n * @returns {HealthCheckClient}\n */\nfunction createHealthCheckEndpointClient(options) {\n const { redisClient, appName, cacheKey, config } = options\n\n if (!redisClient) {\n throw new Error(\n 'redisClient is required for createHealthCheckEndpointClient'\n )\n }\n\n return new HealthCheckClient({\n resources: [{ env: 'REDIS_URL', client: redisClient }],\n appName: appName || process.env.BUILD_APP_NAME || 'unknown-app',\n cacheKey,\n config,\n })\n}\n\n/**\n * @param {Object} options\n * @param {any} options.redisClient\n * @param {string} [options.cacheKey] - Redis key (e.g. 'health:database:status')\n * @param {string} [options.appName] - For cache key: healthcheck:${appName}\n * @param {Object} [options.config]\n * @returns {(req: any, res: any) => Promise<void>}\n */\nfunction getHealthCheckStatus(options) {\n const { redisClient, cacheKey, appName, config } = options\n\n if (!redisClient) {\n throw new Error('redisClient is required for getHealthCheckStatus')\n }\n\n const client = createHealthCheckEndpointClient({\n redisClient,\n cacheKey,\n appName,\n config,\n })\n\n return client.healthHandler()\n}\n\nmodule.exports = {\n createHealthCheckWorkerClient,\n createHealthCheckEndpointClient,\n getHealthCheckStatus,\n additionalDatabaseUrlsToResources,\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"healthCheckWorker.d.ts","sourceRoot":"","sources":["../../src/health/healthCheckWorker.js"],"names":[],"mappings":"AAYA,2EA0DC"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.createHealthCheckWorker = createHealthCheckWorker;
|
|
7
|
+
/**
|
|
8
|
+
* @param {Object} options
|
|
9
|
+
* @param {{ name: string } | { name: string, url?: string } | { name: string, client: any }}[] options.resources - Must include Redis resource with client
|
|
10
|
+
* @param {string} [options.appName]
|
|
11
|
+
* @param {number} [options.refreshIntervalMs]
|
|
12
|
+
* @param {string} [options.databaseUrl]
|
|
13
|
+
* @param {string} [options.databaseName]
|
|
14
|
+
* @param {Object<string, string>} [options.additionalDatabaseUrls]
|
|
15
|
+
*/
|
|
16
|
+
const {
|
|
17
|
+
createHealthCheckWorkerClient
|
|
18
|
+
} = require('./healthCheckUtils');
|
|
19
|
+
const {
|
|
20
|
+
DEFAULT_HEALTH_CONFIG
|
|
21
|
+
} = require('./healthCheckClient');
|
|
22
|
+
function createHealthCheckWorker(options) {
|
|
23
|
+
const {
|
|
24
|
+
refreshIntervalMs = DEFAULT_HEALTH_CONFIG.checkIntervalMs,
|
|
25
|
+
...workerClientOptions
|
|
26
|
+
} = options;
|
|
27
|
+
const appName = workerClientOptions.appName || process.env.BUILD_APP_NAME || 'unknown-app';
|
|
28
|
+
const dynoId = process.env.HOSTNAME || 'unknown-dyno';
|
|
29
|
+
const processType = process.env.BUILD_DYNO_PROCESS_TYPE || 'health-check-worker';
|
|
30
|
+
const logValues = process.env.HEALTH_LOG_VALUES === 'true';
|
|
31
|
+
const prefixLogs = `[${processType}] [${appName}] [${dynoId}] [HealthCheck]`;
|
|
32
|
+
const healthCheckClient = createHealthCheckWorkerClient(workerClientOptions);
|
|
33
|
+
return async function runHealthCheckWorker() {
|
|
34
|
+
console.log(`${prefixLogs} Starting health check worker...`);
|
|
35
|
+
console.log(`${prefixLogs} Refresh interval: ${refreshIntervalMs}ms`);
|
|
36
|
+
try {
|
|
37
|
+
await healthCheckClient.refreshCache();
|
|
38
|
+
if (logValues) {
|
|
39
|
+
console.log(`${prefixLogs} Initial health check completed`);
|
|
40
|
+
}
|
|
41
|
+
} catch (err) {
|
|
42
|
+
console.error(`${prefixLogs} Initial health check failed:`, err);
|
|
43
|
+
}
|
|
44
|
+
const interval = setInterval(async () => {
|
|
45
|
+
try {
|
|
46
|
+
const result = await healthCheckClient.refreshCache();
|
|
47
|
+
if (logValues) {
|
|
48
|
+
console.log(`${prefixLogs} Health check refreshed at ${result.lastCheckAt}, status: ${result.status}`);
|
|
49
|
+
}
|
|
50
|
+
} catch (err) {
|
|
51
|
+
console.error(`${prefixLogs} Health check refresh failed:`, err);
|
|
52
|
+
}
|
|
53
|
+
}, refreshIntervalMs);
|
|
54
|
+
process.on('SIGTERM', () => {
|
|
55
|
+
console.log(`${prefixLogs} Received SIGTERM, shutting down...`);
|
|
56
|
+
clearInterval(interval);
|
|
57
|
+
healthCheckClient.cleanup().finally(() => {
|
|
58
|
+
process.exit(0);
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
process.on('SIGINT', () => {
|
|
62
|
+
console.log(`${prefixLogs} Received SIGINT, shutting down...`);
|
|
63
|
+
clearInterval(interval);
|
|
64
|
+
healthCheckClient.cleanup().finally(() => {
|
|
65
|
+
process.exit(0);
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=healthCheckWorker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"healthCheckWorker.js","names":["createHealthCheckWorkerClient","require","DEFAULT_HEALTH_CONFIG","createHealthCheckWorker","options","refreshIntervalMs","checkIntervalMs","workerClientOptions","appName","process","env","BUILD_APP_NAME","dynoId","HOSTNAME","processType","BUILD_DYNO_PROCESS_TYPE","logValues","HEALTH_LOG_VALUES","prefixLogs","healthCheckClient","runHealthCheckWorker","console","log","refreshCache","err","error","interval","setInterval","result","lastCheckAt","status","on","clearInterval","cleanup","finally","exit"],"sources":["../../src/health/healthCheckWorker.js"],"sourcesContent":["/**\n * @param {Object} options\n * @param {{ name: string } | { name: string, url?: string } | { name: string, client: any }}[] options.resources - Must include Redis resource with client\n * @param {string} [options.appName]\n * @param {number} [options.refreshIntervalMs]\n * @param {string} [options.databaseUrl]\n * @param {string} [options.databaseName]\n * @param {Object<string, string>} [options.additionalDatabaseUrls]\n */\nconst { createHealthCheckWorkerClient } = require('./healthCheckUtils')\nconst { DEFAULT_HEALTH_CONFIG } = require('./healthCheckClient')\n\nexport function createHealthCheckWorker(options) {\n const {\n refreshIntervalMs = DEFAULT_HEALTH_CONFIG.checkIntervalMs,\n ...workerClientOptions\n } = options\n\n const appName =\n workerClientOptions.appName || process.env.BUILD_APP_NAME || 'unknown-app'\n const dynoId = process.env.HOSTNAME || 'unknown-dyno'\n const processType =\n process.env.BUILD_DYNO_PROCESS_TYPE || 'health-check-worker'\n const logValues = process.env.HEALTH_LOG_VALUES === 'true'\n const prefixLogs = `[${processType}] [${appName}] [${dynoId}] [HealthCheck]`\n\n const healthCheckClient = createHealthCheckWorkerClient(workerClientOptions)\n\n return async function runHealthCheckWorker() {\n console.log(`${prefixLogs} Starting health check worker...`)\n console.log(`${prefixLogs} Refresh interval: ${refreshIntervalMs}ms`)\n\n try {\n await healthCheckClient.refreshCache()\n if (logValues) {\n console.log(`${prefixLogs} Initial health check completed`)\n }\n } catch (err) {\n console.error(`${prefixLogs} Initial health check failed:`, err)\n }\n\n const interval = setInterval(async () => {\n try {\n const result = await healthCheckClient.refreshCache()\n if (logValues) {\n console.log(\n `${prefixLogs} Health check refreshed at ${result.lastCheckAt}, status: ${result.status}`\n )\n }\n } catch (err) {\n console.error(`${prefixLogs} Health check refresh failed:`, err)\n }\n }, refreshIntervalMs)\n\n process.on('SIGTERM', () => {\n console.log(`${prefixLogs} Received SIGTERM, shutting down...`)\n clearInterval(interval)\n healthCheckClient.cleanup().finally(() => {\n process.exit(0)\n })\n })\n\n process.on('SIGINT', () => {\n console.log(`${prefixLogs} Received SIGINT, shutting down...`)\n clearInterval(interval)\n healthCheckClient.cleanup().finally(() => {\n process.exit(0)\n })\n })\n }\n}\n"],"mappings":";;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM;EAAEA;AAA8B,CAAC,GAAGC,OAAO,CAAC,oBAAoB,CAAC;AACvE,MAAM;EAAEC;AAAsB,CAAC,GAAGD,OAAO,CAAC,qBAAqB,CAAC;AAEzD,SAASE,uBAAuBA,CAACC,OAAO,EAAE;EAC/C,MAAM;IACJC,iBAAiB,GAAGH,qBAAqB,CAACI,eAAe;IACzD,GAAGC;EACL,CAAC,GAAGH,OAAO;EAEX,MAAMI,OAAO,GACXD,mBAAmB,CAACC,OAAO,IAAIC,OAAO,CAACC,GAAG,CAACC,cAAc,IAAI,aAAa;EAC5E,MAAMC,MAAM,GAAGH,OAAO,CAACC,GAAG,CAACG,QAAQ,IAAI,cAAc;EACrD,MAAMC,WAAW,GACfL,OAAO,CAACC,GAAG,CAACK,uBAAuB,IAAI,qBAAqB;EAC9D,MAAMC,SAAS,GAAGP,OAAO,CAACC,GAAG,CAACO,iBAAiB,KAAK,MAAM;EAC1D,MAAMC,UAAU,GAAG,IAAIJ,WAAW,MAAMN,OAAO,MAAMI,MAAM,iBAAiB;EAE5E,MAAMO,iBAAiB,GAAGnB,6BAA6B,CAACO,mBAAmB,CAAC;EAE5E,OAAO,eAAea,oBAAoBA,CAAA,EAAG;IAC3CC,OAAO,CAACC,GAAG,CAAC,GAAGJ,UAAU,kCAAkC,CAAC;IAC5DG,OAAO,CAACC,GAAG,CAAC,GAAGJ,UAAU,sBAAsBb,iBAAiB,IAAI,CAAC;IAErE,IAAI;MACF,MAAMc,iBAAiB,CAACI,YAAY,CAAC,CAAC;MACtC,IAAIP,SAAS,EAAE;QACbK,OAAO,CAACC,GAAG,CAAC,GAAGJ,UAAU,iCAAiC,CAAC;MAC7D;IACF,CAAC,CAAC,OAAOM,GAAG,EAAE;MACZH,OAAO,CAACI,KAAK,CAAC,GAAGP,UAAU,+BAA+B,EAAEM,GAAG,CAAC;IAClE;IAEA,MAAME,QAAQ,GAAGC,WAAW,CAAC,YAAY;MACvC,IAAI;QACF,MAAMC,MAAM,GAAG,MAAMT,iBAAiB,CAACI,YAAY,CAAC,CAAC;QACrD,IAAIP,SAAS,EAAE;UACbK,OAAO,CAACC,GAAG,CACT,GAAGJ,UAAU,8BAA8BU,MAAM,CAACC,WAAW,aAAaD,MAAM,CAACE,MAAM,EACzF,CAAC;QACH;MACF,CAAC,CAAC,OAAON,GAAG,EAAE;QACZH,OAAO,CAACI,KAAK,CAAC,GAAGP,UAAU,+BAA+B,EAAEM,GAAG,CAAC;MAClE;IACF,CAAC,EAAEnB,iBAAiB,CAAC;IAErBI,OAAO,CAACsB,EAAE,CAAC,SAAS,EAAE,MAAM;MAC1BV,OAAO,CAACC,GAAG,CAAC,GAAGJ,UAAU,qCAAqC,CAAC;MAC/Dc,aAAa,CAACN,QAAQ,CAAC;MACvBP,iBAAiB,CAACc,OAAO,CAAC,CAAC,CAACC,OAAO,CAAC,MAAM;QACxCzB,OAAO,CAAC0B,IAAI,CAAC,CAAC,CAAC;MACjB,CAAC,CAAC;IACJ,CAAC,CAAC;IAEF1B,OAAO,CAACsB,EAAE,CAAC,QAAQ,EAAE,MAAM;MACzBV,OAAO,CAACC,GAAG,CAAC,GAAGJ,UAAU,oCAAoC,CAAC;MAC9Dc,aAAa,CAACN,QAAQ,CAAC;MACvBP,iBAAiB,CAACc,OAAO,CAAC,CAAC,CAACC,OAAO,CAAC,MAAM;QACxCzB,OAAO,CAAC0B,IAAI,CAAC,CAAC,CAAC;MACjB,CAAC,CAAC;IACJ,CAAC,CAAC;EACJ,CAAC;AACH","ignoreList":[]}
|
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export * from './metrics/baseMetricsClient';
|
|
2
|
+
export * from './metrics/metricsClient';
|
|
3
|
+
export * from './metrics/metricsRedisClient';
|
|
4
|
+
export * from './metrics/metricsQueueRedisClient';
|
|
5
|
+
export * from './metrics/metricsDatabaseClient';
|
|
6
|
+
export * from './health/healthCheckClient';
|
|
7
|
+
export * from './health/healthCheckUtils';
|
|
8
|
+
export * from './health/healthCheckWorker';
|
|
9
|
+
export * from './redisUtils';
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,6BAA6B,CAAA;AAC3C,cAAc,yBAAyB,CAAA;AACvC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,mCAAmC,CAAA;AACjD,cAAc,iCAAiC,CAAA;AAC/C,cAAc,4BAA4B,CAAA;AAC1C,cAAc,2BAA2B,CAAA;AACzC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,cAAc,CAAA"}
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
var _baseMetricsClient = require("./metrics/baseMetricsClient");
|
|
7
|
+
Object.keys(_baseMetricsClient).forEach(function (key) {
|
|
8
|
+
if (key === "default" || key === "__esModule") return;
|
|
9
|
+
if (key in exports && exports[key] === _baseMetricsClient[key]) return;
|
|
10
|
+
Object.defineProperty(exports, key, {
|
|
11
|
+
enumerable: true,
|
|
12
|
+
get: function () {
|
|
13
|
+
return _baseMetricsClient[key];
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
});
|
|
17
|
+
var _metricsClient = require("./metrics/metricsClient");
|
|
18
|
+
Object.keys(_metricsClient).forEach(function (key) {
|
|
19
|
+
if (key === "default" || key === "__esModule") return;
|
|
20
|
+
if (key in exports && exports[key] === _metricsClient[key]) return;
|
|
21
|
+
Object.defineProperty(exports, key, {
|
|
22
|
+
enumerable: true,
|
|
23
|
+
get: function () {
|
|
24
|
+
return _metricsClient[key];
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
var _metricsRedisClient = require("./metrics/metricsRedisClient");
|
|
29
|
+
Object.keys(_metricsRedisClient).forEach(function (key) {
|
|
30
|
+
if (key === "default" || key === "__esModule") return;
|
|
31
|
+
if (key in exports && exports[key] === _metricsRedisClient[key]) return;
|
|
32
|
+
Object.defineProperty(exports, key, {
|
|
33
|
+
enumerable: true,
|
|
34
|
+
get: function () {
|
|
35
|
+
return _metricsRedisClient[key];
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
var _metricsQueueRedisClient = require("./metrics/metricsQueueRedisClient");
|
|
40
|
+
Object.keys(_metricsQueueRedisClient).forEach(function (key) {
|
|
41
|
+
if (key === "default" || key === "__esModule") return;
|
|
42
|
+
if (key in exports && exports[key] === _metricsQueueRedisClient[key]) return;
|
|
43
|
+
Object.defineProperty(exports, key, {
|
|
44
|
+
enumerable: true,
|
|
45
|
+
get: function () {
|
|
46
|
+
return _metricsQueueRedisClient[key];
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
var _metricsDatabaseClient = require("./metrics/metricsDatabaseClient");
|
|
51
|
+
Object.keys(_metricsDatabaseClient).forEach(function (key) {
|
|
52
|
+
if (key === "default" || key === "__esModule") return;
|
|
53
|
+
if (key in exports && exports[key] === _metricsDatabaseClient[key]) return;
|
|
54
|
+
Object.defineProperty(exports, key, {
|
|
55
|
+
enumerable: true,
|
|
56
|
+
get: function () {
|
|
57
|
+
return _metricsDatabaseClient[key];
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
var _healthCheckClient = require("./health/healthCheckClient");
|
|
62
|
+
Object.keys(_healthCheckClient).forEach(function (key) {
|
|
63
|
+
if (key === "default" || key === "__esModule") return;
|
|
64
|
+
if (key in exports && exports[key] === _healthCheckClient[key]) return;
|
|
65
|
+
Object.defineProperty(exports, key, {
|
|
66
|
+
enumerable: true,
|
|
67
|
+
get: function () {
|
|
68
|
+
return _healthCheckClient[key];
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
var _healthCheckUtils = require("./health/healthCheckUtils");
|
|
73
|
+
Object.keys(_healthCheckUtils).forEach(function (key) {
|
|
74
|
+
if (key === "default" || key === "__esModule") return;
|
|
75
|
+
if (key in exports && exports[key] === _healthCheckUtils[key]) return;
|
|
76
|
+
Object.defineProperty(exports, key, {
|
|
77
|
+
enumerable: true,
|
|
78
|
+
get: function () {
|
|
79
|
+
return _healthCheckUtils[key];
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
var _healthCheckWorker = require("./health/healthCheckWorker");
|
|
84
|
+
Object.keys(_healthCheckWorker).forEach(function (key) {
|
|
85
|
+
if (key === "default" || key === "__esModule") return;
|
|
86
|
+
if (key in exports && exports[key] === _healthCheckWorker[key]) return;
|
|
87
|
+
Object.defineProperty(exports, key, {
|
|
88
|
+
enumerable: true,
|
|
89
|
+
get: function () {
|
|
90
|
+
return _healthCheckWorker[key];
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
var _redisUtils = require("./redisUtils");
|
|
95
|
+
Object.keys(_redisUtils).forEach(function (key) {
|
|
96
|
+
if (key === "default" || key === "__esModule") return;
|
|
97
|
+
if (key in exports && exports[key] === _redisUtils[key]) return;
|
|
98
|
+
Object.defineProperty(exports, key, {
|
|
99
|
+
enumerable: true,
|
|
100
|
+
get: function () {
|
|
101
|
+
return _redisUtils[key];
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":["_baseMetricsClient","require","Object","keys","forEach","key","exports","defineProperty","enumerable","get","_metricsClient","_metricsRedisClient","_metricsQueueRedisClient","_metricsDatabaseClient","_healthCheckClient","_healthCheckUtils","_healthCheckWorker","_redisUtils"],"sources":["../src/index.ts"],"sourcesContent":["export * from './metrics/baseMetricsClient'\nexport * from './metrics/metricsClient'\nexport * from './metrics/metricsRedisClient'\nexport * from './metrics/metricsQueueRedisClient'\nexport * from './metrics/metricsDatabaseClient'\nexport * from './health/healthCheckClient'\nexport * from './health/healthCheckUtils'\nexport * from './health/healthCheckWorker'\nexport * from './redisUtils'\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BaseMetricsClient provides common functionality for all metrics clients.
|
|
3
|
+
* Handles registry setup, push to remote (VM-agent), default labels, and common operations.
|
|
4
|
+
* Always pushes registry to the configured URL (POST Prometheus text format + Basic auth). No Pushgateway.
|
|
5
|
+
*/
|
|
6
|
+
export class BaseMetricsClient {
|
|
7
|
+
/**
|
|
8
|
+
* @param {Object} config
|
|
9
|
+
* @param {string} [config.appName] Name of the application
|
|
10
|
+
* @param {string} [config.dynoId] Dyno/instance ID
|
|
11
|
+
* @param {string} [config.processType] Process type (web, worker, etc.)
|
|
12
|
+
* @param {boolean} [config.enabled] Enable metrics collection
|
|
13
|
+
* @param {boolean} [config.logValues] Log metrics values to console
|
|
14
|
+
* @param {string} [config.pushgatewayUrl] Push URL (VM-agent import endpoint, e.g. .../api/v1/import/prometheus). /metrics is for GET (scrape), not POST (push).
|
|
15
|
+
* @param {string} [config.pushgatewaySecret] Basic auth secret (Base64 of user:password)
|
|
16
|
+
* @param {number} [config.intervalSec] Interval in seconds for pushing metrics
|
|
17
|
+
* @param {boolean} [config.removeOldMetrics] Enable to clear metrics by service name
|
|
18
|
+
* @param {function} [config.startupValidation] Add to validate on start push.
|
|
19
|
+
* @param {boolean} [config.disablePushgateway] Disable pushing to Pushgateway (use HTTP scraping instead)
|
|
20
|
+
*/
|
|
21
|
+
constructor(config?: {
|
|
22
|
+
appName?: string | undefined;
|
|
23
|
+
dynoId?: string | undefined;
|
|
24
|
+
processType?: string | undefined;
|
|
25
|
+
enabled?: boolean | undefined;
|
|
26
|
+
logValues?: boolean | undefined;
|
|
27
|
+
pushgatewayUrl?: string | undefined;
|
|
28
|
+
pushgatewaySecret?: string | undefined;
|
|
29
|
+
intervalSec?: number | undefined;
|
|
30
|
+
removeOldMetrics?: boolean | undefined;
|
|
31
|
+
startupValidation?: Function | undefined;
|
|
32
|
+
disablePushgateway?: boolean | undefined;
|
|
33
|
+
});
|
|
34
|
+
appName: string;
|
|
35
|
+
dynoId: string;
|
|
36
|
+
processType: string;
|
|
37
|
+
enabled: boolean;
|
|
38
|
+
logValues: boolean;
|
|
39
|
+
pushgatewayUrl: string;
|
|
40
|
+
authToken: string;
|
|
41
|
+
intervalSec: number;
|
|
42
|
+
startupValidation: Function | undefined;
|
|
43
|
+
disablePushgateway: boolean;
|
|
44
|
+
removeOldMetrics: boolean;
|
|
45
|
+
prefixLogs: string;
|
|
46
|
+
_registry: client.Registry<"text/plain; version=0.0.4; charset=utf-8">;
|
|
47
|
+
defaultLabels: {
|
|
48
|
+
app: string;
|
|
49
|
+
dyno_id: string;
|
|
50
|
+
process_type: string;
|
|
51
|
+
};
|
|
52
|
+
gateway: any;
|
|
53
|
+
gauges: {};
|
|
54
|
+
counters: {};
|
|
55
|
+
countersFunctions: {};
|
|
56
|
+
/** @type {Object<string, function(): number | Promise<number>>} */
|
|
57
|
+
gaugeUpdaters: {
|
|
58
|
+
[x: string]: () => number | Promise<number>;
|
|
59
|
+
};
|
|
60
|
+
keepProcessAliveWhenDisabled: boolean;
|
|
61
|
+
/**
|
|
62
|
+
* Create a gauge metric.
|
|
63
|
+
* @param {Object} options - Gauge configuration
|
|
64
|
+
* @param {string} options.name - Name of the gauge
|
|
65
|
+
* @param {string} options.help - Help text describing the gauge
|
|
66
|
+
* @param {function(): number|Promise<number>} [options.updateFn] - Optional function returning the gauge value
|
|
67
|
+
* @param {string[]} [options.labelNames] - Optional custom label names
|
|
68
|
+
* @returns {import('prom-client').Gauge} The created Prometheus gauge
|
|
69
|
+
*/
|
|
70
|
+
createGauge: ({ name, help, updateFn, labelNames, }: {
|
|
71
|
+
name: string;
|
|
72
|
+
help: string;
|
|
73
|
+
updateFn?: (() => number | Promise<number>) | undefined;
|
|
74
|
+
labelNames?: string[] | undefined;
|
|
75
|
+
}) => import('prom-client').Gauge;
|
|
76
|
+
/**
|
|
77
|
+
* Create a Prometheus Counter metric.
|
|
78
|
+
*
|
|
79
|
+
* @param {Object} params - Counter configuration
|
|
80
|
+
* @param {string} params.name - Metric name
|
|
81
|
+
* @param {string} params.help - Metric description
|
|
82
|
+
* @param {string[]} [params.labelNames] - Optional list of label names. Defaults to this.defaultLabels keys.
|
|
83
|
+
*
|
|
84
|
+
* @returns {(labels?: Object, incrementValue?: number) => void}
|
|
85
|
+
* A function to increment the counter.
|
|
86
|
+
* Usage: (labels?, incrementValue?)
|
|
87
|
+
*/
|
|
88
|
+
createCounter({ name, help, labelNames }: {
|
|
89
|
+
name: string;
|
|
90
|
+
help: string;
|
|
91
|
+
labelNames?: string[] | undefined;
|
|
92
|
+
}): (labels?: Object, incrementValue?: number) => void;
|
|
93
|
+
/**
|
|
94
|
+
* Clear all collected counters
|
|
95
|
+
*/
|
|
96
|
+
clearAllCounters: () => void;
|
|
97
|
+
/**
|
|
98
|
+
* Push all gauges and counters to PushGateway and optionally log.
|
|
99
|
+
*/
|
|
100
|
+
_pushMetrics: () => Promise<void>;
|
|
101
|
+
_startPush: (interval?: number, customPushMetics?: undefined) => void;
|
|
102
|
+
_idleInterval: NodeJS.Timer | null | undefined;
|
|
103
|
+
pushMetrics: () => Promise<void>;
|
|
104
|
+
/**
|
|
105
|
+
* Start periodic metrics collection and push.
|
|
106
|
+
*
|
|
107
|
+
* This method wraps the internal `_startPush` method.
|
|
108
|
+
* If a `customPushMetrics` function is provided, it will be executed
|
|
109
|
+
* at the given interval instead of the default `pushMetrics` behavior.
|
|
110
|
+
*
|
|
111
|
+
* @param {number} [interval=this.intervalSec] - Interval in seconds between pushes.
|
|
112
|
+
* @param {() => void | Promise<void>} [customPushMetrics] - Optional custom push function. If provided, Prometheus push is skipped.
|
|
113
|
+
*/
|
|
114
|
+
startPush: (interval?: number | undefined, customPushMetics?: undefined) => void;
|
|
115
|
+
/**
|
|
116
|
+
* Cleanup metrics and exit process.
|
|
117
|
+
* @returns {Promise<void>}
|
|
118
|
+
*/
|
|
119
|
+
cleanup: () => Promise<void>;
|
|
120
|
+
/**
|
|
121
|
+
* Remove old/stale dyno/instance metrics from PushGateway.
|
|
122
|
+
*
|
|
123
|
+
* Compares existing PushGateway metrics for this job and deletes any instances
|
|
124
|
+
* that do not match the current dynoId.
|
|
125
|
+
*
|
|
126
|
+
* @param {boolean} removeOldMetrics If true, performs cleanup; otherwise does nothing
|
|
127
|
+
* @returns {Promise<void>}
|
|
128
|
+
* @private
|
|
129
|
+
*/
|
|
130
|
+
private _clearOldWorkers;
|
|
131
|
+
/**
|
|
132
|
+
* On shutdown: optionally delete this instance's metrics from VictoriaMetrics (by app, dyno_id, process_type).
|
|
133
|
+
* @returns {Promise<void>}
|
|
134
|
+
*/
|
|
135
|
+
gatewayDelete: () => Promise<void>;
|
|
136
|
+
/**
|
|
137
|
+
* Call VictoriaMetrics delete_series API to remove all series matching this instance's labels (app, dyno_id, process_type).
|
|
138
|
+
* @private
|
|
139
|
+
*/
|
|
140
|
+
private _deleteFromVMByLabels;
|
|
141
|
+
/**
|
|
142
|
+
* Push registry to configured URL (VM-agent). POST Prometheus text format + Basic auth.
|
|
143
|
+
*
|
|
144
|
+
* @param {object} [params] Unused; kept for API compatibility.
|
|
145
|
+
* @returns {Promise<void>}
|
|
146
|
+
*/
|
|
147
|
+
gatewayPush: (params?: object | undefined) => Promise<void>;
|
|
148
|
+
/**
|
|
149
|
+
* POST registry (Prometheus text format) to VM-agent. VM-agent accepts push at /api/v1/import/prometheus; /metrics is GET (scrape) only.
|
|
150
|
+
* @private
|
|
151
|
+
*/
|
|
152
|
+
private _pushToVMAgent;
|
|
153
|
+
/**
|
|
154
|
+
* Merge the default metric labels (`app`, `dyno_id`, `process_type`)
|
|
155
|
+
* with custom label names.
|
|
156
|
+
*
|
|
157
|
+
* @param {string[]} labels Additional label names
|
|
158
|
+
* @returns {string[]} Combined label names
|
|
159
|
+
*/
|
|
160
|
+
withDefaultLabels: (labels?: string[]) => string[];
|
|
161
|
+
getDefaultLabels: (labels?: any[]) => {
|
|
162
|
+
app: string;
|
|
163
|
+
dyno_id: string;
|
|
164
|
+
process_type: string;
|
|
165
|
+
};
|
|
166
|
+
_setCleanupHandlers: () => void;
|
|
167
|
+
get metricsEnabled(): boolean;
|
|
168
|
+
get metricsLogValues(): boolean;
|
|
169
|
+
get registry(): client.Registry<"text/plain; version=0.0.4; charset=utf-8">;
|
|
170
|
+
getMetricsAsString(): Promise<string>;
|
|
171
|
+
metricsMiddleware(): (req: any, res: any) => Promise<void>;
|
|
172
|
+
}
|
|
173
|
+
import client = require("prom-client");
|
|
174
|
+
//# sourceMappingURL=baseMetricsClient.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"baseMetricsClient.d.ts","sourceRoot":"","sources":["../../src/metrics/baseMetricsClient.js"],"names":[],"mappings":"AAKA;;;;GAIG;AACH;IACE;;;;;;;;;;;;;OAaG;IACH;QAZ2B,OAAO;QACP,MAAM;QACN,WAAW;QACV,OAAO;QACP,SAAS;QACV,cAAc;QACd,iBAAiB;QACjB,WAAW;QACV,gBAAgB;QACf,iBAAiB;QAClB,kBAAkB;OAoD7C;IAjDC,gBAA4E;IAC5E,eAAqE;IACrE,oBAG6B;IAC7B,iBAAuE;IACvE,mBAC+D;IAC/D,uBACoE;IACpE,kBAC0E;IAC1E,oBAGI;IACJ,wCAAiD;IACjD,4BAEoD;IACpD,0BAEmD;IAEnD,mBAAyF;IAEzF,uEAAsC;IAGtC;;;;MAIC;IAGD,aAAmB;IACnB,WAAgB;IAChB,aAAkB;IAClB,sBAA2B;IAE3B,mEAAmE;IACnE;YADkB,MAAM,SAAc,MAAM,GAAG,QAAQ,MAAM,CAAC;MACvC;IAKvB,sCAAwC;IAG1C;;;;;;;;OAQG;IACH;QAN2B,IAAI,EAApB,MAAM;QACU,IAAI,EAApB,MAAM;QACuC,QAAQ,UAAzC,MAAM,GAAC,QAAQ,MAAM,CAAC;QACf,UAAU;UAC3B,OAAO,aAAa,EAAE,KAAK,CAuBvC;IAED;;;;;;;;;;;OAWG;IACH;QAR0B,IAAI,EAAnB,MAAM;QACS,IAAI,EAAnB,MAAM;QACY,UAAU;kBAEhB,MAAM,mBAAmB,MAAM,KAAK,IAAI,CAuB9D;IAED;;OAEG;IACH,6BAKC;IAED;;OAEG;IACH,kCAiCC;IAED,sEAmDC;IA/CK,+CAA0D;IAiDhE,iCAEC;IAED;;;;;;;;;OASG;IACH,iFAEC;IAED;;;OAGG;IACH,eAFa,QAAQ,IAAI,CAAC,CAOzB;IAED;;;;;;;;;OASG;IACH,yBAEC;IAED;;;OAGG;IACH,qBAFa,QAAQ,IAAI,CAAC,CAezB;IAED;;;OAGG;IACH,8BAkDC;IAED;;;;;OAKG;IACH,8CAFa,QAAQ,IAAI,CAAC,CAgBzB;IAED;;;OAGG;IACH,uBAoDC;IAED;;;;;;OAMG;IACH,6BAHW,MAAM,EAAE,KACN,MAAM,EAAE,CAIpB;IAED;;;;MAEC;IAED,gCAGC;IAID,8BAEC;IAED,gCAEC;IAED,4EAEC;IAED,sCAEC;IAED,2DAWC;CACF"}
|