From 7b1d59463118c9cd6e64323e9fdb6fee8b401dec Mon Sep 17 00:00:00 2001 From: Arpad Borsos Date: Mon, 21 Sep 2020 12:46:20 +0200 Subject: [PATCH 1/6] ref: Make the fields of ClientOptions private --- sentry-core/src/clientoptions.rs | 71 ++++++++++++++++++++++++++------ 1 file changed, 59 insertions(+), 12 deletions(-) diff --git a/sentry-core/src/clientoptions.rs b/sentry-core/src/clientoptions.rs index c53e3ee0..7dfe41fa 100644 --- a/sentry-core/src/clientoptions.rs +++ b/sentry-core/src/clientoptions.rs @@ -27,18 +27,10 @@ pub type BeforeCallback = Arc Option + Send + Sync>; #[derive(Clone)] pub struct ClientOptions { // Common options - /// The DSN to use. If not set the client is effectively disabled. - 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. - pub debug: bool, - /// The release to be sent with events. - pub release: Option>, - /// The environment to be sent with events. - pub environment: Option>, + dsn: Option, + debug: bool, + release: Option>, + environment: Option>, /// The sample rate for event submission. (0.0 - 1.0, defaults to 1.0) pub sample_rate: f32, /// Maximum number of breadcrumbs. (defaults to 100) @@ -102,6 +94,61 @@ impl ClientOptions { pub fn new() -> Self { Self::default() } + + pub fn configure(f: F) -> Self + where + F: FnOnce(&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 + } + pub fn debug(&self) -> bool { + self.debug + } + + /// Set the release to be sent with events. + pub fn set_release(&mut self, release: Cow<'static, str>) -> &mut Self { + self.release = Some(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: Cow<'static, str>) -> &mut Self { + self.environment = Some(environment); + self + } + /// The environment to be sent with events. + pub fn environment(&self) -> Option> { + self.environment.clone() + } + /// Adds a configured integration to the options. /// /// # Examples From f298afb88dd8d971406e831efa8a6297e58cc3a9 Mon Sep 17 00:00:00 2001 From: Arpad Borsos Date: Mon, 21 Sep 2020 15:26:44 +0200 Subject: [PATCH 2/6] convert all of the code except tests --- sentry-actix/src/lib.rs | 2 +- sentry-backtrace/src/integration.rs | 2 +- sentry-backtrace/src/process.rs | 8 +- sentry-contexts/src/integration.rs | 4 +- sentry-core/src/client.rs | 16 +- sentry-core/src/clientoptions.rs | 285 ++++++++++++++++++++++------ sentry-core/src/hub.rs | 2 +- sentry-core/src/macros.rs | 2 +- sentry-core/src/session.rs | 17 +- sentry-core/src/test.rs | 4 +- sentry-error-chain/src/lib.rs | 4 +- sentry-failure/src/lib.rs | 4 +- sentry-log/src/integration.rs | 5 +- sentry/examples/thread-demo.rs | 7 +- sentry/src/defaults.rs | 100 +++++----- sentry/src/init.rs | 2 +- sentry/src/transport.rs | 20 +- 17 files changed, 325 insertions(+), 159 deletions(-) diff --git a/sentry-actix/src/lib.rs b/sentry-actix/src/lib.rs index fd8b797f..54612152 100644 --- a/sentry-actix/src/lib.rs +++ b/sentry-actix/src/lib.rs @@ -217,7 +217,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-backtrace/src/integration.rs b/sentry-backtrace/src/integration.rs index b6d8faeb..6ca340e0 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 cbf812f0..75d9693b 100644 --- a/sentry-contexts/src/integration.rs +++ b/sentry-contexts/src/integration.rs @@ -43,8 +43,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..cee5ee11 100644 --- a/sentry-core/src/client.rs +++ b/sentry-core/src/client.rs @@ -98,7 +98,7 @@ impl Client { Hub::with(|_| {}); let create_transport = || { - options.dsn.as_ref()?; + options.dsn()?; let factory = options.transport.as_ref()?; Some(factory.create_transport(&options)) }; @@ -180,13 +180,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 +211,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. @@ -238,7 +238,7 @@ impl Client { /// 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 +282,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 +290,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 7dfe41fa..d2f9f0cc 100644 --- a/sentry-core/src/clientoptions.rs +++ b/sentry-core/src/clientoptions.rs @@ -1,4 +1,5 @@ use std::borrow::Cow; +use std::collections::VecDeque; use std::fmt; use std::sync::Arc; use std::time::Duration; @@ -31,62 +32,38 @@ pub struct ClientOptions { debug: bool, release: Option>, environment: Option>, - /// The sample rate for event submission. (0.0 - 1.0, defaults to 1.0) - pub sample_rate: f32, - /// Maximum number of breadcrumbs. (defaults to 100) - pub max_breadcrumbs: usize, - /// Attaches stacktraces to messages. - pub attach_stacktrace: bool, - /// If turned on some default PII informat is attached. - pub send_default_pii: bool, - /// The server name to be reported. - pub server_name: Option>, - /// Module prefixes that are always considered "in_app". - pub in_app_include: Vec<&'static str>, - /// Module prefixes that are never "in_app". - pub in_app_exclude: Vec<&'static str>, + sample_rate: f32, + max_breadcrumbs: usize, + attach_stacktrace: bool, + send_default_pii: bool, + server_name: Option>, + in_app_include: Vec<&'static str>, + in_app_exclude: Vec<&'static str>, + // Integration options - /// A list of integrations to enable. - pub integrations: Vec>, - /// Whether to add default integrations. - pub default_integrations: bool, + pub(crate) integrations: VecDeque>, + default_integrations: bool, + // Hooks - /// Callback that is executed before event sending. - pub before_send: Option>>, - /// Callback that is executed for each Breadcrumb being added. - pub before_breadcrumb: Option>, + pub(crate) before_send: Option>>, + pub(crate) before_breadcrumb: Option>, + // Transport options /// 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 transport: Option>, - /// An optional HTTP proxy to use. - /// - /// This will default to the `http_proxy` environment variable. - 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. - pub https_proxy: Option>, - /// The timeout on client drop for draining events on shutdown. - pub shutdown_timeout: Duration, + pub(crate) transport: Option>, + http_proxy: Option>, + https_proxy: Option>, + shutdown_timeout: Duration, + // Other options not documented in Unified API - /// 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 auto_session_tracking: bool, - /// Border frames which indicate a border from a backtrace to - /// useless internals. Some are automatically included. - pub extra_border_frames: Vec<&'static str>, - /// Automatically trim backtraces of junk before sending. (defaults to true) - pub trim_backtraces: bool, - /// The user agent that should be reported. - pub user_agent: Cow<'static, str>, + auto_session_tracking: bool, + extra_border_frames: Vec<&'static str>, + trim_backtraces: bool, + user_agent: Cow<'static, str>, } impl ClientOptions { @@ -95,9 +72,10 @@ impl ClientOptions { Self::default() } + /// Creates new Options and immediately configures them. pub fn configure(f: F) -> Self where - F: FnOnce(&mut ClientOptions), + F: FnOnce(&mut ClientOptions) -> &mut ClientOptions, { let mut opts = Self::new(); f(&mut opts); @@ -125,13 +103,14 @@ impl ClientOptions { 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: Cow<'static, str>) -> &mut Self { - self.release = Some(release); + pub fn set_release(&mut self, release: Option>) -> &mut Self { + self.release = release; self } /// The release to be sent with events. @@ -140,8 +119,8 @@ impl ClientOptions { } /// Set the environment to be sent with events. - pub fn set_environment(&mut self, environment: Cow<'static, str>) -> &mut Self { - self.environment = Some(environment); + pub fn set_environment(&mut self, environment: Option>) -> &mut Self { + self.environment = environment; self } /// The environment to be sent with events. @@ -149,6 +128,204 @@ impl ClientOptions { 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 @@ -162,7 +339,7 @@ impl ClientOptions { /// assert_eq!(options.integrations.len(), 1); /// ``` pub fn add_integration(mut self, integration: I) -> Self { - self.integrations.push(Arc::new(integration)); + self.integrations.push_back(Arc::new(integration)); self } } @@ -222,7 +399,7 @@ impl Default for ClientOptions { server_name: None, in_app_include: vec![], in_app_exclude: vec![], - integrations: vec![], + integrations: VecDeque::new(), default_integrations: true, before_send: None, before_breadcrumb: None, diff --git a/sentry-core/src/hub.rs b/sentry-core/src/hub.rs index 5c05ddeb..4b0a6172 100644 --- a/sentry-core/src/hub.rs +++ b/sentry-core/src/hub.rs @@ -422,7 +422,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..cebe14fc 100644 --- a/sentry-core/src/macros.rs +++ b/sentry-core/src/macros.rs @@ -60,7 +60,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..d62ec70f 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-release".into())), ) } @@ -197,11 +194,9 @@ 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-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..a9a40b54 100644 --- a/sentry-core/src/test.rs +++ b/sentry-core/src/test.rs @@ -123,7 +123,9 @@ pub fn with_captured_envelopes_options>( ) -> Vec { 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 697ff219..1995a07f 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 d2bbf8ea..a7e84b95 100644 --- a/sentry-failure/src/lib.rs +++ b/sentry-failure/src/lib.rs @@ -56,8 +56,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 ee7232b7..07037b68 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/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 8432b50c..4b9c072c 100644 --- a/sentry/src/defaults.rs +++ b/sentry/src/defaults.rs @@ -1,11 +1,11 @@ #![cfg_attr(feature = "error-chain", allow(deprecated))] +use std::borrow::Cow; use std::env; -use std::{borrow::Cow, sync::Arc}; use crate::transports::DefaultTransportFactory; use crate::types::Dsn; -use crate::{ClientOptions, Integration}; +use crate::ClientOptions; /// Apply default client options. /// @@ -51,38 +51,29 @@ 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 { - // default integrations need to be ordered *before* custom integrations, - // since they also process events in order - let mut integrations: Vec> = vec![]; + if opts.default_integrations() { #[cfg(feature = "backtrace")] { - integrations.push(Arc::new( - sentry_backtrace::AttachStacktraceIntegration::default(), - )); + opts.unshift_integration(sentry_backtrace::AttachStacktraceIntegration::default()); } #[cfg(feature = "debug-images")] { - integrations.push(Arc::new( - sentry_debug_images::DebugImagesIntegration::default(), - )) + opts.unshift_integration(sentry_debug_images::DebugImagesIntegration::default()); } #[cfg(feature = "error-chain")] { - integrations.push(Arc::new( - sentry_error_chain::ErrorChainIntegration::default(), - )) + opts.unshift_integration(sentry_error_chain::ErrorChainIntegration::default()); } #[cfg(feature = "contexts")] { - integrations.push(Arc::new(sentry_contexts::ContextIntegration::default())); + opts.unshift_integration(sentry_contexts::ContextIntegration::default()); } #[cfg(feature = "failure")] { - integrations.push(Arc::new(sentry_failure::FailureIntegration::default())); + opts.unshift_integration(sentry_failure::FailureIntegration::default()); } #[cfg(feature = "panic")] { @@ -92,49 +83,54 @@ pub fn apply_defaults(mut opts: ClientOptions) -> ClientOptions { { integration = integration.add_extractor(sentry_failure::panic_extractor); } - integrations.push(Arc::new(integration)); + opts.unshift_integration(integration); } #[cfg(feature = "backtrace")] { - integrations.push(Arc::new( - sentry_backtrace::ProcessStacktraceIntegration::default(), - )); + opts.unshift_integration(sentry_backtrace::ProcessStacktraceIntegration::default()); } - 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..c70dcaa3 100644 --- a/sentry/src/init.rs +++ b/sentry/src/init.rs @@ -91,7 +91,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() From 30cace5fbae57de018e1fc07fa1d035a25c28f90 Mon Sep 17 00:00:00 2001 From: Arpad Borsos Date: Mon, 21 Sep 2020 16:29:45 +0200 Subject: [PATCH 3/6] use deprecation instead of hard errors --- sentry-core/src/client.rs | 3 + sentry-core/src/clientoptions.rs | 124 ++++++++++++++++++++++--------- sentry-core/src/hub.rs | 1 + sentry-core/src/session.rs | 5 +- sentry-core/src/test.rs | 2 + sentry/examples/anyhow-demo.rs | 7 +- sentry/examples/before-send.rs | 13 ++-- sentry/examples/failure-demo.rs | 7 +- sentry/examples/health.rs | 10 +-- sentry/examples/log-demo.rs | 7 +- sentry/examples/panic-demo.rs | 7 +- sentry/src/defaults.rs | 35 ++++++--- sentry/tests/test_basic.rs | 13 ++-- sentry/tests/test_client.rs | 18 ++--- sentry/tests/test_processors.rs | 21 ++---- 15 files changed, 164 insertions(+), 109 deletions(-) diff --git a/sentry-core/src/client.rs b/sentry-core/src/client.rs index cee5ee11..38e1e85c 100644 --- a/sentry-core/src/client.rs +++ b/sentry-core/src/client.rs @@ -93,6 +93,8 @@ 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(|_| {}); @@ -192,6 +194,7 @@ impl Client { event.platform = "native".into(); } + #[allow(deprecated)] if let Some(ref func) = self.options.before_send { sentry_debug!("invoking before_send callback"); let id = event.event_id; diff --git a/sentry-core/src/clientoptions.rs b/sentry-core/src/clientoptions.rs index d2f9f0cc..d7c89169 100644 --- a/sentry-core/src/clientoptions.rs +++ b/sentry-core/src/clientoptions.rs @@ -1,5 +1,6 @@ +#![allow(deprecated)] + use std::borrow::Cow; -use std::collections::VecDeque; use std::fmt; use std::sync::Arc; use std::time::Duration; @@ -28,42 +29,97 @@ pub type BeforeCallback = Arc Option + Send + Sync>; #[derive(Clone)] pub struct ClientOptions { // Common options - dsn: Option, - debug: bool, - release: Option>, - environment: Option>, - sample_rate: f32, - max_breadcrumbs: usize, - attach_stacktrace: bool, - send_default_pii: bool, - server_name: Option>, - in_app_include: Vec<&'static str>, - in_app_exclude: Vec<&'static str>, - + /// 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 - pub(crate) integrations: VecDeque>, - default_integrations: bool, - + /// 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 - pub(crate) before_send: Option>>, - pub(crate) before_breadcrumb: Option>, - + /// 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. /// /// 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(crate) transport: Option>, - http_proxy: Option>, - https_proxy: Option>, - shutdown_timeout: Duration, - + #[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 - auto_session_tracking: bool, - extra_border_frames: Vec<&'static str>, - trim_backtraces: bool, - user_agent: Cow<'static, str>, + /// 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. + #[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>, } impl ClientOptions { @@ -209,10 +265,10 @@ impl ClientOptions { } /// 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 - } + // 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 @@ -339,7 +395,7 @@ impl ClientOptions { /// assert_eq!(options.integrations.len(), 1); /// ``` pub fn add_integration(mut self, integration: I) -> Self { - self.integrations.push_back(Arc::new(integration)); + self.integrations.push(Arc::new(integration)); self } } @@ -399,7 +455,7 @@ impl Default for ClientOptions { server_name: None, in_app_include: vec![], in_app_exclude: vec![], - integrations: VecDeque::new(), + integrations: vec![], default_integrations: true, before_send: None, before_breadcrumb: None, diff --git a/sentry-core/src/hub.rs b/sentry-core/src/hub.rs index 4b0a6172..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) diff --git a/sentry-core/src/session.rs b/sentry-core/src/session.rs index d62ec70f..6cc9eac8 100644 --- a/sentry-core/src/session.rs +++ b/sentry-core/src/session.rs @@ -125,7 +125,7 @@ mod tests { { crate::test::with_captured_envelopes_options( f, - crate::ClientOptions::configure(|opts| opts.set_release("some-release".into())), + crate::ClientOptions::configure(|opts| opts.set_release(Some("some-release".into()))), ) } @@ -195,7 +195,8 @@ mod tests { } }, crate::ClientOptions::configure(|opts| { - opts.set_release("some-release".into()).set_sample_rate(0.5) + opts.set_release(Some("some-release".into())) + .set_sample_rate(0.5) }), ); assert!(envelopes.len() > 25); diff --git a/sentry-core/src/test.rs b/sentry-core/src/test.rs index a9a40b54..75790531 100644 --- a/sentry-core/src/test.rs +++ b/sentry-core/src/test.rs @@ -121,6 +121,8 @@ pub fn with_captured_envelopes_options>( f: F, options: O, ) -> Vec { + #![allow(deprecated)] + let transport = TestTransport::new(); let mut options = options.into(); if options.dsn().is_none() { 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 bed56fd4..ad91deee 100644 --- a/sentry/examples/failure-demo.rs +++ b/sentry/examples/failure-demo.rs @@ -18,10 +18,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/src/defaults.rs b/sentry/src/defaults.rs index 4b9c072c..429b15cc 100644 --- a/sentry/src/defaults.rs +++ b/sentry/src/defaults.rs @@ -1,11 +1,12 @@ -#![cfg_attr(feature = "error-chain", allow(deprecated))] +#![allow(deprecated)] use std::borrow::Cow; use std::env; +use std::sync::Arc; use crate::transports::DefaultTransportFactory; use crate::types::Dsn; -use crate::ClientOptions; +use crate::{ClientOptions, Integration}; /// Apply default client options. /// @@ -55,25 +56,35 @@ pub fn apply_defaults(mut opts: ClientOptions) -> ClientOptions { opts.set_transport(DefaultTransportFactory); } 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")] { - opts.unshift_integration(sentry_backtrace::AttachStacktraceIntegration::default()); + integrations.push(Arc::new( + sentry_backtrace::AttachStacktraceIntegration::default(), + )); } #[cfg(feature = "debug-images")] { - opts.unshift_integration(sentry_debug_images::DebugImagesIntegration::default()); + integrations.push(Arc::new( + sentry_debug_images::DebugImagesIntegration::default(), + )) } #[cfg(feature = "error-chain")] { - opts.unshift_integration(sentry_error_chain::ErrorChainIntegration::default()); + integrations.push(Arc::new( + sentry_error_chain::ErrorChainIntegration::default(), + )) } #[cfg(feature = "contexts")] { - opts.unshift_integration(sentry_contexts::ContextIntegration::default()); + integrations.push(Arc::new(sentry_contexts::ContextIntegration::default())); } #[cfg(feature = "failure")] { - opts.unshift_integration(sentry_failure::FailureIntegration::default()); + integrations.push(Arc::new(sentry_failure::FailureIntegration::default())); } #[cfg(feature = "panic")] { @@ -83,12 +94,18 @@ pub fn apply_defaults(mut opts: ClientOptions) -> ClientOptions { { integration = integration.add_extractor(sentry_failure::panic_extractor); } - opts.unshift_integration(integration); + integrations.push(Arc::new(integration)); } #[cfg(feature = "backtrace")] { - opts.unshift_integration(sentry_backtrace::ProcessStacktraceIntegration::default()); + integrations.push(Arc::new( + sentry_backtrace::ProcessStacktraceIntegration::default(), + )); } + + integrations.reverse(); + integrations.extend(opts.integrations.into_iter()); + opts.integrations = integrations; } if opts.dsn().is_none() { if let Some(dsn) = env::var("SENTRY_DSN") 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); From 1d32a4e9f24ab9997a2c41297f7d6837d401c86d Mon Sep 17 00:00:00 2001 From: Arpad Borsos Date: Mon, 21 Sep 2020 16:35:55 +0200 Subject: [PATCH 4/6] change more doctests --- sentry-core/src/client.rs | 7 +++---- sentry-core/src/clientoptions.rs | 8 +++----- sentry-core/src/macros.rs | 7 +++---- sentry-core/src/test.rs | 9 ++++----- sentry/src/defaults.rs | 8 ++++---- sentry/src/init.rs | 7 +++---- 6 files changed, 20 insertions(+), 26 deletions(-) diff --git a/sentry-core/src/client.rs b/sentry-core/src/client.rs index 38e1e85c..3370e3ea 100644 --- a/sentry-core/src/client.rs +++ b/sentry-core/src/client.rs @@ -233,10 +233,9 @@ 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()); /// ``` diff --git a/sentry-core/src/clientoptions.rs b/sentry-core/src/clientoptions.rs index d7c89169..2f8a9196 100644 --- a/sentry-core/src/clientoptions.rs +++ b/sentry-core/src/clientoptions.rs @@ -21,10 +21,9 @@ 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 { @@ -392,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/macros.rs b/sentry-core/src/macros.rs index cebe14fc..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] diff --git a/sentry-core/src/test.rs b/sentry-core/src/test.rs index 75790531..361d0b64 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 { diff --git a/sentry/src/defaults.rs b/sentry/src/defaults.rs index 429b15cc..085a045c 100644 --- a/sentry/src/defaults.rs +++ b/sentry/src/defaults.rs @@ -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 diff --git a/sentry/src/init.rs b/sentry/src/init.rs index c70dcaa3..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 /// } From 1932d5269f8c4a6f819d7fb3d0a02f896974df44 Mon Sep 17 00:00:00 2001 From: Arpad Borsos Date: Mon, 21 Sep 2020 16:42:00 +0200 Subject: [PATCH 5/6] fixes --- sentry-anyhow/src/lib.rs | 2 +- sentry-core/src/clientoptions.rs | 2 +- sentry-core/src/test.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) 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-core/src/clientoptions.rs b/sentry-core/src/clientoptions.rs index 2f8a9196..acd55f05 100644 --- a/sentry-core/src/clientoptions.rs +++ b/sentry-core/src/clientoptions.rs @@ -23,7 +23,7 @@ pub type BeforeCallback = Arc Option + Send + Sync>; /// ``` /// let _options = sentry::ClientOptions::configure(|o| { /// o.set_debug(true) -/// ); +/// }); /// ``` #[derive(Clone)] pub struct ClientOptions { diff --git a/sentry-core/src/test.rs b/sentry-core/src/test.rs index 361d0b64..002b0493 100644 --- a/sentry-core/src/test.rs +++ b/sentry-core/src/test.rs @@ -40,7 +40,7 @@ lazy_static::lazy_static! { /// /// let transport = TestTransport::new(); /// let options = ClientOptions::configure(|o| { -/// o.set_dsn(("https://public@example.com/1".parse().unwrap()) +/// o.set_dsn("https://public@example.com/1".parse().unwrap()) /// .set_transport(transport.clone()) /// }); /// Hub::current().bind_client(Some(Arc::new(options.into()))); From 10d77449dd4ec4f81bb8e139d56e38fdca312b1e Mon Sep 17 00:00:00 2001 From: Arpad Borsos Date: Mon, 21 Sep 2020 16:44:23 +0200 Subject: [PATCH 6/6] one more --- sentry-core/src/client.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sentry-core/src/client.rs b/sentry-core/src/client.rs index 3370e3ea..5b93f7db 100644 --- a/sentry-core/src/client.rs +++ b/sentry-core/src/client.rs @@ -144,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); } @@ -194,7 +196,6 @@ impl Client { event.platform = "native".into(); } - #[allow(deprecated)] if let Some(ref func) = self.options.before_send { sentry_debug!("invoking before_send callback"); let id = event.event_id;