feat(ratelimit): track per-window token usage and utilization

Poll /api/oauth/usage every 5 min and extract utilization from
/v1/messages response headers for real-time updates. Track proxy
tokens in/out per rate limit window (5h/7d), resetting on window
change. Expose as OTel observable gauges for Grafana dashboards.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Alexander
2026-04-14 12:51:31 +02:00
parent 76aeeb6be1
commit fac9578975
7 changed files with 364 additions and 13 deletions
+4 -3
View File
@@ -5,6 +5,7 @@ import (
"io"
"github.com/fujin/anthropic-proxy/internal/config"
"github.com/fujin/anthropic-proxy/internal/ratelimit"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc"
"go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc"
@@ -21,7 +22,7 @@ import (
// so metrics can be recorded in-process. When cfg.ExportEnabled(), OTLP gRPC
// exporters are additionally configured to push to the LGTM stack.
// Returns a shutdown function and an optional io.Writer for the log bridge.
func Setup(ctx context.Context, cfg config.TelemetryConfig) (shutdown func(context.Context) error, logWriter io.Writer, err error) {
func Setup(ctx context.Context, cfg config.TelemetryConfig, tracker *ratelimit.Tracker) (shutdown func(context.Context) error, logWriter io.Writer, err error) {
res, err := resource.New(ctx,
resource.WithAttributes(
semconv.ServiceName(cfg.ServiceName),
@@ -36,7 +37,7 @@ func Setup(ctx context.Context, cfg config.TelemetryConfig) (shutdown func(conte
// instruments are valid (they just don't export anywhere).
mp := sdkmetric.NewMeterProvider(sdkmetric.WithResource(res))
otel.SetMeterProvider(mp)
InitMetrics(mp.Meter(cfg.ServiceName))
InitMetrics(mp.Meter(cfg.ServiceName), tracker)
return func(ctx context.Context) error { return mp.Shutdown(ctx) }, nil, nil
}
@@ -74,7 +75,7 @@ func Setup(ctx context.Context, cfg config.TelemetryConfig) (shutdown func(conte
sdkmetric.WithResource(res),
)
otel.SetMeterProvider(mp)
InitMetrics(mp.Meter(cfg.ServiceName))
InitMetrics(mp.Meter(cfg.ServiceName), tracker)
// Log exporter
logExp, err := otlploggrpc.New(ctx, logOpts...)