From c33395cee66770c4d88a47537c0ed821f6585f62 Mon Sep 17 00:00:00 2001 From: bndw Date: Sat, 14 Feb 2026 12:29:01 -0800 Subject: fix: properly chain gRPC interceptors and fix dashboard uptime MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two critical fixes for metrics: 1. Fix interceptor chaining - Changed from mixed grpc.UnaryInterceptor/ChainUnaryInterceptor to proper chaining with grpc.ChainUnaryInterceptor - Metrics interceptor now runs first (as intended) - All interceptors properly chained in order: metrics → auth → ratelimit - This fixes metrics not being recorded for any requests 2. Fix dashboard uptime calculation - Changed from page load time to process_start_time_seconds metric - Uptime now persists correctly across page refreshes - Uses Prometheus standard process_start_time_seconds gauge Before: Metrics showed 0 for all requests, uptime reset on refresh After: Metrics properly record all gRPC requests, uptime shows actual relay uptime --- cmd/relay/main.go | 41 ++++++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 19 deletions(-) (limited to 'cmd/relay/main.go') diff --git a/cmd/relay/main.go b/cmd/relay/main.go index bd50e63..457a719 100644 --- a/cmd/relay/main.go +++ b/cmd/relay/main.go @@ -54,7 +54,18 @@ func main() { path, handler := nostrv1connect.NewNostrRelayHandler(connectHandler, connect.WithInterceptors()) mux.Handle(path, handler) - var serverOpts []grpc.ServerOption + var unaryInterceptors []grpc.UnaryServerInterceptor + var streamInterceptors []grpc.StreamServerInterceptor + + var m *metrics.Metrics + if cfg.Metrics.Enabled { + m = metrics.New(cfg.Metrics.ToMetrics()) + unaryInterceptors = append(unaryInterceptors, metrics.UnaryServerInterceptor(m)) + streamInterceptors = append(streamInterceptors, metrics.StreamServerInterceptor(m)) + + mux.Handle("/metrics", m.PrometheusHandler()) + mux.Handle("/dashboard", m.DashboardHandler()) + } if cfg.Auth.Read.Enabled || cfg.Auth.Write.Enabled { authOpts := &auth.InterceptorOptions{ @@ -63,30 +74,22 @@ func main() { TimestampWindow: cfg.Auth.TimestampWindow, SkipMethods: cfg.Auth.SkipMethods, } - serverOpts = append(serverOpts, - grpc.UnaryInterceptor(auth.NostrUnaryInterceptor(authOpts)), - grpc.StreamInterceptor(auth.NostrStreamInterceptor(authOpts)), - ) + unaryInterceptors = append(unaryInterceptors, auth.NostrUnaryInterceptor(authOpts)) + streamInterceptors = append(streamInterceptors, auth.NostrStreamInterceptor(authOpts)) } if cfg.RateLimit.Enabled { limiter := ratelimit.New(cfg.RateLimit.ToRateLimiter()) - serverOpts = append(serverOpts, - grpc.ChainUnaryInterceptor(ratelimit.UnaryInterceptor(limiter)), - grpc.ChainStreamInterceptor(ratelimit.StreamInterceptor(limiter)), - ) + unaryInterceptors = append(unaryInterceptors, ratelimit.UnaryInterceptor(limiter)) + streamInterceptors = append(streamInterceptors, ratelimit.StreamInterceptor(limiter)) } - var m *metrics.Metrics - if cfg.Metrics.Enabled { - m = metrics.New(cfg.Metrics.ToMetrics()) - serverOpts = append(serverOpts, - grpc.ChainUnaryInterceptor(metrics.UnaryServerInterceptor(m)), - grpc.ChainStreamInterceptor(metrics.StreamServerInterceptor(m)), - ) - - mux.Handle("/metrics", m.PrometheusHandler()) - mux.Handle("/dashboard", m.DashboardHandler()) + var serverOpts []grpc.ServerOption + if len(unaryInterceptors) > 0 { + serverOpts = append(serverOpts, grpc.ChainUnaryInterceptor(unaryInterceptors...)) + } + if len(streamInterceptors) > 0 { + serverOpts = append(serverOpts, grpc.ChainStreamInterceptor(streamInterceptors...)) } wsHandler := wshandler.NewHandler(store, subManager) -- cgit v1.2.3