Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit7553443

Browse files
committed
injection_points: Add some cumulative stats for injection points
This acts as a template of what can be achieved with the pluggablecumulative stats APIs introduced in7949d95 for thevariable-numbered case where stats entries are stored in the pgstatsdshash, while being potentially useful on its own for injection points,say to add starting and/or stopping conditions based on the statistics(want to trigger a callback after N calls, for example?).Currently, the only data gathered is the number of times an injectionpoint is run. More fields can always be added as required. All theroutines related to the stats are located in their own file, calledinjection_stats.c in the test module injection_points, for clarity.The stats can be used only if the test module is loaded throughshared_preload_libraries. The key of the dshash uses InvalidOid for thedatabase, and an int4 hash of the injection point name as object ID.A TAP test is added to provide coverage for the new custom cumulativestats APIs, showing the persistency of the data across restarts, forexample.Author: Michael PaquierReviewed-by: Dmitry Dolgov, Bertrand DrouvotDiscussion:https://postgr.es/m/Zmqm9j5EO0I4W8dx@paquier.xyz
1 parent2eff9e6 commit7553443

File tree

9 files changed

+332
-2
lines changed

9 files changed

+332
-2
lines changed

‎doc/src/sgml/xfunc.sgml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3919,6 +3919,11 @@ extern PgStat_Kind pgstat_add_kind(PgStat_Kind kind,
39193919
type in <xref linkend="guc-shared-preload-libraries"/> so that it will
39203920
be loaded early during <productname>PostgreSQL</productname> startup.
39213921
</para>
3922+
3923+
<para>
3924+
An example describing how to register and use custom statistics can be
3925+
found in <filename>src/test/modules/injection_points</filename>.
3926+
</para>
39223927
</sect2>
39233928

39243929
<sect2 id="extend-cpp">

‎src/test/modules/injection_points/Makefile

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
# src/test/modules/injection_points/Makefile
22

3-
MODULES = injection_points
4-
3+
MODULE_big = injection_points
4+
OBJS =\
5+
$(WIN32RES)\
6+
injection_points.o\
7+
injection_stats.o
58
EXTENSION = injection_points
69
DATA = injection_points--1.0.sql
710
PGFILEDESC = "injection_points - facility for injection points"
@@ -11,9 +14,13 @@ REGRESS_OPTS = --dlpath=$(top_builddir)/src/test/regress
1114

1215
ISOLATION = inplace
1316

17+
TAP_TESTS = 1
18+
1419
# The injection points are cluster-wide, so disable installcheck
1520
NO_INSTALLCHECK = 1
1621

22+
exportenable_injection_pointsenable_injection_points
23+
1724
ifdefUSE_PGXS
1825
PG_CONFIG = pg_config
1926
PGXS :=$(shell$(PG_CONFIG) --pgxs)

‎src/test/modules/injection_points/injection_points--1.0.sql

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,3 +74,13 @@ CREATE FUNCTION injection_points_detach(IN point_name TEXT)
7474
RETURNS void
7575
AS'MODULE_PATHNAME','injection_points_detach'
7676
LANGUAGE C STRICT PARALLEL UNSAFE;
77+
78+
--
79+
-- injection_points_stats_numcalls()
80+
--
81+
-- Reports statistics, if any, related to the given injection point.
82+
--
83+
CREATEFUNCTIONinjection_points_stats_numcalls(IN point_nameTEXT)
84+
RETURNSbigint
85+
AS'MODULE_PATHNAME','injection_points_stats_numcalls'
86+
LANGUAGE C STRICT;

‎src/test/modules/injection_points/injection_points.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include"postgres.h"
1919

2020
#include"fmgr.h"
21+
#include"injection_stats.h"
2122
#include"miscadmin.h"
2223
#include"nodes/pg_list.h"
2324
#include"nodes/value.h"
@@ -170,6 +171,9 @@ injection_points_cleanup(int code, Datum arg)
170171
char*name=strVal(lfirst(lc));
171172

172173
(void)InjectionPointDetach(name);
174+
175+
/* Remove stats entry */
176+
pgstat_drop_inj(name);
173177
}
174178
}
175179

@@ -182,6 +186,8 @@ injection_error(const char *name, const void *private_data)
182186
if (!injection_point_allowed(condition))
183187
return;
184188

189+
pgstat_report_inj(name);
190+
185191
elog(ERROR,"error triggered for injection point %s",name);
186192
}
187193

@@ -193,6 +199,8 @@ injection_notice(const char *name, const void *private_data)
193199
if (!injection_point_allowed(condition))
194200
return;
195201

202+
pgstat_report_inj(name);
203+
196204
elog(NOTICE,"notice triggered for injection point %s",name);
197205
}
198206

@@ -211,6 +219,8 @@ injection_wait(const char *name, const void *private_data)
211219
if (!injection_point_allowed(condition))
212220
return;
213221

