pgrx_pg_sys/submodules/
elog.rs

1//LICENSE Portions Copyright 2019-2021 ZomboDB, LLC.
2//LICENSE
3//LICENSE Portions Copyright 2021-2023 Technology Concepts & Design, Inc.
4//LICENSE
5//LICENSE Portions Copyright 2023-2023 PgCentral Foundation, Inc. <contact@pgcentral.org>
6//LICENSE
7//LICENSE All rights reserved.
8//LICENSE
9//LICENSE Use of this source code is governed by the MIT license that can be found in the LICENSE file.
10//! Access to Postgres' logging system
11
12/// Postgres' various logging levels
13#[allow(dead_code)]
14#[derive(Clone, Copy, Debug, Ord, PartialOrd, PartialEq, Eq)]
15pub enum PgLogLevel {
16    /// Debugging messages, in categories of decreasing detail
17    DEBUG5 = crate::DEBUG5 as isize,
18
19    /// Debugging messages, in categories of decreasing detail
20    DEBUG4 = crate::DEBUG4 as isize,
21
22    /// Debugging messages, in categories of decreasing detail
23    DEBUG3 = crate::DEBUG3 as isize,
24
25    /// Debugging messages, in categories of decreasing detail
26    DEBUG2 = crate::DEBUG2 as isize,
27
28    /// Debugging messages, in categories of decreasing detail
29    /// NOTE:  used by GUC debug_* variables
30    DEBUG1 = crate::DEBUG1 as isize,
31
32    /// Server operational messages; sent only to server log by default.
33    LOG = crate::LOG as isize,
34
35    /// Same as LOG for server reporting, but never sent to client.
36    #[allow(non_camel_case_types)]
37    LOG_SERVER_ONLY = crate::LOG_SERVER_ONLY as isize,
38
39    /// Messages specifically requested by user (eg VACUUM VERBOSE output); always sent to client
40    /// regardless of client_min_messages, but by default not sent to server log.
41    INFO = crate::INFO as isize,
42
43    /// Helpful messages to users about query operation; sent to client and not to server log by default.
44    NOTICE = crate::NOTICE as isize,
45
46    /// Warnings.  \[NOTICE\] is for expected messages like implicit sequence creation by SERIAL.
47    /// \[WARNING\] is for unexpected messages.
48    WARNING = crate::WARNING as isize,
49
50    /// user error - abort transaction; return to known state
51    ERROR = crate::ERROR as isize,
52
53    /// fatal error - abort process
54    FATAL = crate::FATAL as isize,
55
56    /// take down the other backends with me
57    PANIC = crate::PANIC as isize,
58}
59
60impl From<isize> for PgLogLevel {
61    #[inline]
62    fn from(i: isize) -> Self {
63        if i == PgLogLevel::DEBUG5 as isize {
64            PgLogLevel::DEBUG5
65        } else if i == PgLogLevel::DEBUG4 as isize {
66            PgLogLevel::DEBUG4
67        } else if i == PgLogLevel::DEBUG3 as isize {
68            PgLogLevel::DEBUG3
69        } else if i == PgLogLevel::DEBUG2 as isize {
70            PgLogLevel::DEBUG2
71        } else if i == PgLogLevel::DEBUG1 as isize {
72            PgLogLevel::DEBUG1
73        } else if i == PgLogLevel::INFO as isize {
74            PgLogLevel::INFO
75        } else if i == PgLogLevel::NOTICE as isize {
76            PgLogLevel::NOTICE
77        } else if i == PgLogLevel::WARNING as isize {
78            PgLogLevel::WARNING
79        } else if i == PgLogLevel::ERROR as isize {
80            PgLogLevel::ERROR
81        } else if i == PgLogLevel::FATAL as isize {
82            PgLogLevel::FATAL
83        } else if i == PgLogLevel::PANIC as isize {
84            PgLogLevel::PANIC
85        } else {
86            // ERROR seems like a good default
87            PgLogLevel::ERROR
88        }
89    }
90}
91
92impl From<i32> for PgLogLevel {
93    #[inline]
94    fn from(i: i32) -> Self {
95        (i as isize).into()
96    }
97}
98
99/// Log to Postgres' `debug5` log level.
100///
101/// This macro accepts arguments like the [`println`] and [`format`] macros.
102/// See [`fmt`](std::fmt) for information about options.
103///
104/// The output these logs goes to the PostgreSQL log file at `DEBUG5` level, depending on how the
105/// [PostgreSQL settings](https://www.postgresql.org/docs/current/runtime-config-logging.html) are configured.
106#[macro_export]
107macro_rules! debug5 {
108    ($($arg:tt)*) => (
109        {
110            extern crate alloc;
111            $crate::ereport!($crate::elog::PgLogLevel::DEBUG5, $crate::errcodes::PgSqlErrorCode::ERRCODE_SUCCESSFUL_COMPLETION, alloc::format!($($arg)*).as_str());
112        }
113    )
114}
115
116/// Log to Postgres' `debug4` log level.
117///
118/// This macro accepts arguments like the [`println`] and [`format`] macros.
119/// See [`fmt`](std::fmt) for information about options.
120///
121/// The output these logs goes to the PostgreSQL log file at `DEBUG4` level, depending on how the
122/// [PostgreSQL settings](https://www.postgresql.org/docs/current/runtime-config-logging.html) are configured.
123#[macro_export]
124macro_rules! debug4 {
125    ($($arg:tt)*) => (
126        {
127            extern crate alloc;
128            $crate::ereport!($crate::elog::PgLogLevel::DEBUG4, $crate::errcodes::PgSqlErrorCode::ERRCODE_SUCCESSFUL_COMPLETION, alloc::format!($($arg)*).as_str());
129        }
130    )
131}
132
133/// Log to Postgres' `debug3` log level.
134///
135/// This macro accepts arguments like the [`println`] and [`format`] macros.
136/// See [`fmt`](std::fmt) for information about options.
137///
138/// The output these logs goes to the PostgreSQL log file at `DEBUG3` level, depending on how the
139/// [PostgreSQL settings](https://www.postgresql.org/docs/current/runtime-config-logging.html) are configured.
140#[macro_export]
141macro_rules! debug3 {
142    ($($arg:tt)*) => (
143        {
144            extern crate alloc;
145            $crate::ereport!($crate::elog::PgLogLevel::DEBUG3, $crate::errcodes::PgSqlErrorCode::ERRCODE_SUCCESSFUL_COMPLETION, alloc::format!($($arg)*).as_str());
146        }
147    )
148}
149
150/// Log to Postgres' `debug2` log level.
151///
152/// This macro accepts arguments like the [`println`] and [`format`] macros.
153/// See [`fmt`](std::fmt) for information about options.
154///
155/// The output these logs goes to the PostgreSQL log file at `DEBUG2` level, depending on how the
156/// [PostgreSQL settings](https://www.postgresql.org/docs/current/runtime-config-logging.html) are configured.
157#[macro_export]
158macro_rules! debug2 {
159    ($($arg:tt)*) => (
160        {
161            extern crate alloc;
162            $crate::ereport!($crate::elog::PgLogLevel::DEBUG2, $crate::errcodes::PgSqlErrorCode::ERRCODE_SUCCESSFUL_COMPLETION, alloc::format!($($arg)*).as_str());
163        }
164    )
165}
166
167/// Log to Postgres' `debug1` log level.
168///
169/// This macro accepts arguments like the [`println`] and [`format`] macros.
170/// See [`fmt`](std::fmt) for information about options.
171///
172/// The output these logs goes to the PostgreSQL log file at `DEBUG1` level, depending on how the
173/// [PostgreSQL settings](https://www.postgresql.org/docs/current/runtime-config-logging.html) are configured.
174#[macro_export]
175macro_rules! debug1 {
176    ($($arg:tt)*) => (
177        {
178            extern crate alloc;
179            $crate::ereport!($crate::elog::PgLogLevel::DEBUG1, $crate::errcodes::PgSqlErrorCode::ERRCODE_SUCCESSFUL_COMPLETION, alloc::format!($($arg)*).as_str());
180        }
181    )
182}
183
184/// Log to Postgres' `log` log level.
185///
186/// This macro accepts arguments like the [`println`] and [`format`] macros.
187/// See [`fmt`](std::fmt) for information about options.
188///
189/// The output these logs goes to the PostgreSQL log file at `LOG` level, depending on how the
190/// [PostgreSQL settings](https://www.postgresql.org/docs/current/runtime-config-logging.html) are configured.
191#[macro_export]
192macro_rules! log {
193    ($($arg:tt)*) => (
194        {
195            extern crate alloc;
196            $crate::ereport!($crate::elog::PgLogLevel::LOG, $crate::errcodes::PgSqlErrorCode::ERRCODE_SUCCESSFUL_COMPLETION, alloc::format!($($arg)*).as_str());
197        }
198    )
199}
200
201/// Log to Postgres' `info` log level.
202///
203/// This macro accepts arguments like the [`println`] and [`format`] macros.
204/// See [`fmt`](std::fmt) for information about options.
205#[macro_export]
206macro_rules! info {
207    ($($arg:tt)*) => (
208        {
209            extern crate alloc;
210            $crate::ereport!($crate::elog::PgLogLevel::INFO, $crate::errcodes::PgSqlErrorCode::ERRCODE_SUCCESSFUL_COMPLETION, alloc::format!($($arg)*).as_str());
211        }
212    )
213}
214
215/// Log to Postgres' `notice` log level.
216///
217/// This macro accepts arguments like the [`println`] and [`format`] macros.
218/// See [`fmt`](std::fmt) for information about options.
219#[macro_export]
220macro_rules! notice {
221    ($($arg:tt)*) => (
222        {
223            extern crate alloc;
224            $crate::ereport!($crate::elog::PgLogLevel::NOTICE, $crate::errcodes::PgSqlErrorCode::ERRCODE_SUCCESSFUL_COMPLETION, alloc::format!($($arg)*).as_str());
225        }
226    )
227}
228
229/// Log to Postgres' `warning` log level.
230///
231/// This macro accepts arguments like the [`println`] and [`format`] macros.
232/// See [`fmt`](std::fmt) for information about options.
233#[macro_export]
234macro_rules! warning {
235    ($($arg:tt)*) => (
236        {
237            extern crate alloc;
238            $crate::ereport!($crate::elog::PgLogLevel::WARNING, $crate::errcodes::PgSqlErrorCode::ERRCODE_WARNING, alloc::format!($($arg)*).as_str());
239        }
240    )
241}
242
243/// Log to Postgres' `error` log level.  This will abort the current Postgres transaction.
244///
245/// This macro accepts arguments like the [`println`] and [`format`] macros.
246/// See [`fmt`](std::fmt) for information about options.
247#[macro_export]
248macro_rules! error {
249    ($($arg:tt)*) => (
250        {
251            extern crate alloc;
252            $crate::ereport!($crate::elog::PgLogLevel::ERROR, $crate::errcodes::PgSqlErrorCode::ERRCODE_INTERNAL_ERROR, alloc::format!($($arg)*).as_str());
253            unreachable!()
254        }
255    );
256}
257
258/// Log to Postgres' `fatal` log level.  This will abort the current Postgres backend connection process.
259///
260/// This macro accepts arguments like the [`println`] and [`format`] macros.
261/// See [`fmt`](std::fmt) for information about options.
262#[allow(non_snake_case)]
263#[macro_export]
264macro_rules! FATAL {
265    ($($arg:tt)*) => (
266        {
267            extern crate alloc;
268            $crate::ereport!($crate::elog::PgLogLevel::FATAL, $crate::errcodes::PgSqlErrorCode::ERRCODE_INTERNAL_ERROR, alloc::format!($($arg)*).as_str());
269            unreachable!()
270        }
271    )
272}
273
274/// Log to Postgres' `panic` log level.  This will cause the entire Postgres cluster to crash.
275///
276/// This macro accepts arguments like the [`println`] and [`format`] macros.
277/// See [`fmt`](std::fmt) for information about options.
278#[allow(non_snake_case)]
279#[macro_export]
280macro_rules! PANIC {
281    ($($arg:tt)*) => (
282        {
283            extern crate alloc;
284            $crate::ereport!($crate::elog::PgLogLevel::PANIC, $crate::errcodes::PgSqlErrorCode::ERRCODE_INTERNAL_ERROR, alloc::format!($($arg)*).as_str());
285            unreachable!()
286        }
287    )
288}
289
290// shamelessly borrowed from https://docs.rs/stdext/0.2.1/src/stdext/macros.rs.html#61-72
291/// This macro returns the name of the enclosing function.
292/// As the internal implementation is based on the [`std::any::type_name`], this macro derives
293/// all the limitations of this function.
294///
295/// [`std::any::type_name`]: https://doc.rust-lang.org/std/any/fn.type_name.html
296#[macro_export]
297macro_rules! function_name {
298    () => {{
299        // Okay, this is ugly, I get it. However, this is the best we can get on a stable rust.
300        fn f() {}
301        fn type_name_of<T>(_: T) -> &'static str {
302            core::any::type_name::<T>()
303        }
304        let name = type_name_of(f);
305        // `3` is the length of the `::f`.
306        &name[..name.len() - 3]
307    }};
308}
309
310/// Sends some kind of message to Postgres, and if it's a [PgLogLevel::ERROR] or greater, Postgres'
311/// error handling takes over and, in the case of [PgLogLevel::ERROR], aborts the current transaction.
312///
313/// This macro is necessary when one needs to supply a specific SQL error code as part of their
314/// error message.
315///
316/// The argument order is:
317/// - `log_level: [PgLogLevel]`
318/// - `error_code: [PgSqlErrorCode]`
319/// - `message: String`
320/// - (optional) `detail: String`
321///
322/// ## Examples
323///
324/// ```rust,no_run
325/// # use pgrx_pg_sys::ereport;
326/// # use pgrx_pg_sys::elog::PgLogLevel;
327/// # use pgrx_pg_sys::errcodes::PgSqlErrorCode;
328/// ereport!(PgLogLevel::ERROR, PgSqlErrorCode::ERRCODE_INTERNAL_ERROR, "oh noes!"); // abort the transaction
329/// ```
330///
331/// ```rust,no_run
332/// # use pgrx_pg_sys::ereport;
333/// # use pgrx_pg_sys::elog::PgLogLevel;
334/// # use pgrx_pg_sys::errcodes::PgSqlErrorCode;
335/// ereport!(PgLogLevel::LOG, PgSqlErrorCode::ERRCODE_SUCCESSFUL_COMPLETION, "this is just a message"); // log output only
336/// ```
337#[macro_export]
338macro_rules! ereport {
339    (ERROR, $errcode:expr, $message:expr $(, $detail:expr)? $(,)?) => {
340        $crate::panic::ErrorReport::new($errcode, $message, $crate::function_name!())
341            $(.set_detail($detail))?
342            .report($crate::elog::PgLogLevel::ERROR);
343        unreachable!();
344    };
345
346    (PANIC, $errcode:expr, $message:expr $(, $detail:expr)? $(,)?) => {
347        $crate::panic::ErrorReport::new($errcode, $message, $crate::function_name!())
348            $(.set_detail($detail))?
349            .report($crate::elog::PgLogLevel::PANIC);
350        unreachable!();
351    };
352
353    (FATAL, $errcode:expr, $message:expr $(, $detail:expr)? $(,)?) => {
354        $crate::panic::ErrorReport::new($errcode, $message, $crate::function_name!())
355            $(.set_detail($detail))?
356            .report($crate::elog::PgLogLevel::FATAL);
357        unreachable!();
358    };
359
360    (WARNING, $errcode:expr, $message:expr $(, $detail:expr)? $(,)?) => {
361        $crate::panic::ErrorReport::new($errcode, $message, $crate::function_name!())
362            $(.set_detail($detail))?
363            .report($crate::elog::PgLogLevel::WARNING)
364    };
365
366    (NOTICE, $errcode:expr, $message:expr $(, $detail:expr)? $(,)?) => {
367        $crate::panic::ErrorReport::new($errcode, $message, $crate::function_name!())
368            $(.set_detail($detail))?
369            .report($crate::elog::PgLogLevel::NOTICE)
370    };
371
372    (INFO, $errcode:expr, $message:expr $(, $detail:expr)? $(,)?) => {
373        $crate::panic::ErrorReport::new($errcode, $message, $crate::function_name!())
374            $(.set_detail($detail))?
375            .report($crate::elog::PgLogLevel::INFO)
376    };
377
378    (LOG, $errcode:expr, $message:expr $(, $detail:expr)? $(,)?) => {
379        $crate::panic::ErrorReport::new($errcode, $message, $crate::function_name!())
380            $(.set_detail($detail))?
381            .report($crate::elog::PgLogLevel::LOG)
382    };
383
384    (DEBUG5, $errcode:expr, $message:expr $(, $detail:expr)? $(,)?) => {
385        $crate::panic::ErrorReport::new($errcode, $message, $crate::function_name!())
386            $(.set_detail($detail))?
387            .report($crate::elog::PgLogLevel::DEBUG5)
388    };
389
390    (DEBUG4, $errcode:expr, $message:expr $(, $detail:expr)? $(,)?) => {
391        $crate::panic::ErrorReport::new($errcode, $message, $crate::function_name!())
392            $(.set_detail($detail))?
393            .report($crate::elog::PgLogLevel::DEBUG4)
394    };
395
396    (DEBUG3, $errcode:expr, $message:expr $(, $detail:expr)? $(,)?) => {
397        $crate::panic::ErrorReport::new($errcode, $message, $crate::function_name!())
398            $(.set_detail($detail))?
399            .report($crate::elog::PgLogLevel::DEBUG3)
400    };
401
402    (DEBUG2, $errcode:expr, $message:expr $(, $detail:expr)? $(,)?) => {
403        $crate::panic::ErrorReport::new($errcode, $message, $crate::function_name!())
404            $(.set_detail($detail))?
405            .report($crate::elog::PgLogLevel::DEBUG2)
406    };
407
408    (DEBUG1, $errcode:expr, $message:expr $(, $detail:expr)? $(,)?) => {
409        $crate::panic::ErrorReport::new($errcode, $message, $crate::function_name!())
410            $(.set_detail($detail))?
411            .report($crate::elog::PgLogLevel::DEBUG1)
412    };
413
414    ($loglevel:expr, $errcode:expr, $message:expr $(, $detail:expr)? $(,)?) => {
415        $crate::panic::ErrorReport::new($errcode, $message, $crate::function_name!())
416            $(.set_detail($detail))?
417            .report($loglevel);
418    };
419}
420
421/// Is an interrupt pending?
422#[inline]
423pub fn interrupt_pending() -> bool {
424    unsafe { crate::InterruptPending != 0 }
425}
426
427/// If an interrupt is pending (perhaps a user-initiated "cancel query" message to this backend),
428/// this will safely abort the current transaction
429#[macro_export]
430macro_rules! check_for_interrupts {
431    () => {
432        #[allow(unused_unsafe)]
433        unsafe {
434            if $crate::InterruptPending != 0 {
435                $crate::ProcessInterrupts();
436            }
437        }
438    };
439}