use super::{
config::Config,
worker::{AllStatsForPeriod, Endpoint, ResponseMetrics, StatsForPeriod},
};
use axum::http::StatusCode;
use chrono::{NaiveDateTime, Utc};
use core::sync::atomic::AtomicUsize;
use flume::Sender;
use parking_lot::{Mutex, RwLock};
use smart_default::SmartDefault;
use std::collections::{HashMap, VecDeque};
use tokio::{
sync::{
RwLock as AsyncRwLock,
broadcast::{Receiver as Listener, Sender as Broadcaster},
},
};
use velcro::hash_map;
#[derive(Debug, SmartDefault)]
#[non_exhaustive]
pub struct State {
pub data: Stats,
pub queue: Option<Sender<ResponseMetrics>>,
pub broadcaster: Option<Broadcaster<AllStatsForPeriod>>,
pub listener: Option<Listener<AllStatsForPeriod>>,
}
#[derive(Debug, SmartDefault)]
#[non_exhaustive]
pub struct Stats {
#[default(Utc::now().naive_utc())]
pub started_at: NaiveDateTime,
pub last_second: RwLock<NaiveDateTime>,
pub connections: AtomicUsize,
pub requests: AtomicUsize,
pub totals: Mutex<StatsTotals>,
pub buffers: RwLock<StatsBuffers>,
}
#[derive(Clone, Debug, PartialEq, SmartDefault)]
#[non_exhaustive]
pub struct StatsTotals {
#[default(hash_map!{
StatusCode::OK: 0,
StatusCode::UNAUTHORIZED: 0,
StatusCode::NOT_FOUND: 0,
StatusCode::INTERNAL_SERVER_ERROR: 0,
})]
pub codes: HashMap<StatusCode, u64>,
pub times: StatsForPeriod,
pub endpoints: HashMap<Endpoint, StatsForPeriod>,
pub connections: StatsForPeriod,
pub memory: StatsForPeriod,
}
#[derive(Clone, Debug, PartialEq, SmartDefault)]
#[non_exhaustive]
pub struct StatsBuffers {
pub responses: VecDeque<StatsForPeriod>,
pub connections: VecDeque<StatsForPeriod>,
pub memory: VecDeque<StatsForPeriod>,
}
pub trait StateProvider: Send + Sync + 'static {
fn config(&self) -> &Config;
fn state(&self) -> &AsyncRwLock<State>;
}