Skip to content

Commit 5634698

Browse files
risssondavepgreene
authored andcommitted
packages/ak-axum/tracing: init (goauthentik#21316)
1 parent bf7b85a commit 5634698

5 files changed

Lines changed: 68 additions & 7 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/ak-axum/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ ak-common.workspace = true
1414
axum.workspace = true
1515
durstr.workspace = true
1616
eyre.workspace = true
17+
tokio.workspace = true
1718
tower-http.workspace = true
1819
tower.workspace = true
1920
tracing.workspace = true

packages/ak-axum/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@
22
33
pub mod error;
44
pub mod router;
5+
pub mod tracing;

packages/ak-axum/src/router.rs

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,32 @@
11
//! Utilities for working with [`Router`].
22
33
use ak_common::config;
4-
use axum::{Router, http::StatusCode};
4+
use axum::{Router, http::StatusCode, middleware::from_fn};
55
use tower::ServiceBuilder;
66
use tower_http::timeout::TimeoutLayer;
77

8+
use crate::tracing::{span_middleware, tracing_middleware};
9+
810
/// Wrap a [`Router`] with common middlewares.
11+
///
12+
/// Set `with_tracing` to [`true`] to log requests.
913
#[inline]
10-
pub fn wrap_router(router: Router) -> Router {
14+
pub fn wrap_router(router: Router, with_tracing: bool) -> Router {
1115
let config = config::get();
1216
let timeout = durstr::parse(&config.web.timeout_http_read_header)
1317
.expect("Invalid duration in http timeout")
1418
+ durstr::parse(&config.web.timeout_http_read).expect("Invalid duration in http timeout")
1519
+ durstr::parse(&config.web.timeout_http_write).expect("Invalid duration in http timeout")
1620
+ durstr::parse(&config.web.timeout_http_idle).expect("Invalid duration in http timeout");
17-
let service_builder = ServiceBuilder::new().layer(TimeoutLayer::with_status_code(
18-
StatusCode::REQUEST_TIMEOUT,
19-
timeout,
20-
));
21-
router.layer(service_builder)
21+
let service_builder = ServiceBuilder::new()
22+
.layer(TimeoutLayer::with_status_code(
23+
StatusCode::REQUEST_TIMEOUT,
24+
timeout,
25+
))
26+
.layer(from_fn(span_middleware));
27+
if with_tracing {
28+
router.layer(service_builder.layer(from_fn(tracing_middleware)))
29+
} else {
30+
router.layer(service_builder)
31+
}
2232
}

packages/ak-axum/src/tracing.rs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
//! Middlewares for tracing requests.
2+
3+
use std::collections::HashMap;
4+
5+
use ak_common::config;
6+
use axum::{extract::Request, middleware::Next, response::Response};
7+
use tokio::time::Instant;
8+
use tracing::{Instrument as _, info, info_span, trace};
9+
10+
/// Create a [`tracing::Span`] for requests.
11+
pub(crate) async fn span_middleware(request: Request, next: Next) -> Response {
12+
let config = config::get();
13+
let http_headers = request
14+
.headers()
15+
.iter()
16+
.filter(|(name, _)| {
17+
for header in &config.log.http_headers {
18+
if header.eq_ignore_ascii_case(name.as_str()) {
19+
return true;
20+
}
21+
}
22+
false
23+
})
24+
.map(|(name, value)| (name.to_string().to_lowercase().replace('-', "_"), value))
25+
.collect::<HashMap<_, _>>();
26+
let span = info_span!(
27+
"request",
28+
path = %request.uri(),
29+
method = %request.method(),
30+
http_headers = ?http_headers,
31+
);
32+
next.run(request).instrument(span).await
33+
}
34+
35+
/// Log requests.
36+
pub(crate) async fn tracing_middleware(request: Request, next: Next) -> Response {
37+
let event = request.uri().clone();
38+
trace!("request start");
39+
40+
let start = Instant::now();
41+
let response = next.run(request).await;
42+
let runtime = start.elapsed();
43+
let status = response.status().as_u16();
44+
45+
info!(status = status, runtime = runtime.as_millis(), "{event}");
46+
47+
response
48+
}

0 commit comments

Comments
 (0)