mirror of https://github.com/postgres/postgres
injection_points: Add some fixed-numbered statistics
Like75534436a4
, this acts mainly as a template to show what can be achieved with fixed-numbered stats (like WAL, bgwriter, etc.) with the pluggable cumulative statistics APIs introduced in7949d95945
. Fixed-numbered stats are defined in their own file, named injection_stats_fixed.c, separated entirely from the variable-numbered case in injection_stats.c. This is mainly for clarity as having both examples in the same file would be confusing. Note that this commit uses the helper routines added in2eff9e678d
. The stats stored track globally the number of times injection points have been attached, detached or run. Two more fields should be added later for the number of times a point has been cached or loaded, but what's here is enough as a template. More TAP tests are added, providing coverage for fixed-numbered custom stats. Author: Michael Paquier Reviewed-by: Dmitry Dolgov, Bertrand Drouvot Discussion: https://postgr.es/m/Zmqm9j5EO0I4W8dx@paquier.xyz
This commit is contained in:
parent
75534436a4
commit
f68cd847fa
|
@ -4,7 +4,8 @@ MODULE_big = injection_points
|
|||
OBJS = \
|
||||
$(WIN32RES) \
|
||||
injection_points.o \
|
||||
injection_stats.o
|
||||
injection_stats.o \
|
||||
injection_stats_fixed.o
|
||||
EXTENSION = injection_points
|
||||
DATA = injection_points--1.0.sql
|
||||
PGFILEDESC = "injection_points - facility for injection points"
|
||||
|
|
|
@ -84,3 +84,14 @@ CREATE FUNCTION injection_points_stats_numcalls(IN point_name TEXT)
|
|||
RETURNS bigint
|
||||
AS 'MODULE_PATHNAME', 'injection_points_stats_numcalls'
|
||||
LANGUAGE C STRICT;
|
||||
|
||||
--
|
||||
-- injection_points_stats_fixed()
|
||||
--
|
||||
-- Reports fixed-numbered statistics for injection points.
|
||||
CREATE FUNCTION injection_points_stats_fixed(OUT numattach int8,
|
||||
OUT numdetach int8,
|
||||
OUT numrun int8)
|
||||
RETURNS record
|
||||
AS 'MODULE_PATHNAME', 'injection_points_stats_fixed'
|
||||
LANGUAGE C STRICT;
|
||||
|
|
|
@ -297,6 +297,7 @@ injection_points_attach(PG_FUNCTION_ARGS)
|
|||
condition.pid = MyProcPid;
|
||||
}
|
||||
|
||||
pgstat_report_inj_fixed(1, 0, 0);
|
||||
InjectionPointAttach(name, "injection_points", function, &condition,
|
||||
sizeof(InjectionPointCondition));
|
||||
|
||||
|
@ -342,6 +343,7 @@ injection_points_run(PG_FUNCTION_ARGS)
|
|||
{
|
||||
char *name = text_to_cstring(PG_GETARG_TEXT_PP(0));
|
||||
|
||||
pgstat_report_inj_fixed(0, 0, 1);
|
||||
INJECTION_POINT(name);
|
||||
|
||||
PG_RETURN_VOID();
|
||||
|
@ -432,6 +434,7 @@ injection_points_detach(PG_FUNCTION_ARGS)
|
|||
{
|
||||
char *name = text_to_cstring(PG_GETARG_TEXT_PP(0));
|
||||
|
||||
pgstat_report_inj_fixed(0, 1, 0);
|
||||
if (!InjectionPointDetach(name))
|
||||
elog(ERROR, "could not detach injection point \"%s\"", name);
|
||||
|
||||
|
@ -459,4 +462,5 @@ _PG_init(void)
|
|||
return;
|
||||
|
||||
pgstat_register_inj();
|
||||
pgstat_register_inj_fixed();
|
||||
}
|
||||
|
|
|
@ -15,9 +15,16 @@
|
|||
#ifndef INJECTION_STATS
|
||||
#define INJECTION_STATS
|
||||
|
||||
/* injection_stats.c */
|
||||
extern void pgstat_register_inj(void);
|
||||
extern void pgstat_create_inj(const char *name);
|
||||
extern void pgstat_drop_inj(const char *name);
|
||||
extern void pgstat_report_inj(const char *name);
|
||||
|
||||
/* injection_stats_fixed.c */
|
||||
extern void pgstat_register_inj_fixed(void);
|
||||
extern void pgstat_report_inj_fixed(uint32 numattach,
|
||||
uint32 numdetach,
|
||||
uint32 numrun);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,192 @@
|
|||
/*--------------------------------------------------------------------------
|
||||
*
|
||||
* injection_stats_fixed.c
|
||||
* Code for fixed-numbered statistics of injection points.
|
||||
*
|
||||
* Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* src/test/modules/injection_points/injection_stats_fixed.c
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "postgres.h"
|
||||
|
||||
#include "fmgr.h"
|
||||
|
||||
#include "common/hashfn.h"
|
||||
#include "funcapi.h"
|
||||
#include "injection_stats.h"
|
||||
#include "pgstat.h"
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/pgstat_internal.h"
|
||||
|
||||
/* Structures for statistics of injection points, fixed-size */
|
||||
typedef struct PgStat_StatInjFixedEntry
|
||||
{
|
||||
PgStat_Counter numattach; /* number of points attached */
|
||||
PgStat_Counter numdetach; /* number of points detached */
|
||||
PgStat_Counter numrun; /* number of points run */
|
||||
TimestampTz stat_reset_timestamp;
|
||||
} PgStat_StatInjFixedEntry;
|
||||
|
||||
typedef struct PgStatShared_InjectionPointFixed
|
||||
{
|
||||
LWLock lock; /* protects all the counters */
|
||||
uint32 changecount;
|
||||
PgStat_StatInjFixedEntry stats;
|
||||
PgStat_StatInjFixedEntry reset_offset;
|
||||
} PgStatShared_InjectionPointFixed;
|
||||
|
||||
/* Callbacks for fixed-numbered stats */
|
||||
static void injection_stats_fixed_init_shmem_cb(void *stats);
|
||||
static void injection_stats_fixed_reset_all_cb(TimestampTz ts);
|
||||
static void injection_stats_fixed_snapshot_cb(void);
|
||||
|
||||
static const PgStat_KindInfo injection_stats_fixed = {
|
||||
.name = "injection_points_fixed",
|
||||
.fixed_amount = true,
|
||||
|
||||
.shared_size = sizeof(PgStat_StatInjFixedEntry),
|
||||
.shared_data_off = offsetof(PgStatShared_InjectionPointFixed, stats),
|
||||
.shared_data_len = sizeof(((PgStatShared_InjectionPointFixed *) 0)->stats),
|
||||
|
||||
.init_shmem_cb = injection_stats_fixed_init_shmem_cb,
|
||||
.reset_all_cb = injection_stats_fixed_reset_all_cb,
|
||||
.snapshot_cb = injection_stats_fixed_snapshot_cb,
|
||||
};
|
||||
|
||||
/*
|
||||
* Kind ID reserved for statistics of injection points.
|
||||
*/
|
||||
#define PGSTAT_KIND_INJECTION_FIXED 130
|
||||
|
||||
/* Track if fixed-numbered stats are loaded */
|
||||
static bool inj_fixed_loaded = false;
|
||||
|
||||
static void
|
||||
injection_stats_fixed_init_shmem_cb(void *stats)
|
||||
{
|
||||
PgStatShared_InjectionPointFixed *stats_shmem =
|
||||
(PgStatShared_InjectionPointFixed *) stats;
|
||||
|
||||
LWLockInitialize(&stats_shmem->lock, LWTRANCHE_PGSTATS_DATA);
|
||||
}
|
||||
|
||||
static void
|
||||
injection_stats_fixed_reset_all_cb(TimestampTz ts)
|
||||
{
|
||||
PgStatShared_InjectionPointFixed *stats_shmem =
|
||||
pgstat_get_custom_shmem_data(PGSTAT_KIND_INJECTION_FIXED);
|
||||
|
||||
LWLockAcquire(&stats_shmem->lock, LW_EXCLUSIVE);
|
||||
pgstat_copy_changecounted_stats(&stats_shmem->reset_offset,
|
||||
&stats_shmem->stats,
|
||||
sizeof(stats_shmem->stats),
|
||||
&stats_shmem->changecount);
|
||||
stats_shmem->stats.stat_reset_timestamp = ts;
|
||||
LWLockRelease(&stats_shmem->lock);
|
||||
}
|
||||
|
||||
static void
|
||||
injection_stats_fixed_snapshot_cb(void)
|
||||
{
|
||||
PgStatShared_InjectionPointFixed *stats_shmem =
|
||||
pgstat_get_custom_shmem_data(PGSTAT_KIND_INJECTION_FIXED);
|
||||
PgStat_StatInjFixedEntry *stat_snap =
|
||||
pgstat_get_custom_snapshot_data(PGSTAT_KIND_INJECTION_FIXED);
|
||||
PgStat_StatInjFixedEntry *reset_offset = &stats_shmem->reset_offset;
|
||||
PgStat_StatInjFixedEntry reset;
|
||||
|
||||
pgstat_copy_changecounted_stats(stat_snap,
|
||||
&stats_shmem->stats,
|
||||
sizeof(stats_shmem->stats),
|
||||
&stats_shmem->changecount);
|
||||
|
||||
LWLockAcquire(&stats_shmem->lock, LW_SHARED);
|
||||
memcpy(&reset, reset_offset, sizeof(stats_shmem->stats));
|
||||
LWLockRelease(&stats_shmem->lock);
|
||||
|
||||
/* compensate by reset offsets */
|
||||
#define FIXED_COMP(fld) stat_snap->fld -= reset.fld;
|
||||
FIXED_COMP(numattach);
|
||||
FIXED_COMP(numdetach);
|
||||
FIXED_COMP(numrun);
|
||||
#undef FIXED_COMP
|
||||
}
|
||||
|
||||
/*
|
||||
* Workhorse to do the registration work, called in _PG_init().
|
||||
*/
|
||||
void
|
||||
pgstat_register_inj_fixed(void)
|
||||
{
|
||||
pgstat_register_kind(PGSTAT_KIND_INJECTION_FIXED, &injection_stats_fixed);
|
||||
|
||||
/* mark stats as loaded */
|
||||
inj_fixed_loaded = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Report fixed number of statistics for an injection point.
|
||||
*/
|
||||
void
|
||||
pgstat_report_inj_fixed(uint32 numattach,
|
||||
uint32 numdetach,
|
||||
uint32 numrun)
|
||||
{
|
||||
PgStatShared_InjectionPointFixed *stats_shmem;
|
||||
|
||||
/* leave if disabled */
|
||||
if (!inj_fixed_loaded)
|
||||
return;
|
||||
|
||||
stats_shmem = pgstat_get_custom_shmem_data(PGSTAT_KIND_INJECTION_FIXED);
|
||||
|
||||
pgstat_begin_changecount_write(&stats_shmem->changecount);
|
||||
stats_shmem->stats.numattach += numattach;
|
||||
stats_shmem->stats.numdetach += numdetach;
|
||||
stats_shmem->stats.numrun += numrun;
|
||||
pgstat_end_changecount_write(&stats_shmem->changecount);
|
||||
}
|
||||
|
||||
/*
|
||||
* SQL function returning fixed-numbered statistics for injection points.
|
||||
*/
|
||||
PG_FUNCTION_INFO_V1(injection_points_stats_fixed);
|
||||
Datum
|
||||
injection_points_stats_fixed(PG_FUNCTION_ARGS)
|
||||
{
|
||||
TupleDesc tupdesc;
|
||||
Datum values[3] = {0};
|
||||
bool nulls[3] = {0};
|
||||
PgStat_StatInjFixedEntry *stats;
|
||||
|
||||
if (!inj_fixed_loaded)
|
||||
PG_RETURN_NULL();
|
||||
|
||||
pgstat_snapshot_fixed(PGSTAT_KIND_INJECTION_FIXED);
|
||||
stats = pgstat_get_custom_snapshot_data(PGSTAT_KIND_INJECTION_FIXED);
|
||||
|
||||
/* Initialise attributes information in the tuple descriptor */
|
||||
tupdesc = CreateTemplateTupleDesc(3);
|
||||
TupleDescInitEntry(tupdesc, (AttrNumber) 1, "numattach",
|
||||
INT8OID, -1, 0);
|
||||
TupleDescInitEntry(tupdesc, (AttrNumber) 2, "numdetach",
|
||||
INT8OID, -1, 0);
|
||||
TupleDescInitEntry(tupdesc, (AttrNumber) 3, "numrun",
|
||||
INT8OID, -1, 0);
|
||||
BlessTupleDesc(tupdesc);
|
||||
|
||||
values[0] = Int64GetDatum(stats->numattach);
|
||||
values[1] = Int64GetDatum(stats->numdetach);
|
||||
values[2] = Int64GetDatum(stats->numrun);
|
||||
nulls[0] = false;
|
||||
nulls[1] = false;
|
||||
nulls[2] = false;
|
||||
|
||||
/* Returns the record as Datum */
|
||||
PG_RETURN_DATUM(HeapTupleGetDatum(heap_form_tuple(tupdesc, values, nulls)));
|
||||
}
|
|
@ -7,6 +7,7 @@ endif
|
|||
injection_points_sources = files(
|
||||
'injection_points.c',
|
||||
'injection_stats.c',
|
||||
'injection_stats_fixed.c',
|
||||
)
|
||||
|
||||
if host_system == 'windows'
|
||||
|
|
|
@ -33,18 +33,27 @@ $node->safe_psql('postgres', "SELECT injection_points_run('stats-notice');");
|
|||
my $numcalls = $node->safe_psql('postgres',
|
||||
"SELECT injection_points_stats_numcalls('stats-notice');");
|
||||
is($numcalls, '2', 'number of stats calls');
|
||||
my $fixedstats = $node->safe_psql('postgres',
|
||||
"SELECT * FROM injection_points_stats_fixed();");
|
||||
is($fixedstats, '1|0|2', 'number of fixed stats');
|
||||
|
||||
# Restart the node cleanly, stats should still be around.
|
||||
$node->restart;
|
||||
$numcalls = $node->safe_psql('postgres',
|
||||
"SELECT injection_points_stats_numcalls('stats-notice');");
|
||||
is($numcalls, '2', 'number of stats after clean restart');
|
||||
$fixedstats = $node->safe_psql('postgres',
|
||||
"SELECT * FROM injection_points_stats_fixed();");
|
||||
is($fixedstats, '1|0|2', 'number of fixed stats after clean restart');
|
||||
|
||||
# On crash the stats are gone.
|
||||
$node->stop('immediate');
|
||||
$node->start;
|
||||
$numcalls = $node->safe_psql('postgres',
|
||||
"SELECT injection_points_stats_numcalls('stats-notice');");
|
||||
is($numcalls, '', 'number of stats after clean restart');
|
||||
is($numcalls, '', 'number of stats after crash');
|
||||
$fixedstats = $node->safe_psql('postgres',
|
||||
"SELECT * FROM injection_points_stats_fixed();");
|
||||
is($fixedstats, '0|0|0', 'number of fixed stats after crash');
|
||||
|
||||
done_testing();
|
||||
|
|
|
@ -2120,6 +2120,7 @@ PgStatShared_Database
|
|||
PgStatShared_Function
|
||||
PgStatShared_HashEntry
|
||||
PgStatShared_InjectionPoint
|
||||
PgStatShared_InjectionPointFixed
|
||||
PgStatShared_IO
|
||||
PgStatShared_Relation
|
||||
PgStatShared_ReplSlot
|
||||
|
@ -2152,6 +2153,7 @@ PgStat_SnapshotEntry
|
|||
PgStat_StatDBEntry
|
||||
PgStat_StatFuncEntry
|
||||
PgStat_StatInjEntry
|
||||
PgStat_StatInjFixedEntry
|
||||
PgStat_StatReplSlotEntry
|
||||
PgStat_StatSubEntry
|
||||
PgStat_StatTabEntry
|
||||
|
|
Loading…
Reference in New Issue