Skip to content

Commit 1b27201

Browse files
committed
[format] add a postgres log format
1 parent bd93e50 commit 1b27201

17 files changed

Lines changed: 270 additions & 48 deletions

NEWS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ Features:
88
* Removed dependency on ncurses during the build. The terminfo
99
files are still used during runtime, but fallback terminfo
1010
files for common terminals are included in the binary.
11+
* Added the postgres_log format.
1112

1213
Interface changes:
1314
* If all the log messages in the LOG view are hidden, a notice

src/formats/formats.am

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ FORMAT_FILES = \
3434
$(srcdir)/%reldir%/page_log.json \
3535
$(srcdir)/%reldir%/pcap_log.json \
3636
$(srcdir)/%reldir%/pino_log.json \
37+
$(srcdir)/%reldir%/postgres_log.json \
3738
$(srcdir)/%reldir%/procstate_log.json \
3839
$(srcdir)/%reldir%/proxifier_log.json \
3940
$(srcdir)/%reldir%/rails_log.json \

src/formats/postgres_log.json

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{
2+
"$schema": "https://lnav.org/schemas/format-v1.schema.json",
3+
"postgres_log": {
4+
"description": "Format file generated from regex101 entry -- https://regex101.com/r/pwVch2/1",
5+
"regex": {
6+
"std": {
7+
"pattern": "(?<timestamp>^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}\\.\\d{3} \\S+) \\[(?<pid>\\d+)\\] (?<level>DEBUG\\d|INFO|NOTICE|WARNING|ERROR|LOG|FATAL|PANIC|STATEMENT):\\s+(?<body>.*)$"
8+
}
9+
},
10+
"value": {
11+
"level": {
12+
"kind": "string"
13+
},
14+
"pid": {
15+
"kind": "string"
16+
},
17+
"timestamp": {
18+
"kind": "string"
19+
}
20+
},
21+
"sample": [
22+
{
23+
"line": "2025-08-13 01:45:01.127 PDT [12347] LOG: database system was shut down at 2025-08-13 01:44:58 PDT"
24+
}
25+
]
26+
}
27+
}

src/ptimec.cc

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,21 @@ main(int argc, char* argv[])
134134

