1 use std::borrow::Cow;
2 use std::fmt;
3 use std::sync::Arc;
4 use std::time::Duration;
5 
6 use crate::constants::USER_AGENT;
7 use crate::protocol::{Breadcrumb, Event};
8 use crate::types::Dsn;
9 use crate::{Integration, IntoDsn, TransportFactory};
10 
11 /// Type alias for before event/breadcrumb handlers.
12 pub type BeforeCallback<T> = Arc<dyn Fn(T) -> Option<T> + Send + Sync>;
13 
14 /// The Session Mode of the SDK.
15 ///
16 /// Depending on the use-case, the SDK can be set to two different session modes:
17 ///
18 /// * **Application Mode Sessions**:
19 ///   This mode should be used for user-attended programs, which typically have
20 ///   a single long running session that span the applications' lifetime.
21 ///
22 /// * **Request Mode Sessions**:
23 ///   This mode is intended for servers that use one session per incoming
24 ///   request, and thus have a lot of very short lived sessions.
25 ///
26 /// Setting the SDK to *request-mode* sessions means that session durations will
27 /// not be tracked, and sessions will be pre-aggregated before being sent upstream.
28 /// This applies both to automatic and manually triggered sessions.
29 ///
30 /// **NOTE**: Support for *request-mode* sessions was added in Sentry `21.2`.
31 ///
32 /// See the [Documentation on Session Modes](https://develop.sentry.dev/sdk/sessions/#sdk-considerations)
33 /// for more information.
34 #[derive(Copy, Clone, Debug, PartialEq)]
35 pub enum SessionMode {
36     /// Long running application session.
37     Application,
38     /// Lots of short per-request sessions.
39     Request,
40 }
41 
42 /// Configuration settings for the client.
43 ///
44 /// These options are explained in more detail in the general
45 /// [sentry documentation](https://docs.sentry.io/error-reporting/configuration/?platform=rust).
46 ///
47 /// # Examples
48 ///
49 /// ```
50 /// let _options = sentry::ClientOptions {
51 ///     debug: true,
52 ///     ..Default::default()
53 /// };
54 /// ```
55 #[derive(Clone)]
56 pub struct ClientOptions {
57     // Common options
58     /// The DSN to use.  If not set the client is effectively disabled.
59     pub dsn: Option<Dsn>,
60     /// Enables debug mode.
61     ///
62     /// In debug mode debug information is printed to stderr to help you understand what
63     /// sentry is doing.  When the `log` feature is enabled, Sentry will instead
64     /// log to the `sentry` logger independently of this flag with the `Debug` level.
65     pub debug: bool,
66     /// The release to be sent with events.
67     pub release: Option<Cow<'static, str>>,
68     /// The environment to be sent with events.
69     ///
70     /// Defaults to either `"development"` or `"production"` depending on the
71     /// `debug_assertions` cfg-attribute.
72     pub environment: Option<Cow<'static, str>>,
73     /// The sample rate for event submission. (0.0 - 1.0, defaults to 1.0)
74     pub sample_rate: f32,
75     /// Maximum number of breadcrumbs. (defaults to 100)
76     pub max_breadcrumbs: usize,
77     /// Attaches stacktraces to messages.
78     pub attach_stacktrace: bool,
79     /// If turned on some default PII informat is attached.
80     pub send_default_pii: bool,
81     /// The server name to be reported.
82     pub server_name: Option<Cow<'static, str>>,
83     /// Module prefixes that are always considered "in_app".
84     pub in_app_include: Vec<&'static str>,
85     /// Module prefixes that are never "in_app".
86     pub in_app_exclude: Vec<&'static str>,
87     // Integration options
88     /// A list of integrations to enable.
89     ///
90     /// See [`sentry::integrations`](integrations/index.html#installing-integrations) for
91     /// how to use this to enable extra integrations.
92     pub integrations: Vec<Arc<dyn Integration>>,
93     /// Whether to add default integrations.
94     ///
95     /// See [`sentry::integrations`](integrations/index.html#default-integrations) for
96     /// details how this works and interacts with manually installed integrations.
97     pub default_integrations: bool,
98     // Hooks
99     /// Callback that is executed before event sending.
100     pub before_send: Option<BeforeCallback<Event<'static>>>,
101     /// Callback that is executed for each Breadcrumb being added.
102     pub before_breadcrumb: Option<BeforeCallback<Breadcrumb>>,
103     // Transport options
104     /// The transport to use.
105     ///
106     /// This is typically either a boxed function taking the client options by
107     /// reference and returning a `Transport`, a boxed `Arc<Transport>` or
108     /// alternatively the `DefaultTransportFactory`.
109     pub transport: Option<Arc<dyn TransportFactory>>,
110     /// An optional HTTP proxy to use.
111     ///
112     /// This will default to the `http_proxy` environment variable.
113     pub http_proxy: Option<Cow<'static, str>>,
114     /// An optional HTTPS proxy to use.
115     ///
116     /// This will default to the `HTTPS_PROXY` environment variable
117     /// or `http_proxy` if that one exists.
118     pub https_proxy: Option<Cow<'static, str>>,
119     /// The timeout on client drop for draining events on shutdown.
120     pub shutdown_timeout: Duration,
121     // Other options not documented in Unified API
122     /// Enable Release Health Session tracking.
123     ///
124     /// When automatic session tracking is enabled, a new "user-mode" session
125     /// is started at the time of `sentry::init`, and will persist for the
126     /// application lifetime.
127     pub auto_session_tracking: bool,
128     /// Determine how Sessions are being tracked.
129     pub session_mode: SessionMode,
130     /// Border frames which indicate a border from a backtrace to
131     /// useless internals. Some are automatically included.
132     pub extra_border_frames: Vec<&'static str>,
133     /// Automatically trim backtraces of junk before sending. (defaults to true)
134     pub trim_backtraces: bool,
135     /// The user agent that should be reported.
136     pub user_agent: Cow<'static, str>,
137 }
138 
139 impl ClientOptions {
140     /// Creates new Options.
new() -> Self141     pub fn new() -> Self {
142         Self::default()
143     }
144 
145     /// Adds a configured integration to the options.
146     ///
147     /// # Examples
148     ///
149     /// ```
150     /// struct MyIntegration;
151     ///
152     /// impl sentry::Integration for MyIntegration {}
153     ///
154     /// let options = sentry::ClientOptions::new().add_integration(MyIntegration);
155     /// assert_eq!(options.integrations.len(), 1);
156     /// ```
add_integration<I: Integration>(mut self, integration: I) -> Self157     pub fn add_integration<I: Integration>(mut self, integration: I) -> Self {
158         self.integrations.push(Arc::new(integration));
159         self
160     }
161 }
162 
163 impl fmt::Debug for ClientOptions {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result164     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
165         #[derive(Debug)]
166         struct BeforeSend;
167         let before_send = self.before_send.as_ref().map(|_| BeforeSend);
168         #[derive(Debug)]
169         struct BeforeBreadcrumb;
170         let before_breadcrumb = self.before_breadcrumb.as_ref().map(|_| BeforeBreadcrumb);
171         #[derive(Debug)]
172         struct TransportFactory;
173 
174         let integrations: Vec<_> = self.integrations.iter().map(|i| i.name()).collect();
175 
176         f.debug_struct("ClientOptions")
177             .field("dsn", &self.dsn)
178             .field("debug", &self.debug)
179             .field("release", &self.release)
180             .field("environment", &self.environment)
181             .field("sample_rate", &self.sample_rate)
182             .field("max_breadcrumbs", &self.max_breadcrumbs)
183             .field("attach_stacktrace", &self.attach_stacktrace)
184             .field("send_default_pii", &self.send_default_pii)
185             .field("server_name", &self.server_name)
186             .field("in_app_include", &self.in_app_include)
187             .field("in_app_exclude", &self.in_app_exclude)
188             .field("integrations", &integrations)
189             .field("default_integrations", &self.default_integrations)
190             .field("before_send", &before_send)
191             .field("before_breadcrumb", &before_breadcrumb)
192             .field("transport", &TransportFactory)
193             .field("http_proxy", &self.http_proxy)
194             .field("https_proxy", &self.https_proxy)
195             .field("shutdown_timeout", &self.shutdown_timeout)
196             .field("auto_session_tracking", &self.auto_session_tracking)
197             .field("session_mode", &self.session_mode)
198             .field("extra_border_frames", &self.extra_border_frames)
199             .field("trim_backtraces", &self.trim_backtraces)
200             .field("user_agent", &self.user_agent)
201             .finish()
202     }
203 }
204 
205 impl Default for ClientOptions {
default() -> ClientOptions206     fn default() -> ClientOptions {
207         ClientOptions {
208             dsn: None,
209             debug: false,
210             release: None,
211             environment: None,
212             sample_rate: 1.0,
213             max_breadcrumbs: 100,
214             attach_stacktrace: false,
215             send_default_pii: false,
216             server_name: None,
217             in_app_include: vec![],
218             in_app_exclude: vec![],
219             integrations: vec![],
220             default_integrations: true,
221             before_send: None,
222             before_breadcrumb: None,
223             transport: None,
224             http_proxy: None,
225             https_proxy: None,
226             shutdown_timeout: Duration::from_secs(2),
227             auto_session_tracking: false,
228             session_mode: SessionMode::Application,
229             extra_border_frames: vec![],
230             trim_backtraces: true,
231             user_agent: Cow::Borrowed(&USER_AGENT),
232         }
233     }
234 }
235 
236 impl<T: IntoDsn> From<(T, ClientOptions)> for ClientOptions {
from((into_dsn, mut opts): (T, ClientOptions)) -> ClientOptions237     fn from((into_dsn, mut opts): (T, ClientOptions)) -> ClientOptions {
238         opts.dsn = into_dsn.into_dsn().expect("invalid value for DSN");
239         opts
240     }
241 }
242 
243 impl<T: IntoDsn> From<T> for ClientOptions {
from(into_dsn: T) -> ClientOptions244     fn from(into_dsn: T) -> ClientOptions {
245         ClientOptions {
246             dsn: into_dsn.into_dsn().expect("invalid value for DSN"),
247             ..ClientOptions::default()
248         }
249     }
250 }
251