llm_cost_tracker 0.2.0.alpha1 → 0.2.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.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +29 -2
  3. data/README.md +4 -3
  4. data/app/assets/llm_cost_tracker/application.css +760 -0
  5. data/app/controllers/llm_cost_tracker/application_controller.rb +1 -7
  6. data/app/controllers/llm_cost_tracker/assets_controller.rb +13 -0
  7. data/app/controllers/llm_cost_tracker/calls_controller.rb +29 -12
  8. data/app/controllers/llm_cost_tracker/dashboard_controller.rb +5 -1
  9. data/app/helpers/llm_cost_tracker/application_helper.rb +46 -5
  10. data/app/helpers/llm_cost_tracker/chart_helper.rb +133 -0
  11. data/app/helpers/llm_cost_tracker/dashboard_filter_helper.rb +42 -0
  12. data/app/helpers/llm_cost_tracker/dashboard_filter_options_helper.rb +34 -0
  13. data/app/helpers/llm_cost_tracker/dashboard_query_helper.rb +58 -0
  14. data/app/helpers/llm_cost_tracker/pagination_helper.rb +18 -0
  15. data/app/services/llm_cost_tracker/dashboard/filter.rb +0 -3
  16. data/app/services/llm_cost_tracker/dashboard/overview_stats.rb +16 -1
  17. data/app/services/llm_cost_tracker/dashboard/spend_anomaly.rb +79 -0
  18. data/app/services/llm_cost_tracker/dashboard/tag_key_explorer.rb +19 -46
  19. data/app/services/llm_cost_tracker/dashboard/top_models.rb +17 -8
  20. data/app/services/llm_cost_tracker/pagination.rb +6 -0
  21. data/app/views/layouts/llm_cost_tracker/application.html.erb +35 -333
  22. data/app/views/llm_cost_tracker/calls/index.html.erb +106 -74
  23. data/app/views/llm_cost_tracker/calls/show.html.erb +58 -1
  24. data/app/views/llm_cost_tracker/dashboard/index.html.erb +201 -111
  25. data/app/views/llm_cost_tracker/data_quality/index.html.erb +178 -78
  26. data/app/views/llm_cost_tracker/errors/database.html.erb +3 -3
  27. data/app/views/llm_cost_tracker/errors/invalid_filter.html.erb +3 -3
  28. data/app/views/llm_cost_tracker/errors/not_found.html.erb +3 -3
  29. data/app/views/llm_cost_tracker/models/index.html.erb +66 -58
  30. data/app/views/llm_cost_tracker/shared/_active_filters.html.erb +16 -0
  31. data/app/views/llm_cost_tracker/shared/_metric_stack.html.erb +23 -0
  32. data/app/views/llm_cost_tracker/shared/_spend_chart.html.erb +18 -0
  33. data/app/views/llm_cost_tracker/shared/_tag_chips.html.erb +15 -0
  34. data/app/views/llm_cost_tracker/shared/setup_required.html.erb +3 -2
  35. data/app/views/llm_cost_tracker/tags/index.html.erb +55 -12
  36. data/app/views/llm_cost_tracker/tags/show.html.erb +88 -39
  37. data/config/routes.rb +3 -0
  38. data/lib/llm_cost_tracker/assets.rb +24 -0
  39. data/lib/llm_cost_tracker/engine.rb +2 -0
  40. data/lib/llm_cost_tracker/llm_api_call.rb +1 -1
  41. data/lib/llm_cost_tracker/price_registry.rb +17 -6
  42. data/lib/llm_cost_tracker/pricing.rb +19 -6
  43. data/lib/llm_cost_tracker/retention.rb +34 -0
  44. data/lib/llm_cost_tracker/tag_query.rb +7 -2
  45. data/lib/llm_cost_tracker/tags_column.rb +13 -1
  46. data/lib/llm_cost_tracker/version.rb +1 -1
  47. data/lib/llm_cost_tracker.rb +1 -0
  48. data/lib/tasks/llm_cost_tracker.rake +8 -0
  49. data/llm_cost_tracker.gemspec +1 -2
  50. metadata +17 -5
  51. data/PLAN_0.2.md +0 -488
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fc82847cd3008ce0d7015928be7a594a595cf1f4e6eea88380532e5ac3f2e6e4
4
- data.tar.gz: aa47d647351e14b84b170f148e53f2aa2ad406543b889ed5e4bc6bbf5037b4ca
3
+ metadata.gz: eba077a3fb9b0dc146673535769b8be4d34dcbde133ae41e2910652b7833e306
4
+ data.tar.gz: 3b384ad865a23598566ee46974bedda14af88673bbe4822501fb5eb65980655a
5
5
  SHA512:
6
- metadata.gz: 945fe190de9c123a65a7b2a2692fb74090adc0ed461c3b8265d40d8b1da61bb48934b792bb6069029fa96294b87c43dcc924250b4181c3c7bb665a8617ed302e
7
- data.tar.gz: 4c6843af269557a262144de52a003c9f1c79e71427f5000b95c49066a5ecb54b54d00b2fa8096cb82361d8eb24da3925d81852aba981565d601f5a4f827ae86b
6
+ metadata.gz: 2c5d72d58222d3b3f66fe7d1511ce69c8a008b45a31351827d59a13a982b5478f24ce7e14afe1417150e51653452ec1cc43c8a9fc8f1f069148da7489e0c2698
7
+ data.tar.gz: a5a70b59d1622080271d0a1a24259c8630938c132e93cfeb041ef258d3d0a720bb44a1e0b8b5be65c6b9801847f031395f2e1d7adc48d9cf71b83c3f276ae281
data/CHANGELOG.md CHANGED
@@ -2,7 +2,34 @@
2
2
 
