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 {
TrackerParams { name, step }
}
}
pub async fn user_tracker(
State(params): State<TrackerParams>,
req: Request,
next: Next,
) -> Result<Response> {
let category = "tracker";
let res = next.run(req).await;
let ctx = CTX.get();
let elapsed = ctx.elapsed().as_millis();
let device_id = &ctx.device_id;
let trace_id = &ctx.trace_id;
let account = ctx.get_account();
if res.status().as_u16() < 400 {
info!(
category,
device_id,
trace_id,
name = params.name,
account = %account,
step = params.step,
elapsed,
result = "success",
);
return Ok(res);
}
let mut error = None;
let mut error_category = None;
let mut error_sub_category = None;
let mut error_exception = true;
if let Some(err) = res.extensions().get::<Error>() {
error = Some(err.message.clone());
error_category = Some(err.category.clone());
error_sub_category = err.sub_category.clone();
error_exception = err.exception.unwrap_or_default();
}
error!(
category = category,
device_id,
trace_id,
name = params.name,
account = %account,
step = params.step,
error,
error_category,
error_sub_category,
error_exception,
elapsed,
result = "failure",
);
Ok(res)
}