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 1wGATX-005x9b-0W for pgsql-hackers@arkaria.postgresql.org; Fri, 24 Apr 2026 06:57:19 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1wGATW-0050MU-1B for pgsql-hackers@arkaria.postgresql.org; Fri, 24 Apr 2026 06:57:18 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1wGATV-0050MM-2f for pgsql-hackers@lists.postgresql.org; Fri, 24 Apr 2026 06:57:18 +0000 Received: from mail-yx1-xb12d.google.com ([2607:f8b0:4864:20::b12d]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.98.2) (envelope-from ) id 1wGATT-00000002XQ5-0Yrf for pgsql-hackers@lists.postgresql.org; Fri, 24 Apr 2026 06:57:16 +0000 Received: by mail-yx1-xb12d.google.com with SMTP id 956f58d0204a3-65075c2ba66so5751600d50.1 for ; Thu, 23 Apr 2026 23:57:15 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1777013834; cv=none; d=google.com; s=arc-20240605; b=YJ1JbXe4MKmM2UHdifLUZxOryX1xW/mVn+OKzyXnNh2b0nMmmCNIVtXiS4z9Fo+Ebf bpi0FYXh1E13/h0sNWArzASqGkuemwGIvRiaEgE0qaZCX5kKaPaduMrj3SFYZ9pm5cKr Gpimv05IhBt19N/U4lU/ajz1Mv6IjVyKGhj9TZvuzVFV/fsiHc3Z2wP21tm3Tr6r68qx +Ix86pxR3doVkugyPBSLdcORde4oSH8oIxHC7/Axus7PyStE/u3yq9CkVz0jM2X3Pzjw +UhFsf1UcmOcghj1rMZnmL0+H3gbJkkS5QenYDtW9fmcn0jmllEhNOyFhL2b/TP9iwSq kz5A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:dkim-signature; bh=NPWkw9NNGuuD+isyptMKULIfXWM8qDcaDxZs25X+J+E=; fh=eGhD8NE58EmIgD6b+gPO+CvU80MO/Q+yy1QKus3+4M4=; b=kcBebl5o8ChEoOuqMHUmiB02vl9DJOW8S1Y+1uwQXKWcIOYvFQfcB7D6javEEXd4He a0zS4XYzctmak60apuzQD2QJDV48z1QmHerdF/T/fYTst07mqXuJYL1AD6/Kpq2/L9P6 pzZkGGowBgPAaohEU40Z57Iv9xlZuANnzDEQaiF8oUuhwy/IMjjmENu8byTOMYAKSBmW sYtOnCeLy3N9mLgAVTWREIkS65rokSbbKj0LJorfjXGPwZHgnYeAhDmJvmn89mJraw03 gJW4x9hals/aGIm69EUkmNY4GoO+hFG/jZkN7SLL1Af8FccrmlTmytjqGFwSUeW46SNw bX4g==; darn=lists.postgresql.org ARC-Authentication-Results: i=1; mx.google.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1777013834; x=1777618634; darn=lists.postgresql.org; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=NPWkw9NNGuuD+isyptMKULIfXWM8qDcaDxZs25X+J+E=; b=JMzXVnAUZhBTSradNdP03p0kHK0lC3dugw74hkYizjG/IewhxKMsj8+PKDLyQrl5Pd CCgUQ5rtCW6ybzjtSLTW//MzcBpV4SMbnIfyuAx65JfCGgBPO/0gTjGojQxrP7LftSzk eSrnMjenYyWDNcW059idGNZB72iEg1e2jiPWNqtWopGXnFFiJdN8o6AbWkoDu0Fndzd2 iGrXeA2bDs0G4Ry3ralQ7LFb75unTLt6d2QY3em+OHVss5Nwxqpnlajgh6U9WIqYjDNA PDe1qw0UN//+K15ictyY4xBeOfnhZurI3L8DqGcD4vBC/AQsgjH98abU9KkOvbKjfRov 2RHQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1777013834; x=1777618634; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=NPWkw9NNGuuD+isyptMKULIfXWM8qDcaDxZs25X+J+E=; b=FDuHoBQLGG4mMwKR72fVmzk34SRkMOxn4K5C7SHtI5vLkQwm1nrbN/Ech3+lQhZSnZ 2Fz0eDovU6wPbW8gr9UbTpPT/Hhb0Obr1RjRjW+BtwDIibMOI3YD4Mt018JMM84bfkV3 1wTpK2yQHBrCr3nyA5W3XADN2000X/ludw7VDZgFPaX+VhUzeqM3EDfx4KqMZEL1YwU6 0N3mv6HBwHU7SNolDf69ocPgWa0o4SPPj4yvJvYnG+J1OCVJtt9/1kslakMkTFrCsfEO whzHNHJ1xy9ONqnO54gOtg7ds6KYteDrE1UD8A1DpGy91MUKyfunzVw6LehYA+Dx6MbL YJ5w== X-Gm-Message-State: AOJu0YwPTwptXNkyZk5IM/Yotqt7vwjLnI8X+WLWv2JNsK4tAtPZX6uP BgVGvbUXOLypqkXJIw9GSuVvhN1+VidRFyH7TXzqr+XYf5pBuES7kumm5S9llDIh63hGWmnHlm9 Qe5HrqCJ/07WZ/vxHYS2+fVmbDydQud8= X-Gm-Gg: AeBDieuceDvTGdTeaPR78lAI3G4YGPjiAqcFB17/p3QtCccOtub9PEc4enTMzOh2UdN 4vVkvSTpWKla6oFdEaer53dTQTHHN670XHDMCvMomWfP4EM9jYe7PIC3p/alwjJ1vVmpvuyGJer cXNU8FFyXUMTWPaRC6Hx2J0dcqE2PQpiR4mbBhN1pnaStxyVP8d4I+GpIoXY/luKXS/qo/s0Nya ylPhw5BJWFIS1Jcm2RVifqLYacarsKi8MttVgtNhX8k6e4DYxEtff2QUzKhSdhw+4ArQYnZzf64 Zo95zdLeVDemM5jpGtaVJJRTPkZ0zmV5rncRHPQZOVJJVFAxeMDLK2BTzEoDYDiBe0nWlLoiXj/ mGYihRn5Uj5tlEi4ZPAHDh+OTMWI0x0LRbTvpma379YhUn1O9za6Qt6rh9IdtYUPeTvrG X-Received: by 2002:a05:690e:128a:b0:650:1cf8:f608 with SMTP id 956f58d0204a3-65310a62a92mr28809853d50.45.1777013834437; Thu, 23 Apr 2026 23:57:14 -0700 (PDT) MIME-Version: 1.0 References: In-Reply-To: From: Pavel Stehule Date: Fri, 24 Apr 2026 08:56:36 +0200 X-Gm-Features: AQROBzD3B6GFk2f-NZfdQQtXvK7LjfotTnKqQCSDusB6gN1h7W4RgrPWP04wmJw Message-ID: Subject: Re: PoC - psql - emphases line with table name in verbose output To: Jim Jones Cc: PostgreSQL Hackers Content-Type: multipart/alternative; boundary="0000000000005cd68006502f4602" List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --0000000000005cd68006502f4602 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Hi =C4=8Dt 23. 4. 2026 v 17:17 odes=C3=ADlatel Jim Jones napsal: > Hi Pavel > > On 14/04/2026 05:42, Pavel Stehule wrote: > > rebase, new commit message and minor cleaning > Thanks for the patch! > > I tested the patch and setting PG_COLOR highlights the INFO messages. > > A few observations: > > =3D=3D string matching is locale-fragile =3D=3D > > Since the code relies on these fixed strings ... > > if (level =3D=3D PG_LOG_INFO && sgr_info_command && > (strncmp(buf, "INFO: vacuuming", strlen("INFO: vacuuming")) =3D=3D 0 = || > strncmp(buf, "INFO: repacking", strlen("INFO: repacking")) =3D=3D 0 = || > strncmp(buf, "INFO: analyzing", strlen("INFO: analyzing")) =3D=3D 0)= ) > > .. the conditions only work if lc_messages is set to English. For > instance, in German you get a different string, which means that > highlighting won't work: > > $ psql postgres -c "VACUUM VERBOSE pg_class;" 2>&1 | grep INFO > INFO: Vacuum von =C2=BBpostgres.pg_catalog.pg_class=C2=AB > INFO: beende Vacuum der Tabelle =C2=BBpostgres.pg_catalog.pg_class=C2=AB= : > Index-Scans: 0 > > $ psql postgres -c "ANALYSE VERBOSE pg_class;" 2>&1 | grep INFO > INFO: analysiere =C2=BBpg_catalog.pg_class=C2=AB > INFO: =C2=BBpg_class=C2=AB: 15 von 15 Seiten gelesen, enthalten 452 lebe= nde > Zeilen und 0 tote Zeilen; 452 Zeilen in Stichprobe, sch=C3=A4tzungsweise = 452 > Zeilen insgesamt > INFO: finished analyzing table "postgres.pg_catalog.pg_class" > > =3D=3D fixed command list =3D=3D > > Future verbose operations, if not added to this list, would silently get > no highlighting. > > I'm wondering if it is possible to achieve it (locale-agnostic) only for > certain commands without touching the code on the server side. Only by > checking strings it'll be difficult to identify which INFO messages to > highlight. > I am afraid this is the end of this direction. :-/ Please, can you check the functionality (only in english). I am interested if this is just helpful and if it makes sense to continue in this feature. Unfortunately, there are not too many possibilities about possible formats, colors in terminals (that can work mostly everywhere). I don't think it is possible to implement this without communication protocol enhancement. And if we will do this, the next question is if we cannot use this for some more complex information about the executed command. For example - I thought about the possibility of teaching psql to read progress stat tables - so can be nice, if the server can send some information to client - maybe pgstat_progres_update can send INFO like - "emphasize: nextinfo, pid: xxxx, progress table: pg_stat_vacuum, commandtype: vacuum, .... Maybe a different approach - instead of a plain text message, we can send messages of this type in client side parsable format - if I am not wrong, we are able to parse json on client side. json is still readable for humans for old clients. On the client side we decide what and how we will display. This can be more generic than just for VERBOSE mode of ANALYZE, VACUUM or REINDEX. some like elog(INFO_CLIENT, '{ "cmdtag": "VACUUM", "state":"started", "progress_tab": "pg_stat_progress_vacuum", "table_name": "yyy", "schema_name":"xxx", ...) elog(INFO_CLIENT, '{"cmdatag": "VACUUM", "state":"finished", "pages_removed": 0, "pages_ ... I don't see some simple and nice solution at this moment. Maybe just using new line after INFO with details so results can looks like INFO: vacuuming "postgres.pg_catalog.pg_class" INFO: finished vacuuming "postgres.pg_catalog.pg_class": index scans: 0 pages: 0 removed, 15 remain, 15 scanned (100.00% of total), 0 eagerly scanned tuples: 0 removed, 452 remain, 0 are dead but not yet removable removable cutoff: 701, which was 0 XIDs old when operation ended frozen: 0 pages from table (0.00% of total) had 0 tuples frozen visibility map: 0 pages set all-visible, 0 pages set all-frozen (0 were all-visible) index scan not needed: 0 pages from table (0.00% of total) had 0 dead item identifiers removed avg read rate: 0.000 MB/s, avg write rate: 0.000 MB/s buffer usage: 75 hits, 0 reads, 0 dirtied WAL usage: 0 records, 0 full page images, 0 bytes, 0 full page image bytes, 0 buffers full memory usage: dead item storage 0.02 MB accumulated across 0 resets (limit 64.00 MB each) system usage: CPU: user: 0.00 s, system: 0.00 s, elapsed: 0.00 s INFO: vacuuming "postgres.pg_catalog.pg_proc" INFO: finished vacuuming "postgres.pg_catalog.pg_proc": index scans: 0 pages: 0 removed, 101 remain, 1 scanned (0.99% of total), 0 eagerly scanned tuples: 0 removed, 3437 remain, 0 are dead but not yet removable removable cutoff: 701, which was 0 XIDs old when operation ended new relfrozenxid: 701, which is 17 XIDs ahead of previous value frozen: 0 pages from table (0.00% of total) had 0 tuples frozen visibility map: 0 pages set all-visible, 0 pages set all-frozen (0 were all-visible) index scan not needed: 0 pages from table (0.00% of total) had 0 dead item identifiers removed avg read rate: 4.534 MB/s, avg write rate: 1.133 MB/s buffer usage: 15 hits, 4 reads, 1 dirtied WAL usage: 1 records, 1 full page images, 5871 bytes, 5752 full page image bytes, 0 buffers full memory usage: dead item storage 0.02 MB accumulated across 0 resets (limit 64.00 MB each) system usage: CPU: user: 0.00 s, system: 0.00 s, elapsed: 0.00 s INFO: vacuuming "postgres.pg_toast.pg_toast_1255" INFO: finished vacuuming "postgres.pg_toast.pg_toast_1255": index scans: 0 pages: 0 removed, 2 remain, 2 scanned (100.00% of total), 0 eagerly scanned tuples: 0 removed, 7 remain, 0 are dead but not yet removable removable cutoff: 701, which was 0 XIDs old when operation ended new relfrozenxid: 701, which is 17 XIDs ahead of previous value frozen: 0 pages from table (0.00% of total) had 0 tuples frozen visibility map: 0 pages set all-visible, 0 pages set all-frozen (0 were all-visible) index scan not needed: 0 pages from table (0.00% of total) had 0 dead item identifiers removed avg read rate: 19.462 MB/s, avg write rate: 2.780 MB/s buffer usage: 36 hits, 7 reads, 1 dirtied WAL usage: 1 records, 1 full page images, 4255 bytes, 4136 full page image bytes, 0 buffers full memory usage: dead item storage 0.02 MB accumulated across 0 resets (limit 64.00 MB each) system usage: CPU: user: 0.00 s, system: 0.00 s, elapsed: 0.00 s This is small change and maybe it can be enough Regards Pavel > Thanks! > > Best, Jim > > --0000000000005cd68006502f4602 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
Hi