3
3
  Format: [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). Versioning: [SemVer](https://semver.org/spec/v2.0.0.html).
4
4
 
5
- ## [0.2.0.alpha1] - 2026-04-20
5
+ ## [Unreleased]
6
+
7
+ ## [0.2.0] - 2026-04-20
8
+
9
+ ### Added
10
+
11
+ - `LlmCostTracker::Retention.prune(older_than:)` and `llm_cost_tracker:prune` rake task.
12
+ - Overview: budget projection, previous-period daily spend comparison, spend anomaly alerts.
13
+ - Call details: token and cost mix breakdowns.
14
+ - Dashboard CSS served as a fingerprinted, immutably-cached file via `LlmCostTracker::AssetsController`.
15
+ - Filter dropdowns for Provider and Model, scoped to the current slice.
16
+ - Pagination with per-page selector and Stripe-style page window.
17
+
18
+ ### Changed
19
+
20
+ - Dashboard UI aligned to Tailwind UI Application UI: dot-indicator badges, value-first stat tiles, inset-shadow form inputs, white secondary buttons with `shadow-sm`.
21
+ - CSS fully namespaced under `lct-*`; removed bare `body` selector to avoid host-app leakage.
22
+
23
+ ### Fixed
24
+
25
+ - Thread-safe price memoization (regression from 0.1.3).
26
+ - `by_tag` on MySQL JSON columns.
27
+ - CSV export escapes formula-prefixed values.
28
+ - Portable dashboard sorting across adapters.
29
+ - Dashboard shows database errors instead of install/setup guidance when the DB is unavailable.
30
+ - Tag key explorer uses SQL discovery on MySQL 8.0+.
31
+
32
+ ## [0.2.0.alpha1, 0.2.0.alpha2] - 2026-04-20
6
33
 
7
34
  ### Breaking
8
35
 
@@ -15,7 +42,7 @@ Format: [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). Versioning: [S
15
42
  ### Added
16
43
 
17
44
  - `LlmApiCall.group_by_period(:day/:month)` — SQL-side period grouping.
18
- - Opt-in `LlmCostTracker::Engine` dashboard (Rails 7.1+): overview with delta-vs-previous-period, provider rollup, models, filterable call list with CSV export and outlier sort modes, call details, tag key explorer, per-key tag breakdown, data quality. PostgreSQL/SQLite use adapter-specific SQL; MySQL falls back to an in-Ruby scan capped at 50k rows. Core middleware still works without Rails.
45
+ - Opt-in `LlmCostTracker::Engine` dashboard (Rails 7.1+): overview with delta-vs-previous-period, provider rollup, models, filterable call list with CSV export and outlier sort modes, call details, tag key explorer, per-key tag breakdown, data quality. PostgreSQL/SQLite use adapter-specific SQL; MySQL 8.0+ uses JSON_TABLE-based tag discovery. Core middleware still works without Rails.
19
46
 
20
47
  ## [0.1.4] - 2026-04-18
21
48
 
data/README.md CHANGED
@@ -201,6 +201,7 @@ rescue LlmCostTracker::BudgetExceededError => e
201
201
  ```bash
202
202
  bin/rails llm_cost_tracker:report
203
203
  DAYS=7 bin/rails llm_cost_tracker:report
204
+ DAYS=90 bin/rails llm_cost_tracker:prune # delete calls older than N days in batches
204
205
  ```
205
206
 
206
207
  ```ruby
@@ -263,11 +264,11 @@ mount LlmCostTracker::Engine => "/llm-costs"
263
264
 
264
265
  Routes (GET-only; CSV export included):
265
266
 
266
- - `/llm-costs` — overview: spend (with delta vs previous period), calls, avg cost/call, avg latency, unknown pricing, budget, daily trend, provider rollup, top models
267
+ - `/llm-costs` — overview: spend with delta vs previous period, budget projection, spend anomaly banner, daily trend vs previous slice, provider rollup, top models
267
268
  - `/llm-costs/models` — by provider + model; sortable by spend, volume, avg cost, latency
268
269
  - `/llm-costs/calls` — filterable + paginated; outlier sort modes (expensive, largest input/output, slowest, unknown pricing); CSV export
269
- - `/llm-costs/calls/:id` — details
270
- - `/llm-costs/tags` — tag keys present in the dataset (PG/SQLite native, MySQL via in-Ruby fallback)
270
+ - `/llm-costs/calls/:id` — details with token mix and cost mix breakdowns
271
+ - `/llm-costs/tags` — tag keys present in the dataset (PG/SQLite native; MySQL 8.0+ via JSON_TABLE)
271
272
  - `/llm-costs/tags/:key` — breakdown by values of a given tag key
272
273
  - `/llm-costs/data_quality` — unknown pricing share, untagged calls, missing latency
273
274