Hello,

  please find attached the patch that adds basic support for the
pg_stat_archiver system view, which allows users that have continuous
archiving procedures in place to keep track of some important metrics
and information.

  Currently, pg_stat_archiver displays:

* archived_wals: number of successfully archived WAL files since start
(or the last reset)
* last_archived_wal: last successfully archived WAL file
* last_archived_wal_time: timestamp of the latest successful WAL archival
* stats_reset: time of last stats reset

  This is an example of output:

postgres=# select * from pg_stat_archiver ;
-[ RECORD 1 ]----------+------------------------------
archived_wals          | 1
last_archived_wal      | 000000010000000000000001
last_archived_wal_time | 2014-01-04 01:01:08.858648+01
stats_reset            | 2014-01-04 00:59:25.895034+01

  Similarly to pg_stat_bgwriter, it is possible to reset statistics just
for this context, calling the pg_stat_reset_shared('archiver') function.

  The patch is here for discussion and has been prepared against HEAD.
It includes also changes in the documentation and the rules.out test.

  I plan to add further information to the pg_stat_archiver view,
including the number of failed attempts of archival and the WAL and
timestamp of the latest failure. However, before proceeding, I'd like to
get some feedback on this small patch as well as advice on possible
regression tests to be added.

  Thank you.

Cheers,
Gabriele

-- 
 Gabriele Bartolini - 2ndQuadrant Italia
 PostgreSQL Training, Services and Support
 gabriele.bartol...@2ndquadrant.it | www.2ndQuadrant.it

diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml
index 4ec6981..6d45972 100644
--- a/doc/src/sgml/monitoring.sgml
+++ b/doc/src/sgml/monitoring.sgml
@@ -270,6 +270,14 @@ postgres: <replaceable>user</> <replaceable>database</> 
<replaceable>host</> <re
      </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,6 +656,49 @@ postgres: <replaceable>user</> <replaceable>database</> 
<replaceable>host</> <re
    </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 successfully archived WAL file</entry>
+     </row>
+     <row>
+      <entry><structfield>last_archived_wal_time</></entry>
+      <entry><type>timestamp with time zone</type></entry>
+      <entry>Time of the last successful 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,6 +1664,8 @@ postgres: <replaceable>user</> <replaceable>database</> 
<replaceable>host</> <re
        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>
 
diff --git a/src/backend/catalog/system_views.sql 
b/src/backend/catalog/system_views.sql
index 575a40f..3a8d7b4 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -672,6 +672,13 @@ CREATE VIEW pg_stat_xact_user_functions AS
     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
+        pg_stat_get_archiver_archived_wals() AS archived_wals,
+        pg_stat_get_archiver_last_archived_wal() AS last_archived_wal,
+        pg_stat_get_archiver_last_archived_wal_time() AS 
last_archived_wal_time,
+        pg_stat_get_archiver_stat_reset_time() AS stats_reset;
+
 CREATE VIEW pg_stat_bgwriter AS
     SELECT
         pg_stat_get_bgwriter_timed_checkpoints() AS checkpoints_timed,
diff --git a/src/backend/postmaster/pgarch.c b/src/backend/postmaster/pgarch.c
index 2bb572e..3cb1ddc 100644
--- a/src/backend/postmaster/pgarch.c
+++ b/src/backend/postmaster/pgarch.c
@@ -36,6 +36,7 @@
 #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"
@@ -46,6 +47,7 @@
 #include "storage/pmsignal.h"
 #include "utils/guc.h"
 #include "utils/ps_status.h"
+#include "utils/timestamp.h"
 
 
 /* ----------
@@ -755,4 +757,12 @@ pgarch_archiveDone(char *xlog)
                                (errcode_for_file_access(),
                                 errmsg("could not rename file \"%s\" to 
\"%s\": %m",
                                                rlogready, rlogdone)));
+       /*
+        * Send off activity statistics to the stats collector.
+        */
+       ArchiverStats.m_archived_wals++;
+       strncpy(ArchiverStats.m_last_archived_wal,
+               xlog, sizeof(ArchiverStats.m_last_archived_wal));
+       ArchiverStats.m_last_archived_wal_timestamp = GetCurrentTimestamp();
+       pgstat_send_archiver();
 }
diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c
index 4bfa62e..ffe5d0e 100644
--- a/src/backend/postmaster/pgstat.c
+++ b/src/backend/postmaster/pgstat.c
@@ -123,6 +123,13 @@ char          *pgstat_stat_filename = NULL;
 char      *pgstat_stat_tmpname = NULL;
 
 /*
+ * Archiver global statistics counters (unused in other processes).
+ * Stored directly in a stats message structure so it can be sent
+ * without needing to copy things around.  We assume this inits to zeroes.
+ */
+PgStat_MsgArchiver ArchiverStats;
+
+/*
  * BgWriter global statistics counters (unused in other processes).
  * Stored directly in a stats message structure so it can be sent
  * without needing to copy things around.  We assume this inits to zeroes.
@@ -217,6 +224,12 @@ static PgBackendStatus *localBackendStatusTable = NULL;
 static int     localNumBackends = 0;
 
 /*
+ * Archiver statistics, kept in the stats collector.
+ * Contains statistics regarding the archiving process.
+ */
+static PgStat_ArchiverStats archiverStats;
+
+/*
  * Cluster wide statistics, kept in the stats collector.
  * Contains statistics that are not collected per database
  * or per table.
@@ -292,6 +305,7 @@ static void 
pgstat_recv_resetsinglecounter(PgStat_MsgResetsinglecounter *msg, in
 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,7 +1271,9 @@ pgstat_reset_shared_counters(const char *target)
                                (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                                 errmsg("must be superuser to reset statistics 
counters")));
 
-       if (strcmp(target, "bgwriter") == 0)
+       if (strcmp(target, "archiver") == 0)
+               msg.m_resettarget = RESET_ARCHIVER;
+       else if (strcmp(target, "bgwriter") == 0)
                msg.m_resettarget = RESET_BGWRITER;
        else
                ereport(ERROR,
@@ -2321,6 +2337,23 @@ pgstat_fetch_stat_numbackends(void)
 
 /*
  * ---------
+ * pgstat_fetch_archiver() -
+ *
+ *     Support function for the SQL-callable pgstat* functions. Returns
+ *     a pointer to the archiver statistics struct.
+ * ---------
+ */
+PgStat_ArchiverStats *
+pgstat_fetch_archiver(void)
+{
+       backend_read_statsfile();
+
+       return &archiverStats;
+}
+
+
+/*
+ * ---------
  * pgstat_fetch_global() -
  *
  *     Support function for the SQL-callable pgstat* functions. Returns
@@ -3034,6 +3067,39 @@ pgstat_send(void *msg, int len)
 }
 
 /* ----------
+ * pgstat_send_archiver() -
+ *
+ *             Send archiver statistics to the collector
+ * ----------
+ */
+void
+pgstat_send_archiver(void)
+{
+       /* We assume this initializes to zeroes */
+       static const PgStat_MsgArchiver all_zeroes;
+
+       /*
+        * This function can be called even if nothing at all has happened. In
+        * this case, avoid sending a completely empty message to the stats
+        * collector.
+        */
+       if (memcmp(&ArchiverStats, &all_zeroes, sizeof(PgStat_MsgArchiver)) == 
0)
+               return;
+
+       /*
+        * Prepare and send the message
+        */
+       pgstat_setheader(&ArchiverStats.m_hdr, PGSTAT_MTYPE_ARCHIVER);
+       pgstat_send(&ArchiverStats, sizeof(ArchiverStats));
+
+       /*
+        * Clear out the statistics buffer, so it can be re-used.
+        */
+       MemSet(&ArchiverStats, 0, sizeof(ArchiverStats));
+}
+
+
+/* ----------
  * pgstat_send_bgwriter() -
  *
  *             Send bgwriter statistics to the collector
@@ -3276,6 +3342,10 @@ PgstatCollectorMain(int argc, char *argv[])
                                        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;
@@ -3546,6 +3616,7 @@ pgstat_write_statsfiles(bool permanent, bool allDbs)
         * Set the timestamp of the stats file.
         */
        globalStats.stats_timestamp = GetCurrentTimestamp();
