strest 0.1.10

Blazing-fast async HTTP load tester in Rust - lock-free design, real-time stats, distributed runs, and optional chart exports for high-load API testing.
Documentation
mod reader;
mod writer;

use std::sync::atomic::{AtomicUsize, Ordering};
use std::time::Duration;

use tokio::sync::mpsc;

use super::{LatencyHistogram, MetricRecord, Metrics, MetricsRange, MetricsSummary};

#[cfg(any(test, feature = "fuzzing"))]
pub use reader::read_metrics_log;
pub use writer::setup_metrics_logger;

#[derive(Debug)]
pub struct LogSink {
    senders: Vec<mpsc::Sender<Metrics>>,
    next: AtomicUsize,
}

impl LogSink {
    #[must_use]
    pub const fn new(senders: Vec<mpsc::Sender<Metrics>>) -> Self {
        Self {
            senders,
            next: AtomicUsize::new(0),
        }
    }

    pub fn send(&self, metric: Metrics) -> bool {
        if self.senders.is_empty() {
            return false;
        }
        let len = self.senders.len();
        let idx = self
            .next
            .fetch_add(1, Ordering::Relaxed)
            .checked_rem(len)
            .unwrap_or(0);
        self.senders
            .get(idx)
            .is_some_and(|sender| match sender.try_send(metric) {
                Ok(()) => true,
                Err(mpsc::error::TrySendError::Full(_)) => true,
                Err(mpsc::error::TrySendError::Closed(_)) => false,
            })
    }
}

#[derive(Debug)]
pub struct LogResult {
    pub records: Vec<MetricRecord>,
    pub summary: MetricsSummary,
    pub metrics_truncated: bool,
    pub latency_sum_ms: u128,
    pub success_latency_sum_ms: u128,
    pub histogram: LatencyHistogram,
    pub success_histogram: LatencyHistogram,
}

#[derive(Debug, Clone)]
pub struct MetricsLoggerConfig {
    pub run_start: tokio::time::Instant,
    pub warmup: Option<Duration>,
    pub expected_status_code: u16,
    pub metrics_range: Option<MetricsRange>,
    pub metrics_max: usize,
    pub db_url: Option<String>,
}