summaryrefslogtreecommitdiffstats
path: root/internal/handler
diff options
context:
space:
mode:
authorbndw <ben@bdw.to>2026-02-15 17:10:49 -0800
committerbndw <ben@bdw.to>2026-02-15 17:10:49 -0800
commit4909a9f9d23ad969a03676d87087c1edad632a5d (patch)
tree6d05615f626c6a239fe9888410e450f3881a3e09 /internal/handler
parentfa8b4bb939430ba9c48fb4d3ba2b0e9095e229d3 (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
Diffstat (limited to 'internal/handler')
-rw-r--r--internal/handler/websocket/handler.go7
-rw-r--r--internal/handler/websocket/handler_test.go1
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}
100func (m *mockMetrics) RecordAuthAttempt(success bool) {} 100func (m *mockMetrics) RecordAuthAttempt(success bool) {}
101func (m *mockMetrics) RecordRateLimitHit(authenticated bool) {}
101func (m *mockMetrics) RecordBlockedEvent(kind int32) { 102func (m *mockMetrics) RecordBlockedEvent(kind int32) {
102 m.mu.Lock() 103 m.mu.Lock()
103 defer m.mu.Unlock() 104 defer m.mu.Unlock()