Rollup merge of #137827 - yaahc:timestamp-metrics, r=estebank

Add timestamp to unstable feature usage metrics

part of https://github.com/rust-lang/rust/issues/129485

with this we should be able to temporarily enable metrics on docs.rs to gather a nice test dataset for the initial PoC dashboard

r? ```@estebank```
This commit is contained in:
Michael Goulet 2025-03-06 15:40:00 -05:00 committed by GitHub
commit 234a68f06f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 23 additions and 4 deletions

View file

@ -1,6 +1,7 @@
//! List of the unstable feature gates.
use std::path::PathBuf;
use std::time::{SystemTime, UNIX_EPOCH};
use rustc_data_structures::fx::FxHashSet;
use rustc_span::{Span, Symbol, sym};
@ -685,11 +686,13 @@ impl Features {
) -> Result<(), Box<dyn std::error::Error>> {
#[derive(serde::Serialize)]
struct LibFeature {
timestamp: u128,
symbol: String,
}
#[derive(serde::Serialize)]
struct LangFeature {
timestamp: u128,
symbol: String,
since: Option<String>,
}
@ -703,10 +706,20 @@ impl Features {
let metrics_file = std::fs::File::create(metrics_path)?;
let metrics_file = std::io::BufWriter::new(metrics_file);
let now = || {
SystemTime::now()
.duration_since(UNIX_EPOCH)
.expect("system time should always be greater than the unix epoch")
.as_nanos()
};
let lib_features = self
.enabled_lib_features
.iter()
.map(|EnabledLibFeature { gate_name, .. }| LibFeature { symbol: gate_name.to_string() })
.map(|EnabledLibFeature { gate_name, .. }| LibFeature {
symbol: gate_name.to_string(),
timestamp: now(),
})
.collect();
let lang_features = self
@ -715,6 +728,7 @@ impl Features {
.map(|EnabledLangFeature { gate_name, stable_since, .. }| LangFeature {
symbol: gate_name.to_string(),
since: stable_since.map(|since| since.to_string()),
timestamp: now(),
})
.collect();

View file

@ -58,12 +58,17 @@ fn test_metrics_dump() {
);
let message = rfs::read_to_string(json_path);
let parsed: serde_json::Value =
let mut parsed: serde_json::Value =
serde_json::from_str(&message).expect("metrics should be dumped as json");
// remove timestamps
assert!(parsed["lib_features"][0]["timestamp"].is_number());
assert!(parsed["lang_features"][0]["timestamp"].is_number());
parsed["lib_features"][0]["timestamp"] = serde_json::json!(null);
parsed["lang_features"][0]["timestamp"] = serde_json::json!(null);
let expected = serde_json::json!(
{
"lib_features":[{"symbol":"ascii_char"}],
"lang_features":[{"symbol":"box_patterns","since":null}]
"lib_features":[{"symbol":"ascii_char", "timestamp":null}],
"lang_features":[{"symbol":"box_patterns","since":null, "timestamp":null}]
}
);