use super::LOG_TARGET;
use axum::extract::Request;
use axum::extract::State;
use axum::middleware::Next;
use axum::response::Response;
use tibba_error::Error;
use tibba_state::CTX;
use tracing::{error, info};
type Result<T> = std::result::Result<T, Error>;
#[derive(Clone, Copy)]
pub struct TrackerParams {
pub name: &'static str,
pub step: &'static str,
}
impl From<(&'static str, &'static str)> for TrackerParams {
fn from((name, step): (&'static str, &'static str)) -> Self {
Self { name, step }
}
}
pub async fn user_tracker(
State(params): State<TrackerParams>,
req: Request,
next: Next,
) -> Result<Response> {
let res = next.run(req).await;
let ctx = CTX.get();
let elapsed = ctx.elapsed_ms();
let device_id = &ctx.device_id;
let trace_id = &ctx.trace_id;
let account = ctx.get_account();
let status = res.status().as_u16();
if status < 400 {
info!(
target: LOG_TARGET,
device_id,
trace_id,
name = params.name, account = %account,
step = params.step, status,
elapsed,
result = "success",
"user tracker",
);
return Ok(res);
}
let (error, error_category, error_sub_category, error_exception) = res
.extensions()
.get::<Error>()
.map(|err| {
(
Some(err.message.clone()),
Some(err.category.clone()),
err.sub_category.clone(),
err.exception.unwrap_or_default(),
)
})
.unwrap_or((None, None, None, true));
error!(
target: LOG_TARGET,
device_id,
trace_id,
name = params.name,
account = %account,
step = params.step,
status,
error,
error_category,
error_sub_category,
error_exception,
elapsed,
result = "failure",
"user tracker",
);
Ok(res)
}