fix metrics tracking

This commit is contained in:
Pas 2025-07-17 11:18:15 -06:00
parent 152c46dec8
commit d229a2fc84
4 changed files with 43 additions and 46 deletions

View file

@ -15,12 +15,7 @@ export default defineTask({
try { try {
// Clear and reinitialize daily metrics // Clear and reinitialize daily metrics
if (global.metrics_daily) { await setupMetrics('daily', true);
global.metrics_daily.clear();
await setupMetrics('daily');
} else {
await setupMetrics('daily');
}
const executionTime = Date.now() - startTime; const executionTime = Date.now() - startTime;
logger.info(`Daily metrics cleared in ${executionTime}ms`); logger.info(`Daily metrics cleared in ${executionTime}ms`);

View file

@ -15,12 +15,7 @@ export default defineTask({
try { try {
// Clear and reinitialize monthly metrics // Clear and reinitialize monthly metrics
if (global.metrics_monthly) { await setupMetrics('monthly', true);
global.metrics_monthly.clear();
await setupMetrics('monthly');
} else {
await setupMetrics('monthly');
}
const executionTime = Date.now() - startTime; const executionTime = Date.now() - startTime;
logger.info(`Monthly metrics cleared in ${executionTime}ms`); logger.info(`Monthly metrics cleared in ${executionTime}ms`);

View file

@ -15,12 +15,7 @@ export default defineTask({
try { try {
// Clear and reinitialize weekly metrics // Clear and reinitialize weekly metrics
if (global.metrics_weekly) { await setupMetrics('weekly', true);
global.metrics_weekly.clear();
await setupMetrics('weekly');
} else {
await setupMetrics('weekly');
}
const executionTime = Date.now() - startTime; const executionTime = Date.now() - startTime;
logger.info(`Weekly metrics cleared in ${executionTime}ms`); logger.info(`Weekly metrics cleared in ${executionTime}ms`);

View file

@ -54,52 +54,53 @@ export function getRegistry(interval: 'default' | 'daily' | 'weekly' | 'monthly'
} }
async function createMetrics(registry: Registry, interval: string): Promise<Metrics> { async function createMetrics(registry: Registry, interval: string): Promise<Metrics> {
const suffix = interval !== 'default' ? `_${interval}` : '';
const newMetrics = { const newMetrics = {
user: new Counter({ user: new Counter({
name: `mw_user_count_${interval !== 'default' ? interval : ''}`, name: `mw_user_count${suffix}`,
help: `Number of users by namespace (${interval})`, help: `Number of users by namespace (${interval})`,
labelNames: ['namespace'], labelNames: ['namespace'],
registers: [registry] registers: [registry]
}), }),
captchaSolves: new Counter({ captchaSolves: new Counter({
name: `mw_captcha_solves_${interval !== 'default' ? interval : ''}`, name: `mw_captcha_solves${suffix}`,
help: `Number of captcha solves by success status (${interval})`, help: `Number of captcha solves by success status (${interval})`,
labelNames: ['success'], labelNames: ['success'],
registers: [registry] registers: [registry]
}), }),
providerHostnames: new Counter({ providerHostnames: new Counter({
name: `mw_provider_hostname_count_${interval !== 'default' ? interval : ''}`, name: `mw_provider_hostname_count${suffix}`,
help: `Number of requests by provider hostname (${interval})`, help: `Number of requests by provider hostname (${interval})`,
labelNames: ['hostname'], labelNames: ['hostname'],
registers: [registry] registers: [registry]
}), }),
providerStatuses: new Counter({ providerStatuses: new Counter({
name: `mw_provider_status_count_${interval !== 'default' ? interval : ''}`, name: `mw_provider_status_count${suffix}`,
help: `Number of provider requests by status (${interval})`, help: `Number of provider requests by status (${interval})`,
labelNames: ['provider_id', 'status'], labelNames: ['provider_id', 'status'],
registers: [registry] registers: [registry]
}), }),
watchMetrics: new Counter({ watchMetrics: new Counter({
name: `mw_media_watch_count_${interval !== 'default' ? interval : ''}`, name: `mw_media_watch_count${suffix}`,
help: `Number of media watch events (${interval})`, help: `Number of media watch events (${interval})`,
labelNames: ['title', 'tmdb_full_id', 'provider_id', 'success'], labelNames: ['title', 'tmdb_full_id', 'provider_id', 'success'],
registers: [registry] registers: [registry]
}), }),
toolMetrics: new Counter({ toolMetrics: new Counter({
name: `mw_provider_tool_count_${interval !== 'default' ? interval : ''}`, name: `mw_provider_tool_count${suffix}`,
help: `Number of provider tool usages (${interval})`, help: `Number of provider tool usages (${interval})`,
labelNames: ['tool'], labelNames: ['tool'],
registers: [registry] registers: [registry]
}), }),
httpRequestDuration: new Histogram({ httpRequestDuration: new Histogram({
name: `http_request_duration_seconds_${interval !== 'default' ? interval : ''}`, name: `http_request_duration_seconds${suffix}`,
help: `request duration in seconds (${interval})`, help: `request duration in seconds (${interval})`,
labelNames: ['method', 'route', 'status_code'], labelNames: ['method', 'route', 'status_code'],
buckets: [0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10], buckets: [0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10],
registers: [registry] registers: [registry]
}), }),
httpRequestSummary: new Summary({ httpRequestSummary: new Summary({
name: `http_request_summary_seconds_${interval !== 'default' ? interval : ''}`, name: `http_request_summary_seconds${suffix}`,
help: `request duration in seconds summary (${interval})`, help: `request duration in seconds summary (${interval})`,
labelNames: ['method', 'route', 'status_code'], labelNames: ['method', 'route', 'status_code'],
percentiles: [0.01, 0.05, 0.5, 0.9, 0.95, 0.99, 0.999], percentiles: [0.01, 0.05, 0.5, 0.9, 0.95, 0.99, 0.999],
@ -198,29 +199,40 @@ process.on('SIGINT', async () => {
process.exit(0); process.exit(0);
}); });
export async function setupMetrics(interval: 'default' | 'daily' | 'weekly' | 'monthly' = 'default') { let defaultMetricsRegistered = false;
const metricsRegistered: Record<string, boolean> = {
default: false,
daily: false,
weekly: false,
monthly: false,
};
export async function setupMetrics(interval: 'default' | 'daily' | 'weekly' | 'monthly' = 'default', clear: boolean = false) {
try { try {
log.info(`Setting up ${interval} metrics...`, { evt: 'start', interval }); log.info(`Setting up ${interval} metrics...`, { evt: 'start', interval });
const registry = registries[interval]; const registry = registries[interval];
// Only clear registry if explicitly requested (e.g., by scheduled task)
// Clear registry if it already exists if (clear) {
registry.clear(); registry.clear();
metricsRegistered[interval] = false; // allow re-registration after clear
// Enable default Node.js metrics collection for default registry only if (interval === 'default') defaultMetricsRegistered = false;
if (interval === 'default') { }
collectDefaultMetrics({ // Only register metrics once per registry per process
register: registry, if (!metricsRegistered[interval]) {
prefix: '', // No prefix to match the example output if (interval === 'default' && !defaultMetricsRegistered) {
eventLoopMonitoringPrecision: 1, // Ensure eventloop metrics are collected collectDefaultMetrics({
gcDurationBuckets: [0.001, 0.01, 0.1, 1, 2, 5], // Match the example buckets register: registry,
}); prefix: '', // No prefix to match the example output
eventLoopMonitoringPrecision: 1, // Ensure eventloop metrics are collected
gcDurationBuckets: [0.001, 0.01, 0.1, 1, 2, 5], // Match the example buckets
});
defaultMetricsRegistered = true;
}
metricsStore[interval] = await createMetrics(registry, interval);
metricsRegistered[interval] = true;
log.info(`Created new ${interval} metrics...`, { evt: 'created', interval });
} }
// Create new metrics instance
metricsStore[interval] = await createMetrics(registry, interval);
log.info(`Created new ${interval} metrics...`, { evt: 'created', interval });
// Load saved metrics // Load saved metrics
const savedMetrics = await loadMetricsFromFile(interval); const savedMetrics = await loadMetricsFromFile(interval);
if (savedMetrics.length > 0) { if (savedMetrics.length > 0) {
@ -256,8 +268,8 @@ export async function setupMetrics(interval: 'default' | 'daily' | 'weekly' | 'm
case 'http_request_duration_seconds': case 'http_request_duration_seconds':
// For histograms, special handling for sum and count // For histograms, special handling for sum and count
if ( if (
value.metricName === `http_request_duration_seconds_${interval !== 'default' ? interval + '_' : ''}sum` || value.metricName === `http_request_duration_seconds${interval !== 'default' ? `_${interval}` : ''}sum` ||
value.metricName === `http_request_duration_seconds_${interval !== 'default' ? interval + '_' : ''}count` value.metricName === `http_request_duration_seconds${interval !== 'default' ? `_${interval}` : ''}count`
) { ) {
metrics.httpRequestDuration.observe(value.labels, value.value); metrics.httpRequestDuration.observe(value.labels, value.value);
} }