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+ }
0 commit comments