PostgreSQL COUNT() returns bigint type which Drizzle returns as a string. This caused prom-client Gauge.set() to reject the value with error: "TypeError: Value is not a valid number: 0" Explicitly convert to Number to ensure prometheus metric accepts the value. Related: BARAAA-64 - DB migrations and connection fixes Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
42 lines
1.3 KiB
TypeScript
42 lines
1.3 KiB
TypeScript
import type { Pool } from 'pg';
|
|
import { drizzle } from 'drizzle-orm/node-postgres';
|
|
import { roomMembers } from '../db/schema.js';
|
|
import { sql } from 'drizzle-orm';
|
|
import { roomsActiveGauge, dbQueryDurationHistogram } from '../lib/metrics.js';
|
|
|
|
/**
|
|
* Collect active rooms metric from database
|
|
*/
|
|
async function collectRoomsActiveMetric(pool: Pool): Promise<void> {
|
|
const db = drizzle(pool);
|
|
const startTime = performance.now();
|
|
|
|
try {
|
|
// Count distinct rooms that have at least one member
|
|
const result = await db
|
|
.select({ count: sql<number>`count(distinct ${roomMembers.roomId})` })
|
|
.from(roomMembers);
|
|
|
|
const count = Number(result[0]?.count) || 0;
|
|
roomsActiveGauge.set(count);
|
|
|
|
const duration = (performance.now() - startTime) / 1000;
|
|
dbQueryDurationHistogram.observe({ operation: 'count_active_rooms' }, duration);
|
|
} catch (err) {
|
|
console.error('Failed to collect rooms active metric:', err);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Start periodic metrics collection
|
|
* Updates room metrics every 30 seconds
|
|
*/
|
|
export function startMetricsCollector(pool: Pool): void {
|
|
// Collect immediately on startup
|
|
collectRoomsActiveMetric(pool).catch(console.error);
|
|
|
|
// Then collect every 30 seconds
|
|
setInterval(() => {
|
|
collectRoomsActiveMetric(pool).catch(console.error);
|
|
}, 30_000);
|
|
}
|