diff options
Diffstat (limited to 'internal')
| -rw-r--r-- | internal/handler/websocket/handler.go | 4 | ||||
| -rw-r--r-- | internal/metrics/dashboard.html | 7 | ||||
| -rw-r--r-- | internal/metrics/metrics.go | 17 |
3 files changed, 28 insertions, 0 deletions
diff --git a/internal/handler/websocket/handler.go b/internal/handler/websocket/handler.go index 8daa89f..35d0aea 100644 --- a/internal/handler/websocket/handler.go +++ b/internal/handler/websocket/handler.go | |||
| @@ -33,6 +33,7 @@ type MetricsRecorder interface { | |||
| 33 | DecrementSubscriptions() | 33 | DecrementSubscriptions() |
| 34 | SetActiveSubscriptions(count int) | 34 | SetActiveSubscriptions(count int) |
| 35 | RecordRequest(method, status string, duration float64) | 35 | RecordRequest(method, status string, duration float64) |
| 36 | RecordBlockedEvent(kind int32) | ||
| 36 | } | 37 | } |
| 37 | 38 | ||
| 38 | type RateLimiter interface { | 39 | type RateLimiter interface { |
| @@ -302,6 +303,9 @@ func (h *Handler) handleEvent(ctx context.Context, conn *websocket.Conn, raw []j | |||
| 302 | // Reject non-core protocol kinds (spam, ephemeral, chat) | 303 | // Reject non-core protocol kinds (spam, ephemeral, chat) |
| 303 | if !isAllowedKind(pbEvent.Kind) { | 304 | if !isAllowedKind(pbEvent.Kind) { |
| 304 | status = "ok" | 305 | status = "ok" |
| 306 | if h.metrics != nil { | ||
| 307 | h.metrics.RecordBlockedEvent(pbEvent.Kind) | ||
| 308 | } | ||
| 305 | h.sendOK(ctx, conn, event.ID, true, "rejected: kind not supported") | 309 | h.sendOK(ctx, conn, event.ID, true, "rejected: kind not supported") |
| 306 | return nil | 310 | return nil |
| 307 | } | 311 | } |
diff --git a/internal/metrics/dashboard.html b/internal/metrics/dashboard.html index 9538ac6..1fa1ddf 100644 --- a/internal/metrics/dashboard.html +++ b/internal/metrics/dashboard.html | |||
| @@ -199,6 +199,10 @@ | |||
| 199 | <span class="metric-label">Deletions</span> | 199 | <span class="metric-label">Deletions</span> |
| 200 | <span class="metric-value" id="event_deletions">0</span> | 200 | <span class="metric-value" id="event_deletions">0</span> |
| 201 | </div> | 201 | </div> |
| 202 | <div class="metric"> | ||
| 203 | <span class="metric-label">Blocked</span> | ||
| 204 | <span class="metric-value" id="events_blocked">0</span> | ||
| 205 | </div> | ||
| 202 | </div> | 206 | </div> |
| 203 | 207 | ||
| 204 | <div class="card"> | 208 | <div class="card"> |
| @@ -317,6 +321,9 @@ | |||
| 317 | document.getElementById('event_deletions').textContent = | 321 | document.getElementById('event_deletions').textContent = |
| 318 | sumMetric(metrics, `${prefix}_relay_event_deletions_total`); | 322 | sumMetric(metrics, `${prefix}_relay_event_deletions_total`); |
| 319 | 323 | ||
| 324 | document.getElementById('events_blocked').textContent = | ||
| 325 | sumMetric(metrics, `${prefix}_relay_events_blocked_total`); | ||
| 326 | |||
| 320 | const durationSum = sumMetric(metrics, `${prefix}_relay_request_duration_seconds_sum`); | 327 | const durationSum = sumMetric(metrics, `${prefix}_relay_request_duration_seconds_sum`); |
| 321 | const durationCount = sumMetric(metrics, `${prefix}_relay_request_duration_seconds_count`); | 328 | const durationCount = sumMetric(metrics, `${prefix}_relay_request_duration_seconds_count`); |
| 322 | const avgLatencyMs = durationCount > 0 ? (durationSum / durationCount * 1000) : 0; | 329 | const avgLatencyMs = durationCount > 0 ? (durationSum / durationCount * 1000) : 0; |
diff --git a/internal/metrics/metrics.go b/internal/metrics/metrics.go index 74f9ffb..dea0748 100644 --- a/internal/metrics/metrics.go +++ b/internal/metrics/metrics.go | |||
| @@ -2,6 +2,7 @@ package metrics | |||
| 2 | 2 | ||
| 3 | import ( | 3 | import ( |
| 4 | _ "embed" | 4 | _ "embed" |
| 5 | "fmt" | ||
| 5 | "net/http" | 6 | "net/http" |
| 6 | 7 | ||
| 7 | "github.com/prometheus/client_golang/prometheus" | 8 | "github.com/prometheus/client_golang/prometheus" |
| @@ -30,6 +31,7 @@ type Metrics struct { | |||
| 30 | eventsTotal prometheus.Gauge | 31 | eventsTotal prometheus.Gauge |
| 31 | dbSizeBytes prometheus.Gauge | 32 | dbSizeBytes prometheus.Gauge |
| 32 | eventDeletionsTotal prometheus.Counter | 33 | eventDeletionsTotal prometheus.Counter |
| 34 | eventsBlockedTotal *prometheus.CounterVec | ||
| 33 | 35 | ||
| 34 | // Config | 36 | // Config |
| 35 | config *Config | 37 | config *Config |
| @@ -195,6 +197,16 @@ func New(config *Config) *Metrics { | |||
| 195 | }, | 197 | }, |
| 196 | ) | 198 | ) |
| 197 | 199 | ||
| 200 | m.eventsBlockedTotal = promauto.NewCounterVec( | ||
| 201 | prometheus.CounterOpts{ | ||
| 202 | Namespace: config.Namespace, | ||
| 203 | Subsystem: config.Subsystem, | ||
| 204 | Name: "events_blocked_total", | ||
| 205 | Help: "Total events blocked by kind filter", | ||
| 206 | }, | ||
| 207 | []string{"kind"}, | ||
| 208 | ) | ||
| 209 | |||
| 198 | return m | 210 | return m |
| 199 | } | 211 | } |
| 200 | 212 | ||
| @@ -274,6 +286,11 @@ func (m *Metrics) RecordEventDeletion() { | |||
| 274 | m.eventDeletionsTotal.Inc() | 286 | m.eventDeletionsTotal.Inc() |
| 275 | } | 287 | } |
| 276 | 288 | ||
| 289 | // RecordBlockedEvent records an event blocked by kind filter. | ||
| 290 | func (m *Metrics) RecordBlockedEvent(kind int32) { | ||
| 291 | m.eventsBlockedTotal.WithLabelValues(fmt.Sprintf("%d", kind)).Inc() | ||
| 292 | } | ||
| 293 | |||
| 277 | // RequestStatus represents the status of a request for metrics. | 294 | // RequestStatus represents the status of a request for metrics. |
| 278 | type RequestStatus string | 295 | type RequestStatus string |
| 279 | 296 | ||
