aboutsummaryrefslogtreecommitdiffstats
path: root/src/api/request_log.rs
blob: 418fe14ecbf186f98b19843630115584378b6aac (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
//! A line per HTTP request, as web servers log them: the method and path, the status,
//! how long until the answer began (a stream, such as the dashboard's events, goes on
//! after), where it came from, and the user. At debug, under the target `http`
//! (`RUST_LOG=info,http=debug`, or `PUT /admin/log`): an open dashboard alone would
//! fill the log at info.

use axum::extract::{ConnectInfo, Request};
use axum::middleware::Next;
use axum::response::Response;
use tokio::time::Instant;
use tracing::{Level, debug, enabled};

use super::auth::AuthenticatedUser;
use super::listen::Peer;

/// Outermost: what the layers inside answer too (a `401` included). The user comes back
/// on the response (`auth::basic_auth`).
pub(crate) async fn log_requests(request: Request, next: Next) -> Response {
    if !enabled!(target: "http", Level::DEBUG) {
        return next.run(request).await;
    }
    let method = request.method().clone();
    let path = request
        .uri()
        .path_and_query()
        .map_or_else(|| request.uri().path().to_owned(), ToString::to_string);
    let from = match request.extensions().get::<ConnectInfo<Peer>>() {
        Some(ConnectInfo(Peer::Tcp(address))) => address.to_string(),
        Some(ConnectInfo(Peer::Unix)) => "unix".to_owned(),
        None => "-".to_owned(),
    };
    let started = Instant::now();
    let response = next.run(request).await;
    let user = response
        .extensions()
        .get::<AuthenticatedUser>()
        .map_or("-", |AuthenticatedUser(user)| user.as_str());
    debug!(
        target: "http",
        method = %method,
        path = %path,
        status = response.status().as_u16(),
        ms = started.elapsed().as_millis(),
        from = %from,
        user = %user,
        "HTTP request"
    );
    response
}