@@ -246,6 +246,7 @@ static int pgStatXactCommit = 0;
246246static int pgStatXactRollback = 0 ;
247247PgStat_Counter pgStatBlockReadTime = 0 ;
248248PgStat_Counter pgStatBlockWriteTime = 0 ;
249+ static PgStat_Counter pgLastSessionReportTime = 0 ;
249250PgStat_Counter pgStatActiveTime = 0 ;
250251PgStat_Counter pgStatTransactionIdleTime = 0 ;
251252SessionEndType pgStatSessionEndCause = DISCONNECT_NORMAL ;
@@ -330,11 +331,12 @@ static bool pgstat_db_requested(Oid databaseid);
330331static PgStat_StatReplSlotEntry * pgstat_get_replslot_entry (NameData name , bool create_it );
331332static void pgstat_reset_replslot (PgStat_StatReplSlotEntry * slotstats , TimestampTz ts );
332333
333- static void pgstat_send_tabstat (PgStat_MsgTabstat * tsmsg );
334+ static void pgstat_send_tabstat (PgStat_MsgTabstat * tsmsg , TimestampTz now );
334335static void pgstat_send_funcstats (void );
335336static void pgstat_send_slru (void );
336337static HTAB * pgstat_collect_oids (Oid catalogid , AttrNumber anum_oid );
337- static void pgstat_send_connstats (bool disconnect , TimestampTz last_report );
338+ static bool pgstat_should_report_connstat (void );
339+ static void pgstat_report_disconnect (Oid dboid );
338340
339341static PgStat_TableStatus * get_tabstat_entry (Oid rel_id , bool isshared );
340342
@@ -366,7 +368,8 @@ static void pgstat_recv_funcpurge(PgStat_MsgFuncpurge *msg, int len);
366368static void pgstat_recv_recoveryconflict (PgStat_MsgRecoveryConflict * msg , int len );
367369static void pgstat_recv_deadlock (PgStat_MsgDeadlock * msg , int len );
368370static void pgstat_recv_checksum_failure (PgStat_MsgChecksumFailure * msg , int len );
369- static void pgstat_recv_connstat (PgStat_MsgConn * msg , int len );
371+ static void pgstat_recv_connect (PgStat_MsgConnect * msg , int len );
372+ static void pgstat_recv_disconnect (PgStat_MsgDisconnect * msg , int len );
370373static void pgstat_recv_replslot (PgStat_MsgReplSlot * msg , int len );
371374static void pgstat_recv_tempfile (PgStat_MsgTempFile * msg , int len );
372375
@@ -890,12 +893,11 @@ pgstat_report_stat(bool disconnect)
890893 !TimestampDifferenceExceeds (last_report , now , PGSTAT_STAT_INTERVAL ))
891894 return ;
892895
893- /* for backends, send connection statistics */
894- if (MyBackendType == B_BACKEND )
895- pgstat_send_connstats (disconnect , last_report );
896-
897896 last_report = now ;
898897
898+ if (disconnect )
899+ pgstat_report_disconnect (MyDatabaseId );
900+
899901 /*
900902 * Destroy pgStatTabHash before we start invalidating PgStat_TableEntry
901903 * entries it points to. (Should we fail partway through the loop below,
@@ -947,7 +949,7 @@ pgstat_report_stat(bool disconnect)
947949 sizeof (PgStat_TableCounts ));
948950 if (++ this_msg -> m_nentries >= PGSTAT_NUM_TABENTRIES )
949951 {
950- pgstat_send_tabstat (this_msg );
952+ pgstat_send_tabstat (this_msg , now );
951953 this_msg -> m_nentries = 0 ;
952954 }
953955 }
@@ -959,13 +961,14 @@ pgstat_report_stat(bool disconnect)
959961
960962 /*
961963 * Send partial messages. Make sure that any pending xact commit/abort
962- * gets counted, even if there are no table stats to send.
964+ * and connection stats get counted, even if there are no table stats to
965+ * send.
963966 */
964967 if (regular_msg .m_nentries > 0 ||
965- pgStatXactCommit > 0 || pgStatXactRollback > 0 )
966- pgstat_send_tabstat (& regular_msg );
968+ pgStatXactCommit > 0 || pgStatXactRollback > 0 || disconnect )
969+ pgstat_send_tabstat (& regular_msg , now );
967970 if (shared_msg .m_nentries > 0 )
968- pgstat_send_tabstat (& shared_msg );
971+ pgstat_send_tabstat (& shared_msg , now );
969972
970973 /* Now, send function statistics */
971974 pgstat_send_funcstats ();
@@ -981,7 +984,7 @@ pgstat_report_stat(bool disconnect)
981984 * Subroutine for pgstat_report_stat: finish and send a tabstat message
982985 */
983986static void
984- pgstat_send_tabstat (PgStat_MsgTabstat * tsmsg )
987+ pgstat_send_tabstat (PgStat_MsgTabstat * tsmsg , TimestampTz now )
985988{
986989 int n ;
987990 int len ;
@@ -1000,17 +1003,44 @@ pgstat_send_tabstat(PgStat_MsgTabstat *tsmsg)
10001003 tsmsg -> m_xact_rollback = pgStatXactRollback ;
10011004 tsmsg -> m_block_read_time = pgStatBlockReadTime ;
10021005 tsmsg -> m_block_write_time = pgStatBlockWriteTime ;
1006+
1007+ if (pgstat_should_report_connstat ())
1008+ {
1009+ long secs ;
1010+ int usecs ;
1011+
1012+ /*
1013+ * pgLastSessionReportTime is initialized to MyStartTimestamp by
1014+ * pgstat_report_connect().
1015+ */
1016+ TimestampDifference (pgLastSessionReportTime , now , & secs , & usecs );
1017+ pgLastSessionReportTime = now ;
1018+ tsmsg -> m_session_time = (PgStat_Counter ) secs * 1000000 + usecs ;
1019+ tsmsg -> m_active_time = pgStatActiveTime ;
1020+ tsmsg -> m_idle_in_xact_time = pgStatTransactionIdleTime ;
1021+ }
1022+ else
1023+ {
1024+ tsmsg -> m_session_time = 0 ;
1025+ tsmsg -> m_active_time = 0 ;
1026+ tsmsg -> m_idle_in_xact_time = 0 ;
1027+ }
10031028 pgStatXactCommit = 0 ;
10041029 pgStatXactRollback = 0 ;
10051030 pgStatBlockReadTime = 0 ;
10061031 pgStatBlockWriteTime = 0 ;
1032+ pgStatActiveTime = 0 ;
1033+ pgStatTransactionIdleTime = 0 ;
10071034 }
10081035 else
10091036 {
10101037 tsmsg -> m_xact_commit = 0 ;
10111038 tsmsg -> m_xact_rollback = 0 ;
10121039 tsmsg -> m_block_read_time = 0 ;
10131040 tsmsg -> m_block_write_time = 0 ;
1041+ tsmsg -> m_session_time = 0 ;
1042+ tsmsg -> m_active_time = 0 ;
1043+ tsmsg -> m_idle_in_xact_time = 0 ;
10141044 }
10151045
10161046 n = tsmsg -> m_nentries ;
@@ -1378,49 +1408,6 @@ pgstat_drop_relation(Oid relid)
13781408}
13791409#endif /* NOT_USED */
13801410
1381-
1382- /* ----------
1383- * pgstat_send_connstats() -
1384- *
1385- * Tell the collector about session statistics.
1386- * The parameter "disconnect" will be true when the backend exits.
1387- * "last_report" is the last time we were called (0 if never).
1388- * ----------
1389- */
1390- static void
1391- pgstat_send_connstats (bool disconnect , TimestampTz last_report )
1392- {
1393- PgStat_MsgConn msg ;
1394- long secs ;
1395- int usecs ;
1396-
1397- if (pgStatSock == PGINVALID_SOCKET || !pgstat_track_counts )
1398- return ;
1399-
1400- pgstat_setheader (& msg .m_hdr , PGSTAT_MTYPE_CONNECTION );
1401- msg .m_databaseid = MyDatabaseId ;
1402-
1403- /* session time since the last report */
1404- TimestampDifference (((last_report == 0 ) ? MyStartTimestamp : last_report ),
1405- GetCurrentTimestamp (),
1406- & secs , & usecs );
1407- msg .m_session_time = secs * 1000000 + usecs ;
1408-
1409- msg .m_disconnect = disconnect ? pgStatSessionEndCause : DISCONNECT_NOT_YET ;
1410-
1411- msg .m_active_time = pgStatActiveTime ;
1412- pgStatActiveTime = 0 ;
1413-
1414- msg .m_idle_in_xact_time = pgStatTransactionIdleTime ;
1415- pgStatTransactionIdleTime = 0 ;
1416-
1417- /* report a new session only the first time */
1418- msg .m_count = (last_report == 0 ) ? 1 : 0 ;
1419-
1420- pgstat_send (& msg , sizeof (PgStat_MsgConn ));
1421- }
1422-
1423-
14241411/* ----------
14251412 * pgstat_reset_counters() -
14261413 *
@@ -1759,6 +1746,63 @@ pgstat_report_tempfile(size_t filesize)
17591746 pgstat_send (& msg , sizeof (msg ));
17601747}
17611748
1749+ /* --------
1750+ * pgstat_report_connect() -
1751+ *
1752+ * Tell the collector about a new connection.
1753+ * --------
1754+ */
1755+ void
1756+ pgstat_report_connect (Oid dboid )
1757+ {
1758+ PgStat_MsgConnect msg ;
1759+
1760+ if (!pgstat_should_report_connstat ())
1761+ return ;
1762+
1763+ pgLastSessionReportTime = MyStartTimestamp ;
1764+
1765+ pgstat_setheader (& msg .m_hdr , PGSTAT_MTYPE_CONNECT );
1766+ msg .m_databaseid = MyDatabaseId ;
1767+ pgstat_send (& msg , sizeof (PgStat_MsgConnect ));
1768+ }
1769+
1770+ /* --------
1771+ * pgstat_report_disconnect() -
1772+ *
1773+ * Tell the collector about a disconnect.
1774+ * --------
1775+ */
1776+ static void
1777+ pgstat_report_disconnect (Oid dboid )
1778+ {
1779+ PgStat_MsgDisconnect msg ;
1780+
1781+ if (!pgstat_should_report_connstat ())
1782+ return ;
1783+
1784+ pgstat_setheader (& msg .m_hdr , PGSTAT_MTYPE_DISCONNECT );
1785+ msg .m_databaseid = MyDatabaseId ;
1786+ msg .m_cause = pgStatSessionEndCause ;
1787+ pgstat_send (& msg , sizeof (PgStat_MsgDisconnect ));
1788+ }
1789+
1790+ /* --------
1791+ * pgstat_should_report_connstats() -
1792+ *
1793+ * We report session statistics only for normal backend processes. Parallel
1794+ * workers run in parallel, so they don't contribute to session times, even
1795+ * though they use CPU time. Walsender processes could be considered here,
1796+ * but they have different session characteristics from normal backends (for
1797+ * example, they are always "active"), so they would skew session statistics.
1798+ * ----------
1799+ */
1800+ static bool
1801+ pgstat_should_report_connstat (void )
1802+ {
1803+ return MyBackendType == B_BACKEND ;
1804+ }
1805+
17621806/* ----------
17631807 * pgstat_report_replslot() -
17641808 *
@@ -3465,8 +3509,12 @@ PgstatCollectorMain(int argc, char *argv[])
34653509 pgstat_recv_replslot (& msg .msg_replslot , len );
34663510 break ;
34673511
3468- case PGSTAT_MTYPE_CONNECTION :
3469- pgstat_recv_connstat (& msg .msg_conn , len );
3512+ case PGSTAT_MTYPE_CONNECT :
3513+ pgstat_recv_connect (& msg .msg_connect , len );
3514+ break ;
3515+
3516+ case PGSTAT_MTYPE_DISCONNECT :
3517+ pgstat_recv_disconnect (& msg .msg_disconnect , len );
34703518 break ;
34713519
34723520 default :
@@ -4904,6 +4952,10 @@ pgstat_recv_tabstat(PgStat_MsgTabstat *msg, int len)
49044952 dbentry -> n_block_read_time += msg -> m_block_read_time ;
49054953 dbentry -> n_block_write_time += msg -> m_block_write_time ;
49064954
4955+ dbentry -> total_session_time += msg -> m_session_time ;
4956+ dbentry -> total_active_time += msg -> m_active_time ;
4957+ dbentry -> total_idle_in_xact_time += msg -> m_idle_in_xact_time ;
4958+
49074959 /*
49084960 * Process all table entries in the message.
49094961 */
@@ -5568,23 +5620,34 @@ pgstat_recv_replslot(PgStat_MsgReplSlot *msg, int len)
55685620}
55695621
55705622/* ----------
5571- * pgstat_recv_connstat () -
5623+ * pgstat_recv_connect () -
55725624 *
5573- * Process connection information .
5625+ * Process a CONNECT message .
55745626 * ----------
55755627 */
55765628static void
5577- pgstat_recv_connstat ( PgStat_MsgConn * msg , int len )
5629+ pgstat_recv_connect ( PgStat_MsgConnect * msg , int len )
55785630{
55795631 PgStat_StatDBEntry * dbentry ;
55805632
55815633 dbentry = pgstat_get_db_entry (msg -> m_databaseid , true);
5634+ dbentry -> n_sessions ++ ;
5635+ }
55825636
5583- dbentry -> n_sessions += msg -> m_count ;
5584- dbentry -> total_session_time += msg -> m_session_time ;
5585- dbentry -> total_active_time += msg -> m_active_time ;
5586- dbentry -> total_idle_in_xact_time += msg -> m_idle_in_xact_time ;
5587- switch (msg -> m_disconnect )
5637+ /* ----------
5638+ * pgstat_recv_disconnect() -
5639+ *
5640+ * Process a DISCONNECT message.
5641+ * ----------
5642+ */
5643+ static void
5644+ pgstat_recv_disconnect (PgStat_MsgDisconnect * msg , int len )
5645+ {
5646+ PgStat_StatDBEntry * dbentry ;
5647+
5648+ dbentry = pgstat_get_db_entry (msg -> m_databaseid , true);
5649+
5650+ switch (msg -> m_cause )
55885651 {
55895652 case DISCONNECT_NOT_YET :
55905653 case DISCONNECT_NORMAL :
0 commit comments