feat(indexer): add indexer lag, finality, and projection health metri… - #383
Conversation
|
@yunus-dev-codecrafter CI is blocked on the current head
Please run the repository lint command against the updated branch, make every changed file lint-clean, and push the fixes. I’ll re-review the new head and allow the remaining CI stages to determine merge eligibility. This indexer/health work also requires independent maintainer approval after CI is green. |
|
@dDevAhmed I'm on it |
|
@yunus-dev-codecrafter PR #383 was merged at head
Please push remediation, run the complete required workflow, prove restart/stalled-projection/reorg/RPC/dead-letter behavior, and obtain explicit indexer-sensitive maintainer approval before #368 is treated as completed. |
closes #368
…cs (#368)
PR Description — #368 V2-BE-032: Indexer Lag, Finality & Projection Health Metrics
Title
feat(indexer): add indexer lag, finality, and projection health metrics (#368)
Summary
This PR adds live indexer health observability to the V2 Optimism/EVM backend. It
measures the observed head, safe/finalized cursors, projection lag, RPC failures,
replay count, and dead letters, exposes sanitized health JSON and Prometheus
metrics, and defines alert thresholds with a runbook link — without leaking
credentials, user data, or live RPC endpoints.
The implementation is based on the live
BlockchainStateServicepath (the dormantEventIndexerServiceundersrc/indexer/is not wired into the app) after auditingthe overlapping code.
Motivation / Problem Context
Contracts emit facts, the indexer projects them, and the API serves those
projections. Operators currently have no visibility into how far the indexer has
fallen behind the chain head, whether finalization is progressing, how many RPC
failures or retries are occurring, or how many events are being dead-lettered. This
PR closes that gap with safe, sanitized signals.
Technical Scope Delivered
(
indexer_observed_head).(
indexer_safe_block,indexer_finalized_block).(
indexer_projection_head).negative (
indexer_projection_lag_blocks).(
indexer_rpc_failures_total).(
indexer_replay_count_total).(
indexer_dead_letters_total).Architecture
BlockchainStateService(src/blockchain/state.service.ts)now tracks the cursors and counters above and derives the projection lag and the
sanitized
IndexerHealthSnapshot.EventIndexingService.processBlockrecords observed head, projection head,replays (on reorg reconciliation), and RPC failures (on processing error).
BlockchainIndexerServiceadvances the projection head as checkpoints commitand records replays on rollback.
IndexerMetricsService(src/metrics/indexer-metrics.service.ts)samples the snapshot into Prometheus gauges/counters and is served at the existing
Bearer-protected
/metricsendpoint (viaMetricsAuthGuard).GET /health/indexerreturns a sanitized, status(
healthy | degraded | unhealthy) health report.Reused / Replaced / Deprecated Paths
MetricsService+ shared Prometheus registry,HealthController/HealthService,BlockchainStateService,MetricsAuthGuard.BlockchainStateServiceratherthan the dormant, un-wired
EventIndexerService(src/indexer/).src/indexer/EventIndexerServicecodepath is identified as legacy/unwired and left for a follow-up.
Security & Integrity
token accounting, or Stellar/Freighter runtime dependencies added.
user data (covered by unit tests).
unhealthy, and thereadiness blockchain check degrades when indexer health is unhealthy.
read/record observability only.
Migration / Rebuild Impact
ChainState); no schema or migration change.(unique index on
(transactionHash, logIndex, eventType)), and state + checkpointcommit atomically in a single transaction.
Observability
Prometheus:
indexer_observed_head,indexer_safe_block,indexer_finalized_block,indexer_projection_head,indexer_projection_lag_blocks,indexer_rpc_failures_total,indexer_replay_count_total,indexer_dead_letters_total.Health JSON:
GET /health/indexer.Alert thresholds and remediation steps:
docs/indexer-runbook.md.Acceptance Criteria Mapping
BlockchainStateServicefields/methods + unit testsGET /health/indexer;IndexerMetricsServiceat/metricsdocs/indexer-runbook.md; sanitization unit testsMetricsAuthGuardMONITORING_GUIDE.md; no migration neededRequired Tests / Evidence of Commands
npm run build— no new errors in any changed file (see Residual Risks forunrelated baseline failures).
npx jest src/blockchain/state.service.spec.ts src/metrics/tests/indexer-metrics.service.spec.ts→ pass (new indexer-health coverage).
npx jest src/blockchain/blockchain-indexer.service.spec.ts src/blockchain/blockchain-indexer.spec.ts src/blockchain/blockchain-replay.spec.ts src/blockchain/blockchain-reorg.integration.spec.ts src/blockchain/state.service.spec.ts src/metrics/tests/indexer-metrics.service.spec.ts src/metrics/tests/metrics.service.spec.ts→ 58 passed.
Residual Risks / Unrelated Baseline Failures
Reported separately, not introduced by this PR:
npm run buildfails onmaindue to pre-existing errors (e.g.,src/notifications/websockets/websocket.gateway.ts,src/admin/protocol/protocol-admin.controller.ts, andsrc/health/health.service.tscollectDiagnostics()missingawait→ TS2739).npm run lintfails repo-wide onmain(CRLF/quote formatting +no-unsafe-*/require-awaitacross existing files).unverified for this scope.
Dependencies
V2-BE-010, V2-BE-019, V2-BE-020 (noted as required prerequisites; not evaluated here).
Additional Notes
protocol-sensitive work).