use pingora_proxy::Session;
use super::metrics;
use crate::http::pingora::context::PingoraRequestCtx;
pub(super) fn emit_request_metrics(session: &Session, ctx: &PingoraRequestCtx) {
if !metrics::is_recorder_installed() {
return;
}
let status_code = session.response_written().map_or(0, |resp| resp.status.as_u16());
let status_class = metrics::status_class(status_code);
let method = request_method_label(session, ctx);
let cluster = ctx.metrics_cluster_shared.clone().unwrap_or_else(metrics::cluster_none);
let route = ctx.metrics_route.clone().unwrap_or_else(metrics::route_unknown);
let labels = metrics::RequestMetricLabels {
cluster: cluster.clone(),
method,
route,
status_class,
};
emit_upstream_request_metric(ctx, &cluster);
if let Some(error_type) = ctx.error_type {
metrics::record_error(error_type);
}
let duration_secs = ctx.request_start.elapsed().as_secs_f64();
metrics::record_request_metrics(labels, duration_secs);
metrics::record_body_size_metrics(
method,
status_class,
cluster,
ctx.request_body_bytes,
ctx.response_body_bytes,
);
}
fn request_method_label(session: &Session, ctx: &PingoraRequestCtx) -> &'static str {
let request_method = session.req_header().method.as_str();
let raw_method = if request_method.is_empty() {
ctx.request_snapshot.as_ref().map_or("UNKNOWN", |r| r.method.as_str())
} else {
request_method
};
metrics::method_label(raw_method)
}
fn emit_upstream_request_metric(ctx: &PingoraRequestCtx, cluster: &::metrics::SharedString) {
if let Some(upstream_status) = ctx.upstream_response_status
&& let Some(upstream) = ctx.upstream_for_retry.as_ref()
{
metrics::record_upstream_request(
cluster.clone(),
::metrics::SharedString::from(std::sync::Arc::clone(&upstream.address)),
metrics::status_class(upstream_status),
);
}
}