Skip to content

Observability & Telemetry

distlimit features a pluggable telemetry architecture via the metrics.Observer interface. When disabled, the telemetry subsystem incurs 0 B/op memory overhead and zero latency impact.


📊 Prometheus Integration (metrics/prometheus)

Section titled “📊 Prometheus Integration (metrics/prometheus)”

The Prometheus collector (distprom.Observer) exports metrics for total evaluation counts, execution latencies, and circuit breaker failover events.

Terminal window
go get github.com/prometheus/client_golang
package main
import (
"net/http"
"time"
"github.com/balramadan/distlimit"
"github.com/balramadan/distlimit/algorithm/tokenbucket"
"github.com/balramadan/distlimit/driver/memory"
distprom "github.com/balramadan/distlimit/metrics/prometheus"
distlimitnethttp "github.com/balramadan/distlimit/middleware/nethttp"
"github.com/prometheus/client_golang/prometheus/promhttp"
)
func main() {
memDriver := memory.New(5 * time.Minute)
// 1. Initialize Prometheus Observer
promObserver := distprom.NewObserver(
distprom.WithNamespace("api_gateway"),
distprom.WithSubsystem("rate_limiter"),
)
// 2. Attach Observer to Limiter
limiter, _ := distlimit.New(
memDriver,
distlimit.WithLimit(100),
distlimit.WithWindow(1*time.Minute),
distlimit.WithAlgorithm(tokenbucket.New()),
distlimit.WithMetricObserver(promObserver),
)
mux := http.NewServeMux()
// 3. Enable Route Labeling on Middleware
apiHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("ok"))
})
mux.Handle("/api/v1/users", distlimitnethttp.New(
limiter,
distlimitnethttp.WithRouteLabeling(true),
)(apiHandler))
// 4. Expose Metrics Endpoint for Prometheus Scraper
mux.Handle("/metrics", promhttp.Handler())
http.ListenAndServe(":8080", mux)
}

Metric Name Type Labels Description
distlimit_requests_total Counter status, driver, algorithm, route Total number of rate limit evaluations. status values: allowed or blocked.
distlimit_evaluation_duration_seconds Histogram driver, algorithm, route Internal execution latency of rate limit evaluations in seconds.
distlimit_hybrid_fallback_total Counter driver Total number of times the Hybrid Driver fell back to memory due to Redis failure.

🔭 OpenTelemetry Integration (metrics/otel)

Section titled “🔭 OpenTelemetry Integration (metrics/otel)”

The OpenTelemetry observer (distotel.Observer) records metric counters and histograms using standard OTel Meter Providers.

Terminal window
go get go.opentelemetry.io/otel
package main
import (
"time"
"github.com/balramadan/distlimit"
"github.com/balramadan/distlimit/algorithm/tokenbucket"
"github.com/balramadan/distlimit/driver/memory"
distotel "github.com/balramadan/distlimit/metrics/otel"
"go.opentelemetry.io/otel"
)
func main() {
memDriver := memory.New(5 * time.Minute)
// Initialize OpenTelemetry Observer using global MeterProvider
otelObserver := distotel.NewObserver(
distotel.WithMeterProvider(otel.GetMeterProvider()),
)
limiter, _ := distlimit.New(
memDriver,
distlimit.WithLimit(100),
distlimit.WithWindow(1*time.Minute),
distlimit.WithAlgorithm(tokenbucket.New()),
distlimit.WithMetricObserver(otelObserver),
)
_ = limiter
}

When no observer is provided (or when using metrics.NewNoopObserver()), distlimit completely skips timestamping and string allocations.

BenchmarkLimiter_NoObserver-2 322239 3223 ns/op 0 B/op 0 allocs/op

Key Performance Takeaway: Enabling rate limiting with observability turned off incurs 0 B/op memory allocations and introduces no Garbage Collection pressure under high concurrency.