135135
switch (arg[index + 1]) {
136136
case 'a':
137+
if (arg[index + 2]) {
138+
printf(
139+
" if (!ptime_upto('%s', str, off_inout, "
140+
"len)) "
141+
"return false;\n",
142+
escape_char(arg[index + 2]));
143+
} else {
144+
printf(
145+
" if (!ptime_upto_end(dst, str, "
146+
"off_inout, "
147+
"len)) "
148+
"return false;\n");
149+
}
150+
index += 1;
151+
break;
137152
case 'Z':
138153
if (arg[index + 2]) {
139154
printf(

src/ptimec.hh

Lines changed: 9 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1022,28 +1022,20 @@ ftime_y(char* dst, off_t& off_inout, ssize_t len, const struct exttm& tm)
10221022
PTIME_APPEND('0' + ((year / 1) % 10));
10231023
}
10241024

1025+
bool ptime_Z_to_gmtoff(exttm* dst,
1026+
const char* str,
1027+
off_t& off_inout,
1028+
ssize_t len);
1029+
10251030
inline bool
10261031
ptime_Z_upto(struct exttm* dst,
10271032
const char* str,
10281033
off_t& off_inout,
10291034
ssize_t len,
10301035
char term)
10311036
{
1032-
auto avail = len - off_inout;
1033-
1034-
if (avail >= 3 && str[off_inout + 0] == 'U' && str[off_inout + 1] == 'T'
1035-
&& str[off_inout + 2] == 'C')
1036-
{
1037-
PTIME_CONSUME(3, { dst->et_flags |= ETF_ZONE_SET | ETF_Z_IS_UTC; });
1038-
dst->et_gmtoff = 0;
1039-
return true;
1040-
}
1041-
if (avail >= 3 && str[off_inout + 0] == 'G' && str[off_inout + 1] == 'M'
1042-
&& str[off_inout + 2] == 'T')
1043-
{
1044-
PTIME_CONSUME(3, { dst->et_flags |= ETF_ZONE_SET | ETF_Z_IS_GMT; });
1045-
dst->et_gmtoff = 0;
1046-
return true;
1037+
if (!ptime_Z_to_gmtoff(dst, str, off_inout, len)) {
1038+
return false;
10471039
}
10481040

10491041
return ptime_upto(term, str, off_inout, len);
@@ -1055,21 +1047,8 @@ ptime_Z_upto_end(struct exttm* dst,
10551047
off_t& off_inout,
10561048
ssize_t len)
10571049
{
1058-
auto avail = len - off_inout;
1059-
1060-
if (avail >= 3 && str[off_inout + 0] == 'U' && str[off_inout + 1] == 'T'
1061-
&& str[off_inout + 2] == 'C')
1062-
{
1063-
PTIME_CONSUME(3, { dst->et_flags |= ETF_ZONE_SET | ETF_Z_IS_UTC; });
1064-
dst->et_gmtoff = 0;
1065-
return true;
1066-
}
1067-
if (avail >= 3 && str[off_inout + 0] == 'G' && str[off_inout + 1] == 'M'
1068-
&& str[off_inout + 2] == 'T')
1069-
{
1070-
PTIME_CONSUME(3, { dst->et_flags |= ETF_ZONE_SET | ETF_Z_IS_GMT; });
1071-
dst->et_gmtoff = 0;
1072-
return true;
1050+
if (!ptime_Z_to_gmtoff(dst, str, off_inout, len)) {
1051+
return false;
10731052
}
10741053

10751054
return ptime_upto_end(str, off_inout, len);

src/ptimec_rt.cc

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,118 @@ ptime_b_slow(struct exttm* dst, const char* str, off_t& off_inout, ssize_t len)
5454
return false;
5555
}
5656

57+
bool
58+
ptime_Z_to_gmtoff(exttm* dst, const char* str, off_t& off_inout, ssize_t len)
59+
{
60+
auto avail = len - off_inout;
61+
62+
if (avail < 3) {
63+
return false;
64+
}
65+
66+
auto zone_start = (unsigned char*) &str[off_inout];
67+
uint32_t zone_int = ABR_TO_INT(zone_start[0] & ~0x20UL,
68+
zone_start[1] & ~0x20UL,
69+
zone_start[2] & ~0x20UL);
70+
switch (zone_int) {
71+
case ABR_TO_INT('U', 'T', 'C'):
72+
PTIME_CONSUME(3, { dst->et_flags |= ETF_ZONE_SET | ETF_Z_IS_UTC; });
73+
dst->et_gmtoff = 0;
74+
break;
75+
case ABR_TO_INT('G', 'M', 'T'):
76+
PTIME_CONSUME(3, { dst->et_flags |= ETF_ZONE_SET | ETF_Z_IS_GMT; });
77+
dst->et_gmtoff = 0;
78+
break;
79+
case ABR_TO_INT('E', 'A', 'T'):
80+
PTIME_CONSUME(3, { dst->et_flags |= ETF_ZONE_SET; });
81+
dst->et_gmtoff = 3 * 60 * 60;
82+
break;
83+
case ABR_TO_INT('W', 'A', 'T'):
84+
PTIME_CONSUME(3, { dst->et_flags |= ETF_ZONE_SET; });
85+
dst->et_gmtoff = 1 * 60 * 60;
86+
break;
87+
case ABR_TO_INT('C', 'E', 'T'):
88+
PTIME_CONSUME(3, { dst->et_flags |= ETF_ZONE_SET; });
89+
dst->et_gmtoff = 1 * 60 * 60;
90+
break;
91+
case ABR_TO_INT('C', 'A', 'T'):
92+
PTIME_CONSUME(3, { dst->et_flags |= ETF_ZONE_SET; });
93+
dst->et_gmtoff = 2 * 60 * 60;
94+
break;
95+
case ABR_TO_INT('I', 'S', 'T'):
96+
PTIME_CONSUME(3, { dst->et_flags |= ETF_ZONE_SET; });
97+
dst->et_gmtoff = 5 * 60 * 60 + 30 * 60;
98+
break;
99+
case ABR_TO_INT('H', 'K', 'T'):
100+
PTIME_CONSUME(3, { dst->et_flags |= ETF_ZONE_SET; });
101+
dst->et_gmtoff = 8 * 60 * 60;
102+
break;
103+
case ABR_TO_INT('J', 'S', 'T'):
104+
PTIME_CONSUME(3, { dst->et_flags |= ETF_ZONE_SET; });
105+
dst->et_gmtoff = 9 * 60 * 60;
106+
break;
107+
case ABR_TO_INT('K', 'S', 'T'):
108+
PTIME_CONSUME(3, { dst->et_flags |= ETF_ZONE_SET; });
109+
dst->et_gmtoff = 9 * 60 * 60;
110+
break;
111+
case ABR_TO_INT('N', 'S', 'T'):
112+
PTIME_CONSUME(3, { dst->et_flags |= ETF_ZONE_SET; });
113+
dst->et_gmtoff = -3 * 60 * 60 + 30 * 60;
114+
break;
115+
case ABR_TO_INT('N', 'D', 'T'):
116+
PTIME_CONSUME(3, { dst->et_flags |= ETF_ZONE_SET; });
117+
dst->et_gmtoff = -2 * 60 * 60 + 30 * 60;
118+
break;
119+
case ABR_TO_INT('E', 'S', 'T'):
120+
PTIME_CONSUME(3, { dst->et_flags |= ETF_ZONE_SET; });
121+
dst->et_gmtoff = -5 * 60 * 60;
122+
break;
123+
case ABR_TO_INT('E', 'D', 'T'):
124+
PTIME_CONSUME(3, { dst->et_flags |= ETF_ZONE_SET; });
125+
dst->et_gmtoff = -4 * 60 * 60;
126+
break;
127+
case ABR_TO_INT('C', 'S', 'T'):
128+
PTIME_CONSUME(3, { dst->et_flags |= ETF_ZONE_SET; });
129+
dst->et_gmtoff = -6 * 60 * 60;
130+
break;
131+
case ABR_TO_INT('C', 'D', 'T'):
132+
PTIME_CONSUME(3, { dst->et_flags |= ETF_ZONE_SET; });
133+
dst->et_gmtoff = -5 * 60 * 60;
134+
break;
135+
case ABR_TO_INT('M', 'S', 'T'):
136+
PTIME_CONSUME(3, { dst->et_flags |= ETF_ZONE_SET; });
137+
dst->et_gmtoff = -7 * 60 * 60;
138+
break;
139+
case ABR_TO_INT('M', 'D', 'T'):
140+
PTIME_CONSUME(3, { dst->et_flags |= ETF_ZONE_SET; });
141+
dst->et_gmtoff = -6 * 60 * 60;
142+
break;
143+
case ABR_TO_INT('P', 'S', 'T'):
144+
PTIME_CONSUME(3, { dst->et_flags |= ETF_ZONE_SET; });
145+
dst->et_gmtoff = -8 * 60 * 60;
146+
break;
147+
case ABR_TO_INT('P', 'D', 'T'):
148+
PTIME_CONSUME(3, { dst->et_flags |= ETF_ZONE_SET; });
149+
dst->et_gmtoff = -7 * 60 * 60;
150+
break;
151+
case ABR_TO_INT('H', 'S', 'T'):
152+
PTIME_CONSUME(3, { dst->et_flags |= ETF_ZONE_SET; });
153+
dst->et_gmtoff = -10 * 60 * 60;
154+
break;
155+
case ABR_TO_INT('A', 'S', 'T'):
156+
PTIME_CONSUME(3, { dst->et_flags |= ETF_ZONE_SET; });
157+
dst->et_gmtoff = -4 * 60 * 60;
158+
break;
159+
case ABR_TO_INT('A', 'D', 'T'):
160+
PTIME_CONSUME(3, { dst->et_flags |= ETF_ZONE_SET; });
161+
dst->et_gmtoff = -3 * 60 * 60;
162+
break;
163+
default:
164+
return false;
165+
}
166+
return true;
167+
}
168+
57169
#define FMT_CASE(ch, c) \
58170
case ch: \
59171
if (!ptime_##c(dst, str, off, len)) \

src/relative_time.cc

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,25 @@ relative_time::from_str(string_fragment str)
348348
if (base_token == RTT_BEFORE) {
349349
retval.negate();
350350
}
351+
switch (token) {
352+
case RTT_YESTERDAY:
353+
case RTT_TODAY:
354+
if (!retval.rt_field[RTF_HOURS].is_set) {
355+
retval.rt_field[RTF_HOURS] = 0;
356+
}
357+
if (!retval.rt_field[RTF_MINUTES].is_set) {
358+
retval.rt_field[RTF_MINUTES] = 0;
359+
}
360+
if (!retval.rt_field[RTF_SECONDS].is_set) {
361+
retval.rt_field[RTF_SECONDS] = 0;
362+
}
363+
if (!retval.rt_field[RTF_MICROSECONDS].is_set) {
364+
retval.rt_field[RTF_MICROSECONDS] = 0;
365+
}
366+
break;
367+
default:
368+
break;
369+
}
351370
tm = retval.adjust(tm);
352371
base_token = RTT_INVALID;
353372

@@ -364,11 +383,6 @@ relative_time::from_str(string_fragment str)
364383
break;
365384
case RTT_YESTERDAY:
366385
retval.rt_field[RTF_DAYS].value -= 1;
367-
case RTT_TODAY:
368-
retval.rt_field[RTF_HOURS] = 0;
369-
retval.rt_field[RTF_MINUTES] = 0;
370-
retval.rt_field[RTF_SECONDS] = 0;
371-
retval.rt_field[RTF_MICROSECONDS] = 0;
372386
break;
373387
default:
374388
break;

test/expected/Makefile.am

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,8 @@ dist_noinst_DATA = \
438438
test_logfile.sh_6602faf7817c494c33e32da7ee95f13aa9210d01.out \
439439
test_logfile.sh_6e91affb9eb4f61e9073d62117cdb29d1e8c2230.err \
440440
test_logfile.sh_6e91affb9eb4f61e9073d62117cdb29d1e8c2230.out \
441+
test_logfile.sh_74590bc7d516f6a6b9191774ca98b3880658cf3f.err \
442+
test_logfile.sh_74590bc7d516f6a6b9191774ca98b3880658cf3f.out \
441443
test_logfile.sh_7c2e11488bccc59458b5775db4b90de964858259.err \
442444
test_logfile.sh_7c2e11488bccc59458b5775db4b90de964858259.out \
443445
test_logfile.sh_82d65f4dac07b1623f8202444d5b9144096e8243.err \
@@ -1402,6 +1404,8 @@ dist_noinst_DATA = \
14021404
test_sql.sh_9ceccab07fbf7130bffe3c201c710719e4a3e9af.out \
14031405
test_sql.sh_9e1d05b821822ee40e13fadb24ec558f4bfcff10.err \
14041406
test_sql.sh_9e1d05b821822ee40e13fadb24ec558f4bfcff10.out \
1407+
test_sql.sh_a3a5327348fc5f166fdc0c11d27f7039fcca238e.err \
1408+
test_sql.sh_a3a5327348fc5f166fdc0c11d27f7039fcca238e.out \
14051409
test_sql.sh_a6b68b9f0044d18e7fa8f9287ddc9110701edc33.err \
14061410
test_sql.sh_a6b68b9f0044d18e7fa8f9287ddc9110701edc33.out \
14071411
test_sql.sh_a7955e89791db9a252d8323436fabc51e2960731.err \

test/expected/test_logfile.sh_74590bc7d516f6a6b9191774ca98b3880658cf3f.err

Whitespace-only changes.
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
Aug 13 08:45:01 2025 -- 123
2+
Aug 13 08:45:01 2025 -- 123
3+
Aug 13 08:45:01 2025 -- 123
4+
Aug 13 08:45:01 2025 -- 125
5+
Aug 13 08:45:01 2025 -- 127
6+
Aug 13 08:45:01 2025 -- 130
7+
Aug 13 08:45:01 2025 -- 130
8+
Aug 13 08:46:10 2025 -- 567
9+
Aug 13 08:46:10 2025 -- 568
10+
Aug 13 08:46:10 2025 -- 568
11+
Aug 13 08:46:11 2025 -- 122
12+
Aug 13 08:46:11 2025 -- 122
13+
Aug 13 08:46:12 2025 -- 212
14+
Aug 13 08:46:12 2025 -- 212
15+
Aug 13 08:46:12 2025 -- 212
16+
Aug 13 08:47:03 2025 -- 904
17+
Aug 13 08:47:03 2025 -- 905
18+
Aug 13 08:47:04 2025 -- 010
19+
Aug 13 08:47:04 2025 -- 010
20+
Aug 13 08:47:05 2025 -- 312
21+
Aug 13 08:47:05 2025 -- 312
22+
Aug 13 08:47:08 2025 -- 444
23+
Aug 13 08:47:08 2025 -- 444
24+
Aug 13 08:50:01 2025 -- 999
25+
Aug 13 08:50:01 2025 -- 999
26+
Aug 13 08:50:02 2025 -- 003
27+
Aug 13 08:50:02 2025 -- 004
28+
Aug 13 08:50:02 2025 -- 010

0 commit comments

Comments
 (0)