| 49 | |
| 50 | impl UsageAccumulator { |
| 51 | fn add_entry(&mut self, entry: &LoadedEntry) { |
| 52 | let usage = entry.data.message.usage; |
| 53 | self.counts.add_usage(usage); |
| 54 | self.counts.extra_total_tokens += entry.extra_total_tokens; |
| 55 | self.cost += entry.cost; |
| 56 | if let Some(credits) = entry.credits { |
| 57 | *self.credits.get_or_insert(0.0) += credits; |
| 58 | } |
| 59 | if let Some(message_count) = entry.message_count { |
| 60 | *self.message_count.get_or_insert(0) += message_count; |
| 61 | } |
| 62 | if let Some(model) = &entry.model { |
| 63 | let model = crate::model_aliases::resolve_model_name(model); |
| 64 | let index = if let Some(index) = self.breakdown_indexes.get(model.as_ref()) { |
| 65 | *index |
| 66 | } else { |
| 67 | let index = self.breakdowns.len(); |
| 68 | let owned = model.into_owned(); |
| 69 | self.breakdown_indexes.insert(owned.clone(), index); |
| 70 | self.models.push(owned.clone()); |
| 71 | self.breakdowns.push(ModelBreakdown { |
| 72 | model_name: owned, |
| 73 | ..ModelBreakdown::default() |
| 74 | }); |
| 75 | index |
| 76 | }; |
| 77 | let breakdown = &mut self.breakdowns[index]; |
| 78 | breakdown.input_tokens += usage.input_tokens; |
| 79 | breakdown.output_tokens += usage.output_tokens; |
| 80 | breakdown.cache_creation_tokens += usage.cache_creation_token_count(); |
| 81 | breakdown.cache_read_tokens += usage.cache_read_input_tokens; |
| 82 | breakdown.extra_total_tokens += entry.extra_total_tokens; |
| 83 | breakdown.cost += entry.cost; |
| 84 | if entry.missing_pricing_model.is_some() { |
| 85 | breakdown.missing_pricing = true; |
| 86 | } |
| 87 | } |
| 88 | } |
| 89 | |
| 90 | fn into_summary(mut self) -> UsageSummary { |
| 91 | self.breakdowns.sort_by(|a, b| b.cost.total_cmp(&a.cost)); |