Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1vQaJX-00BxZH-2M for pgsql-hackers@arkaria.postgresql.org; Wed, 03 Dec 2025 00:01:48 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1vQaJW-00AY9I-1e for pgsql-hackers@arkaria.postgresql.org; Wed, 03 Dec 2025 00:01:46 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1vQaJV-00AY9A-1f for pgsql-hackers@lists.postgresql.org; Wed, 03 Dec 2025 00:01:46 +0000 Received: from fout-a6-smtp.messagingengine.com ([103.168.172.149]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1vQaJS-002pCy-2c for pgsql-hackers@lists.postgresql.org; Wed, 03 Dec 2025 00:01:45 +0000 Received: from phl-compute-01.internal (phl-compute-01.internal [10.202.2.41]) by mailfout.phl.internal (Postfix) with ESMTP id B0D39EC03F6; Tue, 2 Dec 2025 19:01:35 -0500 (EST) Received: from phl-mailfrontend-02 ([10.202.2.163]) by phl-compute-01.internal (MEProxy); Tue, 02 Dec 2025 19:01:35 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=paquier.xyz; h= cc:cc:content-type:content-type:date:date:from:from:in-reply-to :in-reply-to:message-id:mime-version:references:reply-to:subject :subject:to:to; s=fm1; t=1764720095; x=1764806495; bh=RjENF42Sux 7POsPhxN+PX/j1LRhjmsK9nPeVEeua4Ao=; b=HljKxtRttu763xuI3t4rE3VsyF 03Fr1fFo874ciNV/yzVQ7xQgO3vaaSs/yf+zKyTfTMHyLViYCaBzUgsPFPVpHYzQ K70DonDnYOeS2xm/S3hjcZ0mG51NMlEw+qr7zDA9J4hxAYSRgrc8lUdzgPDtJLUT cPVLAAZJ5OugAGErYAQPsHXeYCCMvSQxyDsI14QCDlMNdcX+IgmdHL2OAjCvi5vy pYGiCmLu4KdCxLUI/+UiN5TyVkorgrhHqrgHgtGOgLToIlc+4e4xuzOoIB2SJNcZ Mm7jpEwp9HrUFDk6oORVTHhFA6UKA+1foXXkD/v4aNVWTfV078RSL4t3h1yw== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-type:content-type:date:date :feedback-id:feedback-id:from:from:in-reply-to:in-reply-to :message-id:mime-version:references:reply-to:subject:subject:to :to:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s=fm1; t= 1764720095; x=1764806495; bh=RjENF42Sux7POsPhxN+PX/j1LRhjmsK9nPe VEeua4Ao=; b=TBOEOvj6e+V0wE84/H2x3UHKBH4IbaHCz9dqzT+BazFRU9SiQJU QeAdHmuYLWB95bmQFRJoY2M5KwDyFokwTydO5Ok2w0VQHGHYgt5u4gEbOlAR848D cepYt3a0R+EgdPNzIKhVTi3Q5cEU6So+MUAqBXV5pNzeaXQiitewcVhb4VSfGSqX R55f1kAhgKFXuB8TIBhgIPez9kWy1TNbTORzPJOjpMbV1Sk8fw2XiRqcydj7MZ2e 0WkhcC9A9orgIBMzy6s1MLeoGWqc/11+VHJ0k9CGxaMwC/zJGI7AEyZDzeKgEKDh OnpqjVCNvmLwfxkOw3HHDvLSyEdMvWp5OZA== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeefgedrtddtgddugeehucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfurfetoffkrfgpnffqhgenuceurghi lhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmnegfrhhluc fvnfffucdljedtmdenucfjughrpeffhffvvefukfhfgggtuggjsehgtderredttddvnecu hfhrohhmpefoihgthhgrvghlucfrrghquhhivghruceomhhitghhrggvlhesphgrqhhuih gvrhdrgiihiieqnecuggftrfgrthhtvghrnhepteelieefudffhffhtdetleeggeegfffh keeuveetiefgudduvedutefggeeivdejnecuvehluhhsthgvrhfuihiivgeptdenucfrrg hrrghmpehmrghilhhfrhhomhepmhhitghhrggvlhesphgrqhhuihgvrhdrgiihiidpnhgs pghrtghpthhtohepvddpmhhouggvpehsmhhtphhouhhtpdhrtghpthhtohepshgrmhhimh hsvghihhesghhmrghilhdrtghomhdprhgtphhtthhopehpghhsqhhlqdhhrggtkhgvrhhs sehlihhsthhsrdhpohhsthhgrhgvshhqlhdrohhrgh X-ME-Proxy: Feedback-ID: i0fe9450f:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Tue, 2 Dec 2025 19:01:33 -0500 (EST) Date: Wed, 3 Dec 2025 09:01:14 +0900 From: Michael Paquier To: Sami Imseih Cc: PostgreSQL Hackers Subject: Re: [Proposal] Adding callback support for custom statistics kinds Message-ID: References: MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha512; protocol="application/pgp-signature"; boundary="iZD5a3MSysf+HgEq" Content-Disposition: inline In-Reply-To: List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --iZD5a3MSysf+HgEq Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable On Tue, Dec 02, 2025 at 02:58:32PM -0600, Sami Imseih wrote: > By "template" code, do you mean Something like? >=20 > include/utils/custom_statkinds.h > backend/utils/misc/custom_statkinds.c > > Where the template code here is PgStat_kind definition, callbacks, etc. f= or > injection_points or the new test module that is using a custom kind. I am not completely sure that we need a separate C file for a portion of the code related to custom stats kinds. At least, I am not sure to see which part of pgstat.c, pgstat_internal.h and pgstat_shmem.c could be extracted so as a custom_statkinds.c could have value when taken independently. A test module makes the most sense for such templates IMO, as they can be compiled and checked directly. > v2-0001 are much simplified changes to pgstat.c that simply invoke the ca= llbacks > and all the work is on the extension to implement what it needs to do. > This includes > a callback at the end of WRITE, READ, DISCARD with a flag passed to the c= aller > so they can perform the necessary clean-up actions. + void (*to_serialized_extra_stats) (const PgStat_HashKey *key, + const PgStatShared_Common *header, FILE *statfile); + void (*from_serialized_extra_stats) (const PgStat_HashKey *key, + const PgStatShared_Common *header, FILE *statfile); + void (*end_extra_stats) (PgStat_StatsFileOp status); [...] +typedef struct PgStatShared_CustomEntry +{ + PgStatShared_Common header; + PgStat_StatCustomEntry stats; + char name[NAMEDATALEN]; + dsa_pointer description; +} PgStatShared_CustomEntry; I'm cool with this design, including your point about using a DSA pointer in a stats entry, manipulating this data through the serialization callback. Your module does not use the FILE* which points to the main stats file for the to/from extra serialized callbacks, it seems important to document in pgstat_internal.h that this points to the "main" pgstats file manipulated by the startup process when loading or by the checkpointer when flushing. Perhaps the callback in the module for end_extra_stats should use a switch based on PgStat_StatsFileOp. Minor point. +/* File handle for statistics serialization */ +static FILE *fd =3D NULL; Using a fd tracked directly by the module sounds good to me, yes. That gives to the modules the flexibility to decide what should be the extra files to know about, some file name patterns being possible to decide based on the stats entry keys that need to be written, with files opened when actually required. > v2-0002 implements a new test module that tests mainly that the recovery, > clean and crash, are working as expected. That looks like a good direction to me. The only differences I can see with the stats module in injection_points for variable-sized stats is that this new module does not check pgstat_drop_entry() and pgstat_fetch_entry() when working on a custom stats kind. If we had SQL interfaces calling these two, we could just remove injection_stats.c entirely, moving everything to this new test module. I should have invented a new module from the start, perhaps, but well, that was good enough to check the basic APIs when working on the custom APIs. Removing this duplication would be my own business with your module in the tree, no need for you to worry about that. That would also remove the tweak you have used regarding the duplicated kind ID. Perhaps we should do the same for the fixed-sized kind at the end, and instead of using one .so for both of them, we could just create a separate .so with multiple entries in MODULES? What do you think? What you have here is better than what's in the tree in terms of module separation for HEAD. > I created a new tap test for this which performs a test similar to what is > done in recovery/029_stats_restart.pl. I could merge the new test there, = but > I am reluctant to add a dependency on a new module to recovery. What > do you think? Adding an extra item to recovery's EXTRA_INSTALL would be OK for me, but it seems cleaner to me to keep the tests related to custom stats in their own area like your patch 0002 is doing with its new test module test_custom_statkind. And 029_stats_restart.pl is already covering a lot of ground. + if (pgstat_is_kind_custom(key.kind) && kind_info->from_serialized_ext= ra_stats) + kind_info->from_serialized_extra_stats(&key, header, fpin); [...] + if (pgstat_is_kind_custom(ps->key.kind) && kind_info->to_serialized_e= xtra_stats) + kind_info->to_serialized_extra_stats(&ps->key, shstats, fpout); These restrictions based on custom kinds do not seem mandatory. Why not allowing built-in kinds the same set of operations? + /* Read and verify the hash key */ + if (!pgstat_read_chunk(fd, (void *) key, sizeof(PgStat_HashKey))) + return; [...] + /* Write the hash key to identify this entry */ + pgstat_write_chunk(fd, (void *) key, sizeof(PgStat_HashKey)); I am puzzled by this part of 0002. Why are you overwriting the key once after loading it from the main pgstats file? Writing the key to cross-check that the data matches with what is in the main file is OK, and this should be ensured because of the ordering of the data. I would have done it in a slightly different way, I guess, with the data stored on disk in the main pgstats file including an offset to know where to search in the secondary file. That's what we would do for PGSS as well, I guess, with the secondary file including data structured as a set of: - Entry key, cross-checked with the data read from the main file, based on the offset stored in the main file. - Length of extra data. - The extra data contents. As a whole, I find this patch pretty cool, particularly the point about extending stats entries with DSAs, something that would be essential for PGSS and move it to use pgstats because we don't want the query strings in the main pgstats file and bloat it. Nice. -- Michael --iZD5a3MSysf+HgEq Content-Type: application/pgp-signature; name="signature.asc" -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEG72nH6vTowiyblFKnvQgOdbyQH0FAmkvfcoACgkQnvQgOdby QH2MqQ/+ISmSY0r09vXjKtRyOE/By200uRMtliL3pENvP112Mupdey+jQFWEaDak Tf3tY700w3Dr7IojE+/jIpCW2YGtHcav12OjP/HgH/27t8J73wT/l2nr/NT50ey3 aBdodYTd8b438LvI5AORgQHVtRnMepPj1DHS2JCqUrnSjwSTrgVFATDtYo7+k15l c5MGpfK9rSydLUCvE6prLjgI+l3JnbIibAZFVtawYtSXlBsXd32+fwLt34UVZKHg J4pW/HBi4RopplML96KWVROZzBYKgWQUNl4JhH/53Kr/9Qk+ylVgn0hzeqhdn5W7 WVNwsupcCsZC3KAm8qr/ry8vgiESNcHxKwv+Q3O4kwSl/efNauf8yqn/op8ZZ/yW PScyxltPNweuwFdO6m7+1ed+h1S4U/ur2Qb6HaK8FWThVqhxXrFL9CIIPult+GWi MqMF7rrDrDKq8AXnyPZx2WRPdBeErYaukn4kQf1J6h5hdOLUgMe9DXjOIt3cc5P9 P5FL4HTfm994ziPP0d+Zpm9C3GfrK+ehSY+aCIpQBN5FhGg77vh4cyDOdvC+rvWR ETqA7LuawsNWNVuJveQ9u0xqO9OpxoyKYTjjNcjuOaIorD/V0l0Hhl5HcbWBWLgK SFWIldc10bzS1qNOtEjHEO/Hb1+zlToPfd+GMAyI1i/kcR4RxT4= =OAne -----END PGP SIGNATURE----- --iZD5a3MSysf+HgEq--