diff --git a/sentry-actix/src/lib.rs b/sentry-actix/src/lib.rs index b43004f1..dd5665f3 100644 --- a/sentry-actix/src/lib.rs +++ b/sentry-actix/src/lib.rs @@ -218,7 +218,7 @@ impl Middleware for SentryMiddleware { if cached_data.is_none() && req.is_valid() { let with_pii = client .as_ref() - .map_or(false, |x| x.options().send_default_pii); + .map_or(false, |x| x.options().send_default_pii()); *cached_data = Some(extract_request(&req.get(), with_pii)); } diff --git a/sentry-anyhow/src/lib.rs b/sentry-anyhow/src/lib.rs index 91d6be42..5c28ac93 100644 --- a/sentry-anyhow/src/lib.rs +++ b/sentry-anyhow/src/lib.rs @@ -44,7 +44,7 @@ impl Integration for AnyhowIntegration { } fn setup(&self, cfg: &mut ClientOptions) { - cfg.in_app_exclude.push("anyhow::"); + cfg.add_in_app_exclude(&["anyhow::"]); } } diff --git a/sentry-backtrace/src/integration.rs b/sentry-backtrace/src/integration.rs index 97ed056d..09c4e4a8 100644 --- a/sentry-backtrace/src/integration.rs +++ b/sentry-backtrace/src/integration.rs @@ -65,7 +65,7 @@ impl Integration for AttachStacktraceIntegration { mut event: Event<'static>, options: &ClientOptions, ) -> Option> { - if options.attach_stacktrace && event.exception.is_empty() { + if options.attach_stacktrace() && event.exception.is_empty() { let thread = current_thread(true); if thread.stacktrace.is_some() { event.threads.values.push(thread); diff --git a/sentry-backtrace/src/process.rs b/sentry-backtrace/src/process.rs index 2a4d2e7a..a0425ef1 100644 --- a/sentry-backtrace/src/process.rs +++ b/sentry-backtrace/src/process.rs @@ -15,10 +15,10 @@ use crate::{Frame, Stacktrace}; /// `ClientOptions`. pub fn process_event_stacktrace(stacktrace: &mut Stacktrace, options: &ClientOptions) { // automatically trim backtraces - if options.trim_backtraces { + if options.trim_backtraces() { trim_stacktrace(stacktrace, |frame, _| { if let Some(ref func) = frame.function { - options.extra_border_frames.contains(&func.as_str()) + options.extra_border_frames().contains(&func.as_str()) } else { false } @@ -49,7 +49,7 @@ pub fn process_event_stacktrace(stacktrace: &mut Stacktrace, options: &ClientOpt None => {} } - for m in &options.in_app_exclude { + for m in options.in_app_exclude() { if function_starts_with(func_name, m) { frame.in_app = Some(false); break; @@ -60,7 +60,7 @@ pub fn process_event_stacktrace(stacktrace: &mut Stacktrace, options: &ClientOpt continue; } - for m in &options.in_app_include { + for m in options.in_app_include() { if function_starts_with(func_name, m) { frame.in_app = Some(true); any_in_app = true; diff --git a/sentry-contexts/src/integration.rs b/sentry-contexts/src/integration.rs index bb3d7420..596fc326 100644 --- a/sentry-contexts/src/integration.rs +++ b/sentry-contexts/src/integration.rs @@ -44,8 +44,8 @@ impl Integration for ContextIntegration { } fn setup(&self, options: &mut ClientOptions) { - if options.server_name.is_none() { - options.server_name = server_name().map(Cow::Owned); + if options.server_name().is_none() { + options.set_server_name(server_name().map(Cow::Owned)); } } diff --git a/sentry-core/src/client.rs b/sentry-core/src/client.rs index 5a02c4ee..5b93f7db 100644 --- a/sentry-core/src/client.rs +++ b/sentry-core/src/client.rs @@ -93,12 +93,14 @@ impl Client { /// If the DSN on the options is set to `None` the client will be entirely /// disabled. pub fn with_options(mut options: ClientOptions) -> Client { + #![allow(deprecated)] + // Create the main hub eagerly to avoid problems with the background thread // See https://github.com/getsentry/sentry-rust/issues/237 Hub::with(|_| {}); let create_transport = || { - options.dsn.as_ref()?; + options.dsn()?; let factory = options.transport.as_ref()?; Some(factory.create_transport(&options)) }; @@ -142,6 +144,8 @@ impl Client { mut event: Event<'static>, scope: Option<&Scope>, ) -> Option> { + #![allow(deprecated)] + if let Some(scope) = scope { scope.update_session_from_event(&event); } @@ -180,13 +184,13 @@ impl Client { } if event.release.is_none() { - event.release = self.options.release.clone(); + event.release = self.options.release(); } if event.environment.is_none() { - event.environment = self.options.environment.clone(); + event.environment = self.options.environment(); } if event.server_name.is_none() { - event.server_name = self.options.server_name.clone(); + event.server_name = self.options.server_name(); } if &event.platform == "other" { event.platform = "native".into(); @@ -211,7 +215,7 @@ impl Client { /// Returns the DSN that constructed this client. pub fn dsn(&self) -> Option<&Dsn> { - self.options.dsn.as_ref() + self.options.dsn() } /// Quick check to see if the client is enabled. @@ -230,15 +234,14 @@ impl Client { /// let transport = sentry::test::TestTransport::new(); /// let client = sentry::Client::from(( /// dsn, - /// sentry::ClientOptions { - /// transport: Some(Arc::new(transport)), - /// ..Default::default() - /// }, + /// sentry::ClientOptions::configure(|o| { + /// o.set_transport(Arc::new(transport)) + /// }), /// )); /// assert!(client.is_enabled()); /// ``` pub fn is_enabled(&self) -> bool { - self.options.dsn.is_some() && self.transport.read().unwrap().is_some() + self.options.dsn().is_some() && self.transport.read().unwrap().is_some() } /// Captures an event and sends it to sentry. @@ -282,7 +285,7 @@ impl Client { let transport_opt = self.transport.write().unwrap().take(); if let Some(transport) = transport_opt { sentry_debug!("client close; request transport to shut down"); - transport.shutdown(timeout.unwrap_or(self.options.shutdown_timeout)) + transport.shutdown(timeout.unwrap_or_else(|| self.options.shutdown_timeout())) } else { sentry_debug!("client close; no transport to shut down"); true @@ -290,7 +293,7 @@ impl Client { } fn sample_should_send(&self) -> bool { - let rate = self.options.sample_rate; + let rate = self.options.sample_rate(); if rate >= 1.0 { true } else { diff --git a/sentry-core/src/clientoptions.rs b/sentry-core/src/clientoptions.rs index c53e3ee0..acd55f05 100644 --- a/sentry-core/src/clientoptions.rs +++ b/sentry-core/src/clientoptions.rs @@ -1,3 +1,5 @@ +#![allow(deprecated)] + use std::borrow::Cow; use std::fmt; use std::sync::Arc; @@ -19,49 +21,63 @@ pub type BeforeCallback = Arc Option + Send + Sync>; /// # Examples /// /// ``` -/// let _options = sentry::ClientOptions { -/// debug: true, -/// ..Default::default() -/// }; +/// let _options = sentry::ClientOptions::configure(|o| { +/// o.set_debug(true) +/// }); /// ``` #[derive(Clone)] pub struct ClientOptions { // Common options /// The DSN to use. If not set the client is effectively disabled. + #[deprecated = "use accessor functions instead; direct field access will be removed soon"] pub dsn: Option, /// Enables debug mode. /// /// In debug mode debug information is printed to stderr to help you understand what /// sentry is doing. When the `log` feature is enabled, Sentry will instead /// log to the `sentry` logger independently of this flag with the `Debug` level. + #[deprecated = "use accessor functions instead; direct field access will be removed soon"] pub debug: bool, /// The release to be sent with events. + #[deprecated = "use accessor functions instead; direct field access will be removed soon"] pub release: Option>, /// The environment to be sent with events. + #[deprecated = "use accessor functions instead; direct field access will be removed soon"] pub environment: Option>, /// The sample rate for event submission. (0.0 - 1.0, defaults to 1.0) + #[deprecated = "use accessor functions instead; direct field access will be removed soon"] pub sample_rate: f32, /// Maximum number of breadcrumbs. (defaults to 100) + #[deprecated = "use accessor functions instead; direct field access will be removed soon"] pub max_breadcrumbs: usize, /// Attaches stacktraces to messages. + #[deprecated = "use accessor functions instead; direct field access will be removed soon"] pub attach_stacktrace: bool, /// If turned on some default PII informat is attached. + #[deprecated = "use accessor functions instead; direct field access will be removed soon"] pub send_default_pii: bool, /// The server name to be reported. + #[deprecated = "use accessor functions instead; direct field access will be removed soon"] pub server_name: Option>, /// Module prefixes that are always considered "in_app". + #[deprecated = "use accessor functions instead; direct field access will be removed soon"] pub in_app_include: Vec<&'static str>, /// Module prefixes that are never "in_app". + #[deprecated = "use accessor functions instead; direct field access will be removed soon"] pub in_app_exclude: Vec<&'static str>, // Integration options /// A list of integrations to enable. + #[deprecated = "use accessor functions instead; direct field access will be removed soon"] pub integrations: Vec>, /// Whether to add default integrations. + #[deprecated = "use accessor functions instead; direct field access will be removed soon"] pub default_integrations: bool, // Hooks /// Callback that is executed before event sending. + #[deprecated = "use accessor functions instead; direct field access will be removed soon"] pub before_send: Option>>, /// Callback that is executed for each Breadcrumb being added. + #[deprecated = "use accessor functions instead; direct field access will be removed soon"] pub before_breadcrumb: Option>, // Transport options /// The transport to use. @@ -69,17 +85,21 @@ pub struct ClientOptions { /// This is typically either a boxed function taking the client options by /// reference and returning a `Transport`, a boxed `Arc` or /// alternatively the `DefaultTransportFactory`. + #[deprecated = "use accessor functions instead; direct field access will be removed soon"] pub transport: Option>, /// An optional HTTP proxy to use. /// /// This will default to the `http_proxy` environment variable. + #[deprecated = "use accessor functions instead; direct field access will be removed soon"] pub http_proxy: Option>, /// An optional HTTPS proxy to use. /// /// This will default to the `HTTPS_PROXY` environment variable /// or `http_proxy` if that one exists. + #[deprecated = "use accessor functions instead; direct field access will be removed soon"] pub https_proxy: Option>, /// The timeout on client drop for draining events on shutdown. + #[deprecated = "use accessor functions instead; direct field access will be removed soon"] pub shutdown_timeout: Duration, // Other options not documented in Unified API /// Enable Release Health Session tracking. @@ -87,13 +107,17 @@ pub struct ClientOptions { /// When automatic session tracking is enabled, a new "user-mode" session /// is started at the time of `sentry::init`, and will persist for the /// application lifetime. + #[deprecated = "use accessor functions instead; direct field access will be removed soon"] pub auto_session_tracking: bool, /// Border frames which indicate a border from a backtrace to /// useless internals. Some are automatically included. + #[deprecated = "use accessor functions instead; direct field access will be removed soon"] pub extra_border_frames: Vec<&'static str>, /// Automatically trim backtraces of junk before sending. (defaults to true) + #[deprecated = "use accessor functions instead; direct field access will be removed soon"] pub trim_backtraces: bool, /// The user agent that should be reported. + #[deprecated = "use accessor functions instead; direct field access will be removed soon"] pub user_agent: Cow<'static, str>, } @@ -102,6 +126,261 @@ impl ClientOptions { pub fn new() -> Self { Self::default() } + + /// Creates new Options and immediately configures them. + pub fn configure(f: F) -> Self + where + F: FnOnce(&mut ClientOptions) -> &mut ClientOptions, + { + let mut opts = Self::new(); + f(&mut opts); + opts + } + + /// Set a DSN to use. + /// + /// If not set the client is effectively disabled. + pub fn set_dsn(&mut self, dsn: Dsn) -> &mut Self { + self.dsn = Some(dsn); + self + } + /// The configured DSN. + pub fn dsn(&self) -> Option<&Dsn> { + self.dsn.as_ref() + } + + /// Enables/disables debug mode. + /// + /// In debug mode debug information is printed to stderr to help you understand what + /// sentry is doing. When the `log` feature is enabled, Sentry will instead + /// log to the `sentry` logger independently of this flag with the `Debug` level. + pub fn set_debug(&mut self, debug: bool) -> &mut Self { + self.debug = debug; + self + } + /// Whether debug logging is enabled. + pub fn debug(&self) -> bool { + self.debug + } + + /// Set the release to be sent with events. + pub fn set_release(&mut self, release: Option>) -> &mut Self { + self.release = release; + self + } + /// The release to be sent with events. + pub fn release(&self) -> Option> { + self.release.clone() + } + + /// Set the environment to be sent with events. + pub fn set_environment(&mut self, environment: Option>) -> &mut Self { + self.environment = environment; + self + } + /// The environment to be sent with events. + pub fn environment(&self) -> Option> { + self.environment.clone() + } + + /// Set the sample rate for event submission. (0.0 - 1.0, defaults to 1.0) + pub fn set_sample_rate(&mut self, sample_rate: f32) -> &mut Self { + self.sample_rate = sample_rate; + self + } + /// The sample rate for event submission. + pub fn sample_rate(&self) -> f32 { + self.sample_rate + } + + /// Set the maximum number of breadcrumbs. (defaults to 100) + pub fn set_max_breadcrumbs(&mut self, max_breadcrumbs: usize) -> &mut Self { + self.max_breadcrumbs = max_breadcrumbs; + self + } + /// Maximum number of breadcrumbs. + pub fn max_breadcrumbs(&self) -> usize { + self.max_breadcrumbs + } + + /// Enable attaching stacktraces to message events. + pub fn set_attach_stacktrace(&mut self, attach_stacktrace: bool) -> &mut Self { + self.attach_stacktrace = attach_stacktrace; + self + } + /// Attach stacktraces to message events. + pub fn attach_stacktrace(&self) -> bool { + self.attach_stacktrace + } + + /// Attach some default PII informat to events. + pub fn set_send_default_pii(&mut self, send_default_pii: bool) -> &mut Self { + self.send_default_pii = send_default_pii; + self + } + /// If turned on some default PII informat is attached to events. + pub fn send_default_pii(&self) -> bool { + self.send_default_pii + } + + /// Set the server name to be reported. + pub fn set_server_name(&mut self, server_name: Option>) -> &mut Self { + self.server_name = server_name; + self + } + /// The server name to be reported. + pub fn server_name(&self) -> Option> { + self.server_name.clone() + } + + /// Add module prefixes that are always considered "in_app". + pub fn add_in_app_include(&mut self, in_app_include: &[&'static str]) -> &mut Self { + self.in_app_include.extend_from_slice(in_app_include); + self + } + /// Module prefixes that are always considered "in_app". + pub fn in_app_include(&self) -> &[&'static str] { + &self.in_app_include + } + + /// Add module prefixes that are never "in_app". + pub fn add_in_app_exclude(&mut self, in_app_exclude: &[&'static str]) -> &mut Self { + self.in_app_exclude.extend_from_slice(in_app_exclude); + self + } + /// Module prefixes that are never "in_app". + pub fn in_app_exclude(&self) -> &[&'static str] { + &self.in_app_exclude + } + + /// Enable adding default integrations on init. + pub fn set_default_integrations(&mut self, default_integrations: bool) -> &mut Self { + self.default_integrations = default_integrations; + self + } + /// Whether to add default integrations. + pub fn default_integrations(&self) -> bool { + self.default_integrations + } + + /// Adds another integration *in front* of the already registered ones. + // pub fn unshift_integration(&mut self, integration: I) -> &mut Self { + // self.integrations.push_front(Arc::new(integration)); + // self + // } + + /// Set a callback that is executed before event sending. + pub fn set_before_send(&mut self, before_send: F) -> &mut Self + where + F: Fn(Event<'static>) -> Option> + Send + Sync + 'static, + { + self.before_send = Some(Arc::new(before_send)); + self + } + + /// Set a callback that is executed for each Breadcrumb being added. + pub fn set_before_breadcrumb(&mut self, before_breadcrumb: F) -> &mut Self + where + F: Fn(Breadcrumb) -> Option + Send + Sync + 'static, + { + self.before_breadcrumb = Some(Arc::new(before_breadcrumb)); + self + } + + /// The transport to use. + /// + /// This is typically either a boxed function taking the client options by + /// reference and returning a `Transport`, a boxed `Arc` or + /// alternatively the `DefaultTransportFactory`. + pub fn set_transport(&mut self, transport: F) -> &mut Self + where + F: TransportFactory + 'static, + { + self.transport = Some(Arc::new(transport)); + self + } + /// Whether a [`TransportFactory`] has been set on these options. + pub fn has_transport(&self) -> bool { + self.transport.is_some() + } + + /// An optional HTTP proxy to use. + /// + /// This will default to the `http_proxy` environment variable. + pub fn set_http_proxy(&mut self, http_proxy: Option>) -> &mut Self { + self.http_proxy = http_proxy; + self + } + /// The HTTP proxy Sentry will use. + pub fn http_proxy(&self) -> Option> { + self.http_proxy.clone() + } + + /// Set an optional HTTPS proxy to use. + /// + /// This will default to the `HTTPS_PROXY` environment variable + /// or `http_proxy` if that one exists. + pub fn set_https_proxy(&mut self, https_proxy: Option>) -> &mut Self { + self.https_proxy = https_proxy; + self + } + /// The HTTPS proxy Sentry will use. + pub fn https_proxy(&self) -> Option> { + self.https_proxy.clone() + } + + /// The timeout on client drop for draining events on shutdown. + pub fn shutdown_timeout(&self) -> Duration { + self.shutdown_timeout + } + + /// Enable Release Health Session tracking. + /// + /// When automatic session tracking is enabled, a new "user-mode" session + /// is started at the time of `sentry::init`, and will persist for the + /// application lifetime. + pub fn set_auto_session_tracking(&mut self, auto_session_tracking: bool) -> &mut Self { + self.auto_session_tracking = auto_session_tracking; + self + } + /// Whether automatic session tracking is enabled. + pub fn auto_session_tracking(&self) -> bool { + self.auto_session_tracking + } + + /// Add extra border frames which indicate a border from a backtrace to + /// useless internals. + pub fn add_extra_border_frames(&mut self, extra_border_frames: &[&'static str]) -> &mut Self { + self.extra_border_frames + .extend_from_slice(extra_border_frames); + self + } + /// Border frames which indicate a border from a backtrace to + /// useless internals. Some are automatically included. + pub fn extra_border_frames(&self) -> &[&'static str] { + &self.extra_border_frames + } + + /// Automatically trim backtraces of junk before sending. (defaults to true) + pub fn set_trim_backtraces(&mut self, trim_backtraces: bool) -> &mut Self { + self.trim_backtraces = trim_backtraces; + self + } + /// Automatically trim backtraces of junk before sending. + pub fn trim_backtraces(&self) -> bool { + self.trim_backtraces + } + + /// Set the user agent that should be reported. + pub fn set_user_agent(&mut self, user_agent: Cow<'static, str>) -> &mut Self { + self.user_agent = user_agent; + self + } + /// The user agent that should be reported. + pub fn user_agent(&self) -> Cow<'static, str> { + self.user_agent.clone() + } + /// Adds a configured integration to the options. /// /// # Examples @@ -112,7 +391,6 @@ impl ClientOptions { /// impl sentry::Integration for MyIntegration {} /// /// let options = sentry::ClientOptions::new().add_integration(MyIntegration); - /// assert_eq!(options.integrations.len(), 1); /// ``` pub fn add_integration(mut self, integration: I) -> Self { self.integrations.push(Arc::new(integration)); diff --git a/sentry-core/src/hub.rs b/sentry-core/src/hub.rs index 5c05ddeb..d95e2619 100644 --- a/sentry-core/src/hub.rs +++ b/sentry-core/src/hub.rs @@ -415,6 +415,7 @@ impl Hub { let scope = Arc::make_mut(&mut top.scope); let options = client.options(); for breadcrumb in breadcrumb.into_breadcrumbs() { + #[allow(deprecated)] let breadcrumb_opt = match options.before_breadcrumb { Some(ref callback) => callback(breadcrumb), None => Some(breadcrumb) @@ -422,7 +423,7 @@ impl Hub { if let Some(breadcrumb) = breadcrumb_opt { scope.breadcrumbs.push_back(breadcrumb); } - while scope.breadcrumbs.len() > options.max_breadcrumbs { + while scope.breadcrumbs.len() > options.max_breadcrumbs() { scope.breadcrumbs.pop_front(); } } diff --git a/sentry-core/src/macros.rs b/sentry-core/src/macros.rs index 3b98dfb5..727e9b92 100644 --- a/sentry-core/src/macros.rs +++ b/sentry-core/src/macros.rs @@ -8,10 +8,9 @@ /// ``` /// # #[macro_use] extern crate sentry; /// # fn main() { -/// let _sentry = sentry::init(sentry::ClientOptions { -/// release: sentry::release_name!(), -/// ..Default::default() -/// }); +/// let _sentry = sentry::init(sentry::ClientOptions::configure(|o| { +/// o.set_release(sentry::release_name!()) +/// })); /// # } /// ``` #[macro_export] @@ -60,7 +59,7 @@ macro_rules! sentry_debug { } #[cfg(not(feature = "debug-logs"))] { $crate::Hub::with(|hub| { - if hub.client().map_or(false, |c| c.options().debug) { + if hub.client().map_or(false, |c| c.options().debug()) { eprint!("[sentry] "); eprintln!($($arg)*); } diff --git a/sentry-core/src/session.rs b/sentry-core/src/session.rs index 07cce8cb..6cc9eac8 100644 --- a/sentry-core/src/session.rs +++ b/sentry-core/src/session.rs @@ -57,8 +57,8 @@ impl Session { status: SessionStatus::Ok, errors: 0, attributes: SessionAttributes { - release: options.release.clone()?, - environment: options.environment.clone(), + release: options.release()?, + environment: options.environment(), ip_address: None, user_agent: None, }, @@ -125,10 +125,7 @@ mod tests { { crate::test::with_captured_envelopes_options( f, - crate::ClientOptions { - release: Some("some-release".into()), - ..Default::default() - }, + crate::ClientOptions::configure(|opts| opts.set_release(Some("some-release".into()))), ) } @@ -197,11 +194,10 @@ mod tests { sentry::capture_error(&err); } }, - crate::ClientOptions { - release: Some("some-release".into()), - sample_rate: 0.5, - ..Default::default() - }, + crate::ClientOptions::configure(|opts| { + opts.set_release(Some("some-release".into())) + .set_sample_rate(0.5) + }), ); assert!(envelopes.len() > 25); assert!(envelopes.len() < 75); diff --git a/sentry-core/src/test.rs b/sentry-core/src/test.rs index 739fe2e6..002b0493 100644 --- a/sentry-core/src/test.rs +++ b/sentry-core/src/test.rs @@ -39,11 +39,10 @@ lazy_static::lazy_static! { /// use std::sync::Arc; /// /// let transport = TestTransport::new(); -/// let options = ClientOptions { -/// dsn: Some("https://public@example.com/1".parse().unwrap()), -/// transport: Some(Arc::new(transport.clone())), -/// ..ClientOptions::default() -/// }; +/// let options = ClientOptions::configure(|o| { +/// o.set_dsn("https://public@example.com/1".parse().unwrap()) +/// .set_transport(transport.clone()) +/// }); /// Hub::current().bind_client(Some(Arc::new(options.into()))); /// ``` pub struct TestTransport { @@ -121,9 +120,13 @@ pub fn with_captured_envelopes_options>( f: F, options: O, ) -> Vec { + #![allow(deprecated)] + let transport = TestTransport::new(); let mut options = options.into(); - options.dsn = Some(options.dsn.unwrap_or_else(|| TEST_DSN.clone())); + if options.dsn().is_none() { + options.set_dsn(TEST_DSN.clone()); + } options.transport = Some(Arc::new(transport.clone())); Hub::run( Arc::new(Hub::new( diff --git a/sentry-error-chain/src/lib.rs b/sentry-error-chain/src/lib.rs index 6d9182b6..2e00b1ed 100644 --- a/sentry-error-chain/src/lib.rs +++ b/sentry-error-chain/src/lib.rs @@ -126,7 +126,7 @@ impl Integration for ErrorChainIntegration { } fn setup(&self, cfg: &mut ClientOptions) { - cfg.in_app_exclude.push("error_chain::"); - cfg.extra_border_frames.push("error_chain::make_backtrace"); + cfg.add_in_app_exclude(&["error_chain::"]); + cfg.add_extra_border_frames(&["error_chain::make_backtrace"]); } } diff --git a/sentry-failure/src/lib.rs b/sentry-failure/src/lib.rs index 1757a6b5..6ecf087f 100644 --- a/sentry-failure/src/lib.rs +++ b/sentry-failure/src/lib.rs @@ -58,8 +58,8 @@ impl Integration for FailureIntegration { } fn setup(&self, cfg: &mut ClientOptions) { - cfg.in_app_exclude.push("failure::"); - cfg.extra_border_frames.extend_from_slice(&[ + cfg.add_in_app_exclude(&["failure::"]); + cfg.add_extra_border_frames(&[ "failure::error_message::err_msg", "failure::backtrace::Backtrace::new", "failure::backtrace::internal::InternalBacktrace::new", diff --git a/sentry-log/src/integration.rs b/sentry-log/src/integration.rs index b4562d04..d83084b0 100644 --- a/sentry-log/src/integration.rs +++ b/sentry-log/src/integration.rs @@ -33,9 +33,8 @@ impl Integration for LogIntegration { } fn setup(&self, cfg: &mut ClientOptions) { - cfg.in_app_exclude.push("log::"); - cfg.extra_border_frames - .push("::log"); + cfg.add_in_app_exclude(&["log::"]); + cfg.add_extra_border_frames(&["::log"]); let filter = self.effective_global_filter(); if filter > log::max_level() { diff --git a/sentry/examples/anyhow-demo.rs b/sentry/examples/anyhow-demo.rs index 8a808852..838441af 100644 --- a/sentry/examples/anyhow-demo.rs +++ b/sentry/examples/anyhow-demo.rs @@ -6,10 +6,9 @@ fn execute() -> anyhow::Result { } fn main() { - let _sentry = sentry::init(sentry::ClientOptions { - release: sentry::release_name!(), - ..Default::default() - }); + let _sentry = sentry::init(sentry::ClientOptions::configure(|o| { + o.set_release(sentry::release_name!()) + })); if let Err(err) = execute() { println!("error: {}", err); diff --git a/sentry/examples/before-send.rs b/sentry/examples/before-send.rs index 4526bb43..90221546 100644 --- a/sentry/examples/before-send.rs +++ b/sentry/examples/before-send.rs @@ -1,18 +1,15 @@ -use std::sync::Arc; - fn main() { - let _sentry = sentry::init(sentry::ClientOptions { - before_send: Some(Arc::new(|mut event| { + let _sentry = sentry::init(sentry::ClientOptions::configure(|o| { + o.set_before_send(|mut event| { event.request = Some(sentry::protocol::Request { url: Some("https://example.com/".parse().unwrap()), method: Some("GET".into()), ..Default::default() }); Some(event) - })), - debug: true, - ..Default::default() - }); + }) + .set_debug(true) + })); let id = sentry::capture_message("An HTTP request failed.", sentry::Level::Error); println!("sent event {}", id); diff --git a/sentry/examples/failure-demo.rs b/sentry/examples/failure-demo.rs index f80e3e12..e15dc349 100644 --- a/sentry/examples/failure-demo.rs +++ b/sentry/examples/failure-demo.rs @@ -20,10 +20,9 @@ fn execute() -> Result<(), failure::Error> { } fn main() { - let _sentry = sentry::init(sentry::ClientOptions { - release: sentry::release_name!(), - ..Default::default() - }); + let _sentry = sentry::init(sentry::ClientOptions::configure(|o| { + o.set_release(sentry::release_name!()) + })); if let Err(err) = execute() { println!("error: {}", err); diff --git a/sentry/examples/health.rs b/sentry/examples/health.rs index a88a79f4..a3164947 100644 --- a/sentry/examples/health.rs +++ b/sentry/examples/health.rs @@ -1,13 +1,11 @@ fn main() { - let _sentry = sentry::init(sentry::ClientOptions { + let _sentry = sentry::init(sentry::ClientOptions::configure(|o| // release health requires a release to be set - release: sentry::release_name!(), - debug: true, + o.set_release(sentry::release_name!()) + .set_debug(true) // session tracking is enabled by default, but we want to explicitly // create the session - auto_session_tracking: false, - ..Default::default() - }); + .set_auto_session_tracking(false))); let handle = std::thread::spawn(|| { // this session will be set to crashed diff --git a/sentry/examples/log-demo.rs b/sentry/examples/log-demo.rs index 80e45020..5c39260e 100644 --- a/sentry/examples/log-demo.rs +++ b/sentry/examples/log-demo.rs @@ -7,11 +7,8 @@ fn main() { sentry_log::LogIntegration::default().with_env_logger_dest(Some(log_builder.build())); let _sentry = sentry::init( - sentry::ClientOptions { - release: sentry::release_name!(), - ..Default::default() - } - .add_integration(log_integration), + sentry::ClientOptions::configure(|o| o.set_release(sentry::release_name!())) + .add_integration(log_integration), ); debug!("System is booting"); diff --git a/sentry/examples/panic-demo.rs b/sentry/examples/panic-demo.rs index 4c337e47..f775285c 100644 --- a/sentry/examples/panic-demo.rs +++ b/sentry/examples/panic-demo.rs @@ -1,8 +1,7 @@ fn main() { - let _sentry = sentry::init(sentry::ClientOptions { - release: sentry::release_name!(), - ..Default::default() - }); + let _sentry = sentry::init(sentry::ClientOptions::configure(|o| { + o.set_release(sentry::release_name!()) + })); { let _guard = sentry::Hub::current().push_scope(); diff --git a/sentry/examples/thread-demo.rs b/sentry/examples/thread-demo.rs index 7b3d3591..09d27663 100644 --- a/sentry/examples/thread-demo.rs +++ b/sentry/examples/thread-demo.rs @@ -14,11 +14,8 @@ fn main() { // special behavior in that all other threads spawned will get a hub based on // the hub from here. let _sentry = sentry::init( - sentry::ClientOptions { - release: sentry::release_name!(), - ..Default::default() - } - .add_integration(log_integration), + sentry::ClientOptions::configure(|o| o.set_release(sentry::release_name!())) + .add_integration(log_integration), ); // the log integration sends to Hub::current() diff --git a/sentry/src/defaults.rs b/sentry/src/defaults.rs index 70f4089f..085a045c 100644 --- a/sentry/src/defaults.rs +++ b/sentry/src/defaults.rs @@ -1,8 +1,8 @@ -#![cfg_attr(feature = "error-chain", allow(deprecated))] -#![cfg_attr(feature = "failure", allow(deprecated))] +#![allow(deprecated)] +use std::borrow::Cow; use std::env; -use std::{borrow::Cow, sync::Arc}; +use std::sync::Arc; use crate::transports::DefaultTransportFactory; use crate::types::Dsn; @@ -36,12 +36,12 @@ use crate::{ClientOptions, Integration}; /// std::env::set_var("SENTRY_RELEASE", "release-from-env"); /// /// let options = sentry::ClientOptions::default(); -/// assert_eq!(options.release, None); -/// assert!(options.transport.is_none()); +/// assert_eq!(options.release(), None); +/// assert!(!options.has_transport()); /// /// let options = sentry::apply_defaults(options); -/// assert_eq!(options.release, Some("release-from-env".into())); -/// assert!(options.transport.is_some()); +/// assert_eq!(options.release(), Some("release-from-env".into())); +/// assert!(options.has_transport()); /// ``` /// /// [`AttachStacktraceIntegration`]: integrations/backtrace/struct.AttachStacktraceIntegration.html @@ -52,13 +52,14 @@ use crate::{ClientOptions, Integration}; /// [`PanicIntegration`]: integrations/panic/struct.PanicIntegration.html /// [`ProcessStacktraceIntegration`]: integrations/backtrace/struct.ProcessStacktraceIntegration.html pub fn apply_defaults(mut opts: ClientOptions) -> ClientOptions { - if opts.transport.is_none() { - opts.transport = Some(Arc::new(DefaultTransportFactory)); + if !opts.has_transport() { + opts.set_transport(DefaultTransportFactory); } - if opts.default_integrations { + if opts.default_integrations() { // default integrations need to be ordered *before* custom integrations, // since they also process events in order let mut integrations: Vec> = vec![]; + #[cfg(feature = "backtrace")] { integrations.push(Arc::new( @@ -101,41 +102,52 @@ pub fn apply_defaults(mut opts: ClientOptions) -> ClientOptions { sentry_backtrace::ProcessStacktraceIntegration::default(), )); } + + integrations.reverse(); integrations.extend(opts.integrations.into_iter()); opts.integrations = integrations; } - if opts.dsn.is_none() { - opts.dsn = env::var("SENTRY_DSN") + if opts.dsn().is_none() { + if let Some(dsn) = env::var("SENTRY_DSN") .ok() - .and_then(|dsn| dsn.parse::().ok()); + .and_then(|dsn| dsn.parse::().ok()) + { + opts.set_dsn(dsn); + } } - if opts.release.is_none() { - opts.release = env::var("SENTRY_RELEASE").ok().map(Cow::Owned); + if opts.release().is_none() { + opts.set_release(env::var("SENTRY_RELEASE").ok().map(Cow::Owned)); } - if opts.environment.is_none() { - opts.environment = env::var("SENTRY_ENVIRONMENT") - .ok() - .map(Cow::Owned) - .or_else(|| { - Some(Cow::Borrowed(if cfg!(debug_assertions) { - "debug" - } else { - "release" - })) - }); + if opts.environment().is_none() { + opts.set_environment( + env::var("SENTRY_ENVIRONMENT") + .ok() + .map(Cow::Owned) + .or_else(|| { + Some(Cow::Borrowed(if cfg!(debug_assertions) { + "debug" + } else { + "release" + })) + }), + ); } - if opts.http_proxy.is_none() { - opts.http_proxy = std::env::var("HTTP_PROXY") - .ok() - .map(Cow::Owned) - .or_else(|| std::env::var("http_proxy").ok().map(Cow::Owned)); + if opts.http_proxy().is_none() { + opts.set_http_proxy( + std::env::var("HTTP_PROXY") + .ok() + .map(Cow::Owned) + .or_else(|| std::env::var("http_proxy").ok().map(Cow::Owned)), + ); } - if opts.https_proxy.is_none() { - opts.https_proxy = std::env::var("HTTPS_PROXY") - .ok() - .map(Cow::Owned) - .or_else(|| std::env::var("https_proxy").ok().map(Cow::Owned)) - .or_else(|| opts.http_proxy.clone()); + if opts.https_proxy().is_none() { + opts.set_https_proxy( + std::env::var("HTTPS_PROXY") + .ok() + .map(Cow::Owned) + .or_else(|| std::env::var("https_proxy").ok().map(Cow::Owned)) + .or_else(|| opts.http_proxy()), + ); } opts } diff --git a/sentry/src/init.rs b/sentry/src/init.rs index 8925a34b..f5f3e974 100644 --- a/sentry/src/init.rs +++ b/sentry/src/init.rs @@ -65,10 +65,9 @@ impl Drop for ClientInitGuard { /// created to enable further configuration: /// /// ``` -/// let sentry = sentry::init(sentry::ClientOptions { -/// release: Some("foo-bar-baz@1.0.0".into()), -/// ..Default::default() -/// }); +/// let sentry = sentry::init(sentry::ClientOptions::configure(|o| { +/// o.set_release(Some("foo-bar-baz@1.0.0".into())) +/// })); /// if sentry.is_enabled() { /// // some other initialization /// } @@ -91,7 +90,7 @@ where C: Into, { let opts = apply_defaults(opts.into()); - let auto_session_tracking = opts.auto_session_tracking; + let auto_session_tracking = opts.auto_session_tracking(); let client = Arc::new(Client::from(opts)); Hub::with(|hub| hub.bind_client(Some(client.clone()))); diff --git a/sentry/src/transport.rs b/sentry/src/transport.rs index c8b982d8..15d232fd 100644 --- a/sentry/src/transport.rs +++ b/sentry/src/transport.rs @@ -184,12 +184,12 @@ implement_http_transport! { queue_size: Arc>, http_client: Option, ) { - let dsn = options.dsn.clone().unwrap(); - let user_agent = options.user_agent.to_string(); + let dsn = options.dsn().cloned().unwrap(); + let user_agent = options.user_agent().to_string(); let mut disabled = None::; - let http_proxy = options.http_proxy.as_ref().map(ToString::to_string); - let https_proxy = options.https_proxy.as_ref().map(ToString::to_string); + let http_proxy = options.http_proxy().as_ref().map(ToString::to_string); + let https_proxy = options.https_proxy().as_ref().map(ToString::to_string); thread::Builder::new() .name("sentry-transport".to_string()) @@ -293,10 +293,10 @@ implement_http_transport! { queue_size: Arc>, http_client: curl::easy::Easy, ) { - let dsn = options.dsn.clone().unwrap(); - let user_agent = options.user_agent.to_string(); - let http_proxy = options.http_proxy.as_ref().map(ToString::to_string); - let https_proxy = options.https_proxy.as_ref().map(ToString::to_string); + let dsn = options.dsn().cloned().unwrap(); + let user_agent = options.user_agent().to_string(); + let http_proxy = options.http_proxy().as_ref().map(ToString::to_string); + let https_proxy = options.https_proxy().as_ref().map(ToString::to_string); let mut disabled = None::; let mut handle = http_client; @@ -426,8 +426,8 @@ implement_http_transport! { queue_size: Arc>, http_client: SurfClient, ) { - let dsn = options.dsn.clone().unwrap(); - let user_agent = options.user_agent.to_string(); + let dsn = options.dsn().cloned().unwrap(); + let user_agent = options.user_agent().to_string(); let mut disabled = None::; thread::Builder::new() diff --git a/sentry/tests/test_basic.rs b/sentry/tests/test_basic.rs index 33f5607d..b6d108d9 100644 --- a/sentry/tests/test_basic.rs +++ b/sentry/tests/test_basic.rs @@ -97,16 +97,15 @@ fn test_factory() { let events = Arc::new(AtomicUsize::new(0)); let events_for_options = events.clone(); - let options = sentry::ClientOptions { - dsn: "http://foo@example.com/42".parse().ok(), - transport: Some(Arc::new( + let dsn = "http://foo@example.com/42".parse().unwrap(); + let options = sentry::ClientOptions::configure(|o| { + o.set_dsn(dsn).set_transport( move |opts: &sentry::ClientOptions| -> Arc { - assert_eq!(opts.dsn.as_ref().unwrap().host(), "example.com"); + assert_eq!(opts.dsn().unwrap().host(), "example.com"); Arc::new(TestTransport(events_for_options.clone())) }, - )), - ..Default::default() - }; + ) + }); sentry::Hub::run( Arc::new(sentry::Hub::new( diff --git a/sentry/tests/test_client.rs b/sentry/tests/test_client.rs index c576be95..6b37a491 100644 --- a/sentry/tests/test_client.rs +++ b/sentry/tests/test_client.rs @@ -16,10 +16,7 @@ fn test_into_client() { let c: sentry::Client = sentry::Client::from_config(( "https://public@example.com/42", - sentry::ClientOptions { - release: Some("foo@1.0".into()), - ..Default::default() - }, + sentry::ClientOptions::configure(|o| o.set_release(Some("foo@1.0".into()))), )); { let dsn = c.dsn().unwrap(); @@ -27,20 +24,19 @@ fn test_into_client() { assert_eq!(dsn.host(), "example.com"); assert_eq!(dsn.scheme(), sentry::types::Scheme::Https); assert_eq!(dsn.project_id().value(), 42); - assert_eq!(&c.options().release.as_ref().unwrap(), &"foo@1.0"); + assert_eq!(&c.options().release().unwrap(), "foo@1.0"); } - assert!(sentry::Client::from_config(()).options().dsn.is_none()); + assert!(sentry::Client::from_config(()).options().dsn().is_none()); } #[test] fn test_unwind_safe() { let transport = sentry::test::TestTransport::new(); - let options = sentry::ClientOptions { - dsn: Some("https://public@example.com/1".parse().unwrap()), - transport: Some(Arc::new(transport.clone())), - ..sentry::ClientOptions::default() - }; + let options = sentry::ClientOptions::configure(|o| { + o.set_dsn("https://public@example.com/1".parse().unwrap()) + .set_transport(Arc::new(transport.clone())) + }); let client: Arc = Arc::new(options.into()); diff --git a/sentry/tests/test_processors.rs b/sentry/tests/test_processors.rs index 6025ee69..30aaaf24 100644 --- a/sentry/tests/test_processors.rs +++ b/sentry/tests/test_processors.rs @@ -1,7 +1,5 @@ #![cfg(feature = "test")] -use std::sync::Arc; - #[test] fn test_event_processors() { let events = sentry::test::with_captured_events(|| { @@ -52,11 +50,10 @@ fn test_before_callbacks() { }); sentry::capture_message("Hello World!", sentry::Level::Warning); }, - sentry::ClientOptions { - before_send: Some(Arc::new(Box::new(before_send))), - before_breadcrumb: Some(Arc::new(Box::new(before_breadcrumb))), - ..Default::default() - }, + sentry::ClientOptions::configure(|o| { + o.set_before_send(before_send) + .set_before_breadcrumb(before_breadcrumb) + }), ); assert_eq!(events.len(), 1); @@ -85,10 +82,7 @@ fn test_before_event_callback_drop() { }); sentry::capture_message("Hello World!", sentry::Level::Warning); }, - sentry::ClientOptions { - before_send: Some(Arc::new(Box::new(before_send))), - ..Default::default() - }, + sentry::ClientOptions::configure(|o| o.set_before_send(before_send)), ); assert_eq!(events.len(), 0); @@ -109,10 +103,7 @@ fn test_before_breadcrumb_callback_drop() { }); sentry::capture_message("Hello World!", sentry::Level::Warning); }, - sentry::ClientOptions { - before_breadcrumb: Some(Arc::new(Box::new(before_breadcrumb))), - ..Default::default() - }, + sentry::ClientOptions::configure(|o| o.set_before_breadcrumb(before_breadcrumb)), ); assert_eq!(events.len(), 1);