=C4=8Dt 23. 4. 20= 26 v=C2=A017:17 odes=C3=ADlatel Jim Jones <jim.jones@uni-muenster.de> napsal:=
Hi Pavel

On 14/04/2026 05:42, Pavel Stehule wrote:
> rebase, new commit message and minor cleaning
Thanks for the patch!

I tested the patch and setting PG_COLOR highlights the INFO messages.

A few observations:

=3D=3D string matching is locale-fragile =3D=3D

Since the code relies on these fixed strings ...

if (level =3D=3D PG_LOG_INFO && sgr_info_command &&
=C2=A0 (strncmp(buf, "INFO:=C2=A0 vacuuming", strlen("INFO:= =C2=A0 vacuuming")) =3D=3D 0 ||
=C2=A0 =C2=A0strncmp(buf, "INFO:=C2=A0 repacking", strlen("I= NFO:=C2=A0 repacking")) =3D=3D 0 ||
=C2=A0 =C2=A0strncmp(buf, "INFO:=C2=A0 analyzing", strlen("I= NFO:=C2=A0 analyzing")) =3D=3D 0))

.. the conditions only work if lc_messages is set to English. For
instance, in German you get a different string, which means that
highlighting won't work:

$ psql postgres -c "VACUUM VERBOSE pg_class;" 2>&1 | grep = INFO
INFO:=C2=A0 Vacuum von =C2=BBpostgres.pg_catalog.pg_class=C2=AB
INFO:=C2=A0 beende Vacuum der Tabelle =C2=BBpostgres.pg_catalog.pg_class=C2= =AB:
Index-Scans: 0

