1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
use std::{collections::HashMap, time};
use async_std::task;
use rand::Rng;
use serde::Deserialize;
use crate::{api, error, statics};
#[derive(Deserialize, Debug, Clone)]
pub struct Latency {
pub min: f32,
pub p50: f32,
pub p75: f32,
pub p90: f32,
pub p95: f32,
pub p99: f32,
pub max: f32,
}
impl Latency {
pub fn default() -> Self {
Latency {
min: 0.0,
p50: 0.0,
p75: 0.0,
p90: 0.0,
p95: 0.0,
p99: 0.0,
max: 0.0,
}
}
}
pub type Collection = HashMap<String, Latency>;
pub fn key(api: &str) -> Result<&str, error::FunesError> {
match statics::API_REGEX.find(api) {
Some(v) => Ok(v.as_str()),
None => Err(error::FunesError::LatencyCollection(api.to_string())),
}
}
pub fn map_range(from_range: (f32, f32), to_range: (f32, f32), s: f32) -> f32 {
to_range.0 + (s - from_range.0) * (to_range.1 - to_range.0) / (from_range.1 - from_range.0)
}
fn latency(api: &str, collection: &api::Collection) -> Result<time::Duration, error::FunesError> {
let key = key(api)?;
let latency = collection.get(key).unwrap();
let mut rng = rand::thread_rng();
let random = rng.gen_range(0..=100);
let api_res_time = match random {
0..=50 => map_range((0.0, 50.0), (latency.min, latency.p50), random as f32),
51..=75 => map_range((51.0, 75.0), (latency.p50, latency.p75), random as f32),
76..=90 => map_range((76.0, 90.0), (latency.p75, latency.p90), random as f32),
91..=95 => map_range((91.0, 95.0), (latency.p90, latency.p95), random as f32),
96..=99 => map_range((96.0, 99.0), (latency.p95, latency.p99), random as f32),
100 => latency.max,
_ => 0.0,
};
Ok(time::Duration::from_secs_f32(api_res_time))
}
pub async fn sleep(api: &str, collection: &api::Collection) -> Result<(), error::FunesError> {
if statics::ENVS.latency_enable {
let latency = api::latency(api, collection);
task::sleep(latency?).await;
}
Ok(())
}