rs-zero 0.1.0

Rust-first microservice framework inspired by go-zero engineering practices
Documentation
use std::time::Duration;

use axum::{Router, middleware, routing::get};
use rs_zero::observability::{
    HttpMetricLabels, MetricsRegistry, metrics_router, record_metrics_middleware,
};
use tower::ServiceExt;

#[test]
fn registry_exports_prometheus_text() {
    let registry = MetricsRegistry::new();
    registry.record_http_request(
        HttpMetricLabels::new("GET", "/ready", 200),
        Duration::from_millis(5),
    );
    let text = registry.render_prometheus();
    assert!(text.contains("rs_zero_http_requests_total"));
    assert!(text.contains("route=\"/ready\""));
}

#[tokio::test]
async fn rest_metrics_layer_records_matched_path() {
    let registry = MetricsRegistry::new();
    let app = Router::new()
        .route("/users/{id}", get(|| async { "ok" }))
        .merge(metrics_router(registry.clone()))
        .layer(middleware::from_fn_with_state(
            registry.clone(),
            record_metrics_middleware,
        ));

    let response = app
        .oneshot(
            axum::http::Request::builder()
                .uri("/users/42")
                .body(axum::body::Body::empty())
                .expect("request"),
        )
        .await
        .expect("response");
    assert_eq!(response.status(), axum::http::StatusCode::OK);

    let text = registry.render_prometheus();
    assert!(text.contains("route=\"/users/{id}\""));
    assert!(!text.contains("/users/42"));
}