mirror of
https://github.com/postgres/postgres.git
synced 2025-06-11 20:28:21 +03:00
There was a wild mishmash of function comment formatting in pgstat, making it hard to know what to use for any new function and hard to extend existing comments (particularly due to randomly different forms of indentation). Author: Andres Freund <andres@anarazel.de> Reviewed-By: Thomas Munro <thomas.munro@gmail.com> Discussion: https://postgr.es/m/20220329191727.mzzwbl7udhpq7pmf@alap3.anarazel.de Discussion: https://postgr.es/m/20220308205351.2xcn6k4x5yivcxyd@alap3.anarazel.de
253 lines
5.9 KiB
C
253 lines
5.9 KiB
C
/* -------------------------------------------------------------------------
|
|
*
|
|
* pgstat_database.c
|
|
* Implementation of database statistics.
|
|
*
|
|
* This file contains the implementation of database statistics. It is kept
|
|
* separate from pgstat.c to enforce the line between the statistics access /
|
|
* storage implementation and the details about individual types of
|
|
* statistics.
|
|
*
|
|
* Copyright (c) 2001-2022, PostgreSQL Global Development Group
|
|
*
|
|
* IDENTIFICATION
|
|
* src/backend/utils/activity/pgstat_database.c
|
|
* -------------------------------------------------------------------------
|
|
*/
|
|
|
|
#include "postgres.h"
|
|
|
|
#include "utils/pgstat_internal.h"
|
|
#include "utils/timestamp.h"
|
|
|
|
|
|
static bool pgstat_should_report_connstat(void);
|
|
|
|
|
|
int pgStatXactCommit = 0;
|
|
int pgStatXactRollback = 0;
|
|
PgStat_Counter pgStatBlockReadTime = 0;
|
|
PgStat_Counter pgStatBlockWriteTime = 0;
|
|
PgStat_Counter pgStatActiveTime = 0;
|
|
PgStat_Counter pgStatTransactionIdleTime = 0;
|
|
SessionEndType pgStatSessionEndCause = DISCONNECT_NORMAL;
|
|
|
|
|
|
static PgStat_Counter pgLastSessionReportTime = 0;
|
|
|
|
|
|
/*
|
|
* Tell the collector that we just dropped a database.
|
|
* (If the message gets lost, we will still clean the dead DB eventually
|
|
* via future invocations of pgstat_vacuum_stat().)
|
|
*/
|
|
void
|
|
pgstat_drop_database(Oid databaseid)
|
|
{
|
|
PgStat_MsgDropdb msg;
|
|
|
|
if (pgStatSock == PGINVALID_SOCKET)
|
|
return;
|
|
|
|
pgstat_setheader(&msg.m_hdr, PGSTAT_MTYPE_DROPDB);
|
|
msg.m_databaseid = databaseid;
|
|
pgstat_send(&msg, sizeof(msg));
|
|
}
|
|
|
|
/*
|
|
* Tell the collector about a Hot Standby recovery conflict.
|
|
*/
|
|
void
|
|
pgstat_report_recovery_conflict(int reason)
|
|
{
|
|
PgStat_MsgRecoveryConflict msg;
|
|
|
|
if (pgStatSock == PGINVALID_SOCKET || !pgstat_track_counts)
|
|
return;
|
|
|
|
pgstat_setheader(&msg.m_hdr, PGSTAT_MTYPE_RECOVERYCONFLICT);
|
|
msg.m_databaseid = MyDatabaseId;
|
|
msg.m_reason = reason;
|
|
pgstat_send(&msg, sizeof(msg));
|
|
}
|
|
|
|
/*
|
|
* Tell the collector about a deadlock detected.
|
|
*/
|
|
void
|
|
pgstat_report_deadlock(void)
|
|
{
|
|
PgStat_MsgDeadlock msg;
|
|
|
|
if (pgStatSock == PGINVALID_SOCKET || !pgstat_track_counts)
|
|
return;
|
|
|
|
pgstat_setheader(&msg.m_hdr, PGSTAT_MTYPE_DEADLOCK);
|
|
msg.m_databaseid = MyDatabaseId;
|
|
pgstat_send(&msg, sizeof(msg));
|
|
}
|
|
|
|
/*
|
|
* Tell the collector about one or more checksum failures.
|
|
*/
|
|
void
|
|
pgstat_report_checksum_failures_in_db(Oid dboid, int failurecount)
|
|
{
|
|
PgStat_MsgChecksumFailure msg;
|
|
|
|
if (pgStatSock == PGINVALID_SOCKET || !pgstat_track_counts)
|
|
return;
|
|
|
|
pgstat_setheader(&msg.m_hdr, PGSTAT_MTYPE_CHECKSUMFAILURE);
|
|
msg.m_databaseid = dboid;
|
|
msg.m_failurecount = failurecount;
|
|
msg.m_failure_time = GetCurrentTimestamp();
|
|
|
|
pgstat_send(&msg, sizeof(msg));
|
|
}
|
|
|
|
/*
|
|
* Tell the collector about a checksum failure.
|
|
*/
|
|
void
|
|
pgstat_report_checksum_failure(void)
|
|
{
|
|
pgstat_report_checksum_failures_in_db(MyDatabaseId, 1);
|
|
}
|
|
|
|
/*
|
|
* Tell the collector about a temporary file.
|
|
*/
|
|
void
|
|
pgstat_report_tempfile(size_t filesize)
|
|
{
|
|
PgStat_MsgTempFile msg;
|
|
|
|
if (pgStatSock == PGINVALID_SOCKET || !pgstat_track_counts)
|
|
return;
|
|
|
|
pgstat_setheader(&msg.m_hdr, PGSTAT_MTYPE_TEMPFILE);
|
|
msg.m_databaseid = MyDatabaseId;
|
|
msg.m_filesize = filesize;
|
|
pgstat_send(&msg, sizeof(msg));
|
|
}
|
|
|
|
/*
|
|
* Tell the collector about a new connection.
|
|
*/
|
|
void
|
|
pgstat_report_connect(Oid dboid)
|
|
{
|
|
PgStat_MsgConnect msg;
|
|
|
|
if (!pgstat_should_report_connstat())
|
|
return;
|
|
|
|
pgLastSessionReportTime = MyStartTimestamp;
|
|
|
|
pgstat_setheader(&msg.m_hdr, PGSTAT_MTYPE_CONNECT);
|
|
msg.m_databaseid = MyDatabaseId;
|
|
pgstat_send(&msg, sizeof(PgStat_MsgConnect));
|
|
}
|
|
|
|
/*
|
|
* Tell the collector about a disconnect.
|
|
*/
|
|
void
|
|
pgstat_report_disconnect(Oid dboid)
|
|
{
|
|
PgStat_MsgDisconnect msg;
|
|
|
|
if (!pgstat_should_report_connstat())
|
|
return;
|
|
|
|
pgstat_setheader(&msg.m_hdr, PGSTAT_MTYPE_DISCONNECT);
|
|
msg.m_databaseid = MyDatabaseId;
|
|
msg.m_cause = pgStatSessionEndCause;
|
|
pgstat_send(&msg, sizeof(PgStat_MsgDisconnect));
|
|
}
|
|
|
|
void
|
|
AtEOXact_PgStat_Database(bool isCommit, bool parallel)
|
|
{
|
|
/* Don't count parallel worker transaction stats */
|
|
if (!parallel)
|
|
{
|
|
/*
|
|
* Count transaction commit or abort. (We use counters, not just
|
|
* bools, in case the reporting message isn't sent right away.)
|
|
*/
|
|
if (isCommit)
|
|
pgStatXactCommit++;
|
|
else
|
|
pgStatXactRollback++;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Subroutine for pgstat_send_tabstat: Handle xact commit/rollback and I/O
|
|
* timings.
|
|
*/
|
|
void
|
|
pgstat_update_dbstats(PgStat_MsgTabstat *tsmsg, TimestampTz now)
|
|
{
|
|
if (OidIsValid(tsmsg->m_databaseid))
|
|
{
|
|
tsmsg->m_xact_commit = pgStatXactCommit;
|
|
tsmsg->m_xact_rollback = pgStatXactRollback;
|
|
tsmsg->m_block_read_time = pgStatBlockReadTime;
|
|
tsmsg->m_block_write_time = pgStatBlockWriteTime;
|
|
|
|
if (pgstat_should_report_connstat())
|
|
{
|
|
long secs;
|
|
int usecs;
|
|
|
|
/*
|
|
* pgLastSessionReportTime is initialized to MyStartTimestamp by
|
|
* pgstat_report_connect().
|
|
*/
|
|
TimestampDifference(pgLastSessionReportTime, now, &secs, &usecs);
|
|
pgLastSessionReportTime = now;
|
|
tsmsg->m_session_time = (PgStat_Counter) secs * 1000000 + usecs;
|
|
tsmsg->m_active_time = pgStatActiveTime;
|
|
tsmsg->m_idle_in_xact_time = pgStatTransactionIdleTime;
|
|
}
|
|
else
|
|
{
|
|
tsmsg->m_session_time = 0;
|
|
tsmsg->m_active_time = 0;
|
|
tsmsg->m_idle_in_xact_time = 0;
|
|
}
|
|
pgStatXactCommit = 0;
|
|
pgStatXactRollback = 0;
|
|
pgStatBlockReadTime = 0;
|
|
pgStatBlockWriteTime = 0;
|
|
pgStatActiveTime = 0;
|
|
pgStatTransactionIdleTime = 0;
|
|
}
|
|
else
|
|
{
|
|
tsmsg->m_xact_commit = 0;
|
|
tsmsg->m_xact_rollback = 0;
|
|
tsmsg->m_block_read_time = 0;
|
|
tsmsg->m_block_write_time = 0;
|
|
tsmsg->m_session_time = 0;
|
|
tsmsg->m_active_time = 0;
|
|
tsmsg->m_idle_in_xact_time = 0;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* We report session statistics only for normal backend processes. Parallel
|
|
* workers run in parallel, so they don't contribute to session times, even
|
|
* though they use CPU time. Walsender processes could be considered here,
|
|
* but they have different session characteristics from normal backends (for
|
|
* example, they are always "active"), so they would skew session statistics.
|
|
*/
|
|
static bool
|
|
pgstat_should_report_connstat(void)
|
|
{
|
|
return MyBackendType == B_BACKEND;
|
|
}
|