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}