Skip to content

feat(monitoring): scrape the notification system services - #2165

Merged
LeonardoVieira1630 merged 2 commits into
devfrom
feat/monitoring-notification-system
Sep 25, 2026
Merged

LeonardoVieira1630 merged 2 commits into
devfrom
feat/monitoring-notification-system

Conversation

@LeonardoVieira1630

@LeonardoVieira1630 LeonardoVieira1630 commented Sep 17, 2026 •

Copy link
Copy Markdown
Member

Description

blockful's SPP2 Year 2 roadmap for the ENS DAO (forum post) promises that the notification system's uptime is measured the same way as Anticapture's, by Prometheus, and published quarterly. Today the monitoring stack only scrapes anticapture-* jobs and the notification system only ships logs to Loki.

This PR adds the notification system to the Anticapture monitoring stack:

  • prometheus.yml: four static jobs, notification-subscription-server, notification-dispatcher, notification-consumers, notification-logic-system, 15s interval, targets from NOTIF_SUBSCRIPTION_SERVER_ENDPOINT, NOTIF_DISPATCHER_ENDPOINT, NOTIF_CONSUMERS_ENDPOINT, NOTIF_LOGIC_SYSTEM_ENDPOINT. No bearer: the endpoints are unauthenticated and only reachable through Railway private networking, like authful and relayer.
  • alerts.yml: no rule change. ServiceDown matches every job outside the anticapture-<dao>-* pattern, so the notification-* jobs are covered as-is; the comment now says so. Because the services emit http_server_request_duration_seconds with the same labels as Gateful (see the companion PR below), the generic HighLatency and HighErrorRate alerts cover them too.
  • grafana/dashboards/anticapture.json: new "Notification System" row before Traces, matching the existing rows: scrape status (same shape as General Scrape Status), request rate per service, 5xx per service and route, p99 latency per service. The General Scrape Status panel also picks the new jobs up automatically; its description was updated.
  • README.md: new "Notification system metrics" section documenting the four env vars and which port each one needs.
  • Changesets: minor for @anticapture/observability, plus an empty one for the infra-only files.

Not included: a "notifications dispatched per channel" panel. No such metric exists yet in the notification system; a notifications_delivered_total{channel} counter in consumers is the natural follow-up.

packages/observability (minor): the request metrics the notification services need now live in the shared package instead of being copied per app.

  • createHttpServerMetrics() / createHttpServerRequestDuration(meter): framework-agnostic definition of the standard http_server_request_duration_seconds histogram (name, buckets, http_request_method / http_route / http_response_status_code labels). api, authful, gateful and user-api each define this same histogram by hand today; switching them to the helper is a follow-up.
  • registerFastifyMetrics(server, { exporter }) under the new @anticapture/observability/fastify subpath: serves /metrics and records every request in that histogram, skipping /metrics and /health, with http_route as the route pattern. Only fastify types are imported, so the entry adds no runtime dependency; fastify is an optional peer.
  • Bug fix: createObservabilityProvider registered the OpenTelemetry instrumentations before metrics.setGlobalMeterProvider, so the HTTP auto-instrumentation created its instruments on the API no-op meter and http_server_duration / http_client_duration never reached /metrics. The provider is now set first and passed to registerInstrumentations. Consumers will see those two extra histograms after bumping.
  • collectPrometheusMetrics moved to src/prometheus.ts (re-exported unchanged) so the fastify entry does not pull the whole SDK; CJS output uses tsup code splitting to share one chunk between index.cjs and fastify.cjs.
  • Tests added (vitest): helper, Fastify plugin, and a regression test for the instrumentation fix. Lockfile change is additive (fastify + vitest devDependencies), verified with pnpm install --frozen-lockfile.

Companion PR: blockful/notification-system#276 is in draft until this package is published. It will call registerFastifyMetrics from @anticapture/observability/fastify in each service instead of shipping its own copy. Without it the scrape status panel works but the request rate, 5xx and latency panels stay empty.

Steps to reproduce

Not deployed. After merge, set on the Prometheus Railway service:

