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.
103 pub debug: bool,
104 /// The release to be sent with events.
105 pub release: Option<Cow<'static, str>>,
106 /// The environment to be sent with events.
107 ///
108 /// Defaults to either `"development"` or `"production"` depending on the
109 /// `debug_assertions` cfg-attribute.
110 pub environment: Option<Cow<'static, str>>,
111 /// The sample rate for event submission. (0.0 - 1.0, defaults to 1.0)
112 pub sample_rate: f32,
113 /// The sample rate for tracing transactions. (0.0 - 1.0, defaults to 0.0)
114 pub traces_sample_rate: f32,
115 /// If given, called with a SamplingContext for each transaction to determine the sampling rate.
116 ///
117 /// Return a sample rate between 0.0 and 1.0 for the transaction in question.
118 /// Takes priority over the `sample_rate`.
119 pub traces_sampler: Option<Arc<TracesSampler>>,
120 /// Maximum number of breadcrumbs. (defaults to 100)
121 pub max_breadcrumbs: usize,
122 /// Attaches stacktraces to messages.
123 pub attach_stacktrace: bool,
124 /// 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.
125 pub send_default_pii: bool,
126 /// The server name to be reported.
127 pub server_name: Option<Cow<'static, str>>,
128 /// Module prefixes that are always considered "in_app".
129 pub in_app_include: Vec<&'static str>,
130 /// Module prefixes that are never "in_app".
131 pub in_app_exclude: Vec<&'static str>,
132 // Integration options
133 /// A list of integrations to enable.
134 ///
135 /// See [`sentry::integrations`](integrations/index.html#installing-integrations) for
136 /// how to use this to enable extra integrations.
137 pub integrations: Vec<Arc<dyn Integration>>,
138 /// Whether to add default integrations.
139 ///
140 /// See [`sentry::integrations`](integrations/index.html#default-integrations) for
141 /// details how this works and interacts with manually installed integrations.
142 pub default_integrations: bool,
143 // Hooks
144 /// Callback that is executed before event sending.
145 pub before_send: Option<BeforeCallback<Event<'static>>>,
146 /// Callback that is executed for each Breadcrumb being added.
147 pub before_breadcrumb: Option<BeforeCallback<Breadcrumb>>,
148 /// Callback that is executed for each Log being added.
149 #[cfg(feature = "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 #[cfg(feature = "logs")]
174 pub enable_logs: bool,
175 // Other options not documented in Unified API
176 /// Disable SSL verification.
177 ///
178 /// # Warning
179 ///
180 /// This introduces significant vulnerabilities, and should only be used as a last resort.
181 pub accept_invalid_certs: bool,
182 /// Enable Release Health Session tracking.
183 ///
184 /// When automatic session tracking is enabled, a new "user-mode" session
185 /// is started at the time of `sentry::init`, and will persist for the
186 /// application lifetime.
187 #[cfg(feature = "release-health")]
188 pub auto_session_tracking: bool,
189 /// Determine how Sessions are being tracked.
190 #[cfg(feature = "release-health")]
191 pub session_mode: SessionMode,
192 /// Border frames which indicate a border from a backtrace to
193 /// useless internals. Some are automatically included.
194 pub extra_border_frames: Vec<&'static str>,
195 /// Automatically trim backtraces of junk before sending. (defaults to true)
196 pub trim_backtraces: bool,
197 /// The user agent that should be reported.
198 pub user_agent: Cow<'static, str>,
199}
200
201impl ClientOptions {
202 /// Creates new Options.
203 pub fn new() -> Self {
204 Self::default()
205 }
206
207 /// Adds a configured integration to the options.
208 ///
209 /// # Examples
210 ///
211 /// ```
212 /// struct MyIntegration;
213 ///
214 /// impl sentry::Integration for MyIntegration {}
215 ///
216 /// let options = sentry::ClientOptions::new().add_integration(MyIntegration);
217 /// assert_eq!(options.integrations.len(), 1);
218 /// ```
219 #[must_use]
220 pub fn add_integration<I: Integration>(mut self, integration: I) -> Self {
221 self.integrations.push(Arc::new(integration));
222 self
223 }
224}
225
226impl fmt::Debug for ClientOptions {
227 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
228 #[derive(Debug)]
229 struct BeforeSend;
230 let before_send = self.before_send.as_ref().map(|_| BeforeSend);
231 #[derive(Debug)]
232 struct BeforeBreadcrumb;
233 let before_breadcrumb = self.before_breadcrumb.as_ref().map(|_| BeforeBreadcrumb);
234 #[cfg(feature = "logs")]
235 let before_send_log = {
236 #[derive(Debug)]
237 struct BeforeSendLog;
238 self.before_send_log.as_ref().map(|_| BeforeSendLog)
239 };
240 #[derive(Debug)]
241 struct TransportFactory;
242
243 let integrations: Vec<_> = self.integrations.iter().map(|i| i.name()).collect();
244
245 let mut debug_struct = f.debug_struct("ClientOptions");
246 debug_struct
247 .field("dsn", &self.dsn)
248 .field("debug", &self.debug)
249 .field("release", &self.release)
250 .field("environment", &self.environment)
251 .field("sample_rate", &self.sample_rate)
252 .field("traces_sample_rate", &self.traces_sample_rate)
253 .field(
254 "traces_sampler",
255 &self
256 .traces_sampler
257 .as_ref()
258 .map(|arc| std::ptr::addr_of!(**arc)),
259 )
260 .field("max_breadcrumbs", &self.max_breadcrumbs)
261 .field("attach_stacktrace", &self.attach_stacktrace)
262 .field("send_default_pii", &self.send_default_pii)
263 .field("server_name", &self.server_name)
264 .field("in_app_include", &self.in_app_include)
265 .field("in_app_exclude", &self.in_app_exclude)
266 .field("integrations", &integrations)
267 .field("default_integrations", &self.default_integrations)
268 .field("before_send", &before_send)
269 .field("before_breadcrumb", &before_breadcrumb)
270 .field("transport", &TransportFactory)
271 .field("http_proxy", &self.http_proxy)
272 .field("https_proxy", &self.https_proxy)
273 .field("shutdown_timeout", &self.shutdown_timeout)
274 .field("accept_invalid_certs", &self.accept_invalid_certs);
275
276 #[cfg(feature = "release-health")]
277 debug_struct
278 .field("auto_session_tracking", &self.auto_session_tracking)
279 .field("session_mode", &self.session_mode);
280
281 #[cfg(feature = "logs")]
282 debug_struct
283 .field("enable_logs", &self.enable_logs)
284 .field("before_send_log", &before_send_log);
285
286 debug_struct
287 .field("extra_border_frames", &self.extra_border_frames)
288 .field("trim_backtraces", &self.trim_backtraces)
289 .field("user_agent", &self.user_agent)
290 .finish()
291 }
292}
293
294impl Default for ClientOptions {
295 fn default() -> ClientOptions {
296 ClientOptions {
297 dsn: None,
298 debug: false,
299 release: None,
300 environment: None,
301 sample_rate: 1.0,
302 traces_sample_rate: 0.0,
303 traces_sampler: None,
304 max_breadcrumbs: 100,
305 attach_stacktrace: false,
306 send_default_pii: false,
307 server_name: None,
308 in_app_include: vec![],
309 in_app_exclude: vec![],
310 integrations: vec![],
311 default_integrations: true,
312 before_send: None,
313 before_breadcrumb: None,
314 transport: None,
315 http_proxy: None,
316 https_proxy: None,
317 shutdown_timeout: Duration::from_secs(2),
318 accept_invalid_certs: false,
319 #[cfg(feature = "release-health")]
320 auto_session_tracking: false,
321 #[cfg(feature = "release-health")]
322 session_mode: SessionMode::Application,
323 extra_border_frames: vec![],
324 trim_backtraces: true,
325 user_agent: Cow::Borrowed(USER_AGENT),
326 max_request_body_size: MaxRequestBodySize::Medium,
327 #[cfg(feature = "logs")]
328 enable_logs: true,
329 #[cfg(feature = "logs")]
330 before_send_log: None,
331 }
332 }
333}
334
335impl<T: IntoDsn> From<(T, ClientOptions)> for ClientOptions {
336 fn from((into_dsn, mut opts): (T, ClientOptions)) -> ClientOptions {
337 opts.dsn = into_dsn.into_dsn().expect("invalid value for DSN");
338 opts
339 }
340}
341
342impl<T: IntoDsn> From<T> for ClientOptions {
343 fn from(into_dsn: T) -> ClientOptions {
344 ClientOptions {
345 dsn: into_dsn.into_dsn().expect("invalid value for DSN"),
346 ..ClientOptions::default()
347 }
348 }
349}