summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorLinus Färnstrand <linus@mullvad.net>2017-10-30 20:49:58 +0100
committerLinus Färnstrand <linus@mullvad.net>2017-10-30 20:49:58 +0100
commitbf69d784aeff81c1db0f2c6fc1b864ca30c91cc7 (patch)
tree3265c88d6b32bf5810af7679960254019d5da89e
parent3df28edf3258b3de877a14becac237e413978e02 (diff)
parentc13b1683ba0539a7a44b7c6198b8cced92114da3 (diff)
downloadmullvadvpn-bf69d784aeff81c1db0f2c6fc1b864ca30c91cc7.tar.xz
mullvadvpn-bf69d784aeff81c1db0f2c6fc1b864ca30c91cc7.zip
Merge branch 'problem-report-sysinfo'
-rwxr-xr-xformat.sh2
-rw-r--r--mullvad-daemon/build.rs6
-rw-r--r--mullvad-daemon/src/bin/problem-report.rs74
-rw-r--r--talpid-ipc/src/client.rs9
4 files changed, 77 insertions, 14 deletions
diff --git a/format.sh b/format.sh
index 004ab8fe8a..79ffc82f2e 100755
--- a/format.sh
+++ b/format.sh
@@ -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,