Skip to content

Commit 787ee44

Browse files
committed
Add grafana dashboard
1 parent 761bab3 commit 787ee44

3 files changed

Lines changed: 281 additions & 177 deletions

File tree

deploy/grafana/dashboard.json

Lines changed: 100 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,100 @@
1-
// deploy/grafana/dashboard.json
1+
{
2+
"__inputs": [],
3+
"__requires": [
4+
{ "type": "grafana", "id": "grafana", "name": "Grafana", "version": "10.0.0" },
5+
{ "type": "datasource", "id": "prometheus", "name": "Prometheus", "version": "1.0.0" }
6+
],
7+
"annotations": { "list": [] },
8+
"description": "Rate Limiter — decision throughput, latency, Redis health",
9+
"editable": true,
10+
"fiscalYearStartMonth": 0,
11+
"graphTooltip": 1,
12+
"id": null,
13+
"panels": [
14+
{
15+
"title": "Request rate (allowed vs rejected)",
16+
"type": "timeseries",
17+
"gridPos": { "h": 8, "w": 12, "x": 0, "y": 0 },
18+
"targets": [
19+
{
20+
"expr": "sum(rate(ratelimiter_requests_total{status=\"allowed\"}[1m]))",
21+
"legendFormat": "allowed"
22+
},
23+
{
24+
"expr": "sum(rate(ratelimiter_requests_total{status=\"rejected\"}[1m]))",
25+
"legendFormat": "rejected"
26+
}
27+
]
28+
},
29+
{
30+
"title": "Decision latency — p50 / p95 / p99",
31+
"type": "timeseries",
32+
"gridPos": { "h": 8, "w": 12, "x": 12, "y": 0 },
33+
"targets": [
34+
{
35+
"expr": "histogram_quantile(0.50, sum(rate(ratelimiter_decision_latency_seconds_bucket[1m])) by (le)) * 1000",
36+
"legendFormat": "p50 ms"
37+
},
38+
{
39+
"expr": "histogram_quantile(0.95, sum(rate(ratelimiter_decision_latency_seconds_bucket[1m])) by (le)) * 1000",
40+
"legendFormat": "p95 ms"
41+
},
42+
{
43+
"expr": "histogram_quantile(0.99, sum(rate(ratelimiter_decision_latency_seconds_bucket[1m])) by (le)) * 1000",
44+
"legendFormat": "p99 ms"
45+
}
46+
]
47+
},
48+
{
49+
"title": "Redis command latency — p99",
50+
"type": "timeseries",
51+
"gridPos": { "h": 8, "w": 12, "x": 0, "y": 8 },
52+
"targets": [
53+
{
54+
"expr": "histogram_quantile(0.99, sum(rate(ratelimiter_redis_command_duration_seconds_bucket[1m])) by (le)) * 1000",
55+
"legendFormat": "Redis p99 ms"
56+
}
57+
]
58+
},
59+
{
60+
"title": "Redis errors",
61+
"type": "stat",
62+
"gridPos": { "h": 8, "w": 6, "x": 12, "y": 8 },
63+
"targets": [
64+
{
65+
"expr": "sum(increase(ratelimiter_redis_errors_total[5m]))",
66+
"legendFormat": "errors (5m)"
67+
}
68+
],
69+
"fieldConfig": {
70+
"defaults": {
71+
"thresholds": {
72+
"mode": "absolute",
73+
"steps": [
74+
{ "color": "green", "value": null },
75+
{ "color": "red", "value": 1 }
76+
]
77+
}
78+
}
79+
}
80+
},
81+
{
82+
"title": "Rejection rate %",
83+
"type": "stat",
84+
"gridPos": { "h": 8, "w": 6, "x": 18, "y": 8 },
85+
"targets": [
86+
{
87+
"expr": "sum(rate(ratelimiter_requests_total{status=\"rejected\"}[1m])) / sum(rate(ratelimiter_requests_total[1m])) * 100",
88+
"legendFormat": "rejection %"
89+
}
90+
]
91+
}
92+
],
93+
"schemaVersion": 38,
94+
"tags": ["rate-limiter", "distributed-systems"],
95+
"time": { "from": "now-1h", "to": "now" },
96+
"timepicker": {},
97+
"title": "Rate Limiter",
98+
"uid": "rate-limiter-main",
99+
"version": 1
100+
}

internal/http/handler.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
stdhttp "net/http"
77
"time"
88

9+
"github.com/Pavan-Rana/rate-limiter/internal/metrics"
910
"github.com/prometheus/client_golang/prometheus/promhttp"
1011
)
1112

@@ -18,6 +19,7 @@ func NewRouter(lim Limiter) stdhttp.Handler {
1819
sem := make(chan struct{}, 1000) // Limit to 1000 concurrent requests
1920

2021
mux.HandleFunc("/check", func(w stdhttp.ResponseWriter, r *stdhttp.Request) {
22+
start := time.Now()
2123
select {
2224
case sem <- struct{}{}:
2325
defer func() { <-sem }()
@@ -37,7 +39,10 @@ func NewRouter(lim Limiter) stdhttp.Handler {
3739
}
3840

3941
allowed, err := lim.AllowRequest(ctx, apiKey)
42+
metrics.RecordDecision(apiKey, allowed)
43+
metrics.RecordDecisionLatency(time.Since(start))
4044
if err != nil {
45+
metrics.RecordRedisError()
4146
stdhttp.Error(w, err.Error(), stdhttp.StatusInternalServerError)
4247
return
4348
}

0 commit comments

Comments
 (0)