feat(panel): lay a delivery's log lines out as a table
test / test (push) Has been cancelled

The lines came out as one block of preformatted text, which is what the
system log page does with a tail of mail.log — right there, where the
lines are unrelated to each other and the block is the log itself. Here
they are one message's six or seven lines, and what is read off them is
the pace: the second between the connection and the banner, the ten
between DATA and the reply. Run together, every line began with a
different-width stamp and none of those numbers lined up.

So they are two columns now, when and what, the same shape the send log
itself has. logtail.SplitTimestamp takes the stamp off the head of a
line: postlogd's format, which is what this server writes, and syslog's
traditional one for a deployment that routes the log through syslogd
instead. The stamp loses its microseconds and its offset — five decimal
places are the widest part of the column and the least worth reading —
but is not converted, so the page shows the log's own wall clock rather
than a claim about which zone it was in.

A line whose head is not a stamp either parser recognises keeps its whole
text in the second column and leaves the first empty. The format is the
log's, not ours; a line we cannot split is a line we must not drop, and
the test says so.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
mixeme
2026-08-08 10:22:29 +03:00
parent 928d065d13
commit 99a0483226
7 changed files with 187 additions and 21 deletions
+6 -1
View File
@@ -10,7 +10,12 @@ Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); version
- A **Delivery log** on each delivery's page (`/deliveries/{id}`): the
`mail.log` lines Postfix wrote about that message, oldest first — the
connection to the receiving server, its reply, and the status that reply was
filed as. The queue id was printed on this page as something to go and search
filed as. It is a table of two columns, when and what, so the seconds between
the connection and the reply line up down one edge; the timestamp is the
log's own wall clock without its microseconds and offset, and a line whose
head is not a timestamp keeps its whole text under *Message*
(`logtail.SplitTimestamp`, which reads both postlogd's format and syslog's).
The queue id was printed on this page as something to go and search
the system log for by hand; the search is done for the operator instead
(`logtail.QueueLines`). The read is a bounded tail of the current log and
matches only lines carrying this message's queue id, anchored so a shorter id