Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/desktop_cd.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,7 @@ jobs:
env:
APP_VERSION: ${{ needs.compute-version.outputs.version }}
ANARLOG_GPUI_SIDECAR: optional
SENTRY_DSN: ${{ secrets.SENTRY_DSN_HYPRNOTE_2 }}
- uses: ./.github/actions/apple_cert
id: apple-cert
with:
Expand Down Expand Up @@ -451,6 +452,7 @@ jobs:
env:
APP_VERSION: ${{ needs.compute-version.outputs.version }}
ANARLOG_GPUI_SIDECAR: "1"
SENTRY_DSN: ${{ secrets.SENTRY_DSN_HYPRNOTE_2 }}
TAURI_ENV_TARGET_TRIPLE: ${{ matrix.target }}
- run: |
BUILD_ARGS=(
Expand Down
20 changes: 16 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ anlg-claude = { path = "crates/claude", package = "claude" }
anlg-cli-process = { path = "crates/cli-process", package = "cli-process" }
anlg-cloudsync = { path = "crates/cloudsync", package = "cloudsync" }
anlg-codex = { path = "crates/codex", package = "codex" }
anlg-crash-reporting = { path = "crates/crash-reporting", package = "crash-reporting" }
anlg-data = { path = "crates/data", package = "data" }
anlg-db-app = { path = "crates/db-app", package = "db-app" }
anlg-db-change = { path = "crates/db-change", package = "db-change" }
Expand Down
1 change: 1 addition & 0 deletions apps/desktop-gpui/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ anlg-agent-access = { workspace = true }
anlg-audio = { workspace = true }
anlg-audio-actual = { workspace = true }
anlg-audio-mock = { workspace = true }
anlg-crash-reporting = { workspace = true }
anlg-db-app = { workspace = true }
anlg-db-core = { workspace = true }
anlg-deeplink-core = { workspace = true }
Expand Down
27 changes: 24 additions & 3 deletions apps/desktop-gpui/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ pub const APP_VERSION: &str = match option_env!("APP_VERSION") {
use std::path::PathBuf;
use std::sync::Arc;

use anlg_crash_reporting::{Options as CrashReportingOptions, consent::CONSENT_QUERY};
use anyhow::Context as _;
use gpui::{
App, AppContext as _, Application, Bounds, TitlebarOptions, WindowBounds, WindowDecorations,
Expand All @@ -94,6 +95,7 @@ use gpui::{

use crate::db::Store;
use crate::workspace::Workspace;
use tracing_subscriber::prelude::*;

/// The main window the tray menu acts on.
struct MainWindow {
Expand Down Expand Up @@ -367,13 +369,16 @@ fn parse_args() -> anyhow::Result<Args> {
}

fn main() -> anyhow::Result<()> {
tracing_subscriber::fmt()
.with_env_filter(
tracing_subscriber::registry()
.with(
tracing_subscriber::EnvFilter::try_from_default_env()
.unwrap_or_else(|_| tracing_subscriber::EnvFilter::new("info")),
)
.with(anlg_crash_reporting::tracing_layer())
.with(tracing_subscriber::fmt::layer().with_writer(|| {
anlg_crash_reporting::redaction::RedactingWriter::new(std::io::stderr())
}))
.init();

let args = parse_args()?;
let db_path = match args.db_path {
Some(path) => path,
Expand Down Expand Up @@ -415,6 +420,22 @@ fn main() -> anyhow::Result<()> {
db_path,
args.identifier.clone(),
))?;
let crash_reporting_enabled = runtime.block_on(async {
let rows = sqlx::query_as::<_, (String, String)>(CONSENT_QUERY)
.fetch_all(store.pool())
.await
.unwrap_or_default();
anlg_crash_reporting::consent::from_rows(&rows)
});
let _sentry = anlg_crash_reporting::init(
CrashReportingOptions {
dsn: option_env!("SENTRY_DSN"),
Comment thread
devin-ai-integration[bot] marked this conversation as resolved.
release: Some(format!("anarlog-desktop-gpui@{APP_VERSION}")),
release_channel: option_env!("RELEASE_CHANNEL").unwrap_or("dev"),
service_name: "desktop-gpui",
},
crash_reporting_enabled,
);
let audio = audio::provider(&args.identifier);
let store = Arc::new(store);
let search = search::SearchIndex::start(&store);
Expand Down
3 changes: 3 additions & 0 deletions apps/desktop-gpui/src/workspace/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -724,6 +724,9 @@ impl Workspace {
value: bool,
cx: &mut Context<Self>,
) {
if key == "crash_reporting_consent" {
anlg_crash_reporting::set_enabled(value);
}
self.set_setting(key, serde_json::Value::Bool(value), cx);
}

Expand Down
2 changes: 1 addition & 1 deletion apps/desktop/src-tauri/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ crate-type = ["staticlib", "rlib"]
tauri-build = { workspace = true, features = [] }

[dependencies]
anlg-crash-reporting = { workspace = true }
tauri = { workspace = true, features = ["specta", "protocol-asset"] }

tauri-plugin-agent = { workspace = true }
Expand Down Expand Up @@ -101,7 +102,6 @@ chrono = { workspace = true }
dirs = { workspace = true }
pico-args = { workspace = true }
ractor = { workspace = true }
sentry = { workspace = true, features = ["tracing"] }
serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true }
specta = { workspace = true }
Expand Down
92 changes: 20 additions & 72 deletions apps/desktop/src-tauri/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use db::{cloudsync_runtime_config_from_env, open_desktop_db};
use ext::*;
use store::*;

use anlg_crash_reporting::{Options as CrashReportingOptions, consent::CONSENT_QUERY};
use std::sync::{
Arc,
atomic::{AtomicBool, Ordering},
Expand All @@ -30,20 +31,19 @@ const STAGING_BUNDLE_ID: &str = "com.hyprnote.staging";
const APP_EXIT_REQUESTED_EVENT: &str = "app-exit-requested";
static EXIT_FLUSH_COMPLETE: AtomicBool = AtomicBool::new(false);
static EXIT_FLUSH_REQUESTED: AtomicBool = AtomicBool::new(false);
static CRASH_REPORTING_ENABLED: AtomicBool = AtomicBool::new(false);
const EXIT_FLUSH_FALLBACK_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(10);
const EXIT_HARD_FALLBACK_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(12);

pub(crate) struct CrashReportingState;

impl CrashReportingState {
fn new(enabled: bool) -> Self {
CRASH_REPORTING_ENABLED.store(enabled, Ordering::SeqCst);
anlg_crash_reporting::set_enabled(enabled);
Self
}

fn set_enabled(&self, enabled: bool) {
CRASH_REPORTING_ENABLED.store(enabled, Ordering::SeqCst);
anlg_crash_reporting::set_enabled(enabled);
}
}

Expand All @@ -52,27 +52,12 @@ fn run_crash_reporter_process() -> ! {
}

async fn load_crash_reporting_consent(db: &anlg_db_core::Db) -> bool {
let rows = sqlx::query_as::<_, (String, String)>(
"SELECT id, value_json FROM app_settings \
WHERE id IN ('crash_reporting_consent', 'telemetry_consent')",
)
.fetch_all(db.pool())
.await
.unwrap_or_default();

crash_reporting_consent_from_rows(&rows)
}

fn crash_reporting_consent_from_rows(rows: &[(String, String)]) -> bool {
let read = |id: &str| {
rows.iter()
.find(|(key, _)| key == id)
.and_then(|(_, value)| serde_json::from_str::<bool>(value).ok())
};
let rows = sqlx::query_as::<_, (String, String)>(CONSENT_QUERY)
.fetch_all(db.pool())
.await
.unwrap_or_default();

read("crash_reporting_consent")
.or_else(|| read("telemetry_consent"))
.unwrap_or(false)
anlg_crash_reporting::consent::from_rows(&rows)
}

fn mark_exit_flush_complete() {
Expand Down Expand Up @@ -184,52 +169,15 @@ pub fn main() {
)
});

let sentry_client = {
let dsn = if std::env::var_os("ANARLOG_DISABLE_SENTRY").is_some() {
None
} else {
option_env!("SENTRY_DSN")
};

if let Some(dsn) = dsn {
let release =
option_env!("APP_VERSION").map(|v| format!("anarlog-desktop@{}", v).into());

let client = sentry::init((
dsn,
sentry::ClientOptions {
release,
traces_sample_rate: 1.0,
auto_session_tracking: false,
before_send: Some(Arc::new(|event| {
CRASH_REPORTING_ENABLED
.load(Ordering::SeqCst)
.then(|| tauri_plugin_tracing::redaction::sanitize_sentry_event(event))
.flatten()
})),
before_breadcrumb: Some(Arc::new(|breadcrumb| {
CRASH_REPORTING_ENABLED
.load(Ordering::SeqCst)
.then_some(breadcrumb)
})),
..Default::default()
},
));

sentry::configure_scope(|scope| {
scope.set_tag("service.namespace", "anarlog");
scope.set_tag("service.name", "desktop");
scope.set_tag(
"release_channel",
option_env!("RELEASE_CHANNEL").unwrap_or("dev"),
);
});

Some(client)
} else {
None
}
};
let sentry_client = anlg_crash_reporting::init(
CrashReportingOptions {
dsn: option_env!("SENTRY_DSN"),
release: option_env!("APP_VERSION").map(|v| format!("anarlog-desktop@{v}")),
release_channel: option_env!("RELEASE_CHANNEL").unwrap_or("dev"),
service_name: "desktop",
},
crash_reporting_enabled,
);
let crash_reporting_state = CrashReportingState::new(crash_reporting_enabled);

let audio: std::sync::Arc<dyn anlg_audio_actual::AudioProvider> =
Expand Down Expand Up @@ -750,9 +698,9 @@ mod test {
("crash_reporting_consent".to_string(), "true".to_string()),
];

assert!(crash_reporting_consent_from_rows(&rows));
assert!(!crash_reporting_consent_from_rows(&rows[..1]));
assert!(!crash_reporting_consent_from_rows(&[]));
assert!(anlg_crash_reporting::consent::from_rows(&rows));
assert!(!anlg_crash_reporting::consent::from_rows(&rows[..1]));
assert!(!anlg_crash_reporting::consent::from_rows(&[]));
}

#[test]
Expand Down
14 changes: 14 additions & 0 deletions crates/crash-reporting/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[package]
name = "crash-reporting"
version = "0.1.0"
edition = "2024"
publish = false

[dependencies]
anlg-user-error = { workspace = true }
dirs = { workspace = true }
regex = { workspace = true }
sentry = { workspace = true, features = ["tracing"] }
serde_json = { workspace = true }
tracing = { workspace = true }
tracing-subscriber = { workspace = true }
33 changes: 33 additions & 0 deletions crates/crash-reporting/src/consent.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
use serde_json::from_str;

pub const CONSENT_QUERY: &str = "SELECT id, value_json FROM app_settings \
WHERE id IN ('crash_reporting_consent', 'telemetry_consent')";

pub fn from_rows(rows: &[(String, String)]) -> bool {
let read = |id: &str| {
rows.iter()
.find(|(key, _)| key == id)
.and_then(|(_, value)| from_str::<bool>(value).ok())
};

read("crash_reporting_consent")
.or_else(|| read("telemetry_consent"))
.unwrap_or(false)
}

#[cfg(test)]
mod tests {
use super::from_rows;

#[test]
fn prefers_crash_reporting_consent_over_legacy_telemetry() {
let rows = vec![
("telemetry_consent".to_string(), "false".to_string()),
("crash_reporting_consent".to_string(), "true".to_string()),
];

assert!(from_rows(&rows));
assert!(!from_rows(&rows[..1]));
assert!(!from_rows(&[]));
}
}
Loading
Loading