diff --git a/e2e/tests-dfx/telemetry.bash b/e2e/tests-dfx/telemetry.bash index 90b1f7ca6a..32bd6f5750 100755 --- a/e2e/tests-dfx/telemetry.bash +++ b/e2e/tests-dfx/telemetry.bash @@ -68,11 +68,15 @@ teardown() { } @test "telemetry reprocesses extension commands" { - local log + local log n log=$(dfx info telemetry-log-path) assert_command dfx extension install nns --version 0.3.1 assert_command dfx nns import - assert_command jq -se 'last | .command == "extension run" and (.parameters | any(.name == "name"))' "$log" + assert_command jq -se 'last | .command == "extension run" and (.parameters | any(.name == "@extension_name" and .value == "nns"))' "$log" + n=$(jq -sr 'map(select(has("command"))) | length' "$log") + assert_command dfx nns help + # shellcheck disable=SC2016 + assert_command jq -se '(map(select(has("command"))) | length) == $n' --argjson n "$n" "$log" } @test "concurrent commands do not corrupt the log file" { diff --git a/src/dfx/src/commands/extension/run.rs b/src/dfx/src/commands/extension/run.rs index e249df82a0..5f4e7cd64c 100644 --- a/src/dfx/src/commands/extension/run.rs +++ b/src/dfx/src/commands/extension/run.rs @@ -1,11 +1,13 @@ use crate::lib::environment::Environment; use crate::lib::error::DfxResult; +use crate::lib::telemetry::Telemetry; use clap::Parser; use std::ffi::OsString; #[derive(Parser, Debug)] pub struct RunOpts { /// Specifies the name of the extension to run. + #[arg(id = "@extension_name", value_name = "NAME")] name: OsString, /// Specifies the parameters to pass to the extension. #[arg(allow_hyphen_values = true)] @@ -23,6 +25,9 @@ impl From> for RunOpts { } pub fn exec(env: &dyn Environment, opts: RunOpts) -> DfxResult<()> { + if opts.params.iter().any(|p| p == "--help" || p == "help") { + Telemetry::mark_current_command_likely_noise(); + } let mgr = env.get_extension_manager(); let project_root = env .get_config()? diff --git a/src/dfx/src/lib/telemetry.rs b/src/dfx/src/lib/telemetry.rs index d60ac376f8..2b45ce698e 100644 --- a/src/dfx/src/lib/telemetry.rs +++ b/src/dfx/src/lib/telemetry.rs @@ -71,6 +71,7 @@ pub struct Telemetry { network_type: Option, allowlisted_canisters: BTreeSet, week: Option, + skip: bool, publish: bool, } @@ -239,6 +240,9 @@ impl Telemetry { pub fn append_current_command_timestamped(exit_code: i32) -> DfxResult<()> { try_with_telemetry(|telemetry| { + if telemetry.skip { + return Ok(()); + } let reject = telemetry.last_reject.as_ref(); let call_site = telemetry.last_operation.as_ref().map(|o| match o { Operation::Call { method, canister } => { @@ -272,6 +276,10 @@ impl Telemetry { }) } + pub fn mark_current_command_likely_noise() { + with_telemetry(|t| t.skip = true); + } + pub fn maybe_publish() -> DfxResult { try_with_telemetry(|telemetry| { if telemetry.publish && (Self::check_send_time()? || Self::check_file_size()?) { @@ -656,18 +664,26 @@ fn get_sanitized_arguments(matches: &ArgMatches, command: &Command) -> Vec continue, // ValueSource isn't exhaustive }; - let possible_values = command - .get_arguments() - .find(|arg| arg.get_id() == *id) - .map(|arg| arg.get_possible_values()); - - let sanitized_value = match (possible_values, matches.try_get_one::(id)) { - (Some(possible_values), Ok(Some(s))) - if possible_values.iter().any(|pv| pv.matches(s, true)) => - { - Some(s.clone()) + let sanitized_value = if *id == "@extension_name" { + match matches.try_get_one::(id) { + Ok(Some(s)) if s == "sns" || s == "nns" => { + Some(s.to_str().unwrap().to_string()) + } + _ => None, + } + } else { + let possible_values = command + .get_arguments() + .find(|arg| arg.get_id() == *id) + .map(|arg| arg.get_possible_values()); + match (possible_values, matches.try_get_one::(id)) { + (Some(possible_values), Ok(Some(s))) + if possible_values.iter().any(|pv| pv.matches(s, true)) => + { + Some(s.clone()) + } + _ => None, } - _ => None, }; let argument = Argument {