+       archiverStats.stats_timestamp = globalStats.stats_timestamp;
 
        /*
         * Write the file header --- currently just a format ID.
@@ -3561,6 +3632,12 @@ pgstat_write_statsfiles(bool permanent, bool allDbs)
        (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);
@@ -3826,16 +3903,18 @@ 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.
+        * 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
@@ -3873,7 +3952,17 @@ 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)));
+                               (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;
        }
 
@@ -4167,6 +4256,7 @@ pgstat_read_db_statsfile_timestamp(Oid databaseid, bool 
permanent,
 {
        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;
@@ -4209,6 +4299,18 @@ pgstat_read_db_statsfile_timestamp(Oid databaseid, bool 
permanent,
                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;
 
@@ -4736,6 +4838,12 @@ 
pgstat_recv_resetsharedcounter(PgStat_MsgResetsharedcounter *msg, int len)
                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
@@ -4867,6 +4975,21 @@ pgstat_recv_analyze(PgStat_MsgAnalyze *msg, int len)
 
 
 /* ----------
+ * pgstat_recv_archiver() -
+ *
+ *     Process a ARCHIVER message.
+ * ----------
+ */
+static void
+pgstat_recv_archiver(PgStat_MsgArchiver *msg, int len)
+{
+       archiverStats.archived_wals += msg->m_archived_wals;
+       memcpy(archiverStats.last_archived_wal, msg->m_last_archived_wal,
+               sizeof(archiverStats.last_archived_wal));
+       archiverStats.last_archived_wal_timestamp = 
msg->m_last_archived_wal_timestamp;
+}
+
+/* ----------
  * pgstat_recv_bgwriter() -
  *
  *     Process a BGWRITER message.
diff --git a/src/backend/utils/adt/pgstatfuncs.c 
b/src/backend/utils/adt/pgstatfuncs.c
index 2957fc7..90c7453 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -87,6 +87,11 @@ extern Datum pg_stat_get_db_temp_bytes(PG_FUNCTION_ARGS);
 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_archived_wals(PG_FUNCTION_ARGS);
+extern Datum pg_stat_get_archiver_last_archived_wal(PG_FUNCTION_ARGS);
+extern Datum pg_stat_get_archiver_last_archived_wal_time(PG_FUNCTION_ARGS);
+extern Datum pg_stat_get_archiver_stat_reset_time(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);
@@ -1408,6 +1413,46 @@ pg_stat_get_db_blk_write_time(PG_FUNCTION_ARGS)
 }
 
 Datum
+pg_stat_get_archiver_archived_wals(PG_FUNCTION_ARGS)
+{
+       PG_RETURN_INT64(pgstat_fetch_archiver()->archived_wals);
+}
+
+Datum
+pg_stat_get_archiver_last_archived_wal(PG_FUNCTION_ARGS)
+{
+       char *result = pgstat_fetch_archiver()->last_archived_wal;
+
+       if (result == 0)
+               PG_RETURN_NULL();
+
+       PG_RETURN_TEXT_P(cstring_to_text(result));
+}
+
+Datum
+pg_stat_get_archiver_last_archived_wal_time(PG_FUNCTION_ARGS)
+{
+       TimestampTz result = 
pgstat_fetch_archiver()->last_archived_wal_timestamp;
+
+       if (result == 0)
+               PG_RETURN_NULL();
+
+       PG_RETURN_TIMESTAMPTZ(result);
+}
+
+Datum
+pg_stat_get_archiver_stat_reset_time(PG_FUNCTION_ARGS)
+{
+       TimestampTz result = pgstat_fetch_archiver()->stat_reset_timestamp;
+
+       if (result == 0)
+               PG_RETURN_NULL();
+
+       PG_RETURN_TIMESTAMPTZ(result);
+}
+
+
+Datum
 pg_stat_get_bgwriter_timed_checkpoints(PG_FUNCTION_ARGS)
 {
        PG_RETURN_INT64(pgstat_fetch_global()->timed_checkpoints);
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index 05d7ba5..0c1aea3 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -2700,6 +2700,14 @@ DATA(insert OID = 2844 (  pg_stat_get_db_blk_read_time   
PGNSP PGUID 12 1 0 0 0 f
 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_archived_wals PGNSP PGUID 12 1 0 
0 0 f f f f t f s 0 0 20 "" _null_ _null_ _null_ _null_ 
pg_stat_get_archiver_archived_wals _null_ _null_ _null_ ));
+DESCR("statistics: number of WAL files successfully archived by the archiver");
+DATA(insert OID = 3196 ( pg_stat_get_archiver_last_archived_wal_time PGNSP 
PGUID 12 1 0 0 0 f f f f t f s 0 0 1184 "" _null_ _null_ _null_ _null_ 
pg_stat_get_archiver_last_archived_wal_time _null_ _null_ _null_ ));
+DESCR("statistics: timestamp of the last successfully archived WAL file");
+DATA(insert OID = 3197 ( pg_stat_get_archiver_last_archived_wal PGNSP PGUID 12 
1 0 0 0 f f f f t f s 0 0 25 "" _null_ _null_ _null_ _null_ 
pg_stat_get_archiver_last_archived_wal _null_ _null_ _null_ ));
+DESCR("statistics: last succesfully archived WAL file");
+DATA(insert OID = 3198 ( pg_stat_get_archiver_stat_reset_time PGNSP PGUID 12 1 
0 0 0 f f f f t f s 0 0 1184 "" _null_ _null_ _null_ _null_     
pg_stat_get_archiver_stat_reset_time _null_ _null_ _null_ ));
+DESCR("statistics: last reset for the 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_ ));
diff --git a/src/include/pgstat.h b/src/include/pgstat.h
index b79a0eb..84a9498 100644
--- a/src/include/pgstat.h
+++ b/src/include/pgstat.h
@@ -18,6 +18,7 @@
 #include "utils/hsearch.h"
 #include "utils/relcache.h"
 
+#define MAX_XFN_CHARS  40
 
 /* Values for track_functions GUC variable --- order is significant! */
 typedef enum TrackFunctionsLevel
