use std::time::{SystemTime, UNIX_EPOCH}; use aether_data_contracts::repository::usage::{StoredRequestUsageAudit, UpsertUsageRecord}; use aether_data_contracts::DataLayerError; use serde_json::{Map, Value}; use sqlx::{QueryBuilder, Row, Sqlite, Transaction}; use crate::error::SqlResultExt; #[derive(Debug, Clone, Default, PartialEq, Eq)] pub(crate) struct UsageRoutingSnapshot { candidate_id: Option, candidate_index: Option, key_name: Option, planner_kind: Option, route_family: Option, route_kind: Option, execution_path: Option, local_execution_runtime_miss_reason: Option, selected_provider_id: Option, selected_endpoint_id: Option, selected_provider_api_key_id: Option, has_format_conversion: Option, } impl UsageRoutingSnapshot { fn has_metadata_fields(&self) -> bool { self.candidate_id.is_some() || self.candidate_index.is_some() || self.key_name.is_some() || self.planner_kind.is_some() || self.route_family.is_some() || self.route_kind.is_some() || self.execution_path.is_some() || self.local_execution_runtime_miss_reason.is_some() } fn any_present(&self) -> bool { self.has_metadata_fields() || self.selected_provider_id.is_some() || self.selected_endpoint_id.is_some() || self.selected_provider_api_key_id.is_some() || self.has_format_conversion.is_some() } } #[derive(Debug, Clone, Default, PartialEq)] pub(crate) struct UsageSettlementPricingSnapshot { billing_status: Option, billing_snapshot_schema_version: Option, billing_snapshot_status: Option, settlement_snapshot_schema_version: Option, settlement_snapshot: Option, billing_dimensions: Option, billing_input_tokens: Option, billing_effective_input_tokens: Option, billing_output_tokens: Option, billing_cache_creation_tokens: Option, billing_cache_creation_5m_tokens: Option, billing_cache_creation_1h_tokens: Option, billing_cache_read_tokens: Option, billing_total_input_context: Option, billing_cache_creation_cost_usd: Option, billing_cache_read_cost_usd: Option, billing_total_cost_usd: Option, billing_actual_total_cost_usd: Option, billing_pricing_source: Option, billing_rule_id: Option, billing_rule_version: Option, rate_multiplier: Option, is_free_tier: Option, input_price_per_1m: Option, output_price_per_1m: Option, cache_creation_price_per_1m: Option, cache_read_price_per_1m: Option, price_per_request: Option, } impl UsageSettlementPricingSnapshot { fn any_present(&self) -> bool { self.billing_status.is_some() || self.billing_snapshot_schema_version.is_some() || self.billing_snapshot_status.is_some() || self.settlement_snapshot_schema_version.is_some() || self.settlement_snapshot.is_some() || self.billing_dimensions.is_some() || self.billing_input_tokens.is_some() || self.billing_effective_input_tokens.is_some() || self.billing_output_tokens.is_some() || self.billing_cache_creation_tokens.is_some() || self.billing_cache_creation_5m_tokens.is_some() || self.billing_cache_creation_1h_tokens.is_some() || self.billing_cache_read_tokens.is_some() || self.billing_total_input_context.is_some() || self.billing_cache_creation_cost_usd.is_some() || self.billing_cache_read_cost_usd.is_some() || self.billing_total_cost_usd.is_some() || self.billing_actual_total_cost_usd.is_some() || self.billing_pricing_source.is_some() || self.billing_rule_id.is_some() || self.billing_rule_version.is_some() || self.rate_multiplier.is_some() || self.is_free_tier.is_some() || self.input_price_per_1m.is_some() || self.output_price_per_1m.is_some() || self.cache_creation_price_per_1m.is_some() || self.cache_read_price_per_1m.is_some() || self.price_per_request.is_some() } } pub(crate) fn from_usage( usage: &UpsertUsageRecord, ) -> Result<(UsageRoutingSnapshot, UsageSettlementPricingSnapshot), DataLayerError> { Ok(( routing_snapshot_from_usage(usage), settlement_snapshot_from_usage(usage)?, )) } fn routing_snapshot_from_usage(usage: &UpsertUsageRecord) -> UsageRoutingSnapshot { let metadata = usage.request_metadata.as_ref().and_then(Value::as_object); let mut snapshot = UsageRoutingSnapshot { candidate_id: usage .candidate_id .clone() .or_else(|| metadata_string(metadata, "candidate_id")), candidate_index: usage .candidate_index .or_else(|| metadata_u64(metadata, "candidate_index")), key_name: usage .key_name .clone() .or_else(|| metadata_string(metadata, "key_name")), planner_kind: usage .planner_kind .clone() .or_else(|| metadata_string(metadata, "planner_kind")), route_family: usage .route_family .clone() .or_else(|| metadata_string(metadata, "route_family")), route_kind: usage .route_kind .clone() .or_else(|| metadata_string(metadata, "route_kind")), execution_path: usage .execution_path .clone() .or_else(|| metadata_string(metadata, "execution_path")), local_execution_runtime_miss_reason: usage .local_execution_runtime_miss_reason .clone() .or_else(|| metadata_string(metadata, "local_execution_runtime_miss_reason")), selected_provider_id: None, selected_endpoint_id: None, selected_provider_api_key_id: None, has_format_conversion: None, }; if snapshot.has_metadata_fields() { snapshot.selected_provider_id = usage.provider_id.clone(); snapshot.selected_endpoint_id = usage.provider_endpoint_id.clone(); snapshot.selected_provider_api_key_id = usage.provider_api_key_id.clone(); snapshot.has_format_conversion = usage.has_format_conversion; } snapshot } fn settlement_snapshot_from_usage( usage: &UpsertUsageRecord, ) -> Result { let metadata = usage.request_metadata.as_ref().and_then(Value::as_object); let billing_dimensions = metadata_or_snapshot_dimensions(metadata); let has_billing_dimensions = billing_dimensions.is_some(); let usage_input_tokens = optional_i64(usage.input_tokens, "input_tokens")?; let usage_output_tokens = optional_i64(usage.output_tokens, "output_tokens")?; let usage_cache_creation_uncategorized_tokens = optional_i64( usage.cache_creation_input_tokens, "cache_creation_input_tokens", )?; let usage_cache_creation_5m_tokens = optional_i64( usage.cache_creation_ephemeral_5m_input_tokens, "cache_creation_ephemeral_5m_input_tokens", )?; let usage_cache_creation_1h_tokens = optional_i64( usage.cache_creation_ephemeral_1h_input_tokens, "cache_creation_ephemeral_1h_input_tokens", )?; let usage_cache_read_tokens = optional_i64(usage.cache_read_input_tokens, "cache_read_input_tokens")?; let usage_cache_creation_tokens = cache_creation_tokens_from_parts( usage_cache_creation_uncategorized_tokens, usage_cache_creation_5m_tokens, usage_cache_creation_1h_tokens, ); let billing_cache_creation_tokens = billing_dimension_i64(metadata, "cache_creation_tokens") .or_else(|| { cache_creation_tokens_from_parts( billing_dimension_i64(metadata, "cache_creation_uncategorized_tokens"), billing_dimension_i64(metadata, "cache_creation_ephemeral_5m_tokens"), billing_dimension_i64(metadata, "cache_creation_ephemeral_1h_tokens"), ) }) .or(usage_cache_creation_tokens); let billing_cache_creation_5m_tokens = billing_dimension_i64(metadata, "cache_creation_ephemeral_5m_tokens") .or(usage_cache_creation_5m_tokens); let billing_cache_creation_1h_tokens = billing_dimension_i64(metadata, "cache_creation_ephemeral_1h_tokens") .or(usage_cache_creation_1h_tokens); let billing_input_tokens = billing_dimension_i64(metadata, "input_tokens").or(usage_input_tokens); let billing_output_tokens = billing_dimension_i64(metadata, "output_tokens").or(usage_output_tokens); let billing_cache_read_tokens = billing_dimension_i64(metadata, "cache_read_tokens").or(usage_cache_read_tokens); let api_family = normalized_api_family(usage); let billing_effective_input_tokens = billing_dimension_i64(metadata, "effective_input_tokens") .or_else(|| { has_billing_dimensions .then(|| billing_dimension_i64(metadata, "input_tokens")) .flatten() }) .or_else(|| { effective_input_tokens( billing_input_tokens, billing_cache_creation_tokens, billing_cache_read_tokens, &api_family, ) }); let billing_total_input_context = billing_dimension_i64(metadata, "total_input_context") .or_else(|| { total_input_context( billing_input_tokens, billing_effective_input_tokens, billing_cache_creation_tokens, billing_cache_read_tokens, &api_family, ) }); Ok(UsageSettlementPricingSnapshot { billing_status: Some(usage.billing_status.clone()), billing_snapshot_schema_version: metadata_string( metadata, "billing_snapshot_schema_version", ) .or_else(|| billing_snapshot_string(metadata, "schema_version")), billing_snapshot_status: metadata_string(metadata, "billing_snapshot_status") .or_else(|| billing_snapshot_string(metadata, "status")), settlement_snapshot_schema_version: settlement_snapshot_schema_version(metadata), settlement_snapshot: settlement_snapshot_value(metadata), billing_dimensions, billing_input_tokens, billing_effective_input_tokens, billing_output_tokens, billing_cache_creation_tokens, billing_cache_creation_5m_tokens, billing_cache_creation_1h_tokens, billing_cache_read_tokens, billing_total_input_context, billing_cache_creation_cost_usd: settlement_cache_creation_cost(metadata) .or(usage.cache_creation_cost_usd), billing_cache_read_cost_usd: settlement_cost_breakdown_number(metadata, "cache_read_cost") .or(usage.cache_read_cost_usd), billing_total_cost_usd: settlement_snapshot_number(metadata, "total_cost") .or_else(|| billing_snapshot_number(metadata, "total_cost")) .or(usage.total_cost_usd), billing_actual_total_cost_usd: settlement_snapshot_number(metadata, "actual_total_cost") .or(usage.actual_total_cost_usd), billing_pricing_source: settlement_nested_string( metadata, "pricing_snapshot", "pricing_source", ), billing_rule_id: settlement_nested_string(metadata, "billing_plan_snapshot", "rule_id") .or_else(|| billing_snapshot_string_field(metadata, "rule_id")), billing_rule_version: settlement_nested_string( metadata, "billing_plan_snapshot", "rule_version", ), rate_multiplier: metadata_number(metadata, "rate_multiplier"), is_free_tier: metadata_bool(metadata, "is_free_tier"), input_price_per_1m: metadata_number(metadata, "input_price_per_1m") .or_else(|| billing_snapshot_resolved_number(metadata, "input_price_per_1m")), output_price_per_1m: metadata_number(metadata, "output_price_per_1m") .or_else(|| billing_snapshot_resolved_number(metadata, "output_price_per_1m")) .or(usage.output_price_per_1m), cache_creation_price_per_1m: metadata_number(metadata, "cache_creation_price_per_1m") .or_else(|| billing_snapshot_resolved_number(metadata, "cache_creation_price_per_1m")), cache_read_price_per_1m: metadata_number(metadata, "cache_read_price_per_1m") .or_else(|| billing_snapshot_resolved_number(metadata, "cache_read_price_per_1m")), price_per_request: metadata_number(metadata, "price_per_request") .or_else(|| billing_snapshot_resolved_number(metadata, "price_per_request")), }) } pub(crate) async fn sync( tx: &mut Transaction<'_, Sqlite>, request_id: &str, routing: &UsageRoutingSnapshot, settlement: &UsageSettlementPricingSnapshot, replace_existing: bool, ) -> Result<(), DataLayerError> { sync_routing(tx, request_id, routing, replace_existing).await?; sync_settlement(tx, request_id, settlement, replace_existing).await } async fn sync_routing( tx: &mut Transaction<'_, Sqlite>, request_id: &str, snapshot: &UsageRoutingSnapshot, replace_existing: bool, ) -> Result<(), DataLayerError> { if !snapshot.any_present() && !replace_existing { return Ok(()); } let now = unix_now()?; let mut query = QueryBuilder::::new( "INSERT INTO usage_routing_snapshots (request_id, candidate_id, candidate_index, \ key_name, planner_kind, route_family, route_kind, execution_path, \ local_execution_runtime_miss_reason, selected_provider_id, selected_endpoint_id, \ selected_provider_api_key_id, has_format_conversion, created_at, updated_at) VALUES (", ); { let mut values = query.separated(", "); values .push_bind(request_id) .push_bind(snapshot.candidate_id.as_deref()) .push_bind(optional_i64(snapshot.candidate_index, "candidate_index")?) .push_bind(snapshot.key_name.as_deref()) .push_bind(snapshot.planner_kind.as_deref()) .push_bind(snapshot.route_family.as_deref()) .push_bind(snapshot.route_kind.as_deref()) .push_bind(snapshot.execution_path.as_deref()) .push_bind(snapshot.local_execution_runtime_miss_reason.as_deref()) .push_bind(snapshot.selected_provider_id.as_deref()) .push_bind(snapshot.selected_endpoint_id.as_deref()) .push_bind(snapshot.selected_provider_api_key_id.as_deref()) .push_bind(snapshot.has_format_conversion) .push_bind(now) .push_bind(now); } query.push(") ON CONFLICT (request_id) DO UPDATE SET "); push_sqlite_updates( &mut query, &[ "candidate_id", "candidate_index", "key_name", "planner_kind", "route_family", "route_kind", "execution_path", "local_execution_runtime_miss_reason", "selected_provider_id", "selected_endpoint_id", "selected_provider_api_key_id", "has_format_conversion", ], "usage_routing_snapshots", replace_existing, ); query.push(", updated_at = excluded.updated_at"); query.build().execute(&mut **tx).await.map_sql_err()?; Ok(()) } async fn sync_settlement( tx: &mut Transaction<'_, Sqlite>, request_id: &str, snapshot: &UsageSettlementPricingSnapshot, replace_existing: bool, ) -> Result<(), DataLayerError> { if !snapshot.any_present() && !replace_existing { return Ok(()); } let now = unix_now()?; let settlement_json = json_text(snapshot.settlement_snapshot.as_ref())?; let dimensions_json = json_text(snapshot.billing_dimensions.as_ref())?; let mut query = QueryBuilder::::new( "INSERT INTO usage_settlement_snapshots (request_id, billing_status, \ billing_snapshot_schema_version, billing_snapshot_status, \ settlement_snapshot_schema_version, settlement_snapshot, billing_dimensions, \ billing_input_tokens, billing_effective_input_tokens, billing_output_tokens, \ billing_cache_creation_tokens, billing_cache_creation_5m_tokens, \ billing_cache_creation_1h_tokens, billing_cache_read_tokens, \ billing_total_input_context, billing_cache_creation_cost_usd, \ billing_cache_read_cost_usd, billing_total_cost_usd, \ billing_actual_total_cost_usd, billing_pricing_source, billing_rule_id, \ billing_rule_version, rate_multiplier, is_free_tier, input_price_per_1m, \ output_price_per_1m, cache_creation_price_per_1m, cache_read_price_per_1m, \ price_per_request, created_at, updated_at) VALUES (", ); { let mut values = query.separated(", "); values .push_bind(request_id) .push_bind(snapshot.billing_status.as_deref().unwrap_or("pending")) .push_bind(snapshot.billing_snapshot_schema_version.as_deref()) .push_bind(snapshot.billing_snapshot_status.as_deref()) .push_bind(snapshot.settlement_snapshot_schema_version.as_deref()) .push_bind(settlement_json.as_deref()) .push_bind(dimensions_json.as_deref()) .push_bind(snapshot.billing_input_tokens) .push_bind(snapshot.billing_effective_input_tokens) .push_bind(snapshot.billing_output_tokens) .push_bind(snapshot.billing_cache_creation_tokens) .push_bind(snapshot.billing_cache_creation_5m_tokens) .push_bind(snapshot.billing_cache_creation_1h_tokens) .push_bind(snapshot.billing_cache_read_tokens) .push_bind(snapshot.billing_total_input_context) .push_bind(snapshot.billing_cache_creation_cost_usd) .push_bind(snapshot.billing_cache_read_cost_usd) .push_bind(snapshot.billing_total_cost_usd) .push_bind(snapshot.billing_actual_total_cost_usd) .push_bind(snapshot.billing_pricing_source.as_deref()) .push_bind(snapshot.billing_rule_id.as_deref()) .push_bind(snapshot.billing_rule_version.as_deref()) .push_bind(snapshot.rate_multiplier) .push_bind(snapshot.is_free_tier) .push_bind(snapshot.input_price_per_1m) .push_bind(snapshot.output_price_per_1m) .push_bind(snapshot.cache_creation_price_per_1m) .push_bind(snapshot.cache_read_price_per_1m) .push_bind(snapshot.price_per_request) .push_bind(now) .push_bind(now); } query.push(") ON CONFLICT (request_id) DO UPDATE SET "); if replace_existing { query.push("billing_status = excluded.billing_status, "); } push_sqlite_updates( &mut query, &[ "billing_snapshot_schema_version", "billing_snapshot_status", "settlement_snapshot_schema_version", "settlement_snapshot", "billing_dimensions", "billing_input_tokens", "billing_effective_input_tokens", "billing_output_tokens", "billing_cache_creation_tokens", "billing_cache_creation_5m_tokens", "billing_cache_creation_1h_tokens", "billing_cache_read_tokens", "billing_total_input_context", "billing_cache_creation_cost_usd", "billing_cache_read_cost_usd", "billing_total_cost_usd", "billing_actual_total_cost_usd", "billing_pricing_source", "billing_rule_id", "billing_rule_version", "rate_multiplier", "is_free_tier", "input_price_per_1m", "output_price_per_1m", "cache_creation_price_per_1m", "cache_read_price_per_1m", "price_per_request", ], "usage_settlement_snapshots", replace_existing, ); query.push(", updated_at = excluded.updated_at"); query.build().execute(&mut **tx).await.map_sql_err()?; Ok(()) } fn push_sqlite_updates( query: &mut QueryBuilder<'_, Sqlite>, fields: &[&str], table: &str, replace_existing: bool, ) { for (index, field) in fields.iter().enumerate() { if index > 0 { query.push(", "); } query.push(*field).push(" = "); if replace_existing { query.push("excluded.").push(*field); } else { query .push("COALESCE(excluded.") .push(*field) .push(", ") .push(table) .push(".") .push(*field) .push(")"); } } } pub(crate) fn hydrate_row( row: &sqlx::sqlite::SqliteRow, audit: &mut StoredRequestUsageAudit, ) -> Result<(), DataLayerError> { audit.candidate_id = row.try_get("routing_candidate_id").map_sql_err()?; audit.candidate_index = row .try_get::, _>("routing_candidate_index") .map_sql_err()? .map(|value| { u64::try_from(value).map_err(|_| { DataLayerError::UnexpectedValue(format!( "usage routing candidate_index is negative: {value}" )) }) }) .transpose()?; audit.key_name = row.try_get("routing_key_name").map_sql_err()?; audit.planner_kind = row.try_get("routing_planner_kind").map_sql_err()?; audit.route_family = row.try_get("routing_route_family").map_sql_err()?; audit.route_kind = row.try_get("routing_route_kind").map_sql_err()?; audit.execution_path = row.try_get("routing_execution_path").map_sql_err()?; audit.local_execution_runtime_miss_reason = row .try_get("routing_local_execution_runtime_miss_reason") .map_sql_err()?; let snapshot = settlement_snapshot_from_row(row)?; if let Some(effective) = nonnegative_u64(snapshot.billing_effective_input_tokens) { audit.total_tokens = effective .saturating_add(audit.output_tokens) .saturating_add(audit.cache_creation_input_tokens) .saturating_add(audit.cache_read_input_tokens); } else if let Some(context) = nonnegative_u64(snapshot.billing_total_input_context) { audit.total_tokens = context.saturating_add(audit.output_tokens); } audit.request_metadata = attach_settlement_metadata(audit.request_metadata.take(), &snapshot); Ok(()) } fn settlement_snapshot_from_row( row: &sqlx::sqlite::SqliteRow, ) -> Result { Ok(UsageSettlementPricingSnapshot { billing_status: None, billing_snapshot_schema_version: row .try_get("settlement_billing_snapshot_schema_version") .map_sql_err()?, billing_snapshot_status: row .try_get("settlement_billing_snapshot_status") .map_sql_err()?, settlement_snapshot_schema_version: row .try_get("settlement_snapshot_schema_version") .map_sql_err()?, settlement_snapshot: json_value_from_row(row, "settlement_snapshot")?, billing_dimensions: json_value_from_row(row, "settlement_billing_dimensions")?, billing_input_tokens: row .try_get("settlement_billing_input_tokens") .map_sql_err()?, billing_effective_input_tokens: row .try_get("settlement_billing_effective_input_tokens") .map_sql_err()?, billing_output_tokens: row .try_get("settlement_billing_output_tokens") .map_sql_err()?, billing_cache_creation_tokens: row .try_get("settlement_billing_cache_creation_tokens") .map_sql_err()?, billing_cache_creation_5m_tokens: row .try_get("settlement_billing_cache_creation_5m_tokens") .map_sql_err()?, billing_cache_creation_1h_tokens: row .try_get("settlement_billing_cache_creation_1h_tokens") .map_sql_err()?, billing_cache_read_tokens: row .try_get("settlement_billing_cache_read_tokens") .map_sql_err()?, billing_total_input_context: row .try_get("settlement_billing_total_input_context") .map_sql_err()?, billing_cache_creation_cost_usd: row .try_get("settlement_billing_cache_creation_cost_usd") .map_sql_err()?, billing_cache_read_cost_usd: row .try_get("settlement_billing_cache_read_cost_usd") .map_sql_err()?, billing_total_cost_usd: row .try_get("settlement_billing_total_cost_usd") .map_sql_err()?, billing_actual_total_cost_usd: row .try_get("settlement_billing_actual_total_cost_usd") .map_sql_err()?, billing_pricing_source: row .try_get("settlement_billing_pricing_source") .map_sql_err()?, billing_rule_id: row.try_get("settlement_billing_rule_id").map_sql_err()?, billing_rule_version: row .try_get("settlement_billing_rule_version") .map_sql_err()?, rate_multiplier: row.try_get("settlement_rate_multiplier").map_sql_err()?, is_free_tier: row .try_get::, _>("settlement_is_free_tier") .map_sql_err()? .map(|value| value != 0), input_price_per_1m: row.try_get("settlement_input_price_per_1m").map_sql_err()?, output_price_per_1m: row .try_get("settlement_output_price_per_1m") .map_sql_err()?, cache_creation_price_per_1m: row .try_get("settlement_cache_creation_price_per_1m") .map_sql_err()?, cache_read_price_per_1m: row .try_get("settlement_cache_read_price_per_1m") .map_sql_err()?, price_per_request: row.try_get("settlement_price_per_request").map_sql_err()?, }) } fn attach_settlement_metadata( metadata: Option, snapshot: &UsageSettlementPricingSnapshot, ) -> Option { if !snapshot.any_present() { return metadata; } let mut metadata = match metadata { Some(Value::Object(object)) => object, Some(value) => return Some(value), None => Map::new(), }; insert_string( &mut metadata, "billing_snapshot_schema_version", snapshot.billing_snapshot_schema_version.as_deref(), ); insert_string( &mut metadata, "billing_snapshot_status", snapshot.billing_snapshot_status.as_deref(), ); insert_string( &mut metadata, "settlement_snapshot_schema_version", snapshot.settlement_snapshot_schema_version.as_deref(), ); insert_value( &mut metadata, "settlement_snapshot", snapshot.settlement_snapshot.as_ref(), ); insert_value( &mut metadata, "billing_dimensions", snapshot.billing_dimensions.as_ref(), ); insert_number(&mut metadata, "rate_multiplier", snapshot.rate_multiplier); insert_bool(&mut metadata, "is_free_tier", snapshot.is_free_tier); insert_number( &mut metadata, "input_price_per_1m", snapshot.input_price_per_1m, ); insert_number( &mut metadata, "output_price_per_1m", snapshot.output_price_per_1m, ); insert_number( &mut metadata, "cache_creation_price_per_1m", snapshot.cache_creation_price_per_1m, ); insert_number( &mut metadata, "cache_read_price_per_1m", snapshot.cache_read_price_per_1m, ); insert_number( &mut metadata, "price_per_request", snapshot.price_per_request, ); (!metadata.is_empty()).then_some(Value::Object(metadata)) } fn insert_string(metadata: &mut Map, key: &str, value: Option<&str>) { if let Some(value) = value.map(str::trim).filter(|value| !value.is_empty()) { metadata.insert(key.to_string(), Value::String(value.to_string())); } } fn insert_number(metadata: &mut Map, key: &str, value: Option) { if let Some(number) = value .filter(|value| value.is_finite()) .and_then(serde_json::Number::from_f64) { metadata.insert(key.to_string(), Value::Number(number)); } } fn insert_bool(metadata: &mut Map, key: &str, value: Option) { if let Some(value) = value { metadata.insert(key.to_string(), Value::Bool(value)); } } fn insert_value(metadata: &mut Map, key: &str, value: Option<&Value>) { if let Some(value) = value { metadata.insert(key.to_string(), value.clone()); } } fn metadata_string(metadata: Option<&Map>, key: &str) -> Option { metadata .and_then(|object| object.get(key)) .and_then(Value::as_str) .map(str::trim) .filter(|value| !value.is_empty()) .map(ToOwned::to_owned) } fn metadata_number(metadata: Option<&Map>, key: &str) -> Option { metadata .and_then(|object| object.get(key)) .and_then(Value::as_f64) .filter(|value| value.is_finite()) } fn metadata_u64(metadata: Option<&Map>, key: &str) -> Option { metadata.and_then(|object| { object.get(key).and_then(|value| { value .as_u64() .or_else(|| value.as_i64().and_then(|number| u64::try_from(number).ok())) }) }) } fn metadata_bool(metadata: Option<&Map>, key: &str) -> Option { metadata .and_then(|object| object.get(key)) .and_then(Value::as_bool) } fn billing_snapshot_object(metadata: Option<&Map>) -> Option<&Map> { metadata .and_then(|object| object.get("billing_snapshot")) .and_then(Value::as_object) } fn billing_snapshot_string(metadata: Option<&Map>, key: &str) -> Option { billing_snapshot_object(metadata) .and_then(|snapshot| snapshot.get(key)) .and_then(Value::as_str) .map(str::trim) .filter(|value| !value.is_empty()) .map(ToOwned::to_owned) } fn billing_snapshot_resolved_number( metadata: Option<&Map>, key: &str, ) -> Option { billing_snapshot_object(metadata) .and_then(|snapshot| snapshot.get("resolved_variables")) .and_then(Value::as_object) .and_then(|variables| variables.get(key)) .and_then(Value::as_f64) .filter(|value| value.is_finite()) } fn settlement_snapshot_object( metadata: Option<&Map>, ) -> Option<&Map> { metadata .and_then(|object| object.get("settlement_snapshot")) .and_then(Value::as_object) } fn settlement_snapshot_schema_version(metadata: Option<&Map>) -> Option { metadata_string(metadata, "settlement_snapshot_schema_version").or_else(|| { settlement_snapshot_object(metadata) .and_then(|snapshot| snapshot.get("schema_version")) .and_then(Value::as_str) .map(str::trim) .filter(|value| !value.is_empty()) .map(ToOwned::to_owned) }) } fn settlement_snapshot_value(metadata: Option<&Map>) -> Option { metadata .and_then(|object| object.get("settlement_snapshot")) .cloned() } fn settlement_child_value<'a>( metadata: Option<&'a Map>, child: &str, ) -> Option<&'a Value> { settlement_snapshot_object(metadata).and_then(|snapshot| snapshot.get(child)) } fn settlement_child_object<'a>( metadata: Option<&'a Map>, child: &str, ) -> Option<&'a Map> { settlement_child_value(metadata, child).and_then(Value::as_object) } fn metadata_or_snapshot_dimensions(metadata: Option<&Map>) -> Option { metadata .and_then(|object| object.get("billing_dimensions")) .cloned() .or_else(|| settlement_child_value(metadata, "resolved_dimensions").cloned()) .or_else(|| { billing_snapshot_object(metadata) .and_then(|snapshot| snapshot.get("resolved_dimensions")) .cloned() }) } fn billing_dimension_i64(metadata: Option<&Map>, key: &str) -> Option { metadata_or_snapshot_dimensions(metadata) .and_then(|dimensions| dimensions.get(key).and_then(json_i64)) .filter(|value| *value >= 0) } fn json_i64(value: &Value) -> Option { value .as_i64() .or_else(|| value.as_u64().and_then(|number| i64::try_from(number).ok())) } fn settlement_snapshot_number(metadata: Option<&Map>, key: &str) -> Option { settlement_snapshot_object(metadata) .and_then(|snapshot| snapshot.get(key)) .and_then(Value::as_f64) .filter(|value| value.is_finite()) } fn billing_snapshot_number(metadata: Option<&Map>, key: &str) -> Option { billing_snapshot_object(metadata) .and_then(|snapshot| snapshot.get(key)) .and_then(Value::as_f64) .filter(|value| value.is_finite()) } fn settlement_cost_breakdown_number( metadata: Option<&Map>, key: &str, ) -> Option { settlement_child_object(metadata, "cost_breakdown") .or_else(|| { billing_snapshot_object(metadata) .and_then(|snapshot| snapshot.get("cost_breakdown")) .and_then(Value::as_object) }) .and_then(|breakdown| breakdown.get(key)) .and_then(Value::as_f64) .filter(|value| value.is_finite()) } fn settlement_cache_creation_cost(metadata: Option<&Map>) -> Option { let mut found = false; let total = [ "cache_creation_uncategorized_cost", "cache_creation_ephemeral_5m_cost", "cache_creation_ephemeral_1h_cost", "cache_creation_cost", ] .into_iter() .fold(0.0, |sum, key| { if let Some(value) = settlement_cost_breakdown_number(metadata, key) { found = true; sum + value } else { sum } }); found.then_some(total) } fn settlement_nested_string( metadata: Option<&Map>, child: &str, key: &str, ) -> Option { settlement_child_object(metadata, child) .and_then(|object| object.get(key)) .and_then(Value::as_str) .map(str::trim) .filter(|value| !value.is_empty()) .map(ToOwned::to_owned) } fn billing_snapshot_string_field( metadata: Option<&Map>, key: &str, ) -> Option { billing_snapshot_object(metadata) .and_then(|snapshot| snapshot.get(key)) .and_then(Value::as_str) .map(str::trim) .filter(|value| !value.is_empty()) .map(ToOwned::to_owned) } fn optional_i64(value: Option, field: &str) -> Result, DataLayerError> { value .map(|value| { i64::try_from(value).map_err(|_| { DataLayerError::UnexpectedValue(format!("usage {field} exceeds bigint: {value}")) }) }) .transpose() } fn cache_creation_tokens_from_parts( uncategorized: Option, ephemeral_5m: Option, ephemeral_1h: Option, ) -> Option { let categorized = ephemeral_5m .unwrap_or_default() .saturating_add(ephemeral_1h.unwrap_or_default()); match uncategorized { Some(0) if categorized > 0 => Some(categorized), Some(value) => Some(value), None if categorized > 0 => Some(categorized), None => None, } } fn normalized_api_family(usage: &UpsertUsageRecord) -> String { usage .endpoint_api_format .as_deref() .or(usage.api_format.as_deref()) .unwrap_or_default() .split(':') .next() .unwrap_or_default() .trim() .to_ascii_lowercase() } fn effective_input_tokens( input_tokens: Option, cache_creation_tokens: Option, cache_read_tokens: Option, api_family: &str, ) -> Option { let input_tokens = input_tokens?; let cache_creation_tokens = cache_creation_tokens.unwrap_or_default(); let cache_read_tokens = cache_read_tokens.unwrap_or_default(); if input_tokens > 0 { if api_family == "openai" && (cache_creation_tokens > 0 || cache_read_tokens > 0) { return Some( input_tokens .saturating_sub(cache_creation_tokens) .saturating_sub(cache_read_tokens), ); } if matches!(api_family, "gemini" | "google") && cache_read_tokens > 0 { return Some(input_tokens.saturating_sub(cache_read_tokens)); } } Some(input_tokens) } fn total_input_context( input_tokens: Option, effective_input_tokens: Option, cache_creation_tokens: Option, cache_read_tokens: Option, api_family: &str, ) -> Option { if input_tokens.is_none() && effective_input_tokens.is_none() && cache_creation_tokens.is_none() && cache_read_tokens.is_none() { return None; } let input_tokens = input_tokens.unwrap_or_default(); let effective_input_tokens = effective_input_tokens.unwrap_or(input_tokens); let cache_creation_tokens = cache_creation_tokens.unwrap_or_default(); let cache_read_tokens = cache_read_tokens.unwrap_or_default(); match api_family { "claude" | "anthropic" => Some( input_tokens .saturating_add(cache_creation_tokens) .saturating_add(cache_read_tokens), ), "openai" => Some( effective_input_tokens .saturating_add(cache_creation_tokens) .saturating_add(cache_read_tokens), ), "gemini" | "google" => Some(effective_input_tokens.saturating_add(cache_read_tokens)), _ => Some( input_tokens .saturating_add(cache_creation_tokens) .saturating_add(cache_read_tokens), ), } } fn json_text(value: Option<&Value>) -> Result, DataLayerError> { value .map(|value| { serde_json::to_string(value).map_err(|error| { DataLayerError::UnexpectedValue(format!( "failed to serialize usage settlement snapshot: {error}" )) }) }) .transpose() } fn json_value_from_row( row: &sqlx::sqlite::SqliteRow, column: &str, ) -> Result, DataLayerError> { row.try_get::, _>(column) .map_sql_err()? .map(|value| { serde_json::from_str(&value).map_err(|error| { DataLayerError::UnexpectedValue(format!( "invalid usage settlement JSON in {column}: {error}" )) }) }) .transpose() } fn nonnegative_u64(value: Option) -> Option { value.and_then(|value| u64::try_from(value).ok()) } fn unix_now() -> Result { let seconds = SystemTime::now() .duration_since(UNIX_EPOCH) .map_err(|error| DataLayerError::UnexpectedValue(error.to_string()))? .as_secs(); i64::try_from(seconds) .map_err(|_| DataLayerError::UnexpectedValue("unix timestamp overflow".to_string())) }