Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 49 additions & 1 deletion schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,54 @@
"sizePerSec"
]
},
"metrics": {
"description": "CI friendly statistics",
"type": "object",
"properties": {
"success_rate": {
"description": "The number of success requests / All requests which isn't includes deadline",
"type": "number"
},
"requests_per_sec": {
"description": "The number of requests per second",
"type": "number"
},
"latency_ms": {
"description": "Selected latency statistics in millieseconds",
"type": "object",
"properties": {
"min": {
"type": "number"
},
"mean": {
"type": "number"
},
"p50": {
"type": "number"
},
"p95": {
"type": "number"
},
"p99": {
"type": "number"
}
},
"required": [
"min",
"mean",
"p50",
"p95",
"p99",
"max"
]
}
},
"required": [
"success_rate",
"requests_per_sec",
"latency_ms"
]
},
"responseTimeHistogram": {
"description": "The histogram of response time in seconds. The key is the response time in seconds and the value is the number of requests",
"type": "object",
Expand Down Expand Up @@ -433,4 +481,4 @@
"statusCodeDistribution",
"errorDistribution"
]
}
}
40 changes: 39 additions & 1 deletion src/printer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,24 @@ fn print_json<W: Write>(
size_per_sec: f64,
}

#[derive(Serialize)]
struct Metrics {
success_rate: f64,
requests_per_sec: f64,
latency_ms: LatencyMs,
}

#[derive(Serialize)]
#[serde(rename = "latency_ms")]
struct LatencyMs {
min: f64,
mean: f64,
p50: f64,
p95: f64,
p99: f64,
max: f64,
}

#[derive(Serialize)]
struct Triple {
average: f64,
Expand Down Expand Up @@ -196,6 +214,7 @@ fn print_json<W: Write>(
#[derive(Serialize)]
struct Result {
summary: Summary,
metrics: Metrics,
#[serde(rename = "responseTimeHistogram")]
response_time_histogram: BTreeMap<String, usize>,
#[serde(rename = "latencyPercentiles")]
Expand Down Expand Up @@ -259,7 +278,20 @@ fn print_json<W: Write>(
.percentiles
.into_iter()
.map(|(p, v)| (format!("p{p}"), v))
.collect();
.collect::<BTreeMap<String, f64>>();

let metrics = Metrics {
success_rate: res.success_rate(),
requests_per_sec: res.len() as f64 / total_duration.as_secs_f64(),
latency_ms: LatencyMs {
min: ms(latency_stat.min()),
mean: ms(latency_stat.mean()),
p50: ms(latency_percentiles["p50"]),
p95: ms(latency_percentiles["p95"]),
p99: ms(latency_percentiles["p99"]),
max: ms(latency_stat.max()),
},
};

let first_byte_statistics = res.first_byte_all_statistics();

Expand Down Expand Up @@ -389,6 +421,7 @@ fn print_json<W: Write>(
w,
&Result {
summary,
metrics,
response_time_histogram,
latency_percentiles,
first_byte_histogram,
Expand Down Expand Up @@ -732,6 +765,11 @@ fn percentiles(values: &mut [f64]) -> BTreeMap<String, f64> {
.collect()
}

// convert s to ms
fn ms(value: f64) -> f64 {
(value * 1000.0 * 1000.0).round() / 1000.0
}

#[cfg(test)]
mod tests {
use float_cmp::assert_approx_eq;
Expand Down
Loading