mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-07-28 16:56:16 +08:00
fix(usage): correct cache cost semantics and silence pricing warn storm
- Split CostCalculator into per-app cache semantics: Anthropic's input_tokens is already fresh input, while Codex/Gemini include cached tokens in their prompt count. The old shared formula double-subtracted cache_read for Claude, under-billing input cost. - Backfill now reads cost_multiplier from the per-log snapshot column instead of re-querying providers.meta, so historical rows are no longer rewritten with the current multiplier. - Move the "pricing not found" warn out of find_model_pricing_row; emit it only when a brand new log is written, and skip placeholder models (unknown / empty / null / none) entirely. - Broaden model id normalization: strip namespace prefixes (anthropic./openai./global./bedrock.), bedrock-style -vN suffixes, reasoning effort suffixes (-low/-medium/-high/-xhigh/-minimal), Claude Desktop's claude-<non-anthropic> wrapper, dot-to-dash for Claude, and try a LIKE prefix match for Claude short route ids (e.g. claude-haiku-4-5 -> claude-haiku-4-5-20251001). - Fall back to request_model when the stored model is missing, so early Codex session rows with model=unknown can still be priced.
This commit is contained in:
@@ -4,7 +4,7 @@ use super::calculator::{CostBreakdown, CostCalculator, ModelPricing};
|
||||
use super::parser::TokenUsage;
|
||||
use crate::database::Database;
|
||||
use crate::error::AppError;
|
||||
use crate::services::usage_stats::find_model_pricing_row;
|
||||
use crate::services::usage_stats::{find_model_pricing_row, is_placeholder_pricing_model};
|
||||
use rust_decimal::Decimal;
|
||||
use std::{str::FromStr, time::SystemTime};
|
||||
|
||||
@@ -303,11 +303,21 @@ impl<'a> UsageLogger<'a> {
|
||||
) -> Result<(), AppError> {
|
||||
let pricing = self.get_model_pricing(&pricing_model)?;
|
||||
|
||||
if pricing.is_none() {
|
||||
let has_usage = usage.input_tokens > 0
|
||||
|| usage.output_tokens > 0
|
||||
|| usage.cache_read_tokens > 0
|
||||
|| usage.cache_creation_tokens > 0;
|
||||
|
||||
if pricing.is_none() && has_usage && !is_placeholder_pricing_model(&pricing_model) {
|
||||
log::warn!("[USG-002] 模型定价未找到,成本将记录为 0: {pricing_model}");
|
||||
}
|
||||
|
||||
let cost = CostCalculator::try_calculate(&usage, pricing.as_ref(), cost_multiplier);
|
||||
let cost = CostCalculator::try_calculate_for_app(
|
||||
&app_type,
|
||||
&usage,
|
||||
pricing.as_ref(),
|
||||
cost_multiplier,
|
||||
);
|
||||
|
||||
let log = RequestLog {
|
||||
request_id,
|
||||
|
||||
Reference in New Issue
Block a user