diff options
author | Pavan Deolasee | 2016-03-04 06:51:18 +0000 |
---|---|---|
committer | Pavan Deolasee | 2016-10-18 10:00:19 +0000 |
commit | f38b50177dd627aeff8cff01dd9d94b94c0f3dd4 (patch) | |
tree | 6daf6e6e4727b76452e88565b5a000d3fdd1c43c | |
parent | f2efdfc1328ac83dfaf586e807e3aacc85e871da (diff) |
Add support for process-level control for overriding log levels.
This patch changes the behaviour of pg_msgmodule_set/change() functions. These
functions now only change the log levels for various messages, but the actual
logging won't start until one of the following enable() function is called.
This patch adds a few more functions:
- pg_msgmodule_enable(pid) - the given pid will start logging as per the
current settings for various msgs.
- pg_msgmodule_disable(pid) - the given pid will stop logging and use the
compile time settings
- pg_msgmodule_enable_all(persistent) - all current processes will start
logging as per the current setting. If "persistent" is set to true then all
new processes will also log as per the setting
- pg_msgmodule_disable_all() - all current and future processes will stop
logging and only use compile time settings.
-rw-r--r-- | src/backend/tcop/postgres.c | 4 | ||||
-rw-r--r-- | src/backend/utils/error/elog.c | 253 | ||||
-rw-r--r-- | src/include/catalog/pg_proc.h | 8 | ||||
-rw-r--r-- | src/include/utils/builtins.h | 5 | ||||
-rw-r--r-- | src/include/utils/elog.h | 2 |
5 files changed, 249 insertions, 23 deletions
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index 36e07dfcf8..109114e696 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -4305,6 +4305,10 @@ PostgresMain(int argc, char *argv[], prev_ParseAnalyze_callback = post_parse_analyze_hook; post_parse_analyze_hook = ParseAnalyze_callback; +#ifdef USE_MODULE_MSGIDS + AtProcStart_MsgModule(); +#endif + /* if we exit, try to release cluster lock properly */ on_shmem_exit(PGXCCleanClusterLock, 0); diff --git a/src/backend/utils/error/elog.c b/src/backend/utils/error/elog.c index dabe5c2c60..909e2667e6 100644 --- a/src/backend/utils/error/elog.c +++ b/src/backend/utils/error/elog.c @@ -73,7 +73,9 @@ #include "postmaster/syslogger.h" #include "storage/ipc.h" #include "storage/proc.h" +#include "storage/procarray.h" #include "tcop/tcopprot.h" +#include "utils/builtins.h" #include "utils/guc.h" #include "utils/memutils.h" #include "utils/ps_status.h" @@ -88,6 +90,10 @@ static const char *err_gettext(const char *str) pg_attribute_format_arg(1); static void set_errdata_field(MemoryContextData *cxt, char **ptr, const char *str); +#ifdef USE_MODULE_MSGIDS +static void AtProcExit_MsgModule(int code, Datum arg); +static bool pg_msgmodule_enable_disable(int32 pid, bool enable); +#endif /* Global variables */ ErrorContextCallback *error_context_stack = NULL; @@ -189,7 +195,27 @@ static void setup_formatted_log_time(void); static void setup_formatted_start_time(void); #ifdef USE_MODULE_MSGIDS -char *MsgModuleCtl; +typedef struct MsgModuleCtlStruct +{ + bool mm_enabled; + bool mm_persistent; + char mm_flags[FLEXIBLE_ARRAY_MEMBER]; +} MsgModuleCtlStruct; + +#define StartOfBackendFlags \ + ( \ + PGXL_MSG_MAX_MODULES * \ + PGXL_MSG_MAX_FILEIDS_PER_MODULE * \ + PGXL_MSG_MAX_MSGIDS_PER_FILE \ + ) + +#define SizeOfMsgModuleCtlStruct \ + ( \ + offsetof(MsgModuleCtlStruct, mm_flags) + \ + StartOfBackendFlags + \ + MaxBackends \ + ) +static MsgModuleCtlStruct *MsgModuleCtl; #endif /* @@ -3747,7 +3773,7 @@ write_stderr(const char *fmt,...) #ifdef USE_MODULE_MSGIDS static int -get_overriden_log_level(int moduleid, int fileid, int msgid, int origlevel) +get_overridden_log_level(int moduleid, int fileid, int msgid, int origlevel) { uint32 position; int value, relative, change, elevel; @@ -3759,6 +3785,9 @@ get_overriden_log_level(int moduleid, int fileid, int msgid, int origlevel) if (!IsPostmasterEnvironment || IsInitProcessingMode()) return origlevel; + if (!MsgModuleCtl->mm_enabled) + return origlevel; + /* * Reject invalid bounds */ @@ -3770,6 +3799,9 @@ get_overriden_log_level(int moduleid, int fileid, int msgid, int origlevel) if (origlevel < DEBUG5 || origlevel >= LOG) return origlevel; + if (!(MsgModuleCtl->mm_flags[StartOfBackendFlags + MyBackendId])) + return origlevel; + elevel = origlevel; /* @@ -3781,7 +3813,7 @@ get_overriden_log_level(int moduleid, int fileid, int msgid, int origlevel) (msgid - 1); /* Read once */ - value = MsgModuleCtl[position]; + value = MsgModuleCtl->mm_flags[position]; relative = value & 0x80; change = value & 0x7f; @@ -3836,7 +3868,7 @@ is_log_level_output(int elevel, * especially be useful to turn some specific ERROR messages into FATAL or * PANIC to be able to get a core dump for analysis. */ - elevel = get_overriden_log_level(moduleid, fileid, msgid, + elevel = get_overridden_log_level(moduleid, fileid, msgid, elevel); #endif @@ -3887,8 +3919,6 @@ trace_recovery(int trace_level) Size MsgModuleShmemSize(void) { - Size mm_size; - /* * One byte per message to store overridden log level. * !!TODO We don't really need a byte and a few bits would be enough. So @@ -3901,14 +3931,12 @@ MsgModuleShmemSize(void) * to the largest value that any one module uses, but the actual values are * much smaller * - * In theory, we could also have separate area for each backend so that - * logging can be controlled at a backend level. But the current - * representation is not at all efficient to do that. + * Also have a separate area for MaxBackends so that caller can selectively + * change logging for individual backends. Note that we don't support + * having different logging levels for different backends. So either a + * backend honours the module/file/msg level overrides or it does not. */ - mm_size = mul_size(PGXL_MSG_MAX_MODULES, PGXL_MSG_MAX_FILEIDS_PER_MODULE); - mm_size = mul_size(mm_size, PGXL_MSG_MAX_MSGIDS_PER_FILE); - - return mm_size; + return SizeOfMsgModuleCtlStruct; } void @@ -3917,12 +3945,20 @@ MsgModuleShmemInit(void) bool found; MsgModuleCtl = ShmemInitStruct("Message Module Struct", - (PGXL_MSG_MAX_MODULES * - PGXL_MSG_MAX_FILEIDS_PER_MODULE * - PGXL_MSG_MAX_MSGIDS_PER_FILE), + SizeOfMsgModuleCtlStruct, &found); } +void +AtProcStart_MsgModule(void) +{ + if (MsgModuleCtl->mm_persistent) + MsgModuleCtl->mm_flags[StartOfBackendFlags + MyBackendId] = true; + else + MsgModuleCtl->mm_flags[StartOfBackendFlags + MyBackendId] = false; + before_shmem_exit(AtProcExit_MsgModule, 0); +} + static bool pg_msgmodule_internal(int32 moduleid, int32 fileid, int32 msgid, char value) { @@ -3947,8 +3983,8 @@ pg_msgmodule_internal(int32 moduleid, int32 fileid, int32 msgid, char value) */ len = PGXL_MSG_MAX_FILEIDS_PER_MODULE * PGXL_MSG_MAX_MSGIDS_PER_FILE; start_position = (moduleid - 1) * len; - memset(MsgModuleCtl + start_position, value, len); - return true; + memset(MsgModuleCtl->mm_flags + start_position, value, len); + goto success; } else { @@ -3965,8 +4001,8 @@ pg_msgmodule_internal(int32 moduleid, int32 fileid, int32 msgid, char value) len = PGXL_MSG_MAX_MSGIDS_PER_FILE; start_position = ((moduleid - 1) * PGXL_MSG_MAX_FILEIDS_PER_MODULE * PGXL_MSG_MAX_MSGIDS_PER_FILE) + (fileid - 1) * PGXL_MSG_MAX_MSGIDS_PER_FILE; - memset(MsgModuleCtl + start_position, value, len); - return true; + memset(MsgModuleCtl->mm_flags + start_position, value, len); + goto success; } if (msgid <= 0 || msgid >= PGXL_MSG_MAX_MSGIDS_PER_FILE) @@ -3980,9 +4016,11 @@ pg_msgmodule_internal(int32 moduleid, int32 fileid, int32 msgid, char value) start_position = ((moduleid - 1) * PGXL_MSG_MAX_FILEIDS_PER_MODULE * PGXL_MSG_MAX_MSGIDS_PER_FILE) + ((fileid - 1) * PGXL_MSG_MAX_MSGIDS_PER_FILE) + (msgid - 1); - memset(MsgModuleCtl + start_position, value, len); - return true; + memset(MsgModuleCtl->mm_flags + start_position, value, len); + goto success; } + +success: return true; } @@ -4050,6 +4088,153 @@ pg_msgmodule_change(PG_FUNCTION_ARGS) PG_RETURN_BOOL(pg_msgmodule_internal(moduleid, fileid, msgid, level)); } + +static bool +pg_msgmodule_enable_disable(int32 pid, bool enable) +{ + BackendId backendId; + /* + * pid == -1 implies the action is applied for all backends + */ + if (pid != -1) + { + volatile PGPROC *proc = BackendPidGetProc(pid); + if (proc == NULL) + ereport(ERROR, + (errcode(ERRCODE_INTERNAL_ERROR), + (errmsg("PID %d is not a PostgreSQL server process", pid)))); + backendId = proc->backendId; + MsgModuleCtl->mm_flags[StartOfBackendFlags + backendId] = enable ? true : + false; + } + else + { + /* + * All backends should not honour the current settings + */ + memset(MsgModuleCtl->mm_flags + StartOfBackendFlags, true, + MaxBackends); + } + + /* + * If we are disabling the last backend and no new backends are going to + * participate in the facility, then just disable the entire facility so + * that subsequent backends can quickly bail out + * + * XXX There is a race possible here if another call to turn on the logging + * comes just after we had passed over tje slot. We should possibly protect + * access to the shared memory, but doesn't seem like worth the effort + * right now + */ + if (!enable && !MsgModuleCtl->mm_persistent) + { + int i; + for (i = 0; i < MaxBackends; i++) + if (MsgModuleCtl->mm_flags[StartOfBackendFlags + i]) + break; + if (i == MaxBackends) + MsgModuleCtl->mm_enabled = false; + } + else + MsgModuleCtl->mm_enabled = true; + + return true; +} + +Datum +pg_msgmodule_enable(PG_FUNCTION_ARGS) +{ + int32 pid = PG_GETARG_INT32(0); + + if (!superuser()) + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + (errmsg("must be superuser to change elog message level")))); + + PG_RETURN_BOOL(pg_msgmodule_enable_disable(pid, true)); +} + +Datum +pg_msgmodule_disable(PG_FUNCTION_ARGS) +{ + int32 pid = PG_GETARG_INT32(0); + + if (!superuser()) + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + (errmsg("must be superuser to change elog message level")))); + + PG_RETURN_BOOL(pg_msgmodule_enable_disable(pid, false)); +} + +/* + * pg_msgmodule_enable_all(bool persistent) + * + * All processes to start honouring the current settings of overridden log + * levels. If "persistent" is set to true, then all future processes will also + * honour the settings. + */ +Datum +pg_msgmodule_enable_all(PG_FUNCTION_ARGS) +{ + bool persistent = PG_GETARG_BOOL(0); + + if (!superuser()) + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + (errmsg("must be superuser to change elog message level")))); + + MsgModuleCtl->mm_persistent = persistent; + if (persistent) + { + MsgModuleCtl->mm_enabled = true; + memset(MsgModuleCtl->mm_flags + StartOfBackendFlags, true, + MaxBackends); + PG_RETURN_BOOL(true); + } + else + PG_RETURN_BOOL(pg_msgmodule_enable_disable(-1, true)); +} + +/* + * Disable all current and future processes from honouring the overridden log + * levels + */ +Datum +pg_msgmodule_disable_all(PG_FUNCTION_ARGS) +{ + if (!superuser()) + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + (errmsg("must be superuser to change elog message level")))); + + MsgModuleCtl->mm_enabled = false; + MsgModuleCtl->mm_persistent = false; + memset(MsgModuleCtl->mm_flags + StartOfBackendFlags, false, + MaxBackends); + PG_RETURN_BOOL(true); +} + +/* + * Handle proc exit. If persistent flag is not set then also check if we are + * the last process using the facility and if so, disable it. The current log + * settings are retained and will be used when newer processes are enabled for + * the facility + */ +static void +AtProcExit_MsgModule(int code, Datum arg) +{ + MsgModuleCtl->mm_flags[StartOfBackendFlags + MyBackendId] = false; + if (!MsgModuleCtl->mm_persistent) + { + int i; + for (i = 0; i < MaxBackends; i++) + if (MsgModuleCtl->mm_flags[StartOfBackendFlags + i]) + break; + if (i == MaxBackends) + MsgModuleCtl->mm_enabled = false; + } +} #else Datum pg_msgmodule_set(PG_FUNCTION_ARGS) @@ -4063,4 +4248,28 @@ pg_msgmodule_change(PG_FUNCTION_ARGS) ereport(ERROR, (errmsg_internal("Module msgid support not available. " "Please recompile with --enable-genmsgids"))); } +Datum +pg_msgmodule_enable(PG_FUNCTION_ARGS) +{ + ereport(ERROR, (errmsg_internal("Module msgid support not available. " + "Please recompile with --enable-genmsgids"))); +} +Datum +pg_msgmodule_disable(PG_FUNCTION_ARGS) +{ + ereport(ERROR, (errmsg_internal("Module msgid support not available. " + "Please recompile with --enable-genmsgids"))); +} +Datum +pg_msgmodule_enable_all(PG_FUNCTION_ARGS) +{ + ereport(ERROR, (errmsg_internal("Module msgid support not available. " + "Please recompile with --enable-genmsgids"))); +} +Datum +pg_msgmodule_disable_all(PG_FUNCTION_ARGS) +{ + ereport(ERROR, (errmsg_internal("Module msgid support not available. " + "Please recompile with --enable-genmsgids"))); +} #endif diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h index c3426ce9f3..c6686a8907 100644 --- a/src/include/catalog/pg_proc.h +++ b/src/include/catalog/pg_proc.h @@ -5371,6 +5371,14 @@ DATA(insert OID = 6015 ( pg_msgmodule_set PGNSP PGUID 12 1 1 0 0 f f f f t t i 4 DESCR("set debugging level for module/file/msg"); DATA(insert OID = 6016 ( pg_msgmodule_change PGNSP PGUID 12 1 1 0 0 f f f f t t i 4 0 16 "20 20 20 20" _null_ _null_ _null_ _null_ _null_ pg_msgmodule_change _null_ _null_ _null_ )); DESCR("change debugging level for module/file/msg"); +DATA(insert OID = 6017 ( pg_msgmodule_enable PGNSP PGUID 12 1 1 0 0 f f f f t t i 1 0 16 "20" _null_ _null_ _null_ _null_ _null_ pg_msgmodule_enable _null_ _null_ _null_ )); +DESCR("pid to honour overriden log levels"); +DATA(insert OID = 6018 ( pg_msgmodule_disable PGNSP PGUID 12 1 1 0 0 f f f f t t i 1 0 16 "20" _null_ _null_ _null_ _null_ _null_ pg_msgmodule_disable _null_ _null_ _null_ )); +DESCR("pid to ignore overriden log levels"); +DATA(insert OID = 6019 ( pg_msgmodule_enable_all PGNSP PGUID 12 1 1 0 0 f f f f t t i 1 0 16 "16" _null_ _null_ _null_ _null_ _null_ pg_msgmodule_enable_all _null_ _null_ _null_ )); +DESCR("all current/future processes to honour overriden log levels"); +DATA(insert OID = 6020 ( pg_msgmodule_disable_all PGNSP PGUID 12 1 1 0 0 f f f f t t 0 0 0 16 "" _null_ _null_ _null_ _null_ _null_ pg_msgmodule_disable_all _null_ _null_ _null_ )); +DESCR("all processes to ignore overriden log levels"); #endif /* diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h index 3b6cb84fa4..6d766bddf6 100644 --- a/src/include/utils/builtins.h +++ b/src/include/utils/builtins.h @@ -1313,5 +1313,10 @@ extern Datum pgxc_is_inprogress(PG_FUNCTION_ARGS); #endif #ifdef USE_MODULE_MSGIDS extern Datum pg_msgmodule_set(PG_FUNCTION_ARGS); +extern Datum pg_msgmodule_change(PG_FUNCTION_ARGS); +extern Datum pg_msgmodule_enable(PG_FUNCTION_ARGS); +extern Datum pg_msgmodule_disable(PG_FUNCTION_ARGS); +extern Datum pg_msgmodule_enable_all(PG_FUNCTION_ARGS); +extern Datum pg_msgmodule_disable_all(PG_FUNCTION_ARGS); #endif #endif /* BUILTINS_H */ diff --git a/src/include/utils/elog.h b/src/include/utils/elog.h index 0f7c773662..8e5d2c1f35 100644 --- a/src/include/utils/elog.h +++ b/src/include/utils/elog.h @@ -440,9 +440,9 @@ typedef struct ErrorData #define PGXL_MSG_MAX_FILEIDS_PER_MODULE 100 #define PGXL_MSG_MAX_MSGIDS_PER_FILE 300 -extern char *MsgModuleCtl; extern Size MsgModuleShmemSize(void); extern void MsgModuleShmemInit(void); +extern void AtProcStart_MsgModule(void); #endif extern void EmitErrorReport(void); |