From 743e86f3ed86ffd739441c1a43575eb4281cc3a5 Mon Sep 17 00:00:00 2001 From: Tim Fish Date: Fri, 27 May 2022 00:17:19 +0100 Subject: [PATCH 1/3] PoC --- sentry-core/src/hub.rs | 7 ++--- sentry-core/src/scope/real.rs | 49 +++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 5 deletions(-) diff --git a/sentry-core/src/hub.rs b/sentry-core/src/hub.rs index 27461d8c..79146892 100644 --- a/sentry-core/src/hub.rs +++ b/sentry-core/src/hub.rs @@ -427,17 +427,14 @@ impl Hub { if let Some(ref client) = top.client { let scope = Arc::make_mut(&mut top.scope); let options = client.options(); - let breadcrumbs = Arc::make_mut(&mut scope.breadcrumbs); for breadcrumb in breadcrumb.into_breadcrumbs() { let breadcrumb_opt = match options.before_breadcrumb { Some(ref callback) => callback(breadcrumb), None => Some(breadcrumb) }; + if let Some(breadcrumb) = breadcrumb_opt { - breadcrumbs.push_back(breadcrumb); - } - while breadcrumbs.len() > options.max_breadcrumbs { - breadcrumbs.pop_front(); + scope.add_breadcrumb(breadcrumb, options.max_breadcrumbs); } } } diff --git a/sentry-core/src/scope/real.rs b/sentry-core/src/scope/real.rs index e29651b0..3f4f8d4d 100644 --- a/sentry-core/src/scope/real.rs +++ b/sentry-core/src/scope/real.rs @@ -8,12 +8,24 @@ use crate::protocol::{Attachment, Breadcrumb, Context, Event, Level, User, Value use crate::session::Session; use crate::Client; +#[non_exhaustive] +pub enum ScopeUpdate { + AddBreadcrumb(Breadcrumb), + ClearBreadcrumbs, + User(Option), + SetExtra(String, Value), + RemoveExtra(String), + SetTag(String, String), + RemoveTag(String), +} + #[derive(Debug)] pub struct Stack { layers: Vec, } pub type EventProcessor = Arc) -> Option> + Send + Sync>; +pub type ScopeListener = Arc; /// Holds contextual data for the current scope. /// @@ -44,6 +56,7 @@ pub struct Scope { pub(crate) tags: Arc>, pub(crate) contexts: Arc>, pub(crate) event_processors: Arc>, + pub(crate) scope_listeners: Arc>, pub(crate) session: Arc>>, pub(crate) span: Arc>, pub(crate) attachments: Arc>, @@ -144,6 +157,7 @@ impl Scope { /// Deletes current breadcrumbs from the scope. pub fn clear_breadcrumbs(&mut self) { + self.notify_scope_listeners(|| ScopeUpdate::ClearBreadcrumbs); self.breadcrumbs = Default::default(); } @@ -176,11 +190,13 @@ impl Scope { /// Sets the user for the current scope. pub fn set_user(&mut self, user: Option) { + self.notify_scope_listeners(|| ScopeUpdate::User(user.clone())); self.user = user.map(Arc::new); } /// Sets a tag to a specific value. pub fn set_tag(&mut self, key: &str, value: V) { + self.notify_scope_listeners(|| ScopeUpdate::SetTag(key.to_string(), value.to_string())); Arc::make_mut(&mut self.tags).insert(key.to_string(), value.to_string()); } @@ -188,6 +204,7 @@ impl Scope { /// /// If the tag is not set, does nothing. pub fn remove_tag(&mut self, key: &str) { + self.notify_scope_listeners(|| ScopeUpdate::RemoveTag(key.to_string())); Arc::make_mut(&mut self.tags).remove(key); } @@ -203,11 +220,13 @@ impl Scope { /// Sets a extra to a specific value. pub fn set_extra(&mut self, key: &str, value: Value) { + self.notify_scope_listeners(|| ScopeUpdate::SetExtra(key.to_string(), value.clone())); Arc::make_mut(&mut self.extra).insert(key.to_string(), value); } /// Removes a extra. pub fn remove_extra(&mut self, key: &str) { + self.notify_scope_listeners(|| ScopeUpdate::RemoveExtra(key.to_string())); Arc::make_mut(&mut self.extra).remove(key); } @@ -219,6 +238,14 @@ impl Scope { Arc::make_mut(&mut self.event_processors).push(Arc::new(f)); } + /// Add an scope listener to the scope. + pub fn add_scope_listener(&mut self, f: F) + where + F: Fn(&ScopeUpdate) + Send + Sync + 'static, + { + Arc::make_mut(&mut self.scope_listeners).push(Arc::new(f)); + } + /// Adds an attachment to the scope pub fn add_attachment(&mut self, attachment: Attachment) { Arc::make_mut(&mut self.attachments).push(attachment); @@ -302,4 +329,26 @@ impl Scope { session.update_from_event(event); } } + + pub(crate) fn add_breadcrumb(&mut self, breadcrumb: Breadcrumb, max_breadcrumbs: usize) { + self.notify_scope_listeners(|| ScopeUpdate::AddBreadcrumb(breadcrumb.clone())); + + let breadcrumbs = Arc::make_mut(&mut self.breadcrumbs); + breadcrumbs.push_back(breadcrumb); + + while breadcrumbs.len() > max_breadcrumbs { + breadcrumbs.pop_front(); + } + } + + fn notify_scope_listeners ScopeUpdate>(&mut self, update_fn: F) { + if self.scope_listeners.is_empty() { + return; + } + + let update = update_fn(); + for listener in self.scope_listeners.as_ref() { + listener(&update); + } + } } From 9341aeed7426065799efc8a5365e6755f99dd106 Mon Sep 17 00:00:00 2001 From: Tim Fish Date: Tue, 31 May 2022 11:51:18 +0100 Subject: [PATCH 2/3] Allow serialisation of ScopeUpdate --- sentry-core/src/scope/real.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sentry-core/src/scope/real.rs b/sentry-core/src/scope/real.rs index 3f4f8d4d..83380218 100644 --- a/sentry-core/src/scope/real.rs +++ b/sentry-core/src/scope/real.rs @@ -1,3 +1,4 @@ +use serde::{Deserialize, Serialize}; use std::borrow::Cow; use std::collections::{HashMap, VecDeque}; use std::fmt; @@ -9,6 +10,7 @@ use crate::session::Session; use crate::Client; #[non_exhaustive] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub enum ScopeUpdate { AddBreadcrumb(Breadcrumb), ClearBreadcrumbs, From cb7a480ae9424c7a6b26e5f46ae7d903b82ad0bb Mon Sep 17 00:00:00 2001 From: Tim Fish Date: Tue, 31 May 2022 12:00:31 +0100 Subject: [PATCH 3/3] Expose ScopeUpdate with not a care in the world --- sentry-core/src/lib.rs | 2 +- sentry-core/src/scope/mod.rs | 15 +++++++++++++++ sentry-core/src/scope/real.rs | 13 +------------ sentry/src/lib.rs | 1 + 4 files changed, 18 insertions(+), 13 deletions(-) diff --git a/sentry-core/src/lib.rs b/sentry-core/src/lib.rs index 93a7cff8..1d9431a5 100644 --- a/sentry-core/src/lib.rs +++ b/sentry-core/src/lib.rs @@ -77,7 +77,7 @@ pub use crate::hub::Hub; pub use crate::integration::Integration; pub use crate::intodsn::IntoDsn; pub use crate::performance::*; -pub use crate::scope::{Scope, ScopeGuard}; +pub use crate::scope::{Scope, ScopeGuard, ScopeUpdate}; pub use crate::transport::{Transport, TransportFactory}; // client feature diff --git a/sentry-core/src/scope/mod.rs b/sentry-core/src/scope/mod.rs index c2d0ebed..d1462487 100644 --- a/sentry-core/src/scope/mod.rs +++ b/sentry-core/src/scope/mod.rs @@ -1,3 +1,6 @@ +use sentry_types::protocol::v7::{Breadcrumb, User, Value}; +use serde::{Deserialize, Serialize}; + #[cfg(feature = "client")] mod real; @@ -9,3 +12,15 @@ pub use self::real::*; #[cfg(not(feature = "client"))] pub use self::noop::*; + +#[non_exhaustive] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] +pub enum ScopeUpdate { + AddBreadcrumb(Breadcrumb), + ClearBreadcrumbs, + User(Option), + SetExtra(String, Value), + RemoveExtra(String), + SetTag(String, String), + RemoveTag(String), +} diff --git a/sentry-core/src/scope/real.rs b/sentry-core/src/scope/real.rs index df8926ff..26edc79b 100644 --- a/sentry-core/src/scope/real.rs +++ b/sentry-core/src/scope/real.rs @@ -1,4 +1,3 @@ -use serde::{Deserialize, Serialize}; use std::borrow::Cow; use std::collections::{HashMap, VecDeque}; use std::fmt; @@ -9,17 +8,7 @@ use crate::protocol::{Attachment, Breadcrumb, Context, Event, Level, User, Value use crate::session::Session; use crate::Client; -#[non_exhaustive] -#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] -pub enum ScopeUpdate { - AddBreadcrumb(Breadcrumb), - ClearBreadcrumbs, - User(Option), - SetExtra(String, Value), - RemoveExtra(String), - SetTag(String, String), - RemoveTag(String), -} +use super::ScopeUpdate; #[derive(Debug)] pub struct Stack { diff --git a/sentry/src/lib.rs b/sentry/src/lib.rs index 5cfe255f..a5230d9b 100644 --- a/sentry/src/lib.rs +++ b/sentry/src/lib.rs @@ -224,3 +224,4 @@ pub mod integrations { #[doc(inline)] pub use sentry_core::types::protocol::latest as protocol; +pub use sentry_core::ScopeUpdate;