diff options
| author | bndw <ben@bdw.to> | 2026-02-15 17:10:49 -0800 |
|---|---|---|
| committer | bndw <ben@bdw.to> | 2026-02-15 17:10:49 -0800 |
| commit | 4909a9f9d23ad969a03676d87087c1edad632a5d (patch) | |
| tree | 6d05615f626c6a239fe9888410e450f3881a3e09 | |
| parent | fa8b4bb939430ba9c48fb4d3ba2b0e9095e229d3 (diff) | |
fix: track rate limit hits in metrics
- Added RecordRateLimitHit to MetricsRecorder interface
- Call RecordRateLimitHit when EVENT or REQ is rate limited
- Allows dashboard to show accurate rate limiting statistics
- Previously rate limits were applied but not tracked
| -rw-r--r-- | internal/handler/websocket/handler.go | 7 | ||||
| -rw-r--r-- | internal/handler/websocket/handler_test.go | 1 |
2 files changed, 8 insertions, 0 deletions
diff --git a/internal/handler/websocket/handler.go b/internal/handler/websocket/handler.go index c1b23b8..51288bc 100644 --- a/internal/handler/websocket/handler.go +++ b/internal/handler/websocket/handler.go | |||
| @@ -34,6 +34,7 @@ type MetricsRecorder interface { | |||
| 34 | SetActiveSubscriptions(count int) | 34 | SetActiveSubscriptions(count int) |
| 35 | RecordRequest(method, status string, duration float64) | 35 | RecordRequest(method, status string, duration float64) |
| 36 | RecordAuthAttempt(success bool) | 36 | RecordAuthAttempt(success bool) |
| 37 | RecordRateLimitHit(authenticated bool) | ||
| 37 | RecordBlockedEvent(kind int32) | 38 | RecordBlockedEvent(kind int32) |
| 38 | } | 39 | } |
| 39 | 40 | ||
| @@ -274,6 +275,9 @@ func (h *Handler) handleEvent(ctx context.Context, conn *websocket.Conn, raw []j | |||
| 274 | } | 275 | } |
| 275 | if !h.limiter.Allow(identifier, "EVENT") { | 276 | if !h.limiter.Allow(identifier, "EVENT") { |
| 276 | status = "rate_limited" | 277 | status = "rate_limited" |
| 278 | if h.metrics != nil { | ||
| 279 | h.metrics.RecordRateLimitHit(state.authenticatedPubkey != "") | ||
| 280 | } | ||
| 277 | h.sendOK(ctx, conn, event.ID, false, "rate-limited: slow down") | 281 | h.sendOK(ctx, conn, event.ID, false, "rate-limited: slow down") |
| 278 | return nil | 282 | return nil |
| 279 | } | 283 | } |
| @@ -386,6 +390,9 @@ func (h *Handler) handleReq(ctx context.Context, conn *websocket.Conn, raw []jso | |||
| 386 | } | 390 | } |
| 387 | if !h.limiter.Allow(identifier, "REQ") { | 391 | if !h.limiter.Allow(identifier, "REQ") { |
| 388 | status = "rate_limited" | 392 | status = "rate_limited" |
| 393 | if h.metrics != nil { | ||
| 394 | h.metrics.RecordRateLimitHit(state.authenticatedPubkey != "") | ||
| 395 | } | ||
| 389 | return fmt.Errorf("rate limit exceeded") | 396 | return fmt.Errorf("rate limit exceeded") |
| 390 | } | 397 | } |
| 391 | } | 398 | } |
diff --git a/internal/handler/websocket/handler_test.go b/internal/handler/websocket/handler_test.go index 604a190..2ef72fd 100644 --- a/internal/handler/websocket/handler_test.go +++ b/internal/handler/websocket/handler_test.go | |||
| @@ -98,6 +98,7 @@ func (m *mockMetrics) RecordRequest(method, status string, duration float64) { | |||
| 98 | m.requests[key]++ | 98 | m.requests[key]++ |
| 99 | } | 99 | } |
| 100 | func (m *mockMetrics) RecordAuthAttempt(success bool) {} | 100 | func (m *mockMetrics) RecordAuthAttempt(success bool) {} |
| 101 | func (m *mockMetrics) RecordRateLimitHit(authenticated bool) {} | ||
| 101 | func (m *mockMetrics) RecordBlockedEvent(kind int32) { | 102 | func (m *mockMetrics) RecordBlockedEvent(kind int32) { |
| 102 | m.mu.Lock() | 103 | m.mu.Lock() |
| 103 | defer m.mu.Unlock() | 104 | defer m.mu.Unlock() |