@@ -44,6 +45,7 @@ typedef enum StatMsgType
        PGSTAT_MTYPE_AUTOVAC_START,
        PGSTAT_MTYPE_VACUUM,
        PGSTAT_MTYPE_ANALYZE,
+       PGSTAT_MTYPE_ARCHIVER,
        PGSTAT_MTYPE_BGWRITER,
        PGSTAT_MTYPE_FUNCSTAT,
        PGSTAT_MTYPE_FUNCPURGE,
@@ -102,6 +104,7 @@ typedef struct PgStat_TableCounts
 /* Possible targets for resetting cluster-wide shared values */
 typedef enum PgStat_Shared_Reset_Target
 {
+       RESET_ARCHIVER,
        RESET_BGWRITER
 } PgStat_Shared_Reset_Target;
 
@@ -355,6 +358,19 @@ typedef struct PgStat_MsgAnalyze
 
 
 /* ----------
+ * PgStat_MsgArchiver                  Sent by the archiver to update 
statistics.
+ * ----------
+ */
+typedef struct PgStat_MsgArchiver
+{
+       PgStat_MsgHdr m_hdr;
+
+       PgStat_Counter m_archived_wals;
+       char m_last_archived_wal[MAX_XFN_CHARS +1];
+       TimestampTz m_last_archived_wal_timestamp;
+} PgStat_MsgArchiver;
+
+/* ----------
  * PgStat_MsgBgWriter                  Sent by the bgwriter to update 
statistics.
  * ----------
  */
@@ -501,6 +517,7 @@ typedef union PgStat_Msg
        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;
@@ -611,6 +628,18 @@ typedef struct PgStat_StatFuncEntry
 
 
 /*
+ * Archiver statistics kept in the stats collector
+ */
+typedef struct PgStat_ArchiverStats
+{
+       TimestampTz stats_timestamp;    /* time of stats file update */
+       PgStat_Counter archived_wals;
+       char last_archived_wal[MAX_XFN_CHARS +1]; /* file name of the last 
archived WAL */
+       TimestampTz last_archived_wal_timestamp;        /* time of last 
successful archival */
+       TimestampTz stat_reset_timestamp;
+} PgStat_ArchiverStats;
+
+/*
  * Global statistics kept in the stats collector
  */
 typedef struct PgStat_GlobalStats
@@ -731,6 +760,11 @@ extern char *pgstat_stat_tmpname;
 extern char *pgstat_stat_filename;
 
 /*
+ * Archiver statistics counters are updated directly by pgarch
+ */
+extern PgStat_MsgArchiver ArchiverStats;
+
+/*
  * BgWriter statistics counters are updated directly by bgwriter and bufmgr
  */
 extern PgStat_MsgBgWriter BgWriterStats;
@@ -862,6 +896,7 @@ extern void pgstat_twophase_postcommit(TransactionId xid, 
uint16 info,
 extern void pgstat_twophase_postabort(TransactionId xid, uint16 info,
                                                  void *recdata, uint32 len);
 
+extern void pgstat_send_archiver(void);
 extern void pgstat_send_bgwriter(void);
 
 /* ----------
@@ -874,6 +909,7 @@ extern PgStat_StatTabEntry *pgstat_fetch_stat_tabentry(Oid 
relid);
 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_archiver(void);
 extern PgStat_GlobalStats *pgstat_fetch_global(void);
 
 #endif   /* PGSTAT_H */
diff --git a/src/test/regress/expected/rules.out 
b/src/test/regress/expected/rules.out
index 9f089e3..5916889 100644
--- a/src/test/regress/expected/rules.out
+++ b/src/test/regress/expected/rules.out
@@ -1640,6 +1640,10 @@ pg_stat_all_tables| SELECT c.oid AS relid,
    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 pg_stat_get_archiver_archived_wals() AS archived_wals,
+    pg_stat_get_archiver_last_archived_wal() AS last_archived_wal,
+    pg_stat_get_archiver_last_archived_wal_time() AS last_archived_wal_time,
+    pg_stat_get_archiver_stat_reset_time() AS 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

Reply via email to