pgx_pg_sys/submodules/elog.rs
1/*
2Portions Copyright 2019-2021 ZomboDB, LLC.
3Portions Copyright 2021-2022 Technology Concepts & Design, Inc. <support@tcdi.com>
4
5All rights reserved.
6
7Use of this source code is governed by the MIT license that can be found in the LICENSE file.
8*/
9
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`](std::println) and [`format`](std::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`](std::println) and [`format`](std::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`](std::println) and [`format`](std::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`](std::println) and [`format`](std::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`](std::println) and [`format`](std::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`](std::println) and [`format`](std::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`](std::println) and [`format`](std::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`](std::println) and [`format`](std::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`](std::println) and [`format`](std::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`](std::println) and [`format`](std::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`](std::println) and [`format`](std::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`](std::println) and [`format`](std::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 pgx_pg_sys::ereport;
326/// # use pgx_pg_sys::elog::PgLogLevel;
327/// # use pgx_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 pgx_pg_sys::ereport;
333/// # use pgx_pg_sys::elog::PgLogLevel;
334/// # use pgx_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) => {
340 $crate::panic::ErrorReport::new($errcode, $message, $crate::function_name!())
341 .report($crate::elog::PgLogLevel::ERROR);
342 unreachable!();
343 };
344
345 (PANIC, $errcode:expr, $message:expr) => {
346 $crate::panic::ErrorReport::new($errcode, $message, $crate::function_name!())
347 .report($crate::elog::PgLogLevel::PANIC);
348 unreachable!();
349 };
350
351 (FATAL, $errcode:expr, $message:expr) => {
352 $crate::panic::ErrorReport::new($errcode, $message, $crate::function_name!())
353 .report($crate::elog::PgLogLevel::FATAL);
354 unreachable!();
355 };
356
357 (WARNING, $errcode:expr, $message:expr) => {
358 $crate::panic::ErrorReport::new($errcode, $message, $crate::function_name!())
359 .report($crate::elog::PgLogLevel::WARNING)
360 };
361
362 (NOTICE, $errcode:expr, $message:expr) => {
363 $crate::panic::ErrorReport::new($errcode, $message, $crate::function_name!())
364 .report($crate::elog::PgLogLevel::NOTICE)
365 };
366
367 (INFO, $errcode:expr, $message:expr) => {
368 $crate::panic::ErrorReport::new($errcode, $message, $crate::function_name!())
369 .report($crate::elog::PgLogLevel::INFO)
370 };
371
372 (LOG, $errcode:expr, $message:expr) => {
373 $crate::panic::ErrorReport::new($errcode, $message, $crate::function_name!())
374 .report($crate::elog::PgLogLevel::LOG)
375 };
376
377 (DEBUG5, $errcode:expr, $message:expr) => {
378 $crate::panic::ErrorReport::new($errcode, $message, $crate::function_name!())
379 .report($crate::elog::PgLogLevel::DEBUG5)
380 };
381
382 (DEBUG4, $errcode:expr, $message:expr) => {
383 $crate::panic::ErrorReport::new($errcode, $message, $crate::function_name!())
384 .report($crate::elog::PgLogLevel::DEBUG4)
385 };
386
387 (DEBUG3, $errcode:expr, $message:expr) => {
388 $crate::panic::ErrorReport::new($errcode, $message, $crate::function_name!())
389 .report($crate::elog::PgLogLevel::DEBUG3)
390 };
391
392 (DEBUG2, $errcode:expr, $message:expr) => {
393 $crate::panic::ErrorReport::new($errcode, $message, $crate::function_name!())
394 .report($crate::elog::PgLogLevel::DEBUG2)
395 };
396
397 (DEBUG1, $errcode:expr, $message:expr) => {
398 $crate::panic::ErrorReport::new($errcode, $message, $crate::function_name!())
399 .report($crate::elog::PgLogLevel::DEBUG1)
400 };
401
402 ($loglevel:expr, $errcode:expr, $message:expr) => {
403 $crate::panic::ErrorReport::new($errcode, $message, $crate::function_name!())
404 .report($loglevel);
405 };
406
407 ($loglevel:expr, $errcode:expr, $message:expr, $detail:expr) => {
408 $crate::panic::ErrorReport::new($errcode, $message, $crate::function_name!())
409 .set_detail($detail)
410 .report($loglevel);
411 };
412}
413
414/// Is an interrupt pending?
415#[inline]
416pub fn interrupt_pending() -> bool {
417 #[cfg(any(feature = "pg11"))]
418 unsafe {
419 crate::InterruptPending
420 }
421
422 #[cfg(any(feature = "pg12", feature = "pg13", feature = "pg14", feature = "pg15"))]
423 unsafe {
424 crate::InterruptPending != 0
425 }
426}
427
428/// If an interrupt is pending (perhaps a user-initiated "cancel query" message to this backend),
429/// this will safely abort the current transaction
430#[macro_export]
431macro_rules! check_for_interrupts {
432 () => {
433 #[cfg(any(feature = "pg11"))]
434 #[allow(unused_unsafe)]
435 unsafe {
436 if $crate::InterruptPending {
437 $crate::ProcessInterrupts();
438 }
439 }
440
441 #[cfg(any(feature = "pg12", feature = "pg13", feature = "pg14", feature = "pg15"))]
442 #[allow(unused_unsafe)]
443 unsafe {
444 if $crate::InterruptPending != 0 {
445 $crate::ProcessInterrupts();
446 }
447 }
448 };
449}