222+
pgstat_report_inj(name);
223+
214224
/*
215225
* Use the injection point name for this custom wait event. Note that
216226
* this custom wait event name is not released, but we don't care much for
@@ -299,6 +309,10 @@ injection_points_attach(PG_FUNCTION_ARGS)
299309
inj_list_local=lappend(inj_list_local,makeString(pstrdup(name)));
300310
MemoryContextSwitchTo(oldctx);
301311
}
312+
313+
/* Add entry for stats */
314+
pgstat_create_inj(name);
315+
302316
PG_RETURN_VOID();
303317
}
304318

@@ -431,5 +445,18 @@ injection_points_detach(PG_FUNCTION_ARGS)
431445
MemoryContextSwitchTo(oldctx);
432446
}
433447

448+
/* Remove stats entry */
449+
pgstat_drop_inj(name);
450+
434451
PG_RETURN_VOID();
435452
}
453+
454+
455+
void
456+
_PG_init(void)
457+
{
458+
if (!process_shared_preload_libraries_in_progress)
459+
return;
460+
461+
pgstat_register_inj();
462+
}
Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
/*--------------------------------------------------------------------------
2+
*
3+
* injection_stats.c
4+
*Code for statistics of injection points.
5+
*
6+
* Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
7+
* Portions Copyright (c) 1994, Regents of the University of California
8+
*
9+
* IDENTIFICATION
10+
*src/test/modules/injection_points/injection_stats.c
11+
*
12+
* -------------------------------------------------------------------------
13+
*/
14+
15+
#include"postgres.h"
16+
17+
#include"fmgr.h"
18+
19+
#include"common/hashfn.h"
20+
#include"injection_stats.h"
21+
#include"pgstat.h"
22+
#include"utils/builtins.h"
23+
#include"utils/pgstat_internal.h"
24+
25+
/* Structures for statistics of injection points */
26+
typedefstructPgStat_StatInjEntry
27+
{
28+
PgStat_Counternumcalls;/* number of times point has been run */
29+
}PgStat_StatInjEntry;
30+
31+
typedefstructPgStatShared_InjectionPoint
32+
{
33+
PgStatShared_Commonheader;
34+
PgStat_StatInjEntrystats;
35+
}PgStatShared_InjectionPoint;
36+
37+
staticboolinjection_stats_flush_cb(PgStat_EntryRef*entry_ref,boolnowait);
38+
39+
staticconstPgStat_KindInfoinjection_stats= {
40+
.name="injection_points",
41+
.fixed_amount= false,/* Bounded by the number of points */
42+
43+
/* Injection points are system-wide */
44+
.accessed_across_databases= true,
45+
46+
.shared_size=sizeof(PgStatShared_InjectionPoint),
47+
.shared_data_off= offsetof(PgStatShared_InjectionPoint,stats),
48+
.shared_data_len=sizeof(((PgStatShared_InjectionPoint*)0)->stats),
49+
.pending_size=sizeof(PgStat_StatInjEntry),
50+
.flush_pending_cb=injection_stats_flush_cb,
51+
};
52+
53+
/*
54+
* Compute stats entry idx from point name with a 4-byte hash.
55+
*/
56+
#definePGSTAT_INJ_IDX(name) hash_bytes((const unsigned char *) name, strlen(name))
57+
58+
/*
59+
* Kind ID reserved for statistics of injection points.
60+
*/
61+
#definePGSTAT_KIND_INJECTION129
62+
63+
/* Track if stats are loaded */
64+
staticboolinj_stats_loaded= false;
65+
66+
/*
67+
* Callback for stats handling
68+
*/
69+
staticbool
70+
injection_stats_flush_cb(PgStat_EntryRef*entry_ref,boolnowait)
71+
{
72+
PgStat_StatInjEntry*localent;
73+
PgStatShared_InjectionPoint*shfuncent;
74+
75+
localent= (PgStat_StatInjEntry*)entry_ref->pending;
76+
shfuncent= (PgStatShared_InjectionPoint*)entry_ref->shared_stats;
77+
78+
if (!pgstat_lock_entry(entry_ref,nowait))
79+
return false;
80+
81+
shfuncent->stats.numcalls+=localent->numcalls;
82+
return true;
83+
}
84+
85+
/*
86+
* Support function for the SQL-callable pgstat* functions. Returns
87+
* a pointer to the injection point statistics struct.
88+
*/
89+
staticPgStat_StatInjEntry*
90+
pgstat_fetch_stat_injentry(constchar*name)
91+
{
92+
PgStat_StatInjEntry*entry=NULL;
93+
94+
if (!inj_stats_loaded)
95+
returnNULL;
96+
97+
/* Compile the lookup key as a hash of the point name */
98+
entry= (PgStat_StatInjEntry*)pgstat_fetch_entry(PGSTAT_KIND_INJECTION,
99+
InvalidOid,
100+
PGSTAT_INJ_IDX(name));
101+
returnentry;
102+
}
103+
104+
/*
105+
* Workhorse to do the registration work, called in _PG_init().
106+
*/
107+
void
108+
pgstat_register_inj(void)
109+
{
110+
pgstat_register_kind(PGSTAT_KIND_INJECTION,&injection_stats);
111+
112+
/* mark stats as loaded */
113+
inj_stats_loaded= true;
114+
}
115+
116+
/*
117+
* Report injection point creation.
118+
*/
119+
void
120+
pgstat_create_inj(constchar*name)
121+
{
122+
PgStat_EntryRef*entry_ref;
123+
PgStatShared_InjectionPoint*shstatent;
124+
125+
/* leave if disabled */
126+
if (!inj_stats_loaded)
127+
return;
128+
129+
entry_ref=pgstat_get_entry_ref_locked(PGSTAT_KIND_INJECTION,InvalidOid,
130+
PGSTAT_INJ_IDX(name), false);
131+
shstatent= (PgStatShared_InjectionPoint*)entry_ref->shared_stats;
132+
133+
/* initialize shared memory data */
134+
memset(&shstatent->stats,0,sizeof(shstatent->stats));
135+
pgstat_unlock_entry(entry_ref);
136+
}
137+
138+
/*
139+
* Report injection point drop.
140+
*/
141+
void
142+
pgstat_drop_inj(constchar*name)
143+
{
144+
/* leave if disabled */
145+
if (!inj_stats_loaded)
146+
return;
147+
148+
if (!pgstat_drop_entry(PGSTAT_KIND_INJECTION,InvalidOid,
149+
PGSTAT_INJ_IDX(name)))
150+
pgstat_request_entry_refs_gc();
151+
}
152+
153+
/*
154+
* Report statistics for injection point.
155+
*
156+
* This is simple because the set of stats to report currently is simple:
157+
* track the number of times a point has been run.
158+
*/
159+
void
160+
pgstat_report_inj(constchar*name)
161+
{
162+
PgStat_EntryRef*entry_ref;
163+
PgStatShared_InjectionPoint*shstatent;
164+
PgStat_StatInjEntry*statent;
165+
166+
/* leave if disabled */
167+
if (!inj_stats_loaded)
168+
return;
169+
170+
entry_ref=pgstat_get_entry_ref_locked(PGSTAT_KIND_INJECTION,InvalidOid,
171+
PGSTAT_INJ_IDX(name), false);
172+
173+
shstatent= (PgStatShared_InjectionPoint*)entry_ref->shared_stats;
174+
statent=&shstatent->stats;
175+
176+
/* Update the injection point statistics */
177+
statent->numcalls++;
178+
179+
pgstat_unlock_entry(entry_ref);
180+
}
181+
182+
/*
183+
* SQL function returning the number of times an injection point
184+
* has been called.
185+
*/
186+
PG_FUNCTION_INFO_V1(injection_points_stats_numcalls);
187+
Datum
188+
injection_points_stats_numcalls(PG_FUNCTION_ARGS)
189+
{
190+
char*name=text_to_cstring(PG_GETARG_TEXT_PP(0));
191+
PgStat_StatInjEntry*entry=pgstat_fetch_stat_injentry(name);
192+
193+
if (entry==NULL)
194+
PG_RETURN_NULL();
195+
196+
PG_RETURN_INT64(entry->numcalls);
197+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/*--------------------------------------------------------------------------
2+
*
3+
* injection_stats.h
4+
*Definitions for statistics of injection points.
5+
*
6+
* Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
7+
* Portions Copyright (c) 1994, Regents of the University of California
8+
*
9+
* IDENTIFICATION
10+
*src/test/modules/injection_points/injection_stats.h
11+
*
12+
* -------------------------------------------------------------------------
13+
*/
14+
15+
#ifndefINJECTION_STATS
16+
#defineINJECTION_STATS
17+
18+
externvoidpgstat_register_inj(void);
19+
externvoidpgstat_create_inj(constchar*name);
20+
externvoidpgstat_drop_inj(constchar*name);
21+
externvoidpgstat_report_inj(constchar*name);
22+
23+
#endif

‎src/test/modules/injection_points/meson.build

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ endif
66

77
injection_points_sources=files(
88
'injection_points.c',
9+
'injection_stats.c',
910
)
1011

1112
if host_system=='windows'
@@ -42,4 +43,12 @@ tests += {
4243
'inplace',
4344
],
4445
},
46+
'tap': {
47+
'env': {
48+
'enable_injection_points':get_option('injection_points') ?'yes' :'no',
49+
},
50+
'tests': [
51+
't/001_stats.pl',
52+
],
53+
},
4554
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp