Class: Tracebook::DailyRollupsJob
- Inherits:
-
ApplicationJob
- Object
- ActiveJob::Base
- ApplicationJob
- Tracebook::DailyRollupsJob
- Defined in:
- app/jobs/tracebook/daily_rollups_job.rb
Overview
Background job for aggregating daily metrics.
Summarizes interactions by date/provider/model/project into RollupDaily records for analytics and cost reporting. Should be scheduled nightly for each active provider/model combination.
Aggregated Metrics
- Total interaction count
- Success/error counts
- Input/output token sums
- Total cost in cents
Instance Method Summary collapse
- #determine_currency(scope) ⇒ Object private
- #integer_string?(value) ⇒ Boolean private
- #normalize_status_counts(counts) ⇒ Object private
-
#perform(date:, provider:, model:, project: nil) ⇒ void
Aggregates metrics for a specific date/provider/model/project.
- #status_name_for(raw_key) ⇒ Object private
Instance Method Details
#determine_currency(scope) ⇒ Object (private)
92 93 94 95 96 |
# File 'app/jobs/tracebook/daily_rollups_job.rb', line 92 def determine_currency(scope) scope.pick(:currency) rescue NoMethodError scope.first&.currency end |
#integer_string?(value) ⇒ Boolean (private)
88 89 90 |
# File 'app/jobs/tracebook/daily_rollups_job.rb', line 88 def integer_string?(value) value.match?(/\A-?\d+\z/) end |
#normalize_status_counts(counts) ⇒ Object (private)
72 73 74 75 76 77 78 79 |
# File 'app/jobs/tracebook/daily_rollups_job.rb', line 72 def normalize_status_counts(counts) counts.each_with_object(Hash.new(0)) do |(raw_key, count), normalized| status_name = status_name_for(raw_key) next unless status_name normalized[status_name] += count end end |
#perform(date:, provider:, model:, project: nil) ⇒ void
This method returns an undefined value.
Aggregates metrics for a specific date/provider/model/project.
Creates or updates a RollupDaily record with summarized statistics.
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
# File 'app/jobs/tracebook/daily_rollups_job.rb', line 46 def perform(date:, provider:, model:, project: nil) scope = Interaction.where(provider: provider, model: model) scope = scope.where(project: project) if project scope = scope.where(created_at: date.beginning_of_day..date.end_of_day) counts = normalize_status_counts(scope.group(:status).count) tokens = scope.pluck(Arel.sql("COALESCE(input_tokens, 0)"), Arel.sql("COALESCE(output_tokens, 0)")) costs = scope.pluck(Arel.sql("COALESCE(cost_total_cents, 0)")) input_sum = tokens.sum { |(input, _)| input.to_i } output_sum = tokens.sum { |(_, output)| output.to_i } cost_sum = costs.sum(&:to_i) rollup = RollupDaily.find_or_initialize_by(date: date, provider: provider, model: model, project: project) rollup.interactions_count = scope.count rollup.success_count = counts.fetch("success", 0) rollup.error_count = counts.fetch("error", 0) rollup.input_tokens_sum = input_sum rollup.output_tokens_sum = output_sum rollup.cost_cents_sum = cost_sum rollup.currency = determine_currency(scope) || rollup.currency rollup.save! end |
#status_name_for(raw_key) ⇒ Object (private)
81 82 83 84 85 86 |
# File 'app/jobs/tracebook/daily_rollups_job.rb', line 81 def status_name_for(raw_key) key_string = raw_key.to_s return key_string if Interaction.statuses.key?(key_string) integer_string?(key_string) ? Interaction.statuses.invert[key_string.to_i] : nil end |