NOTIF_SUBSCRIPTION_SERVER_ENDPOINT=${{<subscription-server>.RAILWAY_PRIVATE_DOMAIN}}:<PORT>
NOTIF_DISPATCHER_ENDPOINT=${{<dispatcher>.RAILWAY_PRIVATE_DOMAIN}}:<PORT>
NOTIF_CONSUMERS_ENDPOINT=${{<consumer>.RAILWAY_PRIVATE_DOMAIN}}:<WEBHOOK_API_PORT>
NOTIF_LOGIC_SYSTEM_ENDPOINT=${{<logic-system>.RAILWAY_PRIVATE_DOMAIN}}:<PORT>

Then check Status → Targets for the four notification-* jobs and the "Notification System" row in the Anticapture dashboard.

Related Issue

SPP2 Year 2 roadmap commitment (notification system uptime measured by Prometheus).

Changes

  • New feature implementation
  • Bug fix
  • Code refactoring
  • Documentation
  • Infrastructure
  • Other (please specify)

Changes to Core Features:

  • Have you added an explanation of what your changes do and why you'd like us to include them?
  • Have you written new tests for your core changes, as applicable?
  • Have you successfully run tests with your changes locally?
  • Is it available on the remote server?

Additional Notes

Verification done locally:

  • Rendered prometheus.yml through entrypoint.prometheus.sh with dummy env vars (including the DAO loop) and parsed the result as YAML: 15 jobs, the four notification-* targets substituted correctly. promtool check config was not run: promtool is not installed on my machine and Docker was not running.
  • alerts.yml parses (18 rules).
  • @anticapture/observability: build, typecheck, lint and 4 tests pass; gateful (182 tests) and authful (33) still pass against the changed package; a CommonJS smoke test from the notification-system worktree using the packed tarball confirmed registerFastifyMetrics and the fixed auto-instrumentation both emit.
  • Dashboard JSON parses, panel IDs are unique (90–94 for the new row), Traces shifted down by 12 grid units, file re-formatted with the repo's Prettier so the diff is additive.

🤖 Generated with Claude Code

Add Prometheus jobs for subscription-server, dispatcher, consumers and
logic-system (blockful/notification-system), a Notification System row in
the Grafana dashboard (scrape status, request rate, 5xx, p99 latency) and
document the NOTIF_*_ENDPOINT variables. ServiceDown already matches every
non-DAO job, so the new jobs are covered without a rule change.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@vercel

vercel Bot commented Sep 17, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
anticapture-storybook Ready Ready Preview Sep 17, 2026 7:35pm UTC
1 Skipped Deployment
Project Deployment Actions Updated
anticapture Ignored Ignored Sep 17, 2026 7:35pm UTC

Request Review

@railway-app

railway-app Bot commented Sep 17, 2026 •

Copy link
Copy Markdown

🚅 Deployed to the anticapture-pr-2165 environment in anticapture-infra

