stream access logs and improve access log format (#581)

This commit is contained in:
Adil Hafeez 2025-09-30 18:46:13 -07:00 committed by GitHub
parent 43fceffd93
commit f4d65e2469
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 73 additions and 11 deletions

2
crates/Cargo.lock generated
View file

@ -175,6 +175,7 @@ dependencies = [
"serde_with",
"serde_yaml",
"thiserror 2.0.12",
"time",
"tokio",
"tokio-stream",
"tracing",
@ -2684,6 +2685,7 @@ dependencies = [
"sharded-slab",
"smallvec",
"thread_local",
"time",
"tracing",
"tracing-core",
"tracing-log",

View file

@ -29,6 +29,7 @@ serde_yaml = "0.9.34"
thiserror = "2.0.12"
tokio = { version = "1.44.2", features = ["full"] }
tokio-stream = "0.1.17"
time = { version = "0.3", features = ["formatting", "macros"] }
tracing = "0.1.41"
tracing-opentelemetry = "0.30.0"
tracing-subscriber = { version = "0.3.19", features = ["env-filter", "fmt"] }
tracing-subscriber = { version = "0.3.19", features = ["env-filter", "fmt", "time"] }

View file

@ -153,7 +153,7 @@ pub async fn chat(
Ok(route) => match route {
Some((_, model_name)) => model_name,
None => {
debug!(
info!(
"No route determined, using default model from request: {}",
chat_completions_request_for_arch_router.model
);

View file

@ -1,9 +1,46 @@
use std::sync::OnceLock;
use std::fmt;
use opentelemetry::global;
use opentelemetry_sdk::{propagation::TraceContextPropagator, trace::SdkTracerProvider};
use opentelemetry_stdout::SpanExporter;
use tracing_subscriber::EnvFilter;
use tracing_subscriber::fmt::{format, time::FormatTime, FmtContext, FormatEvent, FormatFields};
use tracing::{Event, Subscriber};
use time::macros::format_description;
struct BracketedTime;
impl FormatTime for BracketedTime {
fn format_time(&self, w: &mut format::Writer<'_>) -> fmt::Result {
let now = time::OffsetDateTime::now_utc();
write!(w, "[{}]", now.format(&format_description!("[year]-[month]-[day] [hour]:[minute]:[second].[subsecond digits:3]")).unwrap())
}
}
struct BracketedFormatter;
impl<S, N> FormatEvent<S, N> for BracketedFormatter
where
S: Subscriber + for<'a> tracing_subscriber::registry::LookupSpan<'a>,
N: for<'a> FormatFields<'a> + 'static,
{
fn format_event(
&self,
ctx: &FmtContext<'_, S, N>,
mut writer: format::Writer<'_>,
event: &Event<'_>,
) -> fmt::Result {
let timer = BracketedTime;
timer.format_time(&mut writer)?;
write!(writer, "[{}] ", event.metadata().level().to_string().to_lowercase())?;
ctx.field_format().format_fields(writer.by_ref(), event)?;
writeln!(writer)
}
}
static INIT_LOGGER: OnceLock<SdkTracerProvider> = OnceLock::new();
@ -22,6 +59,7 @@ pub fn init_tracer() -> &'static SdkTracerProvider {
.with_env_filter(
EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info")),
)
.event_format(BracketedFormatter)
.init();
provider

View file

@ -204,7 +204,7 @@ impl StreamContext {
// Tokenize and record token count.
let token_count = tokenizer::token_count(model, json_string).unwrap_or(0);
info!(
debug!(
"[ARCHGW_REQ_ID:{}] TOKEN_COUNT: model='{}' input_tokens={}",
self.request_identifier(),
model,
@ -492,7 +492,7 @@ impl StreamContext {
body: &[u8],
provider_id: ProviderId,
) -> Result<Vec<u8>, Action> {
info!(
debug!(
"[ARCHGW_REQ_ID:{}] NON_STREAMING_PROCESS: provider_id={:?} body_size={}",
self.request_identifier(),
provider_id,
@ -531,7 +531,7 @@ impl StreamContext {
if let Some((prompt_tokens, completion_tokens, total_tokens)) =
response.extract_usage_counts()
{
info!(
debug!(
"[ARCHGW_REQ_ID:{}] RESPONSE_USAGE: prompt_tokens={} completion_tokens={} total_tokens={}",
self.request_identifier(),
prompt_tokens,
@ -697,7 +697,7 @@ impl HttpContext for StreamContext {
//We need to deserialize the request body based on the resolved API
let mut deserialized_client_request: ProviderRequestType = match self.client_api.as_ref() {
Some(the_client_api) => {
info!(
debug!(
"[ARCHGW_REQ_ID:{}] CLIENT_REQUEST_RECEIVED: api={:?} body_size={}",
self.request_identifier(),
the_client_api,
@ -785,7 +785,7 @@ impl HttpContext for StreamContext {
// Extract user message for tracing
self.user_message = deserialized_client_request.get_recent_user_message();
info!(
debug!(
"[ARCHGW_REQ_ID:{}] MODEL_RESOLUTION: req_model='{}' -> resolved_model='{}' provider='{}' streaming={}",
self.request_identifier(),
model_requested,
@ -871,7 +871,7 @@ impl HttpContext for StreamContext {
if let Ok(status_code) = status_str.parse::<u16>() {
self.upstream_status_code = StatusCode::from_u16(status_code).ok();
info!(
debug!(
"[ARCHGW_REQ_ID:{}] UPSTREAM_RESPONSE_STATUS: {}",
self.request_identifier(),
status_code