From ea46337f24df4d251243d4ea923c5ff1e2f65e96 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter_e@gmx.net>
Date: Tue, 17 Nov 2015 06:46:44 -0500
Subject: [PATCH 2/3] Add log_destination "systemd"

This allows systemd to associate severity levels with messages printed
to standard output or standard error.
---
 doc/src/sgml/config.sgml                      | 14 +++++++++-
 doc/src/sgml/runtime.sgml                     |  2 +-
 src/backend/utils/error/elog.c                | 37 +++++++++++++++++++++++++++
 src/backend/utils/misc/guc.c                  |  4 ++-
 src/backend/utils/misc/postgresql.conf.sample |  7 ++---
 src/include/utils/elog.h                      |  1 +
 6 files changed, 59 insertions(+), 6 deletions(-)

diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index 6e14851..a61d179 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -3821,7 +3821,7 @@ <title>Where To Log</title>
        <para>
         <productname>PostgreSQL</productname> supports several methods
          for logging server messages, including
-         <systemitem>stderr</systemitem>, <systemitem>csvlog</systemitem> and
+         <systemitem>stderr</systemitem>, <systemitem>systemd</systemitem>, <systemitem>csvlog</systemitem> and
          <systemitem>syslog</systemitem>. On Windows,
          <systemitem>eventlog</systemitem> is also supported. Set this
          parameter to a list of desired log destinations separated by
@@ -3831,6 +3831,18 @@ <title>Where To Log</title>
          file or on the server command line.
        </para>
        <para>
+        <systemitem>systemd</systemitem><indexterm><primary>systemd</primary></indexterm>
+        is like <systemitem>stderr</systemitem>, but log messages are
+        additionally prefixed so that <application>systemd</application> can
+        associate severity levels
+        (see <citerefentry><refentrytitle>sd-daemon</refentrytitle><manvolnum>3</manvolnum></citerefentry>).
+        This is recommended if the server is started and logs are captured
+        by <application>systemd</application>.  It is normally not useful to
+        configure <systemitem>systemd</systemitem> together
+        with <systemitem>stderr</systemitem>
+        or <systemitem>syslog</systemitem>.
+       </para>
+       <para>
         If <systemitem>csvlog</> is included in <varname>log_destination</>,
         log entries are output in <quote>comma separated
         value</> (<acronym>CSV</>) format, which is convenient for
diff --git a/doc/src/sgml/runtime.sgml b/doc/src/sgml/runtime.sgml
index 5e95a3b..0773610 100644
--- a/doc/src/sgml/runtime.sgml
+++ b/doc/src/sgml/runtime.sgml
@@ -382,7 +382,7 @@ <title>Starting the Database Server</title>
 [Service]
 Type=notify
 User=postgres
-ExecStart=/usr/local/pgsql/bin/postgres -D /usr/local/pgsql/data
+ExecStart=/usr/local/pgsql/bin/postgres -D /usr/local/pgsql/data -c log_destination=systemd
 ExecReload=/bin/kill -HUP $MAINPID
 KillMode=mixed
 KillSignal=SIGINT
diff --git a/src/backend/utils/error/elog.c b/src/backend/utils/error/elog.c
index 8b5b6c5..12e6cea 100644
--- a/src/backend/utils/error/elog.c
+++ b/src/backend/utils/error/elog.c
@@ -3004,6 +3004,43 @@ send_message_to_server_log(ErrorData *edata)
 			write_console(buf.data, buf.len);
 	}
 
+	if (Log_destination & LOG_DESTINATION_SYSTEMD)
+	{
+		const char *systemd_log_prefix;
+
+		switch (edata->elevel)
+		{
+			case DEBUG5:
+			case DEBUG4:
+			case DEBUG3:
+			case DEBUG2:
+			case DEBUG1:
+				systemd_log_prefix = "<7>" /* SD_DEBUG */;
+				break;
+			case LOG:
+			case COMMERROR:
+			case INFO:
+				systemd_log_prefix = "<6>" /* SD_INFO */;
+				break;
+			case NOTICE:
+			case WARNING:
+				systemd_log_prefix = "<5>" /* SD_NOTICE */;
+				break;
+			case ERROR:
+				systemd_log_prefix = "<4>" /* SD_WARNING */;
+				break;
+			case FATAL:
+				systemd_log_prefix = "<3>" /* SD_ERR */;
+				break;
+			case PANIC:
+			default:
+				systemd_log_prefix = "<2>" /* LOG_CRIT */;
+				break;
+		}
+		write_console(systemd_log_prefix, strlen(systemd_log_prefix));
+		write_console(buf.data, buf.len);
+	}
+
 	/* If in the syslogger process, try to write messages direct to file */
 	if (am_syslogger)
 		write_syslogger_file(buf.data, buf.len, LOG_DESTINATION_STDERR);
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index a185749..c9a06bd 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -3123,7 +3123,7 @@ static struct config_string ConfigureNamesString[] =
 		{"log_destination", PGC_SIGHUP, LOGGING_WHERE,
 			gettext_noop("Sets the destination for server log output."),
 			gettext_noop("Valid values are combinations of \"stderr\", "
-						 "\"syslog\", \"csvlog\", and \"eventlog\", "
+						 "\"syslog\", \"systemd\", \"csvlog\", and \"eventlog\", "
 						 "depending on the platform."),
 			GUC_LIST_INPUT
 		},
@@ -9694,6 +9694,8 @@ check_log_destination(char **newval, void **extra, GucSource source)
 
 		if (pg_strcasecmp(tok, "stderr") == 0)
 			newlogdest |= LOG_DESTINATION_STDERR;
+		else if (pg_strcasecmp(tok, "systemd") == 0)
+			newlogdest |= LOG_DESTINATION_SYSTEMD;
 		else if (pg_strcasecmp(tok, "csvlog") == 0)
 			newlogdest |= LOG_DESTINATION_CSVLOG;
 #ifdef HAVE_SYSLOG
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index 029114f..2af7465 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -322,9 +322,10 @@
 # - Where to Log -
 
 #log_destination = 'stderr'		# Valid values are combinations of
-					# stderr, csvlog, syslog, and eventlog,
-					# depending on platform.  csvlog
-					# requires logging_collector to be on.
+					# stderr, systemd, csvlog, syslog, and
+					# eventlog, depending on platform.
+					# csvlog requires logging_collector to
+					# be on.
 
 # This is used when logging to stderr:
 #logging_collector = off		# Enable capturing of stderr and csvlog
diff --git a/src/include/utils/elog.h b/src/include/utils/elog.h
index 7715719..b816e82 100644
--- a/src/include/utils/elog.h
+++ b/src/include/utils/elog.h
@@ -402,6 +402,7 @@ extern char *Log_destination_string;
 #define LOG_DESTINATION_SYSLOG	 2
 #define LOG_DESTINATION_EVENTLOG 4
 #define LOG_DESTINATION_CSVLOG	 8
+#define LOG_DESTINATION_SYSTEMD	 16
 
 /* Other exported functions */
 extern void DebugFileOpen(void);
-- 
2.6.3

