mkey_exporter/
http.rs

1use crate::profile::Profiler;
2use axum::extract::State;
3use axum::http::header::CONTENT_TYPE;
4use axum::http::{HeaderMap, HeaderValue, StatusCode};
5use axum::response::IntoResponse;
6use prometheus_client::encoding::text;
7use prometheus_client::registry::Registry;
8use std::sync::Arc;
9
10const OCTET_STREAM: &str = "application/octet-stream";
11const METRICS_TEXT: &str = "application/openmetrics-text; version=1.0.0; charset=utf-8";
12
13#[derive(Debug)]
14pub struct RequestState {
15    pub registry: Registry,
16    pub profiler: Profiler,
17}
18
19pub async fn text_metrics_handler(State(state): State<Arc<RequestState>>) -> impl IntoResponse {
20    let mut buf = String::new();
21    let mut headers = HeaderMap::new();
22
23    match text::encode(&mut buf, &state.registry) {
24        Ok(_) => {
25            tracing::debug!(message = "encoded prometheus metrics to text format", bytes = buf.len());
26            headers.insert(CONTENT_TYPE, HeaderValue::from_static(METRICS_TEXT));
27            (StatusCode::OK, headers, buf.into_bytes())
28        }
29        Err(e) => {
30            tracing::error!(message = "error encoding metrics to text format", error = %e);
31            (StatusCode::INTERNAL_SERVER_ERROR, headers, Vec::new())
32        }
33    }
34}
35
36pub async fn pprof_handler(State(state): State<Arc<RequestState>>) -> impl IntoResponse {
37    let mut headers = HeaderMap::new();
38
39    match state.profiler.proto() {
40        Ok(bytes) => {
41            tracing::debug!(message = "encoded profiling data to protobuf", bytes = bytes.len());
42            headers.insert(CONTENT_TYPE, HeaderValue::from_static(OCTET_STREAM));
43            (StatusCode::OK, headers, bytes)
44        }
45        Err(e) => {
46            tracing::error!(message = "error building or encoding profiling report", error = %e);
47            (StatusCode::INTERNAL_SERVER_ERROR, headers, Vec::new())
48        }
49    }
50}