Previously, NOTICE, WARNING, and similar messages received from remote
servers over replication, postgres_fdw, or dblink connections were printed
directly to stderr on the local server (e.g., the subscriber). As a result,
these messages lacked log prefixes (e.g., timestamp), making them harder
to trace and correlate with other log entries.
This commit addresses the issue by introducing a custom notice receiver
for replication, postgres_fdw, and dblink connections. These messages
are now logged via ereport(), ensuring they appear in the logs with proper
formatting and context, which improves clarity and aids in debugging.
Author: Vignesh C <
[email protected]>
Reviewed-by: Álvaro Herrera <[email protected]>
Reviewed-by: Fujii Masao <[email protected]>
Discussion: https://postgr.es/m/CALDaNm2xsHpWRtLm-VL_HJCsaE3+1Y_n-jDEAr3-suxVqc3xoQ@mail.gmail.com
                     errmsg("could not establish connection"),
                     errdetail_internal("%s", msg)));
        }
+
+       PQsetNoticeReceiver(conn, libpqsrv_notice_receiver,
+                           gettext_noop("received message via remote connection"));
+
        dblink_security_check(conn, NULL, connstr);
        if (PQclientEncoding(conn) != GetDatabaseEncoding())
            PQsetClientEncoding(conn, GetDatabaseEncodingName());
                 errdetail_internal("%s", msg)));
    }
 
+   PQsetNoticeReceiver(conn, libpqsrv_notice_receiver,
+                       gettext_noop("received message via remote connection"));
+
    /* check password actually used if not superuser */
    dblink_security_check(conn, connname, connstr);
 
 
                            server->servername),
                     errdetail_internal("%s", pchomp(PQerrorMessage(conn)))));
 
+       PQsetNoticeReceiver(conn, libpqsrv_notice_receiver,
+                           gettext_noop("received message via remote connection"));
+
        /* Perform post-connection security checks. */
        pgfdw_security_check(keywords, values, user, conn);
 
 
                 errhint("Target server's authentication method must be changed, or set password_required=false in the subscription parameters.")));
    }
 
+   PQsetNoticeReceiver(conn->streamConn, libpqsrv_notice_receiver,
+                       gettext_noop("received message via replication"));
+
    /*
     * Set always-secure search path for the cases where the connection is
     * used to run SQL queries, so malicious users can't get control.
 
    return error;
 }
 
+/*
+ * libpqsrv_notice_receiver
+ *
+ * Custom notice receiver for libpq connections.
+ *
+ * This function is intended to be set via PQsetNoticeReceiver() so that
+ * NOTICE, WARNING, and similar messages from the connection are reported via
+ * ereport(), instead of being printed to stderr.
+ */
+static inline void
+libpqsrv_notice_receiver(void *arg, const PGresult *res)
+{
+   char       *message;
+   int         len;
+   char       *prefix = (char *) arg;
+
+   /*
+    * Trim the trailing newline from the message text returned from
+    * PQresultErrorMessage(), as it always includes one, to produce cleaner
+    * log output.
+    */
+   message = PQresultErrorMessage(res);
+   len = strlen(message);
+   if (len > 0 && message[len - 1] == '\n')
+       len--;
+
+   ereport(LOG,
+           errmsg_internal("%s: %.*s", _(prefix), len, message));
+}
+
 #endif                         /* LIBPQ_BE_FE_HELPERS_H */