@@ -338,6 +338,8 @@ pgstat_bestart(void)
338338 lbeentry .st_xact_start_timestamp = 0 ;
339339 lbeentry .st_databaseid = MyDatabaseId ;
340340
341+ MemSet (& lbeentry .st_session , 0 , sizeof (lbeentry .st_session ));
342+
341343 /* We have userid for client-backends, wal-sender and bgworker processes */
342344 if (lbeentry .st_backendType == B_BACKEND
343345 || lbeentry .st_backendType == B_WAL_SENDER
@@ -525,6 +527,9 @@ pgstat_report_activity(BackendState state, const char *cmd_str)
525527 TimestampTz current_timestamp ;
526528 int len = 0 ;
527529
530+ PgBackendSessionStatus st_session_diff ;
531+ MemSet (& st_session_diff , 0 , sizeof (st_session_diff ));
532+
528533 TRACE_POSTGRESQL_STATEMENT_STATUS (cmd_str );
529534
530535 if (!beentry )
@@ -550,6 +555,10 @@ pgstat_report_activity(BackendState state, const char *cmd_str)
550555 beentry -> st_xact_start_timestamp = 0 ;
551556 beentry -> st_query_id = UINT64CONST (0 );
552557 proc -> wait_event_info = 0 ;
558+ beentry -> st_session .total_active_time = 0 ;
559+ beentry -> st_session .total_active_count = 0 ;
560+ beentry -> st_session .total_transaction_idle_time = 0 ;
561+ beentry -> st_session .total_transaction_idle_count = 0 ;
553562 PGSTAT_END_WRITE_ACTIVITY (beentry );
554563 }
555564 return ;
@@ -575,24 +584,40 @@ pgstat_report_activity(BackendState state, const char *cmd_str)
575584 * If the state has changed from "active" or "idle in transaction",
576585 * calculate the duration.
577586 */
578- if ((beentry -> st_state == STATE_RUNNING ||
579- beentry -> st_state == STATE_FASTPATH ||
580- beentry -> st_state == STATE_IDLEINTRANSACTION ||
581- beentry -> st_state == STATE_IDLEINTRANSACTION_ABORTED ) &&
587+ if ((PGSTAT_IS_ACTIVE (beentry ) || PGSTAT_IS_IDLEINTRANSACTION (beentry )) &&
582588 state != beentry -> st_state )
583589 {
584590 long secs ;
585591 int usecs ;
592+ int64 usecs_diff ;
586593
587594 TimestampDifference (beentry -> st_state_start_timestamp ,
588595 current_timestamp ,
589596 & secs , & usecs );
597+ usecs_diff = secs * 1000000 + usecs ;
590598
591- if (beentry -> st_state == STATE_RUNNING ||
592- beentry -> st_state == STATE_FASTPATH )
599+ if (PGSTAT_IS_ACTIVE (beentry ))
593600 pgstat_count_conn_active_time ((PgStat_Counter ) secs * 1000000 + usecs );
594601 else
595602 pgstat_count_conn_txn_idle_time ((PgStat_Counter ) secs * 1000000 + usecs );
603+
604+ /*
605+ * We update per-backend st_total_active_time and st_total_transaction_idle_time
606+ * separately from pgStatActiveTime and pgStatTransactionIdleTime
607+ * used in pg_stat_database to provide per-DB statistics because
608+ * 1. Changing the former values implies modifying beentry and thus
609+ * have to be wrapped into PGSTAT_*_WRITE_ACTIVITY macros (see below).
610+ * 2. The latter values are reset to 0 once the data has been sent
611+ * to the statistics collector.
612+ */
613+ if (PGSTAT_IS_ACTIVE (beentry )) {
614+ st_session_diff .total_active_time = usecs_diff ;
615+ st_session_diff .total_active_count += 1 ;
616+ }
617+ else {
618+ st_session_diff .total_transaction_idle_time = usecs_diff ;
619+ st_session_diff .total_transaction_idle_count += 1 ;
620+ }
596621 }
597622
598623 /*
@@ -618,6 +643,12 @@ pgstat_report_activity(BackendState state, const char *cmd_str)
618643 beentry -> st_activity_start_timestamp = start_timestamp ;
619644 }
620645
646+ beentry -> st_session .total_active_time += st_session_diff .total_active_time ;
647+ beentry -> st_session .total_active_count += st_session_diff .total_active_count ;
648+
649+ beentry -> st_session .total_transaction_idle_time += st_session_diff .total_transaction_idle_time ;
650+ beentry -> st_session .total_transaction_idle_count += st_session_diff .total_transaction_idle_count ;
651+
621652 PGSTAT_END_WRITE_ACTIVITY (beentry );
622653}
623654
0 commit comments