tork_core/middleware/
trace.rs1use std::time::Instant;
4
5use crate::error::Result;
6use crate::logging::Logger;
7use crate::middleware::{DuplicatePolicy, Middleware, Next, Request};
8use crate::response::Response;
9use crate::router::BoxFuture;
10
11pub struct Trace;
17
18impl Trace {
19 pub fn new() -> Self {
21 Self
22 }
23}
24
25impl Default for Trace {
26 fn default() -> Self {
27 Self::new()
28 }
29}
30
31impl Middleware for Trace {
32 fn handle(&self, request: Request, next: Next) -> BoxFuture<'static, Result<Response>> {
33 let method = request.method().clone();
34 let path = request.uri().path().to_owned();
35 let start = Instant::now();
36
37 Box::pin(async move {
38 let result = next.run(request).await;
39 let elapsed = start.elapsed();
40 let status = match &result {
41 Ok(response) => response.status(),
42 Err(error) => error.kind().status(),
43 };
44 Logger::framework("HTTP")
45 .debug(format!("{method} {path} {}", status.as_u16()))
46 .field("method", method.as_str())
47 .field("path", &path)
48 .field("status", status.as_u16())
49 .field("duration_ms", elapsed.as_millis() as u64)
50 .emit();
51 result
52 })
53 }
54
55 fn name(&self) -> &'static str {
56 "Trace"
57 }
58
59 fn duplicate_policy(&self) -> DuplicatePolicy {
60 DuplicatePolicy::Reject
61 }
62}
63
64#[cfg(test)]
65mod tests {
66 use super::*;
67
68 #[test]
69 fn builtin_metadata_is_stable() {
70 let middleware = Trace::new();
71 assert_eq!(middleware.name(), "Trace");
72 assert_eq!(middleware.duplicate_policy(), DuplicatePolicy::Reject);
73 }
74}