sentry_contexts/
integration.rs

1use std::borrow::Cow;
2
3use sentry_core::protocol::map::Entry;
4use sentry_core::protocol::Event;
5use sentry_core::{ClientOptions, Integration};
6
7use crate::utils::{device_context, os_context, rust_context, server_name};
8
9/// Adds Contexts to Sentry Events.
10///
11/// This integration is enabled by default in `sentry` and adds `device`, `os`
12/// and `rust` contexts to Events, and also sets a `server_name` if it is not
13/// already defined.
14///
15/// See the [Contexts Interface] documentation for more info.
16///
17/// # Examples
18///
19/// ```rust
20/// let integration = sentry_contexts::ContextIntegration::new().add_os(false);
21/// let _sentry = sentry::init(sentry::ClientOptions::new().add_integration(integration));
22/// ```
23///
24/// [Contexts Interface]: https://develop.sentry.dev/sdk/event-payloads/contexts/
25#[derive(Debug)]
26pub struct ContextIntegration {
27    add_os: bool,
28    add_rust: bool,
29    add_device: bool,
30}
31
32impl Default for ContextIntegration {
33    fn default() -> Self {
34        Self {
35            add_os: true,
36            add_rust: true,
37            add_device: true,
38        }
39    }
40}
41
42impl ContextIntegration {
43    /// Create a new Context Integration.
44    pub fn new() -> Self {
45        Self::default()
46    }
47
48    /// Add `os` context, enabled by default.
49    #[must_use]
50    pub fn add_os(mut self, add_os: bool) -> Self {
51        self.add_os = add_os;
52        self
53    }
54    /// Add `rust` context, enabled by default.
55    #[must_use]
56    pub fn add_rust(mut self, add_rust: bool) -> Self {
57        self.add_rust = add_rust;
58        self
59    }
60
61    /// Add `device` context, enabled by default.
62    #[must_use]
63    pub fn add_device(mut self, add_device: bool) -> Self {
64        self.add_device = add_device;
65        self
66    }
67}
68
69impl Integration for ContextIntegration {
70    fn name(&self) -> &'static str {
71        "contexts"
72    }
73
74    fn setup(&self, options: &mut ClientOptions) {
75        if options.server_name.is_none() {
76            options.server_name = server_name().map(Cow::Owned);
77        }
78    }
79
80    fn process_event(
81        &self,
82        mut event: Event<'static>,
83        _cfg: &ClientOptions,
84    ) -> Option<Event<'static>> {
85        if self.add_os {
86            if let Entry::Vacant(entry) = event.contexts.entry("os".to_string()) {
87                if let Some(os) = os_context() {
88                    entry.insert(os);
89                }
90            }
91        }
92        if self.add_rust {
93            event
94                .contexts
95                .entry("rust".to_string())
96                .or_insert_with(rust_context);
97        }
98        if self.add_device {
99            event
100                .contexts
101                .entry("device".to_string())
102                .or_insert_with(device_context);
103        }
104
105        Some(event)
106    }
107}