Skip to content

Commit ba56206

Browse files
authored
feat(server): add request-level logging via tower-http TraceLayer (#895)
Wrap gRPC and HTTP services with TraceLayer to log method, path, status, and latency for every request. Health/readiness probe endpoints are logged at debug level to reduce noise.
1 parent a6d4552 commit ba56206

1 file changed

Lines changed: 46 additions & 1 deletion

File tree

crates/openshell-server/src/multiplex.rs

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,11 @@ use std::future::Future;
2222
use std::pin::Pin;
2323
use std::sync::Arc;
2424
use std::task::{Context, Poll};
25+
use std::time::Duration;
2526
use tokio::io::{AsyncRead, AsyncWrite};
26-
use tower::ServiceExt;
27+
use tower::{ServiceBuilder, ServiceExt};
28+
use tower_http::trace::TraceLayer;
29+
use tracing::Span;
2730

2831
use crate::{OpenShellService, ServerState, http_router, inference::InferenceService};
2932

@@ -60,6 +63,23 @@ impl MultiplexService {
6063
let grpc_service = GrpcRouter::new(openshell, inference);
6164
let http_service = http_router(self.state.clone());
6265

66+
let grpc_service = ServiceBuilder::new()
67+
.layer(
68+
TraceLayer::new_for_http()
69+
.make_span_with(make_request_span)
70+
.on_request(())
71+
.on_response(log_response),
72+
)
73+
.service(grpc_service);
74+
let http_service = ServiceBuilder::new()
75+
.layer(
76+
TraceLayer::new_for_http()
77+
.make_span_with(make_request_span)
78+
.on_request(())
79+
.on_response(log_response),
80+
)
81+
.service(http_service);
82+
6383
let service = MultiplexedService::new(grpc_service, http_service);
6484

6585
// HTTP/2 adaptive flow control. Default windows (64 KiB / 64 KiB)
@@ -213,6 +233,31 @@ where
213233
}
214234
}
215235

236+
fn make_request_span<B>(req: &Request<B>) -> Span {
237+
let path = req.uri().path();
238+
if matches!(path, "/health" | "/healthz" | "/readyz") {
239+
tracing::debug_span!(
240+
"request",
241+
method = %req.method(),
242+
path,
243+
)
244+
} else {
245+
tracing::info_span!(
246+
"request",
247+
method = %req.method(),
248+
path,
249+
)
250+
}
251+
}
252+
253+
fn log_response<B>(res: &Response<B>, latency: Duration, _span: &Span) {
254+
tracing::info!(
255+
status = res.status().as_u16(),
256+
latency_ms = latency.as_millis(),
257+
"response"
258+
);
259+
}
260+
216261
/// Boxed body type for uniform handling.
217262
pub struct BoxBody(
218263
http_body_util::combinators::UnsyncBoxBody<Bytes, Box<dyn std::error::Error + Send + Sync>>,

0 commit comments

Comments
 (0)