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
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ python bmp-kusto-scripts/kusto_ingestor.py \
--database "$KUSTO_DATABASE_NAME" \
--table "$KUSTO_TABLE_NAME" \
--filepath "$METRICS_FILE" \
--mapping "$KUSTO_TABLE_MAPPING"
--mapping "$KUSTO_TABLE_MAPPING" \
--ignore-schema
Comment thread
bfjelds marked this conversation as resolved.
Resolved

echo "Metrics uploaded successfully to Kusto."
48 changes: 1 addition & 47 deletions crates/trident/src/logging/tracestream.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ pub(crate) fn clock_boottime_uptime_secs(
}

use osutils::{
dmi,
osrelease::{OsRelease, OS_RELEASE_PATH},
uname, virt,
};
Expand Down Expand Up @@ -806,23 +805,6 @@ where
}
}

/// Obtain product uuid of the hardware Trident is running on. Falls back to
/// "unknown" (rather than failing) since this value is purely informational
/// metadata attached to trace entries.
///
/// Takes the raw string from [`dmi::read_product_uuid_raw`], not the typed
/// [`OsUuid`] from [`dmi::read_product_uuid`]: `OsUuid`'s `Display`
/// canonicalizes a well-formed UUID to lowercase, which would silently
/// change this `asset_id`'s representation (and break continuity with prior
/// telemetry for the same asset) on any host whose BIOS reports
/// `product_uuid` in uppercase.
fn product_uuid_or_unknown(uuid: Result<String, Error>) -> String {
uuid.unwrap_or_else(|err| {
debug!("Failed to read product uuid: {err:#}");
"unknown".into()
})
}

fn correlation_fields(
metric_name: &str,
installation_id: &RwLock<Option<String>>,
Expand Down Expand Up @@ -923,10 +905,6 @@ fn populate_platform_info() -> BTreeMap<String, Value> {
let mut platform_info = BTreeMap::new();
Comment thread
bfjelds marked this conversation as resolved.
Resolved
let mut sys = System::new();
sys.refresh_all();
platform_info.insert(
"asset_id".to_string(),
json!(product_uuid_or_unknown(dmi::read_product_uuid_raw())),
);
platform_info.insert("os_release".to_string(), json!(get_os_release()));
platform_info.insert("total_cpu".to_string(), json!(sys.cpus().len()));
platform_info.insert(
Expand Down Expand Up @@ -1141,26 +1119,6 @@ mod tests {
);
}

#[test]
fn test_read_product_uuid_unknown() {
let uuid = product_uuid_or_unknown(Err(anyhow!("UUID file unavailable")));
assert_eq!(uuid, "unknown");
}

#[test]
fn test_read_product_uuid_exists() {
let uuid = product_uuid_or_unknown(Ok("test_uuid".to_string()));
assert_eq!(uuid, "test_uuid");
}

#[test]
fn test_read_product_uuid_preserves_case() {
// Regression test: must not canonicalize/lowercase a well-formed
// uppercase UUID, unlike OsUuid's Display.
let uuid = product_uuid_or_unknown(Ok("6BA7B810-9DAD-11D1-80B4-00C04FD430C8".to_string()));
assert_eq!(uuid, "6BA7B810-9DAD-11D1-80B4-00C04FD430C8");
}

#[test]
fn test_tracestream_write_metric_event_to_file() {
let temp_dir = tempfile::tempdir().unwrap();
Expand Down Expand Up @@ -1692,7 +1650,7 @@ mod functional_test {

// These two remain functional tests (VM-only) because they assert
// against the actual host's hardware/platform info (CPU count, memory,
// product UUID, os-release, kernel version) -- unlike the metrics-file
// os-release, kernel version) -- unlike the metrics-file
// tests above, there's no way to inject a fake value here, so the
// result is inherently host-dependent.

Expand All @@ -1708,10 +1666,6 @@ mod functional_test {
#[functional_test]
fn test_populate_platform_info() {
let mut expected_platform_info = BTreeMap::new();
expected_platform_info.insert(
"asset_id".to_string(),
json!(product_uuid_or_unknown(dmi::read_product_uuid_raw())),
);
expected_platform_info.insert("os_release".to_string(), json!(get_os_release()));
expected_platform_info.insert("total_cpu".to_string(), json!(4));
expected_platform_info.insert("total_memory_gib".to_string(), json!(6));
Expand Down
18 changes: 7 additions & 11 deletions docs/Reference/Telemetry.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,16 @@ other commands, including `diagnose` and the gRPC client, append instead.
A daemon can accumulate records from multiple gRPC requests in one file.
`diagnose` packages the existing metrics file.

The local metrics file can be found here: `/var/log/trident-metrics.jsonl`.
Servicing paths later copy the current file beside the configured
datastore as `trident-metrics-<SERVICING_STATE>-<TIMESTAMP>.jsonl`
(under `/var/lib/trident` when using the default datastore path).

## Host Metadata

Every recorded event also includes as much of the following host metadata
as is available at the time:

- `asset_id`: the host's DMI product UUID (a stable hardware identifier).
- `os_release`: the `VERSION` field from `/etc/os-release`.
- `kernel_version`: the running kernel release (`uname -r`).
- `total_cpu`: the number of CPUs.
Expand Down Expand Up @@ -81,7 +85,7 @@ Later events include the persistent IDs when available.

## Correlation ID Lifecycle

The four correlation-style fields above have deliberately different
The three correlation-style fields above have deliberately different
lifetimes -- some outlive many servicing operations, some are recreated on
every reinstall, and some exist only for a single command invocation. The
diagram below shows how each behaves across a representative sequence of
Expand Down Expand Up @@ -131,18 +135,10 @@ gantt
section installation_id
installation_id #1 (since install #1) :done, inst1, 2024-01-01, 9d
installation_id #2 (since install #2) :done, inst2, 2024-01-10, 2d

section asset_id
asset_id (never recreated) :active, asset1, 2024-01-01, 11d
```

Reading the diagram by row, from most to least stable:

- **`asset_id`**: identifies the physical machine itself, via its DMI
product UUID. The most stable of the four -- read directly from
hardware rather than the datastore, so it survives every reinstall,
including the second `install` (day 10) that recreates
`installation_id`.
- **`installation_id`**: normally created once at the first `install`
and shared by its multiboot environments. A multiboot install inherits
the running OS's installation ID, persisting it in the staging datastore
Expand All @@ -159,7 +155,7 @@ Reading the diagram by row, from most to least stable:
invocation that stages something new (`install`, `update`,
`update-stage`, `rollback`) -- note `update-finalize` does *not*
regenerate it, since finalize-only invocations only read the value back.
- **`operation_id`**: the shortest-lived of the four, minted fresh for
- **`operation_id`**: the shortest-lived of the three, minted fresh for
every single command invocation and never reused.

## Command Errors
Expand Down
Loading