On 2020-Nov-23, Tom Lane wrote:
> Here's a draft patch.
Here's another of my own. Outside of elog.c it seems identical.
diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c
index 03c553e7ea..a4ab9090f9 100644
--- a/src/backend/access/transam/xact.c
+++ b/src/backend/access/transam/xact.c
@@ -5344,7 +5344,7 @@ static void
ShowTransactionState(const char *str)
{
/* skip work if message will definitely not be printed */
- if (log_min_messages <= DEBUG5 || client_min_messages <= DEBUG5)
+ if (message_level_is_interesting(DEBUG5))
ShowTransactionStateRec(str, CurrentTransactionState);
}
diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 7e915bcadf..32a3099c1f 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -105,7 +105,7 @@ log_invalid_page(RelFileNode node, ForkNumber forkno, BlockNumber blkno,
* tracing of the cause (note the elog context mechanism will tell us
* something about the XLOG record that generated the reference).
*/
- if (log_min_messages <= DEBUG1 || client_min_messages <= DEBUG1)
+ if (message_level_is_interesting(DEBUG1))
report_invalid_page(DEBUG1, node, forkno, blkno, present);
if (invalid_page_tab == NULL)
@@ -159,7 +159,7 @@ forget_invalid_pages(RelFileNode node, ForkNumber forkno, BlockNumber minblkno)
hentry->key.forkno == forkno &&
hentry->key.blkno >= minblkno)
{
- if (log_min_messages <= DEBUG2 || client_min_messages <= DEBUG2)
+ if (message_level_is_interesting(DEBUG2))
{
char *path = relpathperm(hentry->key.node, forkno);
@@ -192,7 +192,7 @@ forget_invalid_pages_db(Oid dbid)
{
if (hentry->key.node.dbNode == dbid)
{
- if (log_min_messages <= DEBUG2 || client_min_messages <= DEBUG2)
+ if (message_level_is_interesting(DEBUG2))
{
char *path = relpathperm(hentry->key.node, hentry->key.forkno);
diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c
index b0d037600e..0ad647ed9c 100644
--- a/src/backend/catalog/dependency.c
+++ b/src/backend/catalog/dependency.c
@@ -1146,15 +1146,8 @@ reportDependentObjects(const ObjectAddresses *targetObjects,
* If no error is to be thrown, and the msglevel is too low to be shown to
* either client or server log, there's no need to do any of the rest of
* the work.
- *
- * Note: this code doesn't know all there is to be known about elog
- * levels, but it works for NOTICE and DEBUG2, which are the only values
- * msglevel can currently have. We also assume we are running in a normal
- * operating environment.
*/
- if (behavior == DROP_CASCADE &&
- msglevel < client_min_messages &&
- (msglevel < log_min_messages || log_min_messages == LOG))
+ if (behavior == DROP_CASCADE && !message_level_is_interesting(msglevel))
return;
/*
diff --git a/src/backend/replication/walreceiver.c b/src/backend/replication/walreceiver.c
index babee386c4..87c3ea450e 100644
--- a/src/backend/replication/walreceiver.c
+++ b/src/backend/replication/walreceiver.c
@@ -1215,7 +1215,7 @@ ProcessWalSndrMessage(XLogRecPtr walEnd, TimestampTz sendTime)
walrcv->lastMsgReceiptTime = lastMsgReceiptTime;
SpinLockRelease(&walrcv->mutex);
- if (log_min_messages <= DEBUG2)
+ if (message_level_is_interesting(DEBUG2))
{
char *sendtime;
char *receipttime;
diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c
index 5d1b1a16be..2eb19ad293 100644
--- a/src/backend/replication/walsender.c
+++ b/src/backend/replication/walsender.c
@@ -1900,7 +1900,7 @@ ProcessStandbyReplyMessage(void)
replyTime = pq_getmsgint64(&reply_message);
replyRequested = pq_getmsgbyte(&reply_message);
- if (log_min_messages <= DEBUG2)
+ if (message_level_is_interesting(DEBUG2))
{
char *replyTimeStr;
@@ -2082,7 +2082,7 @@ ProcessStandbyHSFeedbackMessage(void)
feedbackCatalogXmin = pq_getmsgint(&reply_message, 4);
feedbackCatalogEpoch = pq_getmsgint(&reply_message, 4);
- if (log_min_messages <= DEBUG2)
+ if (message_level_is_interesting(DEBUG2))
{
char *replyTimeStr;
diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c
index 40eac704dc..eb2309ed76 100644
--- a/src/backend/storage/lmgr/proc.c
+++ b/src/backend/storage/lmgr/proc.c
@@ -1341,22 +1341,25 @@ ProcSleep(LOCALLOCK *locallock, LockMethod lockMethodTable)
StringInfoData logbuf; /* errdetail for server log */
/* report the case, if configured to do so */
- initStringInfo(&locktagbuf);
- initStringInfo(&logbuf);
- DescribeLockTag(&locktagbuf, &locktag_copy);
- appendStringInfo(&logbuf,
- _("Process %d waits for %s on %s."),
- MyProcPid,
- GetLockmodeName(lockmethod_copy, lockmode),
- locktagbuf.data);
+ if (message_level_is_interesting(DEBUG1))
+ {
+ initStringInfo(&locktagbuf);
+ initStringInfo(&logbuf);
+ DescribeLockTag(&locktagbuf, &locktag_copy);
+ appendStringInfo(&logbuf,
+ _("Process %d waits for %s on %s."),
+ MyProcPid,
+ GetLockmodeName(lockmethod_copy, lockmode),
+ locktagbuf.data);
- ereport(DEBUG1,
- (errmsg("sending cancel to blocking autovacuum PID %d",
- pid),
- errdetail_log("%s", logbuf.data)));
+ ereport(DEBUG1,
+ (errmsg("sending cancel to blocking autovacuum PID %d",
+ pid),
+ errdetail_log("%s", logbuf.data)));
- pfree(logbuf.data);
- pfree(locktagbuf.data);
+ pfree(logbuf.data);
+ pfree(locktagbuf.data);
+ }
/* send the autovacuum worker Back to Old Kent Road */
if (kill(pid, SIGINT) < 0)
diff --git a/src/backend/utils/error/elog.c b/src/backend/utils/error/elog.c
index 1ba47c194b..aab27aa5aa 100644
--- a/src/backend/utils/error/elog.c
+++ b/src/backend/utils/error/elog.c
@@ -185,6 +185,7 @@ static void send_message_to_frontend(ErrorData *edata);
static const char *error_severity(int elevel);
static void append_with_tabs(StringInfo buf, const char *str);
static bool is_log_level_output(int elevel, int log_min_level);
+static bool is_log_level_output_client(int elevel, int client_min_level);
/*
@@ -293,20 +294,7 @@ errstart(int elevel, const char *domain)
output_to_server = is_log_level_output(elevel, log_min_messages);
/* Determine whether message is enabled for client output */
- if (whereToSendOutput == DestRemote && elevel != LOG_SERVER_ONLY)
- {
- /*
- * client_min_messages is honored only after we complete the
- * authentication handshake. This is required both for security
- * reasons and because many clients can't handle NOTICE messages
- * during authentication.
- */
- if (ClientAuthInProgress)
- output_to_client = (elevel >= ERROR);
- else
- output_to_client = (elevel >= client_min_messages ||
- elevel == INFO);
- }
+ output_to_client = is_log_level_output_client(elevel, client_min_messages);
/* Skip processing effort if non-error message will not be output */
if (elevel < ERROR && !output_to_server && !output_to_client)
@@ -3521,6 +3509,42 @@ is_log_level_output(int elevel, int log_min_level)
return false;
}
+/*
+ * is_log_level_output_client -- is elevel logical >= client_min_level?
+ */
+static bool
+is_log_level_output_client(int elevel, int client_min_level)
+{
+ if (whereToSendOutput == DestRemote && elevel != LOG_SERVER_ONLY)
+ {
+ /*
+ * client_min_level (client_min_messages) is honored only after we
+ * complete the authentication handshake. This is required both for
+ * security reasons and because many clients can't handle NOTICE
+ * messages during authentication.
+ */
+ if (ClientAuthInProgress)
+ return elevel >= ERROR;
+ else
+ return elevel >= client_min_level || elevel == INFO;
+ }
+
+ return false;
+}
+
+/*
+ * Return whether a message of the given elevel would be printed.
+ *
+ * This can be used to skip formatting effort outside of ereport() calls.
+ */
+bool
+message_level_is_interesting(int elevel)
+{
+ return
+ is_log_level_output(elevel, log_min_messages) ||
+ is_log_level_output_client(elevel, client_min_messages);
+}
+
/*
* Adjust the level of a recovery-related message per trace_recovery_messages.
*
diff --git a/src/include/utils/elog.h b/src/include/utils/elog.h
index 1e09ee0541..4049456eab 100644
--- a/src/include/utils/elog.h
+++ b/src/include/utils/elog.h
@@ -393,6 +393,9 @@ extern void pg_re_throw(void) pg_attribute_noreturn();
extern char *GetErrorContextStack(void);
+/* allow skipping formatting messages that won't be emitted */
+extern bool message_level_is_interesting(int elevel);
+
/* Hook for intercepting messages before they are sent to the server log */
typedef void (*emit_log_hook_type) (ErrorData *edata);
extern PGDLLIMPORT emit_log_hook_type emit_log_hook;