Add cluster_name GUC which is included in process titles if set.
authorAndres Freund <andres@anarazel.de>
Sun, 29 Jun 2014 12:15:09 +0000 (14:15 +0200)
committerAndres Freund <andres@anarazel.de>
Sun, 29 Jun 2014 12:15:09 +0000 (14:15 +0200)
When running several postgres clusters on one OS instance it's often
inconveniently hard to identify which "postgres" process belongs to
which postgres instance.

Add the cluster_name GUC, whose value will be included as part of the
process titles if set. With that processes can more easily identified
using tools like 'ps'.

To avoid problems with encoding mismatches between postgresql.conf,
consoles, and individual databases replace non-ASCII chars in the name
with question marks. The length is limited to NAMEDATALEN to make it
less likely to truncate important information at the end of the
status.

Thomas Munro, with some adjustments by me and review by a host of people.

doc/src/sgml/config.sgml
doc/src/sgml/monitoring.sgml
src/backend/utils/misc/guc.c
src/backend/utils/misc/postgresql.conf.sample
src/backend/utils/misc/ps_status.c
src/include/utils/guc.h

index e3d1c622122ab0df5a23c157d3c95026ff97eb68..11d552e82d838060c3323043bae7f982c3eae7a2 100644 (file)
@@ -4131,6 +4131,29 @@ local0.*    /var/log/postgresql
       </listitem>
      </varlistentry>
 
+     <varlistentry id="guc-cluster-name" xreflabel="cluster_name">
+      <term><varname>cluster_name</varname> (<type>string</type>)</term>
+      <indexterm>
+       <primary><varname>cluster_name</> configuration parameter</primary>
+      </indexterm>
+      <listitem>
+       <para>
+        Sets the cluster name that appears in the process title for all
+        processes in this cluster. The name can be any string of less than
+        <symbol>NAMEDATALEN</> characters (64 characters in a standard
+        build). Only printable ASCII characters may be used in the
+        <varname>application_name</varname> value. Other characters will be
+        replaced with question marks (<literal>?</literal>).  No name is shown
+        if this parameter is set to the empty string <literal>''</> (which is
+        the default). This parameter can only be set at server start.
+       </para>
+       <para>
+        The process title is typically viewed using programs like
+        <application>ps</> or, on Windows, <application>Process Explorer</>.
+       </para>
+      </listitem>
+     </varlistentry>
+
      <varlistentry>
       <term><varname>debug_print_parse</varname> (<type>boolean</type>)
       <indexterm>
index 69d99e7c75ff58348172e80c7c950c52dbc5dfc4..cef3fc0dc4e3b6d3dd943b702eafe725853cb1f3 100644 (file)
@@ -91,6 +91,22 @@ postgres: <replaceable>user</> <replaceable>database</> <replaceable>host</> <re
   system view to determine who is blocking whom.)
   </para>
 
+  <para>
+   If <xref linkend="guc-cluster-name"> has been configured the
+   cluster name will also be show in <command>ps</> output:
+<screen>
+$ psql -c 'SHOW cluster_name'
+ cluster_name
+--------------
+ server1
+(1 row)
+
+$ ps aux|grep server1
+postgres   27093  0.0  0.0  30096  2752 ?        Ss   11:34   0:00 postgres: server1: writer process
+...
+</screen>
+  </para>
+
   <para>
    If you have turned off <xref linkend="guc-update-process-title"> then the
    activity indicator is not updated; the process title is set only once
index 6902c2322a9481350a3fb43fa6848e2f399f9092..3a31a7519196cae2eef60b130c3c19c43060231e 100644 (file)
@@ -198,6 +198,7 @@ static void assign_effective_io_concurrency(int newval, void *extra);
 static void assign_pgstat_temp_directory(const char *newval, void *extra);
 static bool check_application_name(char **newval, void **extra, GucSource source);
 static void assign_application_name(const char *newval, void *extra);
