From 8c8983b772b43a7cb339dbcc7eee72d383f03f06 Mon Sep 17 00:00:00 2001 From: Yujong Lee Date: Mon, 28 Sep 2026 23:53:55 +0000 Subject: [PATCH] fix(accounting): include call id and effect progress in needs-attention log Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- litellm-rust/crates/accounting/src/session.rs | 2 +- .../gateway-inference/src/accounting.rs | 85 ++++++++++++------- 2 files changed, 53 insertions(+), 34 deletions(-) diff --git a/litellm-rust/crates/accounting/src/session.rs b/litellm-rust/crates/accounting/src/session.rs index ca38dccf20c..8ebed31e3c9 100644 --- a/litellm-rust/crates/accounting/src/session.rs +++ b/litellm-rust/crates/accounting/src/session.rs @@ -119,7 +119,7 @@ impl From> for EffectState { } } -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct Progress { effects: [EffectState; 3], } diff --git a/litellm-rust/crates/gateway-inference/src/accounting.rs b/litellm-rust/crates/gateway-inference/src/accounting.rs index e0c4820188b..fb12bfb904e 100644 --- a/litellm-rust/crates/gateway-inference/src/accounting.rs +++ b/litellm-rust/crates/gateway-inference/src/accounting.rs @@ -122,44 +122,63 @@ impl ResponsesAccounting { let (ready, admitted) = oneshot::channel(); let service = self.service.clone(); let callback = self.callback.clone(); - tokio::spawn(async move { - let _token = token; - let admission = match service.admit(request).await { - Ok(admission) => admission, - Err(error) => { - let _ = ready.send(Err(AccountingError::Admission(error))); - return; - } - }; - let mut session = Session::new(BudgetAdmission::new(admission.budget_receipt)); - let mut backend = admission.backend; - let delivered = ready.send(Ok(())).is_ok(); - let (outcome, reply, assessment_error) = if delivered { - collect(receiver, backend.as_mut()).await - } else { - (Outcome::Cancelled, None, None) - }; - let result = settle(&mut session, backend.as_mut(), admission.call_id, outcome, assessment_error).await; - match result { - Ok(report) => { - if let Some(callback) = callback - && callback.completed(report.clone()).await.is_err() { - tracing::warn!("accounting terminal callback failed"); + tokio::spawn( + async move { + let _token = token; + let admission = match service.admit(request).await { + Ok(admission) => admission, + Err(error) => { + let _ = ready.send(Err(AccountingError::Admission(error))); + return; } - let delivery = report_result(&report); - if delivery.is_err() { - tracing::error!(status = ?report.status, "call accounting needs attention"); + }; + let mut session = Session::new(BudgetAdmission::new(admission.budget_receipt)); + let mut backend = admission.backend; + let delivered = ready.send(Ok(())).is_ok(); + let (outcome, reply, assessment_error) = if delivered { + collect(receiver, backend.as_mut()).await + } else { + (Outcome::Cancelled, None, None) + }; + let result = settle( + &mut session, + backend.as_mut(), + admission.call_id, + outcome, + assessment_error, + ) + .await; + match result { + Ok(report) => { + if let Some(callback) = callback + && callback.completed(report.clone()).await.is_err() + { + tracing::warn!("accounting terminal callback failed"); + } + let delivery = report_result(&report); + if let Err(error) = &delivery { + tracing::error!( + call_id = %report.call_id, + progress = ?report.progress, + error = %error, + "call accounting needs attention" + ); + } + if let Some(reply) = reply { + let _ = reply.send(delivery); + } } - if let Some(reply) = reply { - let _ = reply.send(delivery); + Err(error) => { + tracing::error!("accounting session contract failed"); + if let Some(reply) = reply { + let _ = reply.send(Err(error)); + } } } - Err(error) => { - tracing::error!("accounting session contract failed"); - if let Some(reply) = reply { let _ = reply.send(Err(error)); } - } } - }.with_current_subscriber().in_current_span()); + .with_current_subscriber() + .in_current_span(), + ); admitted.await.map_err(|_| AccountingError::Closed)??; Ok(Call { sender: Some(sender),