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:
@@ -14,6 +14,7 @@ import (
|
||||
"github.com/fujin/anthropic-proxy/internal/config"
|
||||
"github.com/fujin/anthropic-proxy/internal/logging"
|
||||
"github.com/fujin/anthropic-proxy/internal/proxy"
|
||||
"github.com/fujin/anthropic-proxy/internal/ratelimit"
|
||||
"github.com/fujin/anthropic-proxy/internal/server"
|
||||
"github.com/fujin/anthropic-proxy/internal/telemetry"
|
||||
"github.com/rs/zerolog/log"
|
||||
@@ -25,8 +26,17 @@ func run() error {
|
||||
return fmt.Errorf("load config: %w", err)
|
||||
}
|
||||
|
||||
// Create usage tracker (started later once credential is loaded)
|
||||
var credForTracker *auth.Credential
|
||||
tracker := ratelimit.NewTracker(func() string {
|
||||
if credForTracker == nil {
|
||||
return ""
|
||||
}
|
||||
return credForTracker.Token()
|
||||
})
|
||||
|
||||
// Initialize telemetry (metrics always active; OTLP export when endpoint set)
|
||||
telemetryShutdown, logBridge, err := telemetry.Setup(context.Background(), cfg.Telemetry)
|
||||
telemetryShutdown, logBridge, err := telemetry.Setup(context.Background(), cfg.Telemetry, tracker)
|
||||
if err != nil {
|
||||
return fmt.Errorf("telemetry setup: %w", err)
|
||||
}
|
||||
@@ -85,6 +95,8 @@ func run() error {
|
||||
|
||||
log.Info().Str("credential", cred.Email).Msg("credential loaded")
|
||||
|
||||
credForTracker = cred
|
||||
|
||||
pool := auth.NewPool([]*auth.Credential{cred})
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
@@ -92,6 +104,7 @@ func run() error {
|
||||
|
||||
pool.RefreshExpiring(context.Background())
|
||||
auth.StartBackgroundRefresh(ctx, pool)
|
||||
tracker.Start(ctx)
|
||||
|
||||
var profile *proxy.SniffedProfile
|
||||
if cfg.ClaudeBinary != "" {
|
||||
@@ -103,7 +116,7 @@ func run() error {
|
||||
}
|
||||
|
||||
log.Info().Int("port", cfg.Port).Msg("starting server")
|
||||
srv := server.New(cfg, pool, profile)
|
||||
srv := server.New(cfg, pool, profile, tracker)
|
||||
|
||||
quit := make(chan os.Signal, 1)
|
||||
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
|
||||
|
||||
Reference in New Issue
Block a user