sentry_core/
clientoptions.rs

1use std::borrow::Cow;
2use std::fmt;
3use std::sync::Arc;
4use std::time::Duration;
5
6use crate::constants::USER_AGENT;
7use crate::performance::TracesSampler;
8#[cfg(feature = "logs")]
9use crate::protocol::Log;
10use crate::protocol::{Breadcrumb, Event};
11use crate::types::Dsn;
12use crate::{Integration, IntoDsn, TransportFactory};
13
14/// Type alias for before event/breadcrumb handlers.
15pub type BeforeCallback<T> = Arc<dyn Fn(T) -> Option<T> + Send + Sync>;
16
17/// The Session Mode of the SDK.
18///
19/// Depending on the use-case, the SDK can be set to two different session modes:
20///
21/// * **Application Mode Sessions**:
22///   This mode should be used for user-attended programs, which typically have
23///   a single long running session that span the applications' lifetime.
24///
25/// * **Request Mode Sessions**:
26///   This mode is intended for servers that use one session per incoming
27///   request, and thus have a lot of very short lived sessions.
28///
29/// Setting the SDK to *request-mode* sessions means that session durations will
30/// not be tracked, and sessions will be pre-aggregated before being sent upstream.
31/// This applies both to automatic and manually triggered sessions.
32///
33/// **NOTE**: Support for *request-mode* sessions was added in Sentry `21.2`.
34///
35/// See the [Documentation on Session Modes](https://develop.sentry.dev/sdk/sessions/#sdk-considerations)
36/// for more information.
37///
38/// **NOTE**: The `release-health` feature (enabled by default) needs to be enabled for this option to have
39/// any effect.
40#[derive(Copy, Clone, Debug, PartialEq, Eq)]
41pub enum SessionMode {
42    /// Long running application session.
43    Application,
44    /// Lots of short per-request sessions.
45    Request,
46}
47
48/// The maximum size of an HTTP request body that the SDK captures.
49///
50/// Only request bodies that parse as JSON or form data are currently captured.
51/// See the [Documentation on attaching request body](https://develop.sentry.dev/sdk/expected-features/#attaching-request-body-in-server-sdks)
52/// and the [Documentation on handling sensitive data](https://develop.sentry.dev/sdk/expected-features/data-handling/#sensitive-data)
53/// for more information.
54#[derive(Clone, Copy, PartialEq)]
55pub enum MaxRequestBodySize {
56    /// Don't capture request body
57    None,
58    /// Capture up to 1000 bytes
59    Small,
60    /// Capture up to 10000 bytes
61    Medium,
62    /// Capture entire body
63    Always,
64    /// Capture up to a specific size
65    Explicit(usize),
66}
67
68impl MaxRequestBodySize {
69    /// Check if the content length is within the size limit.
70    pub fn is_within_size_limit(&self, content_length: usize) -> bool {
71        match self {
72            MaxRequestBodySize::None => false,
73            MaxRequestBodySize::Small => content_length <= 1_000,
74            MaxRequestBodySize::Medium => content_length <= 10_000,
75            MaxRequestBodySize::Always => true,
76            MaxRequestBodySize::Explicit(size) => content_length <= *size,
77        }
78    }
79}
80
81/// Configuration settings for the client.
82///
83/// These options are explained in more detail in the general
84/// [sentry documentation](https://docs.sentry.io/error-reporting/configuration/?platform=rust).
85///
86/// # Examples
87///
88/// ```
89/// let _options = sentry::ClientOptions {
90///     debug: true,
91///     ..Default::default()
92/// };
93/// ```
94#[derive(Clone)]
95pub struct ClientOptions {
96    // Common options
97    /// The DSN to use.  If not set the client is effectively disabled.
98    pub dsn: Option<Dsn>,
99    /// Enables debug mode.
100    ///
101    /// In debug mode debug information is printed to stderr to help you understand what
102    /// sentry is doing.  When the `log` feature is enabled, Sentry will instead
103    /// log to the `sentry` logger independently of this flag with the `Debug` level.
104    pub debug: bool,
105    /// The release to be sent with events.
106    pub release: Option<Cow<'static, str>>,
107    /// The environment to be sent with events.
108    ///
109    /// Defaults to either `"development"` or `"production"` depending on the
110    /// `debug_assertions` cfg-attribute.
111    pub environment: Option<Cow<'static, str>>,
112    /// The sample rate for event submission. (0.0 - 1.0, defaults to 1.0)
113    pub sample_rate: f32,
114    /// The sample rate for tracing transactions. (0.0 - 1.0, defaults to 0.0)
115    pub traces_sample_rate: f32,
116    /// If given, called with a SamplingContext for each transaction to determine the sampling rate.
117    ///
118    /// Return a sample rate between 0.0 and 1.0 for the transaction in question.
119    /// Takes priority over the `sample_rate`.
120    pub traces_sampler: Option<Arc<TracesSampler>>,
121    /// Maximum number of breadcrumbs. (defaults to 100)
122    pub max_breadcrumbs: usize,
123    /// Attaches stacktraces to messages.
124    pub attach_stacktrace: bool,
125    /// If turned on, some information that can be considered PII is captured, such as potentially sensitive HTTP headers and user IP address in HTTP server integrations.
126    pub send_default_pii: bool,
127    /// The server name to be reported.
128    pub server_name: Option<Cow<'static, str>>,
129    /// Module prefixes that are always considered "in_app".
130    pub in_app_include: Vec<&'static str>,
131    /// Module prefixes that are never "in_app".
132    pub in_app_exclude: Vec<&'static str>,
133    // Integration options
134    /// A list of integrations to enable.
135    ///
136    /// See [`sentry::integrations`](integrations/index.html#installing-integrations) for
137    /// how to use this to enable extra integrations.
138    pub integrations: Vec<Arc<dyn Integration>>,
139    /// Whether to add default integrations.
140    ///
141    /// See [`sentry::integrations`](integrations/index.html#default-integrations) for
142    /// details how this works and interacts with manually installed integrations.
143    pub default_integrations: bool,
144    // Hooks
145    /// Callback that is executed before event sending.
146    pub before_send: Option<BeforeCallback<Event<'static>>>,
147    /// Callback that is executed for each Breadcrumb being added.
148    pub before_breadcrumb: Option<BeforeCallback<Breadcrumb>>,
149    /// Callback that is executed for each Log being added.
150    #[cfg(feature = "logs")]
151    pub before_send_log: Option<BeforeCallback<Log>>,
152    // Transport options
153    /// The transport to use.
154    ///
155    /// This is typically either a boxed function taking the client options by
156    /// reference and returning a `Transport`, a boxed `Arc<Transport>` or
157    /// alternatively the `DefaultTransportFactory`.
158    pub transport: Option<Arc<dyn TransportFactory>>,
159    /// An optional HTTP proxy to use.
160    ///
161    /// This will default to the `http_proxy` environment variable.
162    pub http_proxy: Option<Cow<'static, str>>,
163    /// An optional HTTPS proxy to use.
164    ///
165    /// This will default to the `HTTPS_PROXY` environment variable
166    /// or `http_proxy` if that one exists.
167    pub https_proxy: Option<Cow<'static, str>>,
168    /// The timeout on client drop for draining events on shutdown.
169    pub shutdown_timeout: Duration,
170    /// Controls the maximum size of an HTTP request body that can be captured when using HTTP
171    /// server integrations. Needs `send_default_pii` to be enabled to have any effect.
172    pub max_request_body_size: MaxRequestBodySize,
173    /// Determines whether captured structured logs should be sent to Sentry (defaults to false).
174    #[cfg(feature = "logs")]
175    pub enable_logs: bool,
176    // Other options not documented in Unified API
177    /// Disable SSL verification.
178    ///
179    /// # Warning
180    ///
181    /// This introduces significant vulnerabilities, and should only be used as a last resort.
182    pub accept_invalid_certs: bool,
183    /// Enable Release Health Session tracking.
184    ///
185    /// When automatic session tracking is enabled, a new "user-mode" session
186    /// is started at the time of `sentry::init`, and will persist for the
187    /// application lifetime.
188    #[cfg(feature = "release-health")]
189    pub auto_session_tracking: bool,
190    /// Determine how Sessions are being tracked.
191    #[cfg(feature = "release-health")]
192    pub session_mode: SessionMode,
193    /// Border frames which indicate a border from a backtrace to
194    /// useless internals. Some are automatically included.
195    pub extra_border_frames: Vec<&'static str>,
196    /// Automatically trim backtraces of junk before sending. (defaults to true)
197    pub trim_backtraces: bool,
198    /// The user agent that should be reported.
199    pub user_agent: Cow<'static, str>,
200}
201
202impl ClientOptions {
203    /// Creates new Options.
204    pub fn new() -> Self {
205        Self::default()
206    }
207
208    /// Adds a configured integration to the options.
209    ///
210    /// # Examples
211    ///
212    /// ```
213    /// struct MyIntegration;
214    ///
215    /// impl sentry::Integration for MyIntegration {}
216    ///
217    /// let options = sentry::ClientOptions::new().add_integration(MyIntegration);
218    /// assert_eq!(options.integrations.len(), 1);
219    /// ```
220    #[must_use]
221    pub fn add_integration<I: Integration>(mut self, integration: I) -> Self {
222        self.integrations.push(Arc::new(integration));
223        self
224    }
225}
226
227impl fmt::Debug for ClientOptions {
228    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
229        #[derive(Debug)]
230        struct BeforeSend;
231        let before_send = self.before_send.as_ref().map(|_| BeforeSend);
232        #[derive(Debug)]
233        struct BeforeBreadcrumb;
234        let before_breadcrumb = self.before_breadcrumb.as_ref().map(|_| BeforeBreadcrumb);
235        #[cfg(feature = "logs")]
236        let before_send_log = {
237            #[derive(Debug)]
238            struct BeforeSendLog;
239            self.before_send_log.as_ref().map(|_| BeforeSendLog)
240        };
241        #[derive(Debug)]
242        struct TransportFactory;
243
244        let integrations: Vec<_> = self.integrations.iter().map(|i| i.name()).collect();
245
246        let mut debug_struct = f.debug_struct("ClientOptions");
247        debug_struct
248            .field("dsn", &self.dsn)
249            .field("debug", &self.debug)
250            .field("release", &self.release)
251            .field("environment", &self.environment)
252            .field("sample_rate", &self.sample_rate)
253            .field("traces_sample_rate", &self.traces_sample_rate)
254            .field(
255                "traces_sampler",
256                &self
257                    .traces_sampler
258                    .as_ref()
259                    .map(|arc| std::ptr::addr_of!(**arc)),
260            )
261            .field("max_breadcrumbs", &self.max_breadcrumbs)
262            .field("attach_stacktrace", &self.attach_stacktrace)
263            .field("send_default_pii", &self.send_default_pii)
264            .field("server_name", &self.server_name)
265            .field("in_app_include", &self.in_app_include)
266            .field("in_app_exclude", &self.in_app_exclude)
267            .field("integrations", &integrations)
268            .field("default_integrations", &self.default_integrations)
269            .field("before_send", &before_send)
270            .field("before_breadcrumb", &before_breadcrumb)
271            .field("transport", &TransportFactory)
272            .field("http_proxy", &self.http_proxy)
273            .field("https_proxy", &self.https_proxy)
274            .field("shutdown_timeout", &self.shutdown_timeout)
275            .field("accept_invalid_certs", &self.accept_invalid_certs);
276
277        #[cfg(feature = "release-health")]
278        debug_struct
279            .field("auto_session_tracking", &self.auto_session_tracking)
280            .field("session_mode", &self.session_mode);
281
282        #[cfg(feature = "logs")]
283        debug_struct
284            .field("enable_logs", &self.enable_logs)
285            .field("before_send_log", &before_send_log);
286
287        debug_struct
288            .field("extra_border_frames", &self.extra_border_frames)
289            .field("trim_backtraces", &self.trim_backtraces)
290            .field("user_agent", &self.user_agent)
291            .finish()
292    }
293}
294
295impl Default for ClientOptions {
296    fn default() -> ClientOptions {
297        ClientOptions {
298            dsn: None,
299            debug: false,
300            release: None,
301            environment: None,
302            sample_rate: 1.0,
303            traces_sample_rate: 0.0,
304            traces_sampler: None,
305            max_breadcrumbs: 100,
306            attach_stacktrace: false,
307            send_default_pii: false,
308            server_name: None,
309            in_app_include: vec![],
310            in_app_exclude: vec![],
311            integrations: vec![],
312            default_integrations: true,
313            before_send: None,
314            before_breadcrumb: None,
315            transport: None,
316            http_proxy: None,
317            https_proxy: None,
318            shutdown_timeout: Duration::from_secs(2),
319            accept_invalid_certs: false,
320            #[cfg(feature = "release-health")]
321            auto_session_tracking: false,
322            #[cfg(feature = "release-health")]
323            session_mode: SessionMode::Application,
324            extra_border_frames: vec![],
325            trim_backtraces: true,
326            user_agent: Cow::Borrowed(USER_AGENT),
327            max_request_body_size: MaxRequestBodySize::Medium,
328            #[cfg(feature = "logs")]
329            enable_logs: false,
330            #[cfg(feature = "logs")]
331            before_send_log: None,
332        }
333    }
334}
335
336impl<T: IntoDsn> From<(T, ClientOptions)> for ClientOptions {
337    fn from((into_dsn, mut opts): (T, ClientOptions)) -> ClientOptions {
338        opts.dsn = into_dsn.into_dsn().expect("invalid value for DSN");
339        opts
340    }
341}
342
343impl<T: IntoDsn> From<T> for ClientOptions {
344    fn from(into_dsn: T) -> ClientOptions {
345        ClientOptions {
346            dsn: into_dsn.into_dsn().expect("invalid value for DSN"),
347            ..ClientOptions::default()
348        }
349    }
350}