From 5454942a2c14e2ae6947fe3ace0f36bec4119234 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Sat, 7 Sep 2024 08:52:02 -0500 Subject: [PATCH] Update Prometheus metrics to conform to best practices --- src/controllers/metrics.ts | 3 +- src/controllers/nostr/relay.ts | 8 ++--- src/db/KyselyLogger.ts | 6 ++-- src/firehose.ts | 4 +-- src/metrics.ts | 53 +++++++++++++---------------- src/middleware/metricsMiddleware.ts | 6 ++-- src/pipeline.ts | 6 ++-- src/storages/EventsDB.ts | 4 +-- 8 files changed, 42 insertions(+), 48 deletions(-) diff --git a/src/controllers/metrics.ts b/src/controllers/metrics.ts index e85294c0..567a3170 100644 --- a/src/controllers/metrics.ts +++ b/src/controllers/metrics.ts @@ -2,12 +2,11 @@ import { register } from 'prom-client'; import { AppController } from '@/app.ts'; import { DittoDB } from '@/db/DittoDB.ts'; -import { dbAvailableConnectionsGauge, dbPoolSizeGauge } from '@/metrics.ts'; +import { dbAvailableConnectionsGauge } from '@/metrics.ts'; /** Prometheus/OpenMetrics controller. */ export const metricsController: AppController = async (c) => { // Update some metrics at request time. - dbPoolSizeGauge.set(DittoDB.poolSize); dbAvailableConnectionsGauge.set(DittoDB.availableConnections); const metrics = await register.metrics(); diff --git a/src/controllers/nostr/relay.ts b/src/controllers/nostr/relay.ts index 583fd153..9f47b382 100644 --- a/src/controllers/nostr/relay.ts +++ b/src/controllers/nostr/relay.ts @@ -12,7 +12,7 @@ import { import { AppController } from '@/app.ts'; import { Conf } from '@/config.ts'; import { relayInfoController } from '@/controllers/nostr/relay-info.ts'; -import { relayConnectionsGauge, relayEventCounter, relayMessageCounter } from '@/metrics.ts'; +import { relayConnectionsGauge, relayEventsCounter, relayMessagesCounter } from '@/metrics.ts'; import * as pipeline from '@/pipeline.ts'; import { RelayError } from '@/RelayError.ts'; import { Storages } from '@/storages.ts'; @@ -54,10 +54,10 @@ function connectStream(socket: WebSocket, ip: string | undefined) { const result = n.json().pipe(n.clientMsg()).safeParse(e.data); if (result.success) { - relayMessageCounter.inc({ verb: result.data[0] }); + relayMessagesCounter.inc({ verb: result.data[0] }); handleMsg(result.data); } else { - relayMessageCounter.inc(); + relayMessagesCounter.inc(); send(['NOTICE', 'Invalid message.']); } }; @@ -130,7 +130,7 @@ function connectStream(socket: WebSocket, ip: string | undefined) { /** Handle EVENT. Store the event. */ async function handleEvent([_, event]: NostrClientEVENT): Promise { - relayEventCounter.inc({ kind: event.kind.toString() }); + relayEventsCounter.inc({ kind: event.kind.toString() }); try { // This will store it (if eligible) and run other side-effects. await pipeline.handleEvent(event, AbortSignal.timeout(1000)); diff --git a/src/db/KyselyLogger.ts b/src/db/KyselyLogger.ts index 3b5b4398..72167e21 100644 --- a/src/db/KyselyLogger.ts +++ b/src/db/KyselyLogger.ts @@ -1,6 +1,6 @@ import { Stickynotes } from '@soapbox/stickynotes'; import { Logger } from 'kysely'; -import { dbQueryCounter, dbQueryTimeHistogram } from '@/metrics.ts'; +import { dbQueriesCounter, dbQueryDurationHistogram } from '@/metrics.ts'; /** Log the SQL for queries. */ export const KyselyLogger: Logger = (event) => { @@ -9,8 +9,8 @@ export const KyselyLogger: Logger = (event) => { const { query, queryDurationMillis } = event; const { sql, parameters } = query; - dbQueryCounter.inc(); - dbQueryTimeHistogram.observe(queryDurationMillis); + dbQueriesCounter.inc(); + dbQueryDurationHistogram.observe(queryDurationMillis); console.debug( sql, diff --git a/src/firehose.ts b/src/firehose.ts index 86d19f74..85e3dc89 100644 --- a/src/firehose.ts +++ b/src/firehose.ts @@ -2,7 +2,7 @@ import { Semaphore } from '@lambdalisue/async'; import { Stickynotes } from '@soapbox/stickynotes'; import { Conf } from '@/config.ts'; -import { firehoseEventCounter } from '@/metrics.ts'; +import { firehoseEventsCounter } from '@/metrics.ts'; import { Storages } from '@/storages.ts'; import { nostrNow } from '@/utils.ts'; @@ -23,7 +23,7 @@ export async function startFirehose(): Promise { if (msg[0] === 'EVENT') { const event = msg[2]; console.debug(`NostrEvent<${event.kind}> ${event.id}`); - firehoseEventCounter.inc({ kind: event.kind }); + firehoseEventsCounter.inc({ kind: event.kind }); sem.lock(async () => { try { diff --git a/src/metrics.ts b/src/metrics.ts index c1fb8238..ee73d083 100644 --- a/src/metrics.ts +++ b/src/metrics.ts @@ -1,86 +1,81 @@ import { Counter, Gauge, Histogram } from 'prom-client'; -export const httpRequestCounter = new Counter({ - name: 'http_requests_total', +export const httpRequestsCounter = new Counter({ + name: 'ditto_http_requests_total', help: 'Total number of HTTP requests', labelNames: ['method'], }); -export const httpResponseCounter = new Counter({ - name: 'http_responses_total', +export const httpResponsesCounter = new Counter({ + name: 'ditto_http_responses_total', help: 'Total number of HTTP responses', labelNames: ['method', 'path', 'status'], }); export const streamingConnectionsGauge = new Gauge({ - name: 'streaming_connections', + name: 'ditto_streaming_connections', help: 'Number of active connections to the streaming API', }); export const fetchCounter = new Counter({ - name: 'fetch_total', + name: 'ditto_fetch_total', help: 'Total number of fetch requests', labelNames: ['method'], }); -export const firehoseEventCounter = new Counter({ - name: 'firehose_events_total', +export const firehoseEventsCounter = new Counter({ + name: 'ditto_firehose_events_total', help: 'Total number of Nostr events processed by the firehose', labelNames: ['kind'], }); -export const pipelineEventCounter = new Counter({ - name: 'pipeline_events_total', +export const pipelineEventsCounter = new Counter({ + name: 'ditto_pipeline_events_total', help: 'Total number of Nostr events processed by the pipeline', labelNames: ['kind'], }); -export const policyEventCounter = new Counter({ - name: 'policy_events_total', +export const policyEventsCounter = new Counter({ + name: 'ditto_policy_events_total', help: 'Total number of policy OK responses', labelNames: ['ok'], }); -export const relayEventCounter = new Counter({ - name: 'relay_events_total', +export const relayEventsCounter = new Counter({ + name: 'ditto_relay_events_total', help: 'Total number of EVENT messages processed by the relay', labelNames: ['kind'], }); -export const relayMessageCounter = new Counter({ - name: 'relay_messages_total', +export const relayMessagesCounter = new Counter({ + name: 'ditto_relay_messages_total', help: 'Total number of Nostr messages processed by the relay', labelNames: ['verb'], }); export const relayConnectionsGauge = new Gauge({ - name: 'relay_connections', + name: 'ditto_relay_connections', help: 'Number of active connections to the relay', }); -export const dbQueryCounter = new Counter({ - name: 'db_query_total', +export const dbQueriesCounter = new Counter({ + name: 'ditto_db_queries_total', help: 'Total number of database queries', labelNames: ['kind'], }); -export const dbEventCounter = new Counter({ - name: 'db_events_total', +export const dbEventsCounter = new Counter({ + name: 'ditto_db_events_total', help: 'Total number of database inserts', labelNames: ['kind'], }); -export const dbPoolSizeGauge = new Gauge({ - name: 'db_pool_size', - help: 'Number of connections in the database pool', -}); - export const dbAvailableConnectionsGauge = new Gauge({ - name: 'db_available_connections', + name: 'ditto_db_available_connections', help: 'Number of available connections in the database pool', }); -export const dbQueryTimeHistogram = new Histogram({ - name: 'db_query_duration_ms', +export const dbQueryDurationHistogram = new Histogram({ + name: 'ditto_db_query_duration_ms', help: 'Duration of database queries', }); diff --git a/src/middleware/metricsMiddleware.ts b/src/middleware/metricsMiddleware.ts index 6cf0e6de..e8a30972 100644 --- a/src/middleware/metricsMiddleware.ts +++ b/src/middleware/metricsMiddleware.ts @@ -1,12 +1,12 @@ import { MiddlewareHandler } from '@hono/hono'; -import { httpRequestCounter, httpResponseCounter } from '@/metrics.ts'; +import { httpRequestsCounter, httpResponsesCounter } from '@/metrics.ts'; /** Prometheus metrics middleware that tracks HTTP requests by methods and responses by status code. */ export const metricsMiddleware: MiddlewareHandler = async (c, next) => { // HTTP Request. const { method } = c.req; - httpRequestCounter.inc({ method }); + httpRequestsCounter.inc({ method }); // Wait for other handlers to run. await next(); @@ -16,5 +16,5 @@ export const metricsMiddleware: MiddlewareHandler = async (c, next) => { // Get a parameterized path name like `/posts/:id` instead of `/posts/1234`. // Tries to find actual route names first before falling back on potential middleware handlers like `app.use('*')`. const path = c.req.matchedRoutes.find((r) => r.method !== 'ALL')?.path ?? c.req.routePath; - httpResponseCounter.inc({ method, status, path }); + httpResponsesCounter.inc({ method, status, path }); }; diff --git a/src/pipeline.ts b/src/pipeline.ts index 2fb18649..15c1ef34 100644 --- a/src/pipeline.ts +++ b/src/pipeline.ts @@ -8,7 +8,7 @@ import { Conf } from '@/config.ts'; import { DittoDB } from '@/db/DittoDB.ts'; import { deleteAttachedMedia } from '@/db/unattached-media.ts'; import { DittoEvent } from '@/interfaces/DittoEvent.ts'; -import { pipelineEventCounter, policyEventCounter } from '@/metrics.ts'; +import { pipelineEventsCounter, policyEventsCounter } from '@/metrics.ts'; import { RelayError } from '@/RelayError.ts'; import { AdminSigner } from '@/signers/AdminSigner.ts'; import { hydrateEvents } from '@/storages/hydrate.ts'; @@ -40,7 +40,7 @@ async function handleEvent(event: DittoEvent, signal: AbortSignal): Promise ${event.id}`); - pipelineEventCounter.inc({ kind: event.kind }); + pipelineEventsCounter.inc({ kind: event.kind }); if (event.kind !== 24133) { await policyFilter(event); @@ -71,7 +71,7 @@ async function policyFilter(event: NostrEvent): Promise { try { const result = await policyWorker.call(event); - policyEventCounter.inc({ ok: String(result[2]) }); + policyEventsCounter.inc({ ok: String(result[2]) }); debug(JSON.stringify(result)); RelayError.assert(result); } catch (e) { diff --git a/src/storages/EventsDB.ts b/src/storages/EventsDB.ts index 07be8067..7cbd9c22 100644 --- a/src/storages/EventsDB.ts +++ b/src/storages/EventsDB.ts @@ -17,7 +17,7 @@ import { nip27 } from 'nostr-tools'; import { Conf } from '@/config.ts'; import { DittoDatabase } from '@/db/DittoDB.ts'; -import { dbEventCounter } from '@/metrics.ts'; +import { dbEventsCounter } from '@/metrics.ts'; import { RelayError } from '@/RelayError.ts'; import { purifyEvent } from '@/storages/hydrate.ts'; import { isNostrId, isURL } from '@/utils.ts'; @@ -73,7 +73,7 @@ class EventsDB implements NStore { async event(event: NostrEvent, opts: { signal?: AbortSignal; timeout?: number } = {}): Promise { event = purifyEvent(event); this.console.debug('EVENT', JSON.stringify(event)); - dbEventCounter.inc({ kind: event.kind }); + dbEventsCounter.inc({ kind: event.kind }); if (await this.isDeletedAdmin(event)) { throw new RelayError('blocked', 'event deleted by admin');