12 个版本 (6 个重大更改)

0.7.0 2024 年 7 月 20 日
0.6.1 2024 年 1 月 23 日
0.5.0 2023 年 11 月 27 日
0.4.0 2023 年 7 月 24 日
0.2.0 2022 年 11 月 25 日

#81 in 网络编程

Download history 5735/week @ 2024-05-03 6004/week @ 2024-05-10 6466/week @ 2024-05-17 5030/week @ 2024-05-24 4879/week @ 2024-05-31 4546/week @ 2024-06-07 4342/week @ 2024-06-14 6269/week @ 2024-06-21 4732/week @ 2024-06-28 5886/week @ 2024-07-05 6108/week @ 2024-07-12 7866/week @ 2024-07-19 8134/week @ 2024-07-26 7814/week @ 2024-08-02 7652/week @ 2024-08-09 7882/week @ 2024-08-16

每月33,092次下载
用于 9 个 Crates (8 个直接)

MIT 许可证

76KB
982

Axum-Prometheus

Axum 应用的 HTTP 指标收集中间件。

axum-prometheus 依赖于 metrics.rs 和其生态系统来收集和导出指标 - 例如,对于 Prometheus,使用 metrics_exporter_prometheus 作为后端与 Prometheus 交互。

指标

默认情况下,跟踪三个 HTTP 指标

  • axum_http_requests_total (标签:端点、方法、状态):处理 HTTP 请求的总数(计数器)
  • axum_http_requests_duration_seconds (标签:端点、方法、状态):处理所有 HTTP 请求的持续时间(直方图)
  • axum_http_requests_pending (标签:端点、方法):当前正在进行的请求数(量表)

此 crate 还允许跟踪响应体大小作为直方图 - 请参阅 PrometheusMetricLayerBuilder::enable_response_body_size

重命名指标

这些指标可以通过在编译时指定环境变量来重命名

  • AXUM_HTTP_REQUESTS_TOTAL
  • AXUM_HTTP_REQUESTS_DURATION_SECONDS
  • AXUM_HTTP_REQUESTS_PENDING
  • AXUM_HTTP_RESPONSE_BODY_SIZE (如果启用了身体大小跟踪)

这些环境变量可以从 Cargo 1.56 开始在您的 .cargo/config.toml 中设置

[env]
AXUM_HTTP_REQUESTS_TOTAL = "my_app_requests_total"
AXUM_HTTP_REQUESTS_DURATION_SECONDS = "my_app_requests_duration_seconds"
AXUM_HTTP_REQUESTS_PENDING = "my_app_requests_pending"
AXUM_HTTP_RESPONSE_BODY_SIZE = "my_app_response_body_size"

..或者可选地使用 PrometheusMetricLayerBuilder::with_prefix 函数。

兼容性

Axum 版本 Crate 版本
0.5 0.1
0.6 0.2, 0.3, 0.4
0.7 0.5, 0.6, 0.7

MSRV

此 crate 的当前 MSRV 是 1.70。

用法

有关更详细的使用案例,请参阅 builder 示例

axum-prometheus 添加到您的 Cargo.toml 文件中。

[dependencies]
axum-prometheus = "0.7.0"

然后实例化 Prometheus 中间件

use std::{net::SocketAddr, time::Duration};
use axum::{routing::get, Router};
use axum_prometheus::PrometheusMetricLayer;

#[tokio::main]
async fn main() {
    let (prometheus_layer, metric_handle) = PrometheusMetricLayer::pair();
    let app = Router::<()>::new()
        .route("/fast", get(|| async {}))
        .route(
            "/slow",
            get(|| async {
                tokio::time::sleep(Duration::from_secs(1)).await;
            }),
        )
        .route("/metrics", get(|| async move { metric_handle.render() }))
        .layer(prometheus_layer);


    let listener = tokio::net::TcpListener::bind(SocketAddr::from(([127, 0, 0, 1], 3000)))
        .await
        .unwrap();
    axum::serve(listener, app).await.unwrap();
}

请注意,/metrics 端点不是自动公开的,因此您需要手动添加该路由。调用 /metrics 端点将公开您的指标

