diff --git a/doc/src/sgml/maintenance.sgml b/doc/src/sgml/maintenance.sgml
index 4a68ec3b40..91b96dc588 100644
--- a/doc/src/sgml/maintenance.sgml
+++ b/doc/src/sgml/maintenance.sgml
@@ -960,6 +960,23 @@ pg_ctl start | rotatelogs /var/log/pgsql_log 86400
   </para>
 
   <para>
+   The <application>logrotate</application> program can also be used to collect log files 
+   produced by the built-in logging collector. In this configuration, the location and
+   names of the log files are determined by logging collector, and 
+   <application>logrotate</application> periodically archives these files. There must be
+   some way for <application>logrotate</application> to inform the application that the
+   log file it is using is going to be archived, and that it must direct further output
+   to a new file. This is commonly done with a <literal>postrotate</literal> script that
+   sends a <literal>SIGHUP</literal> signal to the application, which then reopens the log
+   file. In <productname>PostgreSQL</productname>, this is achieved by sending a 
+   <literal>SIGUSR1</literal> signal to the logging collector process. The PID of this
+   process can be found in the <filename>$PGDATA/logging_collector.pid</filename> file.
+   When the logging collector receives the signal, it switches to the new log files
+   according to its configuration (see <xref linkend="runtime-config-logging-where"/>).
+   If it is configured to use a static file name, it will just reopen the file.
+  </para>
+
+  <para>
    On many systems, however, <application>syslog</application> is not very reliable,
    particularly with large log messages; it might truncate or drop messages
    just when you need them the most.  Also, on <productname>Linux</productname>,
diff --git a/src/backend/postmaster/syslogger.c b/src/backend/postmaster/syslogger.c
index 58b759f305..99201727ec 100644
--- a/src/backend/postmaster/syslogger.c
+++ b/src/backend/postmaster/syslogger.c
@@ -138,6 +138,8 @@ static void flush_pipe_input(char *logbuffer, int *bytes_in_logbuffer);
 static void open_csvlogfile(void);
 static FILE *logfile_open(const char *filename, const char *mode,
 			 bool allow_errors);
+static void syslogger_on_exit(int code, Datum arg);
+static void syslogger_publish_pid(void);
 
 #ifdef WIN32
 static unsigned int __stdcall pipeThread(void *arg);
@@ -286,6 +288,9 @@ SysLoggerMain(int argc, char *argv[])
 	set_next_rotation_time();
 	update_metainfo_datafile();
 
+	/* publish my pid to pid file */
+	syslogger_publish_pid();
+
 	/* main worker loop */
 	for (;;)
 	{
@@ -1417,6 +1422,64 @@ update_metainfo_datafile(void)
 						LOG_METAINFO_DATAFILE_TMP, LOG_METAINFO_DATAFILE)));
 }
 
+/*
+ * The pid file of logging collector.
+ */
+#define PID_FILE "logging_collector.pid"
+
+/*
+ * Clean up the pid file of logging collector.
+ */
+static void
+syslogger_on_exit(int code, Datum arg)
+{
+	unlink(PID_FILE);
+}
+
+/*
+ * Publish the PID of logging collector to a pid file.
+ */
+static void
+syslogger_publish_pid()
+{
+	int fd;
+	char buffer[32];
+
+	/*
+	 * Postmaster switches working directory to data directory, so we
+	 * can use relative file name. If the pid file already exists, just
+	 * overwrite it. Concurrency with other postgres instances should
+	 * have been handled by postmaster.
+	 */
+	fd = open(PID_FILE, O_RDWR | O_CREAT | O_TRUNC, 0600);
+
+	if (fd < 0)
+	{
+		ereport(LOG,
+				(errcode_for_file_access(),
+				 errmsg("could not create log_collector PID file \"%s\": %m",
+						PID_FILE)));
+		return;
+	}
+
+	snprintf(buffer, sizeof(buffer), "%d\n", (int) getpid());
+
+	if (write(fd, buffer, strlen(buffer)) != strlen(buffer))
+	{
+		ereport(LOG,
+				(errcode_for_file_access(),
+				 errmsg("could not write log_collector PID file \"%s\": %m",
+						PID_FILE)));
+		close(fd);
+		unlink(PID_FILE);
+		return;
+	}
+
+	close(fd);
+
+	on_proc_exit(syslogger_on_exit, 0);
+}
+
 /* --------------------------------
  *		signal handler routines
  * --------------------------------
