Class: OpenRouter::UsageTracker
- Inherits:
-
Object
- Object
- OpenRouter::UsageTracker
- Defined in:
- lib/open_router/usage_tracker.rb
Overview
Tracks token usage and costs across API calls
Instance Attribute Summary collapse
-
#model_usage ⇒ Object
readonly
Returns the value of attribute model_usage.
-
#request_count ⇒ Object
readonly
Returns the value of attribute request_count.
-
#session_start ⇒ Object
readonly
Returns the value of attribute session_start.
-
#total_cached_tokens ⇒ Object
readonly
Returns the value of attribute total_cached_tokens.
-
#total_completion_tokens ⇒ Object
readonly
Returns the value of attribute total_completion_tokens.
-
#total_cost ⇒ Object
readonly
Returns the value of attribute total_cost.
-
#total_prompt_tokens ⇒ Object
readonly
Returns the value of attribute total_prompt_tokens.
Instance Method Summary collapse
-
#average_cost_per_request ⇒ Object
Get average cost per request.
-
#average_tokens_per_request ⇒ Object
Get average tokens per request.
-
#cache_hit_rate ⇒ Object
Get cache hit rate.
-
#export_csv ⇒ Object
Export usage history as CSV.
-
#history(limit: nil) ⇒ Object
Get request history.
-
#initialize ⇒ UsageTracker
constructor
A new instance of UsageTracker.
-
#model_breakdown ⇒ Object
Get model usage breakdown.
-
#most_expensive_model ⇒ Object
Get most expensive model.
-
#most_used_model ⇒ Object
Get most used model.
-
#print_summary ⇒ Object
Pretty print summary to console.
-
#reset! ⇒ Object
Reset all tracking counters.
-
#session_duration ⇒ Object
Get session duration in seconds.
-
#summary ⇒ Object
Get usage summary.
-
#tokens_per_second ⇒ Object
Get tokens per second.
-
#total_tokens ⇒ Object
Get total tokens used.
-
#track(response, model: nil) ⇒ Object
Track usage from a response.
Constructor Details
#initialize ⇒ UsageTracker
Returns a new instance of UsageTracker.
9 10 11 |
# File 'lib/open_router/usage_tracker.rb', line 9 def initialize reset! end |
Instance Attribute Details
#model_usage ⇒ Object (readonly)
Returns the value of attribute model_usage.
6 7 8 |
# File 'lib/open_router/usage_tracker.rb', line 6 def model_usage @model_usage end |
#request_count ⇒ Object (readonly)
Returns the value of attribute request_count.
6 7 8 |
# File 'lib/open_router/usage_tracker.rb', line 6 def request_count @request_count end |
#session_start ⇒ Object (readonly)
Returns the value of attribute session_start.
6 7 8 |
# File 'lib/open_router/usage_tracker.rb', line 6 def session_start @session_start end |
#total_cached_tokens ⇒ Object (readonly)
Returns the value of attribute total_cached_tokens.
6 7 8 |
# File 'lib/open_router/usage_tracker.rb', line 6 def total_cached_tokens @total_cached_tokens end |
#total_completion_tokens ⇒ Object (readonly)
Returns the value of attribute total_completion_tokens.
6 7 8 |
# File 'lib/open_router/usage_tracker.rb', line 6 def total_completion_tokens @total_completion_tokens end |
#total_cost ⇒ Object (readonly)
Returns the value of attribute total_cost.
6 7 8 |
# File 'lib/open_router/usage_tracker.rb', line 6 def total_cost @total_cost end |
#total_prompt_tokens ⇒ Object (readonly)
Returns the value of attribute total_prompt_tokens.
6 7 8 |
# File 'lib/open_router/usage_tracker.rb', line 6 def total_prompt_tokens @total_prompt_tokens end |
Instance Method Details
#average_cost_per_request ⇒ Object
Get average cost per request
81 82 83 84 85 |
# File 'lib/open_router/usage_tracker.rb', line 81 def average_cost_per_request return 0 if @request_count.zero? @total_cost / @request_count end |
#average_tokens_per_request ⇒ Object
Get average tokens per request
74 75 76 77 78 |
# File 'lib/open_router/usage_tracker.rb', line 74 def average_tokens_per_request return 0 if @request_count.zero? total_tokens.to_f / @request_count end |
#cache_hit_rate ⇒ Object
Get cache hit rate
115 116 117 118 119 |
# File 'lib/open_router/usage_tracker.rb', line 115 def cache_hit_rate return 0 if @total_prompt_tokens.zero? (@total_cached_tokens.to_f / @total_prompt_tokens) * 100 end |
#export_csv ⇒ Object
Export usage history as CSV
165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 |
# File 'lib/open_router/usage_tracker.rb', line 165 def export_csv require "csv" CSV.generate do |csv| csv << ["Timestamp", "Model", "Prompt Tokens", "Completion Tokens", "Cached Tokens", "Cost", "Response ID"] @request_history.each do |entry| csv << [ entry[:timestamp].iso8601, entry[:model], entry[:prompt_tokens], entry[:completion_tokens], entry[:cached_tokens], entry[:cost]&.round(4), entry[:response_id] ] end end end |
#history(limit: nil) ⇒ Object
Get request history
185 186 187 |
# File 'lib/open_router/usage_tracker.rb', line 185 def history(limit: nil) limit ? @request_history.last(limit) : @request_history end |
#model_breakdown ⇒ Object
Get model usage breakdown
153 154 155 156 157 158 159 160 161 162 |
# File 'lib/open_router/usage_tracker.rb', line 153 def model_breakdown @model_usage.transform_values do |stats| { requests: stats[:requests], tokens: stats[:prompt_tokens] + stats[:completion_tokens], cost: stats[:cost].round(4), cached_tokens: stats[:cached_tokens] } end end |
#most_expensive_model ⇒ Object
Get most expensive model
108 109 110 111 112 |
# File 'lib/open_router/usage_tracker.rb', line 108 def most_expensive_model return nil if @model_usage.empty? @model_usage.max_by { |_, stats| stats[:cost] }&.first end |
#most_used_model ⇒ Object
Get most used model
101 102 103 104 105 |
# File 'lib/open_router/usage_tracker.rb', line 101 def most_used_model return nil if @model_usage.empty? @model_usage.max_by { |_, stats| stats[:requests] }&.first end |
#print_summary ⇒ Object
Pretty print summary to console
190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 |
# File 'lib/open_router/usage_tracker.rb', line 190 def print_summary summary_data = summary puts "\n#{"=" * 60}" puts " OpenRouter Usage Summary" puts "=" * 60 puts "\nš Session" puts " Started: #{summary_data[:session][:start].strftime("%Y-%m-%d %H:%M:%S")}" puts " Duration: #{format_duration(summary_data[:session][:duration_seconds])}" puts " Requests: #{summary_data[:session][:requests]}" puts "\nš¤ Tokens" puts " Total: #{format_number(summary_data[:tokens][:total])}" puts " Prompt: #{format_number(summary_data[:tokens][:prompt])}" puts " Completion: #{format_number(summary_data[:tokens][:completion])}" puts " Cached: #{format_number(summary_data[:tokens][:cached])} (#{summary_data[:tokens][:cache_hit_rate]})" puts "\nš° Cost" puts " Total: $#{summary_data[:cost][:total]}" puts " Average/Request: $#{summary_data[:cost][:average_per_request]}" puts "\nā” Performance" puts " Tokens/Second: #{summary_data[:performance][:tokens_per_second]}" puts " Average Tokens/Request: #{summary_data[:performance][:average_tokens_per_request]}" if summary_data[:models][:breakdown].any? puts "\nš¤ Models Used" summary_data[:models][:breakdown].each do |model, stats| puts " #{model}:" puts " Requests: #{stats[:requests]}" puts " Tokens: #{format_number(stats[:tokens])}" puts " Cost: $#{stats[:cost]}" end end puts "\n#{"=" * 60}" end |
#reset! ⇒ Object
Reset all tracking counters
14 15 16 17 18 19 20 21 22 23 |
# File 'lib/open_router/usage_tracker.rb', line 14 def reset! @total_prompt_tokens = 0 @total_completion_tokens = 0 @total_cached_tokens = 0 @total_cost = 0.0 @request_count = 0 @model_usage = Hash.new { |h, k| h[k] = create_model_stats } @session_start = Time.now @request_history = [] end |
#session_duration ⇒ Object
Get session duration in seconds
88 89 90 |
# File 'lib/open_router/usage_tracker.rb', line 88 def session_duration Time.now - @session_start end |
#summary ⇒ Object
Get usage summary
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
# File 'lib/open_router/usage_tracker.rb', line 122 def summary { session: { start: @session_start, duration_seconds: session_duration, requests: @request_count }, tokens: { total: total_tokens, prompt: @total_prompt_tokens, completion: @total_completion_tokens, cached: @total_cached_tokens, cache_hit_rate: "#{cache_hit_rate.round(2)}%" }, cost: { total: @total_cost.round(4), average_per_request: average_cost_per_request.round(4) }, performance: { tokens_per_second: tokens_per_second.round(2), average_tokens_per_request: average_tokens_per_request.round(0) }, models: { most_used: most_used_model, most_expensive: most_expensive_model, breakdown: model_breakdown } } end |
#tokens_per_second ⇒ Object
Get tokens per second
93 94 95 96 97 98 |
# File 'lib/open_router/usage_tracker.rb', line 93 def tokens_per_second duration = session_duration return 0 if duration.zero? total_tokens.to_f / duration end |
#total_tokens ⇒ Object
Get total tokens used
69 70 71 |
# File 'lib/open_router/usage_tracker.rb', line 69 def total_tokens @total_prompt_tokens + @total_completion_tokens end |
#track(response, model: nil) ⇒ Object
Track usage from a response
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
# File 'lib/open_router/usage_tracker.rb', line 29 def track(response, model: nil) return unless response model ||= response.model prompt_tokens = response.prompt_tokens completion_tokens = response.completion_tokens cached_tokens = response.cached_tokens cost = response.cost_estimate || estimate_cost(model, prompt_tokens, completion_tokens) # Update totals @total_prompt_tokens += prompt_tokens @total_completion_tokens += completion_tokens @total_cached_tokens += cached_tokens @total_cost += cost if cost @request_count += 1 # Update per-model stats if model @model_usage[model][:prompt_tokens] += prompt_tokens @model_usage[model][:completion_tokens] += completion_tokens @model_usage[model][:cached_tokens] += cached_tokens @model_usage[model][:cost] += cost if cost @model_usage[model][:requests] += 1 end # Store in history @request_history << { timestamp: Time.now, model: model, prompt_tokens: prompt_tokens, completion_tokens: completion_tokens, cached_tokens: cached_tokens, cost: cost, response_id: response.id } self end |