Functional Weave
Code in Python

monitor.status-code-summary@1.0.0

impl/rust.rs

1,923 bytes · the Rust implementation · view raw

Imports name this capability’s declared dependencies, which fune builds next to it in your project; each one links to its page.

use super::funejson::Value;  ← the fune runtime: the JSON value the test vectors use; fune build keeps it only where a signature takes one
use super::math_round_div::round_div;  ← from math.round-div ^1.0.0 · built alongside by fune

/// HTTP status codes counted by class, with the server error rate (5xx) and
/// the client error rate (4xx) kept apart: only 5xx is the server's failure.
///
/// # Panics
/// Panics on a status code outside 100 to 599.
pub fn summarise_status_codes(statuses: &[i64]) -> StatusCodeSummary {
    let mut counts = [0i64; 5];
    for &s in statuses {
        if !(100..=599).contains(&s) {
            panic!("status code must be 100 to 599, received {}", s);
        }
        counts[(s / 100 - 1) as usize] += 1;
    }
    let total = statuses.len() as i64;
    let rate = |n: i64| if total == 0 { 0 } else { round_div(n * 10000, total, "half-up") };
    StatusCodeSummary {
        total,
        informational: counts[0],
        success: counts[1],
        redirect: counts[2],
        client_error: counts[3],
        server_error: counts[4],
        error_rate_basis_points: rate(counts[4]),
        client_error_rate_basis_points: rate(counts[3]),
    }
}

pub fn status_code_summary_to_value(s: &StatusCodeSummary) -> Value {
    Value::obj(vec![
        ("total", Value::Int(s.total)),
        ("informational", Value::Int(s.informational)),
        ("success", Value::Int(s.success)),
        ("redirect", Value::Int(s.redirect)),
        ("clientError", Value::Int(s.client_error)),
        ("serverError", Value::Int(s.server_error)),
        ("errorRateBasisPoints", Value::Int(s.error_rate_basis_points)),
        ("clientErrorRateBasisPoints", Value::Int(s.client_error_rate_basis_points)),
    ])
}

pub fn fune_vector(args: &[Value]) -> Value {
    let statuses: Vec<i64> = args[0]
        .as_arr()
        .iter()
        .map(|v| match v {
            Value::Int(i) => *i,
            _ => panic!("status code must be a whole number"),
        })
        .collect();
    status_code_summary_to_value(&summarise_status_codes(&statuses))
}