Service Status Web Updated
prometheus ✅ Success (View Logs) Sep 17, 2026 at 7:38 pm UTC
grafana ✅ Success (View Logs) Web Sep 17, 2026 at 7:37 pm UTC
gateful ✅ Success (View Logs) Web Sep 17, 2026 at 7:35 pm UTC
authful ✅ Success (View Logs) Web Sep 17, 2026 at 7:34 pm UTC
otelcol ✅ Success (View Logs) Sep 17, 2026 at 7:34 pm UTC
tempo ✅ Success (View Logs) Sep 17, 2026 at 7:34 pm UTC
loki ✅ Success (View Logs) Sep 17, 2026 at 7:33 pm UTC
alertmanager ✅ Success (View Logs) Web Sep 17, 2026 at 7:33 pm UTC
uniswap-indexer-offchain ✅ Success (View Logs) Sep 17, 2026 at 7:17 pm UTC
compound-indexer-offchain ✅ Success (View Logs) Sep 17, 2026 at 7:17 pm UTC
gitcoin-indexer-offchain ✅ Success (View Logs) Sep 17, 2026 at 7:11 pm UTC
ens-indexer-offchain ✅ Success (View Logs) Sep 17, 2026 at 7:11 pm UTC
shutter-indexer-offchain ✅ Success (View Logs) Sep 17, 2026 at 7:09 pm UTC
docs ✅ Success (View Logs) Web Sep 17, 2026 at 6:42 pm UTC
mcp ✅ Success (View Logs) Web Sep 17, 2026 at 6:42 pm UTC
nouns-api ✅ Success (View Logs) Sep 17, 2026 at 6:41 pm UTC
aave-api ✅ Success (View Logs) Sep 17, 2026 at 6:41 pm UTC
obol-api ✅ Success (View Logs) Sep 17, 2026 at 6:40 pm UTC
aave-indexer ✅ Success (View Logs) Sep 17, 2026 at 6:39 pm UTC
compound-api ✅ Success (View Logs) Sep 17, 2026 at 6:39 pm UTC
compound-indexer ✅ Success (View Logs) Sep 17, 2026 at 6:39 pm UTC
shutter-api ✅ Success (View Logs) Sep 17, 2026 at 6:39 pm UTC
address-enrichment ✅ Success (View Logs) Web Sep 17, 2026 at 6:39 pm UTC
shutter-indexer ✅ Success (View Logs) Sep 17, 2026 at 6:39 pm UTC
fluid-api ✅ Success (View Logs) Sep 17, 2026 at 6:39 pm UTC
lil-nouns-api ✅ Success (View Logs) Sep 17, 2026 at 6:39 pm UTC
gitcoin-indexer ✅ Success (View Logs) Sep 17, 2026 at 6:39 pm UTC
obol-indexer ✅ Success (View Logs) Sep 17, 2026 at 6:39 pm UTC
uniswap-indexer ✅ Success (View Logs) Sep 17, 2026 at 6:39 pm UTC
ens-indexer ✅ Success (View Logs) Sep 17, 2026 at 6:39 pm UTC
gitcoin-api ✅ Success (View Logs) Sep 17, 2026 at 6:39 pm UTC
lil-nouns-indexer ✅ Success (View Logs) Sep 17, 2026 at 6:39 pm UTC
ens-api ✅ Success (View Logs) Sep 17, 2026 at 6:39 pm UTC
scroll-indexer ✅ Success (View Logs) Sep 17, 2026 at 6:39 pm UTC
fluid-indexer ✅ Success (View Logs) Sep 17, 2026 at 6:39 pm UTC
tornado-indexer ✅ Success (View Logs) Sep 17, 2026 at 6:39 pm UTC
uniswap-api ✅ Success (View Logs) Sep 17, 2026 at 6:39 pm UTC
tornado-api ✅ Success (View Logs) Sep 17, 2026 at 6:39 pm UTC
nouns-indexer ✅ Success (View Logs) Sep 17, 2026 at 6:39 pm UTC
ens-relayer ✅ Success (View Logs) Sep 17, 2026 at 6:39 pm UTC
erpc ✅ Success (View Logs) Sep 17, 2026 at 6:39 pm UTC
nodeful ✅ Success (View Logs) Sep 17, 2026 at 6:39 pm UTC
user-api ✅ Success (View Logs) Web Sep 17, 2026 at 6:36 pm UTC
scroll-api ✅ Success (View Logs) Sep 17, 2026 at 6:36 pm UTC

@railway-app
railway-app Bot temporarily deployed to anticapture-infra / anticapture-pr-2165 September 17, 2026 18:32 Destroyed
…lugin

Add createHttpServerMetrics / createHttpServerRequestDuration, the standard
http_server_request_duration_seconds histogram with the labels the alerts and
dashboard expect, and registerFastifyMetrics under
@anticapture/observability/fastify, which serves /metrics and records every
request. Only fastify types are imported, so the entry adds no runtime
dependency (fastify is an optional peer).

Fix createObservabilityProvider registering the instrumentations before the
global meter provider was set: instruments were created on the API no-op
meter, so the HTTP auto-instrumentation never exported http_server_duration.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

🔍 Vercel preview: https://anticapture-mxn6noxyz-ful.vercel.app

@LeonardoVieira1630
LeonardoVieira1630 merged commit 20c4b8d into dev Sep 25, 2026
58 checks passed
@LeonardoVieira1630
LeonardoVieira1630 deleted the feat/monitoring-notification-system branch September 25, 2026 22:24

This branch was successfully deployed

1 active deployment
Preview – anticapture-storybook — 5c3da3b3 Deployed Sep 17, 2026 by vercel[bot]
anticapture-infra / anticapture-pr-2165 — 5c3da3b3 Deployed Sep 17, 2026 by railway-app[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants