Skip to content

Commit babc38e

Browse files
committed
bencher_fingerprint
1 parent f7b5415 commit babc38e

File tree

17 files changed

+343
-8
lines changed

17 files changed

+343
-8
lines changed

Cargo.lock

Lines changed: 119 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ bencher_adapter = { path = "lib/bencher_adapter" }
2626
bencher_boundary = { path = "lib/bencher_boundary" }
2727
bencher_client = { path = "lib/bencher_client" }
2828
bencher_comment = { path = "lib/bencher_comment" }
29+
bencher_fingerprint = { path = "lib/bencher_fingerprint" }
2930
bencher_github = { path = "lib/bencher_github" }
3031
bencher_json = { path = "lib/bencher_json" }
3132
bencher_logger = { path = "lib/bencher_logger" }

lib/bencher_fingerprint/Cargo.toml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
[package]
2+
name = "bencher_fingerprint"
3+
homepage.workspace = true
4+
version.workspace = true
5+
authors.workspace = true
6+
edition.workspace = true
7+
license-file.workspace = true
8+
9+
[features]
10+
client = ["dep:windows"]
11+
schema = ["dep:schemars"]
12+
13+
[dependencies]
14+
derive_more.workspace = true
15+
schemars = { workspace = true, optional = true }
16+
serde.workspace = true
17+
thiserror.workspace = true
18+
typeshare.workspace = true
19+
uuid = { workspace = true, features = ["serde"] }
20+
21+
[target.'cfg(target_os = "windows")'.dependencies]
22+
windows = { version = "0.60", optional = true, features = [
23+
"System_Profile_SystemManufacturers",
24+
] }
25+
26+
[lints]
27+
workspace = true

lib/bencher_fingerprint/src/lib.rs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
use std::str::FromStr;
2+
3+
use derive_more::Display;
4+
#[cfg(feature = "schema")]
5+
use schemars::JsonSchema;
6+
use serde::{Deserialize, Serialize};
7+
use uuid::Uuid;
8+
9+
#[cfg(feature = "client")]
10+
mod target_os;
11+
12+
#[typeshare::typeshare]
13+
#[derive(Debug, Display, Clone, Copy, Eq, PartialEq, Hash, Serialize, Deserialize)]
14+
#[cfg_attr(feature = "schema", derive(JsonSchema))]
15+
pub struct Fingerprint(Uuid);
16+
17+
#[derive(Debug, Clone, thiserror::Error)]
18+
pub enum FingerprintError {
19+
#[error("Failed to parse fingerprint: {0}")]
20+
Parse(String),
21+
}
22+
23+
impl FromStr for Fingerprint {
24+
type Err = FingerprintError;
25+
26+
fn from_str(fingerprint: &str) -> Result<Self, Self::Err> {
27+
Ok(Self(fingerprint.parse().map_err(|_e| {
28+
FingerprintError::Parse(fingerprint.to_owned())
29+
})?))
30+
}
31+
}
32+
33+
impl From<Uuid> for Fingerprint {
34+
fn from(uuid: Uuid) -> Self {
35+
Self(uuid)
36+
}
37+
}
38+
39+
impl From<Fingerprint> for Uuid {
40+
fn from(fingerprint: Fingerprint) -> Self {
41+
fingerprint.0
42+
}
43+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
use std::fs;
2+
3+
use uuid::Uuid;
4+
5+
const HEX_BASE: u32 = 16;
6+
7+
impl crate::Fingerprint {
8+
pub fn new() -> Option<Self> {
9+
parse_machine_id("/var/lib/dbus/machine-id")
10+
.or_else(|| parse_machine_id("/etc/machine-id"))
11+
.map(Self)
12+
}
13+
}
14+
15+
fn parse_machine_id(path: &str) -> Option<Uuid> {
16+
fs::read_to_string(path)
17+
.ok()
18+
.and_then(|id| u128::from_str_radix(id.trim(), HEX_BASE).ok())
19+
.map(Uuid::from_u128)
20+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
use std::process::Command;
2+
3+
use uuid::Uuid;
4+
5+
impl crate::Fingerprint {
6+
pub fn new() -> Option<Self> {
7+
Command::new("ioreg")
8+
.arg("-d2")
9+
.arg("-c")
10+
.arg("IOPlatformExpertDevice")
11+
.output()
12+
.ok()
13+
.and_then(|out| String::from_utf8(out.stdout).ok())
14+
.and_then(|output| {
15+
for line in output.lines() {
16+
if let Some((_, uuid)) = line.split_once(r#""IOPlatformUUID" = ""#) {
17+
if let Some((uuid, _)) = uuid.split_once('"') {
18+
return Uuid::parse_str(uuid).ok();
19+
}
20+
}
21+
}
22+
None
23+
})
24+
.map(Self)
25+
}
26+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#[cfg(target_os = "linux")]
2+
mod linux;
3+
#[cfg(target_os = "macos")]
4+
mod macos;
5+
#[cfg(target_os = "windows")]
6+
mod windows;
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
use uuid::Uuid;
2+
3+
impl crate::Fingerprint {
4+
pub fn new() -> Option<Self> {
5+
windows::System::Profile::SystemManufacturers::SmbiosInformation::SerialNumber()
6+
.ok()
7+
.as_ref()
8+
.and_then(|hstring| {
9+
let uuid = hstring.to_string();
10+
println!("{uuid}");
11+
println!("{}", uuid.trim());
12+
Uuid::parse_str(&hstring.to_string().trim()).ok()
13+
})
14+
.map(Self)
15+
}
16+
}

lib/bencher_json/Cargo.toml

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,19 @@ publish = false
88

99
[features]
1010
full = ["bencher_valid/full"]
11-
lite = ["bencher_valid/lite"]
11+
lite = ["bencher_fingerprint/client", "bencher_valid/lite"]
1212
db = ["diesel", "serde_yaml", "bencher_valid/db"]
1313
plus = ["bencher_valid/plus"]
14-
schema = ["dep:schemars", "ordered-float/schemars"]
14+
schema = [
15+
"dep:schemars",
16+
"ordered-float/schemars",
17+
"bencher_fingerprint/schema",
18+
]
1519
table = ["dep:tabled"]
1620

1721
[dependencies]
1822
# Workspace
23+
bencher_fingerprint.workspace = true
1924
bencher_valid = { workspace = true, features = ["schema"] }
2025
chrono = { workspace = true, features = ["serde"] }
2126
derive_more.workspace = true

lib/bencher_json/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use std::sync::LazyLock;
22

3+
pub use bencher_fingerprint::Fingerprint;
34
pub use bencher_valid::{
45
BenchmarkName, Boundary, BranchName, CdfBoundary, DateTime, DateTimeMillis, Email, GitHash,
56
Index, IqrBoundary, Jwt, Model, ModelTest, NameId, NameIdKind, NonEmpty, PercentageBoundary,

0 commit comments

Comments
 (0)