llm_cost_tracker 0.1.2 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +48 -0
- data/README.md +149 -32
- data/lib/llm_cost_tracker/budget.rb +7 -19
- data/lib/llm_cost_tracker/configuration.rb +52 -10
- data/lib/llm_cost_tracker/cost.rb +15 -0
- data/lib/llm_cost_tracker/event.rb +24 -0
- data/lib/llm_cost_tracker/generators/llm_cost_tracker/prices_generator.rb +20 -0
- data/lib/llm_cost_tracker/generators/llm_cost_tracker/templates/llm_cost_tracker_prices.yml.erb +36 -0
- data/lib/llm_cost_tracker/llm_api_call.rb +56 -44
- data/lib/llm_cost_tracker/logging.rb +44 -0
- data/lib/llm_cost_tracker/middleware/faraday.rb +15 -12
- data/lib/llm_cost_tracker/parsed_usage.rb +45 -0
- data/lib/llm_cost_tracker/parsers/anthropic.rb +2 -3
- data/lib/llm_cost_tracker/parsers/base.rb +2 -0
- data/lib/llm_cost_tracker/parsers/gemini.rb +4 -4
- data/lib/llm_cost_tracker/parsers/openai.rb +4 -22
- data/lib/llm_cost_tracker/parsers/openai_compatible.rb +12 -8
- data/lib/llm_cost_tracker/parsers/openai_usage.rb +33 -0
- data/lib/llm_cost_tracker/price_registry.rb +36 -6
- data/lib/llm_cost_tracker/pricing.rb +36 -10
- data/lib/llm_cost_tracker/railtie.rb +5 -0
- data/lib/llm_cost_tracker/report.rb +29 -0
- data/lib/llm_cost_tracker/report_data.rb +81 -0
- data/lib/llm_cost_tracker/report_formatter.rb +65 -0
- data/lib/llm_cost_tracker/storage/active_record_backend.rb +19 -0
- data/lib/llm_cost_tracker/storage/active_record_store.rb +11 -11
- data/lib/llm_cost_tracker/storage/backends.rb +26 -0
- data/lib/llm_cost_tracker/storage/custom_backend.rb +16 -0
- data/lib/llm_cost_tracker/storage/log_backend.rb +28 -0
- data/lib/llm_cost_tracker/tag_accessors.rb +15 -0
- data/lib/llm_cost_tracker/tag_query.rb +38 -0
- data/lib/llm_cost_tracker/tags_column.rb +16 -0
- data/lib/llm_cost_tracker/tracker.rb +18 -67
- data/lib/llm_cost_tracker/unknown_pricing.rb +8 -15
- data/lib/llm_cost_tracker/value_object.rb +45 -0
- data/lib/llm_cost_tracker/version.rb +1 -1
- data/lib/llm_cost_tracker.rb +28 -13
- data/lib/tasks/llm_cost_tracker.rake +9 -0
- data/llm_cost_tracker.gemspec +1 -1
- metadata +22 -3
data/lib/llm_cost_tracker.rb
CHANGED
|
@@ -6,9 +6,15 @@ require "active_support/notifications"
|
|
|
6
6
|
require_relative "llm_cost_tracker/version"
|
|
7
7
|
require_relative "llm_cost_tracker/configuration"
|
|
8
8
|
require_relative "llm_cost_tracker/errors"
|
|
9
|
+
require_relative "llm_cost_tracker/logging"
|
|
10
|
+
require_relative "llm_cost_tracker/value_object"
|
|
11
|
+
require_relative "llm_cost_tracker/cost"
|
|
12
|
+
require_relative "llm_cost_tracker/event"
|
|
13
|
+
require_relative "llm_cost_tracker/parsed_usage"
|
|
9
14
|
require_relative "llm_cost_tracker/price_registry"
|
|
10
15
|
require_relative "llm_cost_tracker/pricing"
|
|
11
16
|
require_relative "llm_cost_tracker/parsers/base"
|
|
17
|
+
require_relative "llm_cost_tracker/parsers/openai_usage"
|
|
12
18
|
require_relative "llm_cost_tracker/parsers/openai"
|
|
13
19
|
require_relative "llm_cost_tracker/parsers/openai_compatible"
|
|
14
20
|
require_relative "llm_cost_tracker/parsers/anthropic"
|
|
@@ -18,7 +24,14 @@ require_relative "llm_cost_tracker/middleware/faraday"
|
|
|
18
24
|
require_relative "llm_cost_tracker/budget"
|
|
19
25
|
require_relative "llm_cost_tracker/unknown_pricing"
|
|
20
26
|
require_relative "llm_cost_tracker/event_metadata"
|
|
27
|
+
require_relative "llm_cost_tracker/tags_column"
|
|
28
|
+
require_relative "llm_cost_tracker/tag_query"
|
|
29
|
+
require_relative "llm_cost_tracker/tag_accessors"
|
|
30
|
+
require_relative "llm_cost_tracker/storage/backends"
|
|
21
31
|
require_relative "llm_cost_tracker/tracker"
|
|
32
|
+
require_relative "llm_cost_tracker/report_data"
|
|
33
|
+
require_relative "llm_cost_tracker/report_formatter"
|
|
34
|
+
require_relative "llm_cost_tracker/report"
|
|
22
35
|
|
|
23
36
|
module LlmCostTracker
|
|
24
37
|
class << self
|
|
@@ -30,6 +43,10 @@ module LlmCostTracker
|
|
|
30
43
|
@configuration || CONFIGURATION_MUTEX.synchronize { @configuration ||= Configuration.new }
|
|
31
44
|
end
|
|
32
45
|
|
|
46
|
+
# Configure the gem once during application boot.
|
|
47
|
+
#
|
|
48
|
+
# @yieldparam configuration [LlmCostTracker::Configuration]
|
|
49
|
+
# @return [void]
|
|
33
50
|
def configure
|
|
34
51
|
yield(configuration)
|
|
35
52
|
configuration.normalize_openai_compatible_providers!
|
|
@@ -40,7 +57,7 @@ module LlmCostTracker
|
|
|
40
57
|
CONFIGURATION_MUTEX.synchronize { @configuration = Configuration.new }
|
|
41
58
|
end
|
|
42
59
|
|
|
43
|
-
#
|
|
60
|
+
# Track an LLM request manually for non-Faraday clients.
|
|
44
61
|
#
|
|
45
62
|
# LlmCostTracker.track(
|
|
46
63
|
# provider: :openai,
|
|
@@ -50,6 +67,14 @@ module LlmCostTracker
|
|
|
50
67
|
# feature: "chat",
|
|
51
68
|
# user_id: current_user.id
|
|
52
69
|
# )
|
|
70
|
+
#
|
|
71
|
+
# @param provider [String, Symbol] Provider name, such as :openai or :anthropic.
|
|
72
|
+
# @param model [String] Provider model identifier.
|
|
73
|
+
# @param input_tokens [Integer] Billed input token count.
|
|
74
|
+
# @param output_tokens [Integer] Billed output token count.
|
|
75
|
+
# @param latency_ms [Integer, nil] Optional request latency in milliseconds.
|
|
76
|
+
# @param metadata [Hash] Attribution tags and provider-specific usage metadata.
|
|
77
|
+
# @return [LlmCostTracker::Event] The tracked event.
|
|
53
78
|
def track(provider:, model:, input_tokens:, output_tokens:, latency_ms: nil, **metadata)
|
|
54
79
|
Tracker.record(
|
|
55
80
|
provider: provider.to_s,
|
|
@@ -64,20 +89,10 @@ module LlmCostTracker
|
|
|
64
89
|
private
|
|
65
90
|
|
|
66
91
|
def warn_for_configuration!
|
|
67
|
-
return unless
|
|
92
|
+
return unless configuration.budget_exceeded_behavior == :block_requests
|
|
68
93
|
return if configuration.active_record?
|
|
69
94
|
|
|
70
|
-
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
def log_warning(message)
|
|
74
|
-
message = "[LlmCostTracker] #{message}"
|
|
75
|
-
|
|
76
|
-
if defined?(Rails) && Rails.respond_to?(:logger) && Rails.logger
|
|
77
|
-
Rails.logger.warn(message)
|
|
78
|
-
else
|
|
79
|
-
warn message
|
|
80
|
-
end
|
|
95
|
+
Logging.warn(":block_requests requires storage_backend = :active_record; preflight blocking will be skipped.")
|
|
81
96
|
end
|
|
82
97
|
end
|
|
83
98
|
end
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
namespace :llm_cost_tracker do
|
|
4
|
+
desc "Print an LLM cost report from ActiveRecord storage"
|
|
5
|
+
task report: :environment do
|
|
6
|
+
days = (ENV["DAYS"] || LlmCostTracker::Report::DEFAULT_DAYS).to_i
|
|
7
|
+
puts LlmCostTracker::Report.generate(days: days)
|
|
8
|
+
end
|
|
9
|
+
end
|
data/llm_cost_tracker.gemspec
CHANGED
|
@@ -12,7 +12,7 @@ Gem::Specification.new do |spec|
|
|
|
12
12
|
spec.description = "Tracks token usage and estimated costs for OpenAI, Anthropic, Google Gemini, " \
|
|
13
13
|
"OpenRouter, DeepSeek, and OpenAI-compatible calls. " \
|
|
14
14
|
"Works as Faraday middleware for Ruby clients, with ActiveRecord storage, " \
|
|
15
|
-
"per-user/per-feature attribution,
|
|
15
|
+
"per-user/per-feature attribution, and budget guardrails."
|
|
16
16
|
spec.homepage = "https://github.com/sergey-homenko/llm_cost_tracker"
|
|
17
17
|
spec.license = "MIT"
|
|
18
18
|
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: llm_cost_tracker
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Sergii Khomenko
|
|
@@ -142,8 +142,8 @@ dependencies:
|
|
|
142
142
|
version: '3.0'
|
|
143
143
|
description: Tracks token usage and estimated costs for OpenAI, Anthropic, Google
|
|
144
144
|
Gemini, OpenRouter, DeepSeek, and OpenAI-compatible calls. Works as Faraday middleware
|
|
145
|
-
for Ruby clients, with ActiveRecord storage, per-user/per-feature attribution,
|
|
146
|
-
|
|
145
|
+
for Ruby clients, with ActiveRecord storage, per-user/per-feature attribution, and
|
|
146
|
+
budget guardrails.
|
|
147
147
|
email:
|
|
148
148
|
- sergey@mm.st
|
|
149
149
|
executables: []
|
|
@@ -159,33 +159,52 @@ files:
|
|
|
159
159
|
- lib/llm_cost_tracker.rb
|
|
160
160
|
- lib/llm_cost_tracker/budget.rb
|
|
161
161
|
- lib/llm_cost_tracker/configuration.rb
|
|
162
|
+
- lib/llm_cost_tracker/cost.rb
|
|
162
163
|
- lib/llm_cost_tracker/errors.rb
|
|
164
|
+
- lib/llm_cost_tracker/event.rb
|
|
163
165
|
- lib/llm_cost_tracker/event_metadata.rb
|
|
164
166
|
- lib/llm_cost_tracker/generators/llm_cost_tracker/add_latency_ms_generator.rb
|
|
165
167
|
- lib/llm_cost_tracker/generators/llm_cost_tracker/install_generator.rb
|
|
168
|
+
- lib/llm_cost_tracker/generators/llm_cost_tracker/prices_generator.rb
|
|
166
169
|
- lib/llm_cost_tracker/generators/llm_cost_tracker/templates/add_latency_ms_to_llm_api_calls.rb.erb
|
|
167
170
|
- lib/llm_cost_tracker/generators/llm_cost_tracker/templates/create_llm_api_calls.rb.erb
|
|
168
171
|
- lib/llm_cost_tracker/generators/llm_cost_tracker/templates/initializer.rb.erb
|
|
172
|
+
- lib/llm_cost_tracker/generators/llm_cost_tracker/templates/llm_cost_tracker_prices.yml.erb
|
|
169
173
|
- lib/llm_cost_tracker/generators/llm_cost_tracker/templates/upgrade_llm_api_call_cost_precision.rb.erb
|
|
170
174
|
- lib/llm_cost_tracker/generators/llm_cost_tracker/templates/upgrade_llm_api_call_tags_to_jsonb.rb.erb
|
|
171
175
|
- lib/llm_cost_tracker/generators/llm_cost_tracker/upgrade_cost_precision_generator.rb
|
|
172
176
|
- lib/llm_cost_tracker/generators/llm_cost_tracker/upgrade_tags_to_jsonb_generator.rb
|
|
173
177
|
- lib/llm_cost_tracker/llm_api_call.rb
|
|
178
|
+
- lib/llm_cost_tracker/logging.rb
|
|
174
179
|
- lib/llm_cost_tracker/middleware/faraday.rb
|
|
180
|
+
- lib/llm_cost_tracker/parsed_usage.rb
|
|
175
181
|
- lib/llm_cost_tracker/parsers/anthropic.rb
|
|
176
182
|
- lib/llm_cost_tracker/parsers/base.rb
|
|
177
183
|
- lib/llm_cost_tracker/parsers/gemini.rb
|
|
178
184
|
- lib/llm_cost_tracker/parsers/openai.rb
|
|
179
185
|
- lib/llm_cost_tracker/parsers/openai_compatible.rb
|
|
186
|
+
- lib/llm_cost_tracker/parsers/openai_usage.rb
|
|
180
187
|
- lib/llm_cost_tracker/parsers/registry.rb
|
|
181
188
|
- lib/llm_cost_tracker/price_registry.rb
|
|
182
189
|
- lib/llm_cost_tracker/prices.json
|
|
183
190
|
- lib/llm_cost_tracker/pricing.rb
|
|
184
191
|
- lib/llm_cost_tracker/railtie.rb
|
|
192
|
+
- lib/llm_cost_tracker/report.rb
|
|
193
|
+
- lib/llm_cost_tracker/report_data.rb
|
|
194
|
+
- lib/llm_cost_tracker/report_formatter.rb
|
|
195
|
+
- lib/llm_cost_tracker/storage/active_record_backend.rb
|
|
185
196
|
- lib/llm_cost_tracker/storage/active_record_store.rb
|
|
197
|
+
- lib/llm_cost_tracker/storage/backends.rb
|
|
198
|
+
- lib/llm_cost_tracker/storage/custom_backend.rb
|
|
199
|
+
- lib/llm_cost_tracker/storage/log_backend.rb
|
|
200
|
+
- lib/llm_cost_tracker/tag_accessors.rb
|
|
201
|
+
- lib/llm_cost_tracker/tag_query.rb
|
|
202
|
+
- lib/llm_cost_tracker/tags_column.rb
|
|
186
203
|
- lib/llm_cost_tracker/tracker.rb
|
|
187
204
|
- lib/llm_cost_tracker/unknown_pricing.rb
|
|
205
|
+
- lib/llm_cost_tracker/value_object.rb
|
|
188
206
|
- lib/llm_cost_tracker/version.rb
|
|
207
|
+
- lib/tasks/llm_cost_tracker.rake
|
|
189
208
|
- llm_cost_tracker.gemspec
|
|
190
209
|
homepage: https://github.com/sergey-homenko/llm_cost_tracker
|
|
191
210
|
licenses:
|