mirror of
https://github.com/postgres/postgres.git
synced 2026-02-28 20:30:45 -05:00
If exactly one relation type is requested in a command of the \dtisv family, say "tables", "indexes", etc instead of "relations". This should cover the majority of actual uses, without creating a huge number of new translatable strings. The error messages for no matching relations are adjusted as well. In passing, invent "pg_log_error_internal()" to be used for frontend error messages that don't seem to need translation, analogously to errmsg_internal() in the backend. The implementation is a bit cheesy, being just a macro to prevent xgettext from recognizing a trigger keyword. This won't avoid a useless gettext lookup cycle at runtime --- but surely we don't care about an extra microsecond or two in what's supposed to be a can't-happen case. I (tgl) also made "pg_fatal_internal()", though it's not used in this patch. Author: Greg Sabino Mullane <htamfids@gmail.com> Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us> Discussion: https://postgr.es/m/CAKAnmm+7o93fQV-RFkGaN1QnP-0D4d3JTykD+cLueqjDMKdfag@mail.gmail.com
163 lines
4.4 KiB
C
163 lines
4.4 KiB
C
/*-------------------------------------------------------------------------
|
|
* Logging framework for frontend programs
|
|
*
|
|
* Copyright (c) 2018-2025, PostgreSQL Global Development Group
|
|
*
|
|
* src/include/common/logging.h
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
#ifndef COMMON_LOGGING_H
|
|
#define COMMON_LOGGING_H
|
|
|
|
/*
|
|
* Log levels are informational only. They do not affect program flow.
|
|
*/
|
|
enum pg_log_level
|
|
{
|
|
/*
|
|
* Not initialized yet (not to be used as an actual message log level).
|
|
*/
|
|
PG_LOG_NOTSET = 0,
|
|
|
|
/*
|
|
* Low level messages that are normally off by default.
|
|
*/
|
|
PG_LOG_DEBUG,
|
|
|
|
/*
|
|
* Any program messages that go to stderr, shown by default. (The
|
|
* program's normal output should go to stdout and not use the logging
|
|
* system.)
|
|
*/
|
|
PG_LOG_INFO,
|
|
|
|
/*
|
|
* Warnings and "almost" errors, depends on the program
|
|
*/
|
|
PG_LOG_WARNING,
|
|
|
|
/*
|
|
* Errors
|
|
*/
|
|
PG_LOG_ERROR,
|
|
|
|
/*
|
|
* Turn all logging off (not to be used as an actual message log level).
|
|
*/
|
|
PG_LOG_OFF,
|
|
};
|
|
|
|
/*
|
|
* __pg_log_level is the minimum log level that will actually be shown.
|
|
*/
|
|
extern enum pg_log_level __pg_log_level;
|
|
|
|
/*
|
|
* A log message can have several parts. The primary message is required,
|
|
* others are optional. When emitting multiple parts, do so in the order of
|
|
* this enum, for consistency.
|
|
*/
|
|
enum pg_log_part
|
|
{
|
|
/*
|
|
* The primary message. Try to keep it to one line; follow the backend's
|
|
* style guideline for primary messages.
|
|
*/
|
|
PG_LOG_PRIMARY,
|
|
|
|
/*
|
|
* Additional detail. Follow the backend's style guideline for detail
|
|
* messages.
|
|
*/
|
|
PG_LOG_DETAIL,
|
|
|
|
/*
|
|
* Hint (not guaranteed correct) about how to fix the problem. Follow the
|
|
* backend's style guideline for hint messages.
|
|
*/
|
|
PG_LOG_HINT,
|
|
};
|
|
|
|
/*
|
|
* Kind of a hack to be able to produce the psql output exactly as required by
|
|
* the regression tests.
|
|
*/
|
|
#define PG_LOG_FLAG_TERSE 1
|
|
|
|
void pg_logging_init(const char *argv0);
|
|
void pg_logging_config(int new_flags);
|
|
void pg_logging_set_level(enum pg_log_level new_level);
|
|
void pg_logging_increase_verbosity(void);
|
|
void pg_logging_set_pre_callback(void (*cb) (void));
|
|
void pg_logging_set_locus_callback(void (*cb) (const char **filename, uint64 *lineno));
|
|
|
|
void pg_log_generic(enum pg_log_level level, enum pg_log_part part,
|
|
const char *pg_restrict fmt,...)
|
|
pg_attribute_printf(3, 4);
|
|
void pg_log_generic_v(enum pg_log_level level, enum pg_log_part part,
|
|
const char *pg_restrict fmt, va_list ap)
|
|
pg_attribute_printf(3, 0);
|
|
|
|
/*
|
|
* Preferred style is to use these macros to perform logging; don't call
|
|
* pg_log_generic[_v] directly, except perhaps in error interface code.
|
|
*/
|
|
#define pg_log_error(...) \
|
|
pg_log_generic(PG_LOG_ERROR, PG_LOG_PRIMARY, __VA_ARGS__)
|
|
|
|
#define pg_log_error_detail(...) \
|
|
pg_log_generic(PG_LOG_ERROR, PG_LOG_DETAIL, __VA_ARGS__)
|
|
|
|
#define pg_log_error_hint(...) \
|
|
pg_log_generic(PG_LOG_ERROR, PG_LOG_HINT, __VA_ARGS__)
|
|
|
|
#define pg_log_warning(...) \
|
|
pg_log_generic(PG_LOG_WARNING, PG_LOG_PRIMARY, __VA_ARGS__)
|
|
|
|
#define pg_log_warning_detail(...) \
|
|
pg_log_generic(PG_LOG_WARNING, PG_LOG_DETAIL, __VA_ARGS__)
|
|
|
|
#define pg_log_warning_hint(...) \
|
|
pg_log_generic(PG_LOG_WARNING, PG_LOG_HINT, __VA_ARGS__)
|
|
|
|
#define pg_log_info(...) \
|
|
pg_log_generic(PG_LOG_INFO, PG_LOG_PRIMARY, __VA_ARGS__)
|
|
|
|
#define pg_log_info_detail(...) \
|
|
pg_log_generic(PG_LOG_INFO, PG_LOG_DETAIL, __VA_ARGS__)
|
|
|
|
#define pg_log_info_hint(...) \
|
|
pg_log_generic(PG_LOG_INFO, PG_LOG_HINT, __VA_ARGS__)
|
|
|
|
#define pg_log_debug(...) do { \
|
|
if (unlikely(__pg_log_level <= PG_LOG_DEBUG)) \
|
|
pg_log_generic(PG_LOG_DEBUG, PG_LOG_PRIMARY, __VA_ARGS__); \
|
|
} while(0)
|
|
|
|
#define pg_log_debug_detail(...) do { \
|
|
if (unlikely(__pg_log_level <= PG_LOG_DEBUG)) \
|
|
pg_log_generic(PG_LOG_DEBUG, PG_LOG_DETAIL, __VA_ARGS__); \
|
|
} while(0)
|
|
|
|
#define pg_log_debug_hint(...) do { \
|
|
if (unlikely(__pg_log_level <= PG_LOG_DEBUG)) \
|
|
pg_log_generic(PG_LOG_DEBUG, PG_LOG_HINT, __VA_ARGS__); \
|
|
} while(0)
|
|
|
|
/*
|
|
* A common shortcut: pg_log_error() and immediately exit(1).
|
|
*/
|
|
#define pg_fatal(...) do { \
|
|
pg_log_generic(PG_LOG_ERROR, PG_LOG_PRIMARY, __VA_ARGS__); \
|
|
exit(1); \
|
|
} while(0)
|
|
|
|
/*
|
|
* Use these variants for "can't happen" cases, if it seems translating their
|
|
* messages would be a waste of effort.
|
|
*/
|
|
#define pg_log_error_internal(...) pg_log_error(__VA_ARGS__)
|
|
#define pg_fatal_internal(...) pg_fatal(__VA_ARGS__)
|
|
|
|
#endif /* COMMON_LOGGING_H */
|