$ psql postgres -c "ANALYSE VERBOSE pg_class;" 2>&1 | grep= INFO
INFO:=C2=A0 analysiere =C2=BBpg_catalog.pg_class=C2=AB
INFO:=C2=A0 =C2=BBpg_class=C2=AB: 15 von 15 Seiten gelesen, enthalten 452 l= ebende
Zeilen und 0 tote Zeilen; 452 Zeilen in Stichprobe, sch=C3=A4tzungsweise 45= 2
Zeilen insgesamt
INFO:=C2=A0 finished analyzing table "postgres.pg_catalog.pg_class&quo= t;

=3D=3D fixed command list =3D=3D

Future verbose operations, if not added to this list, would silently get no highlighting.

I'm wondering if it is possible to achieve it (locale-agnostic) only fo= r
certain commands without touching the code on the server side. Only by
checking strings it'll be difficult to identify which INFO messages to<= br> highlight.

I am afraid this is the end = of this direction. :-/=C2=A0

Please, can you check= the functionality (only in english). I am interested if this is just helpf= ul and if it makes sense to continue in this feature. Unfortunately, there = are not too many possibilities about possible formats, colors in terminals = (that can work mostly everywhere).=C2=A0

I don't think it is possible to implement this without=C2=A0 co= mmunication protocol enhancement. And if we will do this, the next question= is if we cannot use this for some more complex information about the execu= ted command.

