feat: api and indexer instrumented with metrics#221
Conversation
// fails the other is cancelled
Codecov Report❌ Patch coverage is ❌ Your patch status has failed because the patch coverage (10.06%) is below the target coverage (50.00%). You can increase the patch coverage or adjust the target coverage. Additional details and impacted files@@ Coverage Diff @@
## main #221 +/- ##
=======================================
Coverage ? 29.67%
=======================================
Files ? 147
Lines ? 11008
Branches ? 0
=======================================
Hits ? 3267
Misses ? 7471
Partials ? 270
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Code Review
This pull request implements comprehensive Prometheus metrics instrumentation across the API server, indexer, relayer, and Canton SDK, including dedicated monitoring endpoints and updated deployment configurations. It also introduces a robust suite of end-to-end tests covering user registration, JSON-RPC facades, and bridge deposit/withdrawal flows. Feedback highlights the need to remove an outdated compile-time guard in the API middleware, address a risky type assertion in the instrumented indexer store to prevent potential panics, and refactor the indexer's monitoring server initialization to ensure architectural consistency across the codebase.
Resolved conflicts in: - pkg/app/api/server.go: kept main's initServices refactor and new AcceptWorker/submitter wiring while layering this branch's metrics registerer through evmStore, transferCache, miner, HTTP middleware, and the optional metrics server (serveAll). - pkg/app/http/middleware.go: combined RequestMetricsMiddleware (this branch) and CORSMiddleware (main) into a single file. - pkg/app/indexer/server.go: kept main's multi-template fetcher (offers + holdings) and wrapped the resulting store/processor in this branch's Prometheus metrics. - pkg/cantonsdk/client/client.go: kept main's net/http import (used by the new registry client). - pkg/config/config.go: kept Monitoring on APIServer (this branch) alongside main's TokenProvider/AcceptWorker/SkipWhitelistCheck/ CORSOrigins fields. Carried this branch's instrumentation forward by adding pass-through metrics for the new main methods: InsertHolding/TakeHolding, InsertPendingOffer/MarkOfferAccepted, ListPendingOffersForParty/ ListAllPendingOffers, ListCustodialUsers, GetMempoolEntriesByStatus, GetPendingOffersForParty/GetAllPendingOffers (indexer HTTP client). Updated the indexer processor's per-event-type counters to type-switch on the new heterogeneous Batch[any]; only ParsedEvent contributes to EventType/EffectiveTime metrics.
|
/gemini review |
There was a problem hiding this comment.
Code Review
This pull request introduces comprehensive Prometheus metrics instrumentation across the Canton Middleware components, including the API server, Indexer, Relayer, Canton SDK client, and database stores, along with Grafana dashboards and Prometheus scraping configurations. The review feedback highlights three key improvement opportunities: preventing potential nil pointer dereference panics in the batch processor and HTTP metrics middleware, and optimizing HTTP request logging performance by replacing fmt.Sprintf with strconv.Itoa in the middleware hot path.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
| reg sharedmetrics.NamespacedRegisterer, | ||
| logger *zap.Logger, | ||
| ) (*services, error) { | ||
| userStore := userstore.NewStore(dbBun) |
There was a problem hiding this comment.
Any reason we are not passing the instrumented userstore here?
There was a problem hiding this comment.
Thanks for pointing it out. I think it got missed while resolving the merge conflict. Fixing
| if url == "" { | ||
| return nil, fmt.Errorf("indexer URL is required: set token_provider.indexer.url or accept_worker.indexer_url") | ||
| } | ||
| c, err := indexerclient.New(url, nil) |
There was a problem hiding this comment.
Shouldn't we use InstrumentedClient for indexer?
There was a problem hiding this comment.
Thanks for pointing it out. I think it got missed while resolving the merge conflict. Fixing
|
|
||
| if s.cfg.Monitoring != nil && s.cfg.Monitoring.Enabled { | ||
| if s.cfg.Monitoring.Server == nil { | ||
| return fmt.Errorf("monitoring is enabled but server config is nil") |
There was a problem hiding this comment.
Returning before g.Wait() abandons the already-started HTTP server goroutine and skips graceful shutdown. This should be a config-validation error at load time (the Monitoring struct is validate:"required", not a runtime check after a goroutine is live. Validate up front and you can delete the runtime guard entirely.
There was a problem hiding this comment.
True, we already have validate in the config. This is dead code. We can drop this.
Closes #205