axum_http_requests_total{method="GET",endpoint="/metrics",status="200"} 5
axum_http_requests_pending{method="GET",endpoint="/metrics"} 1
axum_http_requests_duration_seconds_bucket{method="GET",status="200",endpoint="/metrics",le="0.005"} 4
axum_http_requests_duration_seconds_bucket{method="GET",status="200",endpoint="/metrics",le="0.01"} 4
axum_http_requests_duration_seconds_bucket{method="GET",status="200",endpoint="/metrics",le="0.025"} 4
axum_http_requests_duration_seconds_bucket{method="GET",status="200",endpoint="/metrics",le="0.05"} 4
axum_http_requests_duration_seconds_bucket{method="GET",status="200",endpoint="/metrics",le="0.1"} 4
axum_http_requests_duration_seconds_bucket{method="GET",status="200",endpoint="/metrics",le="0.25"} 4
axum_http_requests_duration_seconds_bucket{method="GET",status="200",endpoint="/metrics",le="0.5"} 4
axum_http_requests_duration_seconds_bucket{method="GET",status="200",endpoint="/metrics",le="1"} 4
axum_http_requests_duration_seconds_bucket{method="GET",status="200",endpoint="/metrics",le="2.5"} 4
axum_http_requests_duration_seconds_bucket{method="GET",status="200",endpoint="/metrics",le="5"} 4
axum_http_requests_duration_seconds_bucket{method="GET",status="200",endpoint="/metrics",le="10"} 4
axum_http_requests_duration_seconds_bucket{method="GET",status="200",endpoint="/metrics",le="+Inf"} 4
axum_http_requests_duration_seconds_sum{method="GET",status="200",endpoint="/metrics"} 0.001997171
axum_http_requests_duration_seconds_count{method="GET",status="200",endpoint="/metrics"} 4

请注意,由于 metrics-exporter-prometheus -version = "0.13" 该crate 引入了 默认的 push-gateway 功能,这需要 openssl 支持。axum_prometheus crate 不依赖 也不默认启用此功能 — 如果您需要它,您可以通过 "push-gateway" 功能在 axum_prometheus 中启用它。

Prometheus 推送网关功能

该crate目前没有为push-gateway功能提供更高层次的API。如果您计划使用它,请在axum-prometheus中启用push-gateway功能,使用BaseMetricLayer,并手动设置您的记录器,类似于 base-metric-layer-example

使用不同于 Prometheus 的导出器

该crate可以与 Prometheus 之外的导出器一起使用。首先,禁用默认功能

axum-prometheus = { version = "0.7.0", default-features = false }

然后实现您想要使用的提供者的 MakeDefaultHandle。对于 StatsD

use metrics_exporter_statsd::StatsdBuilder;
use axum_prometheus::{MakeDefaultHandle, GenericMetricLayer};

// The custom StatsD exporter struct. It may take fields as well.
struct Recorder { port: u16 }

// In order to use this with `axum_prometheus`, we must implement `MakeDefaultHandle`.
impl MakeDefaultHandle for Recorder {
    // We don't need to return anything meaningful from here (unlike PrometheusHandle)
    // Let's just return an empty tuple.
    type Out = ();

    fn make_default_handle(self) -> Self::Out {
        // The regular setup for StatsD. Notice that `self` is passed in by value.
        let recorder = StatsdBuilder::from("127.0.0.1", self.port)
            .with_queue_size(5000)
            .with_buffer_size(1024)
            .build(Some("prefix"))
            .expect("Could not create StatsdRecorder");

        metrics::set_boxed_recorder(Box::new(recorder)).unwrap();
    }
}

fn main() {
    // Use `GenericMetricLayer` instead of `PrometheusMetricLayer`.
    // Generally `GenericMetricLayer::pair_from` is what you're looking for.
    // It lets you pass in a concrete initialized `Recorder`.
    let (metric_layer, _handle) = GenericMetricLayer::pair_from(Recorder { port: 8125 });
}

还可以使用 GenericMetricLayer::pair,但是它只能在记录器结构实现 Default 的情况下调用。

use metrics_exporter_statsd::StatsdBuilder;
use axum_prometheus::{MakeDefaultHandle, GenericMetricLayer};

#[derive(Default)]
struct Recorder { port: u16 }

impl MakeDefaultHandle for Recorder {
   /* .. same as before .. */
}

fn main() {
    // This will internally call `Recorder::make_default_handle(Recorder::default)`.
    let (metric_layer, _handle) = GenericMetricLayer::<_, Recorder>::pair();
}

该crate与(并从) actix-web-promrocket_prometheus 类似,并且还构建在 davidpdrsn 的 tower-http 中的早期工作 LifeCycleHooks 之上。

依赖项

~6–11MB
~187K SLoC