Add benchmark session metadata to JSON exports

This commit is contained in:
David Peter committed 2026-10-05 16:27:35 +02:00
1 parent d60eba407d
commit 6d0ae4f87c
4 files changed
+100 -5

No files matched your search

+17 -5
View File
@@ -8,14 +8,19 @@ use crate::quantity::TimeUnit;
use anyhow::Result;
mod metadata;
use metadata::Metadata;
#[derive(Serialize, Debug)]
struct HyperfineSummary<'a> {
schema_version: u32,
metadata: &'a Metadata,
results: &'a [BenchmarkResult],
}
#[derive(Default)]
pub struct JsonExporter {}
pub struct JsonExporter {
metadata: Metadata,
}
impl Exporter for JsonExporter {
fn serialize(
@@ -26,7 +31,7 @@ impl Exporter for JsonExporter {
_reference_index: Option<usize>,
) -> Result<Vec<u8>> {
let mut output = to_vec_pretty(&HyperfineSummary {
schema_version: 2,
metadata: &self.metadata,
results,
});
if let Ok(ref mut content) = output {
@@ -62,12 +67,19 @@ fn test_json_optional_memory() {
}]),
..BenchmarkResult::default()
};
let output = JsonExporter::default()
let mut exporter = JsonExporter::default();
exporter.metadata.start_time = Some("2000-02-29T12:34:56Z".to_owned());
let output = exporter
.serialize(&[result], None, SortOrder::Command, None)
.unwrap();
let actual: serde_json::Value = serde_json::from_slice(&output).unwrap();
let mut expected = json!({
"schema_version": 2,
"metadata": {
"json_schema_version": metadata::JSON_SCHEMA_VERSION,
"hyperfine_version": env!("CARGO_PKG_VERSION"),
"start_time": "2000-02-29T12:34:56Z",
"platform": exporter.metadata.platform
},
"results": [{
"command": "example",
"measurements": [{
+63
View File
@@ -0,0 +1,63 @@
use serde::Serialize;
pub(super) const JSON_SCHEMA_VERSION: u32 = 2;
#[derive(Debug, Serialize)]
pub(super) struct Metadata {
json_schema_version: u32,
hyperfine_version: &'static str,
#[serde(skip_serializing_if = "Option::is_none")]
pub start_time: Option<String>,
pub platform: Platform,
}
impl Default for Metadata {
fn default() -> Self {
Self {
json_schema_version: JSON_SCHEMA_VERSION,
hyperfine_version: env!("CARGO_PKG_VERSION"),
start_time: utc_now(),
platform: Platform::detect(),
}
}
}
fn utc_now() -> Option<String> {
use std::{fmt::Write, time::SystemTime};
let now = SystemTime::now();
now.duration_since(SystemTime::UNIX_EPOCH).ok()?;
let mut timestamp = String::new();
write!(&mut timestamp, "{}", humantime::format_rfc3339_seconds(now)).ok()?;
Some(timestamp)
}
#[derive(Debug, Default, Serialize)]
pub(super) struct Platform {
#[serde(skip_serializing_if = "Option::is_none")]
os: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
architecture: Option<String>,
}
impl Platform {
fn detect() -> Self {
use platform_info::{PlatformInfo, PlatformInfoAPI, UNameAPI};
let Ok(info) = PlatformInfo::new() else {
return Self::default();
};
Self {
os: Some(info.sysname().to_string_lossy().into_owned()),
architecture: Some(info.machine().to_string_lossy().into_owned()),
}
}
}
#[test]
fn unavailable_platform_fields_are_omitted() {
assert_eq!(
serde_json::to_value(Platform::default()).unwrap(),
serde_json::json!({})
);
}