On Thu, Jan 23, 2014 at 4:10 PM, Michael Paquier <michael.paqu...@gmail.com> wrote: > On Thu, Jan 9, 2014 at 6:36 AM, Gabriele Bartolini > <gabriele.bartol...@2ndquadrant.it> wrote: >> Il 08/01/14 18:42, Simon Riggs ha scritto: >>> Not sure I see why it needs to be an SRF. It only returns one row. >> Attached is version 4, which removes management of SRF stages. > > I have been looking at v4 a bit more, and found a couple of small things: > - a warning in pgstatfuncs.c > - some typos and format fixing in the sgml docs > - some corrections in a couple of comments > - Fixed an error message related to pg_stat_reset_shared referring > only to bgwriter and not the new option archiver. Here is how the new > message looks: > =# select pg_stat_reset_shared('popo'); > ERROR: 22023: unrecognized reset target: "popo" > HINT: Target must be "bgwriter" or "archiver" > A new version is attached containing those fixes. I played also with > the patch and pgbench, simulating some archive failures and successes > while running pgbench and the reports given by pg_stat_archiver were > correct, so I am marking this patch as "Ready for committer".
I refactored the patch further. * Remove ArchiverStats global variable to simplify pgarch.c. * Remove stats_timestamp field from PgStat_ArchiverStats struct because it's not required. I have some review comments: + s.archived_wals, + s.last_archived_wal, + s.last_archived_wal_time, + s.failed_attempts, + s.last_failed_wal, + s.last_failed_wal_time, The column names of pg_stat_archiver look not consistent at least to me. What about the followings? archive_count last_archived_wal last_archived_time fail_count last_failed_wal last_failed_time I think that it's time to rename all the variables related to pg_stat_bgwriter. For example, it's better to change PgStat_GlobalStats to PgStat_Bgwriter. I think that it's okay to make this change as separate patch, though. + char last_archived_wal[MAXFNAMELEN]; /* last WAL file archived */ + TimestampTz last_archived_wal_timestamp; /* last archival success */ + PgStat_Counter failed_attempts; + char last_failed_wal[MAXFNAMELEN]; /* last WAL file involved in failure */ Some hackers don't like the increase of the size of the statsfile. In order to reduce the size as much as possible, we should use the exact size of WAL file here instead of MAXFNAMELEN? Regards, -- Fujii Masao
*** a/doc/src/sgml/monitoring.sgml --- b/doc/src/sgml/monitoring.sgml *************** *** 270,275 **** postgres: <replaceable>user</> <replaceable>database</> <replaceable>host</> <re --- 270,283 ---- </row> <row> + <entry><structname>pg_stat_archiver</><indexterm><primary>pg_stat_archiver</primary></indexterm></entry> + <entry>One row only, showing statistics about the + WAL archiver process's activity. See + <xref linkend="pg-stat-archiver-view"> for details. + </entry> + </row> + + <row> <entry><structname>pg_stat_bgwriter</><indexterm><primary>pg_stat_bgwriter</primary></indexterm></entry> <entry>One row only, showing statistics about the background writer process's activity. See *************** *** 648,653 **** postgres: <replaceable>user</> <replaceable>database</> <replaceable>host</> <re --- 656,718 ---- </para> </note> + <table id="pg-stat-archiver-view" xreflabel="pg_stat_archiver"> + <title><structname>pg_stat_archiver</structname> View</title> + + <tgroup cols="3"> + <thead> + <row> + <entry>Column</entry> + <entry>Type</entry> + <entry>Description</entry> + </row> + </thead> + + <tbody> + <row> + <entry><structfield>archived_wals</></entry> + <entry><type>bigint</type></entry> + <entry>Number of WAL files that have been successfully archived</entry> + </row> + <row> + <entry><structfield>last_archived_wal</></entry> + <entry><type>text</type></entry> + <entry>Name of the last WAL file successfully archived</entry> + </row> + <row> + <entry><structfield>last_archived_wal_time</></entry> + <entry><type>timestamp with time zone</type></entry> + <entry>Time of the last successful archive operation</entry> + </row> + <row> + <entry><structfield>failed_attempts</></entry> + <entry><type>bigint</type></entry> + <entry>Number of failed attempts for archiving WAL files</entry> + </row> + <row> + <entry><structfield>last_failed_wal</></entry> + <entry><type>text</type></entry> + <entry>Name of the WAL file of the last failed archival operation</entry> + </row> + <row> + <entry><structfield>last_failed_wal_time</></entry> + <entry><type>timestamp with time zone</type></entry> + <entry>Time of the last failed archival operation</entry> + </row> + <row> + <entry><structfield>stats_reset</></entry> + <entry><type>timestamp with time zone</type></entry> + <entry>Time at which these statistics were last reset</entry> + </row> + </tbody> + </tgroup> + </table> + + <para> + The <structname>pg_stat_archiver</structname> view will always have a + single row, containing data about the archiver process of the cluster. + </para> + <table id="pg-stat-bgwriter-view" xreflabel="pg_stat_bgwriter"> <title><structname>pg_stat_bgwriter</structname> View</title> *************** *** 1613,1618 **** postgres: <replaceable>user</> <replaceable>database</> <replaceable>host</> <re --- 1678,1685 ---- argument (requires superuser privileges). Calling <literal>pg_stat_reset_shared('bgwriter')</> will zero all the counters shown in the <structname>pg_stat_bgwriter</> view. + Calling <literal>pg_stat_reset_shared('archiver')</> will zero all the + counters shown in the <structname>pg_stat_archiver</> view. </entry> </row> *** a/src/backend/catalog/system_views.sql --- b/src/backend/catalog/system_views.sql *************** *** 672,677 **** CREATE VIEW pg_stat_xact_user_functions AS --- 672,688 ---- WHERE P.prolang != 12 -- fast check to eliminate built-in functions AND pg_stat_get_xact_function_calls(P.oid) IS NOT NULL; + CREATE VIEW pg_stat_archiver AS + SELECT + s.archived_wals, + s.last_archived_wal, + s.last_archived_wal_time, + s.failed_attempts, + s.last_failed_wal, + s.last_failed_wal_time, + s.stats_reset + FROM pg_stat_get_archiver() s; + CREATE VIEW pg_stat_bgwriter AS SELECT pg_stat_get_bgwriter_timed_checkpoints() AS checkpoints_timed, *** a/src/backend/postmaster/pgarch.c --- b/src/backend/postmaster/pgarch.c *************** *** 36,41 **** --- 36,42 ---- #include "access/xlog_internal.h" #include "libpq/pqsignal.h" #include "miscadmin.h" + #include "pgstat.h" #include "postmaster/fork_process.h" #include "postmaster/pgarch.h" #include "postmaster/postmaster.h" *************** *** 496,505 **** pgarch_ArchiverCopyLoop(void) --- 497,513 ---- { /* successful */ pgarch_archiveDone(xlog); + + /* Tell the collector about the WAL file that we successfully archived */ + pgstat_send_archiver(xlog, false); + break; /* out of inner retry loop */ } else { + /* Tell the collector about the WAL file that we failed to archive */ + pgstat_send_archiver(xlog, true); + if (++failures >= NUM_ARCHIVE_RETRIES) { ereport(WARNING, *** a/src/backend/postmaster/pgstat.c --- b/src/backend/postmaster/pgstat.c *************** *** 221,226 **** static int localNumBackends = 0; --- 221,227 ---- * Contains statistics that are not collected per database * or per table. */ + static PgStat_ArchiverStats archiverStats; static PgStat_GlobalStats globalStats; /* Write request info for each database */ *************** *** 292,297 **** static void pgstat_recv_resetsinglecounter(PgStat_MsgResetsinglecounter *msg, in --- 293,299 ---- static void pgstat_recv_autovac(PgStat_MsgAutovacStart *msg, int len); static void pgstat_recv_vacuum(PgStat_MsgVacuum *msg, int len); static void pgstat_recv_analyze(PgStat_MsgAnalyze *msg, int len); + static void pgstat_recv_archiver(PgStat_MsgArchiver *msg, int len); static void pgstat_recv_bgwriter(PgStat_MsgBgWriter *msg, int len); static void pgstat_recv_funcstat(PgStat_MsgFuncstat *msg, int len); static void pgstat_recv_funcpurge(PgStat_MsgFuncpurge *msg, int len); *************** *** 1257,1269 **** pgstat_reset_shared_counters(const char *target) (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("must be superuser to reset statistics counters"))); ! if (strcmp(target, "bgwriter") == 0) msg.m_resettarget = RESET_BGWRITER; else ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("unrecognized reset target: \"%s\"", target), ! errhint("Target must be \"bgwriter\"."))); pgstat_setheader(&msg.m_hdr, PGSTAT_MTYPE_RESETSHAREDCOUNTER); pgstat_send(&msg, sizeof(msg)); --- 1259,1273 ---- (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("must be superuser to reset statistics counters"))); ! if (strcmp(target, "archiver") == 0) ! msg.m_resettarget = RESET_ARCHIVER; ! else if (strcmp(target, "bgwriter") == 0) msg.m_resettarget = RESET_BGWRITER; else ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("unrecognized reset target: \"%s\"", target), ! errhint("Target must be \"archiver\" or \"bgwriter\"."))); pgstat_setheader(&msg.m_hdr, PGSTAT_MTYPE_RESETSHAREDCOUNTER); pgstat_send(&msg, sizeof(msg)); *************** *** 2323,2328 **** pgstat_fetch_stat_numbackends(void) --- 2327,2349 ---- /* * --------- + * pgstat_fetch_stat_archiver() - + * + * Support function for the SQL-callable pgstat* functions. Returns + * a pointer to the archiver statistics struct. + * --------- + */ + PgStat_ArchiverStats * + pgstat_fetch_stat_archiver(void) + { + backend_read_statsfile(); + + return &archiverStats; + } + + + /* + * --------- * pgstat_fetch_global() - * * Support function for the SQL-callable pgstat* functions. Returns *************** *** 3036,3041 **** pgstat_send(void *msg, int len) --- 3057,3084 ---- } /* ---------- + * pgstat_send_archiver() - + * + * Tell the collector about the WAL file that we successfully + * archived or failed to archive. + * ---------- + */ + void + pgstat_send_archiver(const char *xlog, bool failed) + { + PgStat_MsgArchiver msg; + + /* + * Prepare and send the message + */ + pgstat_setheader(&msg.m_hdr, PGSTAT_MTYPE_ARCHIVER); + msg.m_failed = failed; + strncpy(msg.m_xlog, xlog, sizeof(msg.m_xlog)); + msg.m_timestamp = GetCurrentTimestamp(); + pgstat_send(&msg, sizeof(msg)); + } + + /* ---------- * pgstat_send_bgwriter() - * * Send bgwriter statistics to the collector *************** *** 3278,3283 **** PgstatCollectorMain(int argc, char *argv[]) --- 3321,3330 ---- pgstat_recv_analyze((PgStat_MsgAnalyze *) &msg, len); break; + case PGSTAT_MTYPE_ARCHIVER: + pgstat_recv_archiver((PgStat_MsgArchiver *) &msg, len); + break; + case PGSTAT_MTYPE_BGWRITER: pgstat_recv_bgwriter((PgStat_MsgBgWriter *) &msg, len); break; *************** *** 3563,3568 **** pgstat_write_statsfiles(bool permanent, bool allDbs) --- 3610,3621 ---- (void) rc; /* we'll check for error with ferror */ /* + * Write archiver stats struct + */ + rc = fwrite(&archiverStats, sizeof(archiverStats), 1, fpout); + (void) rc; /* we'll check for error with ferror */ + + /* * Walk through the database table. */ hash_seq_init(&hstat, pgStatDBHash); *************** *** 3828,3843 **** pgstat_read_statsfiles(Oid onlydb, bool permanent, bool deep) HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT); /* ! * Clear out global statistics so they start from zero in case we can't ! * load an existing statsfile. */ memset(&globalStats, 0, sizeof(globalStats)); /* * Set the current timestamp (will be kept only in case we can't load an * existing statsfile). */ globalStats.stat_reset_timestamp = GetCurrentTimestamp(); /* * Try to open the stats file. If it doesn't exist, the backends simply --- 3881,3898 ---- HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT); /* ! * Clear out global and archiver statistics so they start from zero ! * in case we can't load an existing statsfile. */ memset(&globalStats, 0, sizeof(globalStats)); + memset(&archiverStats, 0, sizeof(archiverStats)); /* * Set the current timestamp (will be kept only in case we can't load an * existing statsfile). */ globalStats.stat_reset_timestamp = GetCurrentTimestamp(); + archiverStats.stat_reset_timestamp = globalStats.stat_reset_timestamp; /* * Try to open the stats file. If it doesn't exist, the backends simply *************** *** 3875,3881 **** pgstat_read_statsfiles(Oid onlydb, bool permanent, bool deep) if (fread(&globalStats, 1, sizeof(globalStats), fpin) != sizeof(globalStats)) { ereport(pgStatRunningInCollector ? LOG : WARNING, ! (errmsg("corrupted statistics file \"%s\"", statfile))); goto done; } --- 3930,3946 ---- if (fread(&globalStats, 1, sizeof(globalStats), fpin) != sizeof(globalStats)) { ereport(pgStatRunningInCollector ? LOG : WARNING, ! (errmsg("corrupted statistics file (global) \"%s\"", statfile))); ! goto done; ! } ! ! /* ! * Read archiver stats struct ! */ ! if (fread(&archiverStats, 1, sizeof(archiverStats), fpin) != sizeof(archiverStats)) ! { ! ereport(pgStatRunningInCollector ? LOG : WARNING, ! (errmsg("corrupted statistics file (archiver) \"%s\"", statfile))); goto done; } *************** *** 4159,4165 **** done: * stats_timestamp value. * * - if there's no db stat entry (e.g. for a new or inactive database), ! * there's no stat_timestamp value, but also nothing to write so we return * the timestamp of the global statfile. * ---------- */ --- 4224,4230 ---- * stats_timestamp value. * * - if there's no db stat entry (e.g. for a new or inactive database), ! * there's no stats_timestamp value, but also nothing to write so we return * the timestamp of the global statfile. * ---------- */ *************** *** 4169,4174 **** pgstat_read_db_statsfile_timestamp(Oid databaseid, bool permanent, --- 4234,4240 ---- { PgStat_StatDBEntry dbentry; PgStat_GlobalStats myGlobalStats; + PgStat_ArchiverStats myArchiverStats; FILE *fpin; int32 format_id; const char *statfile = permanent ? PGSTAT_STAT_PERMANENT_FILENAME : pgstat_stat_filename; *************** *** 4211,4216 **** pgstat_read_db_statsfile_timestamp(Oid databaseid, bool permanent, --- 4277,4294 ---- return false; } + /* + * Read archiver stats struct + */ + if (fread(&myArchiverStats, 1, sizeof(myArchiverStats), + fpin) != sizeof(myArchiverStats)) + { + ereport(pgStatRunningInCollector ? LOG : WARNING, + (errmsg("corrupted statistics file \"%s\"", statfile))); + FreeFile(fpin); + return false; + } + /* By default, we're going to return the timestamp of the global file. */ *ts = myGlobalStats.stats_timestamp; *************** *** 4738,4743 **** pgstat_recv_resetsharedcounter(PgStat_MsgResetsharedcounter *msg, int len) --- 4816,4827 ---- memset(&globalStats, 0, sizeof(globalStats)); globalStats.stat_reset_timestamp = GetCurrentTimestamp(); } + else if (msg->m_resettarget == RESET_ARCHIVER) + { + /* Reset the archiver statistics for the cluster. */ + memset(&archiverStats, 0, sizeof(archiverStats)); + archiverStats.stat_reset_timestamp = GetCurrentTimestamp(); + } /* * Presumably the sender of this message validated the target, don't *************** *** 4868,4873 **** pgstat_recv_analyze(PgStat_MsgAnalyze *msg, int len) --- 4952,4984 ---- /* ---------- + * pgstat_recv_archiver() - + * + * Process a ARCHIVER message. + * ---------- + */ + static void + pgstat_recv_archiver(PgStat_MsgArchiver *msg, int len) + { + if (msg->m_failed) + { + /* Failed archival attempt */ + ++archiverStats.failed_attempts; + memcpy(archiverStats.last_failed_wal, msg->m_xlog, + sizeof(archiverStats.last_failed_wal)); + archiverStats.last_failed_wal_timestamp = msg->m_timestamp; + } + else + { + /* Successful archival operation */ + ++archiverStats.archived_wals; + memcpy(archiverStats.last_archived_wal, msg->m_xlog, + sizeof(archiverStats.last_archived_wal)); + archiverStats.last_archived_wal_timestamp = msg->m_timestamp; + } + } + + /* ---------- * pgstat_recv_bgwriter() - * * Process a BGWRITER message. *** a/src/backend/utils/adt/pgstatfuncs.c --- b/src/backend/utils/adt/pgstatfuncs.c *************** *** 87,92 **** extern Datum pg_stat_get_db_temp_bytes(PG_FUNCTION_ARGS); --- 87,94 ---- extern Datum pg_stat_get_db_blk_read_time(PG_FUNCTION_ARGS); extern Datum pg_stat_get_db_blk_write_time(PG_FUNCTION_ARGS); + extern Datum pg_stat_get_archiver(PG_FUNCTION_ARGS); + extern Datum pg_stat_get_bgwriter_timed_checkpoints(PG_FUNCTION_ARGS); extern Datum pg_stat_get_bgwriter_requested_checkpoints(PG_FUNCTION_ARGS); extern Datum pg_stat_get_checkpoint_write_time(PG_FUNCTION_ARGS); *************** *** 1712,1714 **** pg_stat_reset_single_function_counters(PG_FUNCTION_ARGS) --- 1714,1783 ---- PG_RETURN_VOID(); } + + Datum + pg_stat_get_archiver(PG_FUNCTION_ARGS) + { + TupleDesc tupdesc; + Datum values[7]; + bool nulls[7]; + PgStat_ArchiverStats *archiver_stats; + + /* Initialise values and NULL flags arrays */ + MemSet(values, 0, sizeof(values)); + MemSet(nulls, 0, sizeof(nulls)); + + /* Initialise attributes information in the tuple descriptor */ + tupdesc = CreateTemplateTupleDesc(7, false); + TupleDescInitEntry(tupdesc, (AttrNumber) 1, "archived_wals", + INT8OID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 2, "last_archived_wal", + TEXTOID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 3, "last_archived_wal_time", + TIMESTAMPTZOID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 4, "failed_attempts", + INT8OID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 5, "last_failed_wal", + TEXTOID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 6, "last_failed_wal_time", + TIMESTAMPTZOID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 7, "stats_reset", + TIMESTAMPTZOID, -1, 0); + + BlessTupleDesc(tupdesc); + + /* Get statistics about the archiver process */ + archiver_stats = pgstat_fetch_stat_archiver(); + + /* Fill values and NULLs */ + values[0] = Int64GetDatum(archiver_stats->archived_wals); + if (archiver_stats->last_archived_wal == 0) + nulls[1] = true; + else + values[1] = CStringGetTextDatum(archiver_stats->last_archived_wal); + + if (archiver_stats->last_archived_wal_timestamp == 0) + nulls[2] = true; + else + values[2] = TimestampTzGetDatum(archiver_stats->last_archived_wal_timestamp); + + values[3] = Int64GetDatum(archiver_stats->failed_attempts); + if (archiver_stats->last_failed_wal == 0) + nulls[4] = true; + else + values[4] = CStringGetTextDatum(archiver_stats->last_failed_wal); + + if (archiver_stats->last_failed_wal_timestamp == 0) + nulls[5] = true; + else + values[5] = TimestampTzGetDatum(archiver_stats->last_failed_wal_timestamp); + + if (archiver_stats->stat_reset_timestamp == 0) + nulls[6] = true; + else + values[6] = TimestampTzGetDatum(archiver_stats->stat_reset_timestamp); + + /* Returns the record as Datum */ + PG_RETURN_DATUM(HeapTupleGetDatum( + heap_form_tuple(tupdesc, values, nulls))); + } *** a/src/include/catalog/pg_proc.h --- b/src/include/catalog/pg_proc.h *************** *** 2702,2707 **** DATA(insert OID = 2844 ( pg_stat_get_db_blk_read_time PGNSP PGUID 12 1 0 0 0 f --- 2702,2709 ---- DESCR("statistics: block read time, in msec"); DATA(insert OID = 2845 ( pg_stat_get_db_blk_write_time PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 701 "26" _null_ _null_ _null_ _null_ pg_stat_get_db_blk_write_time _null_ _null_ _null_ )); DESCR("statistics: block write time, in msec"); + DATA(insert OID = 3195 ( pg_stat_get_archiver PGNSP PGUID 12 1 0 0 0 f f f f f f s 0 0 2249 "" "{20,25,1184,20,25,1184,1184}" "{o,o,o,o,o,o,o}" "{archived_wals,last_archived_wal,last_archived_wal_time,failed_attempts,last_failed_wal,last_failed_wal_time,stats_reset}" _null_ pg_stat_get_archiver _null_ _null_ _null_ )); + DESCR("statistics: information about WAL archiver"); DATA(insert OID = 2769 ( pg_stat_get_bgwriter_timed_checkpoints PGNSP PGUID 12 1 0 0 0 f f f f t f s 0 0 20 "" _null_ _null_ _null_ _null_ pg_stat_get_bgwriter_timed_checkpoints _null_ _null_ _null_ )); DESCR("statistics: number of timed checkpoints started by the bgwriter"); DATA(insert OID = 2770 ( pg_stat_get_bgwriter_requested_checkpoints PGNSP PGUID 12 1 0 0 0 f f f f t f s 0 0 20 "" _null_ _null_ _null_ _null_ pg_stat_get_bgwriter_requested_checkpoints _null_ _null_ _null_ )); *** a/src/include/pgstat.h --- b/src/include/pgstat.h *************** *** 17,22 **** --- 17,23 ---- #include "portability/instr_time.h" #include "utils/hsearch.h" #include "utils/relcache.h" + #include "access/xlog_internal.h" /* Values for track_functions GUC variable --- order is significant! */ *************** *** 44,49 **** typedef enum StatMsgType --- 45,51 ---- PGSTAT_MTYPE_AUTOVAC_START, PGSTAT_MTYPE_VACUUM, PGSTAT_MTYPE_ANALYZE, + PGSTAT_MTYPE_ARCHIVER, PGSTAT_MTYPE_BGWRITER, PGSTAT_MTYPE_FUNCSTAT, PGSTAT_MTYPE_FUNCPURGE, *************** *** 102,107 **** typedef struct PgStat_TableCounts --- 104,110 ---- /* Possible targets for resetting cluster-wide shared values */ typedef enum PgStat_Shared_Reset_Target { + RESET_ARCHIVER, RESET_BGWRITER } PgStat_Shared_Reset_Target; *************** *** 356,361 **** typedef struct PgStat_MsgAnalyze --- 359,376 ---- /* ---------- + * PgStat_MsgArchiver Sent by the archiver to update statistics. + * ---------- + */ + typedef struct PgStat_MsgArchiver + { + PgStat_MsgHdr m_hdr; + bool m_failed; /* Failed attempt */ + char m_xlog[MAXFNAMELEN]; + TimestampTz m_timestamp; + } PgStat_MsgArchiver; + + /* ---------- * PgStat_MsgBgWriter Sent by the bgwriter to update statistics. * ---------- */ *************** *** 502,507 **** typedef union PgStat_Msg --- 517,523 ---- PgStat_MsgAutovacStart msg_autovacuum; PgStat_MsgVacuum msg_vacuum; PgStat_MsgAnalyze msg_analyze; + PgStat_MsgArchiver msg_archiver; PgStat_MsgBgWriter msg_bgwriter; PgStat_MsgFuncstat msg_funcstat; PgStat_MsgFuncpurge msg_funcpurge; *************** *** 518,524 **** typedef union PgStat_Msg * ------------------------------------------------------------ */ ! #define PGSTAT_FILE_FORMAT_ID 0x01A5BC9B /* ---------- * PgStat_StatDBEntry The collector's data per database --- 534,540 ---- * ------------------------------------------------------------ */ ! #define PGSTAT_FILE_FORMAT_ID 0x01A5BC9C /* ---------- * PgStat_StatDBEntry The collector's data per database *************** *** 612,617 **** typedef struct PgStat_StatFuncEntry --- 628,647 ---- /* + * Archiver statistics kept in the stats collector + */ + typedef struct PgStat_ArchiverStats + { + PgStat_Counter archived_wals; + char last_archived_wal[MAXFNAMELEN]; /* last WAL file archived */ + TimestampTz last_archived_wal_timestamp; /* last archival success */ + PgStat_Counter failed_attempts; + char last_failed_wal[MAXFNAMELEN]; /* last WAL file involved in failure */ + TimestampTz last_failed_wal_timestamp; /* last archival failure */ + TimestampTz stat_reset_timestamp; + } PgStat_ArchiverStats; + + /* * Global statistics kept in the stats collector */ typedef struct PgStat_GlobalStats *************** *** 863,868 **** extern void pgstat_twophase_postcommit(TransactionId xid, uint16 info, --- 893,899 ---- extern void pgstat_twophase_postabort(TransactionId xid, uint16 info, void *recdata, uint32 len); + extern void pgstat_send_archiver(const char *xlog, bool failed); extern void pgstat_send_bgwriter(void); /* ---------- *************** *** 875,880 **** extern PgStat_StatTabEntry *pgstat_fetch_stat_tabentry(Oid relid); --- 906,912 ---- extern PgBackendStatus *pgstat_fetch_stat_beentry(int beid); extern PgStat_StatFuncEntry *pgstat_fetch_stat_funcentry(Oid funcid); extern int pgstat_fetch_stat_numbackends(void); + extern PgStat_ArchiverStats *pgstat_fetch_stat_archiver(void); extern PgStat_GlobalStats *pgstat_fetch_global(void); #endif /* PGSTAT_H */ *** a/src/test/regress/expected/rules.out --- b/src/test/regress/expected/rules.out *************** *** 1640,1645 **** pg_stat_all_tables| SELECT c.oid AS relid, --- 1640,1653 ---- LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) WHERE (c.relkind = ANY (ARRAY['r'::"char", 't'::"char", 'm'::"char"])) GROUP BY c.oid, n.nspname, c.relname; + pg_stat_archiver| SELECT s.archived_wals, + s.last_archived_wal, + s.last_archived_wal_time, + s.failed_attempts, + s.last_failed_wal, + s.last_failed_wal_time, + s.stats_reset + FROM pg_stat_get_archiver() s(archived_wals, last_archived_wal, last_archived_wal_time, failed_attempts, last_failed_wal, last_failed_wal_time, stats_reset); pg_stat_bgwriter| SELECT pg_stat_get_bgwriter_timed_checkpoints() AS checkpoints_timed, pg_stat_get_bgwriter_requested_checkpoints() AS checkpoints_req, pg_stat_get_checkpoint_write_time() AS checkpoint_write_time,
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers