Module: RubyLLM::Agents::BudgetTracker
- Extended by:
- CacheHelper
- Defined in:
- lib/ruby_llm/agents/infrastructure/budget_tracker.rb
Overview
Cache-based budget tracking for cost governance
Tracks spending against configured budget limits using cache counters. Supports daily and monthly budgets at both global and per-agent levels. In multi-tenant mode, budgets are tracked separately per tenant.
Note: Uses best-effort enforcement with cache counters. In high-concurrency scenarios, slight overruns may occur due to race conditions. This is an acceptable trade-off for performance.
Constant Summary
Constants included from CacheHelper
Class Method Summary collapse
-
.calculate_forecast(tenant_id: nil) ⇒ Hash?
Calculates budget forecasts based on current spending trends.
-
.check_budget!(agent_type, tenant_id: nil, tenant_config: nil) ⇒ void
Checks if the current spend exceeds budget limits.
-
.check_token_budget!(agent_type, tenant_id: nil, tenant_config: nil) ⇒ void
Checks if the current token usage exceeds budget limits.
-
.current_spend(scope, period, agent_type: nil, tenant_id: nil) ⇒ Float
Returns the current spend for a scope and period.
-
.current_tokens(period, tenant_id: nil) ⇒ Integer
Returns the current token usage for a period (global only).
-
.record_spend!(agent_type, amount, tenant_id: nil, tenant_config: nil) ⇒ void
Records spend and checks for soft cap alerts.
-
.record_tokens!(agent_type, tokens, tenant_id: nil, tenant_config: nil) ⇒ void
Records token usage and checks for soft cap alerts.
-
.remaining_budget(scope, period, agent_type: nil, tenant_id: nil) ⇒ Float?
Returns the remaining budget for a scope and period.
-
.remaining_token_budget(period, tenant_id: nil) ⇒ Integer?
Returns the remaining token budget for a period (global only).
-
.reset!(tenant_id: nil) ⇒ void
Resets all budget counters (useful for testing).
-
.status(agent_type: nil, tenant_id: nil) ⇒ Hash
Returns a summary of all budget statuses.
Methods included from CacheHelper
cache_delete, cache_exist?, cache_increment, cache_key, cache_read, cache_store, cache_write
Class Method Details
.calculate_forecast(tenant_id: nil) ⇒ Hash?
Calculates budget forecasts based on current spending trends
169 170 171 172 173 174 |
# File 'lib/ruby_llm/agents/infrastructure/budget_tracker.rb', line 169 def calculate_forecast(tenant_id: nil) tenant_id = resolve_tid(tenant_id) budget_config = Budget::ConfigResolver.resolve_budget_config(tenant_id) Budget::Forecaster.calculate_forecast(tenant_id: tenant_id, budget_config: budget_config) end |
.check_budget!(agent_type, tenant_id: nil, tenant_config: nil) ⇒ void
This method returns an undefined value.
Checks if the current spend exceeds budget limits
46 47 48 49 50 51 52 53 54 |
# File 'lib/ruby_llm/agents/infrastructure/budget_tracker.rb', line 46 def check_budget!(agent_type, tenant_id: nil, tenant_config: nil) tenant_id = resolve_tid(tenant_id) budget_config = Budget::ConfigResolver.resolve_budget_config(tenant_id, runtime_config: tenant_config) return unless budget_config[:enabled] return unless budget_config[:enforcement] == :hard check_budget_limits!(agent_type, tenant_id, budget_config) end |
.check_token_budget!(agent_type, tenant_id: nil, tenant_config: nil) ⇒ void
This method returns an undefined value.
Checks if the current token usage exceeds budget limits
63 64 65 66 67 68 69 70 71 |
# File 'lib/ruby_llm/agents/infrastructure/budget_tracker.rb', line 63 def check_token_budget!(agent_type, tenant_id: nil, tenant_config: nil) tenant_id = resolve_tid(tenant_id) budget_config = Budget::ConfigResolver.resolve_budget_config(tenant_id, runtime_config: tenant_config) return unless budget_config[:enabled] return unless budget_config[:enforcement] == :hard check_token_limits!(agent_type, tenant_id, budget_config) end |
.current_spend(scope, period, agent_type: nil, tenant_id: nil) ⇒ Float
Returns the current spend for a scope and period
112 113 114 115 |
# File 'lib/ruby_llm/agents/infrastructure/budget_tracker.rb', line 112 def current_spend(scope, period, agent_type: nil, tenant_id: nil) tenant_id = resolve_tid(tenant_id) Budget::BudgetQuery.current_spend(scope, period, agent_type: agent_type, tenant_id: tenant_id) end |
.current_tokens(period, tenant_id: nil) ⇒ Integer
Returns the current token usage for a period (global only)
122 123 124 125 |
# File 'lib/ruby_llm/agents/infrastructure/budget_tracker.rb', line 122 def current_tokens(period, tenant_id: nil) tenant_id = resolve_tid(tenant_id) Budget::BudgetQuery.current_tokens(period, tenant_id: tenant_id) end |
.record_spend!(agent_type, amount, tenant_id: nil, tenant_config: nil) ⇒ void
This method returns an undefined value.
Records spend and checks for soft cap alerts
80 81 82 83 84 85 86 87 |
# File 'lib/ruby_llm/agents/infrastructure/budget_tracker.rb', line 80 def record_spend!(agent_type, amount, tenant_id: nil, tenant_config: nil) return if amount.nil? || amount <= 0 tenant_id = resolve_tid(tenant_id) budget_config = Budget::ConfigResolver.resolve_budget_config(tenant_id, runtime_config: tenant_config) Budget::SpendRecorder.record_spend!(agent_type, amount, tenant_id: tenant_id, budget_config: budget_config) end |
.record_tokens!(agent_type, tokens, tenant_id: nil, tenant_config: nil) ⇒ void
This method returns an undefined value.
Records token usage and checks for soft cap alerts
96 97 98 99 100 101 102 103 |
# File 'lib/ruby_llm/agents/infrastructure/budget_tracker.rb', line 96 def record_tokens!(agent_type, tokens, tenant_id: nil, tenant_config: nil) return if tokens.nil? || tokens <= 0 tenant_id = resolve_tid(tenant_id) budget_config = Budget::ConfigResolver.resolve_budget_config(tenant_id, runtime_config: tenant_config) Budget::SpendRecorder.record_tokens!(agent_type, tokens, tenant_id: tenant_id, budget_config: budget_config) end |
.remaining_budget(scope, period, agent_type: nil, tenant_id: nil) ⇒ Float?
Returns the remaining budget for a scope and period
134 135 136 137 138 139 |
# File 'lib/ruby_llm/agents/infrastructure/budget_tracker.rb', line 134 def remaining_budget(scope, period, agent_type: nil, tenant_id: nil) tenant_id = resolve_tid(tenant_id) budget_config = Budget::ConfigResolver.resolve_budget_config(tenant_id) Budget::BudgetQuery.remaining_budget(scope, period, agent_type: agent_type, tenant_id: tenant_id, budget_config: budget_config) end |
.remaining_token_budget(period, tenant_id: nil) ⇒ Integer?
Returns the remaining token budget for a period (global only)
146 147 148 149 150 151 |
# File 'lib/ruby_llm/agents/infrastructure/budget_tracker.rb', line 146 def remaining_token_budget(period, tenant_id: nil) tenant_id = resolve_tid(tenant_id) budget_config = Budget::ConfigResolver.resolve_budget_config(tenant_id) Budget::BudgetQuery.remaining_token_budget(period, tenant_id: tenant_id, budget_config: budget_config) end |
.reset!(tenant_id: nil) ⇒ void
This method returns an undefined value.
Resets all budget counters (useful for testing)
180 181 182 183 184 185 186 187 188 189 190 191 |
# File 'lib/ruby_llm/agents/infrastructure/budget_tracker.rb', line 180 def reset!(tenant_id: nil) tenant_id = resolve_tid(tenant_id) tenant_part = Budget::SpendRecorder.tenant_key_part(tenant_id) today = Budget::SpendRecorder.date_key_part(:daily) month = Budget::SpendRecorder.date_key_part(:monthly) BudgetTracker.cache_delete(BudgetTracker.cache_key("budget", tenant_part, today)) BudgetTracker.cache_delete(BudgetTracker.cache_key("budget", tenant_part, month)) # Reset memoized table existence check (useful for testing) Budget::ConfigResolver.reset_tenant_budget_table_check! end |
.status(agent_type: nil, tenant_id: nil) ⇒ Hash
Returns a summary of all budget statuses
158 159 160 161 162 163 |
# File 'lib/ruby_llm/agents/infrastructure/budget_tracker.rb', line 158 def status(agent_type: nil, tenant_id: nil) tenant_id = resolve_tid(tenant_id) budget_config = Budget::ConfigResolver.resolve_budget_config(tenant_id) Budget::BudgetQuery.status(agent_type: agent_type, tenant_id: tenant_id, budget_config: budget_config) end |