s2n_quic_core/
probe.rs

1// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2// SPDX-License-Identifier: Apache-2.0
3
4#[doc(hidden)]
5#[macro_export]
6macro_rules! __probe_define__ {
7    (extern "probe" {
8        $(
9            $(
10                #[doc = $doc:tt]
11            )*
12            #[link_name = $link_name:ident]
13            $vis:vis fn $fun:ident($($arg:ident: $arg_t:ty),* $(,)?);
14        )*
15    }) => {
16        $(
17            $(
18                #[doc = $doc]
19            )*
20            #[inline(always)]
21            $vis fn $fun($($arg: $arg_t),*) {
22                $crate::probe::__trace!(
23                    name: stringify!($fun),
24                    target: concat!(module_path!(), "::", stringify!($fun)),
25                    $(
26                        $arg = ?$arg,
27                    )*
28                );
29
30                $crate::probe::__usdt!(
31                    s2n_quic,
32                    $link_name,
33                    $(
34                        $arg
35                    ),*
36                );
37            }
38        )*
39    }
40}
41
42#[doc(inline)]
43pub use __probe_define__ as define;
44
45#[cfg(feature = "probe-tracing")]
46#[doc(hidden)]
47pub use tracing::trace as __trace;
48
49#[cfg(not(feature = "probe-tracing"))]
50#[macro_export]
51#[doc(hidden)]
52macro_rules! __trace_impl__ {
53    ($($fmt:tt)*) => {};
54}
55
56#[cfg(not(feature = "probe-tracing"))]
57#[doc(hidden)]
58pub use __trace_impl__ as __trace;
59
60#[cfg(feature = "usdt")]
61#[doc(hidden)]
62pub use probe::probe as __usdt_emit__;
63
64#[cfg(feature = "usdt")]
65#[doc(hidden)]
66#[macro_export]
67macro_rules! __usdt_impl__ {
68    ($provider:ident, $name:ident $(, $arg:ident)* $(,)?) => {{
69        // define a function with inline(never) to consolidate probes to this single location
70        #[inline(never)]
71        fn probe($($arg: isize),*) {
72            $crate::probe::__usdt_emit__!($provider, $name, $($arg),*);
73        }
74        probe($(
75            $crate::probe::Arg::into_usdt($arg),
76        )*);
77    }}
78}
79
80#[cfg(not(feature = "usdt"))]
81#[doc(hidden)]
82#[macro_export]
83macro_rules! __usdt_impl__ {
84    ($provider:ident, $name:ident $(, $arg:ident)* $(,)?) => {{
85        // make sure all of the args implement Arg
86        $(
87            let _ = $crate::probe::Arg::into_usdt($arg);
88        )*
89    }}
90}
91
92#[doc(inline)]
93pub use __usdt_impl__ as __usdt;
94
95pub trait Arg {
96    fn into_usdt(self) -> isize;
97}
98
99macro_rules! impl_int_arg {
100    ($($ty:ident),* $(,)?) => {
101        $(
102            impl Arg for $ty {
103                #[inline]
104                fn into_usdt(self) -> isize {
105                    self as _
106                }
107            }
108        )*
109    }
110}
111
112impl_int_arg!(u8, i8, u16, i16, u32, i32, u64, i64, usize, isize);
113
114impl Arg for bool {
115    #[inline]
116    fn into_usdt(self) -> isize {
117        if self {
118            1
119        } else {
120            0
121        }
122    }
123}
124
125impl Arg for core::time::Duration {
126    #[inline]
127    fn into_usdt(self) -> isize {
128        self.as_nanos() as _
129    }
130}
131
132impl Arg for crate::time::Timestamp {
133    #[inline]
134    fn into_usdt(self) -> isize {
135        unsafe { self.as_duration().into_usdt() }
136    }
137}
138
139impl Arg for crate::packet::number::PacketNumber {
140    #[inline]
141    fn into_usdt(self) -> isize {
142        self.as_u64().into_usdt()
143    }
144}
145
146impl Arg for crate::varint::VarInt {
147    #[inline]
148    fn into_usdt(self) -> isize {
149        self.as_u64().into_usdt()
150    }
151}
152
153impl Arg for &core::ffi::CStr {
154    #[inline]
155    fn into_usdt(self) -> isize {
156        self.as_ptr() as _
157    }
158}
159
160#[cfg(test)]
161mod tests {
162    crate::probe::define!(
163        extern "probe" {
164            /// Testing the probe capability
165            #[link_name = s2n_quic_core__probe__tests__test123]
166            pub fn test123(a: u8, b: core::time::Duration, c: u64);
167        }
168    );
169
170    #[test]
171    fn call_probe_test() {
172        test123(123, core::time::Duration::from_secs(123), 123);
173    }
174}