diff options
| author | Linus Färnstrand <linus@mullvad.net> | 2017-10-30 20:49:58 +0100 |
|---|---|---|
| committer | Linus Färnstrand <linus@mullvad.net> | 2017-10-30 20:49:58 +0100 |
| commit | bf69d784aeff81c1db0f2c6fc1b864ca30c91cc7 (patch) | |
| tree | 3265c88d6b32bf5810af7679960254019d5da89e | |
| parent | 3df28edf3258b3de877a14becac237e413978e02 (diff) | |
| parent | c13b1683ba0539a7a44b7c6198b8cced92114da3 (diff) | |
| download | mullvadvpn-bf69d784aeff81c1db0f2c6fc1b864ca30c91cc7.tar.xz mullvadvpn-bf69d784aeff81c1db0f2c6fc1b864ca30c91cc7.zip | |
Merge branch 'problem-report-sysinfo'
| -rwxr-xr-x | format.sh | 2 | ||||
| -rw-r--r-- | mullvad-daemon/build.rs | 6 | ||||
| -rw-r--r-- | mullvad-daemon/src/bin/problem-report.rs | 74 | ||||
| -rw-r--r-- | talpid-ipc/src/client.rs | 9 |
4 files changed, 77 insertions, 14 deletions
@@ -5,7 +5,7 @@ set -u -VERSION="0.2.9" +VERSION="0.2.13" CMD="rustfmt" INSTALL_CMD="cargo install --vers $VERSION --force rustfmt-nightly" diff --git a/mullvad-daemon/build.rs b/mullvad-daemon/build.rs index c810fe395a..b39c3fb9ab 100644 --- a/mullvad-daemon/build.rs +++ b/mullvad-daemon/build.rs @@ -27,15 +27,15 @@ fn main() { // Implementation borrowed from rustfmt. Returns a string containing commit hash and commit date // if it was able to obtain it, otherwise an empty string. fn commit_info() -> String { - match (commit_hash(), commit_date()) { + match (commit_description(), commit_date()) { (Some(hash), Some(date)) => format!("({} {})", hash.trim(), date), _ => String::new(), } } -fn commit_hash() -> Option<String> { +fn commit_description() -> Option<String> { Command::new("git") - .args(&["rev-parse", "--short", "HEAD"]) + .args(&["describe", "--dirty"]) .output() .ok() .and_then(|out| String::from_utf8(out.stdout).ok()) diff --git a/mullvad-daemon/src/bin/problem-report.rs b/mullvad-daemon/src/bin/problem-report.rs index 8ecae0a0e5..3d617b4bf6 100644 --- a/mullvad-daemon/src/bin/problem-report.rs +++ b/mullvad-daemon/src/bin/problem-report.rs @@ -19,6 +19,7 @@ use std::fmt; use std::fs::File; use std::io::{self, Read, Seek, SeekFrom, Write}; use std::path::{Path, PathBuf}; +use std::process::Command; /// Maximum number of bytes to read from each log file const LOG_MAX_READ_BYTES: usize = 5 * 1024 * 1024; @@ -48,10 +49,10 @@ error_chain!{ quick_main!(run); fn run() -> Result<()> { - let app = clap::App::new(crate_name!()) + let app = clap::App::new("problem-report") .version(crate_version!()) .author(crate_authors!()) - .about(crate_description!()) + .about("Mullvad VPN problem report tool. Collects logs and send them to Mullvad support.") .setting(clap::AppSettings::SubcommandRequired) .subcommand( clap::SubCommand::with_name("collect") @@ -121,7 +122,7 @@ fn run() -> Result<()> { } fn collect_report(log_paths: &[&Path], output_path: &Path) -> Result<()> { - let mut problem_report = ProblemReport::default(); + let mut problem_report = ProblemReport::new(); for log_path in log_paths { problem_report.add_log(log_path); } @@ -149,15 +150,31 @@ fn write_problem_report(path: &Path, problem_report: ProblemReport) -> io::Resul Ok(()) } -#[derive(Debug, Default)] + +#[derive(Debug)] struct ProblemReport { + system_info: Vec<String>, logs: Vec<(String, String)>, } impl ProblemReport { + pub fn new() -> Self { + ProblemReport { + system_info: Self::collect_system_info(), + logs: Vec::new(), + } + } + + fn collect_system_info() -> Vec<String> { + vec![ + format!("Mullvad daemon: {}", daemon_version()), + format!("OS: {}", os_version()), + ] + } + /// Attach file log to this report. This method uses the error chain instead of log /// contents if error occurred when reading log file. - fn add_log(&mut self, path: &Path) { + pub fn add_log(&mut self, path: &Path) { let content = read_file_lossy(path, LOG_MAX_READ_BYTES) .chain_err(|| ErrorKind::ReadLogError(path.to_path_buf())) .unwrap_or_else(|e| e.display_chain().to_string()); @@ -168,6 +185,11 @@ impl ProblemReport { impl fmt::Display for ProblemReport { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + writeln!(fmt, "System information:")?; + for system_info in &self.system_info { + writeln!(fmt, "{}", system_info)?; + } + writeln!(fmt, "")?; for &(ref label, ref content) in &self.logs { writeln!(fmt, "{}", LOG_DELIMITER)?; writeln!(fmt, "Log: {}", label)?; @@ -194,3 +216,45 @@ fn read_file_lossy(path: &Path, max_bytes: usize) -> io::Result<String> { file.take(max_bytes as u64).read_to_end(&mut buffer)?; Ok(String::from_utf8_lossy(&buffer).into_owned()) } + +fn daemon_version() -> String { + format!( + "v{} {}", + env!("CARGO_PKG_VERSION"), + include_str!(concat!(env!("OUT_DIR"), "/git-commit-info.txt")) + ) +} + +#[cfg(target_os = "linux")] +fn os_version() -> String { + format!( + "Linux, {}", + command_stdout_lossy("lsb_release", &["-ds"]) + .unwrap_or(String::from("[Failed to get LSB release]")) + ) +} + +#[cfg(target_os = "macos")] +fn os_version() -> String { + format!( + "macOS {}", + command_stdout_lossy("sw_vers", &["-productVersion"]) + .unwrap_or(String::from("[Failed to detect version]")) + ) +} + +#[cfg(windows)] +fn os_version() -> String { + String::from("Windows") +} + +/// Helper for getting stdout of some command as a String. Ignores the exit code of the command. +fn command_stdout_lossy(cmd: &str, args: &[&str]) -> Option<String> { + Command::new(cmd) + .args(args) + .output() + .map(|output| { + String::from_utf8_lossy(&output.stdout).trim().to_string() + }) + .ok() +} diff --git a/talpid-ipc/src/client.rs b/talpid-ipc/src/client.rs index f3765a52fe..8085e461a3 100644 --- a/talpid-ipc/src/client.rs +++ b/talpid-ipc/src/client.rs @@ -41,11 +41,10 @@ struct Handler<O: for<'de> serde::Deserialize<'de>> { impl<O: for<'de> serde::Deserialize<'de>> Handler<O> { fn parse_reply(&self, msg: ws::Message) -> Result<O> { - let json: serde_json::Value = - match msg { - ws::Message::Text(s) => serde_json::from_str(&s), - ws::Message::Binary(b) => serde_json::from_slice(&b), - }.chain_err(|| "Unable to deserialize ws message as JSON")?; + let json: serde_json::Value = match msg { + ws::Message::Text(s) => serde_json::from_str(&s), + ws::Message::Binary(b) => serde_json::from_slice(&b), + }.chain_err(|| "Unable to deserialize ws message as JSON")?; let result: Option<serde_json::Value> = match json { serde_json::Value::Object(mut map) => map.remove("result"), _ => None, |
