diff --git a/README.md b/README.md index ff06bffee..4d9c7835b 100644 --- a/README.md +++ b/README.md @@ -465,6 +465,7 @@ Here is a table of the [diagnostic data we collect][diagnosticdata]: | `is_ci` | Whether the installer is being used in CI (e.g. GitHub Actions). | | `action` | Either `Install` or `Uninstall`. | | `status` | One of `Success`, `Failure`, `Pending`, or `Cancelled`. | +| `attribution` | Optionally defined by the user, associate the diagnostics of this run to the provided value. | | `failure_chain` | A high level description of what the failure was, if any. For example: `Command("diskutil")` if the command `diskutil list` failed. | To disable diagnostic reporting, set the diagnostics URL to an empty string by passing `--diagnostic-endpoint=""` or setting `NIX_INSTALLER_DIAGNOSTIC_ENDPOINT=""`. diff --git a/src/action/mod.rs b/src/action/mod.rs index 36b1f81e3..259243445 100644 --- a/src/action/mod.rs +++ b/src/action/mod.rs @@ -156,6 +156,7 @@ impl Planner for MyPlanner { #[cfg(feature = "diagnostics")] async fn diagnostic_data(&self) -> Result { Ok(nix_installer::diagnostics::DiagnosticData::new( + self.common.attribution.clone(), self.common.diagnostic_endpoint.clone(), self.typetag_name().into(), self.configured_settings() diff --git a/src/diagnostics.rs b/src/diagnostics.rs index 138832860..294f579b7 100644 --- a/src/diagnostics.rs +++ b/src/diagnostics.rs @@ -34,6 +34,7 @@ pub enum DiagnosticAction { /// A report sent to an endpoint #[derive(Debug, serde::Deserialize, serde::Serialize, Clone)] pub struct DiagnosticReport { + pub attribution: Option, pub version: String, pub planner: String, pub configured_settings: Vec, @@ -50,6 +51,7 @@ pub struct DiagnosticReport { /// A preparation of data to be sent to the `endpoint`. #[derive(Debug, serde::Deserialize, serde::Serialize, Clone, Default)] pub struct DiagnosticData { + attribution: Option, version: String, planner: String, configured_settings: Vec, @@ -65,6 +67,7 @@ pub struct DiagnosticData { impl DiagnosticData { pub fn new( + attribution: Option, endpoint: Option, planner: String, configured_settings: Vec, @@ -81,6 +84,7 @@ impl DiagnosticData { let is_ci = is_ci::cached() || std::env::var("NIX_INSTALLER_CI").unwrap_or_else(|_| "0".into()) == "1"; Ok(Self { + attribution, endpoint, version: env!("CARGO_PKG_VERSION").into(), planner, @@ -131,6 +135,7 @@ impl DiagnosticData { pub fn report(&self, action: DiagnosticAction, status: DiagnosticStatus) -> DiagnosticReport { let Self { + attribution, version, planner, configured_settings, @@ -143,6 +148,7 @@ impl DiagnosticData { failure_chain, } = self; DiagnosticReport { + attribution: attribution.clone(), version: version.clone(), planner: planner.clone(), configured_settings: configured_settings.clone(), diff --git a/src/planner/linux.rs b/src/planner/linux.rs index 81ab4b76e..f0e0b6a5e 100644 --- a/src/planner/linux.rs +++ b/src/planner/linux.rs @@ -129,6 +129,7 @@ impl Planner for Linux { #[cfg(feature = "diagnostics")] async fn diagnostic_data(&self) -> Result { Ok(crate::diagnostics::DiagnosticData::new( + self.settings.attribution.clone(), self.settings.diagnostic_endpoint.clone(), self.typetag_name().into(), self.configured_settings() diff --git a/src/planner/macos.rs b/src/planner/macos.rs index 644477da3..c29373fad 100644 --- a/src/planner/macos.rs +++ b/src/planner/macos.rs @@ -210,6 +210,7 @@ impl Planner for Macos { #[cfg(feature = "diagnostics")] async fn diagnostic_data(&self) -> Result { Ok(crate::diagnostics::DiagnosticData::new( + self.settings.attribution.clone(), self.settings.diagnostic_endpoint.clone(), self.typetag_name().into(), self.configured_settings() diff --git a/src/planner/mod.rs b/src/planner/mod.rs index 0c548603d..cc102fae6 100644 --- a/src/planner/mod.rs +++ b/src/planner/mod.rs @@ -72,6 +72,7 @@ impl Planner for MyPlanner { #[cfg(feature = "diagnostics")] async fn diagnostic_data(&self) -> Result { Ok(nix_installer::diagnostics::DiagnosticData::new( + self.common.attribution.clone(), self.common.diagnostic_endpoint.clone(), self.typetag_name().into(), self.configured_settings() diff --git a/src/planner/ostree.rs b/src/planner/ostree.rs index 554ebbb17..667141025 100644 --- a/src/planner/ostree.rs +++ b/src/planner/ostree.rs @@ -262,6 +262,7 @@ impl Planner for Ostree { #[cfg(feature = "diagnostics")] async fn diagnostic_data(&self) -> Result { Ok(crate::diagnostics::DiagnosticData::new( + self.settings.attribution.clone(), self.settings.diagnostic_endpoint.clone(), self.typetag_name().into(), self.configured_settings() diff --git a/src/planner/steam_deck.rs b/src/planner/steam_deck.rs index a4ac1ff4d..33ffc86fa 100644 --- a/src/planner/steam_deck.rs +++ b/src/planner/steam_deck.rs @@ -388,6 +388,7 @@ impl Planner for SteamDeck { #[cfg(feature = "diagnostics")] async fn diagnostic_data(&self) -> Result { Ok(crate::diagnostics::DiagnosticData::new( + self.settings.attribution.clone(), self.settings.diagnostic_endpoint.clone(), self.typetag_name().into(), self.configured_settings() diff --git a/src/settings.rs b/src/settings.rs index a45fc096c..f27a63785 100644 --- a/src/settings.rs +++ b/src/settings.rs @@ -57,6 +57,18 @@ Settings which only apply to certain [`Planner`](crate::planner::Planner)s shoul #[derive(Debug, serde::Deserialize, serde::Serialize, Clone)] #[cfg_attr(feature = "cli", derive(clap::Parser))] pub struct CommonSettings { + /// Attribute the diagnostics of this run to a specific usage category + #[cfg_attr( + feature = "cli", + clap( + long, + default_value = None, + env = "NIX_INSTALLER_ATTRIBUTION", + global = true + ) + )] + pub attribution: Option, + /// Modify the user profile to automatically load nix #[cfg_attr( feature = "cli", @@ -289,6 +301,7 @@ impl CommonSettings { }; Ok(Self { + attribution: None, modify_profile: true, nix_build_group_name: String::from("nixbld"), nix_build_group_id: 30_000, @@ -308,6 +321,7 @@ impl CommonSettings { /// A listing of the settings, suitable for [`Planner::settings`](crate::planner::Planner::settings) pub fn settings(&self) -> Result, InstallSettingsError> { let Self { + attribution: _, modify_profile, nix_build_group_name, nix_build_group_id,