Skip to main content

sentry_core/
macros.rs

1/// Returns the intended release for Sentry as an `Option<Cow<'static, str>>`.
2///
3/// This can be used with `ClientOptions` to set the release name.  It uses
4/// the information supplied by cargo to calculate a release.
5///
6/// # Examples
7///
8/// ```
9/// # #[macro_use] extern crate sentry;
10/// # fn main() {
11/// let _sentry = sentry::init(
12///     sentry::ClientOptions::new().maybe_release(sentry::release_name!()),
13/// );
14/// # }
15/// ```
16#[macro_export]
17macro_rules! release_name {
18    () => {{
19        use std::sync::Once;
20        static mut INIT: Once = Once::new();
21        static mut RELEASE: Option<String> = None;
22        unsafe {
23            INIT.call_once(|| {
24                RELEASE = option_env!("CARGO_PKG_NAME").and_then(|name| {
25                    option_env!("CARGO_PKG_VERSION").map(|version| format!("{}@{}", name, version))
26                });
27            });
28            RELEASE.as_ref().map(|x| {
29                let release: &'static str = ::std::mem::transmute(x.as_str());
30                ::std::borrow::Cow::Borrowed(release)
31            })
32        }
33    }};
34}
35
36// TODO: temporarily exported for use in `sentry` crate
37#[macro_export]
38#[doc(hidden)]
39macro_rules! with_client_impl {
40    ($body:block) => {
41        #[cfg(feature = "client")]
42        {
43            $body
44        }
45        #[cfg(not(feature = "client"))]
46        {
47            Default::default()
48        }
49    };
50}
51
52// TODO: temporarily exported for use in `sentry` crate
53#[macro_export]
54#[doc(hidden)]
55macro_rules! sentry_debug {
56    ($($arg:tt)*) => {{
57        let hub = $crate::Hub::current();
58        if hub.client().map_or(false, |c| c.options().debug) {
59            eprint!("[sentry] ");
60            eprintln!($($arg)*);
61        }
62    }}
63}
64
65/// Panics in debug builds and logs through `sentry_debug!` in non-debug builds.
66#[macro_export]
67#[doc(hidden)]
68macro_rules! debug_panic_or_log {
69    ($($arg:tt)*) => {{
70        #[cfg(debug_assertions)]
71        panic!($($arg)*);
72
73        #[cfg(not(debug_assertions))]
74        $crate::sentry_debug!($($arg)*);
75    }};
76}
77
78/// If the condition is false, panics in debug builds and logs in non-debug builds.
79#[macro_export]
80#[doc(hidden)]
81macro_rules! debug_assert_or_log {
82    ($cond:expr $(,)?) => {{
83        let condition = $cond;
84        if !condition {
85            $crate::debug_panic_or_log!("assertion failed: {}", stringify!($cond));
86        }
87    }};
88    ($cond:expr, $($arg:tt)+) => {{
89        let condition = $cond;
90        if !condition {
91            $crate::debug_panic_or_log!($($arg)+);
92        }
93    }};
94}
95
96#[allow(unused_macros)]
97macro_rules! minimal_unreachable {
98    () => {
99        panic!(
100            "this code should not be reachable. It's stubbed out for minimal usage. \
101             If you get this error this is a bug in the sentry minimal support"
102        );
103    };
104}
105
106#[cfg(test)]
107mod tests {
108    #[test]
109    fn debug_assert_or_log_does_not_panic_when_condition_holds() {
110        crate::debug_assert_or_log!(2 + 2 == 4, "should not panic");
111    }
112
113    #[test]
114    #[cfg(debug_assertions)]
115    #[should_panic(expected = "assertion failed: 1 == 2")]
116    fn debug_assert_or_log_panics_with_default_message_when_condition_fails() {
117        crate::debug_assert_or_log!(1 == 2);
118    }
119
120    #[test]
121    #[cfg(debug_assertions)]
122    #[should_panic(expected = "custom invariant message")]
123    fn debug_assert_or_log_panics_with_custom_message_when_condition_fails() {
124        crate::debug_assert_or_log!(false, "custom invariant message");
125    }
126
127    #[test]
128    #[cfg(not(debug_assertions))]
129    fn no_panic_without_debug_assertions() {
130        crate::debug_assert_or_log!(false, "should not panic");
131    }
132}