+static bool check_cluster_name(char **newval, void **extra, GucSource source);
 static const char *show_unix_socket_permissions(void);
 static const char *show_log_file_mode(void);
 
@@ -443,6 +444,7 @@ int         temp_file_limit = -1;
 
 int            num_temp_buffers = 1024;
 
+char      *cluster_name = "";
 char      *data_directory;
 char      *ConfigFileName;
 char      *HbaFileName;
@@ -3261,6 +3263,17 @@ static struct config_string ConfigureNamesString[] =
        check_application_name, assign_application_name, NULL
    },
 
+   {
+       {"cluster_name", PGC_POSTMASTER, LOGGING_WHAT,
+           gettext_noop("Sets the name of the cluster which is included in the process title."),
+           NULL,
+           GUC_IS_NAME
+       },
+       &cluster_name,
+       "",
+       check_cluster_name, NULL, NULL
+   },
+
    /* End-of-list marker */
    {
        {NULL, 0, 0, NULL, NULL}, NULL, NULL, NULL, NULL, NULL
@@ -9470,6 +9483,21 @@ assign_application_name(const char *newval, void *extra)
    pgstat_report_appname(newval);
 }
 
+static bool
+check_cluster_name(char **newval, void **extra, GucSource source)
+{
+   /* Only allow clean ASCII chars in the cluster name */
+   char       *p;
+
+   for (p = *newval; *p; p++)
+   {
+       if (*p < 32 || *p > 126)
+           *p = '?';
+   }
+
+   return true;
+}
+
 static const char *
 show_unix_socket_permissions(void)
 {
index d109394d3b79bad1d37a2041c8df3afa8ab18049..3f3e706b2ae4f481d8bac2cf852ca6fd7197bd77 100644 (file)
                    # than the specified size in kilobytes;
                    # -1 disables, 0 logs all temp files
 #log_timezone = 'GMT'
-
+#cluster_name = ''         # added to process titles if nonempty
+                   # (change requires restart)
 
 #------------------------------------------------------------------------------
 # RUNTIME STATISTICS
index 5407d3f9aceb0bb941cb24214455792439410b5d..e73a0e2cce7876e1ad8a48268779240a3878dd09 100644 (file)
@@ -29,6 +29,7 @@
 #include "libpq/libpq.h"
 #include "miscadmin.h"
 #include "utils/ps_status.h"
+#include "utils/guc.h"
 
 extern char **environ;
 bool       update_process_title = true;
@@ -264,15 +265,24 @@ init_ps_display(const char *username, const char *dbname,
     * apparently setproctitle() already adds a `progname:' prefix to the ps
     * line
     */
-   snprintf(ps_buffer, ps_buffer_size,
-            "%s %s %s ",
-            username, dbname, host_info);
+#define PROGRAM_NAME_PREFIX ""
 #else
-   snprintf(ps_buffer, ps_buffer_size,
-            "postgres: %s %s %s ",
-            username, dbname, host_info);
+#define PROGRAM_NAME_PREFIX "postgres: "
 #endif
 
+   if (*cluster_name == '\0')
+   {
+       snprintf(ps_buffer, ps_buffer_size,
+                PROGRAM_NAME_PREFIX "%s %s %s ",
+                username, dbname, host_info);
+   }
+   else
+   {
+       snprintf(ps_buffer, ps_buffer_size,
+                PROGRAM_NAME_PREFIX "%s: %s %s %s ",
+                cluster_name, username, dbname, host_info);
+   }
+
    ps_buffer_cur_len = ps_buffer_fixed_size = strlen(ps_buffer);
 
    set_ps_display(initial_str, true);
index 1493d2cb79cbcde4fccf29a02efa2523d938a52a..0a729c11902aae80e17735399daf2e726bd41ede 100644 (file)
@@ -224,6 +224,7 @@ extern int  temp_file_limit;
 
 extern int num_temp_buffers;
 
+extern char *cluster_name;
 extern char *data_directory;
 extern char *ConfigFileName;
 extern char *HbaFileName;