diff --git a/notification-service/src/index.ts b/notification-service/src/index.ts index 8ca17d52..9bb3ce25 100644 --- a/notification-service/src/index.ts +++ b/notification-service/src/index.ts @@ -5,6 +5,7 @@ import { Notifier } from "./notifier"; import { createApi } from "./api"; import { pollScoreChanges, PollHandle } from "./listener"; import { ScoreChangedEvent } from "./types"; +import { Metrics } from "./metrics"; /** * Builds a signal handler that lets in-flight event processing finish and @@ -39,10 +40,11 @@ async function main(): Promise { const config = loadConfig(); const store = new Store(config.db_path); - const notifier = new Notifier(config, store); + const metrics = new Metrics(); + const notifier = new Notifier(config, store, metrics); // ── REST API ────────────────────────────────────────────────────────── - const app = createApi(store); + const app = createApi(store, { metrics }); const httpServer = app.listen(config.api_port, () => { console.log(`[api] Listening on port ${config.api_port}`); }); @@ -68,6 +70,7 @@ async function main(): Promise { } await notifier.notifyInvestors(event, investors); + metrics.recordEventProcessed(); }; // ── Start event polling ────────────────────────────────────────────── diff --git a/notification-service/src/notifier.ts b/notification-service/src/notifier.ts index ecfc514b..a1d1ec48 100644 --- a/notification-service/src/notifier.ts +++ b/notification-service/src/notifier.ts @@ -1,6 +1,7 @@ import nodemailer from "nodemailer"; import { ScoreChangedEvent, WebhookPayload, ServiceConfig } from "./types"; import { Store } from "./db"; +import { Metrics } from "./metrics"; /** Upper bound on tracked dedup keys, so long-running processes don't grow unbounded. */ const MAX_TRACKED_NOTIFICATIONS = 5000; @@ -12,6 +13,7 @@ const WEBHOOK_TIMEOUT_MS = 10_000; export class Notifier { private config: ServiceConfig; private store: Store; + private metrics?: Metrics; private transporter?: nodemailer.Transporter; /** * Keys of (event, investor) pairs already successfully notified, to guard @@ -22,9 +24,10 @@ export class Notifier { */ private notifiedRecipients: Set = new Set(); - constructor(config: ServiceConfig, store: Store) { + constructor(config: ServiceConfig, store: Store, metrics?: Metrics) { this.config = config; this.store = store; + this.metrics = metrics; if (config.email_transport) { this.transporter = nodemailer.createTransport(config.email_transport); @@ -82,21 +85,13 @@ export class Notifier { try { if (hasEmail && this.transporter && pref.email) { await this.sendEmail(pref.email, subject, text); - this.store.recordNotification( - addr, - event.project_id, - "email", - event.ledger, - ); + this.store.recordNotification(addr, event.project_id, "email", event.ledger); + this.metrics?.recordNotificationSent(); } if (hasWebhook && pref.webhook_url) { await this.sendWebhook(pref.webhook_url, event, addr); - this.store.recordNotification( - addr, - event.project_id, - "webhook", - event.ledger, - ); + this.store.recordNotification(addr, event.project_id, "webhook", event.ledger); + this.metrics?.recordNotificationSent(); } this.rememberRecipient(recipientKey); } catch (err) {