diff --git a/.github/workflows/nym-connect-publish-macos.yml b/.github/workflows/nym-connect-publish-macos.yml index 21ec00ce1e..8fee0b23f9 100644 --- a/.github/workflows/nym-connect-publish-macos.yml +++ b/.github/workflows/nym-connect-publish-macos.yml @@ -78,6 +78,8 @@ jobs: APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }} TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }} TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }} + SENTRY_DSN_RUST: ${{ secrets.SENTRY_DSN_RUST }} + SENTRY_DSN_JS: ${{ secrets.SENTRY_DSN_JS }} run: yarn && yarn build - name: Upload Artifact diff --git a/.github/workflows/nym-connect-publish-ubuntu.yml b/.github/workflows/nym-connect-publish-ubuntu.yml index f71c277e0c..35120ed535 100644 --- a/.github/workflows/nym-connect-publish-ubuntu.yml +++ b/.github/workflows/nym-connect-publish-ubuntu.yml @@ -61,6 +61,8 @@ jobs: env: TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }} TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }} + SENTRY_DSN_RUST: ${{ secrets.SENTRY_DSN_RUST }} + SENTRY_DSN_JS: ${{ secrets.SENTRY_DSN_JS }} - name: Upload Artifact uses: actions/upload-artifact@v3 diff --git a/.github/workflows/nym-connect-publish-windows10.yml b/.github/workflows/nym-connect-publish-windows10.yml index 8c793d88d0..5658c1db40 100644 --- a/.github/workflows/nym-connect-publish-windows10.yml +++ b/.github/workflows/nym-connect-publish-windows10.yml @@ -79,6 +79,8 @@ jobs: WINDOWS_CERTIFICATE_PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }} TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }} TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }} + SENTRY_DSN_RUST: ${{ secrets.SENTRY_DSN_RUST }} + SENTRY_DSN_JS: ${{ secrets.SENTRY_DSN_JS }} run: yarn build - name: Upload Artifact diff --git a/nym-connect/desktop/Cargo.lock b/nym-connect/desktop/Cargo.lock index 18ef59a2d7..89bfdbc8f3 100644 --- a/nym-connect/desktop/Cargo.lock +++ b/nym-connect/desktop/Cargo.lock @@ -1414,9 +1414,9 @@ checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" [[package]] name = "dotenvy" -version = "0.15.6" +version = "0.15.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03d8c417d7a8cb362e0c37e5d815f5eb7c37f79ff93707329d5a194e42e54ca0" +checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" [[package]] name = "dtoa" @@ -3532,6 +3532,7 @@ dependencies = [ "anyhow", "bip39", "dirs 4.0.0", + "dotenvy", "eyre", "fern", "fix-path-env", diff --git a/nym-connect/desktop/src-tauri/Cargo.toml b/nym-connect/desktop/src-tauri/Cargo.toml index bc89fd17ec..edce6a2bb6 100644 --- a/nym-connect/desktop/src-tauri/Cargo.toml +++ b/nym-connect/desktop/src-tauri/Cargo.toml @@ -46,6 +46,7 @@ yaml-rust = "0.4" toml = "0.7" sentry = { version = "0.31.5", features = [ "anyhow" ] } sentry-log = "0.31.5" +dotenvy = "0.15.7" nym-client-core = { path = "../../../common/client-core" } nym-api-requests = { path = "../../../nym-api/nym-api-requests" } diff --git a/nym-connect/desktop/src-tauri/src/build.rs b/nym-connect/desktop/src-tauri/src/build.rs index 261851f6b6..7c65873b94 100644 --- a/nym-connect/desktop/src-tauri/src/build.rs +++ b/nym-connect/desktop/src-tauri/src/build.rs @@ -1,3 +1,16 @@ +use std::env; + +mod constants; + +use constants::{SENTRY_DSN_JS, SENTRY_DSN_RUST}; + fn main() { + // set these env vars at compile time + if let Ok(dsn) = env::var(SENTRY_DSN_RUST) { + println!("cargo:rustc-env={}={}", SENTRY_DSN_RUST, dsn); + } + if let Ok(dsn) = env::var(SENTRY_DSN_JS) { + println!("cargo:rustc-env={}={}", SENTRY_DSN_JS, dsn); + } tauri_build::build(); } diff --git a/nym-connect/desktop/src-tauri/src/constants.rs b/nym-connect/desktop/src-tauri/src/constants.rs new file mode 100644 index 0000000000..379fa02be8 --- /dev/null +++ b/nym-connect/desktop/src-tauri/src/constants.rs @@ -0,0 +1,3 @@ +// env var keys +pub const SENTRY_DSN_RUST: &str = "SENTRY_DSN_RUST"; +pub const SENTRY_DSN_JS: &str = "SENTRY_DSN_JS"; diff --git a/nym-connect/desktop/src-tauri/src/main.rs b/nym-connect/desktop/src-tauri/src/main.rs index de486c05de..02981ee1ee 100644 --- a/nym-connect/desktop/src-tauri/src/main.rs +++ b/nym-connect/desktop/src-tauri/src/main.rs @@ -3,6 +3,7 @@ windows_subsystem = "windows" )] +use std::env; use std::sync::Arc; use nym_config::defaults::setup_env; @@ -15,21 +16,20 @@ use crate::state::State; use crate::window::window_toggle; mod config; +mod constants; mod error; mod events; mod logging; mod menu; mod models; +mod monitoring; mod operations; mod state; mod tasks; mod window; -// TODO DSN shouldn't be hardcoded -const SENTRY_DSN: &str = - "https://68a2c55113ed47aaa30b9899039b0799@o967446.ingest.sentry.io/4505483113594880"; - fn main() { + dotenvy::dotenv().ok(); setup_env(None); println!("Starting up..."); @@ -46,37 +46,21 @@ fn main() { }); let monitoring = user_data.monitoring.unwrap_or(false); - - let _guard = sentry::init(( - SENTRY_DSN, - sentry::ClientOptions { - release: sentry::release_name!(), - sample_rate: 1.0, // TODO lower this in prod - traces_sample_rate: 1.0, - ..Default::default() // TODO add data scrubbing - // see https://docs.sentry.io/platforms/rust/data-management/sensitive-data/ - }, - )); - - sentry::configure_scope(|scope| { - scope.set_user(Some(sentry::User { - id: Some("nym".into()), - ..Default::default() - })); - }); + let mut _sentry_guard; if monitoring { - println!("Sentry reporting and monitoring is enabled"); - } else { - println!("Monitoring is disabled, dropping sentry guard"); - drop(_guard) - } + match monitoring::init() { + Ok(guard) => { + println!("Monitoring and error reporting enabled"); - let user_data = UserData::read().unwrap_or_else(|e| { - println!("{}", e); - println!("Fallback to default"); - UserData::default() - }); + // we must keep the sentry guard in scope during app lifetime + _sentry_guard = guard; + } + Err(e) => { + println!("Unable to init monitoring: {e}"); + } + } + } let context = tauri::generate_context!(); tauri::Builder::default() diff --git a/nym-connect/desktop/src-tauri/src/monitoring.rs b/nym-connect/desktop/src-tauri/src/monitoring.rs new file mode 100644 index 0000000000..e4555f3277 --- /dev/null +++ b/nym-connect/desktop/src-tauri/src/monitoring.rs @@ -0,0 +1,38 @@ +use std::env; + +use anyhow::{Context, Result}; +use sentry::ClientInitGuard; + +use crate::constants::{SENTRY_DSN_JS, SENTRY_DSN_RUST}; + +pub fn init() -> Result { + // if these env vars were set at compile time, use their value + if let Some(v) = option_env!("SENTRY_DSN_RUST") { + env::set_var(SENTRY_DSN_RUST, v); + } + if let Some(v) = option_env!("SENTRY_DSN_JS") { + env::set_var(SENTRY_DSN_JS, v); + } + + let dsn = env::var(SENTRY_DSN_RUST).context(format!("{} env var not set", SENTRY_DSN_RUST))?; + println!("using DSN {dsn}"); + let guard = sentry::init(( + dsn, + sentry::ClientOptions { + release: sentry::release_name!(), + sample_rate: 1.0, // TODO lower this in prod + traces_sample_rate: 1.0, + ..Default::default() // TODO add data scrubbing + // see https://docs.sentry.io/platforms/rust/data-management/sensitive-data/ + }, + )); + + sentry::configure_scope(|scope| { + scope.set_user(Some(sentry::User { + id: Some("nym".into()), + ..Default::default() + })); + }); + + Ok(guard) +} diff --git a/nym-connect/desktop/src/sentry.ts b/nym-connect/desktop/src/sentry.ts index 13f7529c30..5127c5dc0c 100644 --- a/nym-connect/desktop/src/sentry.ts +++ b/nym-connect/desktop/src/sentry.ts @@ -1,17 +1,25 @@ import React from 'react'; import { createRoutesFromChildren, matchRoutes, useLocation, useNavigationType } from 'react-router-dom'; +import { invoke } from '@tauri-apps/api'; import * as Sentry from '@sentry/react'; import { CaptureConsole } from '@sentry/integrations'; import { getVersion } from '@tauri-apps/api/app'; -const SENTRY_DSN = 'https://625e2658da4945a7a253f3ee04413a31@o967446.ingest.sentry.io/4505306292289536'; +const SENTRY_DSN = 'SENTRY_DSN_JS'; async function initSentry() { console.log('⚠ performance monitoring and error reporting enabled'); console.log('initializing sentry'); + const dsn = await invoke('get_env', { variable: SENTRY_DSN }); + + if (!dsn) { + console.warn(`unable to initialize sentry, ${SENTRY_DSN} env var not set`); + return; + } + Sentry.init({ - dsn: SENTRY_DSN, + dsn, integrations: [ new Sentry.BrowserTracing({ // Set `tracePropagationTargets` to control for which URLs distributed tracing should be enabled