diff --git a/rust/Cargo.lock b/rust/Cargo.lock index fcfd29439..8e3609fd5 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -215,6 +215,9 @@ name = "anyhow" version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6" +dependencies = [ + "backtrace", +] [[package]] name = "approx" @@ -2443,6 +2446,7 @@ version = "0.1.0" dependencies = [ "arc-swap", "sentry", + "sentry-anyhow", "thiserror", "tracing", ] @@ -6538,6 +6542,17 @@ dependencies = [ "webpki-roots", ] +[[package]] +name = "sentry-anyhow" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d672bfd1ed4e90978435f3c0704edb71a7a9d86403657839d518cd6aa278aff5" +dependencies = [ + "anyhow", + "sentry-backtrace", + "sentry-core", +] + [[package]] name = "sentry-backtrace" version = "0.34.0" diff --git a/rust/gtk-client/Cargo.lock b/rust/gtk-client/Cargo.lock index 2ae3065ee..dfe4af1bc 100644 --- a/rust/gtk-client/Cargo.lock +++ b/rust/gtk-client/Cargo.lock @@ -150,6 +150,9 @@ name = "anyhow" version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6" +dependencies = [ + "backtrace", +] [[package]] name = "arbitrary" @@ -735,9 +738,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.18" +version = "4.5.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0956a43b323ac1afaffc053ed5c4b7c1f1800bacd1683c353aabbb752515dd3" +checksum = "7be5744db7978a28d9df86a214130d106a89ce49644cbc4e3f0c22c3fba30615" dependencies = [ "clap_builder", "clap_derive", @@ -745,9 +748,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.18" +version = "4.5.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d72166dd41634086d5803a47eb71ae740e61d84709c36f3c34110173db3961b" +checksum = "a5fbc17d3ef8278f55b282b2a2e75ae6f6c7d4bb70ed3d0382375104bfafdb4b" dependencies = [ "anstream", "anstyle", @@ -1347,6 +1350,7 @@ dependencies = [ "firezone-headless-client", "firezone-logging", "firezone-telemetry", + "gdk-pixbuf", "glib", "gtk", "notify-rust", @@ -1418,6 +1422,7 @@ dependencies = [ "ip-packet", "ip_network", "ipconfig", + "itertools 0.13.0", "known-folders", "libc", "nix 0.29.0", @@ -1462,6 +1467,7 @@ version = "0.1.0" dependencies = [ "arc-swap", "sentry", + "sentry-anyhow", "tracing", ] @@ -1491,6 +1497,7 @@ dependencies = [ "rangemap", "secrecy", "serde", + "serde_json", "snownet", "socket-factory", "socket2", @@ -3035,6 +3042,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae99c7fa6dd38c7cafe1ec085e804f8f555a2f8659b0dbe03f1f9963a9b51092" dependencies = [ "log", + "serde", "windows-sys 0.52.0", ] @@ -3744,6 +3752,7 @@ dependencies = [ "httpdate", "reqwest", "rustls 0.22.4", + "sentry-contexts", "sentry-core", "sentry-panic", "sentry-tracing", @@ -3752,6 +3761,17 @@ dependencies = [ "webpki-roots", ] +[[package]] +name = "sentry-anyhow" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d672bfd1ed4e90978435f3c0704edb71a7a9d86403657839d518cd6aa278aff5" +dependencies = [ + "anyhow", + "sentry-backtrace", + "sentry-core", +] + [[package]] name = "sentry-backtrace" version = "0.34.0" @@ -3764,6 +3784,20 @@ dependencies = [ "sentry-core", ] +[[package]] +name = "sentry-contexts" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a8dd746da3d16cb8c39751619cefd4fcdbd6df9610f3310fd646b55f6e39910" +dependencies = [ + "hostname", + "libc", + "os_info", + "rustc_version", + "sentry-core", + "uname", +] + [[package]] name = "sentry-core" version = "0.34.0" @@ -4608,6 +4642,15 @@ dependencies = [ "winapi", ] +[[package]] +name = "uname" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b72f89f0ca32e4db1c04e2a72f5345d59796d4866a1ee0609084569f73683dc8" +dependencies = [ + "libc", +] + [[package]] name = "unicode-bidi" version = "0.3.15" diff --git a/rust/gtk-client/Cargo.toml b/rust/gtk-client/Cargo.toml index 6d4a31bb8..089ce9f2f 100644 --- a/rust/gtk-client/Cargo.toml +++ b/rust/gtk-client/Cargo.toml @@ -15,6 +15,7 @@ firezone-gui-client-common = { path = "../gui-client/src-common" } firezone-headless-client = { path = "../headless-client" } firezone-logging = { path = "../logging" } firezone-telemetry = { path = "../telemetry" } +gdk-pixbuf = "0.18.5" glib = "0.18.5" gtk = "0.18.1" notify-rust = "4.11.3" diff --git a/rust/gtk-client/src/main.rs b/rust/gtk-client/src/main.rs index c88e28a0a..2d269d9f3 100644 --- a/rust/gtk-client/src/main.rs +++ b/rust/gtk-client/src/main.rs @@ -93,16 +93,10 @@ fn main() -> Result<()> { .build(); app.connect_activate(|app| { - // We create the main window. - let win = ApplicationWindow::builder() - .application(app) - .default_width(640) - .default_height(480) - .title("Firezone GTK+ 3") - .build(); - - // Don't forget to make all widgets visible. - win.show_all(); + if let Err(error) = build_ui(app) { + tracing::error!(?error, "`build_ui` failed"); + telemetry::capture_anyhow(&error); + } }); gtk::init()?; @@ -155,6 +149,31 @@ fn main() -> Result<()> { Ok(()) } +fn build_ui(app: >k::Application) -> Result<()> { + let icon_pixbuf = gdk_pixbuf::Pixbuf::from_file( + "/usr/share/icons/hicolor/128x128/apps/firezone-client-gui.png", + )?; + + let win = ApplicationWindow::builder() + .application(app) + .default_width(640) + .default_height(480) + .icon(&icon_pixbuf) + .title("About Firezone") + .build(); + win.show_all(); + + let win = ApplicationWindow::builder() + .application(app) + .default_width(640) + .default_height(480) + .icon(&icon_pixbuf) + .title("Settings") + .build(); + win.show_all(); + Ok(()) +} + // Worker task to accept deep links from a named pipe forever /// /// * `server` An initial named pipe server to consume before making new servers. This lets us also use the named pipe to enforce single-instance @@ -204,6 +223,7 @@ impl MainThreadLoop { fn handle_req(&mut self, req: MainThreadReq) -> Result<()> { match req { MainThreadReq::Quit => self.app.quit(), + MainThreadReq::SetTrayIcon(icon) => self.set_icon(icon)?, MainThreadReq::SetTrayMenu(app_state) => self.set_tray_menu(*app_state)?, } Ok(()) @@ -303,6 +323,7 @@ fn build_item(that: &common::system_tray::Item) -> tray_icon::menu::MenuItem { enum MainThreadReq { /// The controller exited, quit the GTK app and exit the loop Quit, + SetTrayIcon(common::system_tray::Icon), SetTrayMenu(Box), } @@ -353,8 +374,8 @@ impl GuiIntegration for GtkIntegration { Ok(()) } - fn set_tray_icon(&mut self, _icon: common::system_tray::Icon) -> Result<()> { - tracing::warn!("set_tray_icon not implemented"); + fn set_tray_icon(&mut self, icon: common::system_tray::Icon) -> Result<()> { + self.main_tx.try_send(MainThreadReq::SetTrayIcon(icon))?; Ok(()) } diff --git a/rust/telemetry/Cargo.toml b/rust/telemetry/Cargo.toml index b94e91943..f86fad2ae 100644 --- a/rust/telemetry/Cargo.toml +++ b/rust/telemetry/Cargo.toml @@ -6,6 +6,7 @@ edition = "2021" [dependencies] arc-swap = "1.7.1" sentry = { version = "0.34.0", default-features = false, features = ["contexts", "panic", "reqwest", "rustls", "tracing"] } +sentry-anyhow = "0.34.0" tracing = { workspace = true } [dev-dependencies] diff --git a/rust/telemetry/src/lib.rs b/rust/telemetry/src/lib.rs index c3c8e6d3d..e076f4dc7 100644 --- a/rust/telemetry/src/lib.rs +++ b/rust/telemetry/src/lib.rs @@ -6,6 +6,7 @@ pub use sentry::{ end_session_with_status, start_transaction, types::protocol::v7::SessionStatus, Breadcrumb, Hub, Level, TransactionContext, }; +pub use sentry_anyhow::capture_anyhow; pub struct Dsn(&'static str);