From c53611e3e7dc74c0c7dd79c78873fda1887f5b7f Mon Sep 17 00:00:00 2001 From: Bruce Momjian Date: Tue, 17 Feb 2004 03:54:57 +0000 Subject: [PATCH] This patch brings up to date what I did last year (now unfortunately bitrotted) to allow the logging of the end of a session, enabled by the config setting "log_disconnections". Andrew Dunstan --- doc/src/sgml/runtime.sgml | 16 +++- src/backend/postmaster/postmaster.c | 15 +++- src/backend/tcop/postgres.c | 73 ++++++++++++++++++- src/backend/utils/misc/guc.c | 11 ++- src/backend/utils/misc/postgresql.conf.sample | 1 + src/include/libpq/libpq-be.h | 5 +- 6 files changed, 116 insertions(+), 5 deletions(-) diff --git a/doc/src/sgml/runtime.sgml b/doc/src/sgml/runtime.sgml index 67e8931273..e6bc6f7be4 100644 --- a/doc/src/sgml/runtime.sgml +++ b/doc/src/sgml/runtime.sgml @@ -1,5 +1,5 @@ @@ -1909,6 +1909,20 @@ SET ENABLE_SEQSCAN TO OFF; + + log_disconnections (boolean) + + + This outputs a line in the server logs similar to LOG_CONNECTIONS + but at session termination, and includes the duration of the + session. This is off by default. This option can only be set at + server start or in the postgresql.conf + configuration file. + + + + + log_duration (boolean) diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index 2809cd9f5e..ab9af54bac 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -37,7 +37,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.366 2004/02/11 22:25:02 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.367 2004/02/17 03:54:56 momjian Exp $ * * NOTES * @@ -2428,6 +2428,13 @@ BackendInit(Port *port) * Signal handlers setting is moved to tcop/postgres... */ + /* save start time for end of session reporting */ + gettimeofday(&(port->session_start),NULL); + + /* set these to empty in case they are needed before we set them up */ + port->remote_host = ""; + port->remote_port = ""; + /* Save port etc. for ps status */ MyProcPort = port; @@ -2483,6 +2490,12 @@ BackendInit(Port *port) StrNCpy(remote_host, tmphost, sizeof(remote_host)); } + /* + * save remote_host and remote_port in port stucture + */ + port->remote_host = strdup(remote_host); + port->remote_port = strdup(remote_port); + /* * Ready to begin client interaction. We will give up and exit(0) * after a time delay, so that a broken client can't hog a connection diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index 735e5aa69d..19cb8909ac 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.389 2004/02/06 19:36:18 wieck Exp $ + * $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.390 2004/02/17 03:54:57 momjian Exp $ * * NOTES * this is the "main" module of the postgres backend and @@ -84,6 +84,9 @@ sigjmp_buf Warn_restart; bool Warn_restart_ready = false; bool InError = false; +/* flag for logging end of session */ +bool Log_disconnections = false; + /* * Flags for expensive function optimization -- JMH 3/9/92 */ @@ -149,6 +152,7 @@ static void start_xact_command(void); static void finish_xact_command(void); static void SigHupHandler(SIGNAL_ARGS); static void FloatExceptionHandler(SIGNAL_ARGS); +static void log_session_end(void); /* ---------------------------------------------------------------- @@ -2406,7 +2410,10 @@ PostgresMain(int argc, char *argv[], const char *username) * other output options. */ if (debug_flag >= 1) + { SetConfigOption("log_connections", "true", debug_context, gucsource); + SetConfigOption("log_disconnections", "true", debug_context, gucsource); + } if (debug_flag >= 2) SetConfigOption("log_statement", "true", debug_context, gucsource); if (debug_flag >= 3) @@ -2435,6 +2442,12 @@ PostgresMain(int argc, char *argv[], const char *username) gucopts = lnext(gucopts); SetConfigOption(name, value, PGC_BACKEND, PGC_S_CLIENT); } + + /* + * set up handler to log session end. + */ + if (IsUnderPostmaster && Log_disconnections) + on_proc_exit(log_session_end,0); } /* @@ -3178,3 +3191,61 @@ ShowUsage(const char *title) pfree(str.data); } + +/* + * on_proc_exit handler to log end of session + */ +static void +log_session_end(void) +{ + Port * port = MyProcPort; + struct timeval end; + int hours, minutes, seconds; + + char session_time[20]; + char uname[6+NAMEDATALEN]; + char dbname[10+NAMEDATALEN]; + char remote_host[7 + NI_MAXHOST]; + char remote_port[7 + NI_MAXSERV]; + + snprintf(uname, sizeof(uname)," user=%s",port->user_name); + snprintf(dbname, sizeof(dbname)," database=%s",port->database_name); + snprintf(remote_host,sizeof(remote_host)," host=%s", + port->remote_host); + /* prevent redundant or empty reporting of port */ + if (!LogSourcePort && strlen(port->remote_port)) + snprintf(remote_port,sizeof(remote_port)," port=%s",port->remote_port); + else + remote_port[0] = '\0'; + + + gettimeofday(&end,NULL); + + if (end.tv_usec < port->session_start.tv_usec) + { + end.tv_sec--; + end.tv_usec += 1000000; + } + end.tv_sec -= port->session_start.tv_sec; + end.tv_usec -= port->session_start.tv_usec; + + hours = end.tv_sec / 3600; + end.tv_sec %= 3600; + minutes = end.tv_sec / 60; + seconds = end.tv_sec % 60; + + /* if time has gone backwards for some reason say so, or print time */ + + if (end.tv_sec < 0) + snprintf(session_time,sizeof(session_time),"negative!"); + else + /* for stricter accuracy here we could round - this is close enough */ + snprintf(session_time, sizeof(session_time),"%d:%02d:%02d.%02ld", + hours, minutes, seconds, end.tv_usec/10000); + + ereport( + LOG, + (errmsg("disconnection: session time: %s%s%s%s%s", + session_time,uname,dbname,remote_host,remote_port))); + +} diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index 7fe7c33cf8..1dbf330ef6 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -10,7 +10,7 @@ * Written by Peter Eisentraut . * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.186 2004/02/06 19:36:18 wieck Exp $ + * $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.187 2004/02/17 03:54:57 momjian Exp $ * *-------------------------------------------------------------------- */ @@ -65,6 +65,7 @@ /* XXX these should appear in other modules' header files */ extern bool Log_connections; +extern bool Log_disconnections; extern bool check_function_bodies; extern int PreAuthDelay; extern int AuthenticationTimeout; @@ -499,6 +500,14 @@ static struct config_bool ConfigureNamesBool[] = &Log_connections, false, NULL, NULL }, + { + {"log_disconnections", PGC_BACKEND, LOGGING_WHAT, + gettext_noop("Logs end of a session, including duration"), + NULL + }, + &Log_disconnections, + false, NULL, NULL + }, { {"log_timestamp", PGC_SIGHUP, LOGGING_WHAT, gettext_noop("Prefixes server log messages with a time stamp."), diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample index 85e7ce899d..3d58e9783f 100644 --- a/src/backend/utils/misc/postgresql.conf.sample +++ b/src/backend/utils/misc/postgresql.conf.sample @@ -182,6 +182,7 @@ #debug_print_plan = false #debug_pretty_print = false #log_connections = false +#log_disconnections = false #log_duration = false #log_pid = false #log_statement = false diff --git a/src/include/libpq/libpq-be.h b/src/include/libpq/libpq-be.h index f011afed86..09bd92136d 100644 --- a/src/include/libpq/libpq-be.h +++ b/src/include/libpq/libpq-be.h @@ -11,7 +11,7 @@ * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/libpq/libpq-be.h,v 1.39 2003/12/20 17:31:21 momjian Exp $ + * $PostgreSQL: pgsql/src/include/libpq/libpq-be.h,v 1.40 2004/02/17 03:54:57 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -47,6 +47,9 @@ typedef struct Port ProtocolVersion proto; /* FE/BE protocol version */ SockAddr laddr; /* local addr (postmaster) */ SockAddr raddr; /* remote addr (client) */ + char *remote_host; /* name (or ip addr) of remote host */ + char *remote_port; /* text rep of remote port */ + struct timeval session_start; /* for session duration logging */ CAC_state canAcceptConnections; /* postmaster connection status */ /*