diff --git a/Cargo.lock b/Cargo.lock index ee75fe72714..fffd53e19e8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1064,12 +1064,8 @@ dependencies = [ "rustup-utils 1.16.0", "same-file 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", "sha2 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "tempfile 3.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1114,7 +1110,6 @@ dependencies = [ "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "wait-timeout 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.5 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "winreg 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1224,16 +1219,6 @@ name = "serde" version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "serde_derive" -version = "1.0.79" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.9 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "serde_json" version = "1.0.32" @@ -1926,7 +1911,6 @@ dependencies = [ "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" "checksum serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)" = "84257ccd054dc351472528c8587b4de2dbf0dc0fe2e634030c1a90bfdacebaa9" -"checksum serde_derive 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)" = "31569d901045afbff7a9479f793177fe9259819aff10ab4f89ef69bbc5f567fe" "checksum serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)" = "43344e7ce05d0d8280c5940cabb4964bea626aa58b1ec0e8c73fa2a8512a38ce" "checksum serde_urlencoded 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "aaed41d9fb1e2f587201b863356590c90c1157495d811430a0c0325fe8169650" "checksum sha2 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9eb6be24e4c23a84d7184280d2722f7f2731fcdd4a9d886efbfe4413e4847ea0" diff --git a/Cargo.toml b/Cargo.toml index 53f98745368..8951df19c58 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -46,12 +46,8 @@ regex = "1.0.1" remove_dir_all = "0.5.1" same-file = "1.0" scopeguard = "0.3" -serde = "1.0" -serde_derive = "1.0" -serde_json = "1.0" sha2 = "0.7.0" tempdir = "0.3.4" -tempfile = "3.0.2" term = "0.5.1" time = "0.1.34" toml = "0.4" diff --git a/src/rustup-cli/common.rs b/src/rustup-cli/common.rs index 0b167ccef48..91da0a8fd90 100644 --- a/src/rustup-cli/common.rs +++ b/src/rustup-cli/common.rs @@ -3,7 +3,6 @@ use crate::errors::*; use crate::self_update; use crate::term2; -use rustup::telemetry_analysis::TelemetryAnalysis; use rustup::{self, Cfg, Notification, Toolchain, UpdateStatus}; use rustup_utils::notify::NotificationLevel; use rustup_utils::utils; @@ -434,11 +433,3 @@ pub fn report_error(e: &Error) { false } } - -pub fn show_telemetry(analysis: TelemetryAnalysis) -> Result<()> { - println!("Telemetry Analysis"); - - println!("{}", analysis); - - Ok(()) -} diff --git a/src/rustup-cli/proxy_mode.rs b/src/rustup-cli/proxy_mode.rs index da07827a385..9f26338cbb8 100644 --- a/src/rustup-cli/proxy_mode.rs +++ b/src/rustup-cli/proxy_mode.rs @@ -57,5 +57,5 @@ fn direct_proxy( None => cfg.create_command_for_dir(&utils::current_dir()?, arg0)?, Some(tc) => cfg.create_command_for_toolchain(tc, false, arg0)?, }; - Ok(run_command_for_dir(cmd, arg0, args, &cfg)?) + Ok(run_command_for_dir(cmd, arg0, args)?) } diff --git a/src/rustup-cli/rustup_mode.rs b/src/rustup-cli/rustup_mode.rs index afdfca8740f..0352995bc23 100644 --- a/src/rustup-cli/rustup_mode.rs +++ b/src/rustup-cli/rustup_mode.rs @@ -4,7 +4,6 @@ use crate::help::*; use crate::self_update; use crate::term2; use clap::{App, AppSettings, Arg, ArgGroup, ArgMatches, Shell, SubCommand}; -use rustup::settings::TelemetryMode; use rustup::{command, Cfg, Toolchain}; use rustup_dist::dist::{PartialTargetTriple, PartialToolchainDesc, TargetTriple}; use rustup_dist::manifest::Component; @@ -71,12 +70,6 @@ pub fn main() -> Result<()> { ("uninstall", Some(m)) => self_uninstall(m)?, (_, _) => unreachable!(), }, - ("telemetry", Some(c)) => match c.subcommand() { - ("enable", Some(_)) => set_telemetry(&cfg, TelemetryMode::On)?, - ("disable", Some(_)) => set_telemetry(&cfg, TelemetryMode::Off)?, - ("analyze", Some(_)) => analyze_telemetry(&cfg)?, - (_, _) => unreachable!(), - }, ("set", Some(c)) => match c.subcommand() { ("default-host", Some(m)) => set_default_host_triple(&cfg, m)?, (_, _) => unreachable!(), @@ -453,17 +446,6 @@ pub fn cli() -> App<'static, 'static> { SubCommand::with_name("upgrade-data").about("Upgrade the internal data format."), ), ) - .subcommand( - SubCommand::with_name("telemetry") - .about("rustup telemetry commands") - .setting(AppSettings::Hidden) - .setting(AppSettings::VersionlessSubcommands) - .setting(AppSettings::DeriveDisplayOrder) - .setting(AppSettings::SubcommandRequiredElseHelp) - .subcommand(SubCommand::with_name("enable").about("Enable rustup telemetry")) - .subcommand(SubCommand::with_name("disable").about("Disable rustup telemetry")) - .subcommand(SubCommand::with_name("analyze").about("Analyze stored telemetry")), - ) .subcommand( SubCommand::with_name("set") .about("Alter rustup settings") @@ -630,7 +612,7 @@ fn run(cfg: &Cfg, m: &ArgMatches) -> Result<()> { let args: Vec<_> = args.collect(); let cmd = cfg.create_command_for_toolchain(toolchain, m.is_present("install"), args[0])?; - let ExitCode(c) = command::run_command_for_dir(cmd, args[0], &args[1..], &cfg)?; + let ExitCode(c) = command::run_command_for_dir(cmd, args[0], &args[1..])?; process::exit(c) } @@ -1030,18 +1012,6 @@ fn self_uninstall(m: &ArgMatches) -> Result<()> { self_update::uninstall(no_prompt) } -fn set_telemetry(cfg: &Cfg, t: TelemetryMode) -> Result<()> { - match t { - TelemetryMode::On => Ok(cfg.set_telemetry(true)?), - TelemetryMode::Off => Ok(cfg.set_telemetry(false)?), - } -} - -fn analyze_telemetry(cfg: &Cfg) -> Result<()> { - let analysis = cfg.analyze_telemetry()?; - common::show_telemetry(analysis) -} - fn set_default_host_triple(cfg: &Cfg, m: &ArgMatches) -> Result<()> { cfg.set_default_host_triple(m.value_of("host_triple").expect(""))?; Ok(()) diff --git a/src/rustup-mock/Cargo.toml b/src/rustup-mock/Cargo.toml index 1db7432ed7a..adaf4b4f3c4 100644 --- a/src/rustup-mock/Cargo.toml +++ b/src/rustup-mock/Cargo.toml @@ -20,7 +20,6 @@ tempdir = "0.3.4" tar = "0.4.0" toml = "0.4" sha2 = "0.7.0" -wait-timeout = "0.1.3" [target."cfg(windows)".dependencies] winapi = "0.3" diff --git a/src/rustup-mock/src/clitools.rs b/src/rustup-mock/src/clitools.rs index 78151effa01..1da283f245c 100644 --- a/src/rustup-mock/src/clitools.rs +++ b/src/rustup-mock/src/clitools.rs @@ -15,12 +15,10 @@ use std::fs::{self, File}; use std::io::{self, Read, Write}; use std::mem; use std::path::{Path, PathBuf}; -use std::process::{Command, Stdio}; +use std::process::Command; use std::sync::Arc; -use std::time::Duration; use tempdir::TempDir; use url::Url; -use wait_timeout::ChildExt; /// The configuration used by the tests in this module pub struct Config { @@ -252,25 +250,6 @@ pub fn expect_ok_contains(config: &Config, args: &[&str], stdout: &str, stderr: } } -pub fn expect_timeout_ok(config: &Config, timeout: Duration, args: &[&str]) { - let mut child = cmd(config, args[0], &args[1..]) - .stdout(Stdio::null()) - .stderr(Stdio::null()) - .spawn() - .unwrap(); - - match child.wait_timeout(timeout).unwrap() { - Some(status) => { - assert!(status.success(), "not ok {:?}", args); - } - None => { - // child hasn't exited yet - child.kill().unwrap(); - panic!("command timed out: {:?}", args); - } - } -} - fn print_command(args: &[&str], out: &SanitizedOutput) { print!("\n>"); for arg in args { diff --git a/src/rustup-mock/src/lib.rs b/src/rustup-mock/src/lib.rs index 00f6ff59a81..591eed7733b 100644 --- a/src/rustup-mock/src/lib.rs +++ b/src/rustup-mock/src/lib.rs @@ -8,7 +8,6 @@ extern crate tar; extern crate tempdir; extern crate toml; extern crate url; -extern crate wait_timeout; extern crate walkdir; extern crate xz2; diff --git a/src/rustup-utils/src/toml_utils.rs b/src/rustup-utils/src/toml_utils.rs index 4b6f4ffa846..55be9b7cb1c 100644 --- a/src/rustup-utils/src/toml_utils.rs +++ b/src/rustup-utils/src/toml_utils.rs @@ -43,18 +43,6 @@ pub fn get_bool(table: &mut toml::value::Table, key: &str, path: &str) -> Result }) } -pub fn get_opt_bool(table: &mut toml::value::Table, key: &str, path: &str) -> Result> { - if let Ok(v) = get_value(table, key, path) { - if let toml::Value::Boolean(b) = v { - Ok(Some(b)) - } else { - Err(ErrorKind::ExpectedType("bool", path.to_owned() + key).into()) - } - } else { - Ok(None) - } -} - pub fn get_table( table: &mut toml::value::Table, key: &str, diff --git a/src/rustup/command.rs b/src/rustup/command.rs index 71fbe5c9da1..51f1dbe772f 100644 --- a/src/rustup/command.rs +++ b/src/rustup/command.rs @@ -1,155 +1,11 @@ -use regex::Regex; use std::ffi::OsStr; -use std::fs::File; -use std::io::{self, BufRead, BufReader, Seek, SeekFrom, Write}; -use std::process::{self, Command, Stdio}; -use std::time::Instant; -use tempfile::tempfile; +use std::io; +use std::process::{self, Command}; use crate::errors::*; -use crate::notifications::*; -use crate::telemetry::{Telemetry, TelemetryEvent}; -use crate::Cfg; use rustup_utils::{self, utils::ExitCode}; pub fn run_command_for_dir>( - cmd: Command, - arg0: &str, - args: &[S], - cfg: &Cfg, -) -> Result { - if (arg0 == "rustc" || arg0 == "rustc.exe") && cfg.telemetry_enabled()? { - return telemetry_rustc(cmd, arg0, args, cfg); - } - - exec_command_for_dir_without_telemetry(cmd, arg0, args) -} - -fn telemetry_rustc>( - mut cmd: Command, - arg0: &str, - args: &[S], - cfg: &Cfg, -) -> Result { - #[cfg(unix)] - fn file_as_stdio(file: &File) -> Stdio { - use std::os::unix::io::{AsRawFd, FromRawFd}; - unsafe { Stdio::from_raw_fd(file.as_raw_fd()) } - } - - #[cfg(windows)] - fn file_as_stdio(file: &File) -> Stdio { - use std::os::windows::io::{AsRawHandle, FromRawHandle}; - unsafe { Stdio::from_raw_handle(file.as_raw_handle()) } - } - - let now = Instant::now(); - - cmd.args(args); - - let has_color_args = args.iter().any(|e| { - let e = e.as_ref().to_str().unwrap_or(""); - e.starts_with("--color") - }); - - if stderr_isatty() && !has_color_args { - cmd.arg("--color"); - cmd.arg("always"); - } - - let mut cmd_err_file = tempfile().unwrap(); - let cmd_err_stdio = file_as_stdio(&cmd_err_file); - - // FIXME rust-lang/rust#32254. It's not clear to me - // when and why this is needed. - let mut cmd = cmd - .stdin(Stdio::inherit()) - .stdout(Stdio::inherit()) - .stderr(cmd_err_stdio) - .spawn() - .unwrap(); - - let status = cmd.wait(); - - let duration = now.elapsed(); - - let ms = (duration.as_secs() as u64 * 1000) + (duration.subsec_nanos() as u64 / 1000 / 1000); - - let t = Telemetry::new(cfg.rustup_dir.join("telemetry")); - - match status { - Ok(status) => { - let exit_code = status.code().unwrap_or(1); - - let re = Regex::new(r"\[(?PE.{4})\]").unwrap(); - - let mut buffer = String::new(); - // Chose a HashSet instead of a Vec to avoid calls to sort() and dedup(). - // The HashSet should be faster if there are a lot of errors, too. - let mut errors: Vec = Vec::new(); - - let stderr = io::stderr(); - let mut handle = stderr.lock(); - - cmd_err_file.seek(SeekFrom::Start(0)).unwrap(); - - let mut buffered_stderr = BufReader::new(cmd_err_file); - - while buffered_stderr.read_line(&mut buffer).unwrap() > 0 { - let b = buffer.to_owned(); - buffer.clear(); - let _ = handle.write(b.as_bytes()); - - if let Some(caps) = re.captures(&b) { - if caps.len() > 0 { - errors.push( - caps.name("error") - .map(|m| m.as_str()) - .unwrap_or("") - .to_owned(), - ); - } - }; - } - - let e = if errors.is_empty() { - None - } else { - Some(errors) - }; - - let te = TelemetryEvent::RustcRun { - duration_ms: ms, - exit_code: exit_code, - errors: e, - }; - - let _ = t.log_telemetry(te).map_err(|xe| { - (cfg.notify_handler)(Notification::TelemetryCleanupError(&xe)); - }); - - Ok(ExitCode(exit_code)) - } - Err(e) => { - let exit_code = e.raw_os_error().unwrap_or(1); - let te = TelemetryEvent::RustcRun { - duration_ms: ms, - exit_code: exit_code, - errors: None, - }; - - let _ = t.log_telemetry(te).map_err(|xe| { - (cfg.notify_handler)(Notification::TelemetryCleanupError(&xe)); - }); - - Err(e).chain_err(|| rustup_utils::ErrorKind::RunningCommand { - name: OsStr::new(arg0).to_owned(), - }) - } - } -} - -fn exec_command_for_dir_without_telemetry>( mut cmd: Command, arg0: &str, args: &[S], @@ -176,26 +32,3 @@ fn exec_command_for_dir_without_telemetry>( Ok(ExitCode(status.code().unwrap())) } } - -#[cfg(unix)] -fn stderr_isatty() -> bool { - use libc; - unsafe { libc::isatty(libc::STDERR_FILENO) != 0 } -} - -#[cfg(windows)] -fn stderr_isatty() -> bool { - type DWORD = u32; - type BOOL = i32; - type HANDLE = *mut u8; - const STD_ERROR_HANDLE: DWORD = -12i32 as DWORD; - extern "system" { - fn GetStdHandle(which: DWORD) -> HANDLE; - fn GetConsoleMode(hConsoleHandle: HANDLE, lpMode: *mut DWORD) -> BOOL; - } - unsafe { - let handle = GetStdHandle(STD_ERROR_HANDLE); - let mut out = 0; - GetConsoleMode(handle, &mut out) != 0 - } -} diff --git a/src/rustup/config.rs b/src/rustup/config.rs index 414a4881d7e..bfbaee3b1c0 100644 --- a/src/rustup/config.rs +++ b/src/rustup/config.rs @@ -8,8 +8,7 @@ use std::sync::Arc; use crate::errors::*; use crate::notifications::*; -use crate::settings::{Settings, SettingsFile, TelemetryMode, DEFAULT_METADATA_VERSION}; -use crate::telemetry_analysis::*; +use crate::settings::{Settings, SettingsFile, DEFAULT_METADATA_VERSION}; use crate::toolchain::{Toolchain, UpdateStatus}; use rustup_dist::{dist, temp}; use rustup_utils::utils; @@ -508,52 +507,4 @@ impl Cfg { Ok(name.to_owned()) } } - - pub fn set_telemetry(&self, telemetry_enabled: bool) -> Result<()> { - if telemetry_enabled { - self.enable_telemetry() - } else { - self.disable_telemetry() - } - } - - fn enable_telemetry(&self) -> Result<()> { - self.settings_file.with_mut(|s| { - s.telemetry = TelemetryMode::On; - Ok(()) - })?; - - let _ = utils::ensure_dir_exists("telemetry", &self.rustup_dir.join("telemetry"), &|_| ()); - - (self.notify_handler)(Notification::SetTelemetry("on")); - - Ok(()) - } - - fn disable_telemetry(&self) -> Result<()> { - self.settings_file.with_mut(|s| { - s.telemetry = TelemetryMode::Off; - Ok(()) - })?; - - (self.notify_handler)(Notification::SetTelemetry("off")); - - Ok(()) - } - - pub fn telemetry_enabled(&self) -> Result { - Ok(match self.settings_file.with(|s| Ok(s.telemetry))? { - TelemetryMode::On => true, - TelemetryMode::Off => false, - }) - } - - pub fn analyze_telemetry(&self) -> Result { - let mut t = TelemetryAnalysis::new(self.rustup_dir.join("telemetry")); - - let events = t.import_telemery()?; - t.analyze_telemetry_events(&events)?; - - Ok(t) - } } diff --git a/src/rustup/errors.rs b/src/rustup/errors.rs index 48e569c9671..cfd47dafb41 100644 --- a/src/rustup/errors.rs +++ b/src/rustup/errors.rs @@ -64,12 +64,6 @@ error_chain! { NoExeName { description("couldn't determine self executable name") } - TelemetryCleanupError { - description("unable to remove old telemetry files") - } - TelemetryAnalysisError { - description("error analyzing telemetry files") - } } } diff --git a/src/rustup/lib.rs b/src/rustup/lib.rs index e3891d17a3a..d4881453093 100644 --- a/src/rustup/lib.rs +++ b/src/rustup/lib.rs @@ -8,11 +8,6 @@ extern crate libc; extern crate regex; extern crate rustup_dist; extern crate rustup_utils; -#[macro_use] -extern crate serde_derive; -extern crate serde_json; -extern crate tempfile; -extern crate time; extern crate toml; extern crate url; @@ -68,6 +63,4 @@ mod errors; mod install; mod notifications; pub mod settings; -pub mod telemetry; -pub mod telemetry_analysis; mod toolchain; diff --git a/src/rustup/notifications.rs b/src/rustup/notifications.rs index 7812ca7d3ee..60563e15574 100644 --- a/src/rustup/notifications.rs +++ b/src/rustup/notifications.rs @@ -32,9 +32,6 @@ pub enum Notification<'a> { NonFatalError(&'a Error), UpgradeRemovesToolchains, MissingFileDuringSelfUninstall(PathBuf), - SetTelemetry(&'a str), - - TelemetryCleanupError(&'a Error), } impl<'a> From> for Notification<'a> { @@ -67,8 +64,7 @@ impl<'a> Notification<'a> { | UpdatingToolchain(_) | ReadMetadataVersion(_) | InstalledToolchain(_) - | UpdateHashMatches - | TelemetryCleanupError(_) => NotificationLevel::Verbose, + | UpdateHashMatches => NotificationLevel::Verbose, SetDefaultToolchain(_) | SetOverrideToolchain(_, _) | UsingExistingToolchain(_) @@ -76,8 +72,7 @@ impl<'a> Notification<'a> { | UninstalledToolchain(_) | ToolchainNotInstalled(_) | UpgradingMetadata(_, _) - | MetadataUpgradeNotNeeded(_) - | SetTelemetry(_) => NotificationLevel::Info, + | MetadataUpgradeNotNeeded(_) => NotificationLevel::Info, NonFatalError(_) => NotificationLevel::Error, UpgradeRemovesToolchains | MissingFileDuringSelfUninstall(_) => NotificationLevel::Warn, } @@ -130,8 +125,6 @@ impl<'a> Display for Notification<'a> { "expected file does not exist to uninstall: {}", p.display() ), - SetTelemetry(telemetry_status) => write!(f, "telemetry set to '{}'", telemetry_status), - TelemetryCleanupError(e) => write!(f, "unable to remove old telemetry files: '{}'", e), } } } diff --git a/src/rustup/settings.rs b/src/rustup/settings.rs index f88862347c5..5952bdc3d3f 100644 --- a/src/rustup/settings.rs +++ b/src/rustup/settings.rs @@ -77,7 +77,6 @@ impl SettingsFile { let override_db = multirust_dir.join("overrides"); let default_file = multirust_dir.join("default"); - let telemetry_file = multirust_dir.join("telemetry-on"); // Legacy upgrade self.with_mut(|s| { s.version = utils::read_file("version", &legacy_version_file)? @@ -99,9 +98,6 @@ impl SettingsFile { } } } - if utils::is_file(&telemetry_file) { - s.telemetry = TelemetryMode::On; - } Ok(()) })?; @@ -109,25 +105,17 @@ impl SettingsFile { let _ = utils::remove_file("version", &legacy_version_file); let _ = utils::remove_file("default", &default_file); let _ = utils::remove_file("overrides", &override_db); - let _ = utils::remove_file("telemetry", &telemetry_file); } Ok(()) } } -#[derive(Copy, Clone, Debug, PartialEq)] -pub enum TelemetryMode { - On, - Off, -} - #[derive(Clone, Debug, PartialEq)] pub struct Settings { pub version: String, pub default_host_triple: Option, pub default_toolchain: Option, pub overrides: BTreeMap, - pub telemetry: TelemetryMode, } impl Default for Settings { @@ -137,7 +125,6 @@ impl Default for Settings { default_host_triple: None, default_toolchain: None, overrides: BTreeMap::new(), - telemetry: TelemetryMode::Off, } } } @@ -192,11 +179,6 @@ impl Settings { default_host_triple: get_opt_string(&mut table, "default_host_triple", path)?, default_toolchain: get_opt_string(&mut table, "default_toolchain", path)?, overrides: Self::table_to_overrides(&mut table, path)?, - telemetry: if get_opt_bool(&mut table, "telemetry", path)?.unwrap_or(false) { - TelemetryMode::On - } else { - TelemetryMode::Off - }, }) } pub fn to_toml(self) -> toml::value::Table { @@ -215,9 +197,6 @@ impl Settings { let overrides = Self::overrides_to_table(self.overrides); result.insert("overrides".to_owned(), toml::Value::Table(overrides)); - let telemetry = self.telemetry == TelemetryMode::On; - result.insert("telemetry".to_owned(), toml::Value::Boolean(telemetry)); - result } diff --git a/src/rustup/telemetry.rs b/src/rustup/telemetry.rs deleted file mode 100644 index 6536d660bce..00000000000 --- a/src/rustup/telemetry.rs +++ /dev/null @@ -1,115 +0,0 @@ -use crate::errors::*; -use rustup_utils::{raw, utils}; -use serde_json; -use time; - -use std::fs; -use std::path::PathBuf; - -#[derive(Deserialize, Serialize, Debug, Clone)] -pub enum TelemetryEvent { - RustcRun { - duration_ms: u64, - exit_code: i32, - errors: Option>, - }, - ToolchainUpdate { - toolchain: String, - success: bool, - }, - TargetAdd { - toolchain: String, - target: String, - success: bool, - }, -} - -#[derive(Deserialize, Serialize, Debug)] -pub struct LogMessage { - log_time_s: i64, - event: TelemetryEvent, - version: i32, -} - -impl LogMessage { - pub fn get_event(&self) -> TelemetryEvent { - self.event.clone() - } -} - -#[derive(Debug)] -pub struct Telemetry { - telemetry_dir: PathBuf, -} - -const LOG_FILE_VERSION: i32 = 1; -const MAX_TELEMETRY_FILES: usize = 100; - -impl Telemetry { - pub fn new(telemetry_dir: PathBuf) -> Telemetry { - Telemetry { - telemetry_dir: telemetry_dir, - } - } - - pub fn log_telemetry(&self, event: TelemetryEvent) -> Result<()> { - let current_time = time::now_utc(); - let ln = LogMessage { - log_time_s: current_time.to_timespec().sec, - event: event, - version: LOG_FILE_VERSION, - }; - - let json = serde_json::to_string(&ln).unwrap(); - - let filename = format!( - "log-{}-{:02}-{:02}.json", - current_time.tm_year + 1900, - current_time.tm_mon + 1, - current_time.tm_mday - ); - - // Check for the telemetry file. If it doesn't exist, it's a new day. - // If it is a new day, then attempt to clean the telemetry directory. - if !raw::is_file(&self.telemetry_dir.join(&filename)) { - self.clean_telemetry_dir()?; - } - - let _ = utils::append_file("telemetry", &self.telemetry_dir.join(&filename), &json); - - Ok(()) - } - - pub fn clean_telemetry_dir(&self) -> Result<()> { - let telemetry_dir_contents = self.telemetry_dir.read_dir(); - - let contents = telemetry_dir_contents.chain_err(|| ErrorKind::TelemetryCleanupError)?; - - let mut telemetry_files: Vec = Vec::new(); - - for c in contents { - let x = c.unwrap(); - let filename = x.path().file_name().unwrap().to_str().unwrap().to_owned(); - if filename.starts_with("log") && filename.ends_with("json") { - telemetry_files.push(x.path()); - } - } - - if telemetry_files.len() < MAX_TELEMETRY_FILES { - return Ok(()); - } - - let dl: usize = telemetry_files.len() - MAX_TELEMETRY_FILES; - let dl = dl + 1 as usize; - - telemetry_files.sort(); - telemetry_files.dedup(); - - for i in 0..dl { - let i = i as usize; - fs::remove_file(&telemetry_files[i]).chain_err(|| ErrorKind::TelemetryCleanupError)?; - } - - Ok(()) - } -} diff --git a/src/rustup/telemetry_analysis.rs b/src/rustup/telemetry_analysis.rs deleted file mode 100644 index 2e985f42951..00000000000 --- a/src/rustup/telemetry_analysis.rs +++ /dev/null @@ -1,332 +0,0 @@ -use std::collections::HashMap; -use std::fmt; -use std::fs::File; -use std::io::BufRead; -use std::io::BufReader; -use std::path::PathBuf; - -use itertools::Itertools; -use serde_json; - -use crate::errors::*; -use crate::telemetry::{LogMessage, TelemetryEvent}; - -pub struct TelemetryAnalysis { - telemetry_dir: PathBuf, - rustc_statistics: RustcStatistics, - rustc_success_statistics: RustcStatistics, - rustc_error_statistics: RustcStatistics, -} - -#[derive(Default)] -pub struct RustcStatistics { - rustc_execution_count: u32, - compile_time_ms_total: u64, - compile_time_ms_mean: u64, - compile_time_ms_ntile_75: u64, - compile_time_ms_ntile_90: u64, - compile_time_ms_ntile_95: u64, - compile_time_ms_ntile_99: u64, - compile_time_ms_stdev: f64, - exit_codes_with_count: HashMap, - error_codes_with_counts: HashMap, -} - -impl RustcStatistics { - pub fn new() -> RustcStatistics { - Default::default() - } -} - -impl fmt::Display for RustcStatistics { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let mut errors: String = String::new(); - - if !self.error_codes_with_counts.is_empty() { - errors = " rustc errors\n".to_owned(); - for (error, count) in &self.error_codes_with_counts { - errors = errors + &format!(" '{}': {}\n", error, count); - } - } - - let mut exits: String = String::new(); - - if !self.exit_codes_with_count.is_empty() { - exits = " rustc exit codes\n".to_owned(); - - for (exit, count) in &self.exit_codes_with_count { - exits = exits + &format!(" {}: {}\n", exit, count); - } - } - - write!( - f, - r" - Total compiles: {} - Compile Time (ms) - Total : {} - Mean : {} - STDEV : {} - 75th : {} - 90th : {} - 95th : {} - 99th : {} - -{} - -{}", - self.rustc_execution_count, - self.compile_time_ms_total, - self.compile_time_ms_mean, - self.compile_time_ms_stdev, - self.compile_time_ms_ntile_75, - self.compile_time_ms_ntile_90, - self.compile_time_ms_ntile_95, - self.compile_time_ms_ntile_99, - errors, - exits - ) - } -} - -impl fmt::Display for TelemetryAnalysis { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!( - f, - r" -Overall rustc statistics: -{} - -rustc successful execution statistics -{} - -rustc error statistics -{}", - self.rustc_statistics, self.rustc_success_statistics, self.rustc_error_statistics - ) - } -} - -impl TelemetryAnalysis { - pub fn new(telemetry_dir: PathBuf) -> TelemetryAnalysis { - TelemetryAnalysis { - telemetry_dir: telemetry_dir, - rustc_statistics: RustcStatistics::new(), - rustc_success_statistics: RustcStatistics::new(), - rustc_error_statistics: RustcStatistics::new(), - } - } - - pub fn import_telemery(&mut self) -> Result> { - let mut events: Vec = Vec::new(); - let contents = self - .telemetry_dir - .read_dir() - .chain_err(|| ErrorKind::TelemetryAnalysisError)?; - - let mut telemetry_files: Vec = Vec::new(); - - for c in contents { - let x = c.unwrap(); - let filename = x.path().file_name().unwrap().to_str().unwrap().to_owned(); - - if filename.starts_with("log") && filename.ends_with("json") { - telemetry_files.push(x.path()); - match self.read_telemetry_file(x.path()) { - Ok(y) => events.extend(y), - Err(e) => return Err(e), - }; - } - } - - Ok(events) - } - - fn read_telemetry_file(&self, path: PathBuf) -> Result> { - let mut events: Vec = Vec::new(); - - let f = File::open(&path).chain_err(|| ErrorKind::TelemetryAnalysisError)?; - - let file = BufReader::new(&f); - - for line in file.lines() { - let l = line.unwrap(); - let log_message_result = serde_json::from_str(&l); - - if log_message_result.is_ok() { - let log_message: LogMessage = log_message_result.unwrap(); - let event: TelemetryEvent = log_message.get_event(); - events.push(event); - } - } - - Ok(events) - } - - pub fn analyze_telemetry_events(&mut self, events: &[TelemetryEvent]) -> Result<()> { - let mut rustc_durations = Vec::new(); - let mut rustc_exit_codes = Vec::new(); - - let mut rustc_successful_durations = Vec::new(); - - let mut rustc_error_durations = Vec::new(); - let mut error_list: Vec> = Vec::new(); - let mut error_codes_with_counts: HashMap = HashMap::new(); - - let mut toolchains = Vec::new(); - let mut toolchains_with_errors = Vec::new(); - let mut targets = Vec::new(); - - let mut updated_toolchains = Vec::new(); - let mut updated_toolchains_with_errors = Vec::new(); - - for event in events { - match *event { - TelemetryEvent::RustcRun { - duration_ms, - ref exit_code, - ref errors, - } => { - self.rustc_statistics.rustc_execution_count += 1; - rustc_durations.push(duration_ms); - - let exit_count = self - .rustc_statistics - .exit_codes_with_count - .entry(*exit_code) - .or_insert(0); - *exit_count += 1; - - rustc_exit_codes.push(exit_code); - - if errors.is_some() { - let errors = errors.clone().unwrap(); - - for e in &errors { - let error_count = - error_codes_with_counts.entry(e.to_owned()).or_insert(0); - *error_count += 1; - } - - error_list.push(errors); - rustc_error_durations.push(duration_ms); - } else { - rustc_successful_durations.push(duration_ms); - } - } - TelemetryEvent::TargetAdd { - ref toolchain, - ref target, - success, - } => { - toolchains.push(toolchain.to_owned()); - targets.push(target.to_owned()); - if !success { - toolchains_with_errors.push(toolchain.to_owned()); - } - } - TelemetryEvent::ToolchainUpdate { - ref toolchain, - success, - } => { - updated_toolchains.push(toolchain.to_owned()); - if !success { - updated_toolchains_with_errors.push(toolchain.to_owned()); - } - } - } - } - - self.rustc_statistics = compute_rustc_percentiles(&rustc_durations); - self.rustc_error_statistics = compute_rustc_percentiles(&rustc_error_durations); - self.rustc_error_statistics.error_codes_with_counts = error_codes_with_counts; - self.rustc_success_statistics = compute_rustc_percentiles(&rustc_successful_durations); - - let error_list = Itertools::flatten(error_list.into_iter()); - - for e in error_list { - let error_count = self - .rustc_statistics - .error_codes_with_counts - .entry(e) - .or_insert(0); - *error_count += 1; - } - - Ok(()) - } -} - -pub fn compute_rustc_percentiles(values: &[u64]) -> RustcStatistics { - RustcStatistics { - rustc_execution_count: (values.len() as u32), - compile_time_ms_total: values.iter().fold(0, |sum, val| sum + val), - compile_time_ms_mean: mean(values), - compile_time_ms_ntile_75: ntile(75, values), - compile_time_ms_ntile_90: ntile(90, values), - compile_time_ms_ntile_95: ntile(95, values), - compile_time_ms_ntile_99: ntile(99, values), - compile_time_ms_stdev: stdev(values), - exit_codes_with_count: HashMap::new(), - error_codes_with_counts: HashMap::new(), - } -} - -pub fn ntile(percentile: i32, values: &[u64]) -> u64 { - if values.is_empty() { - return 0u64; - } - - let mut values = values.to_owned(); - values.sort(); - - let count = values.len() as f32; - let percentile = (percentile as f32) / 100f32; - - let n = (count * percentile).ceil() - 1f32; - let n = n as usize; - - values[n] -} - -pub fn mean(values: &[u64]) -> u64 { - if values.is_empty() { - return 0; - } - - let count = values.len() as f64; - - let sum = values.iter().fold(0, |sum, val| sum + val) as f64; - - (sum / count) as u64 -} - -pub fn variance(values: &[u64]) -> f64 { - if values.is_empty() { - return 0f64; - } - - let mean = mean(values); - - let mut deviations: Vec = Vec::new(); - - for v in values.iter() { - let x = (*v as i64) - (mean as i64); - - deviations.push(x * x); - } - - let sum = deviations.iter().fold(0, |sum, val| sum + val) as f64; - - sum / (values.len() as f64) -} - -pub fn stdev(values: &[u64]) -> f64 { - if values.is_empty() { - return 0f64; - } - - let variance = variance(values); - - variance.sqrt() -} diff --git a/src/rustup/toolchain.rs b/src/rustup/toolchain.rs index 3cb1e5610f4..78d26a7adc7 100644 --- a/src/rustup/toolchain.rs +++ b/src/rustup/toolchain.rs @@ -3,8 +3,6 @@ use crate::env_var; use crate::errors::*; use crate::install::{self, InstallMethod}; use crate::notifications::*; -use crate::telemetry; -use crate::telemetry::{Telemetry, TelemetryEvent}; use rustup_dist; use rustup_dist::dist::ToolchainDesc; use rustup_dist::download::DownloadCfg; @@ -27,7 +25,6 @@ pub struct Toolchain<'a> { cfg: &'a Cfg, name: String, path: PathBuf, - telemetry: telemetry::Telemetry, dist_handler: Box, } @@ -54,7 +51,6 @@ impl<'a> Toolchain<'a> { cfg: cfg, name: resolved_name, path: path.clone(), - telemetry: Telemetry::new(cfg.rustup_dir.join("telemetry")), dist_handler: Box::new(move |n| (cfg.notify_handler)(n.into())), }) } @@ -165,13 +161,6 @@ impl<'a> Toolchain<'a> { } pub fn install_from_dist(&self, force_update: bool) -> Result { - if self.cfg.telemetry_enabled()? { - return self.install_from_dist_with_telemetry(force_update); - } - self.install_from_dist_inner(force_update) - } - - pub fn install_from_dist_inner(&self, force_update: bool) -> Result { let update_hash = self.update_hash()?; self.install(InstallMethod::Dist( &self.desc()?, @@ -181,36 +170,6 @@ impl<'a> Toolchain<'a> { )) } - pub fn install_from_dist_with_telemetry(&self, force_update: bool) -> Result { - let result = self.install_from_dist_inner(force_update); - - match result { - Ok(us) => { - let te = TelemetryEvent::ToolchainUpdate { - toolchain: self.name().to_string(), - success: true, - }; - match self.telemetry.log_telemetry(te) { - Ok(_) => Ok(us), - Err(e) => { - (self.cfg.notify_handler)(Notification::TelemetryCleanupError(&e)); - Ok(us) - } - } - } - Err(e) => { - let te = TelemetryEvent::ToolchainUpdate { - toolchain: self.name().to_string(), - success: true, - }; - let _ = self.telemetry.log_telemetry(te).map_err(|xe| { - (self.cfg.notify_handler)(Notification::TelemetryCleanupError(&xe)); - }); - Err(e) - } - } - } - pub fn install_from_dist_if_not_installed(&self) -> Result { let update_hash = self.update_hash()?; self.install_if_not_installed(InstallMethod::Dist( @@ -572,50 +531,7 @@ impl<'a> Toolchain<'a> { } } - pub fn add_component(&self, component: Component) -> Result<()> { - if self.cfg.telemetry_enabled()? { - return self.telemetry_add_component(component); - } - self.add_component_without_telemetry(component) - } - - fn telemetry_add_component(&self, component: Component) -> Result<()> { - let output = self.bare_add_component(component); - - match output { - Ok(_) => { - let te = TelemetryEvent::ToolchainUpdate { - toolchain: self.name.to_owned(), - success: true, - }; - - match self.telemetry.log_telemetry(te) { - Ok(_) => Ok(()), - Err(e) => { - (self.cfg.notify_handler)(Notification::TelemetryCleanupError(&e)); - Ok(()) - } - } - } - Err(e) => { - let te = TelemetryEvent::ToolchainUpdate { - toolchain: self.name.to_owned(), - success: false, - }; - - let _ = self.telemetry.log_telemetry(te).map_err(|xe| { - (self.cfg.notify_handler)(Notification::TelemetryCleanupError(&xe)); - }); - Err(e) - } - } - } - - fn add_component_without_telemetry(&self, component: Component) -> Result<()> { - self.bare_add_component(component) - } - - fn bare_add_component(&self, mut component: Component) -> Result<()> { + pub fn add_component(&self, mut component: Component) -> Result<()> { if !self.exists() { return Err(ErrorKind::ToolchainNotInstalled(self.name.to_owned()).into()); } diff --git a/tests/cli-exact.rs b/tests/cli-exact.rs index c8b5e399f8a..f7f57a2b37f 100644 --- a/tests/cli-exact.rs +++ b/tests/cli-exact.rs @@ -391,30 +391,6 @@ info: installing component 'rust-std' for '{0}' }); } -#[test] -fn enable_telemetry() { - setup(&|config| { - expect_ok_ex( - config, - &["rustup", "telemetry", "enable"], - r"", - "info: telemetry set to 'on'\n", - ); - }); -} - -#[test] -fn disable_telemetry() { - setup(&|config| { - expect_ok_ex( - config, - &["rustup", "telemetry", "disable"], - r"", - "info: telemetry set to 'off'\n", - ); - }); -} - // issue #927 #[test] fn undefined_linked_toolchain() { diff --git a/tests/cli-misc.rs b/tests/cli-misc.rs index d51ee4ad8cb..bbe6df97096 100644 --- a/tests/cli-misc.rs +++ b/tests/cli-misc.rs @@ -5,21 +5,16 @@ extern crate rustup_dist; extern crate rustup_mock; extern crate rustup_utils; extern crate tempdir; -extern crate time; use rustup_dist::errors::TOOLSTATE_MSG; use rustup_mock::clitools::{ - self, expect_err, expect_ok, expect_ok_ex, expect_stderr_ok, expect_stdout_ok, - expect_timeout_ok, run, set_current_dist_date, this_host_triple, Config, Scenario, + self, expect_err, expect_ok, expect_ok_ex, expect_stderr_ok, expect_stdout_ok, run, + set_current_dist_date, this_host_triple, Config, Scenario, }; use rustup_utils::{raw, utils}; use std::env::consts::EXE_SUFFIX; -use std::ops::Add; -use std::ops::Sub; -use std::time::Duration as StdDuration; use tempdir::TempDir; -use time::Duration; macro_rules! for_host { ($s: expr) => { @@ -148,7 +143,6 @@ fn upgrade_toml_settings() { rustup_utils::raw::write_file(&config.rustupdir.join("default"), "beta").unwrap(); rustup_utils::raw::write_file(&config.rustupdir.join("overrides"), "a;nightly\nb;stable") .unwrap(); - rustup_utils::raw::write_file(&config.rustupdir.join("telemetry-on"), "").unwrap(); expect_err( config, &["rustup", "default", "nightly"], @@ -164,9 +158,6 @@ fn upgrade_toml_settings() { assert!(!rustup_utils::raw::is_file( &config.rustupdir.join("overrides") )); - assert!(!rustup_utils::raw::is_file( - &config.rustupdir.join("telemetry-on") - )); assert!(rustup_utils::raw::is_file( &config.rustupdir.join("settings.toml") )); @@ -177,7 +168,6 @@ fn upgrade_toml_settings() { assert!(content.contains("[overrides]")); assert!(content.contains("a = \"nightly")); assert!(content.contains("b = \"stable")); - assert!(content.contains("telemetry = true")); }); } @@ -467,76 +457,6 @@ fn proxies_pass_empty_args() { }); } -#[test] -fn enabling_telemetry_and_compiling_creates_log() { - setup(&|config| { - expect_ok(config, &["rustup", "default", "stable"]); - expect_ok(config, &["rustup", "telemetry", "enable"]); - expect_ok(config, &["rustc", "--version"]); - - let telemetry_dir = config.rustupdir.join("telemetry"); - let _ = utils::assert_is_directory(telemetry_dir.as_path()); - - let out = telemetry_dir.read_dir(); - assert!(out.is_ok()); - - let contents = out.unwrap(); - assert!(contents.count() > 0); - }); -} - -#[test] -fn telemetry_supports_huge_output() { - setup(&|config| { - expect_ok(config, &["rustup", "default", "stable"]); - expect_ok(config, &["rustup", "telemetry", "enable"]); - expect_timeout_ok( - config, - StdDuration::from_secs(5), - &["rustc", "--huge-output"], - ); - expect_stdout_ok( - config, - &["rustup", "telemetry", "analyze"], - "'E0428': 10000", - ) - }) -} - -#[test] -fn telemetry_cleanup_removes_old_files() { - setup(&|config| { - expect_ok(config, &["rustup", "default", "stable"]); - expect_ok(config, &["rustup", "telemetry", "enable"]); - - let telemetry_dir = config.rustupdir.join("telemetry"); - - let mut d = time::now_utc().sub(Duration::days(120)); - let one_day = time::Duration::days(1); - - for _ in 0..110 { - let file_name = format!( - "log-{}-{:02}-{:02}.json", - d.tm_year + 1900, - d.tm_mon + 1, - d.tm_mday - ); - let _ = raw::write_file(&telemetry_dir.join(&file_name), ""); - d = d.add(one_day); - } - - expect_ok(config, &["rustc", "--version"]); - - let out = telemetry_dir.read_dir(); - assert!(out.is_ok()); - - let contents = out.unwrap(); - let count = contents.count(); - - assert_eq!(count, 100); - }); -} - #[test] fn rls_exists_in_toolchain() { setup(&|config| {