open_router_usage_tracker 0.1.0

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 2942349a31ca24bfb080791b3dba9bcb36eaf6fc9709718fe989e65c968ee489
4
+ data.tar.gz: 57459071b36f2873e5dedf5f4c4d9d98bd1327527edeca2ff9c7bfaff7c14098
5
+ SHA512:
6
+ metadata.gz: 961ca4017ed1159fb13920d86a07ad4ca78b7bea40f2d105893bdc57653a3deed4164c047b858c0cb5a779419deebd0cdc0a1f0e65d87dab232052b27558f44f
7
+ data.tar.gz: 3c538fda52c54f226498c6f845d84f7fdd0e42ee78c582062a42fd529d54946ecb10ea470cc2ec7a59a68648358c7d454fbe771661454107f25d21e7a600a436
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright MclPio
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,102 @@
1
+ # OpenRouterUsageTracker
2
+ [![Gem Version](https://badge.fury.io/rb/open_router_usage_tracker.svg)](https://badge.fury.io/rb/open_router_usage_tracker)
3
+ [![Build Status](https://github.com/mclpio/open_router_usage_tracker/actions/workflows/ci.yml/badge.svg)](https://github.com/mclpio/open_router_usage_tracker/actions)
4
+
5
+ An effortless Rails engine to track API token usage and cost from [OpenRouter.io](https://openrouter.ai/), enabling easy rate-limiting and monitoring for your users.
6
+
7
+ ## Motivation
8
+ Managing Large Language Model (LLM) API costs is crucial for any application that provides AI features to users. This gem provides simple, out-of-the-box tools to log every OpenRouter API call, associate it with a user, and query their usage over time. This allows you to easily implement spending caps, rate limits, or usage-based billing tiers.
9
+
10
+ ## Installation
11
+ Add this line to your application's Gemfile:
12
+
13
+ ```ruby
14
+ gem "open_router_usage_tracker"
15
+ ```
16
+
17
+ And then execute:
18
+ ```bash
19
+ $ bundle
20
+ ```
21
+
22
+ Or install it yourself as:
23
+ ```bash
24
+ $ gem install open_router_usage_tracker
25
+ ```
26
+
27
+ ## Setup
28
+
29
+ 1. **Run the Install Generator**: This will create a migration file in your application to add the open_router_usage_logs table.
30
+ ```bash
31
+ bin/rails g open_router_usage_tracker:install
32
+ ```
33
+
34
+ 1. **Run the Database Migration**:
35
+ ```bash
36
+ bin/rails db:migrate
37
+ ```
38
+
39
+ 1. **Include the `Trackable` Concern**: To add the usage tracking methods (`usage_in_period`, etc.) to your user model, include the concern. This works with any user-like model (e.g., `User`, `Account`).
40
+ ```ruby
41
+ # app/models/user.rb
42
+ class User < ApplicationRecord
43
+ include OpenRouterUsageTracker::Trackable
44
+
45
+ # ... rest of your model
46
+ end
47
+ ```
48
+
49
+ ## Usage
50
+ Using the gem involves two parts: logging new requests and tracking existing usage.
51
+
52
+ ### Logging a Request
53
+ In your application where you receive a successful response from the OpenRouter API, call the `log` method. It's designed to be simple and fail loudly if the data is invalid.
54
+
55
+ ```ruby
56
+ # Assume `api_response` is the parsed JSON hash from OpenRouter
57
+ # and `current_user` is your authenticated user object.
58
+
59
+ begin
60
+ OpenRouterUsageTracker.log(response: api_response, user: current_user)
61
+ rescue ActiveRecord::RecordInvalid => e
62
+ # This can happen if the response hash is missing required keys
63
+ # (e.g., 'id', 'model', 'usage').
64
+ logger.error "Failed to log OpenRouter usage: #{e.message}"
65
+ end
66
+ ```
67
+
68
+ ### Tracking Usage
69
+ The `Trackable` concern adds powerful querying methods to your user model.
70
+
71
+ The main method is `usage_in_period(range)`, which returns a hash containing the total tokens and cost for a given time range.
72
+
73
+ **Example: Implementing a rate limit**
74
+
75
+ Imagine you want to prevent users from using more than 100,000 tokens in a 24-hour period.
76
+
77
+ ```ruby
78
+ # somewhere in a controller or before_action
79
+
80
+ def check_usage_limit
81
+ usage = current_user.usage_in_last_24_hours
82
+
83
+ if usage[:tokens] > 100_000
84
+ render json: { error: "You have exceeded your daily usage limit." }, status: :too_many_requests
85
+ return
86
+ end
87
+ end
88
+ ```
89
+
90
+ The gem also provides `usage_in_last_24_hours` as a convenience method and you can always get all the data using `usage_logs`.
91
+
92
+ ## Contributing
93
+ Open an issue first.
94
+
95
+ 1. Fork the repository.
96
+ 1. Create your feature branch (git checkout -b my-new-feature).
97
+ 1. Commit your changes (git commit -am 'Add some feature').
98
+ 1. Push to the branch (git push origin my-new-feature).
99
+ 1. Create a new Pull Request.
100
+
101
+ ## License
102
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,3 @@
1
+ require "bundler/setup"
2
+
3
+ require "bundler/gem_tasks"
@@ -0,0 +1,32 @@
1
+ require "active_support/concern"
2
+
3
+ module OpenRouterUsageTracker
4
+ module Trackable
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ has_many :usage_logs, as: :user, class_name: "OpenRouterUsageTracker::UsageLog", dependent: :destroy
9
+ end
10
+
11
+ # A flexible method to query usage within any time period.
12
+ #
13
+ # Example:
14
+ # user.usage_in_period(24.hours.ago..Time.current)
15
+ # => { tokens: 1500, cost: 0.025 }
16
+ #
17
+ def usage_in_period(range)
18
+ logs_in_range = self.usage_logs.where(created_at: range)
19
+
20
+ # Use .to_i and .to_d to handle cases where there are no logs (sum returns nil)
21
+ total_tokens = logs_in_range.sum(:total_tokens).to_i
22
+ total_cost = logs_in_range.sum(:cost).to_d
23
+
24
+ { tokens: total_tokens, cost: total_cost }
25
+ end
26
+
27
+ # A convenience method for checking the last 24 hours.
28
+ def usage_in_last_24_hours
29
+ usage_in_period(24.hours.ago..Time.current)
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,17 @@
1
+ module OpenRouterUsageTracker
2
+ # This class represents a single entry of an OpenRouter API call.
3
+ class UsageLog < ApplicationRecord
4
+ self.table_name = "open_router_usage_logs"
5
+
6
+ belongs_to :user, polymorphic: true
7
+
8
+ validates :model, presence: true
9
+ validates :prompt_tokens, presence: true
10
+ validates :completion_tokens, presence: true
11
+ validates :total_tokens, presence: true
12
+ validates :cost, presence: true
13
+ validates :raw_usage_response, presence: true
14
+
15
+ validates :request_id, presence: true, uniqueness: true
16
+ end
17
+ end
@@ -0,0 +1,18 @@
1
+ require "rails/generators"
2
+ require "rails/generators/migration"
3
+
4
+ module OpenRouterUsageTracker
5
+ class InstallGenerator < Rails::Generators::Base
6
+ include Rails::Generators::Migration
7
+
8
+ source_root File.expand_path("templates", __dir__)
9
+
10
+ def self.next_migration_number(dir)
11
+ Time.now.utc.strftime("%Y%m%d%H%M%S")
12
+ end
13
+
14
+ def create_files
15
+ migration_template "migration.rb", "db/migrate/create_open_router_usage_logs.rb"
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,22 @@
1
+ class CreateOpenRouterUsageLogs < ActiveRecord::Migration[8.0]
2
+ def change
3
+ create_table :open_router_usage_logs do |t|
4
+ t.string :model, null: false
5
+ t.integer :prompt_tokens, null: false
6
+ t.integer :completion_tokens, null: false
7
+ t.integer :total_tokens, null: false
8
+ t.decimal :cost, precision: 10, scale: 5, null: false
9
+ t.references :user, null: false, polymorphic: true
10
+ t.string :request_id, null: false
11
+
12
+ # Storing the raw API response is recommended for auditing and future-proofing.
13
+ # If you are using PostgreSQL, you can change `t.json` to `t.jsonb` for
14
+ # better performance and indexing capabilities.
15
+ t.json :raw_usage_response, null: false, default: {}
16
+
17
+ t.timestamps
18
+ end
19
+
20
+ add_index :open_router_usage_logs, :request_id, unique: true
21
+ end
22
+ end
@@ -0,0 +1,15 @@
1
+ # lib/open_router_usage_tracker/engine.rb
2
+
3
+ require "rails/engine"
4
+
5
+ module OpenRouterUsageTracker
6
+ class Engine < ::Rails::Engine
7
+ initializer "open_router_usage_tracker.migrations" do |app|
8
+ unless app.root.to_s.match root.to_s
9
+ config.paths["db/migrate"].expanded.each do |expanded_path|
10
+ app.config.paths["db/migrate"] << expanded_path
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,4 @@
1
+ module OpenRouterUsageTracker
2
+ class Railtie < ::Rails::Railtie
3
+ end
4
+ end
@@ -0,0 +1,3 @@
1
+ module OpenRouterUsageTracker
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,24 @@
1
+ require "open_router_usage_tracker/version"
2
+ require "open_router_usage_tracker/railtie"
3
+ require "open_router_usage_tracker/engine"
4
+
5
+ module OpenRouterUsageTracker
6
+ class << self
7
+ attr_writer :configuration
8
+
9
+ def log(response:, user:)
10
+ attributes = {
11
+ model: response["model"],
12
+ prompt_tokens: response.dig("usage", "prompt_tokens"),
13
+ completion_tokens: response.dig("usage", "completion_tokens"),
14
+ total_tokens: response.dig("usage", "total_tokens"),
15
+ cost: response.dig("usage", "cost"),
16
+ request_id: response["id"],
17
+ raw_usage_response: response,
18
+ user: user
19
+ }
20
+
21
+ OpenRouterUsageTracker::UsageLog.create!(attributes)
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :open_router_usage_tracker do
3
+ # # Task goes here
4
+ # end
metadata ADDED
@@ -0,0 +1,70 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: open_router_usage_tracker
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - MclPio
8
+ bindir: bin
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: rails
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: 8.0.2
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - ">="
24
+ - !ruby/object:Gem::Version
25
+ version: 8.0.2
26
+ description: This gem is your rocket launch to managing you web app's LLM usage and
27
+ rate limiting users with built in methods!
28
+ email:
29
+ - mclpious@gmail.com
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - MIT-LICENSE
35
+ - README.md
36
+ - Rakefile
37
+ - app/models/concerns/open_router_usage_tracker/trackable.rb
38
+ - app/models/open_router_usage_tracker/usage_log.rb
39
+ - lib/generators/open_router_usage_tracker/install/install_generator.rb
40
+ - lib/generators/open_router_usage_tracker/install/templates/migration.rb
41
+ - lib/open_router_usage_tracker.rb
42
+ - lib/open_router_usage_tracker/engine.rb
43
+ - lib/open_router_usage_tracker/railtie.rb
44
+ - lib/open_router_usage_tracker/version.rb
45
+ - lib/tasks/open_router_usage_tracker_tasks.rake
46
+ homepage: https://github.com/MclPio/open_router_usage_tracker
47
+ licenses:
48
+ - MIT
49
+ metadata:
50
+ homepage_uri: https://github.com/MclPio/open_router_usage_tracker
51
+ source_code_uri: https://github.com/MclPio/open_router_usage_tracker
52
+ changelog_uri: https://github.com/MclPio/open_router_usage_tracker/blob/main/CHANGELOG.md
53
+ rdoc_options: []
54
+ require_paths:
55
+ - lib
56
+ required_ruby_version: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ required_rubygems_version: !ruby/object:Gem::Requirement
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ requirements: []
67
+ rubygems_version: 3.6.9
68
+ specification_version: 4
69
+ summary: Track API token usage and cost from OpenRouter
70
+ test_files: []