diff --git a/src/files.js b/src/files.js index 18368843008ac6e71b32d55a3c70d9d37ca7454f..cc9703c909242e077a874aa2b6c87a8153b9185d 100644 --- a/src/files.js +++ b/src/files.js @@ -7,12 +7,19 @@ import { NotFoundError } from './errors.js' import * as redis from './redis.js' import zlib from 'node:zlib' import { promisify } from 'node:util' +import { Gauge } from 'prom-client' + const gzip = promisify(zlib.gzip) const compressFileSize = Number(process.env.COMPRESS_FILE_SIZE) const compressionMimeTypes = (process.env.COMPRESS_FILE_TYPES || '').replace(/([.+*?^$()[\]{}|])/g, '\\$1').split(' ') const compressionWhitelistRegex = new RegExp(`^(${compressionMimeTypes.join('|')})($|;)`, 'i') +export const fileCacheSizeGauge = new Gauge({ + name: 'file_cache_size', + help: 'Number of entries in file cache' +}) + export function createWritable (body) { if (typeof body !== 'string' && !(body instanceof Buffer)) return JSON.stringify(body) return body @@ -96,6 +103,7 @@ export function getFile ({ version, path }) { if (body) { logger.debug(`[Files] Resolve from redis: ${key}`) + fileCacheSizeGauge.inc() return (cache.getCache()[key] = { body, ...JSON.parse(meta) }) } } @@ -113,6 +121,7 @@ export function getFile ({ version, path }) { // overwrite cache with synchronous data logger.debug(`[Files] Store in memory: ${key}`) + fileCacheSizeGauge.inc() return (cache.getCache()[key] = dataFromServer) })() diff --git a/src/manifests.js b/src/manifests.js index 937b0bfb0f8604295a169922d0435aa585cba4d4..bf014cc491f3587d32d595cde20fe2eb49eb0db0 100644 --- a/src/manifests.js +++ b/src/manifests.js @@ -27,7 +27,7 @@ export async function fetchViteManifests () { return viteManifests.reduce((memo, manifest) => Object.assign(memo, manifest), {}) } -export function getViteManifests ({ version }) { +export async function getViteManifests ({ version }) { return cache.get(getRedisKey({ version, name: 'viteManifests' }), () => fetchViteManifests()) } diff --git a/src/version.js b/src/version.js index 387f259fc00aea1da8369881454cbbe9259a0b4b..990dfcbfffbae9de579b17fcb8cd1c9225e80960 100644 --- a/src/version.js +++ b/src/version.js @@ -3,9 +3,27 @@ import { getRedisKey, hash } from './util.js' import { logger } from './logger.js' import * as cache from './cache.js' import * as redis from './redis.js' +import { Gauge } from 'prom-client' +import { getViteManifests } from './manifests.js' let latestVersion +const manifestFileEntriesGauge = new Gauge({ + name: 'manifest_file_entries', + help: 'Number of entries in merged vite manifest (number of all known files)', + async collect () { + const version = latestVersion + this.set({ version }, Object.keys(await getViteManifests({ version })).length) + }, + labelNames: ['version'] +}) + +const versionUpdateGauge = new Gauge({ + name: 'version_update_event', + help: 'Timestamp of a version update event', + labelNames: ['version'] +}) + export const fetchLatestVersion = async () => { const infos = await Promise.all(configMap.urls.map(async baseUrl => { try { @@ -36,6 +54,7 @@ export async function getLatestVersion () { const version = await redis.client.get(getRedisKey({ name: 'latestVersion' })) if (version) { logger.info(`[Version] Got initial version from redis: '${version}'`) + versionUpdateGauge.setToCurrentTime({ version }) return (latestVersion = version) } } @@ -61,6 +80,7 @@ export function registerLatestVersionListener (client) { if (channel !== key) return logger.info(`[Version] Received 'updateLatestVersion' event. Clearing cache. New version: '${version}'`) await configMap.load() + versionUpdateGauge.setToCurrentTime({ version }) cache.clear() latestVersion = version }) @@ -73,6 +93,12 @@ export async function updateVersionProcessor () { getLatestVersion(), fetchLatestVersion() ]) + + // don't wait for the data, can be done in background + getViteManifests({ fetchedVersion }).then(manifests => { + manifestFileEntriesGauge.set({ version: fetchedVersion }, Object.keys(manifests).length) + }) + if (storedVersion === fetchedVersion) { logger.info(`[Version] No new version has been found. No update needed. Current version: ${storedVersion}`) return fetchedVersion @@ -91,6 +117,7 @@ export async function updateVersionProcessor () { await redis.client.set(getRedisKey({ name: 'prevProcessedVersion' }), fetchedVersion) } } else { + versionUpdateGauge.setToCurrentTime({ version: latestVersion }) // if redis is disabled, this will only be trigger by a setInterval and not from a redis event logger.info('[Version] Clear local cache due to version update.') cache.clear()