#[cfg(feature = "crash-report")]
mod config;
#[cfg(feature = "crash-report")]
mod consent;
#[cfg(feature = "crash-report")]
mod scrub;
#[cfg(feature = "crash-report")]
mod imp {
use std::sync::Arc;
use std::time::Duration;
use sentry::{ClientInitGuard, ClientOptions};
use crate::core::config::config_path;
use super::consent::resolve;
const BAKED_DSN: &str = env!("SAFERSKILLS_SENTRY_DSN");
const BAKED_RELEASE: &str = env!("SAFERSKILLS_RELEASE");
fn resolve_dsn() -> Option<String> {
std::env::var("SAFERSKILLS_SENTRY_DSN")
.ok()
.filter(|s| !s.is_empty())
.or_else(|| {
if BAKED_DSN.is_empty() {
None
} else {
Some(BAKED_DSN.to_string())
}
})
}
pub fn init() -> Option<ClientInitGuard> {
let dsn = resolve_dsn();
let decision = resolve(&config_path(), dsn.is_some());
if !decision.enabled() {
return None;
}
let parsed = dsn.as_deref().and_then(|s| s.parse().ok());
parsed.as_ref()?;
let release = format!("saferskills-cli@{BAKED_RELEASE}");
let environment = if cfg!(debug_assertions) {
"development"
} else {
"production"
};
let options = ClientOptions {
dsn: parsed,
release: Some(release.into()),
environment: Some(environment.into()),
send_default_pii: false,
traces_sample_rate: 0.0,
attach_stacktrace: true,
before_send: Some(Arc::new(super::scrub::scrub_event)),
..Default::default()
};
Some(sentry::init(options))
}
pub fn enrich_cli_scope(command: &str, subcommand: Option<&str>) {
sentry::configure_scope(|scope| {
scope.set_tag("process_type", "cli");
scope.set_tag("command", command);
if let Some(sub) = subcommand {
scope.set_tag("subcommand", sub);
}
});
}
pub fn install_panic_hook() {
let prev = std::panic::take_hook();
std::panic::set_hook(Box::new(move |info| {
let location = info
.location()
.map(|l| format!("{}:{}", l.file(), l.line()))
.unwrap_or_else(|| "unknown".to_string());
sentry::configure_scope(|scope| {
scope.set_tag("panic_location", &location);
});
prev(info);
}));
}
pub fn flush(timeout: Duration) {
if let Some(client) = sentry::Hub::current().client() {
let _ = client.flush(Some(timeout));
}
}
}
#[cfg(feature = "crash-report")]
pub use imp::{enrich_cli_scope, flush, init, install_panic_hook};
#[cfg(not(feature = "crash-report"))]
mod shim {
use std::time::Duration;
pub struct ClientInitGuard;
pub fn init() -> Option<ClientInitGuard> {
None
}
pub fn enrich_cli_scope(_command: &str, _subcommand: Option<&str>) {}
pub fn install_panic_hook() {}
pub fn flush(_timeout: Duration) {}
}
#[cfg(not(feature = "crash-report"))]
pub use shim::{enrich_cli_scope, flush, init, install_panic_hook, ClientInitGuard};