udf/macros.rs
1//! macro definitions
2
3/// Print a formatted log message to `stderr` to display in server logs
4///
5/// Performs formatting to match other common SQL error logs, roughly:
6///
7/// ```text
8/// 2022-10-15 13:12:54+00:00 [Warning] Udf: this is the message
9/// ```
10///
11/// ```
12/// # #[cfg(not(miri))] // need to skip Miri because. it can't cross FFI
13/// # fn test() {
14///
15/// use udf::udf_log;
16///
17/// // Prints "2022-10-08 05:27:30+00:00 [Error] UDF: this is an error"
18/// // This matches the default entrypoint log format
19/// udf_log!(Error: "this is an error");
20///
21/// udf_log!(Warning: "this is a warning");
22///
23/// udf_log!(Note: "this is info: value {}", 10 + 10);
24///
25/// udf_log!(Debug: "this is a debug message");
26///
27/// udf_log!("i print without the '[Level] UDF:' formatting");
28///
29/// # }
30/// # #[cfg(not(miri))]
31/// # test();
32/// ```
33#[macro_export]
34macro_rules! udf_log {
35 (Critical: $($msg:tt)*) => {{
36 let formatted = format!("[Critical] UDF: {}", format!($($msg)*));
37 udf_log!(formatted);
38 }};
39 (Error: $($msg:tt)*) => {{
40 let formatted = format!("[Error] UDF: {}", format!($($msg)*));
41 udf_log!(formatted);
42 }};
43 (Warning: $($msg:tt)*) => {{
44 let formatted = format!("[Warning] UDF: {}", format!($($msg)*));
45 udf_log!(formatted);
46 }};
47 (Note: $($msg:tt)*) => {{
48 let formatted = format!("[Note] UDF: {}", format!($($msg)*));
49 udf_log!(formatted);
50 }};
51 (Debug: $($msg:tt)*) => {{
52 let formatted = format!("[Debug] UDF: {}", format!($($msg)*));
53 udf_log!(formatted);
54 }};
55 ($msg:tt) => {
56 eprintln!(
57 "{} {}",
58 $crate::chrono::Utc::now().format("%Y-%m-%d %H:%M:%S%:z"),
59 $msg
60 );
61 };
62}
63
64/// Log a call to a function, with optional printing of state
65///
66/// Log calls are only printed with feature "logging-debug". Call state is only
67/// printed with feature "logging-debug-calls".
68macro_rules! log_call {
69 // Log for entering a function
70 (enter: $name:literal, $type:ty, $($state:expr),*) => {
71 log_call!(@common: "ENTER", "receive", $name, $type, $($state),*)
72 };
73
74 // Logging for exiting a function
75 (exit: $name:literal, $type:ty, $($state:expr),*) => {
76 log_call!(@common: "EXIT", "return", $name, $type, $($state),*)
77 };
78
79 // Internal macro, common enter/exit printing
80 (@common:
81 $enter_or_exit:literal,
82 $receive_or_return:literal,
83 $fn_name:literal,
84 $type:ty,
85 $($state:expr),*
86 ) => {{
87 #[cfg(feature = "logging-debug")]
88 $crate::udf_log!(
89 Debug: "{} {} for '{}'",
90 $enter_or_exit, $fn_name, std::any::type_name::<$type>()
91 );
92
93 cfg_if::cfg_if! {
94 if #[cfg(feature = "logging-debug-calls")] {
95 $crate::udf_log!(Debug: "data {} state at {}", $receive_or_return, $fn_name);
96 // For each specified item, print the expression and its value
97 $(
98 $crate::udf_log!(
99 Debug: "[{}]: {} = {:#?}",
100 $receive_or_return, std::stringify!($state), $state
101 );
102 )*
103 }
104 }
105 }}
106}