patch for distinguishing PG instances in event log v2
Hello,
The attached file is a revised patch which reflects all review comments by
Magnus in:
http://archives.postgresql.org/pgsql-hackers/2011-07/msg00839.php
I made sure the previous tests (both custom and default "PostgreSQL" event
source) succeeded.
I'm submitting this to the currently open CommitFest 2001-9 shortly. Please
review it again.
Regards
MauMau
Attachments:
multi_event_source_v2.patchapplication/octet-stream; name=multi_event_source_v2.patchDownload
diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
new file mode 100644
index 5d37065..9d73640
*** a/doc/src/sgml/config.sgml
--- b/doc/src/sgml/config.sgml
*************** local0.* /var/log/postgresql
*** 2949,2954 ****
--- 2949,2962 ----
to the <application>syslog</application> daemon's configuration file
to make it work.
</para>
+ <para>
+ On Windows, when you use the <systemitem>eventlog</systemitem>
+ option for <varname>log_destination</>, you should
+ register an event sourceand its library with the operating
+ system so that the Windows Event Viewer can display event
+ log messages cleanly.
+ See <xref linkend="event-log-registration"> for details.
+ </para>
</note>
</listitem>
</varlistentry>
*************** local0.* /var/log/postgresql
*** 3189,3194 ****
--- 3197,3220 ----
<productname>PostgreSQL</productname> messages in
<application>syslog</application> logs. The default is
<literal>postgres</literal>.
+ This parameter can only be set in the <filename>postgresql.conf</>
+ file or on the server command line.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry id="guc-event-source" xreflabel="event_source">
+ <term><varname>event_source</varname> (<type>string</type>)</term>
+ <indexterm>
+ <primary><varname>event_source</> configuration parameter</primary>
+ </indexterm>
+ <listitem>
+ <para>
+ When logging to <application>event log</> is enabled, this parameter
+ determines the program name used to identify
+ <productname>PostgreSQL</productname> messages in
+ <application>event log</application>. The default is
+ <literal>PostgreSQL</literal>.
This parameter can only be set in the <filename>postgresql.conf</>
file or on the server command line.
</para>
diff --git a/doc/src/sgml/installation.sgml b/doc/src/sgml/installation.sgml
new file mode 100644
index 96387bd..262b91a
*** a/doc/src/sgml/installation.sgml
--- b/doc/src/sgml/installation.sgml
*************** PostgreSQL, contrib and HTML documentati
*** 1551,1569 ****
</procedure>
<formalpara>
- <title>Registering <application>eventlog</> on <systemitem
- class="osname">Windows</>:</title>
- <para>
- To register a <systemitem class="osname">Windows</> <application>eventlog</>
- library with the operating system, issue this command after installation:
- <screen>
- <userinput>regsvr32 <replaceable>pgsql_library_directory</>/pgevent.dll</>
- </screen>
- This creates registry entries used by the event viewer.
- </para>
- </formalpara>
-
- <formalpara>
<title>Uninstallation:</title>
<para>
To undo the installation use the command <command>gmake
--- 1551,1556 ----
diff --git a/doc/src/sgml/runtime.sgml b/doc/src/sgml/runtime.sgml
new file mode 100644
index d18ba79..9a8a22d
*** a/doc/src/sgml/runtime.sgml
--- b/doc/src/sgml/runtime.sgml
*************** ssh -L 63333:db.foo.com:5432 joe@shell.f
*** 2294,2297 ****
--- 2294,2347 ----
</sect1>
+ <sect1 id="event-log-registration">
+ <title>Registering <application>Event Log</> on <systemitem
+ class="osname">Windows</></title>
+
+ <indexterm zone="event-log-registration">
+ <primary>event log</primary>
+ <secondary>event log</secondary>
+ </indexterm>
+
+ <para>
+ To register a <systemitem class="osname">Windows</> <application>event log</>
+ library with the operating system, issue this command:
+ <screen>
+ <userinput>regsvr32 <replaceable>pgsql_library_directory</>/pgevent.dll</>
+ </screen>
+ This creates registry entries used by the event viewer, under the default event
+ source named "PostgreSQL".
+ </para>
+
+ <para>
+ You can specify the event source name with /i option. In this case, -n option
+ is necessary, too:
+ <screen>
+ <userinput>regsvr32 /n /i:<replaceable>event_source_name</>
+ <replaceable>pgsql_library_directory</>/pgevent.dll</>
+ </screen>
+ You also need to set <xref linkend="guc-event-source"> in
+ <filename>postgresql.conf</filename>. Note that the event source specification
+ only takes effect for the database server. Other applications like
+ <command>pg_ctl</command> always use "PostgreSQL" event source.
+ </para>
+
+ <para>
+ To unregister the <application>event log</> library from
+ the operating system, issue this command:
+ <screen>
+ <userinput>regsvr32 /u [/i:<replaceable>event_source_name</>]
+ <replaceable>pgsql_library_directory</>/pgevent.dll</>
+ </screen>
+ </para>
+
+ <note>
+ <para>
+ To enable event logging in the database server, modify
+ <xref linkend="guc-log-destination"> to include
+ <systemitem>eventlog</systemitem> in <filename>postgresql.conf</filename>.
+ </para>
+ </note>
+ </sect1>
+
</chapter>
diff --git a/src/backend/utils/error/elog.c b/src/backend/utils/error/elog.c
new file mode 100644
index 337b875..47ee4df
*** a/src/backend/utils/error/elog.c
--- b/src/backend/utils/error/elog.c
*************** static void write_syslog(int level, cons
*** 122,127 ****
--- 122,128 ----
static void write_console(const char *line, int len);
#ifdef WIN32
+ extern char *event_source; /* guc */
static void write_eventlog(int level, const char *line, int len);
#endif
*************** write_eventlog(int level, const char *li
*** 1645,1651 ****
if (evtHandle == INVALID_HANDLE_VALUE)
{
! evtHandle = RegisterEventSource(NULL, "PostgreSQL");
if (evtHandle == NULL)
{
evtHandle = INVALID_HANDLE_VALUE;
--- 1646,1652 ----
if (evtHandle == INVALID_HANDLE_VALUE)
{
! evtHandle = RegisterEventSource(NULL, event_source ? event_source : "PostgreSQL");
if (evtHandle == NULL)
{
evtHandle = INVALID_HANDLE_VALUE;
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
new file mode 100644
index 92391ed..a6420b2
*** a/src/backend/utils/misc/guc.c
--- b/src/backend/utils/misc/guc.c
*************** bool log_executor_stats = false;
*** 411,416 ****
--- 411,417 ----
bool log_statement_stats = false; /* this is sort of all three
* above together */
bool log_btree_build_stats = false;
+ char *event_source;
bool check_function_bodies = true;
bool default_with_oids = false;
*************** int tcp_keepalives_count;
*** 449,454 ****
--- 450,458 ----
static char *log_destination_string;
static char *syslog_ident_str;
+ #ifdef WIN32
+ static char *event_source_str;
+ #endif
static bool phony_autocommit;
static bool session_auth_is_superuser;
static double phony_random_seed;
*************** static struct config_string ConfigureNam
*** 2822,2827 ****
--- 2826,2844 ----
NULL, assign_syslog_ident, NULL
},
+ #ifdef WIN32
+ {
+ {"event_source", PGC_POSTMASTER, LOGGING_WHERE,
+ gettext_noop("Sets the application name used to identify"
+ "PostgreSQL messages in the event log."),
+ NULL
+ },
+ &event_source,
+ "PostgreSQL",
+ NULL, NULL, NULL
+ },
+ #endif
+
{
{"TimeZone", PGC_USERSET, CLIENT_CONN_LOCALE,
gettext_noop("Sets the time zone for displaying and interpreting time stamps."),
*************** assign_syslog_ident(const char *newval,
*** 8213,8219 ****
#endif
/* Without syslog support, it will always be set to "none", so ignore */
}
-
static void
assign_session_replication_role(int newval, void *extra)
--- 8230,8235 ----
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
new file mode 100644
index 655dad4..a6f4c3d
*** a/src/backend/utils/misc/postgresql.conf.sample
--- b/src/backend/utils/misc/postgresql.conf.sample
***************
*** 300,305 ****
--- 300,308 ----
#syslog_facility = 'LOCAL0'
#syslog_ident = 'postgres'
+ # This is relevant only when logging to eventlog:
+ #event_source = 'PostgreSQL'
+
#silent_mode = off # Run server silently.
# DO NOT USE without syslog or
# logging_collector
diff --git a/src/bin/pgevent/pgevent.c b/src/bin/pgevent/pgevent.c
new file mode 100644
index 1fcde86..cab75c3
*** a/src/bin/pgevent/pgevent.c
--- b/src/bin/pgevent/pgevent.c
***************
*** 15,31 ****
#include <windows.h>
#include <olectl.h>
#include <string.h>
/* Global variables */
HANDLE g_module = NULL; /* hModule of DLL */
/* Prototypes */
! STDAPI
! DllRegisterServer(void);
STDAPI DllUnregisterServer(void);
BOOL WINAPI DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved);
/*
* DllRegisterServer --- Instructs DLL to create its registry entries
*/
--- 15,67 ----
#include <windows.h>
#include <olectl.h>
#include <string.h>
+ #include <stdio.h>
+ #include <stdlib.h>
/* Global variables */
HANDLE g_module = NULL; /* hModule of DLL */
+ /*
+ * The event source is stored as a registry key.
+ * The maximum length of a registry key is 255 characters.
+ * http://msdn.microsoft.com/en-us/library/ms724872(v=vs.85).aspx
+ */
+ char event_source[256] = "PostgreSQL";
/* Prototypes */
! HRESULT DllInstall(BOOL bInstall, __in_opt LPCWSTR pszCmdLine);
! STDAPI DllRegisterServer(void);
STDAPI DllUnregisterServer(void);
BOOL WINAPI DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved);
/*
+ * DllInstall --- Passes the command line argument to DLL
+ */
+
+ HRESULT
+ DllInstall(BOOL bInstall,
+ __in_opt LPCWSTR pszCmdLine)
+ {
+ size_t ret;
+
+ if (pszCmdLine && *pszCmdLine != '\0')
+ wcstombs_s(&ret, event_source, sizeof(event_source),
+ pszCmdLine, sizeof(event_source));
+
+ /*
+ * This is an ugry part due to the strange behavior of "regsvr32 /i".
+ * When installing, regsvr32 calls DllRegisterServer before DllInstall.
+ * When uninstalling (i.e. "regsvr32 /u /i"), on the other hand,
+ * regsvr32 calls DllInstall and then DllUnregisterServer as expected.
+ * This strange behavior forces us to specify -n (i.e. "regsvr32 /n /i").
+ * Without -n, DllRegisterServer called before DllInstall would
+ * mistakenly overwrite the default "PostgreSQL" event source registration.
+ */
+ if (bInstall)
+ DllRegisterServer();
+ return S_OK;
+ }
+
+ /*
* DllRegisterServer --- Instructs DLL to create its registry entries
*/
*************** DllRegisterServer(void)
*** 35,40 ****
--- 71,77 ----
HKEY key;
DWORD data;
char buffer[_MAX_PATH];
+ char key_name[400];
/* Set the name of DLL full path name. */
if (!GetModuleFileName((HMODULE) g_module, buffer, sizeof(buffer)))
*************** DllRegisterServer(void)
*** 47,53 ****
* Add PostgreSQL source name as a subkey under the Application key in the
* EventLog registry key.
*/
! if (RegCreateKey(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\PostgreSQL", &key))
{
MessageBox(NULL, "Could not create the registry key.", "PostgreSQL error", MB_OK | MB_ICONSTOP);
return SELFREG_E_TYPELIB;
--- 84,93 ----
* Add PostgreSQL source name as a subkey under the Application key in the
* EventLog registry key.
*/
! snprintf(key_name, sizeof(key_name),
! "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\%s",
! event_source);
! if (RegCreateKey(HKEY_LOCAL_MACHINE, key_name, &key))
{
MessageBox(NULL, "Could not create the registry key.", "PostgreSQL error", MB_OK | MB_ICONSTOP);
return SELFREG_E_TYPELIB;
*************** DllRegisterServer(void)
*** 90,101 ****
STDAPI
DllUnregisterServer(void)
{
/*
* Remove PostgreSQL source name as a subkey under the Application key in
* the EventLog registry key.
*/
! if (RegDeleteKey(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\PostgreSQL"))
{
MessageBox(NULL, "Could not delete the registry key.", "PostgreSQL error", MB_OK | MB_ICONSTOP);
return SELFREG_E_TYPELIB;
--- 130,146 ----
STDAPI
DllUnregisterServer(void)
{
+ char key_name[400];
+
/*
* Remove PostgreSQL source name as a subkey under the Application key in
* the EventLog registry key.
*/
! snprintf(key_name, sizeof(key_name),
! "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\%s",
! event_source);
! if (RegDeleteKey(HKEY_LOCAL_MACHINE, key_name))
{
MessageBox(NULL, "Could not delete the registry key.", "PostgreSQL error", MB_OK | MB_ICONSTOP);
return SELFREG_E_TYPELIB;
diff --git a/src/bin/pgevent/pgevent.def b/src/bin/pgevent/pgevent.def
new file mode 100644
index 21bab7a..6b4d44a
*** a/src/bin/pgevent/pgevent.def
--- b/src/bin/pgevent/pgevent.def
***************
*** 2,4 ****
--- 2,5 ----
EXPORTS
DllUnregisterServer ;
DllRegisterServer ;
+ DllInstall ;
2011/7/16 MauMau <maumau307@gmail.com>:
Hello,
The attached file is a revised patch which reflects all review comments by
Magnus in:http://archives.postgresql.org/pgsql-hackers/2011-07/msg00839.php
I made sure the previous tests (both custom and default "PostgreSQL" event
source) succeeded.I'm submitting this to the currently open CommitFest 2001-9 shortly. Please
review it again.
I have applied this patch after another round of rather extensive modifications.
--
Magnus Hagander
Me: http://www.hagander.net/
Work: http://www.redpill-linpro.com/
From: "Magnus Hagander" <magnus@hagander.net>
2011/7/16 MauMau <maumau307@gmail.com>:
Hello,
The attached file is a revised patch which reflects all review comments by
Magnus in:http://archives.postgresql.org/pgsql-hackers/2011-07/msg00839.php
I have applied this patch after another round of rather extensive
modifications.
Thank you, Magnus. I'll see the final code some later.
Regards
MauMau