Skip to main content

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