diff options
| author | bndw <ben@bdw.to> | 2026-02-14 12:29:01 -0800 |
|---|---|---|
| committer | bndw <ben@bdw.to> | 2026-02-14 12:29:01 -0800 |
| commit | c33395cee66770c4d88a47537c0ed821f6585f62 (patch) | |
| tree | e7f61e5881089f2f10bd06d5828cd7c58b2bc98e /cmd/relay/main.go | |
| parent | eb666af39feed4be9c8c1354cf52d0ea38ab5d36 (diff) | |
fix: properly chain gRPC interceptors and fix dashboard uptime
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
Diffstat (limited to 'cmd/relay/main.go')
| -rw-r--r-- | cmd/relay/main.go | 41 |
1 files changed, 22 insertions, 19 deletions
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() { | |||
| 54 | path, handler := nostrv1connect.NewNostrRelayHandler(connectHandler, connect.WithInterceptors()) | 54 | path, handler := nostrv1connect.NewNostrRelayHandler(connectHandler, connect.WithInterceptors()) |
| 55 | mux.Handle(path, handler) | 55 | mux.Handle(path, handler) |
| 56 | 56 | ||
| 57 | var serverOpts []grpc.ServerOption | 57 | var unaryInterceptors []grpc.UnaryServerInterceptor |
| 58 | var streamInterceptors []grpc.StreamServerInterceptor | ||
| 59 | |||
| 60 | var m *metrics.Metrics | ||
| 61 | if cfg.Metrics.Enabled { | ||
| 62 | m = metrics.New(cfg.Metrics.ToMetrics()) | ||
| 63 | unaryInterceptors = append(unaryInterceptors, metrics.UnaryServerInterceptor(m)) | ||
| 64 | streamInterceptors = append(streamInterceptors, metrics.StreamServerInterceptor(m)) | ||
| 65 | |||
| 66 | mux.Handle("/metrics", m.PrometheusHandler()) | ||
| 67 | mux.Handle("/dashboard", m.DashboardHandler()) | ||
| 68 | } | ||
| 58 | 69 | ||
| 59 | if cfg.Auth.Read.Enabled || cfg.Auth.Write.Enabled { | 70 | if cfg.Auth.Read.Enabled || cfg.Auth.Write.Enabled { |
| 60 | authOpts := &auth.InterceptorOptions{ | 71 | authOpts := &auth.InterceptorOptions{ |
| @@ -63,30 +74,22 @@ func main() { | |||
| 63 | TimestampWindow: cfg.Auth.TimestampWindow, | 74 | TimestampWindow: cfg.Auth.TimestampWindow, |
| 64 | SkipMethods: cfg.Auth.SkipMethods, | 75 | SkipMethods: cfg.Auth.SkipMethods, |
| 65 | } | 76 | } |
| 66 | serverOpts = append(serverOpts, | 77 | unaryInterceptors = append(unaryInterceptors, auth.NostrUnaryInterceptor(authOpts)) |
| 67 | grpc.UnaryInterceptor(auth.NostrUnaryInterceptor(authOpts)), | 78 | streamInterceptors = append(streamInterceptors, auth.NostrStreamInterceptor(authOpts)) |
| 68 | grpc.StreamInterceptor(auth.NostrStreamInterceptor(authOpts)), | ||
| 69 | ) | ||
| 70 | } | 79 | } |
| 71 | 80 | ||
| 72 | if cfg.RateLimit.Enabled { | 81 | if cfg.RateLimit.Enabled { |
| 73 | limiter := ratelimit.New(cfg.RateLimit.ToRateLimiter()) | 82 | limiter := ratelimit.New(cfg.RateLimit.ToRateLimiter()) |
| 74 | serverOpts = append(serverOpts, | 83 | unaryInterceptors = append(unaryInterceptors, ratelimit.UnaryInterceptor(limiter)) |
| 75 | grpc.ChainUnaryInterceptor(ratelimit.UnaryInterceptor(limiter)), | 84 | streamInterceptors = append(streamInterceptors, ratelimit.StreamInterceptor(limiter)) |
| 76 | grpc.ChainStreamInterceptor(ratelimit.StreamInterceptor(limiter)), | ||
| 77 | ) | ||
| 78 | } | 85 | } |
| 79 | 86 | ||
| 80 | var m *metrics.Metrics | 87 | var serverOpts []grpc.ServerOption |
| 81 | if cfg.Metrics.Enabled { | 88 | if len(unaryInterceptors) > 0 { |
| 82 | m = metrics.New(cfg.Metrics.ToMetrics()) | 89 | serverOpts = append(serverOpts, grpc.ChainUnaryInterceptor(unaryInterceptors...)) |
| 83 | serverOpts = append(serverOpts, | 90 | } |
| 84 | grpc.ChainUnaryInterceptor(metrics.UnaryServerInterceptor(m)), | 91 | if len(streamInterceptors) > 0 { |
| 85 | grpc.ChainStreamInterceptor(metrics.StreamServerInterceptor(m)), | 92 | serverOpts = append(serverOpts, grpc.ChainStreamInterceptor(streamInterceptors...)) |
| 86 | ) | ||
| 87 | |||
| 88 | mux.Handle("/metrics", m.PrometheusHandler()) | ||
| 89 | mux.Handle("/dashboard", m.DashboardHandler()) | ||
| 90 | } | 93 | } |
| 91 | 94 | ||
| 92 | wsHandler := wshandler.NewHandler(store, subManager) | 95 | wsHandler := wshandler.NewHandler(store, subManager) |
