sentry_core/clientoptions.rs
1use std::borrow::Cow;
2use std::fmt;
3use std::num::NonZeroUsize;
4use std::sync::Arc;
5use std::time::Duration;
6
7use crate::constants::USER_AGENT;
8use crate::performance::{TracesSampler, TransactionContext};
9use crate::protocol::{Breadcrumb, Event, Log, Metric, OrganizationId};
10use crate::types::Dsn;
11use crate::{Integration, IntoDsn, TransportFactory};
12
13/// Type alias for before event/breadcrumb handlers.
14pub type BeforeCallback<T> = Arc<dyn Fn(T) -> Option<T> + Send + Sync>;
15
16/// The Session Mode of the SDK.
17///
18/// Depending on the use-case, the SDK can be set to two different session modes:
19///
20/// * **Application Mode Sessions**:
21/// This mode should be used for user-attended programs, which typically have
22/// a single long running session that span the applications' lifetime.
23///
24/// * **Request Mode Sessions**:
25/// This mode is intended for servers that use one session per incoming
26/// request, and thus have a lot of very short lived sessions.
27///
28/// Setting the SDK to *request-mode* sessions means that session durations will
29/// not be tracked, and sessions will be pre-aggregated before being sent upstream.
30/// This applies both to automatic and manually triggered sessions.
31///
32/// **NOTE**: Support for *request-mode* sessions was added in Sentry `21.2`.
33///
34/// See the
35/// [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
39/// option to have 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 Sentry documentation on [attaching request bodies] and [handling sensitive data] for
52/// more information.
53///
54/// [attaching request bodies]: https://develop.sentry.dev/sdk/expected-features/#attaching-request-body-in-server-sdks
55/// [handling sensitive data]: https://develop.sentry.dev/sdk/expected-features/data-handling/#sensitive-data
56#[derive(Clone, Copy, PartialEq)]
57pub enum MaxRequestBodySize {
58 /// Don't capture request body
59 None,
60 /// Capture up to 1000 bytes
61 Small,
62 /// Capture up to 10000 bytes
63 Medium,
64 /// Capture entire body
65 Always,
66 /// Capture up to a specific size
67 Explicit(usize),
68}
69
70impl MaxRequestBodySize {
71 /// Check if the content length is within the size limit.
72 pub fn is_within_size_limit(&self, content_length: usize) -> bool {
73 match self {
74 MaxRequestBodySize::None => false,
75 MaxRequestBodySize::Small => content_length <= 1_000,
76 MaxRequestBodySize::Medium => content_length <= 10_000,
77 MaxRequestBodySize::Always => true,
78 MaxRequestBodySize::Explicit(size) => content_length <= *size,
79 }
80 }
81}
82
83/// Defines how traces should be sampled.
84///
85/// Leaving this at [`Disabled`](Self::Disabled) is distinct from explicitly configuring
86/// [`FixedRate`](Self::FixedRate) with a rate of `0.0`. Both disable local transaction sampling
87/// when there is no parent sampling decision, but an explicit fixed-rate strategy can still honor
88/// an inherited sampling decision.
89#[derive(Clone, Default)]
90#[non_exhaustive]
91pub enum TracesSamplingStrategy {
92 /// Sample the trace at a fixed sample rate. The rate should be between 0.0 and 1.0, inclusive.
93 FixedRate(f32),
94 /// Sample the traces using a [`TracesSampler`] function.
95 Function(Arc<TracesSampler>),
96 /// Disable tracing.
97 #[default]
98 Disabled,
99}
100
101impl fmt::Debug for TracesSamplingStrategy {
102 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
103 match self {
104 Self::FixedRate(rate) => f.debug_tuple("FixedRate").field(rate).finish(),
105 Self::Function(callback) => f
106 .debug_tuple("Function")
107 .field(&format_args!("{:p}", Arc::as_ptr(callback)))
108 .finish(),
109 Self::Disabled => f.write_str("Disabled"),
110 }
111 }
112}
113
114/// The sampling strategy for events.
115///
116/// Currently, we only support fixed rates. This defaults to `Self::FixedRate(1.0)`.
117#[derive(Clone, Debug)]
118#[non_exhaustive]
119pub enum EventSamplingStrategy {
120 /// Sample events at a fixed sample rate. The rate should be between 0.0 and 1.0, inclusive.
121 FixedRate(f32),
122}
123
124impl Default for EventSamplingStrategy {
125 fn default() -> Self {
126 Self::FixedRate(1.0)
127 }
128}
129
130/// Configuration settings for the client.
131///
132/// These options are explained in more detail in the general
133/// [sentry documentation](https://docs.sentry.io/error-reporting/configuration/?platform=rust).
134///
135/// # Examples
136///
137/// ```
138/// let _options = sentry::ClientOptions::new().debug(true);
139/// ```
140#[derive(Clone)]
141#[must_use = "ClientOptions must be passed to sentry::init to have any effect"]
142#[non_exhaustive]
143pub struct ClientOptions {
144 // Common options
145 /// The DSN to use.
146 ///
147 /// See [`dsn`](method@ClientOptions::dsn) for details.
148 pub dsn: Option<Dsn>,
149 /// Enables debug mode.
150 ///
151 /// See [`debug`](method@ClientOptions::debug) for details.
152 pub debug: bool,
153 /// The release to be sent with events.
154 ///
155 /// See [`release`](method@ClientOptions::release) for details.
156 pub release: Option<Cow<'static, str>>,
157 /// The environment to be sent with events.
158 ///
159 /// See [`environment`](method@ClientOptions::environment) for details.
160 pub environment: Option<Cow<'static, str>>,
161 /// The sampling strategy for event submission.
162 ///
163 /// This can be set to with [`sample_rate`](method@ClientOptions::sample_rate).
164 pub event_sampling_strategy: EventSamplingStrategy,
165 /// The traces sampling strategy.
166 ///
167 /// This can be set to a fixed rate with
168 /// [`traces_sample_rate`](method@ClientOptions::traces_sample_rate), a function with
169 /// [`traces_sampler`](method@ClientOptions::traces_sampler), or can be left at the default
170 /// disabled value.
171 pub traces_sampling_strategy: TracesSamplingStrategy,
172 /// The organization ID used for trace continuation.
173 ///
174 /// See [`org_id`](method@ClientOptions::org_id) for details.
175 pub org_id: Option<OrganizationId>,
176 /// Enables strict trace continuation.
177 ///
178 /// See [`strict_trace_continuation`](method@ClientOptions::strict_trace_continuation) for
179 /// details.
180 pub strict_trace_continuation: bool,
181 /// Maximum number of breadcrumbs.
182 ///
183 /// See [`max_breadcrumbs`](method@ClientOptions::max_breadcrumbs) for details.
184 pub max_breadcrumbs: usize,
185 /// Attaches stacktraces to messages.
186 ///
187 /// See [`attach_stacktrace`](method@ClientOptions::attach_stacktrace) for details.
188 pub attach_stacktrace: bool,
189 /// Whether to send default PII.
190 ///
191 /// See [`send_default_pii`](method@ClientOptions::send_default_pii) for details.
192 pub send_default_pii: bool,
193 /// The server name to be reported.
194 ///
195 /// See [`server_name`](method@ClientOptions::server_name) for details.
196 pub server_name: Option<Cow<'static, str>>,
197 /// Module prefixes that are always considered "in_app".
198 ///
199 /// See [`in_app_include`](method@ClientOptions::in_app_include) for details.
200 pub in_app_include: Vec<&'static str>,
201 /// Module prefixes that are never "in_app".
202 ///
203 /// See [`in_app_exclude`](method@ClientOptions::in_app_exclude) for details.
204 pub in_app_exclude: Vec<&'static str>,
205 // Integration options
206 /// A list of integrations to enable.
207 ///
208 /// See [`integrations`](method@ClientOptions::integrations) and
209 /// [`add_integration`](method@ClientOptions::add_integration) for details.
210 pub integrations: Vec<Arc<dyn Integration>>,
211 /// Whether to add default integrations.
212 ///
213 /// See [`default_integrations`](method@ClientOptions::default_integrations) for details.
214 pub default_integrations: bool,
215 // Hooks
216 /// Callback that is executed before event sending.
217 ///
218 /// See [`before_send`](method@ClientOptions::before_send) for details.
219 pub before_send: Option<BeforeCallback<Event<'static>>>,
220 /// Callback that is executed for each Breadcrumb being added.
221 ///
222 /// See [`before_breadcrumb`](method@ClientOptions::before_breadcrumb) for details.
223 pub before_breadcrumb: Option<BeforeCallback<Breadcrumb>>,
224 /// Callback that is executed for each Log being added.
225 ///
226 /// See [`before_send_log`](method@ClientOptions::before_send_log) for details.
227 pub before_send_log: Option<BeforeCallback<Log>>,
228 // Transport options
229 /// The transport to use.
230 ///
231 /// See [`transport`](method@ClientOptions::transport) for details.
232 pub transport: Option<Arc<dyn TransportFactory>>,
233 /// An optional HTTP proxy to use.
234 ///
235 /// See [`http_proxy`](method@ClientOptions::http_proxy) for details.
236 pub http_proxy: Option<Cow<'static, str>>,
237 /// An optional HTTPS proxy to use.
238 ///
239 /// See [`https_proxy`](method@ClientOptions::https_proxy) for details.
240 pub https_proxy: Option<Cow<'static, str>>,
241 /// The timeout on client drop for draining events on shutdown.
242 ///
243 /// See [`shutdown_timeout`](method@ClientOptions::shutdown_timeout) for details.
244 pub shutdown_timeout: Duration,
245 /// The maximum size of an HTTP request body to capture.
246 ///
247 /// See [`max_request_body_size`](method@ClientOptions::max_request_body_size) for details.
248 pub max_request_body_size: MaxRequestBodySize,
249 /// The maximum number of commands the transport channel can queue.
250 ///
251 /// The channel primarily carries envelopes, which are sent to Sentry on a background thread.
252 /// If the channel is full — for example, in high-throughput scenarios — new envelopes are
253 /// dropped and recorded as queue-overflow client reports, so increasing this value trades
254 /// memory usage for reliability. Control commands, such as flushing and shutdown, also count
255 /// against this capacity.
256 ///
257 /// If left unset, each transport uses its own default. The current default is `30` for all
258 /// built-in transports, but this is subject to change.
259 ///
260 /// See [`transport_channel_capacity`](method@ClientOptions::transport_channel_capacity).
261 pub transport_channel_capacity: Option<NonZeroUsize>,
262 /// Deprecated. Setting this to `false` only disables automatic log capture by the
263 /// log-capturing integrations (`log` and `tracing` with the `logs` feature); it does not
264 /// disable logs captured manually via [`Hub::capture_log`](crate::Hub::capture_log) and the
265 /// `logger_*` macros. Defaults to `true`.
266 ///
267 /// To stop an integration from sending logs, use its own options to configure what it
268 /// captures.
269 #[deprecated = "logs captured manually are always sent; only automatic capture by integrations respects this option"]
270 pub enable_logs: bool,
271 /// Deprecated no-op. Metrics are always enabled, regardless of this option's value.
272 #[deprecated = "this option is a deprecated no-op"]
273 pub enable_metrics: bool,
274 /// Callback that is executed for each [`Metric`] before sending.
275 ///
276 /// See [`before_send_metric`](method@ClientOptions::before_send_metric) for details.
277 pub before_send_metric: Option<BeforeCallback<Metric>>,
278 // Other options not documented in Unified API
279 /// Whether to disable SSL verification.
280 ///
281 /// See [`accept_invalid_certs`](method@ClientOptions::accept_invalid_certs) for details.
282 pub accept_invalid_certs: bool,
283 /// Whether Release Health Session tracking is enabled.
284 ///
285 /// See [`auto_session_tracking`](method@ClientOptions::auto_session_tracking) for details.
286 pub auto_session_tracking: bool,
287 /// Determine how Sessions are being tracked.
288 ///
289 /// See [`session_mode`](method@ClientOptions::session_mode) for details.
290 pub session_mode: SessionMode,
291 /// The user agent that should be reported.
292 ///
293 /// See [`user_agent`](method@ClientOptions::user_agent) for details.
294 pub user_agent: Cow<'static, str>,
295}
296
297impl ClientOptions {
298 /// Creates new Options.
299 #[inline]
300 pub fn new() -> Self {
301 Self::default()
302 }
303
304 /// Sets the [DSN](field@ClientOptions::dsn) to use.
305 ///
306 /// # Panics
307 ///
308 /// Panics if the value fails to parse as a [DSN](`Dsn`).
309 #[inline]
310 pub fn dsn(self, dsn: &str) -> Self {
311 let dsn = Some(dsn.parse().expect("invalid value for DSN"));
312 Self { dsn, ..self }
313 }
314
315 /// Enables or disables [debug mode](field@ClientOptions::debug).
316 ///
317 /// In debug mode debug information is printed to stderr to help you understand what sentry is
318 /// doing. Defaults to `false`.
319 #[inline]
320 pub fn debug(self, debug: bool) -> Self {
321 Self { debug, ..self }
322 }
323
324 /// Sets the [release](field@ClientOptions::release) to be sent with events.
325 #[inline]
326 pub fn release<T>(self, release: T) -> Self
327 where
328 T: Into<Cow<'static, str>>,
329 {
330 let release = Some(release.into());
331 Self { release, ..self }
332 }
333
334 /// Sets the [release](field@ClientOptions::release) to be sent with events if one is provided.
335 ///
336 /// Use this with [`release_name!`](crate::release_name), which returns the release as an
337 /// `Option`.
338 #[inline]
339 pub fn maybe_release<T>(self, release: Option<T>) -> Self
340 where
341 T: Into<Cow<'static, str>>,
342 {
343 match release {
344 Some(release) => self.release(release),
345 None => self,
346 }
347 }
348
349 /// Sets the [environment](field@ClientOptions::environment) to be sent with events.
350 ///
351 /// Defaults to either `"development"` or `"production"` depending on the `debug_assertions`
352 /// cfg-attribute.
353 #[inline]
354 pub fn environment<T>(self, environment: T) -> Self
355 where
356 T: Into<Cow<'static, str>>,
357 {
358 let environment = Some(environment.into());
359 Self {
360 environment,
361 ..self
362 }
363 }
364
365 /// Sets the [event sampling strategy](field@ClientOptions::event_sampling_strategy) to a fixed
366 /// sample rate for event submission.
367 ///
368 /// Must be between `0.0` and `1.0`. Defaults to `1.0`.
369 ///
370 /// # Panics
371 ///
372 /// Panics if the `sample_rate` is outside the allowed range.
373 #[inline]
374 pub fn sample_rate(self, sample_rate: f32) -> Self {
375 if !(0.0..=1.0).contains(&sample_rate) {
376 panic!("Sample rate {sample_rate} is outside the allowed range [0.0, 1.0].")
377 }
378
379 let event_sampling_strategy = EventSamplingStrategy::FixedRate(sample_rate);
380
381 Self {
382 event_sampling_strategy,
383 ..self
384 }
385 }
386
387 /// Sets the [traces sampling strategy](field@ClientOptions::traces_sampling_strategy) to a
388 /// fixed sample rate for tracing transactions.
389 ///
390 /// Must be between `0.0` and `1.0`.
391 ///
392 /// Calling this method stores an explicit fixed-rate traces sampling strategy, even when the
393 /// rate is `0.0`. That is distinct from leaving traces sampling unset, which uses
394 /// [`TracesSamplingStrategy::Disabled`].
395 ///
396 /// # Panics
397 ///
398 /// Panics if the `traces_sample_rate` is outside the allowed range.
399 #[inline]
400 pub fn traces_sample_rate(self, traces_sample_rate: f32) -> Self {
401 if !(0.0..=1.0).contains(&traces_sample_rate) {
402 panic!(
403 "Traces sample rate {traces_sample_rate} is outside the allowed range [0.0, 1.0]."
404 )
405 }
406
407 let traces_sampling_strategy = TracesSamplingStrategy::FixedRate(traces_sample_rate);
408
409 Self {
410 traces_sampling_strategy,
411 ..self
412 }
413 }
414
415 /// Sets the [traces sampling strategy](field@ClientOptions::traces_sampling_strategy) to a
416 /// sampler callback for tracing transactions.
417 ///
418 /// Return a sample rate between `0.0` and `1.0` for the transaction in question. This replaces
419 /// any fixed-rate strategy configured with [`Self::traces_sample_rate`] and is distinct from
420 /// leaving traces sampling unset.
421 #[inline]
422 pub fn traces_sampler<F>(self, traces_sampler: F) -> Self
423 where
424 F: Fn(&TransactionContext) -> f32 + Send + Sync + 'static,
425 {
426 let traces_sampling_strategy =
427 TracesSamplingStrategy::Function(Arc::new(traces_sampler) as Arc<TracesSampler>);
428
429 Self {
430 traces_sampling_strategy,
431 ..self
432 }
433 }
434
435 /// Sets the [organization ID](field@ClientOptions::org_id) used for trace continuation.
436 ///
437 /// By default, we infer the organization ID from the DSN when available. Setting this option
438 /// overrides the DSN-derived organization ID.
439 ///
440 /// This option should be used in local Relay and self-hosted setups, as the organization ID
441 /// cannot be inferred from the DSN in these cases.
442 #[inline]
443 pub fn org_id(self, org_id: OrganizationId) -> Self {
444 let org_id = Some(org_id);
445 Self { org_id, ..self }
446 }
447
448 /// Enables or disables [strict trace continuation](field@ClientOptions::strict_trace_continuation).
449 ///
450 /// Strict trace continuation helps prevent the SDK from continuing traces that originate from
451 /// services instrumented with Sentry by another organization.
452 ///
453 /// By default, the SDK will always continue incoming traces, unless this SDK has an org ID
454 /// embedded in the DSN or explicitly set with [`Self::org_id`] **and** the incoming trace
455 /// includes a different org ID.
456 ///
457 /// When strict trace continuation is enabled, the SDK additionally will not continue traces in
458 /// the case where one of the SDK's org ID or the incoming trace org ID are missing.
459 #[inline]
460 pub fn strict_trace_continuation(self, strict_trace_continuation: bool) -> Self {
461 Self {
462 strict_trace_continuation,
463 ..self
464 }
465 }
466
467 /// Sets the [maximum number of breadcrumbs](field@ClientOptions::max_breadcrumbs).
468 ///
469 /// Defaults to `100`.
470 #[inline]
471 pub fn max_breadcrumbs(self, max_breadcrumbs: usize) -> Self {
472 Self {
473 max_breadcrumbs,
474 ..self
475 }
476 }
477
478 /// Enables or disables [attaching stacktraces](field@ClientOptions::attach_stacktrace) to
479 /// messages.
480 ///
481 /// Defaults to `false`.
482 #[inline]
483 pub fn attach_stacktrace(self, attach_stacktrace: bool) -> Self {
484 Self {
485 attach_stacktrace,
486 ..self
487 }
488 }
489
490 /// Enables or disables sending [default PII](field@ClientOptions::send_default_pii).
491 ///
492 /// This includes information such as potentially sensitive HTTP headers and user IP addresses
493 /// in HTTP server integrations. Defaults to `false`.
494 #[inline]
495 pub fn send_default_pii(self, send_default_pii: bool) -> Self {
496 Self {
497 send_default_pii,
498 ..self
499 }
500 }
501
502 /// Sets the [server name](field@ClientOptions::server_name) to be reported.
503 #[inline]
504 pub fn server_name<T>(self, server_name: T) -> Self
505 where
506 T: Into<Cow<'static, str>>,
507 {
508 let server_name = Some(server_name.into());
509 Self {
510 server_name,
511 ..self
512 }
513 }
514
515 /// Sets [module prefixes](field@ClientOptions::in_app_include) that are always considered
516 /// in-app.
517 #[inline]
518 pub fn in_app_include<I>(self, in_app_include: I) -> Self
519 where
520 I: IntoIterator<Item = &'static str>,
521 {
522 let in_app_include = in_app_include.into_iter().collect();
523 Self {
524 in_app_include,
525 ..self
526 }
527 }
528
529 /// Sets [module prefixes](field@ClientOptions::in_app_exclude) that are never considered
530 /// in-app.
531 #[inline]
532 pub fn in_app_exclude<I>(self, in_app_exclude: I) -> Self
533 where
534 I: IntoIterator<Item = &'static str>,
535 {
536 let in_app_exclude = in_app_exclude.into_iter().collect();
537 Self {
538 in_app_exclude,
539 ..self
540 }
541 }
542
543 /// Sets the [integrations](field@ClientOptions::integrations) to enable, replacing the
544 /// existing list.
545 ///
546 /// See [`sentry::integrations`](integrations/index.html#installing-integrations) for how to
547 /// use this to enable extra integrations. Use
548 /// [`add_integration`](method@ClientOptions::add_integration) to append.
549 #[inline]
550 pub fn integrations<I>(self, integrations: I) -> Self
551 where
552 I: IntoIterator<Item = Arc<dyn Integration>>,
553 {
554 let integrations = integrations.into_iter().collect();
555 Self {
556 integrations,
557 ..self
558 }
559 }
560
561 /// Enables or disables [default integrations](field@ClientOptions::default_integrations).
562 ///
563 /// See [`sentry::integrations`](integrations/index.html#default-integrations) for details.
564 /// Defaults to `true`.
565 #[inline]
566 pub fn default_integrations(self, default_integrations: bool) -> Self {
567 Self {
568 default_integrations,
569 ..self
570 }
571 }
572
573 /// Sets the [callback](field@ClientOptions::before_send) that is executed before event
574 /// sending.
575 #[inline]
576 pub fn before_send<F>(self, before_send: F) -> Self
577 where
578 F: Fn(Event<'static>) -> Option<Event<'static>> + Send + Sync + 'static,
579 {
580 let before_send = Some(Arc::new(before_send) as BeforeCallback<Event<'static>>);
581 Self {
582 before_send,
583 ..self
584 }
585 }
586
587 /// Sets the [callback](field@ClientOptions::before_breadcrumb) that is executed before adding
588 /// each breadcrumb.
589 #[inline]
590 pub fn before_breadcrumb<F>(self, before_breadcrumb: F) -> Self
591 where
592 F: Fn(Breadcrumb) -> Option<Breadcrumb> + Send + Sync + 'static,
593 {
594 let before_breadcrumb = Some(Arc::new(before_breadcrumb) as BeforeCallback<Breadcrumb>);
595 Self {
596 before_breadcrumb,
597 ..self
598 }
599 }
600
601 /// Sets the [callback](field@ClientOptions::before_send_log) that is executed before sending
602 /// each log.
603 #[cfg(feature = "logs")]
604 #[inline]
605 pub fn before_send_log<F>(self, before_send_log: F) -> Self
606 where
607 F: Fn(Log) -> Option<Log> + Send + Sync + 'static,
608 {
609 let before_send_log = Some(Arc::new(before_send_log) as BeforeCallback<Log>);
610 Self {
611 before_send_log,
612 ..self
613 }
614 }
615
616 /// Sets the [callback](field@ClientOptions::before_send_metric) that is executed before
617 /// sending each metric.
618 ///
619 /// This callback can modify a metric or return `None` to drop it.
620 #[cfg(feature = "metrics")]
621 #[inline]
622 pub fn before_send_metric<F>(self, before_send_metric: F) -> Self
623 where
624 F: Fn(Metric) -> Option<Metric> + Send + Sync + 'static,
625 {
626 let before_send_metric = Some(Arc::new(before_send_metric) as BeforeCallback<Metric>);
627 Self {
628 before_send_metric,
629 ..self
630 }
631 }
632
633 /// Sets the [transport](field@ClientOptions::transport) to use.
634 ///
635 /// This is typically either a function taking the client options by reference and returning a
636 /// transport, an `Arc<Transport>`, or the `DefaultTransportFactory`. Types that do not
637 /// implement [`TransportFactory`] use direct field assignment.
638 #[inline]
639 pub fn transport<T: TransportFactory + 'static>(self, transport: T) -> Self {
640 let transport = Some(Arc::new(transport) as Arc<dyn TransportFactory>);
641 Self { transport, ..self }
642 }
643
644 /// Sets the optional [HTTP proxy](field@ClientOptions::http_proxy) to use.
645 ///
646 /// This defaults to the `http_proxy` environment variable.
647 #[inline]
648 pub fn http_proxy<T>(self, http_proxy: T) -> Self
649 where
650 T: Into<Cow<'static, str>>,
651 {
652 let http_proxy = Some(http_proxy.into());
653 Self { http_proxy, ..self }
654 }
655
656 /// Sets the optional [HTTPS proxy](field@ClientOptions::https_proxy) to use.
657 ///
658 /// This defaults to the `HTTPS_PROXY` environment variable, or `http_proxy` if that one
659 /// exists.
660 #[inline]
661 pub fn https_proxy<T>(self, https_proxy: T) -> Self
662 where
663 T: Into<Cow<'static, str>>,
664 {
665 let https_proxy = Some(https_proxy.into());
666 Self {
667 https_proxy,
668 ..self
669 }
670 }
671
672 /// Sets the [shutdown drain timeout](field@ClientOptions::shutdown_timeout).
673 ///
674 /// Defaults to 2 seconds.
675 #[inline]
676 pub fn shutdown_timeout(self, shutdown_timeout: Duration) -> Self {
677 Self {
678 shutdown_timeout,
679 ..self
680 }
681 }
682
683 /// Sets the [maximum request body size](field@ClientOptions::max_request_body_size) to
684 /// capture.
685 ///
686 /// Controls the maximum size of an HTTP request body that can be captured when using HTTP
687 /// server integrations. Needs [`send_default_pii`](method@ClientOptions::send_default_pii) to
688 /// be enabled to have any effect. Defaults to [`MaxRequestBodySize::Medium`].
689 #[inline]
690 pub fn max_request_body_size(self, max_request_body_size: MaxRequestBodySize) -> Self {
691 Self {
692 max_request_body_size,
693 ..self
694 }
695 }
696
697 /// Sets the
698 /// [transport channel capacity](field@ClientOptions::transport_channel_capacity).
699 ///
700 /// The smallest usable channel capacity is `1`. If `0` is passed, the capacity is clamped
701 /// to `1` and a debug message is emitted.
702 #[inline]
703 pub fn transport_channel_capacity(self, transport_channel_capacity: usize) -> Self {
704 #[cfg_attr(not(feature = "client"), expect(clippy::unnecessary_lazy_evaluations))]
705 let transport_channel_capacity = NonZeroUsize::new(transport_channel_capacity)
706 .unwrap_or_else(|| {
707 #[cfg(feature = "client")]
708 sentry_debug!("cannot set transport channel capacity to 0; clamping to 1");
709 NonZeroUsize::MIN
710 })
711 .into();
712 Self {
713 transport_channel_capacity,
714 ..self
715 }
716 }
717
718 /// Deprecated. Setting [`enable_logs`](field@ClientOptions::enable_logs) to `false` only
719 /// disables automatic log capture by the log-capturing integrations (`log` and `tracing`
720 /// with the `logs` feature); it does not disable logs captured manually via
721 /// [`Hub::capture_log`](crate::Hub::capture_log) and the `logger_*` macros.
722 ///
723 /// To stop an integration from sending logs, use its own options to configure what it
724 /// captures. Alternatively, use [`Self::before_send_log`] to filter logs.
725 #[deprecated = "logs captured manually are always sent; only automatic capture by integrations respects this option"]
726 #[inline]
727 pub fn enable_logs(self, enable_logs: bool) -> Self {
728 Self {
729 #[expect(deprecated, reason = "need to set deprecated field")]
730 enable_logs,
731 ..self
732 }
733 }
734
735 /// This function is a no-op, as it sets the deprecated field
736 /// [`enable_metrics`](field@ClientOptions::enable_metrics). Metrics are always enabled.
737 ///
738 /// To stop sending metrics, simply remove any calls to our metrics APIs.
739 #[deprecated = "this function sets a no-op option"]
740 #[inline]
741 pub fn enable_metrics(self, enable_metrics: bool) -> Self {
742 Self {
743 #[expect(deprecated, reason = "need to set deprecated field")]
744 enable_metrics,
745 ..self
746 }
747 }
748
749 /// Enables or disables
750 /// [accepting invalid TLS certificates](field@ClientOptions::accept_invalid_certs).
751 ///
752 /// This introduces significant vulnerabilities, and should only be used as a last resort.
753 /// Defaults to `false`.
754 #[inline]
755 pub fn accept_invalid_certs(self, accept_invalid_certs: bool) -> Self {
756 Self {
757 accept_invalid_certs,
758 ..self
759 }
760 }
761
762 /// Enables or disables
763 /// [automatic session tracking](field@ClientOptions::auto_session_tracking).
764 ///
765 /// When enabled, a new "user-mode" session is started at `sentry::init` and persists for the
766 /// application lifetime. Defaults to `false`.
767 #[cfg(feature = "release-health")]
768 #[inline]
769 pub fn auto_session_tracking(self, auto_session_tracking: bool) -> Self {
770 Self {
771 auto_session_tracking,
772 ..self
773 }
774 }
775
776 /// Sets how [sessions are tracked](field@ClientOptions::session_mode).
777 ///
778 /// See [`SessionMode`] for the available modes. Defaults to [`SessionMode::Application`].
779 #[cfg(feature = "release-health")]
780 #[inline]
781 pub fn session_mode(self, session_mode: SessionMode) -> Self {
782 Self {
783 session_mode,
784 ..self
785 }
786 }
787
788 /// Sets the [user agent](field@ClientOptions::user_agent) that should be reported.
789 ///
790 /// Defaults to the SDK user agent.
791 #[inline]
792 pub fn user_agent<T>(self, user_agent: T) -> Self
793 where
794 T: Into<Cow<'static, str>>,
795 {
796 let user_agent = user_agent.into();
797 Self { user_agent, ..self }
798 }
799
800 /// Adds a configured integration to the options.
801 ///
802 /// # Examples
803 ///
804 /// ```
805 /// struct MyIntegration;
806 ///
807 /// impl sentry::Integration for MyIntegration {}
808 ///
809 /// let options = sentry::ClientOptions::new().add_integration(MyIntegration);
810 /// assert_eq!(options.integrations.len(), 1);
811 /// ```
812 #[inline]
813 pub fn add_integration<I: Integration>(mut self, integration: I) -> Self {
814 self.integrations.push(Arc::new(integration));
815 self
816 }
817}
818impl fmt::Debug for ClientOptions {
819 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
820 #[derive(Debug)]
821 struct BeforeSend;
822 let before_send = self.before_send.as_ref().map(|_| BeforeSend);
823 #[derive(Debug)]
824 struct BeforeBreadcrumb;
825 let before_breadcrumb = self.before_breadcrumb.as_ref().map(|_| BeforeBreadcrumb);
826 let before_send_log = {
827 #[derive(Debug)]
828 struct BeforeSendLog;
829 self.before_send_log.as_ref().map(|_| BeforeSendLog)
830 };
831 let before_send_metric = {
832 #[derive(Debug)]
833 struct BeforeSendMetric;
834 self.before_send_metric.as_ref().map(|_| BeforeSendMetric)
835 };
836 #[derive(Debug)]
837 struct TransportFactory;
838
839 let integrations: Vec<_> = self.integrations.iter().map(|i| i.name()).collect();
840
841 let mut debug_struct = f.debug_struct("ClientOptions");
842 debug_struct
843 .field("dsn", &self.dsn)
844 .field("debug", &self.debug)
845 .field("release", &self.release)
846 .field("environment", &self.environment)
847 .field("event_sampling_strategy", &self.event_sampling_strategy)
848 .field("traces_sampling_strategy", &self.traces_sampling_strategy)
849 .field("max_breadcrumbs", &self.max_breadcrumbs)
850 .field("attach_stacktrace", &self.attach_stacktrace)
851 .field("send_default_pii", &self.send_default_pii)
852 .field("server_name", &self.server_name)
853 .field("in_app_include", &self.in_app_include)
854 .field("in_app_exclude", &self.in_app_exclude)
855 .field("integrations", &integrations)
856 .field("default_integrations", &self.default_integrations)
857 .field("before_send", &before_send)
858 .field("before_breadcrumb", &before_breadcrumb)
859 .field("transport", &TransportFactory)
860 .field("http_proxy", &self.http_proxy)
861 .field("https_proxy", &self.https_proxy)
862 .field("shutdown_timeout", &self.shutdown_timeout)
863 .field(
864 "transport_channel_capacity",
865 &self.transport_channel_capacity,
866 )
867 .field("accept_invalid_certs", &self.accept_invalid_certs)
868 .field("auto_session_tracking", &self.auto_session_tracking)
869 .field("session_mode", &self.session_mode)
870 .field(
871 "enable_logs",
872 #[expect(deprecated, reason = "still need to debug-log this field")]
873 &self.enable_logs,
874 )
875 .field("before_send_log", &before_send_log)
876 .field(
877 "enable_metrics",
878 #[expect(deprecated, reason = "still need to debug-log this field")]
879 &self.enable_metrics,
880 )
881 .field("before_send_metric", &before_send_metric)
882 .field("org_id", &self.org_id)
883 .field("strict_trace_continuation", &self.strict_trace_continuation)
884 .field("user_agent", &self.user_agent)
885 .finish()
886 }
887}
888
889impl Default for ClientOptions {
890 fn default() -> ClientOptions {
891 ClientOptions {
892 dsn: None,
893 org_id: None,
894 strict_trace_continuation: false,
895 debug: false,
896 release: None,
897 environment: None,
898 event_sampling_strategy: Default::default(),
899 traces_sampling_strategy: Default::default(),
900 max_breadcrumbs: 100,
901 attach_stacktrace: false,
902 send_default_pii: false,
903 server_name: None,
904 in_app_include: vec![],
905 in_app_exclude: vec![],
906 integrations: vec![],
907 default_integrations: true,
908 before_send: None,
909 before_breadcrumb: None,
910 transport: None,
911 http_proxy: None,
912 https_proxy: None,
913 shutdown_timeout: Duration::from_secs(2),
914 accept_invalid_certs: false,
915 auto_session_tracking: false,
916 session_mode: SessionMode::Application,
917 user_agent: Cow::Borrowed(USER_AGENT),
918 max_request_body_size: MaxRequestBodySize::Medium,
919 transport_channel_capacity: None,
920 #[expect(deprecated, reason = "still need to set deprecated fields")]
921 enable_logs: true,
922 before_send_log: None,
923 #[expect(deprecated, reason = "still need to set deprecated fields")]
924 enable_metrics: true,
925 before_send_metric: None,
926 }
927 }
928}
929
930impl<T: IntoDsn> From<(T, ClientOptions)> for ClientOptions {
931 fn from((into_dsn, mut opts): (T, ClientOptions)) -> ClientOptions {
932 opts.dsn = into_dsn.into_dsn().expect("invalid value for DSN");
933 opts
934 }
935}
936
937impl<T: IntoDsn> From<T> for ClientOptions {
938 fn from(into_dsn: T) -> ClientOptions {
939 ClientOptions {
940 dsn: into_dsn.into_dsn().expect("invalid value for DSN"),
941 ..ClientOptions::default()
942 }
943 }
944}