For exampl= e - I thought about the possibility of teaching psql to read progress stat = tables - so can be nice, if the server can send some information to client = - maybe pgstat_progres_update can send INFO=C2=A0

= like - "emphasize: nextinfo, pid: xxxx, progress table: pg_stat_vacuum= , commandtype: vacuum, ....

Maybe a different appr= oach=C2=A0- instead of a plain text message, we can send messages of this t= ype in client side parsable format - if I am not wrong, we are able to pars= e json on client side. json is still readable for humans for old clients. O= n the client side we decide what and how we will display. This can be more = generic than just for VERBOSE mode of ANALYZE, VACUUM or REINDEX.

some like

elog(INFO_CLIENT, '{= "cmdtag": "VACUUM", "state":"started&qu= ot;, "progress_tab": "pg_stat_progress_vacuum", "t= able_name": "yyy", "schema_name":"xxx", = ...)

elog(INFO_CLIENT, '{"cmdatag": = "VACUUM", "state":"finished", "pages_rem= oved": 0, "pages_ ...

I don't see so= me simple and nice solution at this moment. Maybe just using new line after= INFO with details

so results can looks like
=

INFO: =C2=A0vacuuming "postgres.pg_catalog.pg_clas= s"
INFO: =C2=A0finished vacuuming "postgres.pg_catalog.pg_clas= s": index scans: 0
pages: 0 removed, 15 remain, 15 scanned (100.00%= of total), 0 eagerly scanned
tuples: 0 removed, 452 remain, 0 are dead = but not yet removable
removable cutoff: 701, which was 0 XIDs old when o= peration ended
frozen: 0 pages from table (0.00% of total) had 0 tuples = frozen
visibility map: 0 pages set all-visible, 0 pages set all-frozen (= 0 were all-visible)
index scan not needed: 0 pages from table (0.00% of = total) had 0 dead item identifiers removed
avg read rate: 0.000 MB/s, av= g write rate: 0.000 MB/s
buffer usage: 75 hits, 0 reads, 0 dirtied
WA= L usage: 0 records, 0 full page images, 0 bytes, 0 full page image bytes, 0= buffers full
memory usage: dead item storage 0.02 MB accumulated across= 0 resets (limit 64.00 MB each)
system usage: CPU: user: 0.00 s, system:= 0.00 s, elapsed: 0.00 s

INFO: =C2=A0vacuuming "postgres.pg_cat= alog.pg_proc"
INFO: =C2=A0finished vacuuming "postgres.pg_cata= log.pg_proc": index scans: 0
pages: 0 removed, 101 remain, 1 scanne= d (0.99% of total), 0 eagerly scanned
tuples: 0 removed, 3437 remain, 0 = are dead but not yet removable
removable cutoff: 701, which was 0 XIDs o= ld when operation ended
new relfrozenxid: 701, which is 17 XIDs ahead of= previous value
frozen: 0 pages from table (0.00% of total) had 0 tuples= frozen
visibility map: 0 pages set all-visible, 0 pages set all-frozen = (0 were all-visible)
index scan not needed: 0 pages from table (0.00% of= total) had 0 dead item identifiers removed
avg read rate: 4.534 MB/s, a= vg write rate: 1.133 MB/s
buffer usage: 15 hits, 4 reads, 1 dirtied
W= AL usage: 1 records, 1 full page images, 5871 bytes, 5752 full page image b= ytes, 0 buffers full
memory usage: dead item storage 0.02 MB accumulated= across 0 resets (limit 64.00 MB each)
system usage: CPU: user: 0.00 s, = system: 0.00 s, elapsed: 0.00 s

INFO: =C2=A0vacuuming "postgres= .pg_toast.pg_toast_1255"
INFO: =C2=A0finished vacuuming "postg= res.pg_toast.pg_toast_1255": index scans: 0
pages: 0 removed, 2 rem= ain, 2 scanned (100.00% of total), 0 eagerly scanned
tuples: 0 removed, = 7 remain, 0 are dead but not yet removable
removable cutoff: 701, which = was 0 XIDs old when operation ended
new relfrozenxid: 701, which is 17 X= IDs ahead of previous value
frozen: 0 pages from table (0.00% of total) = had 0 tuples frozen
visibility map: 0 pages set all-visible, 0 pages set= all-frozen (0 were all-visible)
index scan not needed: 0 pages from tab= le (0.00% of total) had 0 dead item identifiers removed
avg read rate: 1= 9.462 MB/s, avg write rate: 2.780 MB/s
buffer usage: 36 hits, 7 reads, 1= dirtied
WAL usage: 1 records, 1 full page images, 4255 bytes, 4136 full= page image bytes, 0 buffers full
memory usage: dead item storage 0.02 M= B accumulated across 0 resets (limit 64.00 MB each)
system usage: CPU: u= ser: 0.00 s, system: 0.00 s, elapsed: 0.00 s

This = is small change and maybe it can be enough=C2=A0

R= egards

Pavel


Thanks!

Best, Jim

--0000000000005cd68006502f4602--