sentry_core/
integration.rs

1use std::any::{type_name, Any};
2
3use crate::protocol::Event;
4use crate::ClientOptions;
5
6/// Integration abstraction.
7///
8/// An Integration in sentry has two primary purposes.
9/// It can act as an *Event Source*, which will capture new events;
10/// or as an *Event Processor*, which can modify every `Event` flowing through
11/// the pipeline.
12///
13/// # Examples
14///
15/// ```
16/// use sentry::protocol::{Event, Level};
17/// use sentry::ClientOptions;
18///
19/// struct MyProcessorIntegration {
20///     override_environment: &'static str,
21///     override_level: Level,
22/// }
23///
24/// impl sentry::Integration for MyProcessorIntegration {
25///     fn setup(&self, options: &mut ClientOptions) {
26///         options.environment = Some(self.override_environment.into());
27///     }
28///     fn process_event(
29///         &self,
30///         mut event: Event<'static>,
31///         _options: &ClientOptions,
32///     ) -> Option<Event<'static>> {
33///         event.level = self.override_level;
34///         Some(event)
35///     }
36/// }
37///
38/// let options = ClientOptions::new().add_integration(MyProcessorIntegration {
39///     override_environment: "my_env",
40///     override_level: Level::Error,
41/// });
42///
43/// let events = sentry::test::with_captured_events_options(
44///     || {
45///         sentry::capture_message("some message", Level::Info);
46///     },
47///     options,
48/// );
49/// let captured_event = events.into_iter().next().unwrap();
50///
51/// assert_eq!(captured_event.level, Level::Error);
52/// assert_eq!(captured_event.environment, Some("my_env".into()));
53/// ```
54// NOTE: we need `Any` here so that the `TypeId` machinery works correctly.
55pub trait Integration: Sync + Send + Any + AsAny {
56    /// Name of this integration.
57    ///
58    /// This will be added to the SDK information sent to sentry.
59    fn name(&self) -> &'static str {
60        type_name::<Self>()
61    }
62
63    /// Called whenever the integration is attached to a Client.
64    fn setup(&self, options: &mut ClientOptions) {
65        let _ = options;
66    }
67
68    /// The Integrations Event Processor Hook.
69    ///
70    /// An integration can process, or even completely drop an `Event`.
71    /// Examples include adding or processing a backtrace, obfuscate some
72    /// personal information, or add additional information.
73    fn process_event(
74        &self,
75        event: Event<'static>,
76        options: &ClientOptions,
77    ) -> Option<Event<'static>> {
78        let _ = options;
79        Some(event)
80    }
81}
82
83// This is needed as a workaround to be able to safely downcast integrations
84#[doc(hidden)]
85pub trait AsAny {
86    fn as_any(&self) -> &dyn Any;
87}
88
89impl<T: Any> AsAny for T {
90    fn as_any(&self) -> &dyn Any {
91        self
92    }
93}