use pingora_proxy::Session;
use crate::http::pingora::context::PingoraRequestCtx;
pub(super) fn http_version_label(version: http::Version) -> &'static str {
match version {
http::Version::HTTP_09 => "0.9",
http::Version::HTTP_10 => "1.0",
http::Version::HTTP_11 => "1.1",
http::Version::HTTP_2 => "2",
http::Version::HTTP_3 => "3",
_ => "unknown",
}
}
pub(super) fn record_response_span_attributes(session: &Session, ctx: &PingoraRequestCtx) {
if ctx.request_span.is_disabled() {
return;
}
let response = session.response_written();
let status = response.map(|resp| resp.status);
let method = session.req_header().method.as_str();
record_response_span_fields(status, method, response, ctx);
}
pub(super) fn record_response_span_fields(
status: Option<http::StatusCode>,
method: &str,
response: Option<&pingora_http::ResponseHeader>,
ctx: &PingoraRequestCtx,
) {
if let Some(status) = status {
let code = status.as_u16();
if code > 0 {
ctx.request_span.record("http.response.status_code", code);
}
if status.is_server_error() {
ctx.request_span.record("otel.status_code", "ERROR");
ctx.request_span.record("error.type", code.to_string().as_str());
}
}
if let Some(route) = &ctx.metrics_route {
ctx.request_span.record("http.route", route.as_ref());
ctx.request_span
.record("otel.name", format!("{method} {route}").as_str());
}
if let Some(upstream) = &ctx.upstream_for_retry {
ctx.request_span.record("upstream.address", upstream.address.as_ref());
}
if let Some(cluster) = &ctx.metrics_cluster {
ctx.request_span.record("upstream.cluster", cluster.as_ref());
}
record_upstream_exchange_span(ctx, response);
}
fn record_upstream_exchange_span(ctx: &PingoraRequestCtx, response: Option<&pingora_http::ResponseHeader>) {
if ctx.upstream_exchange_span.is_disabled() {
return;
}
if let Some(status) = ctx
.upstream_response_status
.or_else(|| response.map(|resp| resp.status.as_u16()))
{
ctx.upstream_exchange_span.record("http.response.status_code", status);
}
ctx.upstream_exchange_span
.record("http.response.body.size", ctx.response_body_bytes);
}