Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: introduce release-health feature #749

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions sentry-actix/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ actix-web = { version = "4", default-features = false }
futures-util = { version = "0.3.5", default-features = false }
sentry-core = { version = "0.36.0", path = "../sentry-core", default-features = false, features = [
"client",
"release-health",
] }
actix-http = "3.9.0"

Expand Down
3 changes: 2 additions & 1 deletion sentry-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ client = ["rand"]
# I would love to just have a `log` feature, but this is used inside a macro,
# and macros actually expand features (and extern crate) where they are used!
debug-logs = ["dep:log"]
test = ["client"]
test = ["client", "release-health"]
release-health = []

[dependencies]
cadence = { version = "1.4.0", optional = true }
Expand Down
4 changes: 4 additions & 0 deletions sentry-core/src/api.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#[cfg(feature = "release-health")]
use sentry_types::protocol::v7::SessionStatus;

use crate::protocol::{Event, Level};
Expand Down Expand Up @@ -279,11 +280,13 @@ pub fn last_event_id() -> Option<Uuid> {
///
/// sentry::end_session();
/// ```
#[cfg(feature = "release-health")]
pub fn start_session() {
Hub::with_active(|hub| hub.start_session())
}

/// End the current Release Health Session.
#[cfg(feature = "release-health")]
pub fn end_session() {
end_session_with_status(SessionStatus::Exited)
}
Expand All @@ -295,6 +298,7 @@ pub fn end_session() {
///
/// When an `Abnormal` session should be captured, it has to be done explicitly
/// using this function.
#[cfg(feature = "release-health")]
pub fn end_session_with_status(status: SessionStatus) {
Hub::with_active(|hub| hub.end_session_with_status(status))
}
13 changes: 12 additions & 1 deletion sentry-core/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ use crate::constants::SDK_INFO;
use crate::protocol::{ClientSdkInfo, Event};
use crate::session::SessionFlusher;
use crate::types::{Dsn, Uuid};
use crate::{ClientOptions, Envelope, Hub, Integration, Scope, SessionMode, Transport};
#[cfg(feature = "release-health")]
use crate::SessionMode;
use crate::{ClientOptions, Envelope, Hub, Integration, Scope, Transport};

impl<T: Into<ClientOptions>> From<T> for Client {
fn from(o: T) -> Client {
Expand Down Expand Up @@ -60,10 +62,15 @@ impl fmt::Debug for Client {
impl Clone for Client {
fn clone(&self) -> Client {
let transport = Arc::new(RwLock::new(self.transport.read().unwrap().clone()));

#[cfg(feature = "release-health")]
let session_flusher = RwLock::new(Some(SessionFlusher::new(
transport.clone(),
self.options.session_mode,
)));
#[cfg(not(feature = "release-health"))]
let session_flusher = RwLock::new(None);

Client {
options: self.options.clone(),
transport,
Expand Down Expand Up @@ -131,10 +138,13 @@ impl Client {
sdk_info.integrations.push(integration.name().to_string());
}

#[cfg(feature = "release-health")]
let session_flusher = RwLock::new(Some(SessionFlusher::new(
transport.clone(),
options.session_mode,
)));
#[cfg(not(feature = "release-health"))]
let session_flusher = RwLock::new(None);

Client {
options,
Expand Down Expand Up @@ -266,6 +276,7 @@ impl Client {
let mut envelope: Envelope = event.into();
// For request-mode sessions, we aggregate them all instead of
// flushing them out early.
#[cfg(feature = "release-health")]
if self.options.session_mode == SessionMode::Application {
let session_item = scope.and_then(|scope| {
scope
Expand Down
2 changes: 2 additions & 0 deletions sentry-core/src/clientoptions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,9 @@ impl Default for ClientOptions {
https_proxy: None,
shutdown_timeout: Duration::from_secs(2),
accept_invalid_certs: false,
#[cfg(feature = "release-health")]
auto_session_tracking: false,
#[cfg(feature = "release-health")]
session_mode: SessionMode::Application,
extra_border_frames: vec![],
trim_backtraces: true,
Expand Down
3 changes: 3 additions & 0 deletions sentry-core/src/hub.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ impl Hub {
///
/// See the global [`start_session`](fn.start_session.html)
/// for more documentation.
#[cfg(feature = "release-health")]
pub fn start_session(&self) {
with_client_impl! {{
self.inner.with_mut(|stack| {
Expand All @@ -143,6 +144,7 @@ impl Hub {
/// End the current Release Health Session.
///
/// See the global [`sentry::end_session`](crate::end_session) for more documentation.
#[cfg(feature = "release-health")]
pub fn end_session(&self) {
self.end_session_with_status(SessionStatus::Exited)
}
Expand All @@ -151,6 +153,7 @@ impl Hub {
///
/// See the global [`end_session_with_status`](crate::end_session_with_status)
/// for more documentation.
#[cfg(feature = "release-health")]
pub fn end_session_with_status(&self, status: SessionStatus) {
with_client_impl! {{
self.inner.with_mut(|stack| {
Expand Down
9 changes: 9 additions & 0 deletions sentry-core/src/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@ use crate::protocol::{
EnvelopeItem, Event, Level, SessionAggregateItem, SessionAggregates, SessionAttributes,
SessionStatus, SessionUpdate,
};

#[cfg(feature = "release-health")]
use crate::scope::StackLayer;

#[cfg(feature = "release-health")]
use crate::types::random_uuid;
use crate::{Client, Envelope};

Expand All @@ -35,6 +39,7 @@ impl Drop for Session {
}

impl Session {
#[cfg(feature = "release-health")]
pub fn from_stack(stack: &StackLayer) -> Option<Self> {
let client = stack.client.as_ref()?;
let options = client.options();
Expand Down Expand Up @@ -110,6 +115,7 @@ impl Session {
}
}

#[cfg(feature = "release-health")]
pub(crate) fn create_envelope_item(&mut self) -> Option<EnvelopeItem> {
if self.dirty {
let item = self.session_update.clone().into();
Expand All @@ -123,6 +129,7 @@ impl Session {

// as defined here: https://develop.sentry.dev/sdk/envelopes/#size-limits
const MAX_SESSION_ITEMS: usize = 100;
#[cfg(feature = "release-health")]
const FLUSH_INTERVAL: Duration = Duration::from_secs(60);

#[derive(Debug, Default)]
Expand Down Expand Up @@ -189,6 +196,7 @@ pub(crate) struct SessionFlusher {

impl SessionFlusher {
/// Creates a new Flusher that will submit envelopes to the given `transport`.
#[cfg(feature = "release-health")]
pub fn new(transport: TransportArc, mode: SessionMode) -> Self {
let queue = Arc::new(Mutex::new(Default::default()));
#[allow(clippy::mutex_atomic)]
Expand Down Expand Up @@ -447,6 +455,7 @@ mod tests {
},
crate::ClientOptions {
release: Some("some-release".into()),
#[cfg(feature = "release-health")]
session_mode: SessionMode::Request,
..Default::default()
},
Expand Down
10 changes: 9 additions & 1 deletion sentry/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,14 @@ all-features = true
rustdoc-args = ["--cfg", "doc_cfg"]

[features]
default = ["backtrace", "contexts", "debug-images", "panic", "transport"]
default = [
"backtrace",
"contexts",
"debug-images",
"panic",
"transport",
"release-health",
]

# default integrations
backtrace = ["sentry-backtrace", "sentry-tracing?/backtrace"]
Expand All @@ -39,6 +46,7 @@ tracing = ["sentry-tracing"]
# other features
test = ["sentry-core/test"]
debug-logs = ["dep:log", "sentry-core/debug-logs"]
release-health = ["sentry-core/release-health"]
# transports
transport = ["reqwest", "native-tls"]
reqwest = ["dep:reqwest", "httpdate", "tokio"]
Expand Down
8 changes: 7 additions & 1 deletion sentry/src/init.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use std::sync::Arc;

use sentry_core::{sentry_debug, SessionMode};
use sentry_core::sentry_debug;
#[cfg(feature = "release-health")]
use sentry_core::SessionMode;

use crate::defaults::apply_defaults;
use crate::{Client, ClientOptions, Hub};
Expand Down Expand Up @@ -34,6 +36,7 @@ impl Drop for ClientInitGuard {
sentry_debug!("dropping client guard (no client to dispose)");
}
// end any session that might be open before closing the client
#[cfg(feature = "release-health")]
crate::end_session();
self.0.close(None);
}
Expand Down Expand Up @@ -93,8 +96,10 @@ where
C: Into<ClientOptions>,
{
let opts = apply_defaults(opts.into());

let auto_session_tracking = opts.auto_session_tracking;
let session_mode = opts.session_mode;

let client = Arc::new(Client::from(opts));

Hub::with(|hub| hub.bind_client(Some(client.clone())));
Expand All @@ -103,6 +108,7 @@ where
} else {
sentry_debug!("initialized disabled sentry client due to disabled or invalid DSN");
}
#[cfg(feature = "release-health")]
if auto_session_tracking && session_mode == SessionMode::Application {
crate::start_session()
}
Expand Down