Util-Linux package development
 help / color / mirror / Atom feed
* Re: [PATCH] uuidd: add cont_clock persistence
From: Karel Zak @ 2024-01-04 12:12 UTC (permalink / raw)
  To: Michael Trapp; +Cc: util-linux
In-Reply-To: <20231215221829.46932-1-michael.trapp@sap.com>

On Fri, Dec 15, 2023 at 11:18:29PM +0100, Michael Trapp wrote:
> cont_clock requires a correct time setup and therefore it
> must be possible to detect a step back between uuidd starts.
> 
> Reserving the next 10 seconds in clock-cont.txt is sufficient
> and should not have a noticeable performance impact.
> It will also provide the possibility to start with the clock_reg
> from the previous session when the system was rebooted.
> 
> Whith that, the early cont_clock initialization in uuidd
> should be removed because writing the cont_clock persitence
> when -C was not set is useless and might be confusing.

Hi Michael, 

that is an interesting idea; I have only a few pedantic notes ;-)

> ---
>  libuuid/src/gen_uuid.c | 78 ++++++++++++++++++++++++++++++++++++------
>  libuuid/src/uuidP.h    |  1 +
>  misc-utils/uuidd.c     |  9 -----
>  3 files changed, 69 insertions(+), 19 deletions(-)
> 
> diff --git a/libuuid/src/gen_uuid.c b/libuuid/src/gen_uuid.c
> index 826cd2245..94b99f1bd 100644
> --- a/libuuid/src/gen_uuid.c
> +++ b/libuuid/src/gen_uuid.c
> @@ -355,44 +355,102 @@ static uint64_t get_clock_counter(void)
>  /*
>   * Get continuous clock value.
>   *
> - * Return -1 if there is no further clock counter available,
> + * Return -1 if there is no valid clock counter available,
>   * otherwise return 0.
>   *
>   * This implementation doesn't deliver clock counters based on
>   * the current time because last_clock_reg is only incremented
>   * by the number of requested UUIDs.
>   * max_clock_offset is used to limit the offset of last_clock_reg.
> + * used/reserved UUIDs are written to LIBUUID_CLOCK_CONT_FILE.
>   */
>  static int get_clock_cont(uint32_t *clock_high,
>  			  uint32_t *clock_low,
>  			  int num,
>  			  uint32_t max_clock_offset)
>  {
> -	/* 100ns based time offset according to RFC 4122. 4.1.4. */
> +	/* all 64bit clock_reg values in this function represent '100ns ticks'
> +         * due to the combination of tv_usec + MAX_ADJUSTMENT */
> +
> +	enum { fd_init = -2, fd_error = -1 };

In the code (below) the enum items seems like variables, a little bit
confusing. It would be better use upper-case, STATE_FD_INIT, STATE_FD_ERROR.

> +	/* time offset according to RFC 4122. 4.1.4. */
>  	const uint64_t reg_offset = (((uint64_t) 0x01B21DD2) << 32) + 0x13814000;
>  	static uint64_t last_clock_reg = 0;
> -	uint64_t clock_reg;
> +	static uint64_t saved_clock_reg = 0;
> +	static int state_fd = fd_init;
> +	static FILE *state_f = NULL;
> +	uint64_t clock_reg, next_clock_reg;
>  
> -	if (last_clock_reg == 0)
> -		last_clock_reg = get_clock_counter();
> +	if (state_fd == fd_error)
> +		return -1;
>  
>  	clock_reg = get_clock_counter();
> +
> +	if (state_fd == fd_init) {
> +		mode_t save_umask;
> +		struct stat st;
> +
> +		save_umask = umask(0);
> +		state_fd = open(LIBUUID_CLOCK_CONT_FILE, O_RDWR|O_CREAT|O_CLOEXEC, 0660);
> +		(void) umask(save_umask);
> +		if (state_fd == fd_error)
> +			return -1;
> +
> +		state_f = fdopen(state_fd, "r+" UL_CLOEXECSTR);
> +		if (!state_f)
> +			goto error;

Seems it duplicates code from get_clock(), what about introduce a generic

    state_fd_init(LIBUUID_CLOCK_CONT_FILE, &state_fd, &state_f);

and use the same in get_clock() for LIBUUID_CLOCK_FILE?

> +		if (fstat(state_fd, &st))
> +			goto error;
> +
> +		if (st.st_size) {
> +			rewind(state_f);
> +			if (fscanf(state_f, "cont: %lu\n", &last_clock_reg) != 1)
> +				goto error;
> +		} else
> +			last_clock_reg = clock_reg;

For LIBUUID_CLOCK_FILE we use flock(), I guess it's unnecessary for
LIBUUID_CLOCK_CONT_FILE as we assume only one uuidd instance, right?

Thanks!
 Karel


-- 
 Karel Zak  <kzak@redhat.com>
 http://karelzak.blogspot.com


^ permalink raw reply

* Re: [PATCH] util-linux-demsg-issue-2666-patch-1.patch
From: Edward Chron @ 2024-01-03 14:51 UTC (permalink / raw)
  To: Karel Zak; +Cc: Edward Chron, util-linux, colona
In-Reply-To: <20240102115815.av7ges3f47m6bciq@ws.net.home>

Thank you Karel, I will fix this test issue and resubmit the patch series.

On Tue, Jan 2, 2024 at 3:58 AM Karel Zak <kzak@redhat.com> wrote:
>
> On Sun, Dec 31, 2023 at 10:33:36AM -0800, Edward Chron wrote:
> > +     if (*rec->caller_id) {
> > +             if (ctl->json) {
> > +                     ul_jsonwrt_value_s(&ctl->jfmt, "caller", rec->caller_id);
> > +             } else {
> > +                     char cidbuf[PID_CHARS_MAX+3] = {'\0'};
> > +
> > +                     sprintf(cidbuf, "[%*s] ",
> > +                             (char)ctl->caller_id_size, rec->caller_id);
> > +                     ctl->indent += strnlen(cidbuf, sizeof(cidbuf));
> > +                     fputs(cidbuf, stdout);
> > +             }
> > +     }
>
> The variable width (ctl->caller_id_size) of caller ID makes your
> regression test fragile, see:
>
> https://github.com/util-linux/util-linux/actions/runs/7384780996/job/20088287790?pr=2647
>
> --- /home/runner/work/util-linux/util-linux/tests/expected/dmesg/cid-limit      2024-01-02 10:34:02.893193174 +0000
> +++ /home/runner/work/util-linux/util-linux/tests/output/dmesg/cid-limit        2024-01-02 10:38:29.209015303 +0000
> @@ -1,4 +1,4 @@
> -[    1.000000] [    T1] example[1]
> -[    8.000000] [    T2] example[2]
> -[   27.000000] [    T3] example[3]
> -[   64.000000] [    T4] example[4]
> +[    1.000000] [   T1] example[1]
> +[    8.000000] [   T2] example[2]
> +[   27.000000] [   T3] example[3]
> +[   64.000000] [   T4] example[4]
>
>
> I see two possible ways to fix it:
>
>  * "normalize" the output in the tests -- just use sed(1) to
>    remove all the blanks space "[    T4]" to "[T4]", so the output
>    will be always the same
>
>  * or use fixed width for the caller_id in dmesg.c
>
>
>     Karel
>
> --
>  Karel Zak  <kzak@redhat.com>
>  http://karelzak.blogspot.com
>

^ permalink raw reply

* Re: [PATCH] util-linux-demsg-issue-2666-patch-1.patch
From: Karel Zak @ 2024-01-02 11:58 UTC (permalink / raw)
  To: Edward Chron; +Cc: util-linux, colona, echron
In-Reply-To: <20231231183336.18934-1-echron@arista.com>

On Sun, Dec 31, 2023 at 10:33:36AM -0800, Edward Chron wrote:
> +	if (*rec->caller_id) {
> +		if (ctl->json) {
> +			ul_jsonwrt_value_s(&ctl->jfmt, "caller", rec->caller_id);
> +		} else {
> +			char cidbuf[PID_CHARS_MAX+3] = {'\0'};
> +
> +			sprintf(cidbuf, "[%*s] ",
> +				(char)ctl->caller_id_size, rec->caller_id);
> +			ctl->indent += strnlen(cidbuf, sizeof(cidbuf));
> +			fputs(cidbuf, stdout);
> +		}
> +	}

The variable width (ctl->caller_id_size) of caller ID makes your
regression test fragile, see:

https://github.com/util-linux/util-linux/actions/runs/7384780996/job/20088287790?pr=2647

--- /home/runner/work/util-linux/util-linux/tests/expected/dmesg/cid-limit	2024-01-02 10:34:02.893193174 +0000
+++ /home/runner/work/util-linux/util-linux/tests/output/dmesg/cid-limit	2024-01-02 10:38:29.209015303 +0000
@@ -1,4 +1,4 @@
-[    1.000000] [    T1] example[1]
-[    8.000000] [    T2] example[2]
-[   27.000000] [    T3] example[3]
-[   64.000000] [    T4] example[4]
+[    1.000000] [   T1] example[1]
+[    8.000000] [   T2] example[2]
+[   27.000000] [   T3] example[3]
+[   64.000000] [   T4] example[4]


I see two possible ways to fix it:

 * "normalize" the output in the tests -- just use sed(1) to
   remove all the blanks space "[    T4]" to "[T4]", so the output
   will be always the same

 * or use fixed width for the caller_id in dmesg.c


    Karel

-- 
 Karel Zak  <kzak@redhat.com>
 http://karelzak.blogspot.com


^ permalink raw reply

* Re: [PATCH] util-linux-demsg-issue-2666-patch-1.patch
From: Karel Zak @ 2024-01-02 10:35 UTC (permalink / raw)
  To: Edward Chron; +Cc: util-linux, colona, echron
In-Reply-To: <20231231183336.18934-1-echron@arista.com>

On Sun, Dec 31, 2023 at 10:33:36AM -0800, Edward Chron wrote:
> util-linux/sys-utils dmesg add PRINTK_CALLER support
> Submission to Project: util-linux
> Open Incident: #2609 at github.com/util-linux/util-linux/issues/2609
> Component: util-linux/sys-utils
> File: dmesg.c
> Code level patch applied against: 2.39.3 - latest code pulled from
>            git.github.com:util-linux/util-linux.git
> Revision: #1 on 2023/12/08 per Review from Karel Zak
> Revision: #2 on 2023/12/12 Adjust line offsets for master update and
>                            Add caller_id_size init to dmesg -K
> Revision: #3 on 2023/12/12 Use of sizeof for cidbuf and limit search
>                            for caller_id to dmesg prefix to msg text
> Revision: #4 on 2023/12/15 Ensure SYSLOG and kmsg inputs have
>                            caller_id_size set appropriately
> Revision: #5 on 2023/12/24 Make caller_id width consistent with
>                            makedumpfile
> Revision: #6 on 2023/12/30 Use updated test naming convention
>                            Include expected results for new tests

https://github.com/util-linux/util-linux/pull/2647 updated with all
your latest 4 patches.

 Karel


-- 
 Karel Zak  <kzak@redhat.com>
 http://karelzak.blogspot.com


^ permalink raw reply

* [PATCH] util-linux-demsg-issue-2666-patch-4.patch
From: Edward Chron @ 2023-12-31 18:36 UTC (permalink / raw)
  To: util-linux; +Cc: colona, echron, echron

Submission to Project: util-linux
Open Incident: #2663 at github.com/util-linux/util-linux/issues/2663
Component: util-linux/sys-utils
Files: tests/ts/dmesg kmsg interface files and related expected files
Testing on Fedora 39 with Linux-6.6.6 Kernel and CONFIG_PRINTK_CALLER
config option set.
Patch tested and generated with the latest util-linux code pulled.
Revision: no caller optional fields in any of the kmsg-input entries
Revision: retrofitted to apply on top of Issue: #2609 and Issue #2637
This is patch 2 of 2 (second in the series)
A second patch needed to hold 2nd binary file (git binary files issue)

This patch is needed because git format does not produce correct
output if two binary files are included in the same patch.
So adding the second binary file in a second patch to resolve the
issue.

Signed-off-by: Ivan Delalande <colona@arista.com>
Signed-off-by: Edward Chron <echron@arista.com>
---
 tests/ts/dmesg/kmsg-newlines | Bin 0 -> 182 bytes
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 tests/ts/dmesg/kmsg-newlines

diff --git a/tests/ts/dmesg/kmsg-newlines b/tests/ts/dmesg/kmsg-newlines
new file mode 100644
index 0000000000000000000000000000000000000000..a1f96c562ec4da27e24117908a7a1e78f10f9f97
GIT binary patch
literal 182
zcmZ9GQ3`-C3`6(bQ+R*~-JJO0c`6EOVNL{3?>7CJf##!mg!EuoE<!u5%P!3=LCM(k
zhpQ9ag)&0MF&uoI#!D$*CJr(kqr>n+<{(0`_@?1)ORQ&j*x!yx&p^cr8s&&zH$C?_
BGAjT8

literal 0
HcmV?d00001

-- 
2.43.0

^ permalink raw reply

* [PATCH] util-linux-demsg-issue-2666-patch-3.patch
From: Edward Chron @ 2023-12-31 18:35 UTC (permalink / raw)
  To: util-linux; +Cc: colona, echron, echron

Submission to Project: util-linux
Open Incident: #2663 at github.com/util-linux/util-linux/issues/2663
Component: util-linux/sys-utils
Files: tests/ts/dmesg kmsg interface files and related expected files
Testing on Fedora 39 with Linux-6.6.6 Kernel and CONFIG_PRINTK_CALLER
config option set.
Patch tested and generated with the latest util-linux code pulled.
Revision: no caller optional fields in any of the kmsg-input entries
Revision: retrofitted to apply on top of Issue: #2609 and Issue #2637
This is patch 1 of 2 (first in the series)
Second patch needed to hold second binary file (git binary files issue)

For issue #2609 Thomas and Zak pointed out the we need tests to verify
that the dmesg command works correctly and to allow us to compare the
results from PRINTK_CALLER id field tests provided by #2609 with the
standard (syslog interface) dmesg tests.

Except for a kmsg json test that Thomas added recently we don't have
basic dmesg tests for the kmsg interface to compare results against.

We added tests for the dmesg SYSLOG PRINTK_CALLER id interface so we
can compare against those tests.
Those tests were submitted with Issue #2637.

Those tests were created before Thomas added the new dmesg kmsg test
and I will rename those tests to match the naming scheme that Thomas
is using for tests that are specific to syslog interface and specific
to kmsg interface.

Issue #2609 introduces dmesg kmsg interface support for the PRINTK_CALLER
id field and provides tests to compare against the SYSLOG interface tests
added by #2637. Those tests also need to renamed to be consistent Thomas's
test naming scheme.

Here we've created tests for the dmesg kmsg interface following the
existing test structure for dmesg tests.

With the addition of this set of tests, we have tests for SYSLOG and
SYSLOG PRINTK_CALLER id field to compare against the kmsg and kmsg
PRINTK_CALLER id field tests.

Currently the only kmsg interface specific test that exists is the
kmsg-file test that Thomas added to test the dmesg kmsg interface for
json support.

Thomas also added code for the -K file interface to process dmesg ksmg
interface files for testing so we utilize that code here and add to it.

The kmsg-input file is expanded to provide statements and fields to
completely test the kmsg interface with tests that are equivalent to the
SYSLOG interface dmesg tests.

Additionally a ksmg-newlines file is added which provides kmsg format
for testing with indentation.

The output of the existing kmsg-file test is adjusted to match the
expanded kmsg-input file.

All tests follow the standard util-linux tests format used by dmesg for
unit tests.

Signed-off-by: Ivan Delalande <colona@arista.com>
Signed-off-by: Edward Chron <echron@arista.com>
---
 tests/expected/dmesg/kmsg-colors         |  45 ++++++++
 tests/expected/dmesg/kmsg-console-levels |  61 +++++++++++
 tests/expected/dmesg/kmsg-decode         |  45 ++++++++
 tests/expected/dmesg/kmsg-delta          |  45 ++++++++
 tests/expected/dmesg/kmsg-facilities     |  59 +++++++++++
 tests/expected/dmesg/kmsg-indentation    |  35 +++++++
 tests/expected/dmesg/kmsg-limit          |  31 ++++++
 tests/ts/dmesg/kmsg-colors               |  29 ++++++
 tests/ts/dmesg/kmsg-console-levels       |  43 ++++++++
 tests/ts/dmesg/kmsg-decode               |  28 +++++
 tests/ts/dmesg/kmsg-delta                |  28 +++++
 tests/ts/dmesg/kmsg-facilities           |  31 ++++++
 tests/ts/dmesg/kmsg-indentation          |  40 +++++++
 tests/ts/dmesg/kmsg-limit                |  29 ++++++
 18 files changed, 663 insertions(+), 17 deletions(-)
 create mode 100644 tests/expected/dmesg/kmsg-colors
 create mode 100644 tests/expected/dmesg/kmsg-console-levels
 create mode 100644 tests/expected/dmesg/kmsg-decode
 create mode 100644 tests/expected/dmesg/kmsg-delta
 create mode 100644 tests/expected/dmesg/kmsg-facilities
 create mode 100644 tests/expected/dmesg/kmsg-indentation
 create mode 100644 tests/expected/dmesg/kmsg-limit
 create mode 100755 tests/ts/dmesg/kmsg-colors
 create mode 100755 tests/ts/dmesg/kmsg-console-levels
 create mode 100755 tests/ts/dmesg/kmsg-decode
 create mode 100755 tests/ts/dmesg/kmsg-delta
 create mode 100755 tests/ts/dmesg/kmsg-facilities
 create mode 100755 tests/ts/dmesg/kmsg-indentation
 create mode 100755 tests/ts/dmesg/kmsg-limit

diff --git a/tests/expected/dmesg/kmsg-colors b/tests/expected/dmesg/kmsg-colors
new file mode 100644
index 000000000..35294c5fa
--- /dev/null
+++ b/tests/expected/dmesg/kmsg-colors
@@ -0,0 +1,45 @@
+kern  :emerg : ^[[32m[    0.000000] ^[[0mLinux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000
+kern  :alert : ^[[32m[    0.000001] ^[[0m^[[33mCommand line: ^[[0m^[[7m^[[31minitrd=\ucode.img initrd=\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system^[[0m
+kern  :crit  : ^[[32m[    0.000002] ^[[0m^[[1m^[[31mBIOS-provided physical RAM map:^[[0m
+kern  :err   : ^[[32m[    0.000003] ^[[0m^[[33mBIOS-e820: ^[[0m^[[31m[mem 0x0000000000000000-0x000000000009efff] usable^[[0m
+kern  :warn  : ^[[32m[    0.000004] ^[[0m^[[33mBIOS-e820: ^[[0m^[[1m[mem 0x000000000009f000-0x00000000000bffff] reserved^[[0m
+kern  :notice: ^[[32m[    0.000005] ^[[0m^[[33mBIOS-e820: ^[[0m[mem 0x0000000000100000-0x0000000009afffff] usable
+kern  :info  : ^[[32m[    0.000006] ^[[0m^[[33mBIOS-e820: ^[[0m[mem 0x0000000009b00000-0x0000000009dfffff] reserved
+kern  :debug : ^[[32m[    0.000007] ^[[0m^[[33mBIOS-e820: ^[[0m[mem 0x0000000009e00000-0x0000000009efffff] usable
+kern  :info  : ^[[32m[    0.000008] ^[[0m^[[33mBIOS-e820: ^[[0m[mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS
+kern  :info  : ^[[32m[    0.000009] ^[[0m^[[33mBIOS-e820: ^[[0m[mem 0x0000000009f3c000-0x000000004235ffff] usable
+kern  :info  : ^[[32m[    0.000010] ^[[0m^[[33mBIOS-e820: ^[[0m[mem 0x0000000042360000-0x000000004455ffff] reserved
+kern  :info  : ^[[32m[    0.201607] ^[[0m^[[33msmp: ^[[0mBringing up secondary CPUs ...
+kern  :info  : ^[[32m[    0.201607] ^[[0m^[[33msmpboot: ^[[0mx86: Booting SMP configuration:
+kern  :warn  : ^[[32m[    0.209670] ^[[0m^[[1m  #1  #3  #5  #7^[[0m
+kern  :info  : ^[[32m[    0.212630] ^[[0m^[[33msmp: ^[[0mBrought up 1 node, 16 CPUs
+kern  :notice: ^[[32m[    0.215936] ^[[0m^[[33maudit: ^[[0mtype=2000 audit(1702926179.015:1): state=initialized audit_enabled=0 res=1
+kern  :info  : ^[[32m[    0.215937] ^[[0m^[[33mthermal_sys: ^[[0mRegistered thermal governor 'fair_share'
+kern  :warn  : ^[[32m[    0.215966] ^[[0m^[[33mENERGY_PERF_BIAS: ^[[0m^[[1mSet to 'normal', was 'performance'^[[0m
+kern  :info  : ^[[32m[    0.367657] ^[[0m^[[33mACPI: ^[[0m\_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+kern  :info  : ^[[32m[    0.368615] ^[[0m^[[33mACPI: ^[[0m\_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+kern  :info  : ^[[32m[    0.376316] ^[[0m^[[33mACPI: ^[[0m\_SB_.PRWL: New power resource
+kern  :info  : ^[[32m[    0.376343] ^[[0m^[[33mACPI: ^[[0m\_SB_.PRWB: New power resource
+kern  :info  : ^[[32m[    0.377373] ^[[0m^[[33mACPI: ^[[0mPCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+kern  :info  : ^[[32m[    0.377378] ^[[0m^[[33macpi PNP0A08:00: ^[[0m_OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+kern  :info  : ^[[32m[    0.377569] ^[[0m^[[33macpi PNP0A08:00: ^[[0m_OSC: platform does not support [SHPCHotplug AER]
+kern  :info  : ^[[32m[    0.377933] ^[[0m^[[33macpi PNP0A08:00: ^[[0m_OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+kern  :info  : ^[[32m[    0.378458] ^[[0mPCI host bridge to bus 0000:00
+kern  :info  : ^[[32m[    0.378459] ^[[0m^[[33mpci_bus 0000:00: ^[[0mroot bus resource [io  0x0000-0x0cf7 window]
+kern  :info  : ^[[32m[    0.378461] ^[[0m^[[33mpci_bus 0000:00: ^[[0mroot bus resource [io  0x0d00-0xffff window]
+user  :notice: ^[[32m[    9.398562] ^[[0muser network daemon initialization complete
+daemon:info  : ^[[32m[   10.441520] ^[[0m^[[33msystemd[1]: ^[[0msystemd 254.7-1.fc39 running in system mode
+daemon:info  : ^[[32m[   11.441524] ^[[0m^[[33msystemd[1]: ^[[0mDetected architecture x86-64.
+daemon:info  : ^[[32m[   12.441525] ^[[0m^[[33msystemd[1]: ^[[0mRunning in initrd.
+daemon:info  : ^[[32m[   13.541598] ^[[0m^[[33msystemd[1]: ^[[0mHostname set to <catalina>.
+kern  :info  : ^[[32m[   15.641860] ^[[0m^[[33musb 3-3: ^[[0mNew USB device found, idVendor=1a40, idProduct=0101, bcdDevice= 1.11
+kern  :err   : ^[[32m[   16.690000] ^[[0m^[[33mSerial bus multi instantiate pseudo device driver INT3515:00: ^[[0m^[[31merror -ENXIO: IRQ index 1 not found.^[[0m
+kern  :err   : ^[[32m[   17.710000] ^[[0m^[[33msnd_hda_intel 0000:00:1f.3: ^[[0m^[[31mCORB reset timeout#2, CORBRP = 65535^[[0m
+syslog:info  : ^[[32m[   18.820000] ^[[0m^[[33msystemd-journald[723]: ^[[0mReceived client request to flush runtime journal.
+syslog:warn  : ^[[32m[   20.840000] ^[[0m^[[33msystemd-journald[723]: ^[[0m^[[1mFile /var/log/journal/a124ea923b144109a12d557d5ac53179/system.journal corrupted or uncleanly shut down, renaming and replacing.^[[0m
+syslog:info  : ^[[32m[   21.852348] ^[[0m^[[33msystemd-journald[723]: ^[[0m/var/log/journal/ad7a2547ac0e4342a342e62a34a3eae4/user-1000.journal: Journal file uses a different sequence number ID, rotating.
+kern  :warn  : ^[[32m[   24.871100] ^[[0m^[[33mPEFILE: ^[[0m^[[1mUnsigned PE binary^[[0m
+kern  :err   : ^[[32m[   33.918091] ^[[0m^[[33msnd_hda_intel 0000:00:1f.3: ^[[0m^[[31mCORB reset timeout#2, CORBRP = 65535^[[0m
+kern  :info  : ^[[32m[  144.931785] ^[[0m^[[33musb 3-3.1: ^[[0mdevice firmware changed
+kern  :info  : ^[[32m[  145.953248] ^[[0m^[[33musb 3-3.1: ^[[0mUSB disconnect, device number 44
+kern  :info  : ^[[32m[  147.981859] ^[[0m^[[33musb 3-3.1: ^[[0mNew USB device found, idVendor=17ef, idProduct=6047, bcdDevice= 3.30
diff --git a/tests/expected/dmesg/kmsg-console-levels b/tests/expected/dmesg/kmsg-console-levels
new file mode 100644
index 000000000..d48312510
--- /dev/null
+++ b/tests/expected/dmesg/kmsg-console-levels
@@ -0,0 +1,61 @@
+* Output level: err+
+<0>[    0.000000] Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000
+<1>[    0.000001] Command line: initrd=\ucode.img initrd=\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system
+<2>[    0.000002] BIOS-provided physical RAM map:
+<3>[    0.000003] BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable
+<3>[   16.690000] Serial bus multi instantiate pseudo device driver INT3515:00: error -ENXIO: IRQ index 1 not found.
+<3>[   17.710000] snd_hda_intel 0000:00:1f.3: CORB reset timeout#2, CORBRP = 65535
+<3>[   33.918091] snd_hda_intel 0000:00:1f.3: CORB reset timeout#2, CORBRP = 65535
+* Output level: emerg+
+<0>[    0.000000] Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000
+* Output level: +err
+<3>[    0.000003] BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable
+<4>[    0.000004] BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved
+<5>[    0.000005] BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable
+<6>[    0.000006] BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved
+<7>[    0.000007] BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable
+<6>[    0.000008] BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS
+<6>[    0.000009] BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable
+<6>[    0.000010] BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved
+<6>[    0.201607] smp: Bringing up secondary CPUs ...
+<6>[    0.201607] smpboot: x86: Booting SMP configuration:
+<4>[    0.209670]   #1  #3  #5  #7
+<6>[    0.212630] smp: Brought up 1 node, 16 CPUs
+<5>[    0.215936] audit: type=2000 audit(1702926179.015:1): state=initialized audit_enabled=0 res=1
+<6>[    0.215937] thermal_sys: Registered thermal governor 'fair_share'
+<4>[    0.215966] ENERGY_PERF_BIAS: Set to 'normal', was 'performance'
+<6>[    0.367657] ACPI: \_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+<6>[    0.368615] ACPI: \_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+<6>[    0.376316] ACPI: \_SB_.PRWL: New power resource
+<6>[    0.376343] ACPI: \_SB_.PRWB: New power resource
+<6>[    0.377373] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+<6>[    0.377378] acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+<6>[    0.377569] acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]
+<6>[    0.377933] acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+<6>[    0.378458] PCI host bridge to bus 0000:00
+<6>[    0.378459] pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]
+<6>[    0.378461] pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]
+<13>[    9.398562] user network daemon initialization complete
+<30>[   10.441520] systemd[1]: systemd 254.7-1.fc39 running in system mode
+<30>[   11.441524] systemd[1]: Detected architecture x86-64.
+<30>[   12.441525] systemd[1]: Running in initrd.
+<30>[   13.541598] systemd[1]: Hostname set to <catalina>.
+<6>[   15.641860] usb 3-3: New USB device found, idVendor=1a40, idProduct=0101, bcdDevice= 1.11
+<3>[   16.690000] Serial bus multi instantiate pseudo device driver INT3515:00: error -ENXIO: IRQ index 1 not found.
+<3>[   17.710000] snd_hda_intel 0000:00:1f.3: CORB reset timeout#2, CORBRP = 65535
+<46>[   18.820000] systemd-journald[723]: Received client request to flush runtime journal.
+<44>[   20.840000] systemd-journald[723]: File /var/log/journal/a124ea923b144109a12d557d5ac53179/system.journal corrupted or uncleanly shut down, renaming and replacing.
+<46>[   21.852348] systemd-journald[723]: /var/log/journal/ad7a2547ac0e4342a342e62a34a3eae4/user-1000.journal: Journal file uses a different sequence number ID, rotating.
+<4>[   24.871100] PEFILE: Unsigned PE binary
+<3>[   33.918091] snd_hda_intel 0000:00:1f.3: CORB reset timeout#2, CORBRP = 65535
+<6>[  144.931785] usb 3-3.1: device firmware changed
+<6>[  145.953248] usb 3-3.1: USB disconnect, device number 44
+<6>[  147.981859] usb 3-3.1: New USB device found, idVendor=17ef, idProduct=6047, bcdDevice= 3.30
+* Output level: +debug
+<7>[    0.000007] BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable
+* Output level: notice
+<5>[    0.000005] BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable
+<5>[    0.215936] audit: type=2000 audit(1702926179.015:1): state=initialized audit_enabled=0 res=1
+<13>[    9.398562] user network daemon initialization complete
+* Output level: +
+test_dmesg: unknown level '+'
diff --git a/tests/expected/dmesg/kmsg-decode b/tests/expected/dmesg/kmsg-decode
new file mode 100644
index 000000000..85a664a61
--- /dev/null
+++ b/tests/expected/dmesg/kmsg-decode
@@ -0,0 +1,45 @@
+kern  :emerg : [    0.000000] Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000
+kern  :alert : [    0.000001] Command line: initrd=\ucode.img initrd=\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system
+kern  :crit  : [    0.000002] BIOS-provided physical RAM map:
+kern  :err   : [    0.000003] BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable
+kern  :warn  : [    0.000004] BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved
+kern  :notice: [    0.000005] BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable
+kern  :info  : [    0.000006] BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved
+kern  :debug : [    0.000007] BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable
+kern  :info  : [    0.000008] BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS
+kern  :info  : [    0.000009] BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable
+kern  :info  : [    0.000010] BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved
+kern  :info  : [    0.201607] smp: Bringing up secondary CPUs ...
+kern  :info  : [    0.201607] smpboot: x86: Booting SMP configuration:
+kern  :warn  : [    0.209670]   #1  #3  #5  #7
+kern  :info  : [    0.212630] smp: Brought up 1 node, 16 CPUs
+kern  :notice: [    0.215936] audit: type=2000 audit(1702926179.015:1): state=initialized audit_enabled=0 res=1
+kern  :info  : [    0.215937] thermal_sys: Registered thermal governor 'fair_share'
+kern  :warn  : [    0.215966] ENERGY_PERF_BIAS: Set to 'normal', was 'performance'
+kern  :info  : [    0.367657] ACPI: \_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+kern  :info  : [    0.368615] ACPI: \_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+kern  :info  : [    0.376316] ACPI: \_SB_.PRWL: New power resource
+kern  :info  : [    0.376343] ACPI: \_SB_.PRWB: New power resource
+kern  :info  : [    0.377373] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+kern  :info  : [    0.377378] acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+kern  :info  : [    0.377569] acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]
+kern  :info  : [    0.377933] acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+kern  :info  : [    0.378458] PCI host bridge to bus 0000:00
+kern  :info  : [    0.378459] pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]
+kern  :info  : [    0.378461] pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]
+user  :notice: [    9.398562] user network daemon initialization complete
+daemon:info  : [   10.441520] systemd[1]: systemd 254.7-1.fc39 running in system mode
+daemon:info  : [   11.441524] systemd[1]: Detected architecture x86-64.
+daemon:info  : [   12.441525] systemd[1]: Running in initrd.
+daemon:info  : [   13.541598] systemd[1]: Hostname set to <catalina>.
+kern  :info  : [   15.641860] usb 3-3: New USB device found, idVendor=1a40, idProduct=0101, bcdDevice= 1.11
+kern  :err   : [   16.690000] Serial bus multi instantiate pseudo device driver INT3515:00: error -ENXIO: IRQ index 1 not found.
+kern  :err   : [   17.710000] snd_hda_intel 0000:00:1f.3: CORB reset timeout#2, CORBRP = 65535
+syslog:info  : [   18.820000] systemd-journald[723]: Received client request to flush runtime journal.
+syslog:warn  : [   20.840000] systemd-journald[723]: File /var/log/journal/a124ea923b144109a12d557d5ac53179/system.journal corrupted or uncleanly shut down, renaming and replacing.
+syslog:info  : [   21.852348] systemd-journald[723]: /var/log/journal/ad7a2547ac0e4342a342e62a34a3eae4/user-1000.journal: Journal file uses a different sequence number ID, rotating.
+kern  :warn  : [   24.871100] PEFILE: Unsigned PE binary
+kern  :err   : [   33.918091] snd_hda_intel 0000:00:1f.3: CORB reset timeout#2, CORBRP = 65535
+kern  :info  : [  144.931785] usb 3-3.1: device firmware changed
+kern  :info  : [  145.953248] usb 3-3.1: USB disconnect, device number 44
+kern  :info  : [  147.981859] usb 3-3.1: New USB device found, idVendor=17ef, idProduct=6047, bcdDevice= 3.30
diff --git a/tests/expected/dmesg/kmsg-delta b/tests/expected/dmesg/kmsg-delta
new file mode 100644
index 000000000..caea3e9db
--- /dev/null
+++ b/tests/expected/dmesg/kmsg-delta
@@ -0,0 +1,45 @@
+[    0.000000 <    0.000000>] Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000
+[    0.000001 <    0.000000>] Command line: initrd=\ucode.img initrd=\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system
+[    0.000002 <    0.000000>] BIOS-provided physical RAM map:
+[    0.000003 <    0.000000>] BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable
+[    0.000004 <    0.000000>] BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved
+[    0.000005 <    0.000000>] BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable
+[    0.000006 <    0.000000>] BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved
+[    0.000007 <    0.000000>] BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable
+[    0.000008 <    0.000000>] BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS
+[    0.000009 <    0.000000>] BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable
+[    0.000010 <    0.000000>] BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved
+[    0.201607 <    0.000000>] smp: Bringing up secondary CPUs ...
+[    0.201607 <    0.000000>] smpboot: x86: Booting SMP configuration:
+[    0.209670 <    0.000000>]   #1  #3  #5  #7
+[    0.212630 <    0.000000>] smp: Brought up 1 node, 16 CPUs
+[    0.215936 <    0.000000>] audit: type=2000 audit(1702926179.015:1): state=initialized audit_enabled=0 res=1
+[    0.215937 <    0.000000>] thermal_sys: Registered thermal governor 'fair_share'
+[    0.215966 <    0.000000>] ENERGY_PERF_BIAS: Set to 'normal', was 'performance'
+[    0.367657 <    0.000000>] ACPI: \_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+[    0.368615 <    0.000000>] ACPI: \_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+[    0.376316 <    0.000000>] ACPI: \_SB_.PRWL: New power resource
+[    0.376343 <    0.000000>] ACPI: \_SB_.PRWB: New power resource
+[    0.377373 <    0.000000>] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+[    0.377378 <    0.000000>] acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+[    0.377569 <    0.000000>] acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]
+[    0.377933 <    0.000000>] acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+[    0.378458 <    0.000000>] PCI host bridge to bus 0000:00
+[    0.378459 <    0.000000>] pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]
+[    0.378461 <    0.000000>] pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]
+[    9.398562 <    9.000000>] user network daemon initialization complete
+[   10.441520 <    1.000000>] systemd[1]: systemd 254.7-1.fc39 running in system mode
+[   11.441524 <    1.000000>] systemd[1]: Detected architecture x86-64.
+[   12.441525 <    1.000000>] systemd[1]: Running in initrd.
+[   13.541598 <    1.000000>] systemd[1]: Hostname set to <catalina>.
+[   15.641860 <    2.000000>] usb 3-3: New USB device found, idVendor=1a40, idProduct=0101, bcdDevice= 1.11
+[   16.690000 <    1.000000>] Serial bus multi instantiate pseudo device driver INT3515:00: error -ENXIO: IRQ index 1 not found.
+[   17.710000 <    1.000000>] snd_hda_intel 0000:00:1f.3: CORB reset timeout#2, CORBRP = 65535
+[   18.820000 <    1.000000>] systemd-journald[723]: Received client request to flush runtime journal.
+[   20.840000 <    2.000000>] systemd-journald[723]: File /var/log/journal/a124ea923b144109a12d557d5ac53179/system.journal corrupted or uncleanly shut down, renaming and replacing.
+[   21.852348 <    1.000000>] systemd-journald[723]: /var/log/journal/ad7a2547ac0e4342a342e62a34a3eae4/user-1000.journal: Journal file uses a different sequence number ID, rotating.
+[   24.871100 <    3.000000>] PEFILE: Unsigned PE binary
+[   33.918091 <    9.000000>] snd_hda_intel 0000:00:1f.3: CORB reset timeout#2, CORBRP = 65535
+[  144.931785 <  111.000000>] usb 3-3.1: device firmware changed
+[  145.953248 <    1.000000>] usb 3-3.1: USB disconnect, device number 44
+[  147.981859 <    2.000000>] usb 3-3.1: New USB device found, idVendor=17ef, idProduct=6047, bcdDevice= 3.30
diff --git a/tests/expected/dmesg/kmsg-facilities b/tests/expected/dmesg/kmsg-facilities
new file mode 100644
index 000000000..4b460951a
--- /dev/null
+++ b/tests/expected/dmesg/kmsg-facilities
@@ -0,0 +1,59 @@
+dmesg Facility: -1
+dmesg Facility: 0
+[    0.000000] Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000
+[    0.000001] Command line: initrd=\ucode.img initrd=\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system
+[    0.000002] BIOS-provided physical RAM map:
+[    0.000003] BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable
+[    0.000004] BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved
+[    0.000005] BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable
+[    0.000006] BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved
+[    0.000007] BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable
+[    0.000008] BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS
+[    0.000009] BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable
+[    0.000010] BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved
+[    0.201607] smp: Bringing up secondary CPUs ...
+[    0.201607] smpboot: x86: Booting SMP configuration:
+[    0.209670]   #1  #3  #5  #7
+[    0.212630] smp: Brought up 1 node, 16 CPUs
+[    0.215936] audit: type=2000 audit(1702926179.015:1): state=initialized audit_enabled=0 res=1
+[    0.215937] thermal_sys: Registered thermal governor 'fair_share'
+[    0.215966] ENERGY_PERF_BIAS: Set to 'normal', was 'performance'
+[    0.367657] ACPI: \_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+[    0.368615] ACPI: \_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+[    0.376316] ACPI: \_SB_.PRWL: New power resource
+[    0.376343] ACPI: \_SB_.PRWB: New power resource
+[    0.377373] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+[    0.377378] acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+[    0.377569] acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]
+[    0.377933] acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+[    0.378458] PCI host bridge to bus 0000:00
+[    0.378459] pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]
+[    0.378461] pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]
+[   15.641860] usb 3-3: New USB device found, idVendor=1a40, idProduct=0101, bcdDevice= 1.11
+[   16.690000] Serial bus multi instantiate pseudo device driver INT3515:00: error -ENXIO: IRQ index 1 not found.
+[   17.710000] snd_hda_intel 0000:00:1f.3: CORB reset timeout#2, CORBRP = 65535
+[   24.871100] PEFILE: Unsigned PE binary
+[   33.918091] snd_hda_intel 0000:00:1f.3: CORB reset timeout#2, CORBRP = 65535
+[  144.931785] usb 3-3.1: device firmware changed
+[  145.953248] usb 3-3.1: USB disconnect, device number 44
+[  147.981859] usb 3-3.1: New USB device found, idVendor=17ef, idProduct=6047, bcdDevice= 3.30
+dmesg Facility: 1
+[    9.398562] user network daemon initialization complete
+dmesg Facility: 2
+dmesg Facility: 3
+[   10.441520] systemd[1]: systemd 254.7-1.fc39 running in system mode
+[   11.441524] systemd[1]: Detected architecture x86-64.
+[   12.441525] systemd[1]: Running in initrd.
+[   13.541598] systemd[1]: Hostname set to <catalina>.
+dmesg Facility: 4
+dmesg Facility: 5
+[   18.820000] systemd-journald[723]: Received client request to flush runtime journal.
+[   20.840000] systemd-journald[723]: File /var/log/journal/a124ea923b144109a12d557d5ac53179/system.journal corrupted or uncleanly shut down, renaming and replacing.
+[   21.852348] systemd-journald[723]: /var/log/journal/ad7a2547ac0e4342a342e62a34a3eae4/user-1000.journal: Journal file uses a different sequence number ID, rotating.
+dmesg Facility: 6
+dmesg Facility: 7
+dmesg Facility: 8
+dmesg Facility: 9
+dmesg Facility: 10
+dmesg Facility: 11
+dmesg Facility: 12
diff --git a/tests/expected/dmesg/kmsg-indentation b/tests/expected/dmesg/kmsg-indentation
new file mode 100644
index 000000000..25f41b454
--- /dev/null
+++ b/tests/expected/dmesg/kmsg-indentation
@@ -0,0 +1,35 @@
+[    1.000000] line zero
+[    2.000000] line one
+[    4.000000] line two
+[    7.000000] line three
+[   11.000000] line four
+kern  :notice: [    1.000000] line zero
+user  :crit  : [    2.000000] line one
+mail  :warn  : [    4.000000] line two
+daemon:info  : [    7.000000] line three
+syslog:emerg : [   11.000000] line four
+[<    0.000000>] line zero
+[<    1.000000>] line one
+[<    2.000000>] line two
+[<    3.000000>] line three
+[<    4.000000>] line four
+line zero
+line one
+line two
+line three
+line four
+[Feb13 23:31] line zero
+[  +1.000000] line one
+[  +2.000000] line two
+[  +3.000000] line three
+[  +4.000000] line four
+[Fri Feb 13 23:31:31 2009] line zero
+[Fri Feb 13 23:31:32 2009] line one
+[Fri Feb 13 23:31:34 2009] line two
+[Fri Feb 13 23:31:37 2009] line three
+[Fri Feb 13 23:31:41 2009] line four
+2009-02-13T23:31:31,123456+00:00 line zero
+2009-02-13T23:31:32,123456+00:00 line one
+2009-02-13T23:31:34,123456+00:00 line two
+2009-02-13T23:31:37,123456+00:00 line three
+2009-02-13T23:31:41,123456+00:00 line four
diff --git a/tests/expected/dmesg/kmsg-limit b/tests/expected/dmesg/kmsg-limit
new file mode 100644
index 000000000..0c39b4762
--- /dev/null
+++ b/tests/expected/dmesg/kmsg-limit
@@ -0,0 +1,31 @@
+[    0.201607] smp: Bringing up secondary CPUs ...
+[    0.201607] smpboot: x86: Booting SMP configuration:
+[    0.209670]   #1  #3  #5  #7
+[    0.212630] smp: Brought up 1 node, 16 CPUs
+[    0.215936] audit: type=2000 audit(1702926179.015:1): state=initialized audit_enabled=0 res=1
+[    0.215937] thermal_sys: Registered thermal governor 'fair_share'
+[    0.215966] ENERGY_PERF_BIAS: Set to 'normal', was 'performance'
+[    0.367657] ACPI: \_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+[    0.368615] ACPI: \_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+[    0.376316] ACPI: \_SB_.PRWL: New power resource
+[    0.376343] ACPI: \_SB_.PRWB: New power resource
+[    0.377373] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+[    0.377378] acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+[    0.377569] acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]
+[    0.377933] acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+[    0.378458] PCI host bridge to bus 0000:00
+[    0.378459] pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]
+[    0.378461] pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]
+[    9.398562] user network daemon initialization complete
+[   10.441520] systemd[1]: systemd 254.7-1.fc39 running in system mode
+[   11.441524] systemd[1]: Detected architecture x86-64.
+[   12.441525] systemd[1]: Running in initrd.
+[   13.541598] systemd[1]: Hostname set to <catalina>.
+[   15.641860] usb 3-3: New USB device found, idVendor=1a40, idProduct=0101, bcdDevice= 1.11
+[   16.690000] Serial bus multi instantiate pseudo device driver INT3515:00: error -ENXIO: IRQ index 1 not found.
+[   17.710000] snd_hda_intel 0000:00:1f.3: CORB reset timeout#2, CORBRP = 65535
+[   18.820000] systemd-journald[723]: Received client request to flush runtime journal.
+[   20.840000] systemd-journald[723]: File /var/log/journal/a124ea923b144109a12d557d5ac53179/system.journal corrupted or uncleanly shut down, renaming and replacing.
+[   21.852348] systemd-journald[723]: /var/log/journal/ad7a2547ac0e4342a342e62a34a3eae4/user-1000.journal: Journal file uses a different sequence number ID, rotating.
+[   24.871100] PEFILE: Unsigned PE binary
+[   33.918091] snd_hda_intel 0000:00:1f.3: CORB reset timeout#2, CORBRP = 65535
diff --git a/tests/ts/dmesg/kmsg-colors b/tests/ts/dmesg/kmsg-colors
new file mode 100755
index 000000000..959e7b547
--- /dev/null
+++ b/tests/ts/dmesg/kmsg-colors
@@ -0,0 +1,29 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="kmsg-colors"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+ts_inhibit_custom_colorscheme
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG --color=always -K $TS_SELF/kmsg-input -x >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/kmsg-console-levels b/tests/ts/dmesg/kmsg-console-levels
new file mode 100755
index 000000000..36f8ec097
--- /dev/null
+++ b/tests/ts/dmesg/kmsg-console-levels
@@ -0,0 +1,43 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="kmsg-levels"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+for I in {-1..8}; do
+	$TS_HELPER_DMESG -F $TS_SELF/kmsg-input -l $I >> $TS_OUTPUT 2>/dev/null
+done
+
+echo "* Output level: err+" >> $TS_OUTPUT 2>/dev/null
+$TS_HELPER_DMESG -K $TS_SELF/kmsg-input -r -l err+ >> $TS_OUTPUT 2>/dev/null
+echo "* Output level: emerg+" >> $TS_OUTPUT 2>/dev/null
+$TS_HELPER_DMESG -K $TS_SELF/kmsg-input -r -l emerg+ >> $TS_OUTPUT 2>/dev/null
+echo "* Output level: +err" >> $TS_OUTPUT 2>/dev/null
+$TS_HELPER_DMESG -K $TS_SELF/kmsg-input -r -l +err >> $TS_OUTPUT 2>/dev/null
+echo "* Output level: +debug" >> $TS_OUTPUT 2>/dev/null
+$TS_HELPER_DMESG -K $TS_SELF/kmsg-input -r -l +debug >> $TS_OUTPUT 2>/dev/null
+echo "* Output level: notice" >> $TS_OUTPUT 2>/dev/null
+$TS_HELPER_DMESG -K $TS_SELF/kmsg-input -r -l notice >> $TS_OUTPUT 2>/dev/null
+echo "* Output level: +" >> $TS_OUTPUT 2>/dev/null
+$TS_HELPER_DMESG -K $TS_SELF/kmsg-input -r -l + 2>> $TS_OUTPUT >/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/kmsg-decode b/tests/ts/dmesg/kmsg-decode
new file mode 100755
index 000000000..51fef159d
--- /dev/null
+++ b/tests/ts/dmesg/kmsg-decode
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="kmsg-decode"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG -x -K $TS_SELF/kmsg-input >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/kmsg-delta b/tests/ts/dmesg/kmsg-delta
new file mode 100755
index 000000000..7ae082e76
--- /dev/null
+++ b/tests/ts/dmesg/kmsg-delta
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="kmsg-delta"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG -d -K $TS_SELF/kmsg-input >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/kmsg-facilities b/tests/ts/dmesg/kmsg-facilities
new file mode 100755
index 000000000..b274c5de4
--- /dev/null
+++ b/tests/ts/dmesg/kmsg-facilities
@@ -0,0 +1,31 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="kmsg-facilities"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+for I in {-1..12}; do
+        echo "dmesg Facility: $I" >> $TS_OUTPUT
+	$TS_HELPER_DMESG -K $TS_SELF/kmsg-input -f $I >> $TS_OUTPUT 2>/dev/null
+done
+
+ts_finalize
diff --git a/tests/ts/dmesg/kmsg-indentation b/tests/ts/dmesg/kmsg-indentation
new file mode 100755
index 000000000..16870158f
--- /dev/null
+++ b/tests/ts/dmesg/kmsg-indentation
@@ -0,0 +1,40 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="kmsg-indentation"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG -K $TS_SELF/kmsg-newlines >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG -K $TS_SELF/kmsg-newlines -x >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=delta --kmsg-file $TS_SELF/kmsg-newlines >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=notime --kmsg-file $TS_SELF/kmsg-newlines >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=reltime --kmsg-file $TS_SELF/kmsg-newlines >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=ctime --kmsg-file $TS_SELF/kmsg-newlines >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=iso --kmsg-file $TS_SELF/kmsg-newlines >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+ts_finalize
diff --git a/tests/ts/dmesg/kmsg-limit b/tests/ts/dmesg/kmsg-limit
new file mode 100755
index 000000000..ff70bcf83
--- /dev/null
+++ b/tests/ts/dmesg/kmsg-limit
@@ -0,0 +1,29 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="kmsg-limit"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG --since @1234567890.124 --until @1234567991 -K $TS_SELF/kmsg-input \
+	>> $TS_OUTPUT 2> $TS_ERRLOG
+
+ts_finalize
-- 
2.43.0


^ permalink raw reply related

* [PATCH] util-linux-demsg-issue-2666-patch-2.patch
From: Edward Chron @ 2023-12-31 18:34 UTC (permalink / raw)
  To: util-linux; +Cc: colona, echron, echron

Submission to Project: util-linux
Open Incident: #2637 at github.com/util-linux/util-linux/issues/2637
Component: util-linux/sys-utils
Files: tests/ts/dmesg syslog interface caller-id files, tests
       and related expected files
Testing on Fedora 39 with Linux-6.6.6 Kernel and CONFIG_PRINTK_CALLER
config option set.
Patch tested and generated with the latest util-linux code pulled.
Retro-fitted to merge on top of the patch for Issue: #2609

For Issue #2609 Thomas and Zak pointed out the we need tests to verify
that the dmesg command works correctly and to allow us to compare the
results from PRINTK_CALLER id field tests provided by #2609 with the
standard (syslog interface) dmesg tests.

Currently, dmesg only has standard syslog interface tests even though
dmesg -S the syslog interface supports the caller_id field. There
are no syslog caller-id tests.

We would like syslog caller-id tests both to validate that the dmesg
code works correctly with the caller-id field being present and also
to compare against the addition of dmesg kmsg caller_id support added
by Issue #2609.

These tests are for the dmesg syslog interface with caller-id follow the
existing test structure for dmesg tests. The existing dmesg -F interface
is used to input our test files.

Until Thomas added a dmesg kmsg interface for json format testing
there were no dmesg tests except the tests for the generic dmesg
syslog tests. So we're naming the syslog caller-id tests to follow
the test naming convention that Thomas introduced.

For caller_id tests we prefix the test name with cid- abbreviating
the caller_id name to keep the names short. There is no unqiue
indentifier for syslog tests, so syslog tests are currently:

colors, console-levels, decode, delta, facilities, indentation,
limit, json

The cid versions of these test files are just prefixed with cid-
The patch for Issue: #2609 has the files:
cid-input and cid-json and the expected file for cide-json

Additional new dmesg tests are found with Issue #2663 which add
standard dmesg kmsg interface tests providing equivalent tests to
the existing dmesg syslog interface tests.

Also, Issue #2609 introduces dmesg kmsg interface caller-id tests
equivalent to the dmesg syslog interface with caller-id tests introduced
here along with the necessary dmesg kmsg interface caller-id support
needed to accomodate the PRINTK_CALLER id field.

Just for reference, on a Linux system with the CONFIG_PRINTK_CALLER
configuration option set the output from dmesg -S looks like:

    [  520.899558] [   T3919] hub 3-3:1.0: USB hub found

on a system where the PRINTK_CALLER configuration option is not set the
output looks like:

    [  520.899558] hub 3-3:1.0: USB hub found

the additional field specifies either a Thread Id or CPU id depending on
the context of the task or thread at the time the printk that added the
message to the kernel ring buffer was executed.

Signed-off-by: Ivan Delalande <colona@arista.com>
Signed-off-by: Edward Chron <echron@arista.com>
---
 tests/expected/dmesg/cid-colors         | 106 ++++++++++
 tests/expected/dmesg/cid-console-levels | 253 ++++++++++++++++++++++++
 tests/expected/dmesg/cid-decode         | 106 ++++++++++
 tests/expected/dmesg/cid-delta          | 106 ++++++++++
 tests/expected/dmesg/cid-facilities     | 104 ++++++++++
 tests/expected/dmesg/cid-indentation    |  35 ++++
 tests/expected/dmesg/cid-limit          |   4 +
 tests/ts/dmesg/cid-colors               |  29 +++
 tests/ts/dmesg/cid-console-levels       |  36 ++++
 tests/ts/dmesg/cid-decode               |  28 +++
 tests/ts/dmesg/cid-delta                |  27 +++
 tests/ts/dmesg/cid-facilities           |  30 +++
 tests/ts/dmesg/cid-indentation          |  40 ++++
 tests/ts/dmesg/cid-limit                |  29 +++
 tests/ts/dmesg/cid-newlines             |   5 +
 15 files changed, 938 insertions(+)
 create mode 100644 tests/expected/dmesg/cid-colors
 create mode 100644 tests/expected/dmesg/cid-console-levels
 create mode 100644 tests/expected/dmesg/cid-decode
 create mode 100644 tests/expected/dmesg/cid-delta
 create mode 100644 tests/expected/dmesg/cid-facilities
 create mode 100644 tests/expected/dmesg/cid-indentation
 create mode 100644 tests/expected/dmesg/cid-limit
 create mode 100755 tests/ts/dmesg/cid-colors
 create mode 100755 tests/ts/dmesg/cid-console-levels
 create mode 100755 tests/ts/dmesg/cid-decode
 create mode 100755 tests/ts/dmesg/cid-delta
 create mode 100755 tests/ts/dmesg/cid-facilities
 create mode 100755 tests/ts/dmesg/cid-indentation
 create mode 100755 tests/ts/dmesg/cid-limit
 create mode 100644 tests/ts/dmesg/cid-newlines

diff --git a/tests/expected/dmesg/cid-colors b/tests/expected/dmesg/cid-colors
new file mode 100644
index 000000000..3b7aff6d7
--- /dev/null
+++ b/tests/expected/dmesg/cid-colors
@@ -0,0 +1,106 @@
+kern  :emerg : ^[[32m[    0.000000] ^[[0m[    T0] example[0]
+kern  :alert : ^[[32m[    1.000000] ^[[0m[    T1] ^[[7m^[[31mexample[1]^[[0m
+kern  :crit  : ^[[32m[    8.000000] ^[[0m[    T2] ^[[1m^[[31mexample[2]^[[0m
+kern  :err   : ^[[32m[   27.000000] ^[[0m[    T3] ^[[31mexample[3]^[[0m
+kern  :warn  : ^[[32m[   64.000000] ^[[0m[    T4] ^[[1mexample[4]^[[0m
+kern  :notice: ^[[32m[  125.000000] ^[[0m[    T5] example[5]
+kern  :info  : ^[[32m[  216.000000] ^[[0m[    T6] example[6]
+kern  :debug : ^[[32m[  343.000000] ^[[0m[    T7] example[7]
+user  :emerg : ^[[32m[  512.000000] ^[[0m[    T8] example[8]
+user  :alert : ^[[32m[  729.000000] ^[[0m[    T9] ^[[7m^[[31mexample[9]^[[0m
+user  :crit  : ^[[32m[ 1000.000000] ^[[0m[   T10] ^[[1m^[[31mexample[10]^[[0m
+user  :err   : ^[[32m[ 1331.000000] ^[[0m[   T11] ^[[31mexample[11]^[[0m
+user  :warn  : ^[[32m[ 1728.000000] ^[[0m[   T12] ^[[1mexample[12]^[[0m
+user  :notice: ^[[32m[ 2197.000000] ^[[0m[   T13] example[13]
+user  :info  : ^[[32m[ 2744.000000] ^[[0m[   T14] example[14]
+user  :debug : ^[[32m[ 3375.000000] ^[[0m[   T15] example[15]
+mail  :emerg : ^[[32m[ 4096.000000] ^[[0m[   T16] example[16]
+mail  :alert : ^[[32m[ 4913.000000] ^[[0m[   T17] ^[[7m^[[31mexample[17]^[[0m
+mail  :crit  : ^[[32m[ 5832.000000] ^[[0m[   T18] ^[[1m^[[31mexample[18]^[[0m
+mail  :err   : ^[[32m[ 6859.000000] ^[[0m[   T19] ^[[31mexample[19]^[[0m
+mail  :warn  : ^[[32m[ 8000.000000] ^[[0m[   T20] ^[[1mexample[20]^[[0m
+mail  :notice: ^[[32m[ 9261.000000] ^[[0m[   T21] example[21]
+mail  :info  : ^[[32m[10648.000000] ^[[0m[   T22] example[22]
+mail  :debug : ^[[32m[12167.000000] ^[[0m[   T23] example[23]
+daemon:emerg : ^[[32m[13824.000000] ^[[0m[   T24] example[24]
+daemon:alert : ^[[32m[15625.000000] ^[[0m[   T25] ^[[7m^[[31mexample[25]^[[0m
+daemon:crit  : ^[[32m[17576.000000] ^[[0m[   T26] ^[[1m^[[31mexample[26]^[[0m
+daemon:err   : ^[[32m[19683.000000] ^[[0m[   T27] ^[[31mexample[27]^[[0m
+daemon:warn  : ^[[32m[21952.000000] ^[[0m[   T28] ^[[1mexample[28]^[[0m
+daemon:notice: ^[[32m[24389.000000] ^[[0m[   T29] example[29]
+daemon:info  : ^[[32m[27000.000000] ^[[0m[   T10] example[30]
+daemon:debug : ^[[32m[29791.000000] ^[[0m[   T31] example[31]
+auth  :emerg : ^[[32m[32768.000000] ^[[0m[   T32] example[32]
+auth  :alert : ^[[32m[35937.000000] ^[[0m[   T33] ^[[7m^[[31mexample[33]^[[0m
+auth  :crit  : ^[[32m[39304.000000] ^[[0m[   T34] ^[[1m^[[31mexample[34]^[[0m
+auth  :err   : ^[[32m[42875.000000] ^[[0m[   T35] ^[[31mexample[35]^[[0m
+auth  :warn  : ^[[32m[46656.000000] ^[[0m[   T36] ^[[1mexample[36]^[[0m
+auth  :notice: ^[[32m[50653.000000] ^[[0m[   T37] example[37]
+auth  :info  : ^[[32m[54872.000000] ^[[0m[   T38] example[38]
+auth  :debug : ^[[32m[59319.000000] ^[[0m[   T39] example[39]
+syslog:emerg : ^[[32m[64000.000000] ^[[0m[   T40] example[40]
+syslog:alert : ^[[32m[68921.000000] ^[[0m[   T41] ^[[7m^[[31mexample[41]^[[0m
+syslog:crit  : ^[[32m[74088.000000] ^[[0m[   T42] ^[[1m^[[31mexample[42]^[[0m
+syslog:err   : ^[[32m[79507.000000] ^[[0m[   T43] ^[[31mexample[43]^[[0m
+syslog:warn  : ^[[32m[85184.000000] ^[[0m[   T44] ^[[1mexample[44]^[[0m
+syslog:notice: ^[[32m[91125.000000] ^[[0m[   T45] example[45]
+syslog:info  : ^[[32m[97336.000000] ^[[0m[   T46] example[46]
+syslog:debug : ^[[32m[103823.000000] ^[[0m[   T47] example[47]
+lpr   :emerg : ^[[32m[110592.000000] ^[[0m[   T48] example[48]
+lpr   :alert : ^[[32m[117649.000000] ^[[0m[   T49] ^[[7m^[[31mexample[49]^[[0m
+lpr   :crit  : ^[[32m[125000.000000] ^[[0m[   T50] ^[[1m^[[31mexample[50]^[[0m
+lpr   :err   : ^[[32m[132651.000000] ^[[0m[   T51] ^[[31mexample[51]^[[0m
+lpr   :warn  : ^[[32m[140608.000000] ^[[0m[   T52] ^[[1mexample[52]^[[0m
+lpr   :notice: ^[[32m[148877.000000] ^[[0m[   T53] example[53]
+lpr   :info  : ^[[32m[157464.000000] ^[[0m[   T54] example[54]
+lpr   :debug : ^[[32m[166375.000000] ^[[0m[   T55] example[55]
+news  :emerg : ^[[32m[175616.000000] ^[[0m[   T56] example[56]
+news  :alert : ^[[32m[185193.000000] ^[[0m[   T57] ^[[7m^[[31mexample[57]^[[0m
+news  :crit  : ^[[32m[195112.000000] ^[[0m[   T58] ^[[1m^[[31mexample[58]^[[0m
+news  :err   : ^[[32m[205379.000000] ^[[0m[   T59] ^[[31mexample[59]^[[0m
+news  :warn  : ^[[32m[216000.000000] ^[[0m[   T60] ^[[1mexample[60]^[[0m
+news  :notice: ^[[32m[226981.000000] ^[[0m[   T61] example[61]
+news  :info  : ^[[32m[238328.000000] ^[[0m[   T62] example[62]
+news  :debug : ^[[32m[250047.000000] ^[[0m[   T63] example[63]
+uucp  :emerg : ^[[32m[262144.000000] ^[[0m[   T64] example[64]
+uucp  :alert : ^[[32m[274625.000000] ^[[0m[   T65] ^[[7m^[[31mexample[65]^[[0m
+uucp  :crit  : ^[[32m[287496.000000] ^[[0m[   T66] ^[[1m^[[31mexample[66]^[[0m
+uucp  :err   : ^[[32m[300763.000000] ^[[0m[   T67] ^[[31mexample[67]^[[0m
+uucp  :warn  : ^[[32m[314432.000000] ^[[0m[   T68] ^[[1mexample[68]^[[0m
+uucp  :notice: ^[[32m[328509.000000] ^[[0m[   T69] example[69]
+uucp  :info  : ^[[32m[343000.000000] ^[[0m[   T70] example[70]
+uucp  :debug : ^[[32m[357911.000000] ^[[0m[   T71] example[71]
+cron  :emerg : ^[[32m[373248.000000] ^[[0m[   T72] example[72]
+cron  :alert : ^[[32m[389017.000000] ^[[0m[   T73] ^[[7m^[[31mexample[73]^[[0m
+cron  :crit  : ^[[32m[405224.000000] ^[[0m[   T74] ^[[1m^[[31mexample[74]^[[0m
+cron  :err   : ^[[32m[421875.000000] ^[[0m[   T75] ^[[31mexample[75]^[[0m
+cron  :warn  : ^[[32m[438976.000000] ^[[0m[   T76] ^[[1mexample[76]^[[0m
+cron  :notice: ^[[32m[456533.000000] ^[[0m[   T77] example[77]
+cron  :info  : ^[[32m[474552.000000] ^[[0m[   T78] example[78]
+cron  :debug : ^[[32m[493039.000000] ^[[0m[   T79] example[79]
+authpriv:emerg : ^[[32m[512000.000000] ^[[0m[   T80] example[80]
+authpriv:alert : ^[[32m[531441.000000] ^[[0m[   T81] ^[[7m^[[31mexample[81]^[[0m
+authpriv:crit  : ^[[32m[551368.000000] ^[[0m[   T82] ^[[1m^[[31mexample[82]^[[0m
+authpriv:err   : ^[[32m[571787.000000] ^[[0m[   T83] ^[[31mexample[83]^[[0m
+authpriv:warn  : ^[[32m[592704.000000] ^[[0m[   T84] ^[[1mexample[84]^[[0m
+authpriv:notice: ^[[32m[614125.000000] ^[[0m[   T85] example[85]
+authpriv:info  : ^[[32m[636056.000000] ^[[0m[   T86] example[86]
+authpriv:debug : ^[[32m[658503.000000] ^[[0m[   T87] example[87]
+ftp   :emerg : ^[[32m[681472.000000] ^[[0m[   T88] example[88]
+ftp   :alert : ^[[32m[704969.000000] ^[[0m[   T89] ^[[7m^[[31mexample[89]^[[0m
+ftp   :crit  : ^[[32m[729000.000000] ^[[0m[   T90] ^[[1m^[[31mexample[90]^[[0m
+ftp   :err   : ^[[32m[753571.000000] ^[[0m[   T91] ^[[31mexample[91]^[[0m
+ftp   :warn  : ^[[32m[778688.000000] ^[[0m[   T92] ^[[1mexample[92]^[[0m
+ftp   :notice: ^[[32m[804357.000000] ^[[0m[   T93] example[93]
+ftp   :info  : ^[[32m[830584.000000] ^[[0m[   T94] example[94]
+ftp   :debug : ^[[32m[857375.000000] ^[[0m[   T95] example[95]
+res0  :emerg : ^[[32m[884736.000000] ^[[0m[   T96] example[96]
+res0  :alert : ^[[32m[912673.000000] ^[[0m[   T97] ^[[7m^[[31mexample[97]^[[0m
+res0  :crit  : ^[[32m[941192.000000] ^[[0m[   T98] ^[[1m^[[31mexample[98]^[[0m
+res0  :err   : ^[[32m[970299.000000] ^[[0m[   T99] ^[[31mexample[99]^[[0m
+res0  :warn  : ^[[32m[1000000.000000] ^[[0m[  T100] ^[[1mexample[100]^[[0m
+res0  :notice: ^[[32m[1030301.000000] ^[[0m[  T101] example[101]
+res0  :info  : ^[[32m[1061208.000000] ^[[0m[  T102] example[102]
+res0  :debug : ^[[32m[1092727.000000] ^[[0m[  T103] example[103]
+res1  :emerg : ^[[32m[1124864.000000] ^[[0m[  T104] example[104]
+local2:info  : ^[[32m[4557523.000000] ^[[0m[  T105] example[105]
diff --git a/tests/expected/dmesg/cid-console-levels b/tests/expected/dmesg/cid-console-levels
new file mode 100644
index 000000000..9fe993b20
--- /dev/null
+++ b/tests/expected/dmesg/cid-console-levels
@@ -0,0 +1,253 @@
+[    0.000000] [    T0] example[0]
+[  512.000000] [    T8] example[8]
+[ 4096.000000] [   T16] example[16]
+[13824.000000] [   T24] example[24]
+[32768.000000] [   T32] example[32]
+[64000.000000] [   T40] example[40]
+[110592.000000] [   T48] example[48]
+[175616.000000] [   T56] example[56]
+[262144.000000] [   T64] example[64]
+[373248.000000] [   T72] example[72]
+[512000.000000] [   T80] example[80]
+[681472.000000] [   T88] example[88]
+[884736.000000] [   T96] example[96]
+[1124864.000000] [  T104] example[104]
+[    1.000000] [    T1] example[1]
+[  729.000000] [    T9] example[9]
+[ 4913.000000] [   T17] example[17]
+[15625.000000] [   T25] example[25]
+[35937.000000] [   T33] example[33]
+[68921.000000] [   T41] example[41]
+[117649.000000] [   T49] example[49]
+[185193.000000] [   T57] example[57]
+[274625.000000] [   T65] example[65]
+[389017.000000] [   T73] example[73]
+[531441.000000] [   T81] example[81]
+[704969.000000] [   T89] example[89]
+[912673.000000] [   T97] example[97]
+[    8.000000] [    T2] example[2]
+[ 1000.000000] [   T10] example[10]
+[ 5832.000000] [   T18] example[18]
+[17576.000000] [   T26] example[26]
+[39304.000000] [   T34] example[34]
+[74088.000000] [   T42] example[42]
+[125000.000000] [   T50] example[50]
+[195112.000000] [   T58] example[58]
+[287496.000000] [   T66] example[66]
+[405224.000000] [   T74] example[74]
+[551368.000000] [   T82] example[82]
+[729000.000000] [   T90] example[90]
+[941192.000000] [   T98] example[98]
+[   27.000000] [    T3] example[3]
+[ 1331.000000] [   T11] example[11]
+[ 6859.000000] [   T19] example[19]
+[19683.000000] [   T27] example[27]
+[42875.000000] [   T35] example[35]
+[79507.000000] [   T43] example[43]
+[132651.000000] [   T51] example[51]
+[205379.000000] [   T59] example[59]
+[300763.000000] [   T67] example[67]
+[421875.000000] [   T75] example[75]
+[571787.000000] [   T83] example[83]
+[753571.000000] [   T91] example[91]
+[970299.000000] [   T99] example[99]
+[   64.000000] [    T4] example[4]
+[ 1728.000000] [   T12] example[12]
+[ 8000.000000] [   T20] example[20]
+[21952.000000] [   T28] example[28]
+[46656.000000] [   T36] example[36]
+[85184.000000] [   T44] example[44]
+[140608.000000] [   T52] example[52]
+[216000.000000] [   T60] example[60]
+[314432.000000] [   T68] example[68]
+[438976.000000] [   T76] example[76]
+[592704.000000] [   T84] example[84]
+[778688.000000] [   T92] example[92]
+[1000000.000000] [  T100] example[100]
+[  125.000000] [    T5] example[5]
+[ 2197.000000] [   T13] example[13]
+[ 9261.000000] [   T21] example[21]
+[24389.000000] [   T29] example[29]
+[50653.000000] [   T37] example[37]
+[91125.000000] [   T45] example[45]
+[148877.000000] [   T53] example[53]
+[226981.000000] [   T61] example[61]
+[328509.000000] [   T69] example[69]
+[456533.000000] [   T77] example[77]
+[614125.000000] [   T85] example[85]
+[804357.000000] [   T93] example[93]
+[1030301.000000] [  T101] example[101]
+[  216.000000] [    T6] example[6]
+[ 2744.000000] [   T14] example[14]
+[10648.000000] [   T22] example[22]
+[27000.000000] [   T10] example[30]
+[54872.000000] [   T38] example[38]
+[97336.000000] [   T46] example[46]
+[157464.000000] [   T54] example[54]
+[238328.000000] [   T62] example[62]
+[343000.000000] [   T70] example[70]
+[474552.000000] [   T78] example[78]
+[636056.000000] [   T86] example[86]
+[830584.000000] [   T94] example[94]
+[1061208.000000] [  T102] example[102]
+[4557523.000000] [  T105] example[105]
+[  343.000000] [    T7] example[7]
+[ 3375.000000] [   T15] example[15]
+[12167.000000] [   T23] example[23]
+[29791.000000] [   T31] example[31]
+[59319.000000] [   T39] example[39]
+[103823.000000] [   T47] example[47]
+[166375.000000] [   T55] example[55]
+[250047.000000] [   T63] example[63]
+[357911.000000] [   T71] example[71]
+[493039.000000] [   T79] example[79]
+[658503.000000] [   T87] example[87]
+[857375.000000] [   T95] example[95]
+[1092727.000000] [  T103] example[103]
+[    0.000000] [    T0] example[0]
+[    1.000000] [    T1] example[1]
+[    8.000000] [    T2] example[2]
+[   27.000000] [    T3] example[3]
+[  512.000000] [    T8] example[8]
+[  729.000000] [    T9] example[9]
+[ 1000.000000] [   T10] example[10]
+[ 1331.000000] [   T11] example[11]
+[ 4096.000000] [   T16] example[16]
+[ 4913.000000] [   T17] example[17]
+[ 5832.000000] [   T18] example[18]
+[ 6859.000000] [   T19] example[19]
+[13824.000000] [   T24] example[24]
+[15625.000000] [   T25] example[25]
+[17576.000000] [   T26] example[26]
+[19683.000000] [   T27] example[27]
+[32768.000000] [   T32] example[32]
+[35937.000000] [   T33] example[33]
+[39304.000000] [   T34] example[34]
+[42875.000000] [   T35] example[35]
+[64000.000000] [   T40] example[40]
+[68921.000000] [   T41] example[41]
+[74088.000000] [   T42] example[42]
+[79507.000000] [   T43] example[43]
+[110592.000000] [   T48] example[48]
+[117649.000000] [   T49] example[49]
+[125000.000000] [   T50] example[50]
+[132651.000000] [   T51] example[51]
+[175616.000000] [   T56] example[56]
+[185193.000000] [   T57] example[57]
+[195112.000000] [   T58] example[58]
+[205379.000000] [   T59] example[59]
+[262144.000000] [   T64] example[64]
+[274625.000000] [   T65] example[65]
+[287496.000000] [   T66] example[66]
+[300763.000000] [   T67] example[67]
+[373248.000000] [   T72] example[72]
+[389017.000000] [   T73] example[73]
+[405224.000000] [   T74] example[74]
+[421875.000000] [   T75] example[75]
+[512000.000000] [   T80] example[80]
+[531441.000000] [   T81] example[81]
+[551368.000000] [   T82] example[82]
+[571787.000000] [   T83] example[83]
+[681472.000000] [   T88] example[88]
+[704969.000000] [   T89] example[89]
+[729000.000000] [   T90] example[90]
+[753571.000000] [   T91] example[91]
+[884736.000000] [   T96] example[96]
+[912673.000000] [   T97] example[97]
+[941192.000000] [   T98] example[98]
+[970299.000000] [   T99] example[99]
+[1124864.000000] [  T104] example[104]
+[    0.000000] [    T0] example[0]
+[  512.000000] [    T8] example[8]
+[ 4096.000000] [   T16] example[16]
+[13824.000000] [   T24] example[24]
+[32768.000000] [   T32] example[32]
+[64000.000000] [   T40] example[40]
+[110592.000000] [   T48] example[48]
+[175616.000000] [   T56] example[56]
+[262144.000000] [   T64] example[64]
+[373248.000000] [   T72] example[72]
+[512000.000000] [   T80] example[80]
+[681472.000000] [   T88] example[88]
+[884736.000000] [   T96] example[96]
+[1124864.000000] [  T104] example[104]
+[   27.000000] [    T3] example[3]
+[   64.000000] [    T4] example[4]
+[  125.000000] [    T5] example[5]
+[  216.000000] [    T6] example[6]
+[  343.000000] [    T7] example[7]
+[ 1331.000000] [   T11] example[11]
+[ 1728.000000] [   T12] example[12]
+[ 2197.000000] [   T13] example[13]
+[ 2744.000000] [   T14] example[14]
+[ 3375.000000] [   T15] example[15]
+[ 6859.000000] [   T19] example[19]
+[ 8000.000000] [   T20] example[20]
+[ 9261.000000] [   T21] example[21]
+[10648.000000] [   T22] example[22]
+[12167.000000] [   T23] example[23]
+[19683.000000] [   T27] example[27]
+[21952.000000] [   T28] example[28]
+[24389.000000] [   T29] example[29]
+[27000.000000] [   T10] example[30]
+[29791.000000] [   T31] example[31]
+[42875.000000] [   T35] example[35]
+[46656.000000] [   T36] example[36]
+[50653.000000] [   T37] example[37]
+[54872.000000] [   T38] example[38]
+[59319.000000] [   T39] example[39]
+[79507.000000] [   T43] example[43]
+[85184.000000] [   T44] example[44]
+[91125.000000] [   T45] example[45]
+[97336.000000] [   T46] example[46]
+[103823.000000] [   T47] example[47]
+[132651.000000] [   T51] example[51]
+[140608.000000] [   T52] example[52]
+[148877.000000] [   T53] example[53]
+[157464.000000] [   T54] example[54]
+[166375.000000] [   T55] example[55]
+[205379.000000] [   T59] example[59]
+[216000.000000] [   T60] example[60]
+[226981.000000] [   T61] example[61]
+[238328.000000] [   T62] example[62]
+[250047.000000] [   T63] example[63]
+[300763.000000] [   T67] example[67]
+[314432.000000] [   T68] example[68]
+[328509.000000] [   T69] example[69]
+[343000.000000] [   T70] example[70]
+[357911.000000] [   T71] example[71]
+[421875.000000] [   T75] example[75]
+[438976.000000] [   T76] example[76]
+[456533.000000] [   T77] example[77]
+[474552.000000] [   T78] example[78]
+[493039.000000] [   T79] example[79]
+[571787.000000] [   T83] example[83]
+[592704.000000] [   T84] example[84]
+[614125.000000] [   T85] example[85]
+[636056.000000] [   T86] example[86]
+[658503.000000] [   T87] example[87]
+[753571.000000] [   T91] example[91]
+[778688.000000] [   T92] example[92]
+[804357.000000] [   T93] example[93]
+[830584.000000] [   T94] example[94]
+[857375.000000] [   T95] example[95]
+[970299.000000] [   T99] example[99]
+[1000000.000000] [  T100] example[100]
+[1030301.000000] [  T101] example[101]
+[1061208.000000] [  T102] example[102]
+[1092727.000000] [  T103] example[103]
+[4557523.000000] [  T105] example[105]
+[  343.000000] [    T7] example[7]
+[ 3375.000000] [   T15] example[15]
+[12167.000000] [   T23] example[23]
+[29791.000000] [   T31] example[31]
+[59319.000000] [   T39] example[39]
+[103823.000000] [   T47] example[47]
+[166375.000000] [   T55] example[55]
+[250047.000000] [   T63] example[63]
+[357911.000000] [   T71] example[71]
+[493039.000000] [   T79] example[79]
+[658503.000000] [   T87] example[87]
+[857375.000000] [   T95] example[95]
+[1092727.000000] [  T103] example[103]
+test_dmesg: unknown level '+'
diff --git a/tests/expected/dmesg/cid-decode b/tests/expected/dmesg/cid-decode
new file mode 100644
index 000000000..757b9284d
--- /dev/null
+++ b/tests/expected/dmesg/cid-decode
@@ -0,0 +1,106 @@
+kern  :emerg : [    0.000000] [    T0] example[0]
+kern  :alert : [    1.000000] [    T1] example[1]
+kern  :crit  : [    8.000000] [    T2] example[2]
+kern  :err   : [   27.000000] [    T3] example[3]
+kern  :warn  : [   64.000000] [    T4] example[4]
+kern  :notice: [  125.000000] [    T5] example[5]
+kern  :info  : [  216.000000] [    T6] example[6]
+kern  :debug : [  343.000000] [    T7] example[7]
+user  :emerg : [  512.000000] [    T8] example[8]
+user  :alert : [  729.000000] [    T9] example[9]
+user  :crit  : [ 1000.000000] [   T10] example[10]
+user  :err   : [ 1331.000000] [   T11] example[11]
+user  :warn  : [ 1728.000000] [   T12] example[12]
+user  :notice: [ 2197.000000] [   T13] example[13]
+user  :info  : [ 2744.000000] [   T14] example[14]
+user  :debug : [ 3375.000000] [   T15] example[15]
+mail  :emerg : [ 4096.000000] [   T16] example[16]
+mail  :alert : [ 4913.000000] [   T17] example[17]
+mail  :crit  : [ 5832.000000] [   T18] example[18]
+mail  :err   : [ 6859.000000] [   T19] example[19]
+mail  :warn  : [ 8000.000000] [   T20] example[20]
+mail  :notice: [ 9261.000000] [   T21] example[21]
+mail  :info  : [10648.000000] [   T22] example[22]
+mail  :debug : [12167.000000] [   T23] example[23]
+daemon:emerg : [13824.000000] [   T24] example[24]
+daemon:alert : [15625.000000] [   T25] example[25]
+daemon:crit  : [17576.000000] [   T26] example[26]
+daemon:err   : [19683.000000] [   T27] example[27]
+daemon:warn  : [21952.000000] [   T28] example[28]
+daemon:notice: [24389.000000] [   T29] example[29]
+daemon:info  : [27000.000000] [   T10] example[30]
+daemon:debug : [29791.000000] [   T31] example[31]
+auth  :emerg : [32768.000000] [   T32] example[32]
+auth  :alert : [35937.000000] [   T33] example[33]
+auth  :crit  : [39304.000000] [   T34] example[34]
+auth  :err   : [42875.000000] [   T35] example[35]
+auth  :warn  : [46656.000000] [   T36] example[36]
+auth  :notice: [50653.000000] [   T37] example[37]
+auth  :info  : [54872.000000] [   T38] example[38]
+auth  :debug : [59319.000000] [   T39] example[39]
+syslog:emerg : [64000.000000] [   T40] example[40]
+syslog:alert : [68921.000000] [   T41] example[41]
+syslog:crit  : [74088.000000] [   T42] example[42]
+syslog:err   : [79507.000000] [   T43] example[43]
+syslog:warn  : [85184.000000] [   T44] example[44]
+syslog:notice: [91125.000000] [   T45] example[45]
+syslog:info  : [97336.000000] [   T46] example[46]
+syslog:debug : [103823.000000] [   T47] example[47]
+lpr   :emerg : [110592.000000] [   T48] example[48]
+lpr   :alert : [117649.000000] [   T49] example[49]
+lpr   :crit  : [125000.000000] [   T50] example[50]
+lpr   :err   : [132651.000000] [   T51] example[51]
+lpr   :warn  : [140608.000000] [   T52] example[52]
+lpr   :notice: [148877.000000] [   T53] example[53]
+lpr   :info  : [157464.000000] [   T54] example[54]
+lpr   :debug : [166375.000000] [   T55] example[55]
+news  :emerg : [175616.000000] [   T56] example[56]
+news  :alert : [185193.000000] [   T57] example[57]
+news  :crit  : [195112.000000] [   T58] example[58]
+news  :err   : [205379.000000] [   T59] example[59]
+news  :warn  : [216000.000000] [   T60] example[60]
+news  :notice: [226981.000000] [   T61] example[61]
+news  :info  : [238328.000000] [   T62] example[62]
+news  :debug : [250047.000000] [   T63] example[63]
+uucp  :emerg : [262144.000000] [   T64] example[64]
+uucp  :alert : [274625.000000] [   T65] example[65]
+uucp  :crit  : [287496.000000] [   T66] example[66]
+uucp  :err   : [300763.000000] [   T67] example[67]
+uucp  :warn  : [314432.000000] [   T68] example[68]
+uucp  :notice: [328509.000000] [   T69] example[69]
+uucp  :info  : [343000.000000] [   T70] example[70]
+uucp  :debug : [357911.000000] [   T71] example[71]
+cron  :emerg : [373248.000000] [   T72] example[72]
+cron  :alert : [389017.000000] [   T73] example[73]
+cron  :crit  : [405224.000000] [   T74] example[74]
+cron  :err   : [421875.000000] [   T75] example[75]
+cron  :warn  : [438976.000000] [   T76] example[76]
+cron  :notice: [456533.000000] [   T77] example[77]
+cron  :info  : [474552.000000] [   T78] example[78]
+cron  :debug : [493039.000000] [   T79] example[79]
+authpriv:emerg : [512000.000000] [   T80] example[80]
+authpriv:alert : [531441.000000] [   T81] example[81]
+authpriv:crit  : [551368.000000] [   T82] example[82]
+authpriv:err   : [571787.000000] [   T83] example[83]
+authpriv:warn  : [592704.000000] [   T84] example[84]
+authpriv:notice: [614125.000000] [   T85] example[85]
+authpriv:info  : [636056.000000] [   T86] example[86]
+authpriv:debug : [658503.000000] [   T87] example[87]
+ftp   :emerg : [681472.000000] [   T88] example[88]
+ftp   :alert : [704969.000000] [   T89] example[89]
+ftp   :crit  : [729000.000000] [   T90] example[90]
+ftp   :err   : [753571.000000] [   T91] example[91]
+ftp   :warn  : [778688.000000] [   T92] example[92]
+ftp   :notice: [804357.000000] [   T93] example[93]
+ftp   :info  : [830584.000000] [   T94] example[94]
+ftp   :debug : [857375.000000] [   T95] example[95]
+res0  :emerg : [884736.000000] [   T96] example[96]
+res0  :alert : [912673.000000] [   T97] example[97]
+res0  :crit  : [941192.000000] [   T98] example[98]
+res0  :err   : [970299.000000] [   T99] example[99]
+res0  :warn  : [1000000.000000] [  T100] example[100]
+res0  :notice: [1030301.000000] [  T101] example[101]
+res0  :info  : [1061208.000000] [  T102] example[102]
+res0  :debug : [1092727.000000] [  T103] example[103]
+res1  :emerg : [1124864.000000] [  T104] example[104]
+local2:info  : [4557523.000000] [  T105] example[105]
diff --git a/tests/expected/dmesg/cid-delta b/tests/expected/dmesg/cid-delta
new file mode 100644
index 000000000..9b75c63af
--- /dev/null
+++ b/tests/expected/dmesg/cid-delta
@@ -0,0 +1,106 @@
+[    0.000000 <    0.000000>] [    T0] example[0]
+[    1.000000 <    0.000000>] [    T1] example[1]
+[    8.000000 <    7.000000>] [    T2] example[2]
+[   27.000000 <   19.000000>] [    T3] example[3]
+[   64.000000 <   37.000000>] [    T4] example[4]
+[  125.000000 <   61.000000>] [    T5] example[5]
+[  216.000000 <   91.000000>] [    T6] example[6]
+[  343.000000 <  127.000000>] [    T7] example[7]
+[  512.000000 <  169.000000>] [    T8] example[8]
+[  729.000000 <  217.000000>] [    T9] example[9]
+[ 1000.000000 <  271.000000>] [   T10] example[10]
+[ 1331.000000 <  331.000000>] [   T11] example[11]
+[ 1728.000000 <  397.000000>] [   T12] example[12]
+[ 2197.000000 <  469.000000>] [   T13] example[13]
+[ 2744.000000 <  547.000000>] [   T14] example[14]
+[ 3375.000000 <  631.000000>] [   T15] example[15]
+[ 4096.000000 <  721.000000>] [   T16] example[16]
+[ 4913.000000 <  817.000000>] [   T17] example[17]
+[ 5832.000000 <  919.000000>] [   T18] example[18]
+[ 6859.000000 < 1027.000000>] [   T19] example[19]
+[ 8000.000000 < 1141.000000>] [   T20] example[20]
+[ 9261.000000 < 1261.000000>] [   T21] example[21]
+[10648.000000 < 1387.000000>] [   T22] example[22]
+[12167.000000 < 1519.000000>] [   T23] example[23]
+[13824.000000 < 1657.000000>] [   T24] example[24]
+[15625.000000 < 1801.000000>] [   T25] example[25]
+[17576.000000 < 1951.000000>] [   T26] example[26]
+[19683.000000 < 2107.000000>] [   T27] example[27]
+[21952.000000 < 2269.000000>] [   T28] example[28]
+[24389.000000 < 2437.000000>] [   T29] example[29]
+[27000.000000 < 2611.000000>] [   T10] example[30]
+[29791.000000 < 2791.000000>] [   T31] example[31]
+[32768.000000 < 2977.000000>] [   T32] example[32]
+[35937.000000 < 3169.000000>] [   T33] example[33]
+[39304.000000 < 3367.000000>] [   T34] example[34]
+[42875.000000 < 3571.000000>] [   T35] example[35]
+[46656.000000 < 3781.000000>] [   T36] example[36]
+[50653.000000 < 3997.000000>] [   T37] example[37]
+[54872.000000 < 4219.000000>] [   T38] example[38]
+[59319.000000 < 4447.000000>] [   T39] example[39]
+[64000.000000 < 4681.000000>] [   T40] example[40]
+[68921.000000 < 4921.000000>] [   T41] example[41]
+[74088.000000 < 5167.000000>] [   T42] example[42]
+[79507.000000 < 5419.000000>] [   T43] example[43]
+[85184.000000 < 5677.000000>] [   T44] example[44]
+[91125.000000 < 5941.000000>] [   T45] example[45]
+[97336.000000 < 6211.000000>] [   T46] example[46]
+[103823.000000 < 6487.000000>] [   T47] example[47]
+[110592.000000 < 6769.000000>] [   T48] example[48]
+[117649.000000 < 7057.000000>] [   T49] example[49]
+[125000.000000 < 7351.000000>] [   T50] example[50]
+[132651.000000 < 7651.000000>] [   T51] example[51]
+[140608.000000 < 7957.000000>] [   T52] example[52]
+[148877.000000 < 8269.000000>] [   T53] example[53]
+[157464.000000 < 8587.000000>] [   T54] example[54]
+[166375.000000 < 8911.000000>] [   T55] example[55]
+[175616.000000 < 9241.000000>] [   T56] example[56]
+[185193.000000 < 9577.000000>] [   T57] example[57]
+[195112.000000 < 9919.000000>] [   T58] example[58]
+[205379.000000 <10267.000000>] [   T59] example[59]
+[216000.000000 <10621.000000>] [   T60] example[60]
+[226981.000000 <10981.000000>] [   T61] example[61]
+[238328.000000 <11347.000000>] [   T62] example[62]
+[250047.000000 <11719.000000>] [   T63] example[63]
+[262144.000000 <12097.000000>] [   T64] example[64]
+[274625.000000 <12481.000000>] [   T65] example[65]
+[287496.000000 <12871.000000>] [   T66] example[66]
+[300763.000000 <13267.000000>] [   T67] example[67]
+[314432.000000 <13669.000000>] [   T68] example[68]
+[328509.000000 <14077.000000>] [   T69] example[69]
+[343000.000000 <14491.000000>] [   T70] example[70]
+[357911.000000 <14911.000000>] [   T71] example[71]
+[373248.000000 <15337.000000>] [   T72] example[72]
+[389017.000000 <15769.000000>] [   T73] example[73]
+[405224.000000 <16207.000000>] [   T74] example[74]
+[421875.000000 <16651.000000>] [   T75] example[75]
+[438976.000000 <17101.000000>] [   T76] example[76]
+[456533.000000 <17557.000000>] [   T77] example[77]
+[474552.000000 <18019.000000>] [   T78] example[78]
+[493039.000000 <18487.000000>] [   T79] example[79]
+[512000.000000 <18961.000000>] [   T80] example[80]
+[531441.000000 <19441.000000>] [   T81] example[81]
+[551368.000000 <19927.000000>] [   T82] example[82]
+[571787.000000 <20419.000000>] [   T83] example[83]
+[592704.000000 <20917.000000>] [   T84] example[84]
+[614125.000000 <21421.000000>] [   T85] example[85]
+[636056.000000 <21931.000000>] [   T86] example[86]
+[658503.000000 <22447.000000>] [   T87] example[87]
+[681472.000000 <22969.000000>] [   T88] example[88]
+[704969.000000 <23497.000000>] [   T89] example[89]
+[729000.000000 <24031.000000>] [   T90] example[90]
+[753571.000000 <24571.000000>] [   T91] example[91]
+[778688.000000 <25117.000000>] [   T92] example[92]
+[804357.000000 <25669.000000>] [   T93] example[93]
+[830584.000000 <26227.000000>] [   T94] example[94]
+[857375.000000 <26791.000000>] [   T95] example[95]
+[884736.000000 <27361.000000>] [   T96] example[96]
+[912673.000000 <27937.000000>] [   T97] example[97]
+[941192.000000 <28519.000000>] [   T98] example[98]
+[970299.000000 <29107.000000>] [   T99] example[99]
+[1000000.000000 <29701.000000>] [  T100] example[100]
+[1030301.000000 <30301.000000>] [  T101] example[101]
+[1061208.000000 <30907.000000>] [  T102] example[102]
+[1092727.000000 <31519.000000>] [  T103] example[103]
+[1124864.000000 <32137.000000>] [  T104] example[104]
+[4557523.000000 <3432659.000000>] [  T105] example[105]
diff --git a/tests/expected/dmesg/cid-facilities b/tests/expected/dmesg/cid-facilities
new file mode 100644
index 000000000..b8afa3809
--- /dev/null
+++ b/tests/expected/dmesg/cid-facilities
@@ -0,0 +1,104 @@
+[    0.000000] [    T0] example[0]
+[    1.000000] [    T1] example[1]
+[    8.000000] [    T2] example[2]
+[   27.000000] [    T3] example[3]
+[   64.000000] [    T4] example[4]
+[  125.000000] [    T5] example[5]
+[  216.000000] [    T6] example[6]
+[  343.000000] [    T7] example[7]
+[  512.000000] [    T8] example[8]
+[  729.000000] [    T9] example[9]
+[ 1000.000000] [   T10] example[10]
+[ 1331.000000] [   T11] example[11]
+[ 1728.000000] [   T12] example[12]
+[ 2197.000000] [   T13] example[13]
+[ 2744.000000] [   T14] example[14]
+[ 3375.000000] [   T15] example[15]
+[ 4096.000000] [   T16] example[16]
+[ 4913.000000] [   T17] example[17]
+[ 5832.000000] [   T18] example[18]
+[ 6859.000000] [   T19] example[19]
+[ 8000.000000] [   T20] example[20]
+[ 9261.000000] [   T21] example[21]
+[10648.000000] [   T22] example[22]
+[12167.000000] [   T23] example[23]
+[13824.000000] [   T24] example[24]
+[15625.000000] [   T25] example[25]
+[17576.000000] [   T26] example[26]
+[19683.000000] [   T27] example[27]
+[21952.000000] [   T28] example[28]
+[24389.000000] [   T29] example[29]
+[27000.000000] [   T10] example[30]
+[29791.000000] [   T31] example[31]
+[32768.000000] [   T32] example[32]
+[35937.000000] [   T33] example[33]
+[39304.000000] [   T34] example[34]
+[42875.000000] [   T35] example[35]
+[46656.000000] [   T36] example[36]
+[50653.000000] [   T37] example[37]
+[54872.000000] [   T38] example[38]
+[59319.000000] [   T39] example[39]
+[64000.000000] [   T40] example[40]
+[68921.000000] [   T41] example[41]
+[74088.000000] [   T42] example[42]
+[79507.000000] [   T43] example[43]
+[85184.000000] [   T44] example[44]
+[91125.000000] [   T45] example[45]
+[97336.000000] [   T46] example[46]
+[103823.000000] [   T47] example[47]
+[110592.000000] [   T48] example[48]
+[117649.000000] [   T49] example[49]
+[125000.000000] [   T50] example[50]
+[132651.000000] [   T51] example[51]
+[140608.000000] [   T52] example[52]
+[148877.000000] [   T53] example[53]
+[157464.000000] [   T54] example[54]
+[166375.000000] [   T55] example[55]
+[175616.000000] [   T56] example[56]
+[185193.000000] [   T57] example[57]
+[195112.000000] [   T58] example[58]
+[205379.000000] [   T59] example[59]
+[216000.000000] [   T60] example[60]
+[226981.000000] [   T61] example[61]
+[238328.000000] [   T62] example[62]
+[250047.000000] [   T63] example[63]
+[262144.000000] [   T64] example[64]
+[274625.000000] [   T65] example[65]
+[287496.000000] [   T66] example[66]
+[300763.000000] [   T67] example[67]
+[314432.000000] [   T68] example[68]
+[328509.000000] [   T69] example[69]
+[343000.000000] [   T70] example[70]
+[357911.000000] [   T71] example[71]
+[373248.000000] [   T72] example[72]
+[389017.000000] [   T73] example[73]
+[405224.000000] [   T74] example[74]
+[421875.000000] [   T75] example[75]
+[438976.000000] [   T76] example[76]
+[456533.000000] [   T77] example[77]
+[474552.000000] [   T78] example[78]
+[493039.000000] [   T79] example[79]
+[512000.000000] [   T80] example[80]
+[531441.000000] [   T81] example[81]
+[551368.000000] [   T82] example[82]
+[571787.000000] [   T83] example[83]
+[592704.000000] [   T84] example[84]
+[614125.000000] [   T85] example[85]
+[636056.000000] [   T86] example[86]
+[658503.000000] [   T87] example[87]
+[681472.000000] [   T88] example[88]
+[704969.000000] [   T89] example[89]
+[729000.000000] [   T90] example[90]
+[753571.000000] [   T91] example[91]
+[778688.000000] [   T92] example[92]
+[804357.000000] [   T93] example[93]
+[830584.000000] [   T94] example[94]
+[857375.000000] [   T95] example[95]
+[884736.000000] [   T96] example[96]
+[912673.000000] [   T97] example[97]
+[941192.000000] [   T98] example[98]
+[970299.000000] [   T99] example[99]
+[1000000.000000] [  T100] example[100]
+[1030301.000000] [  T101] example[101]
+[1061208.000000] [  T102] example[102]
+[1092727.000000] [  T103] example[103]
diff --git a/tests/expected/dmesg/cid-indentation b/tests/expected/dmesg/cid-indentation
new file mode 100644
index 000000000..573682795
--- /dev/null
+++ b/tests/expected/dmesg/cid-indentation
@@ -0,0 +1,35 @@
+[    1.000000] [    T1] new
+                        line
+[    2.000000] [    T2] two
+                        new
+                        lines
+user  :crit  : [    1.000000] [    T1] new
+                                       line
+mail  :warn  : [    2.000000] [    T2] two
+                                       new
+                                       lines
+[<    0.000000>] [    T1] new
+                          line
+[<    1.000000>] [    T2] two
+                          new
+                          lines
+[    T1] new
+         line
+[    T2] two
+         new
+         lines
+[Feb13 23:31] [    T1] new
+                       line
+[  +1.000000] [    T2] two
+                       new
+                       lines
+[Fri Feb 13 23:31:31 2009] [    T1] new
+                                    line
+[Fri Feb 13 23:31:32 2009] [    T2] two
+                                    new
+                                    lines
+2009-02-13T23:31:31,123456+00:00 [    T1] new
+                                          line
+2009-02-13T23:31:32,123456+00:00 [    T2] two
+                                          new
+                                          lines
diff --git a/tests/expected/dmesg/cid-limit b/tests/expected/dmesg/cid-limit
new file mode 100644
index 000000000..c30b4ac9a
--- /dev/null
+++ b/tests/expected/dmesg/cid-limit
@@ -0,0 +1,4 @@
+[    1.000000] [    T1] example[1]
+[    8.000000] [    T2] example[2]
+[   27.000000] [    T3] example[3]
+[   64.000000] [    T4] example[4]
diff --git a/tests/ts/dmesg/cid-colors b/tests/ts/dmesg/cid-colors
new file mode 100755
index 000000000..d17dd17c0
--- /dev/null
+++ b/tests/ts/dmesg/cid-colors
@@ -0,0 +1,29 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="cid-colors"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+ts_inhibit_custom_colorscheme
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG --color=always -F $TS_SELF/cid-input -x >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/cid-console-levels b/tests/ts/dmesg/cid-console-levels
new file mode 100755
index 000000000..e2f241bde
--- /dev/null
+++ b/tests/ts/dmesg/cid-console-levels
@@ -0,0 +1,36 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="cid-levels"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+for I in {-1..8}; do
+	$TS_HELPER_DMESG -F $TS_SELF/cid-input -l $I >> $TS_OUTPUT 2>/dev/null
+done
+
+$TS_HELPER_DMESG -F $TS_SELF/cid-input -l err+ >> $TS_OUTPUT 2>/dev/null
+$TS_HELPER_DMESG -F $TS_SELF/cid-input -l emerg+ >> $TS_OUTPUT 2>/dev/null
+$TS_HELPER_DMESG -F $TS_SELF/cid-input -l +err >> $TS_OUTPUT 2>/dev/null
+$TS_HELPER_DMESG -F $TS_SELF/cid-input -l +debug >> $TS_OUTPUT 2>/dev/null
+$TS_HELPER_DMESG -F $TS_SELF/cid-input -l + 2>> $TS_OUTPUT >/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/cid-decode b/tests/ts/dmesg/cid-decode
new file mode 100755
index 000000000..488f52a32
--- /dev/null
+++ b/tests/ts/dmesg/cid-decode
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="cid-decode"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG -x -F $TS_SELF/cid-input >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/cid-delta b/tests/ts/dmesg/cid-delta
new file mode 100755
index 000000000..8ba952a5d
--- /dev/null
+++ b/tests/ts/dmesg/cid-delta
@@ -0,0 +1,27 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="cid-delta"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+$TS_HELPER_DMESG -d -F $TS_SELF/cid-input >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/cid-facilities b/tests/ts/dmesg/cid-facilities
new file mode 100755
index 000000000..b4b613e8b
--- /dev/null
+++ b/tests/ts/dmesg/cid-facilities
@@ -0,0 +1,30 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="cid-facilities"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+for I in {-1..12}; do
+	$TS_HELPER_DMESG -F $TS_SELF/cid-input -f $I >> $TS_OUTPUT 2>/dev/null
+done
+
+ts_finalize
diff --git a/tests/ts/dmesg/cid-indentation b/tests/ts/dmesg/cid-indentation
new file mode 100755
index 000000000..434e1694b
--- /dev/null
+++ b/tests/ts/dmesg/cid-indentation
@@ -0,0 +1,40 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="cid-indentation"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG -F $TS_SELF/cid-newlines >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG -F $TS_SELF/cid-newlines -x >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=delta --file $TS_SELF/cid-newlines >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=notime --file $TS_SELF/cid-newlines >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=reltime --file $TS_SELF/cid-newlines >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=ctime --file $TS_SELF/cid-newlines >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=iso --file $TS_SELF/cid-newlines >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+ts_finalize
diff --git a/tests/ts/dmesg/cid-limit b/tests/ts/dmesg/cid-limit
new file mode 100755
index 000000000..34f928a9e
--- /dev/null
+++ b/tests/ts/dmesg/cid-limit
@@ -0,0 +1,29 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="cid-limit"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG --since @1234567890.124 --until @1234567991 \
+	-F $TS_SELF/cid-input >> $TS_OUTPUT 2> $TS_ERRLOG
+
+ts_finalize
diff --git a/tests/ts/dmesg/cid-newlines b/tests/ts/dmesg/cid-newlines
new file mode 100644
index 000000000..682ce40bb
--- /dev/null
+++ b/tests/ts/dmesg/cid-newlines
@@ -0,0 +1,5 @@
+<10>[    1.000000] [    T1] new
+line
+<20>[    2.000000] [    T2] two
+new
+lines
-- 
2.43.0


^ permalink raw reply related

* [PATCH] util-linux-demsg-issue-2666-patch-1.patch
From: Edward Chron @ 2023-12-31 18:33 UTC (permalink / raw)
  To: util-linux; +Cc: colona, echron, echron

util-linux/sys-utils dmesg add PRINTK_CALLER support
Submission to Project: util-linux
Open Incident: #2609 at github.com/util-linux/util-linux/issues/2609
Component: util-linux/sys-utils
File: dmesg.c
Code level patch applied against: 2.39.3 - latest code pulled from
           git.github.com:util-linux/util-linux.git
Revision: #1 on 2023/12/08 per Review from Karel Zak
Revision: #2 on 2023/12/12 Adjust line offsets for master update and
                           Add caller_id_size init to dmesg -K
Revision: #3 on 2023/12/12 Use of sizeof for cidbuf and limit search
                           for caller_id to dmesg prefix to msg text
Revision: #4 on 2023/12/15 Ensure SYSLOG and kmsg inputs have
                           caller_id_size set appropriately
Revision: #5 on 2023/12/24 Make caller_id width consistent with
                           makedumpfile
Revision: #6 on 2023/12/30 Use updated test naming convention
                           Include expected results for new tests

Add support to standard dmesg command for the optional Linux Kernel
debug CONFIG option PRINTK_CALLER which adds an optional dmesg field
that contains the Thread Id or CPU Id that is issuing the printk to
add the message to the kernel ring buffer. This makes debugging simpler
as dmesg entries for a specific thread or CPU can be recognized.

The dmesg -S using the old syslog interface supports printing the
PRINTK_CALLER field but currently standard dmesg does not support
printing the field if present. There are utilities that use dmesg and
so it would be optimal if dmesg supported PRINTK_CALLER as well.

The additional field provided by PRINTK_CALLER is only present
if it was configured for the Linux kernel where the dmesg command
is run. It is a debug option and not configured by default so the
dmesg output will only change for those kernels where the option was
configured when the kernel was built. For users who went to the
trouble to configure PRINTK_CALLER and have the extra field available
for debugging, having dmesg print the field is very helpful.

Size of the PRINTK_CALLER field is determined by the maximum number
tasks that can be run on the system which is limited by the value of
/proc/sys/kernel/pid_max as pid values are from 0 to value - 1.
This value determines the number of id digits needed by the caller id.
The PRINTK_CALLER field is printed as T<id> for a Task Id or C<id>
for a CPU Id for a printk in CPU context. The values are left space
padded and enclosed in parentheses such as: [    T123] or [     C16]

For consistency with dmesg -S which supports the PRINTK_CALLER field
the field is printed followed by a space. For JSON format output the
PRINTK_CALLER field is identified as caller as that is consistent with
it's naming in /dev/kmsg. No space padding is used to reduce space
consumed by the JSON output. So the output from the command on a system
with PRINTK_CALLER field enabled in the Linux .config file the dmesg
output appears as:

> dmesg
...
[  520.897104] [   T3919] usb 3-3: Product: USB 2.0 Hub

and

> dmesg -x
...
kern  :info  : [  520.897104] [   T3919] usb 3-3: Product: USB 2.0 Hub

and

> dmesg -J
...
      },{
         "pri": 6,
         "time":    520.897104,
         "caller": "T3919",
         "msg": "usb 3-3: Product: USB 2.0 Hub"
      },{

and

> dmesg -J -x
...
      },{
         "fac": "kern",
         "pri": "info",
         "time":   520.897104,
         "caller": "T3919",
         "msg": "usb 3-3: Product: USB 2.0 Hub"
      },{

>

For comparison:

> dmesg -S
...
[  520.897104] [ T3919] usb 3-3: Product: USB 2.0 Hub

and

> dmesg -S -x
...
kern  :info  : [  520.897104] [ T3919] usb 3-3: Product: USB 2.0 Hub

Note: When dmesg uses the old syslog interface the reserved space for
      the PRINTK_CALLER field is capped at 5 digits because 32-bit
      kernels are capped at 32768 as the max number of PIDs. However,
      64-bit systems are currently capped at 2^22 PIDs (0 - 4194303).
      The PID cap is set by PID_MAX_LIMIT but the system limit can be
      less so we use /proc/sys/kernel/pid_max to determine the size
      needed to hold the maximum PID value size for the current system.
      Many 64-bit systems support 2^22 PIDs (0 - 4194303) and you see:

> dmesg -x
...
kern  :info  : [  520.899558] [   T3919] hub 3-3:1.0: USB hub found
...
kern  :info  : [ 9830.456898] [  T98982] cgroup: fork rejected by pids ...
kern  :info  : [14301.158878] [ T137336] cgroup: fork rejected by pids ...
kern  :info  : [18980.803190] [T1637865] cgroup: fork rejected by pids ...

> dmesg -S -x
...
kern  :info  : [  520.899558] [ T3919] hub 3-3:1.0: USB hub found
...
kern  :info  : [ 9830.456898] [T98982] cgroup: fork rejected by pids ...
kern  :info  : [14301.158878] [T137336] cgroup: fork rejected by pids ...
kern  :info  : [18980.803190] [T1637865] cgroup: fork rejected by pids ...

This is the only difference seen with PRINTK_CALLER configured and
printing between the dmesg /dev/kmsg interface and the dmesg -S syslog
interface.

Tests naming has been revised based on naming convention Thomas used to
introduce dmest json tests. The naming of test and input files that
reside in tests/ts/dmeg include:

<name> are existing dmesg syslog interface tests and input files.
cid-<name> are dmesg syslog interface caller_id tests and input files.
json-<name> are dmesg kmsg interface tests and input files.
cid-json-<name> are dmesg kmsg interface caller_id tests and input files.

Resulting expected files match the test names.

Signed-off-by: Ivan Delalande <colona@arista.com>
Signed-off-by: Edward Chron <echron@arista.com>
---
 include/pathnames.h                          |   3 +
 sys-utils/dmesg.c                            | 128 ++++-
 tests/expected/dmesg/cid-json                | 535 +++++++++++++++++++
 tests/expected/dmesg/cid-kmsg-colors         |  45 ++
 tests/expected/dmesg/cid-kmsg-console-levels |  97 ++++
 tests/expected/dmesg/cid-kmsg-decode         |  45 ++
 tests/expected/dmesg/cid-kmsg-delta          |  45 ++
 tests/expected/dmesg/cid-kmsg-facilities     |  45 ++
 tests/expected/dmesg/cid-kmsg-indentation    |  28 +
 tests/expected/dmesg/cid-kmsg-json           | 230 ++++++++
 tests/expected/dmesg/cid-kmsg-limit          |  31 ++
 tests/expected/dmesg/kmsg-file               | 126 ++++-
 tests/ts/dmesg/cid-input                     | 106 ++++
 tests/ts/dmesg/cid-json                      |  28 +
 tests/ts/dmesg/cid-kmsg-colors               |  29 +
 tests/ts/dmesg/cid-kmsg-console-levels       |  36 ++
 tests/ts/dmesg/cid-kmsg-decode               |  28 +
 tests/ts/dmesg/cid-kmsg-delta                |  28 +
 tests/ts/dmesg/cid-kmsg-facilities           |  30 ++
 tests/ts/dmesg/cid-kmsg-indentation          |  40 ++
 tests/ts/dmesg/cid-kmsg-input                | Bin 0 -> 4425 bytes
 tests/ts/dmesg/cid-kmsg-json                 |  28 +
 tests/ts/dmesg/cid-kmsg-limit                |  29 +
 tests/ts/dmesg/cid-kmsg-newlines             | Bin 0 -> 152 bytes
 tests/ts/dmesg/kmsg-input                    | Bin 1955 -> 3944 bytes
 25 files changed, 1720 insertions(+), 20 deletions(-)
 create mode 100644 tests/expected/dmesg/cid-json
 create mode 100644 tests/expected/dmesg/cid-kmsg-colors
 create mode 100644 tests/expected/dmesg/cid-kmsg-console-levels
 create mode 100644 tests/expected/dmesg/cid-kmsg-decode
 create mode 100644 tests/expected/dmesg/cid-kmsg-delta
 create mode 100644 tests/expected/dmesg/cid-kmsg-facilities
 create mode 100644 tests/expected/dmesg/cid-kmsg-indentation
 create mode 100644 tests/expected/dmesg/cid-kmsg-json
 create mode 100644 tests/expected/dmesg/cid-kmsg-limit
 create mode 100644 tests/ts/dmesg/cid-input
 create mode 100755 tests/ts/dmesg/cid-json
 create mode 100755 tests/ts/dmesg/cid-kmsg-colors
 create mode 100755 tests/ts/dmesg/cid-kmsg-console-levels
 create mode 100755 tests/ts/dmesg/cid-kmsg-decode
 create mode 100755 tests/ts/dmesg/cid-kmsg-delta
 create mode 100755 tests/ts/dmesg/cid-kmsg-facilities
 create mode 100755 tests/ts/dmesg/cid-kmsg-indentation
 create mode 100644 tests/ts/dmesg/cid-kmsg-input
 create mode 100755 tests/ts/dmesg/cid-kmsg-json
 create mode 100755 tests/ts/dmesg/cid-kmsg-limit
 create mode 100644 tests/ts/dmesg/cid-kmsg-newlines

diff --git a/include/pathnames.h b/include/pathnames.h
index caf0e63d4..81fa405f6 100644
--- a/include/pathnames.h
+++ b/include/pathnames.h
@@ -230,4 +230,7 @@
 /* cgroup path */
 #define _PATH_SYS_CGROUP	"/sys/fs/cgroup"
 
+/* Maximum number of PIDs system supports */
+#define _PATH_PROC_PIDMAX	"/proc/sys/kernel/pid_max"
+
 #endif /* PATHNAMES_H */
diff --git a/sys-utils/dmesg.c b/sys-utils/dmesg.c
index 77728b419..e27966b05 100644
--- a/sys-utils/dmesg.c
+++ b/sys-utils/dmesg.c
@@ -13,7 +13,9 @@
  */
 #include <stdio.h>
 #include <getopt.h>
+#include <stdbool.h>
 #include <stdlib.h>
+#include <string.h>
 #include <sys/klog.h>
 #include <sys/syslog.h>
 #include <sys/time.h>
@@ -41,6 +43,7 @@
 #include "mangle.h"
 #include "pager.h"
 #include "jsonwrt.h"
+#include "pathnames.h"
 
 /* Close the log.  Currently a NOP. */
 #define SYSLOG_ACTION_CLOSE          0
@@ -65,6 +68,12 @@
 /* Return size of the log buffer */
 #define SYSLOG_ACTION_SIZE_BUFFER   10
 
+#define PID_CHARS_MAX sizeof(stringify_value(LONG_MAX))
+#define PID_CHARS_DEFAULT sizeof(stringify_value(INT_MAX))
+#define SYSLOG_DEFAULT_CALLER_ID_CHARS sizeof(stringify_value(SHRT_MAX))-1
+#define DMESG_CALLER_PREFIX "caller="
+#define DMESG_CALLER_PREFIXSZ (sizeof(DMESG_CALLER_PREFIX)-1)
+
 /*
  * Color scheme
  */
@@ -233,6 +242,7 @@ struct dmesg_control {
 			force_prefix:1;	/* force timestamp and decode prefix
 					   on each line */
 	int		indent;		/* due to timestamps if newline */
+	size_t          caller_id_size;   /* PRINTK_CALLERID max field size */
 };
 
 struct dmesg_record {
@@ -242,6 +252,7 @@ struct dmesg_record {
 	int		level;
 	int		facility;
 	struct timeval  tv;
+	char		caller_id[PID_CHARS_MAX];
 
 	const char	*next;		/* buffer with next unparsed record */
 	size_t		next_size;	/* size of the next buffer */
@@ -254,6 +265,7 @@ struct dmesg_record {
 		(_r)->level = -1; \
 		(_r)->tv.tv_sec = 0; \
 		(_r)->tv.tv_usec = 0; \
+		(_r)->caller_id[0] = 0; \
 	} while (0)
 
 static int process_kmsg(struct dmesg_control *ctl);
@@ -551,6 +563,45 @@ static int get_syslog_buffer_size(void)
 	return n > 0 ? n : 0;
 }
 
+/*
+ * Get the number of characters needed to hold the maximum number
+ * of tasks this system supports. This size of string could hold
+ * a thread id large enough for the highest thread id.
+ * This is needed to determine the number of characters reserved for
+ * the PRINTK_CALLER field if it has been configured in the Linux Kernel.
+ *
+ * The number of digits sets the max value since the value can't exceed
+ * a value of that size. The /proc field defined by _PATH_PROC_PIDMAX
+ * holds the maximum number of PID values that may be ussed by the system,
+ * so 0 to that value minus one.
+ *
+ * For determining the size of the PRINTK_CALLER field, we make the safe
+ * assumption that the number of threads >= number of cpus. This because
+ * the PRINTK_CALLER field can hold either a thread id or a CPU id value.
+ *
+ * If we can't access the pid max kernel proc entry we assign a default
+ * field size of 5 characters as that is what the old syslog interface
+ * uses as the reserved field size. This is justified because 32-bit Linux
+ * systems are limited to PID values between (0-32767).
+ *
+ */
+static size_t max_threads_id_size(void)
+{
+	char taskmax[PID_CHARS_MAX] = {'\0'};
+	ssize_t rdsize;
+	int fd;
+
+	fd = open(_PATH_PROC_PIDMAX, O_RDONLY);
+	if (fd == -1)
+		return PID_CHARS_DEFAULT;
+
+	rdsize = read(fd, taskmax, sizeof(taskmax));
+	if (rdsize == -1)
+		return PID_CHARS_DEFAULT;
+
+	return strnlen(taskmax, sizeof(taskmax));
+}
+
 /*
  * Reads messages from regular file by mmap
  */
@@ -624,6 +675,8 @@ static ssize_t process_buffer(struct dmesg_control *ctl, char **buf)
 			ctl->bufsize = get_syslog_buffer_size();
 
 		n = read_syslog_buffer(ctl, buf);
+		/* Set number of PID characters for caller_id spacing */
+		ctl->caller_id_size = SYSLOG_DEFAULT_CALLER_ID_CHARS;
 		break;
 	case DMESG_METHOD_KMSG:
 		if (ctl->filename)
@@ -728,6 +781,39 @@ static const char *skip_item(const char *begin, const char *end, const char *sep
 	return begin;
 }
 
+/*
+ * Checks to see if the caller (caller id) field is present in the kmsg record.
+ * This is true if the PRINTK_CALLER config option has been set in the kernel.
+ *
+ * If the caller_id is found in the kmsg buffer then return the id and id type
+ * to the caller in dmesg caller_id. Returns string pointer to next value.
+ *
+ */
+static const char *parse_callerid(const char *p_str, const char *end,
+				  struct dmesg_record *p_drec)
+{
+	const char *p_after;
+	const char *p_next;
+	size_t cid_size;
+	char *p_scn;
+	char *p_cid;
+
+	/* Check for PRINTK_CALLER prefix, must be before msg text */
+	p_cid = strstr(p_str, DMESG_CALLER_PREFIX);
+	p_scn = strchr(p_str, ';');
+	if (p_cid != NULL && p_drec != NULL && p_scn != NULL && p_cid < p_scn) {
+		p_next = p_cid + DMESG_CALLER_PREFIXSZ;
+		p_after = skip_item(p_next, end, ",;");
+		cid_size = p_after - p_next;
+		if (cid_size < sizeof(p_drec->caller_id))
+			xstrncpy(p_drec->caller_id, p_next, cid_size);
+		else
+			return p_str;
+		return p_after;
+	}
+	return p_str;
+}
+
 /*
  * Parses one record from syslog(2) buffer
  */
@@ -795,8 +881,22 @@ static int get_next_syslog_record(struct dmesg_control *ctl,
 				begin++;
 		}
 
-		rec->mesg = begin;
-		rec->mesg_size = end - begin;
+		if (*begin == '[' && (*(begin + 1) == ' ' ||
+			(*(begin + 1) == 'T' || *(begin + 1) == 'C'))) {
+			const char *start = begin + 1;
+			size_t id_size;
+
+			start = start + strspn(start, " ");
+			begin = skip_item(begin, end, "]");
+			id_size = begin - start;
+			if (id_size < sizeof(rec->caller_id))
+				xstrncpy(rec->caller_id, start, id_size);
+			rec->mesg = begin + 1;
+			rec->mesg_size = end - begin - 1;
+		} else {
+			rec->mesg = begin;
+			rec->mesg_size = end - begin;
+		}
 
 		/* Don't count \n from the last message to the message size */
 		if (*end != '\n' && *(end - 1) == '\n')
@@ -1101,6 +1201,19 @@ full_output:
 			color_disable();
 	}
 
+	if (*rec->caller_id) {
+		if (ctl->json) {
+			ul_jsonwrt_value_s(&ctl->jfmt, "caller", rec->caller_id);
+		} else {
+			char cidbuf[PID_CHARS_MAX+3] = {'\0'};
+
+			sprintf(cidbuf, "[%*s] ",
+				(char)ctl->caller_id_size, rec->caller_id);
+			ctl->indent += strnlen(cidbuf, sizeof(cidbuf));
+			fputs(cidbuf, stdout);
+		}
+	}
+
 	/*
 	 * A kernel message may contain several lines of output, separated
 	 * by '\n'.  If the timestamp and decode outputs are forced then each
@@ -1284,7 +1397,10 @@ static int parse_kmsg_record(struct dmesg_control *ctl,
 		goto mesg;
 
 	/* D) optional fields (ignore) */
-	p = skip_item(p, end, ";");
+	p = skip_item(p, end, ",;");
+
+	/* Include optional PRINTK_CALLER field if it is present */
+	p = parse_callerid(p, end, rec);
 
 mesg:
 	/* E) message text */
@@ -1336,6 +1452,9 @@ static int process_kmsg(struct dmesg_control *ctl)
 	if (ctl->method != DMESG_METHOD_KMSG || ctl->kmsg < 0)
 		return -1;
 
+	/* Determine number of PID characters for caller_id spacing */
+	ctl->caller_id_size = max_threads_id_size();
+
 	/*
 	 * The very first read() call is done in kmsg_init() where we test
 	 * /dev/kmsg usability. The return code from the initial read() is
@@ -1446,6 +1565,7 @@ int main(int argc, char *argv[])
 		.kmsg = -1,
 		.time_fmt = DMESG_TIMEFTM_TIME,
 		.indent = 0,
+		.caller_id_size = 0,
 	};
 	int colormode = UL_COLORMODE_UNDEF;
 	enum {
@@ -1538,10 +1658,12 @@ int main(int argc, char *argv[])
 		case 'F':
 			ctl.filename = optarg;
 			ctl.method = DMESG_METHOD_MMAP;
+			ctl.caller_id_size = SYSLOG_DEFAULT_CALLER_ID_CHARS;
 			break;
 		case 'K':
 			ctl.filename = optarg;
 			ctl.method = DMESG_METHOD_KMSG;
+			ctl.caller_id_size = max_threads_id_size();
 			break;
 		case 'f':
 			ctl.fltr_fac = 1;
diff --git a/tests/expected/dmesg/cid-json b/tests/expected/dmesg/cid-json
new file mode 100644
index 000000000..8a4d0e23d
--- /dev/null
+++ b/tests/expected/dmesg/cid-json
@@ -0,0 +1,535 @@
+{
+   "dmesg": [
+      {
+         "pri": 0,
+         "time":     0.000000,
+         "caller": "T0",
+         "msg": "example[0]"
+      },{
+         "pri": 1,
+         "time":     1.000000,
+         "caller": "T1",
+         "msg": "example[1]"
+      },{
+         "pri": 2,
+         "time":     8.000000,
+         "caller": "T2",
+         "msg": "example[2]"
+      },{
+         "pri": 3,
+         "time":    27.000000,
+         "caller": "T3",
+         "msg": "example[3]"
+      },{
+         "pri": 4,
+         "time":    64.000000,
+         "caller": "T4",
+         "msg": "example[4]"
+      },{
+         "pri": 5,
+         "time":   125.000000,
+         "caller": "T5",
+         "msg": "example[5]"
+      },{
+         "pri": 6,
+         "time":   216.000000,
+         "caller": "T6",
+         "msg": "example[6]"
+      },{
+         "pri": 7,
+         "time":   343.000000,
+         "caller": "T7",
+         "msg": "example[7]"
+      },{
+         "pri": 8,
+         "time":   512.000000,
+         "caller": "T8",
+         "msg": "example[8]"
+      },{
+         "pri": 9,
+         "time":   729.000000,
+         "caller": "T9",
+         "msg": "example[9]"
+      },{
+         "pri": 10,
+         "time":  1000.000000,
+         "caller": "T10",
+         "msg": "example[10]"
+      },{
+         "pri": 11,
+         "time":  1331.000000,
+         "caller": "T11",
+         "msg": "example[11]"
+      },{
+         "pri": 12,
+         "time":  1728.000000,
+         "caller": "T12",
+         "msg": "example[12]"
+      },{
+         "pri": 13,
+         "time":  2197.000000,
+         "caller": "T13",
+         "msg": "example[13]"
+      },{
+         "pri": 14,
+         "time":  2744.000000,
+         "caller": "T14",
+         "msg": "example[14]"
+      },{
+         "pri": 15,
+         "time":  3375.000000,
+         "caller": "T15",
+         "msg": "example[15]"
+      },{
+         "pri": 16,
+         "time":  4096.000000,
+         "caller": "T16",
+         "msg": "example[16]"
+      },{
+         "pri": 17,
+         "time":  4913.000000,
+         "caller": "T17",
+         "msg": "example[17]"
+      },{
+         "pri": 18,
+         "time":  5832.000000,
+         "caller": "T18",
+         "msg": "example[18]"
+      },{
+         "pri": 19,
+         "time":  6859.000000,
+         "caller": "T19",
+         "msg": "example[19]"
+      },{
+         "pri": 20,
+         "time":  8000.000000,
+         "caller": "T20",
+         "msg": "example[20]"
+      },{
+         "pri": 21,
+         "time":  9261.000000,
+         "caller": "T21",
+         "msg": "example[21]"
+      },{
+         "pri": 22,
+         "time": 10648.000000,
+         "caller": "T22",
+         "msg": "example[22]"
+      },{
+         "pri": 23,
+         "time": 12167.000000,
+         "caller": "T23",
+         "msg": "example[23]"
+      },{
+         "pri": 24,
+         "time": 13824.000000,
+         "caller": "T24",
+         "msg": "example[24]"
+      },{
+         "pri": 25,
+         "time": 15625.000000,
+         "caller": "T25",
+         "msg": "example[25]"
+      },{
+         "pri": 26,
+         "time": 17576.000000,
+         "caller": "T26",
+         "msg": "example[26]"
+      },{
+         "pri": 27,
+         "time": 19683.000000,
+         "caller": "T27",
+         "msg": "example[27]"
+      },{
+         "pri": 28,
+         "time": 21952.000000,
+         "caller": "T28",
+         "msg": "example[28]"
+      },{
+         "pri": 29,
+         "time": 24389.000000,
+         "caller": "T29",
+         "msg": "example[29]"
+      },{
+         "pri": 30,
+         "time": 27000.000000,
+         "caller": "T10",
+         "msg": "example[30]"
+      },{
+         "pri": 31,
+         "time": 29791.000000,
+         "caller": "T31",
+         "msg": "example[31]"
+      },{
+         "pri": 32,
+         "time": 32768.000000,
+         "caller": "T32",
+         "msg": "example[32]"
+      },{
+         "pri": 33,
+         "time": 35937.000000,
+         "caller": "T33",
+         "msg": "example[33]"
+      },{
+         "pri": 34,
+         "time": 39304.000000,
+         "caller": "T34",
+         "msg": "example[34]"
+      },{
+         "pri": 35,
+         "time": 42875.000000,
+         "caller": "T35",
+         "msg": "example[35]"
+      },{
+         "pri": 36,
+         "time": 46656.000000,
+         "caller": "T36",
+         "msg": "example[36]"
+      },{
+         "pri": 37,
+         "time": 50653.000000,
+         "caller": "T37",
+         "msg": "example[37]"
+      },{
+         "pri": 38,
+         "time": 54872.000000,
+         "caller": "T38",
+         "msg": "example[38]"
+      },{
+         "pri": 39,
+         "time": 59319.000000,
+         "caller": "T39",
+         "msg": "example[39]"
+      },{
+         "pri": 40,
+         "time": 64000.000000,
+         "caller": "T40",
+         "msg": "example[40]"
+      },{
+         "pri": 41,
+         "time": 68921.000000,
+         "caller": "T41",
+         "msg": "example[41]"
+      },{
+         "pri": 42,
+         "time": 74088.000000,
+         "caller": "T42",
+         "msg": "example[42]"
+      },{
+         "pri": 43,
+         "time": 79507.000000,
+         "caller": "T43",
+         "msg": "example[43]"
+      },{
+         "pri": 44,
+         "time": 85184.000000,
+         "caller": "T44",
+         "msg": "example[44]"
+      },{
+         "pri": 45,
+         "time": 91125.000000,
+         "caller": "T45",
+         "msg": "example[45]"
+      },{
+         "pri": 46,
+         "time": 97336.000000,
+         "caller": "T46",
+         "msg": "example[46]"
+      },{
+         "pri": 47,
+         "time": 103823.000000,
+         "caller": "T47",
+         "msg": "example[47]"
+      },{
+         "pri": 48,
+         "time": 110592.000000,
+         "caller": "T48",
+         "msg": "example[48]"
+      },{
+         "pri": 49,
+         "time": 117649.000000,
+         "caller": "T49",
+         "msg": "example[49]"
+      },{
+         "pri": 50,
+         "time": 125000.000000,
+         "caller": "T50",
+         "msg": "example[50]"
+      },{
+         "pri": 51,
+         "time": 132651.000000,
+         "caller": "T51",
+         "msg": "example[51]"
+      },{
+         "pri": 52,
+         "time": 140608.000000,
+         "caller": "T52",
+         "msg": "example[52]"
+      },{
+         "pri": 53,
+         "time": 148877.000000,
+         "caller": "T53",
+         "msg": "example[53]"
+      },{
+         "pri": 54,
+         "time": 157464.000000,
+         "caller": "T54",
+         "msg": "example[54]"
+      },{
+         "pri": 55,
+         "time": 166375.000000,
+         "caller": "T55",
+         "msg": "example[55]"
+      },{
+         "pri": 56,
+         "time": 175616.000000,
+         "caller": "T56",
+         "msg": "example[56]"
+      },{
+         "pri": 57,
+         "time": 185193.000000,
+         "caller": "T57",
+         "msg": "example[57]"
+      },{
+         "pri": 58,
+         "time": 195112.000000,
+         "caller": "T58",
+         "msg": "example[58]"
+      },{
+         "pri": 59,
+         "time": 205379.000000,
+         "caller": "T59",
+         "msg": "example[59]"
+      },{
+         "pri": 60,
+         "time": 216000.000000,
+         "caller": "T60",
+         "msg": "example[60]"
+      },{
+         "pri": 61,
+         "time": 226981.000000,
+         "caller": "T61",
+         "msg": "example[61]"
+      },{
+         "pri": 62,
+         "time": 238328.000000,
+         "caller": "T62",
+         "msg": "example[62]"
+      },{
+         "pri": 63,
+         "time": 250047.000000,
+         "caller": "T63",
+         "msg": "example[63]"
+      },{
+         "pri": 64,
+         "time": 262144.000000,
+         "caller": "T64",
+         "msg": "example[64]"
+      },{
+         "pri": 65,
+         "time": 274625.000000,
+         "caller": "T65",
+         "msg": "example[65]"
+      },{
+         "pri": 66,
+         "time": 287496.000000,
+         "caller": "T66",
+         "msg": "example[66]"
+      },{
+         "pri": 67,
+         "time": 300763.000000,
+         "caller": "T67",
+         "msg": "example[67]"
+      },{
+         "pri": 68,
+         "time": 314432.000000,
+         "caller": "T68",
+         "msg": "example[68]"
+      },{
+         "pri": 69,
+         "time": 328509.000000,
+         "caller": "T69",
+         "msg": "example[69]"
+      },{
+         "pri": 70,
+         "time": 343000.000000,
+         "caller": "T70",
+         "msg": "example[70]"
+      },{
+         "pri": 71,
+         "time": 357911.000000,
+         "caller": "T71",
+         "msg": "example[71]"
+      },{
+         "pri": 72,
+         "time": 373248.000000,
+         "caller": "T72",
+         "msg": "example[72]"
+      },{
+         "pri": 73,
+         "time": 389017.000000,
+         "caller": "T73",
+         "msg": "example[73]"
+      },{
+         "pri": 74,
+         "time": 405224.000000,
+         "caller": "T74",
+         "msg": "example[74]"
+      },{
+         "pri": 75,
+         "time": 421875.000000,
+         "caller": "T75",
+         "msg": "example[75]"
+      },{
+         "pri": 76,
+         "time": 438976.000000,
+         "caller": "T76",
+         "msg": "example[76]"
+      },{
+         "pri": 77,
+         "time": 456533.000000,
+         "caller": "T77",
+         "msg": "example[77]"
+      },{
+         "pri": 78,
+         "time": 474552.000000,
+         "caller": "T78",
+         "msg": "example[78]"
+      },{
+         "pri": 79,
+         "time": 493039.000000,
+         "caller": "T79",
+         "msg": "example[79]"
+      },{
+         "pri": 80,
+         "time": 512000.000000,
+         "caller": "T80",
+         "msg": "example[80]"
+      },{
+         "pri": 81,
+         "time": 531441.000000,
+         "caller": "T81",
+         "msg": "example[81]"
+      },{
+         "pri": 82,
+         "time": 551368.000000,
+         "caller": "T82",
+         "msg": "example[82]"
+      },{
+         "pri": 83,
+         "time": 571787.000000,
+         "caller": "T83",
+         "msg": "example[83]"
+      },{
+         "pri": 84,
+         "time": 592704.000000,
+         "caller": "T84",
+         "msg": "example[84]"
+      },{
+         "pri": 85,
+         "time": 614125.000000,
+         "caller": "T85",
+         "msg": "example[85]"
+      },{
+         "pri": 86,
+         "time": 636056.000000,
+         "caller": "T86",
+         "msg": "example[86]"
+      },{
+         "pri": 87,
+         "time": 658503.000000,
+         "caller": "T87",
+         "msg": "example[87]"
+      },{
+         "pri": 88,
+         "time": 681472.000000,
+         "caller": "T88",
+         "msg": "example[88]"
+      },{
+         "pri": 89,
+         "time": 704969.000000,
+         "caller": "T89",
+         "msg": "example[89]"
+      },{
+         "pri": 90,
+         "time": 729000.000000,
+         "caller": "T90",
+         "msg": "example[90]"
+      },{
+         "pri": 91,
+         "time": 753571.000000,
+         "caller": "T91",
+         "msg": "example[91]"
+      },{
+         "pri": 92,
+         "time": 778688.000000,
+         "caller": "T92",
+         "msg": "example[92]"
+      },{
+         "pri": 93,
+         "time": 804357.000000,
+         "caller": "T93",
+         "msg": "example[93]"
+      },{
+         "pri": 94,
+         "time": 830584.000000,
+         "caller": "T94",
+         "msg": "example[94]"
+      },{
+         "pri": 95,
+         "time": 857375.000000,
+         "caller": "T95",
+         "msg": "example[95]"
+      },{
+         "pri": 96,
+         "time": 884736.000000,
+         "caller": "T96",
+         "msg": "example[96]"
+      },{
+         "pri": 97,
+         "time": 912673.000000,
+         "caller": "T97",
+         "msg": "example[97]"
+      },{
+         "pri": 98,
+         "time": 941192.000000,
+         "caller": "T98",
+         "msg": "example[98]"
+      },{
+         "pri": 99,
+         "time": 970299.000000,
+         "caller": "T99",
+         "msg": "example[99]"
+      },{
+         "pri": 100,
+         "time": 1000000.000000,
+         "caller": "T100",
+         "msg": "example[100]"
+      },{
+         "pri": 101,
+         "time": 1030301.000000,
+         "caller": "T101",
+         "msg": "example[101]"
+      },{
+         "pri": 102,
+         "time": 1061208.000000,
+         "caller": "T102",
+         "msg": "example[102]"
+      },{
+         "pri": 103,
+         "time": 1092727.000000,
+         "caller": "T103",
+         "msg": "example[103]"
+      },{
+         "pri": 104,
+         "time": 1124864.000000,
+         "caller": "T104",
+         "msg": "example[104]"
+      },{
+         "pri": 150,
+         "time": 4557523.000000,
+         "caller": "T105",
+         "msg": "example[105]"
+      }
+   ]
+}
diff --git a/tests/expected/dmesg/cid-kmsg-colors b/tests/expected/dmesg/cid-kmsg-colors
new file mode 100644
index 000000000..7d11dae33
--- /dev/null
+++ b/tests/expected/dmesg/cid-kmsg-colors
@@ -0,0 +1,45 @@
+kern  :emerg : ^[[32m[    0.000000] ^[[0m[      T1] Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000
+kern  :alert : ^[[32m[    0.000001] ^[[0m[      T2] ^[[33mCommand line: ^[[0m^[[7m^[[31minitrd=\ucode.img initrd=\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system^[[0m
+kern  :crit  : ^[[32m[    0.000002] ^[[0m[      T3] ^[[1m^[[31mBIOS-provided physical RAM map:^[[0m
+kern  :err   : ^[[32m[    0.000003] ^[[0m[      T4] ^[[33mBIOS-e820: ^[[0m^[[31m[mem 0x0000000000000000-0x000000000009efff] usable^[[0m
+kern  :warn  : ^[[32m[    0.000004] ^[[0m[      T5] ^[[33mBIOS-e820: ^[[0m^[[1m[mem 0x000000000009f000-0x00000000000bffff] reserved^[[0m
+kern  :notice: ^[[32m[    0.000005] ^[[0m[      T6] ^[[33mBIOS-e820: ^[[0m[mem 0x0000000000100000-0x0000000009afffff] usable
+kern  :info  : ^[[32m[    0.000006] ^[[0m[      T7] ^[[33mBIOS-e820: ^[[0m[mem 0x0000000009b00000-0x0000000009dfffff] reserved
+kern  :debug : ^[[32m[    0.000007] ^[[0m[      T8] ^[[33mBIOS-e820: ^[[0m[mem 0x0000000009e00000-0x0000000009efffff] usable
+kern  :info  : ^[[32m[    0.000008] ^[[0m[      T9] ^[[33mBIOS-e820: ^[[0m[mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS
+kern  :info  : ^[[32m[    0.000009] ^[[0m[     T10] ^[[33mBIOS-e820: ^[[0m[mem 0x0000000009f3c000-0x000000004235ffff] usable
+kern  :info  : ^[[32m[    0.000010] ^[[0m[     T11] ^[[33mBIOS-e820: ^[[0m[mem 0x0000000042360000-0x000000004455ffff] reserved
+kern  :info  : ^[[32m[    0.201607] ^[[0m[     T12] ^[[33msmp: ^[[0mBringing up secondary CPUs ...
+kern  :info  : ^[[32m[    0.201607] ^[[0m[     T13] ^[[33msmpboot: ^[[0mx86: Booting SMP configuration:
+kern  :warn  : ^[[32m[    0.209670] ^[[0m[     T14] ^[[1m  #1  #3  #5  #7^[[0m
+kern  :info  : ^[[32m[    0.212630] ^[[0m[     T15] ^[[33msmp: ^[[0mBrought up 1 node, 16 CPUs
+kern  :notice: ^[[32m[    0.215936] ^[[0m[     T16] ^[[33maudit: ^[[0mtype=2000 audit(1702926179.015:1): state=initialized audit_enabled=0 res=1
+kern  :info  : ^[[32m[    0.215937] ^[[0m[     T17] ^[[33mthermal_sys: ^[[0mRegistered thermal governor 'fair_share'
+kern  :warn  : ^[[32m[    0.215966] ^[[0m[     T18] ^[[33mENERGY_PERF_BIAS: ^[[0m^[[1mSet to 'normal', was 'performance'^[[0m
+kern  :info  : ^[[32m[    0.367657] ^[[0m[     T19] ^[[33mACPI: ^[[0m\_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+kern  :info  : ^[[32m[    0.368615] ^[[0m[     T20] ^[[33mACPI: ^[[0m\_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+kern  :info  : ^[[32m[    0.376316] ^[[0m[     T21] ^[[33mACPI: ^[[0m\_SB_.PRWL: New power resource
+kern  :info  : ^[[32m[    0.376343] ^[[0m[     T22] ^[[33mACPI: ^[[0m\_SB_.PRWB: New power resource
+kern  :info  : ^[[32m[    0.377373] ^[[0m[     T23] ^[[33mACPI: ^[[0mPCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+kern  :info  : ^[[32m[    0.377378] ^[[0m[     T24] ^[[33macpi PNP0A08:00: ^[[0m_OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+kern  :info  : ^[[32m[    0.377569] ^[[0m[     T25] ^[[33macpi PNP0A08:00: ^[[0m_OSC: platform does not support [SHPCHotplug AER]
+kern  :info  : ^[[32m[    0.377933] ^[[0m[     T26] ^[[33macpi PNP0A08:00: ^[[0m_OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+kern  :info  : ^[[32m[    0.378458] ^[[0m[     T27] PCI host bridge to bus 0000:00
+kern  :info  : ^[[32m[    0.378459] ^[[0m[     T28] ^[[33mpci_bus 0000:00: ^[[0mroot bus resource [io  0x0000-0x0cf7 window]
+kern  :info  : ^[[32m[    0.378461] ^[[0m[     T29] ^[[33mpci_bus 0000:00: ^[[0mroot bus resource [io  0x0d00-0xffff window]
+user  :notice: ^[[32m[    9.398562] ^[[0m[     T30] user network daemon initialization complete
+daemon:info  : ^[[32m[   10.441520] ^[[0m[     T31] ^[[33msystemd[1]: ^[[0msystemd 254.7-1.fc39 running in system mode
+daemon:info  : ^[[32m[   11.441524] ^[[0m[     T32] ^[[33msystemd[1]: ^[[0mDetected architecture x86-64.
+daemon:info  : ^[[32m[   12.441525] ^[[0m[     T33] ^[[33msystemd[1]: ^[[0mRunning in initrd.
+daemon:info  : ^[[32m[   13.541598] ^[[0m[     T34] ^[[33msystemd[1]: ^[[0mHostname set to <catalina>.
+kern  :info  : ^[[32m[   15.641860] ^[[0m[     T35] ^[[33musb 3-3: ^[[0mNew USB device found, idVendor=1a40, idProduct=0101, bcdDevice= 1.11
+kern  :err   : ^[[32m[   16.690000] ^[[0m[     T36] ^[[33mSerial bus multi instantiate pseudo device driver INT3515:00: ^[[0m^[[31merror -ENXIO: IRQ index 1 not found.^[[0m
+kern  :err   : ^[[32m[   17.710000] ^[[0m[     T37] ^[[33msnd_hda_intel 0000:00:1f.3: ^[[0m^[[31mCORB reset timeout#2, CORBRP = 65535^[[0m
+syslog:info  : ^[[32m[   18.820000] ^[[0m[     T38] ^[[33msystemd-journald[723]: ^[[0mReceived client request to flush runtime journal.
+syslog:warn  : ^[[32m[   20.840000] ^[[0m[     T39] ^[[33msystemd-journald[723]: ^[[0m^[[1mFile /var/log/journal/a124ea923b144109a12d557d5ac53179/system.journal corrupted or uncleanly shut down, renaming and replacing.^[[0m
+syslog:info  : ^[[32m[   21.852348] ^[[0m[     T40] ^[[33msystemd-journald[723]: ^[[0m/var/log/journal/ad7a2547ac0e4342a342e62a34a3eae4/user-1000.journal: Journal file uses a different sequence number ID, rotating.
+kern  :warn  : ^[[32m[   24.871100] ^[[0m[      41] ^[[33mPEFILE: ^[[0m^[[1mUnsigned PE binary^[[0m
+kern  :err   : ^[[32m[   33.918091] ^[[0m[      42] ^[[33msnd_hda_intel 0000:00:1f.3: ^[[0m^[[31mCORB reset timeout#2, CORBRP = 65535^[[0m
+kern  :info  : ^[[32m[  144.931785] ^[[0m[      C1] ^[[33musb 3-3.1: ^[[0mdevice firmware changed
+kern  :info  : ^[[32m[  145.953248] ^[[0m[      C2] ^[[33musb 3-3.1: ^[[0mUSB disconnect, device number 44
+kern  :info  : ^[[32m[  147.981859] ^[[0m[      C3] ^[[33musb 3-3.1: ^[[0mNew USB device found, idVendor=17ef, idProduct=6047, bcdDevice= 3.30
diff --git a/tests/expected/dmesg/cid-kmsg-console-levels b/tests/expected/dmesg/cid-kmsg-console-levels
new file mode 100644
index 000000000..59c343108
--- /dev/null
+++ b/tests/expected/dmesg/cid-kmsg-console-levels
@@ -0,0 +1,97 @@
+[    0.000000] [      T1] Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000
+[    0.000001] [      T2] Command line: initrd=\ucode.img initrd=\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system
+[    0.000002] [      T3] BIOS-provided physical RAM map:
+[    0.000003] [      T4] BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable
+[   16.690000] [     T36] Serial bus multi instantiate pseudo device driver INT3515:00: error -ENXIO: IRQ index 1 not found.
+[   17.710000] [     T37] snd_hda_intel 0000:00:1f.3: CORB reset timeout#2, CORBRP = 65535
+[   33.918091] [      42] snd_hda_intel 0000:00:1f.3: CORB reset timeout#2, CORBRP = 65535
+[    0.000004] [      T5] BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved
+[    0.209670] [     T14]   #1  #3  #5  #7
+[    0.215966] [     T18] ENERGY_PERF_BIAS: Set to 'normal', was 'performance'
+[   20.840000] [     T39] systemd-journald[723]: File /var/log/journal/a124ea923b144109a12d557d5ac53179/system.journal corrupted or uncleanly shut down, renaming and replacing.
+[   24.871100] [      41] PEFILE: Unsigned PE binary
+[    0.000005] [      T6] BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable
+[    0.215936] [     T16] audit: type=2000 audit(1702926179.015:1): state=initialized audit_enabled=0 res=1
+[    9.398562] [     T30] user network daemon initialization complete
+[    0.000006] [      T7] BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved
+[    0.000008] [      T9] BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS
+[    0.000009] [     T10] BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable
+[    0.000010] [     T11] BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved
+[    0.201607] [     T12] smp: Bringing up secondary CPUs ...
+[    0.201607] [     T13] smpboot: x86: Booting SMP configuration:
+[    0.212630] [     T15] smp: Brought up 1 node, 16 CPUs
+[    0.215937] [     T17] thermal_sys: Registered thermal governor 'fair_share'
+[    0.367657] [     T19] ACPI: \_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+[    0.368615] [     T20] ACPI: \_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+[    0.376316] [     T21] ACPI: \_SB_.PRWL: New power resource
+[    0.376343] [     T22] ACPI: \_SB_.PRWB: New power resource
+[    0.377373] [     T23] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+[    0.377378] [     T24] acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+[    0.377569] [     T25] acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]
+[    0.377933] [     T26] acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+[    0.378458] [     T27] PCI host bridge to bus 0000:00
+[    0.378459] [     T28] pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]
+[    0.378461] [     T29] pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]
+[   10.441520] [     T31] systemd[1]: systemd 254.7-1.fc39 running in system mode
+[   11.441524] [     T32] systemd[1]: Detected architecture x86-64.
+[   12.441525] [     T33] systemd[1]: Running in initrd.
+[   13.541598] [     T34] systemd[1]: Hostname set to <catalina>.
+[   15.641860] [     T35] usb 3-3: New USB device found, idVendor=1a40, idProduct=0101, bcdDevice= 1.11
+[   18.820000] [     T38] systemd-journald[723]: Received client request to flush runtime journal.
+[   21.852348] [     T40] systemd-journald[723]: /var/log/journal/ad7a2547ac0e4342a342e62a34a3eae4/user-1000.journal: Journal file uses a different sequence number ID, rotating.
+[  144.931785] [      C1] usb 3-3.1: device firmware changed
+[  145.953248] [      C2] usb 3-3.1: USB disconnect, device number 44
+[  147.981859] [      C3] usb 3-3.1: New USB device found, idVendor=17ef, idProduct=6047, bcdDevice= 3.30
+[    0.000007] [      T8] BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable
+[    0.000000] [      T1] Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000
+[    0.000001] [      T2] Command line: initrd=\ucode.img initrd=\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system
+[    0.000002] [      T3] BIOS-provided physical RAM map:
+[    0.000003] [      T4] BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable
+[   16.690000] [     T36] Serial bus multi instantiate pseudo device driver INT3515:00: error -ENXIO: IRQ index 1 not found.
+[   17.710000] [     T37] snd_hda_intel 0000:00:1f.3: CORB reset timeout#2, CORBRP = 65535
+[   33.918091] [      42] snd_hda_intel 0000:00:1f.3: CORB reset timeout#2, CORBRP = 65535
+[    0.000000] [      T1] Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000
+[    0.000003] [      T4] BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable
+[    0.000004] [      T5] BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved
+[    0.000005] [      T6] BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable
+[    0.000006] [      T7] BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved
+[    0.000007] [      T8] BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable
+[    0.000008] [      T9] BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS
+[    0.000009] [     T10] BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable
+[    0.000010] [     T11] BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved
+[    0.201607] [     T12] smp: Bringing up secondary CPUs ...
+[    0.201607] [     T13] smpboot: x86: Booting SMP configuration:
+[    0.209670] [     T14]   #1  #3  #5  #7
+[    0.212630] [     T15] smp: Brought up 1 node, 16 CPUs
+[    0.215936] [     T16] audit: type=2000 audit(1702926179.015:1): state=initialized audit_enabled=0 res=1
+[    0.215937] [     T17] thermal_sys: Registered thermal governor 'fair_share'
+[    0.215966] [     T18] ENERGY_PERF_BIAS: Set to 'normal', was 'performance'
+[    0.367657] [     T19] ACPI: \_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+[    0.368615] [     T20] ACPI: \_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+[    0.376316] [     T21] ACPI: \_SB_.PRWL: New power resource
+[    0.376343] [     T22] ACPI: \_SB_.PRWB: New power resource
+[    0.377373] [     T23] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+[    0.377378] [     T24] acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+[    0.377569] [     T25] acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]
+[    0.377933] [     T26] acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+[    0.378458] [     T27] PCI host bridge to bus 0000:00
+[    0.378459] [     T28] pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]
+[    0.378461] [     T29] pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]
+[    9.398562] [     T30] user network daemon initialization complete
+[   10.441520] [     T31] systemd[1]: systemd 254.7-1.fc39 running in system mode
+[   11.441524] [     T32] systemd[1]: Detected architecture x86-64.
+[   12.441525] [     T33] systemd[1]: Running in initrd.
+[   13.541598] [     T34] systemd[1]: Hostname set to <catalina>.
+[   15.641860] [     T35] usb 3-3: New USB device found, idVendor=1a40, idProduct=0101, bcdDevice= 1.11
+[   16.690000] [     T36] Serial bus multi instantiate pseudo device driver INT3515:00: error -ENXIO: IRQ index 1 not found.
+[   17.710000] [     T37] snd_hda_intel 0000:00:1f.3: CORB reset timeout#2, CORBRP = 65535
+[   18.820000] [     T38] systemd-journald[723]: Received client request to flush runtime journal.
+[   20.840000] [     T39] systemd-journald[723]: File /var/log/journal/a124ea923b144109a12d557d5ac53179/system.journal corrupted or uncleanly shut down, renaming and replacing.
+[   21.852348] [     T40] systemd-journald[723]: /var/log/journal/ad7a2547ac0e4342a342e62a34a3eae4/user-1000.journal: Journal file uses a different sequence number ID, rotating.
+[   24.871100] [      41] PEFILE: Unsigned PE binary
+[   33.918091] [      42] snd_hda_intel 0000:00:1f.3: CORB reset timeout#2, CORBRP = 65535
+[  144.931785] [      C1] usb 3-3.1: device firmware changed
+[  145.953248] [      C2] usb 3-3.1: USB disconnect, device number 44
+[  147.981859] [      C3] usb 3-3.1: New USB device found, idVendor=17ef, idProduct=6047, bcdDevice= 3.30
+[    0.000007] [      T8] BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable
+test_dmesg: unknown level '+'
diff --git a/tests/expected/dmesg/cid-kmsg-decode b/tests/expected/dmesg/cid-kmsg-decode
new file mode 100644
index 000000000..f9cdab620
--- /dev/null
+++ b/tests/expected/dmesg/cid-kmsg-decode
@@ -0,0 +1,45 @@
+kern  :emerg : [    0.000000] [      T1] Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000
+kern  :alert : [    0.000001] [      T2] Command line: initrd=\ucode.img initrd=\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system
+kern  :crit  : [    0.000002] [      T3] BIOS-provided physical RAM map:
+kern  :err   : [    0.000003] [      T4] BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable
+kern  :warn  : [    0.000004] [      T5] BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved
+kern  :notice: [    0.000005] [      T6] BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable
+kern  :info  : [    0.000006] [      T7] BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved
+kern  :debug : [    0.000007] [      T8] BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable
+kern  :info  : [    0.000008] [      T9] BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS
+kern  :info  : [    0.000009] [     T10] BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable
+kern  :info  : [    0.000010] [     T11] BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved
+kern  :info  : [    0.201607] [     T12] smp: Bringing up secondary CPUs ...
+kern  :info  : [    0.201607] [     T13] smpboot: x86: Booting SMP configuration:
+kern  :warn  : [    0.209670] [     T14]   #1  #3  #5  #7
+kern  :info  : [    0.212630] [     T15] smp: Brought up 1 node, 16 CPUs
+kern  :notice: [    0.215936] [     T16] audit: type=2000 audit(1702926179.015:1): state=initialized audit_enabled=0 res=1
+kern  :info  : [    0.215937] [     T17] thermal_sys: Registered thermal governor 'fair_share'
+kern  :warn  : [    0.215966] [     T18] ENERGY_PERF_BIAS: Set to 'normal', was 'performance'
+kern  :info  : [    0.367657] [     T19] ACPI: \_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+kern  :info  : [    0.368615] [     T20] ACPI: \_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+kern  :info  : [    0.376316] [     T21] ACPI: \_SB_.PRWL: New power resource
+kern  :info  : [    0.376343] [     T22] ACPI: \_SB_.PRWB: New power resource
+kern  :info  : [    0.377373] [     T23] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+kern  :info  : [    0.377378] [     T24] acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+kern  :info  : [    0.377569] [     T25] acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]
+kern  :info  : [    0.377933] [     T26] acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+kern  :info  : [    0.378458] [     T27] PCI host bridge to bus 0000:00
+kern  :info  : [    0.378459] [     T28] pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]
+kern  :info  : [    0.378461] [     T29] pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]
+user  :notice: [    9.398562] [     T30] user network daemon initialization complete
+daemon:info  : [   10.441520] [     T31] systemd[1]: systemd 254.7-1.fc39 running in system mode
+daemon:info  : [   11.441524] [     T32] systemd[1]: Detected architecture x86-64.
+daemon:info  : [   12.441525] [     T33] systemd[1]: Running in initrd.
+daemon:info  : [   13.541598] [     T34] systemd[1]: Hostname set to <catalina>.
+kern  :info  : [   15.641860] [     T35] usb 3-3: New USB device found, idVendor=1a40, idProduct=0101, bcdDevice= 1.11
+kern  :err   : [   16.690000] [     T36] Serial bus multi instantiate pseudo device driver INT3515:00: error -ENXIO: IRQ index 1 not found.
+kern  :err   : [   17.710000] [     T37] snd_hda_intel 0000:00:1f.3: CORB reset timeout#2, CORBRP = 65535
+syslog:info  : [   18.820000] [     T38] systemd-journald[723]: Received client request to flush runtime journal.
+syslog:warn  : [   20.840000] [     T39] systemd-journald[723]: File /var/log/journal/a124ea923b144109a12d557d5ac53179/system.journal corrupted or uncleanly shut down, renaming and replacing.
+syslog:info  : [   21.852348] [     T40] systemd-journald[723]: /var/log/journal/ad7a2547ac0e4342a342e62a34a3eae4/user-1000.journal: Journal file uses a different sequence number ID, rotating.
+kern  :warn  : [   24.871100] [      41] PEFILE: Unsigned PE binary
+kern  :err   : [   33.918091] [      42] snd_hda_intel 0000:00:1f.3: CORB reset timeout#2, CORBRP = 65535
+kern  :info  : [  144.931785] [      C1] usb 3-3.1: device firmware changed
+kern  :info  : [  145.953248] [      C2] usb 3-3.1: USB disconnect, device number 44
+kern  :info  : [  147.981859] [      C3] usb 3-3.1: New USB device found, idVendor=17ef, idProduct=6047, bcdDevice= 3.30
diff --git a/tests/expected/dmesg/cid-kmsg-delta b/tests/expected/dmesg/cid-kmsg-delta
new file mode 100644
index 000000000..25f6fb5e2
--- /dev/null
+++ b/tests/expected/dmesg/cid-kmsg-delta
@@ -0,0 +1,45 @@
+[    0.000000 <    0.000000>] [      T1] Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000
+[    0.000001 <    0.000000>] [      T2] Command line: initrd=\ucode.img initrd=\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system
+[    0.000002 <    0.000000>] [      T3] BIOS-provided physical RAM map:
+[    0.000003 <    0.000000>] [      T4] BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable
+[    0.000004 <    0.000000>] [      T5] BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved
+[    0.000005 <    0.000000>] [      T6] BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable
+[    0.000006 <    0.000000>] [      T7] BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved
+[    0.000007 <    0.000000>] [      T8] BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable
+[    0.000008 <    0.000000>] [      T9] BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS
+[    0.000009 <    0.000000>] [     T10] BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable
+[    0.000010 <    0.000000>] [     T11] BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved
+[    0.201607 <    0.000000>] [     T12] smp: Bringing up secondary CPUs ...
+[    0.201607 <    0.000000>] [     T13] smpboot: x86: Booting SMP configuration:
+[    0.209670 <    0.000000>] [     T14]   #1  #3  #5  #7
+[    0.212630 <    0.000000>] [     T15] smp: Brought up 1 node, 16 CPUs
+[    0.215936 <    0.000000>] [     T16] audit: type=2000 audit(1702926179.015:1): state=initialized audit_enabled=0 res=1
+[    0.215937 <    0.000000>] [     T17] thermal_sys: Registered thermal governor 'fair_share'
+[    0.215966 <    0.000000>] [     T18] ENERGY_PERF_BIAS: Set to 'normal', was 'performance'
+[    0.367657 <    0.000000>] [     T19] ACPI: \_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+[    0.368615 <    0.000000>] [     T20] ACPI: \_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+[    0.376316 <    0.000000>] [     T21] ACPI: \_SB_.PRWL: New power resource
+[    0.376343 <    0.000000>] [     T22] ACPI: \_SB_.PRWB: New power resource
+[    0.377373 <    0.000000>] [     T23] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+[    0.377378 <    0.000000>] [     T24] acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+[    0.377569 <    0.000000>] [     T25] acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]
+[    0.377933 <    0.000000>] [     T26] acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+[    0.378458 <    0.000000>] [     T27] PCI host bridge to bus 0000:00
+[    0.378459 <    0.000000>] [     T28] pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]
+[    0.378461 <    0.000000>] [     T29] pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]
+[    9.398562 <    9.000000>] [     T30] user network daemon initialization complete
+[   10.441520 <    1.000000>] [     T31] systemd[1]: systemd 254.7-1.fc39 running in system mode
+[   11.441524 <    1.000000>] [     T32] systemd[1]: Detected architecture x86-64.
+[   12.441525 <    1.000000>] [     T33] systemd[1]: Running in initrd.
+[   13.541598 <    1.000000>] [     T34] systemd[1]: Hostname set to <catalina>.
+[   15.641860 <    2.000000>] [     T35] usb 3-3: New USB device found, idVendor=1a40, idProduct=0101, bcdDevice= 1.11
+[   16.690000 <    1.000000>] [     T36] Serial bus multi instantiate pseudo device driver INT3515:00: error -ENXIO: IRQ index 1 not found.
+[   17.710000 <    1.000000>] [     T37] snd_hda_intel 0000:00:1f.3: CORB reset timeout#2, CORBRP = 65535
+[   18.820000 <    1.000000>] [     T38] systemd-journald[723]: Received client request to flush runtime journal.
+[   20.840000 <    2.000000>] [     T39] systemd-journald[723]: File /var/log/journal/a124ea923b144109a12d557d5ac53179/system.journal corrupted or uncleanly shut down, renaming and replacing.
+[   21.852348 <    1.000000>] [     T40] systemd-journald[723]: /var/log/journal/ad7a2547ac0e4342a342e62a34a3eae4/user-1000.journal: Journal file uses a different sequence number ID, rotating.
+[   24.871100 <    3.000000>] [      41] PEFILE: Unsigned PE binary
+[   33.918091 <    9.000000>] [      42] snd_hda_intel 0000:00:1f.3: CORB reset timeout#2, CORBRP = 65535
+[  144.931785 <  111.000000>] [      C1] usb 3-3.1: device firmware changed
+[  145.953248 <    1.000000>] [      C2] usb 3-3.1: USB disconnect, device number 44
+[  147.981859 <    2.000000>] [      C3] usb 3-3.1: New USB device found, idVendor=17ef, idProduct=6047, bcdDevice= 3.30
diff --git a/tests/expected/dmesg/cid-kmsg-facilities b/tests/expected/dmesg/cid-kmsg-facilities
new file mode 100644
index 000000000..118bd2449
--- /dev/null
+++ b/tests/expected/dmesg/cid-kmsg-facilities
@@ -0,0 +1,45 @@
+kern  :emerg : [    0.000000] [      T1] Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000
+kern  :alert : [    0.000001] [      T2] Command line: initrd=\ucode.img initrd=\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system
+kern  :crit  : [    0.000002] [      T3] BIOS-provided physical RAM map:
+kern  :err   : [    0.000003] [      T4] BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable
+kern  :warn  : [    0.000004] [      T5] BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved
+kern  :notice: [    0.000005] [      T6] BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable
+kern  :info  : [    0.000006] [      T7] BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved
+kern  :debug : [    0.000007] [      T8] BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable
+kern  :info  : [    0.000008] [      T9] BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS
+kern  :info  : [    0.000009] [     T10] BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable
+kern  :info  : [    0.000010] [     T11] BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved
+kern  :info  : [    0.201607] [     T12] smp: Bringing up secondary CPUs ...
+kern  :info  : [    0.201607] [     T13] smpboot: x86: Booting SMP configuration:
+kern  :warn  : [    0.209670] [     T14]   #1  #3  #5  #7
+kern  :info  : [    0.212630] [     T15] smp: Brought up 1 node, 16 CPUs
+kern  :notice: [    0.215936] [     T16] audit: type=2000 audit(1702926179.015:1): state=initialized audit_enabled=0 res=1
+kern  :info  : [    0.215937] [     T17] thermal_sys: Registered thermal governor 'fair_share'
+kern  :warn  : [    0.215966] [     T18] ENERGY_PERF_BIAS: Set to 'normal', was 'performance'
+kern  :info  : [    0.367657] [     T19] ACPI: \_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+kern  :info  : [    0.368615] [     T20] ACPI: \_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+kern  :info  : [    0.376316] [     T21] ACPI: \_SB_.PRWL: New power resource
+kern  :info  : [    0.376343] [     T22] ACPI: \_SB_.PRWB: New power resource
+kern  :info  : [    0.377373] [     T23] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+kern  :info  : [    0.377378] [     T24] acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+kern  :info  : [    0.377569] [     T25] acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]
+kern  :info  : [    0.377933] [     T26] acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+kern  :info  : [    0.378458] [     T27] PCI host bridge to bus 0000:00
+kern  :info  : [    0.378459] [     T28] pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]
+kern  :info  : [    0.378461] [     T29] pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]
+kern  :info  : [   15.641860] [     T35] usb 3-3: New USB device found, idVendor=1a40, idProduct=0101, bcdDevice= 1.11
+kern  :err   : [   16.690000] [     T36] Serial bus multi instantiate pseudo device driver INT3515:00: error -ENXIO: IRQ index 1 not found.
+kern  :err   : [   17.710000] [     T37] snd_hda_intel 0000:00:1f.3: CORB reset timeout#2, CORBRP = 65535
+kern  :warn  : [   24.871100] [      41] PEFILE: Unsigned PE binary
+kern  :err   : [   33.918091] [      42] snd_hda_intel 0000:00:1f.3: CORB reset timeout#2, CORBRP = 65535
+kern  :info  : [  144.931785] [      C1] usb 3-3.1: device firmware changed
+kern  :info  : [  145.953248] [      C2] usb 3-3.1: USB disconnect, device number 44
+kern  :info  : [  147.981859] [      C3] usb 3-3.1: New USB device found, idVendor=17ef, idProduct=6047, bcdDevice= 3.30
+user  :notice: [    9.398562] [     T30] user network daemon initialization complete
+daemon:info  : [   10.441520] [     T31] systemd[1]: systemd 254.7-1.fc39 running in system mode
+daemon:info  : [   11.441524] [     T32] systemd[1]: Detected architecture x86-64.
+daemon:info  : [   12.441525] [     T33] systemd[1]: Running in initrd.
+daemon:info  : [   13.541598] [     T34] systemd[1]: Hostname set to <catalina>.
+syslog:info  : [   18.820000] [     T38] systemd-journald[723]: Received client request to flush runtime journal.
+syslog:warn  : [   20.840000] [     T39] systemd-journald[723]: File /var/log/journal/a124ea923b144109a12d557d5ac53179/system.journal corrupted or uncleanly shut down, renaming and replacing.
+syslog:info  : [   21.852348] [     T40] systemd-journald[723]: /var/log/journal/ad7a2547ac0e4342a342e62a34a3eae4/user-1000.journal: Journal file uses a different sequence number ID, rotating.
diff --git a/tests/expected/dmesg/cid-kmsg-indentation b/tests/expected/dmesg/cid-kmsg-indentation
new file mode 100644
index 000000000..fe03a0e1e
--- /dev/null
+++ b/tests/expected/dmesg/cid-kmsg-indentation
@@ -0,0 +1,28 @@
+[    0.000000] [      T0] line zero
+[    1.000000] [      T1] new
+[    2.000000] [      T2] two
+[    3.000000] [      T3] three
+[    0.000000] [      T0] line zero
+[    1.000000] [      T1] new
+[    2.000000] [      T2] two
+[    3.000000] [      T3] three
+[<    0.000000>] [      T0] line zero
+[<    0.000000>] [      T1] new
+[<    1.000000>] [      T2] two
+[<    1.000000>] [      T3] three
+[      T0] line zero
+[      T1] new
+[      T2] two
+[      T3] three
+[Feb13 23:31] [      T0] line zero
+[  +0.000000] [      T1] new
+[  +1.000000] [      T2] two
+[  +1.000000] [      T3] three
+[Fri Feb 13 23:31:30 2009] [      T0] line zero
+[Fri Feb 13 23:31:31 2009] [      T1] new
+[Fri Feb 13 23:31:32 2009] [      T2] two
+[Fri Feb 13 23:31:33 2009] [      T3] three
+2009-02-13T23:31:30,123456+00:00 [      T0] line zero
+2009-02-13T23:31:31,123456+00:00 [      T1] new
+2009-02-13T23:31:32,123456+00:00 [      T2] two
+2009-02-13T23:31:33,123456+00:00 [      T3] three
diff --git a/tests/expected/dmesg/cid-kmsg-json b/tests/expected/dmesg/cid-kmsg-json
new file mode 100644
index 000000000..578efd720
--- /dev/null
+++ b/tests/expected/dmesg/cid-kmsg-json
@@ -0,0 +1,230 @@
+{
+   "dmesg": [
+      {
+         "pri": 0,
+         "time":     0.000000,
+         "caller": "T1",
+         "msg": "Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000"
+      },{
+         "pri": 1,
+         "time":     0.000001,
+         "caller": "T2",
+         "msg": "Command line: initrd=\\ucode.img initrd=\\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system"
+      },{
+         "pri": 2,
+         "time":     0.000002,
+         "caller": "T3",
+         "msg": "BIOS-provided physical RAM map:"
+      },{
+         "pri": 3,
+         "time":     0.000003,
+         "caller": "T4",
+         "msg": "BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable"
+      },{
+         "pri": 4,
+         "time":     0.000004,
+         "caller": "T5",
+         "msg": "BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved"
+      },{
+         "pri": 5,
+         "time":     0.000005,
+         "caller": "T6",
+         "msg": "BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable"
+      },{
+         "pri": 6,
+         "time":     0.000006,
+         "caller": "T7",
+         "msg": "BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved"
+      },{
+         "pri": 7,
+         "time":     0.000007,
+         "caller": "T8",
+         "msg": "BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable"
+      },{
+         "pri": 6,
+         "time":     0.000008,
+         "caller": "T9",
+         "msg": "BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS"
+      },{
+         "pri": 6,
+         "time":     0.000009,
+         "caller": "T10",
+         "msg": "BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable"
+      },{
+         "pri": 6,
+         "time":     0.000010,
+         "caller": "T11",
+         "msg": "BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved"
+      },{
+         "pri": 6,
+         "time":     0.201607,
+         "caller": "T12",
+         "msg": "smp: Bringing up secondary CPUs ..."
+      },{
+         "pri": 6,
+         "time":     0.201607,
+         "caller": "T13",
+         "msg": "smpboot: x86: Booting SMP configuration:"
+      },{
+         "pri": 4,
+         "time":     0.209670,
+         "caller": "T14",
+         "msg": "  #1  #3  #5  #7"
+      },{
+         "pri": 6,
+         "time":     0.212630,
+         "caller": "T15",
+         "msg": "smp: Brought up 1 node, 16 CPUs"
+      },{
+         "pri": 5,
+         "time":     0.215936,
+         "caller": "T16",
+         "msg": "audit: type=2000 audit(1702926179.015:1): state=initialized audit_enabled=0 res=1"
+      },{
+         "pri": 6,
+         "time":     0.215937,
+         "caller": "T17",
+         "msg": "thermal_sys: Registered thermal governor 'fair_share'"
+      },{
+         "pri": 4,
+         "time":     0.215966,
+         "caller": "T18",
+         "msg": "ENERGY_PERF_BIAS: Set to 'normal', was 'performance'"
+      },{
+         "pri": 6,
+         "time":     0.367657,
+         "caller": "T19",
+         "msg": "ACPI: \\_SB_.PCI0.GP19.NHI1.PWRS: New power resource"
+      },{
+         "pri": 6,
+         "time":     0.368615,
+         "caller": "T20",
+         "msg": "ACPI: \\_SB_.PCI0.GP19.XHC4.PWRS: New power resource"
+      },{
+         "pri": 6,
+         "time":     0.376316,
+         "caller": "T21",
+         "msg": "ACPI: \\_SB_.PRWL: New power resource"
+      },{
+         "pri": 6,
+         "time":     0.376343,
+         "caller": "T22",
+         "msg": "ACPI: \\_SB_.PRWB: New power resource"
+      },{
+         "pri": 6,
+         "time":     0.377373,
+         "caller": "T23",
+         "msg": "ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])"
+      },{
+         "pri": 6,
+         "time":     0.377378,
+         "caller": "T24",
+         "msg": "acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]"
+      },{
+         "pri": 6,
+         "time":     0.377569,
+         "caller": "T25",
+         "msg": "acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]"
+      },{
+         "pri": 6,
+         "time":     0.377933,
+         "caller": "T26",
+         "msg": "acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]"
+      },{
+         "pri": 6,
+         "time":     0.378458,
+         "caller": "T27",
+         "msg": "PCI host bridge to bus 0000:00"
+      },{
+         "pri": 6,
+         "time":     0.378459,
+         "caller": "T28",
+         "msg": "pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]"
+      },{
+         "pri": 6,
+         "time":     0.378461,
+         "caller": "T29",
+         "msg": "pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]"
+      },{
+         "pri": 13,
+         "time":     9.398562,
+         "caller": "T30",
+         "msg": "user network daemon initialization complete"
+      },{
+         "pri": 30,
+         "time":    10.441520,
+         "caller": "T31",
+         "msg": "systemd[1]: systemd 254.7-1.fc39 running in system mode"
+      },{
+         "pri": 30,
+         "time":    11.441524,
+         "caller": "T32",
+         "msg": "systemd[1]: Detected architecture x86-64."
+      },{
+         "pri": 30,
+         "time":    12.441525,
+         "caller": "T33",
+         "msg": "systemd[1]: Running in initrd."
+      },{
+         "pri": 30,
+         "time":    13.541598,
+         "caller": "T34",
+         "msg": "systemd[1]: Hostname set to <catalina>."
+      },{
+         "pri": 6,
+         "time":    15.641860,
+         "caller": "T35",
+         "msg": "usb 3-3: New USB device found, idVendor=1a40, idProduct=0101, bcdDevice= 1.11"
+      },{
+         "pri": 3,
+         "time":    16.690000,
+         "caller": "T36",
+         "msg": "Serial bus multi instantiate pseudo device driver INT3515:00: error -ENXIO: IRQ index 1 not found."
+      },{
+         "pri": 3,
+         "time":    17.710000,
+         "caller": "T37",
+         "msg": "snd_hda_intel 0000:00:1f.3: CORB reset timeout#2, CORBRP = 65535"
+      },{
+         "pri": 46,
+         "time":    18.820000,
+         "caller": "T38",
+         "msg": "systemd-journald[723]: Received client request to flush runtime journal."
+      },{
+         "pri": 44,
+         "time":    20.840000,
+         "caller": "T39",
+         "msg": "systemd-journald[723]: File /var/log/journal/a124ea923b144109a12d557d5ac53179/system.journal corrupted or uncleanly shut down, renaming and replacing."
+      },{
+         "pri": 46,
+         "time":    21.852348,
+         "caller": "T40",
+         "msg": "systemd-journald[723]: /var/log/journal/ad7a2547ac0e4342a342e62a34a3eae4/user-1000.journal: Journal file uses a different sequence number ID, rotating."
+      },{
+         "pri": 4,
+         "time":    24.871100,
+         "caller": "41",
+         "msg": "PEFILE: Unsigned PE binary"
+      },{
+         "pri": 3,
+         "time":    33.918091,
+         "caller": "42",
+         "msg": "snd_hda_intel 0000:00:1f.3: CORB reset timeout#2, CORBRP = 65535"
+      },{
+         "pri": 6,
+         "time":   144.931785,
+         "caller": "C1",
+         "msg": "usb 3-3.1: device firmware changed"
+      },{
+         "pri": 6,
+         "time":   145.953248,
+         "caller": "C2",
+         "msg": "usb 3-3.1: USB disconnect, device number 44"
+      },{
+         "pri": 6,
+         "time":   147.981859,
+         "caller": "C3",
+         "msg": "usb 3-3.1: New USB device found, idVendor=17ef, idProduct=6047, bcdDevice= 3.30"
+      }
+   ]
+}
diff --git a/tests/expected/dmesg/cid-kmsg-limit b/tests/expected/dmesg/cid-kmsg-limit
new file mode 100644
index 000000000..8db1c9a65
--- /dev/null
+++ b/tests/expected/dmesg/cid-kmsg-limit
@@ -0,0 +1,31 @@
+[    0.201607] [     T12] smp: Bringing up secondary CPUs ...
+[    0.201607] [     T13] smpboot: x86: Booting SMP configuration:
+[    0.209670] [     T14]   #1  #3  #5  #7
+[    0.212630] [     T15] smp: Brought up 1 node, 16 CPUs
+[    0.215936] [     T16] audit: type=2000 audit(1702926179.015:1): state=initialized audit_enabled=0 res=1
+[    0.215937] [     T17] thermal_sys: Registered thermal governor 'fair_share'
+[    0.215966] [     T18] ENERGY_PERF_BIAS: Set to 'normal', was 'performance'
+[    0.367657] [     T19] ACPI: \_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+[    0.368615] [     T20] ACPI: \_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+[    0.376316] [     T21] ACPI: \_SB_.PRWL: New power resource
+[    0.376343] [     T22] ACPI: \_SB_.PRWB: New power resource
+[    0.377373] [     T23] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+[    0.377378] [     T24] acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+[    0.377569] [     T25] acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]
+[    0.377933] [     T26] acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+[    0.378458] [     T27] PCI host bridge to bus 0000:00
+[    0.378459] [     T28] pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]
+[    0.378461] [     T29] pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]
+[    9.398562] [     T30] user network daemon initialization complete
+[   10.441520] [     T31] systemd[1]: systemd 254.7-1.fc39 running in system mode
+[   11.441524] [     T32] systemd[1]: Detected architecture x86-64.
+[   12.441525] [     T33] systemd[1]: Running in initrd.
+[   13.541598] [     T34] systemd[1]: Hostname set to <catalina>.
+[   15.641860] [     T35] usb 3-3: New USB device found, idVendor=1a40, idProduct=0101, bcdDevice= 1.11
+[   16.690000] [     T36] Serial bus multi instantiate pseudo device driver INT3515:00: error -ENXIO: IRQ index 1 not found.
+[   17.710000] [     T37] snd_hda_intel 0000:00:1f.3: CORB reset timeout#2, CORBRP = 65535
+[   18.820000] [     T38] systemd-journald[723]: Received client request to flush runtime journal.
+[   20.840000] [     T39] systemd-journald[723]: File /var/log/journal/a124ea923b144109a12d557d5ac53179/system.journal corrupted or uncleanly shut down, renaming and replacing.
+[   21.852348] [     T40] systemd-journald[723]: /var/log/journal/ad7a2547ac0e4342a342e62a34a3eae4/user-1000.journal: Journal file uses a different sequence number ID, rotating.
+[   24.871100] [      41] PEFILE: Unsigned PE binary
+[   33.918091] [      42] snd_hda_intel 0000:00:1f.3: CORB reset timeout#2, CORBRP = 65535
diff --git a/tests/expected/dmesg/kmsg-file b/tests/expected/dmesg/kmsg-file
index 54b5e612d..984588e3e 100644
--- a/tests/expected/dmesg/kmsg-file
+++ b/tests/expected/dmesg/kmsg-file
@@ -1,49 +1,77 @@
 {
    "dmesg": [
       {
-         "pri": 5,
+         "pri": 0,
          "time":     0.000000,
          "msg": "Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000"
       },{
-         "pri": 6,
-         "time":     0.000000,
+         "pri": 1,
+         "time":     0.000001,
          "msg": "Command line: initrd=\\ucode.img initrd=\\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system"
       },{
-         "pri": 6,
-         "time":     0.000000,
+         "pri": 2,
+         "time":     0.000002,
          "msg": "BIOS-provided physical RAM map:"
       },{
-         "pri": 6,
-         "time":     0.000000,
+         "pri": 3,
+         "time":     0.000003,
          "msg": "BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable"
       },{
-         "pri": 6,
-         "time":     0.000000,
+         "pri": 4,
+         "time":     0.000004,
          "msg": "BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved"
       },{
-         "pri": 6,
-         "time":     0.000000,
+         "pri": 5,
+         "time":     0.000005,
          "msg": "BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable"
       },{
          "pri": 6,
-         "time":     0.000000,
+         "time":     0.000006,
          "msg": "BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved"
       },{
-         "pri": 6,
-         "time":     0.000000,
+         "pri": 7,
+         "time":     0.000007,
          "msg": "BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable"
       },{
          "pri": 6,
-         "time":     0.000000,
+         "time":     0.000008,
          "msg": "BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS"
       },{
          "pri": 6,
-         "time":     0.000000,
+         "time":     0.000009,
          "msg": "BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable"
       },{
          "pri": 6,
-         "time":     0.000000,
+         "time":     0.000010,
          "msg": "BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved"
+      },{
+         "pri": 6,
+         "time":     0.201607,
+         "msg": "smp: Bringing up secondary CPUs ..."
+      },{
+         "pri": 6,
+         "time":     0.201607,
+         "msg": "smpboot: x86: Booting SMP configuration:"
+      },{
+         "pri": 4,
+         "time":     0.209670,
+         "msg": "  #1  #3  #5  #7"
+      },{
+         "pri": 6,
+         "time":     0.212630,
+         "msg": "smp: Brought up 1 node, 16 CPUs"
+      },{
+         "pri": 5,
+         "time":     0.215936,
+         "msg": "audit: type=2000 audit(1702926179.015:1): state=initialized audit_enabled=0 res=1"
+      },{
+         "pri": 6,
+         "time":     0.215937,
+         "msg": "thermal_sys: Registered thermal governor 'fair_share'"
+      },{
+         "pri": 4,
+         "time":     0.215966,
+         "msg": "ENERGY_PERF_BIAS: Set to 'normal', was 'performance'"
       },{
          "pri": 6,
          "time":     0.367657,
@@ -88,6 +116,70 @@
          "pri": 6,
          "time":     0.378461,
          "msg": "pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]"
+      },{
+         "pri": 13,
+         "time":     9.398562,
+         "msg": "user network daemon initialization complete"
+      },{
+         "pri": 30,
+         "time":    10.441520,
+         "msg": "systemd[1]: systemd 254.7-1.fc39 running in system mode"
+      },{
+         "pri": 30,
+         "time":    11.441524,
+         "msg": "systemd[1]: Detected architecture x86-64."
+      },{
+         "pri": 30,
+         "time":    12.441525,
+         "msg": "systemd[1]: Running in initrd."
+      },{
+         "pri": 30,
+         "time":    13.541598,
+         "msg": "systemd[1]: Hostname set to <catalina>."
+      },{
+         "pri": 6,
+         "time":    15.641860,
+         "msg": "usb 3-3: New USB device found, idVendor=1a40, idProduct=0101, bcdDevice= 1.11"
+      },{
+         "pri": 3,
+         "time":    16.690000,
+         "msg": "Serial bus multi instantiate pseudo device driver INT3515:00: error -ENXIO: IRQ index 1 not found."
+      },{
+         "pri": 3,
+         "time":    17.710000,
+         "msg": "snd_hda_intel 0000:00:1f.3: CORB reset timeout#2, CORBRP = 65535"
+      },{
+         "pri": 46,
+         "time":    18.820000,
+         "msg": "systemd-journald[723]: Received client request to flush runtime journal."
+      },{
+         "pri": 44,
+         "time":    20.840000,
+         "msg": "systemd-journald[723]: File /var/log/journal/a124ea923b144109a12d557d5ac53179/system.journal corrupted or uncleanly shut down, renaming and replacing."
+      },{
+         "pri": 46,
+         "time":    21.852348,
+         "msg": "systemd-journald[723]: /var/log/journal/ad7a2547ac0e4342a342e62a34a3eae4/user-1000.journal: Journal file uses a different sequence number ID, rotating."
+      },{
+         "pri": 4,
+         "time":    24.871100,
+         "msg": "PEFILE: Unsigned PE binary"
+      },{
+         "pri": 3,
+         "time":    33.918091,
+         "msg": "snd_hda_intel 0000:00:1f.3: CORB reset timeout#2, CORBRP = 65535"
+      },{
+         "pri": 6,
+         "time":   144.931785,
+         "msg": "usb 3-3.1: device firmware changed"
+      },{
+         "pri": 6,
+         "time":   145.953248,
+         "msg": "usb 3-3.1: USB disconnect, device number 44"
+      },{
+         "pri": 6,
+         "time":   147.981859,
+         "msg": "usb 3-3.1: New USB device found, idVendor=17ef, idProduct=6047, bcdDevice= 3.30"
       }
    ]
 }
diff --git a/tests/ts/dmesg/cid-input b/tests/ts/dmesg/cid-input
new file mode 100644
index 000000000..7dbd89d8f
--- /dev/null
+++ b/tests/ts/dmesg/cid-input
@@ -0,0 +1,106 @@
+<0>[    0.000000] [    T0] example[0]
+<1>[    1.000000] [    T1] example[1]
+<2>[    8.000000] [    T2] example[2]
+<3>[   27.000000] [    T3] example[3]
+<4>[   64.000000] [    T4] example[4]
+<5>[  125.000000] [    T5] example[5]
+<6>[  216.000000] [    T6] example[6]
+<7>[  343.000000] [    T7] example[7]
+<8>[  512.000000] [    T8] example[8]
+<9>[  729.000000] [    T9] example[9]
+<10>[ 1000.000000] [   T10] example[10]
+<11>[ 1331.000000] [   T11] example[11]
+<12>[ 1728.000000] [   T12] example[12]
+<13>[ 2197.000000] [   T13] example[13]
+<14>[ 2744.000000] [   T14] example[14]
+<15>[ 3375.000000] [   T15] example[15]
+<16>[ 4096.000000] [   T16] example[16]
+<17>[ 4913.000000] [   T17] example[17]
+<18>[ 5832.000000] [   T18] example[18]
+<19>[ 6859.000000] [   T19] example[19]
+<20>[ 8000.000000] [   T20] example[20]
+<21>[ 9261.000000] [   T21] example[21]
+<22>[10648.000000] [   T22] example[22]
+<23>[12167.000000] [   T23] example[23]
+<24>[13824.000000] [   T24] example[24]
+<25>[15625.000000] [   T25] example[25]
+<26>[17576.000000] [   T26] example[26]
+<27>[19683.000000] [   T27] example[27]
+<28>[21952.000000] [   T28] example[28]
+<29>[24389.000000] [   T29] example[29]
+<30>[27000.000000] [   T10] example[30]
+<31>[29791.000000] [   T31] example[31]
+<32>[32768.000000] [   T32] example[32]
+<33>[35937.000000] [   T33] example[33]
+<34>[39304.000000] [   T34] example[34]
+<35>[42875.000000] [   T35] example[35]
+<36>[46656.000000] [   T36] example[36]
+<37>[50653.000000] [   T37] example[37]
+<38>[54872.000000] [   T38] example[38]
+<39>[59319.000000] [   T39] example[39]
+<40>[64000.000000] [   T40] example[40]
+<41>[68921.000000] [   T41] example[41]
+<42>[74088.000000] [   T42] example[42]
+<43>[79507.000000] [   T43] example[43]
+<44>[85184.000000] [   T44] example[44]
+<45>[91125.000000] [   T45] example[45]
+<46>[97336.000000] [   T46] example[46]
+<47>[103823.000000] [   T47] example[47]
+<48>[110592.000000] [   T48] example[48]
+<49>[117649.000000] [   T49] example[49]
+<50>[125000.000000] [   T50] example[50]
+<51>[132651.000000] [   T51] example[51]
+<52>[140608.000000] [   T52] example[52]
+<53>[148877.000000] [   T53] example[53]
+<54>[157464.000000] [   T54] example[54]
+<55>[166375.000000] [   T55] example[55]
+<56>[175616.000000] [   T56] example[56]
+<57>[185193.000000] [   T57] example[57]
+<58>[195112.000000] [   T58] example[58]
+<59>[205379.000000] [   T59] example[59]
+<60>[216000.000000] [   T60] example[60]
+<61>[226981.000000] [   T61] example[61]
+<62>[238328.000000] [   T62] example[62]
+<63>[250047.000000] [   T63] example[63]
+<64>[262144.000000] [   T64] example[64]
+<65>[274625.000000] [   T65] example[65]
+<66>[287496.000000] [   T66] example[66]
+<67>[300763.000000] [   T67] example[67]
+<68>[314432.000000] [   T68] example[68]
+<69>[328509.000000] [   T69] example[69]
+<70>[343000.000000] [   T70] example[70]
+<71>[357911.000000] [   T71] example[71]
+<72>[373248.000000] [   T72] example[72]
+<73>[389017.000000] [   T73] example[73]
+<74>[405224.000000] [   T74] example[74]
+<75>[421875.000000] [   T75] example[75]
+<76>[438976.000000] [   T76] example[76]
+<77>[456533.000000] [   T77] example[77]
+<78>[474552.000000] [   T78] example[78]
+<79>[493039.000000] [   T79] example[79]
+<80>[512000.000000] [   T80] example[80]
+<81>[531441.000000] [   T81] example[81]
+<82>[551368.000000] [   T82] example[82]
+<83>[571787.000000] [   T83] example[83]
+<84>[592704.000000] [   T84] example[84]
+<85>[614125.000000] [   T85] example[85]
+<86>[636056.000000] [   T86] example[86]
+<87>[658503.000000] [   T87] example[87]
+<88>[681472.000000] [   T88] example[88]
+<89>[704969.000000] [   T89] example[89]
+<90>[729000.000000] [   T90] example[90]
+<91>[753571.000000] [   T91] example[91]
+<92>[778688.000000] [   T92] example[92]
+<93>[804357.000000] [   T93] example[93]
+<94>[830584.000000] [   T94] example[94]
+<95>[857375.000000] [   T95] example[95]
+<96>[884736.000000] [   T96] example[96]
+<97>[912673.000000] [   T97] example[97]
+<98>[941192.000000] [   T98] example[98]
+<99>[970299.000000] [   T99] example[99]
+<100>[1000000.000000] [  T100] example[100]
+<101>[1030301.000000] [  T101] example[101]
+<102>[1061208.000000] [  T102] example[102]
+<103>[1092727.000000] [  T103] example[103]
+<104>[1124864.000000] [  T104] example[104]
+<150>[4557523.000000] [  T105] example[105]
diff --git a/tests/ts/dmesg/cid-json b/tests/ts/dmesg/cid-json
new file mode 100755
index 000000000..78363793d
--- /dev/null
+++ b/tests/ts/dmesg/cid-json
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="cid-json"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG -J -F $TS_SELF/cid-input >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/cid-kmsg-colors b/tests/ts/dmesg/cid-kmsg-colors
new file mode 100755
index 000000000..90a593354
--- /dev/null
+++ b/tests/ts/dmesg/cid-kmsg-colors
@@ -0,0 +1,29 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="cid-kmsg-colors"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+ts_inhibit_custom_colorscheme
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG --color=always -K $TS_SELF/cid-kmsg-input -x >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/cid-kmsg-console-levels b/tests/ts/dmesg/cid-kmsg-console-levels
new file mode 100755
index 000000000..2cd445d05
--- /dev/null
+++ b/tests/ts/dmesg/cid-kmsg-console-levels
@@ -0,0 +1,36 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="cid-kmsg-levels"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+for I in {-1..8}; do
+	$TS_HELPER_DMESG -K $TS_SELF/cid-kmsg-input -l $I >> $TS_OUTPUT 2>/dev/null
+done
+
+$TS_HELPER_DMESG -K $TS_SELF/cid-kmsg-input -l err+ >> $TS_OUTPUT 2>/dev/null
+$TS_HELPER_DMESG -K $TS_SELF/cid-kmsg-input -l emerg+ >> $TS_OUTPUT 2>/dev/null
+$TS_HELPER_DMESG -K $TS_SELF/cid-kmsg-input -l +err >> $TS_OUTPUT 2>/dev/null
+$TS_HELPER_DMESG -K $TS_SELF/cid-kmsg-input -l +debug >> $TS_OUTPUT 2>/dev/null
+$TS_HELPER_DMESG -K $TS_SELF/cid-kmsg-input -l + 2>> $TS_OUTPUT >/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/cid-kmsg-decode b/tests/ts/dmesg/cid-kmsg-decode
new file mode 100755
index 000000000..316fb2079
--- /dev/null
+++ b/tests/ts/dmesg/cid-kmsg-decode
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="cid-kmsg-decode"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG -x -K $TS_SELF/cid-kmsg-input >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/cid-kmsg-delta b/tests/ts/dmesg/cid-kmsg-delta
new file mode 100755
index 000000000..64c2e6933
--- /dev/null
+++ b/tests/ts/dmesg/cid-kmsg-delta
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="cid-kmsg-delta"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG -d -K $TS_SELF/cid-kmsg-input >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/cid-kmsg-facilities b/tests/ts/dmesg/cid-kmsg-facilities
new file mode 100755
index 000000000..f50f2b73d
--- /dev/null
+++ b/tests/ts/dmesg/cid-kmsg-facilities
@@ -0,0 +1,30 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="cid-kmsg-facilities"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+for I in {-1..12}; do
+	$TS_HELPER_DMESG -K $TS_SELF/cid-kmsg-input -f $I -x >> $TS_OUTPUT 2>/dev/null
+done
+
+ts_finalize
diff --git a/tests/ts/dmesg/cid-kmsg-indentation b/tests/ts/dmesg/cid-kmsg-indentation
new file mode 100755
index 000000000..d45e1e30b
--- /dev/null
+++ b/tests/ts/dmesg/cid-kmsg-indentation
@@ -0,0 +1,40 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="cid-kmsg-indentation"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG -K $TS_SELF/cid-kmsg-newlines >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG -K $TS_SELF/cid-kmsg-newlines >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=delta --kmsg-file $TS_SELF/cid-kmsg-newlines >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=notime --kmsg-file $TS_SELF/cid-kmsg-newlines >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=reltime --kmsg-file $TS_SELF/cid-kmsg-newlines >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=ctime --kmsg-file $TS_SELF/cid-kmsg-newlines >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=iso --kmsg-file $TS_SELF/cid-kmsg-newlines >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+ts_finalize
diff --git a/tests/ts/dmesg/cid-kmsg-input b/tests/ts/dmesg/cid-kmsg-input
new file mode 100644
index 0000000000000000000000000000000000000000..8ebfb5170e647b57d1f3f504150ddb3def3b4247
GIT binary patch
literal 4425
zcmbtXYjfht5%p*PimuuZwrho~(dbP`#m4NK)Y>Ls@7*oOMGevbx>paPhadU%IU`^Z
z>)6RA43yAgPM_)NKHV}j1EZsbB1vS?yJg)kaaKRmqb$le&&bgo-Rg)UT(S<M<3!#3
zi#l!oozU?j4C(lDzkfoE>!!}gG)!)I2Gi*C^&KS<?&5fkiB+7GCuHgt(~T4Qz-V$c
zqS1ITxEkF~FTP)&T@Cwmm1i0m7G21&fg-~QOg~^geKhbnJYbp{JH}?WpQowFA_65D
zP@Kh85%vE5Y=?E2M^cZ|Mf+lNU!?Q0(=4I6T|7}(ysWB7KE|Q!o#J?!J*Lvg*op_`
zOIgV@h~hF7MMOoOSL;Vov0BOEbbbHuz|_>(G2`9y;mxG8D)PrTk`b+zFJ%lz)A;O)
zFgG|n;F=n{Db{+5^h_h5`&6c6Jga55Kb^fxzMRkJ4^)?8mdL{cOH*S9Xul8W&w;!T
zI0GI43t7tIQAURcwx-4o(s>t>HB{S>zEFrQj*h0r4$yrM(4V~qj5dHfj;^N04$^xU
zQoe>%Ufk#CX<iG^e-}`Bao>;roGV8@&{=;pr0cJf!vjb2F?Jl8@jfOG_c1M#+dq?J
zhK6qolf8op0Ou#3mSt}+cfNEqZWx+rFvn=Sl$qT!T?KSr#MuI0s#jFXFwY`Uyik91
zSCX#lYMC6#|9U!C(`U$?fSx@EIQXkzln4N29xv)bRL~rxg{5((Fnq@~v~VX*R+p4+
z&<Bp6ji1}tW5_#ZI(*L)_Lgp5FP4>J%P4~$XvCa`u8M4Kx|nMFyd96s>54jvL9}{V
z$({+HQFGy#xrXVR4s(6oV0OSx0xBy}$(|CGSS0a3k><^#Q<<rRjCzL3q#kQ{n%>&j
zo?G2+wUk9Fk|}f~ps`%UkedQPo9nd5p~hKW(9vAP#k5?CLLN0v;%oNK9(%7lxE_o@
zf1i#9<4@D`;n^ghiL9u~=?EyWbfnRfDCr2|HCGq1P~kb6#i2%y>)3k){jQ4PfRv(6
zC+Aar)E^r9=MnSu>&qe2N573>;aWb?Du0rNT5nz#A;d@_Vk;fbVQm31jkgiMUG}a2
zfQVgl9nRWoHrXr0@o!(=CWROUgw<AF)BHCO=Wj!}fN;6H2f;TGa1f0V-YQq3g`|7s
zu?ISi@>IkbDjEXnepZ+G*MUZytUcwe5!<R`T3r#YVj5kKj5EUvPzz~#GwBC(Goi9x
zt@5HO>3;BB$qW^y-=q<pO-5JLPx9~&94B&-$_!6kO@=hM7}MqGTjv&W%^wbFa(6!Y
zKDixS^^}=Ix)^*N_6NO>>MYn9UGwu5Kig?bm}$SoZ<UBj#TG@mERlEBmM+~-E=T>#
zyjmsog3boxU!-9fiiVF!-Kn05gniRZS&rhKXH}6Wa20k!ZjFzw2BgmWVkKsA5?3$u
z<#tRLqyDdQV&LRi_TJXHT@?n)ysT)p4g)0MdegCus*^!_Smt`>o>RT<DvYPCM}wy4
zXeMuyi|*r`HqC)5w&C2Rr#Or9r#<c)pxw@HF2H_^1hO9VoxQHg{}mEZQ~XqM`rk+}
zuDL#{BlkVq*=wPUZjC;KGFd(4#UB(2nW8KGA-7Gz!1kuAL{?B7lmL&LsEL-vY_nYt
zIP0$awCJ8aK(?EnE+W&mbhpFwdB}Y#>MT<w2|2pHPbmt<29;}!HK^_OilZp5ks8zs
zkO(VP1JEJI>VI8GRqi^Dh0@rtvovNlIBiMfsE#e1@s7y4o!w5hHO6f$&2NVqxArDq
zBIGiWN>t}Y^#2r!3Z*F%e{QO?hg!#M$6}td=N}uMo)PcxwdUPT&S~8a(>$-UNTWFV
z3YE!=9ur7HoQ{e-s>7;hFxBnP!sue%J`>X!Yl{nje?(x&JU=jP6mE{Kay8~Sz6!=x
zI&-Hxkp;?W6Y*)CR57*$g*HQttt72VSx5PnT~x#<k2Ji#<u+=vl1Nz;sFt0<^|#?o
zK*RChFg=pbO#@J^m!r4&ZN=&b$&cGB!46gt_R%gd*KK;-Het70X3=yRiD{fwGHDcE
zF=2BZ?(E-;&zpW4+YzTSud5HH)?6Krs7H=%a~tIx{h^Il8xOtzPyX<>``h^)l{FJd
zbnluRQ9PER#OfmolNcfoBmbx+1P4kpPwH~1B3hZG%{&BvWx)*kCBw6RHsil#=2M(V
zI(-zyX_7BaH&~|vaV&*z@|nsD!^e4K+iqlw(B^27Ht$9H=6PgkQPeAy9oU>Y3lk}_
z<b}#*U7<=m;kB<o)0C<NRBv;I#3qC|Q>2w|IGQKVHo4V~eam=@^lQG6E0FH42n~t8
z#1!~RM;!#0LRzOvX*z0ex0D0=>)PKmS02Fqk_1KZe2)GM?k<(P(L7OBr!y6U7g$4%
zhH%3gq%F;~JeL7=7cUm;js~BGUj_l)Wo5j`;F8gRW=PTEMTHqN5oetH%rpF!C|eMl
z|2xba4gD)*#Ik&BlGhTUKHDmQ&Vp@r&Eq0{LcdAjQe+Ff4z_xR*J<ths;a>NB*wC_
zWmx=f-F>rdpb;3nQs-F)oz%7lH?Fj-|I(5VORn!BGFmmX&)b$%Yx<s?xpLl?Gsm#p
QJvrk#H{NA~_oc&s0T4C|J^%m!

literal 0
HcmV?d00001

diff --git a/tests/ts/dmesg/cid-kmsg-json b/tests/ts/dmesg/cid-kmsg-json
new file mode 100755
index 000000000..ad1e3e785
--- /dev/null
+++ b/tests/ts/dmesg/cid-kmsg-json
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="cid-kmsg-json"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG -J -K $TS_SELF/cid-kmsg-input >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/cid-kmsg-limit b/tests/ts/dmesg/cid-kmsg-limit
new file mode 100755
index 000000000..884d4f8ce
--- /dev/null
+++ b/tests/ts/dmesg/cid-kmsg-limit
@@ -0,0 +1,29 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="cid-kmsg-limit"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG --since @1234567890.124 --until @1234567991 -K $TS_SELF/cid-kmsg-input \
+	>> $TS_OUTPUT 2> $TS_ERRLOG
+
+ts_finalize
diff --git a/tests/ts/dmesg/cid-kmsg-newlines b/tests/ts/dmesg/cid-kmsg-newlines
new file mode 100644
index 0000000000000000000000000000000000000000..574d2177796677b73f1efcf273005169ed832c60
GIT binary patch
literal 152
zcmXrjF#tkco#e!voYW%Q5CiL+%)C^Es??%<E(Svb9YY;M128~RV`!b1TFwPh$Hia-
tQeuRm#K^j&Jf91MLCT7`7>o^cjC71K)EQfsWE7>QazV)4{GwE-1^{d2D<=Q|

literal 0
HcmV?d00001

diff --git a/tests/ts/dmesg/kmsg-input b/tests/ts/dmesg/kmsg-input
index b000f4c951ccdcec96c820d37efc64ac8b68a93c..c08331dbf2bfdc9622105e120be99e448cfa89ea 100644
GIT binary patch
literal 3944
zcmbtXYg5};66G_$qO0-&sK`QBZz=1o1>*#71<=}%Ns6Uh*V47E89lsu@R(mer)3jN
zD9C0P;j&(R`rN*Ky4!|k;OKq$oEGgp-Kwfi%Yt0p)$N|F;-%;b+RymmKlrjcJD~kV
z9Mk@%!Qg;|rJK4S(=aW=H-tu?&aWs-@D$(2Fl^GSJ|I)Kg>D?sJ3*7Ph@$aucotnw
zPrjWWos9-`Ru&o=Hl3)rgCfHS%^(y3y*Kc;yCXC{dLIU5p35R35K$qeMcPzJ|KImc
z+{R_1^fX^=-|U{td|vlD;@#uwj^gTJ)g<aRjaB~;--pF*u8cygtgwEl8<mGiTF0_V
zs4B~5{YoxZD^(q?pYQIN8Xvt6$D@l$Z&j7IX`&KZEg$MMmKlwY&IlIa?vADLv3XJX
zrV-M0u5vQ&d12dsy=S)qHJ{IKsIBEJQ@cC1#>Y=!f;sS>!_0sJm`c^Ex>d>Uj-&DM
zHjwCOZ36|8aklul8Xs@M1hbbg$p+?$kEikRHjsJ=#L;=q$JhLyz;JY)$0wLu9H1LI
z8bl*H|1#O#akT))+kEC${2a(OE$2r*!qD*l77(o59~jxTvjKXFkgHjSp_zto4GvVD
zuR=Pm(qe&sYFAXNxGWM`J<uS!s!7*%UWElMZrjX|$syhQE{t)?wk$-L&eKI($p*Sd
zy4sp0*f4NCLyJEU3zptl_&E4@9kM{`3)8iDbsIKiyI3|%Mo<AAY9!o_4d<I>dU)Rn
zEY26%CMkF{4=dF-v3Tlk><iB@1Je~=pc}#o#X(4QBOBFc1*bAg|Ae}_SEs6AMI?QL
zle#ZDMy9{^!0~C8s>)?Hg;GNrt3?VySFqmPr$vb>SCkd)&1G6m>!qyJUbk>-&C_L`
z!}H<z)3<3f9Dkf1kB%lGO;kfoNqaB_{GLX4vZg)MggM_RVg_+F+k)I(&vlpzXH`gC
zou-rHsU8hRhW;rMfqs5E5_<I87_jH+j#lNJs(3kNTg4DN!(by^-xVy?S7E-M4(y-6
zApD+d30~5VFyr4ozwRCh1Us86*Gs$O*X=ymd6xHNhegvE3CAg$EEHXH6mDogDRY??
zsPo8y>sedltOq3?tXJ=^VOY^JUZoVBN5+xihiD5ly_gI_x|mSiu2yB$)O0<(Z&ZN-
zJm|8SjwaC=4YD%+1K$(1$W?*2&L$%oo{Z@<`r5lh{#iG>G`TvSe4AVj&-(0UmrjOX
zMuTDhJzs@SPS>OYCgr$X9bO@|%4EaoKuM`;D4}`eNY|6oXmDCKtE^qn(Qy2WzHNhj
z2S~10eIp=6iQZNgO;u(H3IeSjJw|6k;_HE2$yu7E%>#YD9MefO_*EhTM10%fo#Cxr
zmUTn3_0~ci>y5-NanD8?+vfUpj@c?sr(4g%uDNy=kC{)`X-S*T$lWKNdvuo;NqP5-
z<p$_!w>CH6bjvez2%;_z4Zq+y=^6yr^8d}Vurx0~2eAU*ad|*!(Ris)&0SgjL5Wm3
z#;fl|t*g4&vV4`P2Es>4^(_;9!?uNEcJ;NJN0MuCgNnF5C)2TYuP5|*Yz0)cMZv`!
zT3SD+90hm-WobfmP&_(p%sZ$PxQiREsTk@~K5r|<-J$2&XdfL9TN7qy%r$7+c>LsY
zJ%Bx0IGV5=Fb_C8wk=MPC56ltdR13M{}#&zMZJ)J?|PMw)*u|$7QV}CZtEFYJ!@TL
zt|rH{9@S`Gwnd^*ntXxS%c?IVWP!`5Dw8&D`i9{7a~3Bj>(P#cF2uIR0sK8_V&Mm&
z>7b)oh`FZ;*9|y-;D4ejw45$8^EPWz#1_q{Kp$!pt!mXK<s+q}O3_Vdbbe_$=v!Q#
zR8^t5^oHkOM;9TD#{YtOqVBuS*sRx}Z<Bhg8Q+<`f4mbu!7|GLeN=c}H=J>Ni)6Y?
z<TNcBm34KL-HW-7zzr_O$KA|_Xs5X<+vc6Ab$7=R^~rS{%R$S-tm9y;_A!;NSH9V^
z-tTBch0Ky`&$N(uV-+i`God(3QA&aQpH@Nl5d1uA>m?^4`=N~;Hr2L)jXA;a?YFT%
zrkSF{TUi}u<>GJya43;_N(QDi<NP%OTqlm>C60_83sb^o4%avDLqb*6t~j9)`?iQP
zC5!BV>Sf!Y7T@8=MTNN`XQA+~he{#FF|L>?N5R7U;5(*eZ)NU}QFuu*@g%h9$=Fb6
z*rvosx%?$9C6#^1+VAmxJ@O3cpX<odoR^K~HAza+`5Yq(0$X!nF-lO;<}=Q#6A&*k
z2yLi>sjZo|?+KtH2cqG}(dS`ES4EvJ3amaF(hRby9ynoyiHxzVK=?+$W$^#c7+1rL
z29?`(fL-vpFl@xCi||ns^R&wEFjP^zl*IzSIkvj&O9ci2HwwU_1lSIC0?T_2+f@Mk
z9xICibxM15vk8%H|Cjgy@V&stHghxDqRkW7TUEwW^X)3*8n*YW%2>K(yvYIM`|e+I
CU~KgO

delta 113
zcmaDMx0s*NbRy$&Rx=$#9fOH$yMYWN9fQfXj4CW<I>tJa<Cx_pH#4dNIVKR!DMoc5
m#}vX5X3_+!h++Z>nnMH^Lj_+kX@ez=nYDnl`{n@F|I7fH$sSVx

-- 
2.43.0


^ permalink raw reply related

* [PATCH] Add standard dmesg kmsg interface tests Issue: #2663 patch #2
From: Edward Chron @ 2023-12-31 18:28 UTC (permalink / raw)
  To: util-linux; +Cc: colona, echron, echron

Submission to Project: util-linux
Open Incident: #2663 at github.com/util-linux/util-linux/issues/2663
Component: util-linux/sys-utils
Files: tests/ts/dmesg kmsg interface files and related expected files
Testing on Fedora 39 with Linux-6.6.6 Kernel and CONFIG_PRINTK_CALLER
config option set.
Patch tested and generated with the latest util-linux code pulled.
Revision: no caller optional fields in any of the kmsg-input entries
Revision: retrofitted to apply on top of Issue: #2609 and Issue #2637
This is patch 2 of 2 (second in the series)
A second patch needed to hold 2nd binary file (git binary files issue)

This patch is needed because git format does not produce correct
output if two binary files are included in the same patch.
So adding the second binary file in a second patch to resolve the
issue.

Signed-off-by: Ivan Delalande <colona@arista.com>
Signed-off-by: Edward Chron <echron@arista.com>
---
 tests/ts/dmesg/kmsg-newlines | Bin 0 -> 182 bytes
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 tests/ts/dmesg/kmsg-newlines

diff --git a/tests/ts/dmesg/kmsg-newlines b/tests/ts/dmesg/kmsg-newlines
new file mode 100644
index 0000000000000000000000000000000000000000..a1f96c562ec4da27e24117908a7a1e78f10f9f97
GIT binary patch
literal 182
zcmZ9GQ3`-C3`6(bQ+R*~-JJO0c`6EOVNL{3?>7CJf##!mg!EuoE<!u5%P!3=LCM(k
zhpQ9ag)&0MF&uoI#!D$*CJr(kqr>n+<{(0`_@?1)ORQ&j*x!yx&p^cr8s&&zH$C?_
BGAjT8

literal 0
HcmV?d00001

-- 
2.43.0

^ permalink raw reply

* [PATCH] Add standard dmesg kmsg interface tests Issue: #2663
From: Edward Chron @ 2023-12-31 18:28 UTC (permalink / raw)
  To: util-linux; +Cc: colona, echron, echron

Submission to Project: util-linux
Open Incident: #2663 at github.com/util-linux/util-linux/issues/2663
Component: util-linux/sys-utils
Files: tests/ts/dmesg kmsg interface files and related expected files
Testing on Fedora 39 with Linux-6.6.6 Kernel and CONFIG_PRINTK_CALLER
config option set.
Patch tested and generated with the latest util-linux code pulled.
Revision: no caller optional fields in any of the kmsg-input entries
Revision: retrofitted to apply on top of Issue: #2609 and Issue #2637
This is patch 1 of 2 (first in the series)
Second patch needed to hold second binary file (git binary files issue)

For issue #2609 Thomas and Zak pointed out the we need tests to verify
that the dmesg command works correctly and to allow us to compare the
results from PRINTK_CALLER id field tests provided by #2609 with the
standard (syslog interface) dmesg tests.

Except for a kmsg json test that Thomas added recently we don't have
basic dmesg tests for the kmsg interface to compare results against.

We added tests for the dmesg SYSLOG PRINTK_CALLER id interface so we
can compare against those tests.
Those tests were submitted with Issue #2637.

Those tests were created before Thomas added the new dmesg kmsg test
and I will rename those tests to match the naming scheme that Thomas
is using for tests that are specific to syslog interface and specific
to kmsg interface.

Issue #2609 introduces dmesg kmsg interface support for the PRINTK_CALLER
id field and provides tests to compare against the SYSLOG interface tests
added by #2637. Those tests also need to renamed to be consistent Thomas's
test naming scheme.

Here we've created tests for the dmesg kmsg interface following the
existing test structure for dmesg tests.

With the addition of this set of tests, we have tests for SYSLOG and
SYSLOG PRINTK_CALLER id field to compare against the kmsg and kmsg
PRINTK_CALLER id field tests.

Currently the only kmsg interface specific test that exists is the
kmsg-file test that Thomas added to test the dmesg kmsg interface for
json support.

Thomas also added code for the -K file interface to process dmesg ksmg
interface files for testing so we utilize that code here and add to it.

The kmsg-input file is expanded to provide statements and fields to
completely test the kmsg interface with tests that are equivalent to the
SYSLOG interface dmesg tests.

Additionally a ksmg-newlines file is added which provides kmsg format
for testing with indentation.

The output of the existing kmsg-file test is adjusted to match the
expanded kmsg-input file.

All tests follow the standard util-linux tests format used by dmesg for
unit tests.

Signed-off-by: Ivan Delalande <colona@arista.com>
Signed-off-by: Edward Chron <echron@arista.com>
---
 tests/expected/dmesg/kmsg-colors         |  45 ++++++++
 tests/expected/dmesg/kmsg-console-levels |  61 +++++++++++
 tests/expected/dmesg/kmsg-decode         |  45 ++++++++
 tests/expected/dmesg/kmsg-delta          |  45 ++++++++
 tests/expected/dmesg/kmsg-facilities     |  59 +++++++++++
 tests/expected/dmesg/kmsg-indentation    |  35 +++++++
 tests/expected/dmesg/kmsg-limit          |  31 ++++++
 tests/ts/dmesg/kmsg-colors               |  29 ++++++
 tests/ts/dmesg/kmsg-console-levels       |  43 ++++++++
 tests/ts/dmesg/kmsg-decode               |  28 +++++
 tests/ts/dmesg/kmsg-delta                |  28 +++++
 tests/ts/dmesg/kmsg-facilities           |  31 ++++++
 tests/ts/dmesg/kmsg-indentation          |  40 +++++++
 tests/ts/dmesg/kmsg-limit                |  29 ++++++
 18 files changed, 663 insertions(+), 17 deletions(-)
 create mode 100644 tests/expected/dmesg/kmsg-colors
 create mode 100644 tests/expected/dmesg/kmsg-console-levels
 create mode 100644 tests/expected/dmesg/kmsg-decode
 create mode 100644 tests/expected/dmesg/kmsg-delta
 create mode 100644 tests/expected/dmesg/kmsg-facilities
 create mode 100644 tests/expected/dmesg/kmsg-indentation
 create mode 100644 tests/expected/dmesg/kmsg-limit
 create mode 100755 tests/ts/dmesg/kmsg-colors
 create mode 100755 tests/ts/dmesg/kmsg-console-levels
 create mode 100755 tests/ts/dmesg/kmsg-decode
 create mode 100755 tests/ts/dmesg/kmsg-delta
 create mode 100755 tests/ts/dmesg/kmsg-facilities
 create mode 100755 tests/ts/dmesg/kmsg-indentation
 create mode 100755 tests/ts/dmesg/kmsg-limit

diff --git a/tests/expected/dmesg/kmsg-colors b/tests/expected/dmesg/kmsg-colors
new file mode 100644
index 000000000..35294c5fa
--- /dev/null
+++ b/tests/expected/dmesg/kmsg-colors
@@ -0,0 +1,45 @@
+kern  :emerg : ^[[32m[    0.000000] ^[[0mLinux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000
+kern  :alert : ^[[32m[    0.000001] ^[[0m^[[33mCommand line: ^[[0m^[[7m^[[31minitrd=\ucode.img initrd=\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system^[[0m
+kern  :crit  : ^[[32m[    0.000002] ^[[0m^[[1m^[[31mBIOS-provided physical RAM map:^[[0m
+kern  :err   : ^[[32m[    0.000003] ^[[0m^[[33mBIOS-e820: ^[[0m^[[31m[mem 0x0000000000000000-0x000000000009efff] usable^[[0m
+kern  :warn  : ^[[32m[    0.000004] ^[[0m^[[33mBIOS-e820: ^[[0m^[[1m[mem 0x000000000009f000-0x00000000000bffff] reserved^[[0m
+kern  :notice: ^[[32m[    0.000005] ^[[0m^[[33mBIOS-e820: ^[[0m[mem 0x0000000000100000-0x0000000009afffff] usable
+kern  :info  : ^[[32m[    0.000006] ^[[0m^[[33mBIOS-e820: ^[[0m[mem 0x0000000009b00000-0x0000000009dfffff] reserved
+kern  :debug : ^[[32m[    0.000007] ^[[0m^[[33mBIOS-e820: ^[[0m[mem 0x0000000009e00000-0x0000000009efffff] usable
+kern  :info  : ^[[32m[    0.000008] ^[[0m^[[33mBIOS-e820: ^[[0m[mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS
+kern  :info  : ^[[32m[    0.000009] ^[[0m^[[33mBIOS-e820: ^[[0m[mem 0x0000000009f3c000-0x000000004235ffff] usable
+kern  :info  : ^[[32m[    0.000010] ^[[0m^[[33mBIOS-e820: ^[[0m[mem 0x0000000042360000-0x000000004455ffff] reserved
+kern  :info  : ^[[32m[    0.201607] ^[[0m^[[33msmp: ^[[0mBringing up secondary CPUs ...
+kern  :info  : ^[[32m[    0.201607] ^[[0m^[[33msmpboot: ^[[0mx86: Booting SMP configuration:
+kern  :warn  : ^[[32m[    0.209670] ^[[0m^[[1m  #1  #3  #5  #7^[[0m
+kern  :info  : ^[[32m[    0.212630] ^[[0m^[[33msmp: ^[[0mBrought up 1 node, 16 CPUs
+kern  :notice: ^[[32m[    0.215936] ^[[0m^[[33maudit: ^[[0mtype=2000 audit(1702926179.015:1): state=initialized audit_enabled=0 res=1
+kern  :info  : ^[[32m[    0.215937] ^[[0m^[[33mthermal_sys: ^[[0mRegistered thermal governor 'fair_share'
+kern  :warn  : ^[[32m[    0.215966] ^[[0m^[[33mENERGY_PERF_BIAS: ^[[0m^[[1mSet to 'normal', was 'performance'^[[0m
+kern  :info  : ^[[32m[    0.367657] ^[[0m^[[33mACPI: ^[[0m\_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+kern  :info  : ^[[32m[    0.368615] ^[[0m^[[33mACPI: ^[[0m\_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+kern  :info  : ^[[32m[    0.376316] ^[[0m^[[33mACPI: ^[[0m\_SB_.PRWL: New power resource
+kern  :info  : ^[[32m[    0.376343] ^[[0m^[[33mACPI: ^[[0m\_SB_.PRWB: New power resource
+kern  :info  : ^[[32m[    0.377373] ^[[0m^[[33mACPI: ^[[0mPCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+kern  :info  : ^[[32m[    0.377378] ^[[0m^[[33macpi PNP0A08:00: ^[[0m_OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+kern  :info  : ^[[32m[    0.377569] ^[[0m^[[33macpi PNP0A08:00: ^[[0m_OSC: platform does not support [SHPCHotplug AER]
+kern  :info  : ^[[32m[    0.377933] ^[[0m^[[33macpi PNP0A08:00: ^[[0m_OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+kern  :info  : ^[[32m[    0.378458] ^[[0mPCI host bridge to bus 0000:00
+kern  :info  : ^[[32m[    0.378459] ^[[0m^[[33mpci_bus 0000:00: ^[[0mroot bus resource [io  0x0000-0x0cf7 window]
+kern  :info  : ^[[32m[    0.378461] ^[[0m^[[33mpci_bus 0000:00: ^[[0mroot bus resource [io  0x0d00-0xffff window]
+user  :notice: ^[[32m[    9.398562] ^[[0muser network daemon initialization complete
+daemon:info  : ^[[32m[   10.441520] ^[[0m^[[33msystemd[1]: ^[[0msystemd 254.7-1.fc39 running in system mode
+daemon:info  : ^[[32m[   11.441524] ^[[0m^[[33msystemd[1]: ^[[0mDetected architecture x86-64.
+daemon:info  : ^[[32m[   12.441525] ^[[0m^[[33msystemd[1]: ^[[0mRunning in initrd.
+daemon:info  : ^[[32m[   13.541598] ^[[0m^[[33msystemd[1]: ^[[0mHostname set to <catalina>.
+kern  :info  : ^[[32m[   15.641860] ^[[0m^[[33musb 3-3: ^[[0mNew USB device found, idVendor=1a40, idProduct=0101, bcdDevice= 1.11
+kern  :err   : ^[[32m[   16.690000] ^[[0m^[[33mSerial bus multi instantiate pseudo device driver INT3515:00: ^[[0m^[[31merror -ENXIO: IRQ index 1 not found.^[[0m
+kern  :err   : ^[[32m[   17.710000] ^[[0m^[[33msnd_hda_intel 0000:00:1f.3: ^[[0m^[[31mCORB reset timeout#2, CORBRP = 65535^[[0m
+syslog:info  : ^[[32m[   18.820000] ^[[0m^[[33msystemd-journald[723]: ^[[0mReceived client request to flush runtime journal.
+syslog:warn  : ^[[32m[   20.840000] ^[[0m^[[33msystemd-journald[723]: ^[[0m^[[1mFile /var/log/journal/a124ea923b144109a12d557d5ac53179/system.journal corrupted or uncleanly shut down, renaming and replacing.^[[0m
+syslog:info  : ^[[32m[   21.852348] ^[[0m^[[33msystemd-journald[723]: ^[[0m/var/log/journal/ad7a2547ac0e4342a342e62a34a3eae4/user-1000.journal: Journal file uses a different sequence number ID, rotating.
+kern  :warn  : ^[[32m[   24.871100] ^[[0m^[[33mPEFILE: ^[[0m^[[1mUnsigned PE binary^[[0m
+kern  :err   : ^[[32m[   33.918091] ^[[0m^[[33msnd_hda_intel 0000:00:1f.3: ^[[0m^[[31mCORB reset timeout#2, CORBRP = 65535^[[0m
+kern  :info  : ^[[32m[  144.931785] ^[[0m^[[33musb 3-3.1: ^[[0mdevice firmware changed
+kern  :info  : ^[[32m[  145.953248] ^[[0m^[[33musb 3-3.1: ^[[0mUSB disconnect, device number 44
+kern  :info  : ^[[32m[  147.981859] ^[[0m^[[33musb 3-3.1: ^[[0mNew USB device found, idVendor=17ef, idProduct=6047, bcdDevice= 3.30
diff --git a/tests/expected/dmesg/kmsg-console-levels b/tests/expected/dmesg/kmsg-console-levels
new file mode 100644
index 000000000..d48312510
--- /dev/null
+++ b/tests/expected/dmesg/kmsg-console-levels
@@ -0,0 +1,61 @@
+* Output level: err+
+<0>[    0.000000] Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000
+<1>[    0.000001] Command line: initrd=\ucode.img initrd=\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system
+<2>[    0.000002] BIOS-provided physical RAM map:
+<3>[    0.000003] BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable
+<3>[   16.690000] Serial bus multi instantiate pseudo device driver INT3515:00: error -ENXIO: IRQ index 1 not found.
+<3>[   17.710000] snd_hda_intel 0000:00:1f.3: CORB reset timeout#2, CORBRP = 65535
+<3>[   33.918091] snd_hda_intel 0000:00:1f.3: CORB reset timeout#2, CORBRP = 65535
+* Output level: emerg+
+<0>[    0.000000] Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000
+* Output level: +err
+<3>[    0.000003] BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable
+<4>[    0.000004] BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved
+<5>[    0.000005] BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable
+<6>[    0.000006] BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved
+<7>[    0.000007] BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable
+<6>[    0.000008] BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS
+<6>[    0.000009] BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable
+<6>[    0.000010] BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved
+<6>[    0.201607] smp: Bringing up secondary CPUs ...
+<6>[    0.201607] smpboot: x86: Booting SMP configuration:
+<4>[    0.209670]   #1  #3  #5  #7
+<6>[    0.212630] smp: Brought up 1 node, 16 CPUs
+<5>[    0.215936] audit: type=2000 audit(1702926179.015:1): state=initialized audit_enabled=0 res=1
+<6>[    0.215937] thermal_sys: Registered thermal governor 'fair_share'
+<4>[    0.215966] ENERGY_PERF_BIAS: Set to 'normal', was 'performance'
+<6>[    0.367657] ACPI: \_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+<6>[    0.368615] ACPI: \_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+<6>[    0.376316] ACPI: \_SB_.PRWL: New power resource
+<6>[    0.376343] ACPI: \_SB_.PRWB: New power resource
+<6>[    0.377373] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+<6>[    0.377378] acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+<6>[    0.377569] acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]
+<6>[    0.377933] acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+<6>[    0.378458] PCI host bridge to bus 0000:00
+<6>[    0.378459] pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]
+<6>[    0.378461] pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]
+<13>[    9.398562] user network daemon initialization complete
+<30>[   10.441520] systemd[1]: systemd 254.7-1.fc39 running in system mode
+<30>[   11.441524] systemd[1]: Detected architecture x86-64.
+<30>[   12.441525] systemd[1]: Running in initrd.
+<30>[   13.541598] systemd[1]: Hostname set to <catalina>.
+<6>[   15.641860] usb 3-3: New USB device found, idVendor=1a40, idProduct=0101, bcdDevice= 1.11
+<3>[   16.690000] Serial bus multi instantiate pseudo device driver INT3515:00: error -ENXIO: IRQ index 1 not found.
+<3>[   17.710000] snd_hda_intel 0000:00:1f.3: CORB reset timeout#2, CORBRP = 65535
+<46>[   18.820000] systemd-journald[723]: Received client request to flush runtime journal.
+<44>[   20.840000] systemd-journald[723]: File /var/log/journal/a124ea923b144109a12d557d5ac53179/system.journal corrupted or uncleanly shut down, renaming and replacing.
+<46>[   21.852348] systemd-journald[723]: /var/log/journal/ad7a2547ac0e4342a342e62a34a3eae4/user-1000.journal: Journal file uses a different sequence number ID, rotating.
+<4>[   24.871100] PEFILE: Unsigned PE binary
+<3>[   33.918091] snd_hda_intel 0000:00:1f.3: CORB reset timeout#2, CORBRP = 65535
+<6>[  144.931785] usb 3-3.1: device firmware changed
+<6>[  145.953248] usb 3-3.1: USB disconnect, device number 44
+<6>[  147.981859] usb 3-3.1: New USB device found, idVendor=17ef, idProduct=6047, bcdDevice= 3.30
+* Output level: +debug
+<7>[    0.000007] BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable
+* Output level: notice
+<5>[    0.000005] BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable
+<5>[    0.215936] audit: type=2000 audit(1702926179.015:1): state=initialized audit_enabled=0 res=1
+<13>[    9.398562] user network daemon initialization complete
+* Output level: +
+test_dmesg: unknown level '+'
diff --git a/tests/expected/dmesg/kmsg-decode b/tests/expected/dmesg/kmsg-decode
new file mode 100644
index 000000000..85a664a61
--- /dev/null
+++ b/tests/expected/dmesg/kmsg-decode
@@ -0,0 +1,45 @@
+kern  :emerg : [    0.000000] Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000
+kern  :alert : [    0.000001] Command line: initrd=\ucode.img initrd=\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system
+kern  :crit  : [    0.000002] BIOS-provided physical RAM map:
+kern  :err   : [    0.000003] BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable
+kern  :warn  : [    0.000004] BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved
+kern  :notice: [    0.000005] BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable
+kern  :info  : [    0.000006] BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved
+kern  :debug : [    0.000007] BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable
+kern  :info  : [    0.000008] BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS
+kern  :info  : [    0.000009] BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable
+kern  :info  : [    0.000010] BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved
+kern  :info  : [    0.201607] smp: Bringing up secondary CPUs ...
+kern  :info  : [    0.201607] smpboot: x86: Booting SMP configuration:
+kern  :warn  : [    0.209670]   #1  #3  #5  #7
+kern  :info  : [    0.212630] smp: Brought up 1 node, 16 CPUs
+kern  :notice: [    0.215936] audit: type=2000 audit(1702926179.015:1): state=initialized audit_enabled=0 res=1
+kern  :info  : [    0.215937] thermal_sys: Registered thermal governor 'fair_share'
+kern  :warn  : [    0.215966] ENERGY_PERF_BIAS: Set to 'normal', was 'performance'
+kern  :info  : [    0.367657] ACPI: \_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+kern  :info  : [    0.368615] ACPI: \_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+kern  :info  : [    0.376316] ACPI: \_SB_.PRWL: New power resource
+kern  :info  : [    0.376343] ACPI: \_SB_.PRWB: New power resource
+kern  :info  : [    0.377373] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+kern  :info  : [    0.377378] acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+kern  :info  : [    0.377569] acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]
+kern  :info  : [    0.377933] acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+kern  :info  : [    0.378458] PCI host bridge to bus 0000:00
+kern  :info  : [    0.378459] pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]
+kern  :info  : [    0.378461] pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]
+user  :notice: [    9.398562] user network daemon initialization complete
+daemon:info  : [   10.441520] systemd[1]: systemd 254.7-1.fc39 running in system mode
+daemon:info  : [   11.441524] systemd[1]: Detected architecture x86-64.
+daemon:info  : [   12.441525] systemd[1]: Running in initrd.
+daemon:info  : [   13.541598] systemd[1]: Hostname set to <catalina>.
+kern  :info  : [   15.641860] usb 3-3: New USB device found, idVendor=1a40, idProduct=0101, bcdDevice= 1.11
+kern  :err   : [   16.690000] Serial bus multi instantiate pseudo device driver INT3515:00: error -ENXIO: IRQ index 1 not found.
+kern  :err   : [   17.710000] snd_hda_intel 0000:00:1f.3: CORB reset timeout#2, CORBRP = 65535
+syslog:info  : [   18.820000] systemd-journald[723]: Received client request to flush runtime journal.
+syslog:warn  : [   20.840000] systemd-journald[723]: File /var/log/journal/a124ea923b144109a12d557d5ac53179/system.journal corrupted or uncleanly shut down, renaming and replacing.
+syslog:info  : [   21.852348] systemd-journald[723]: /var/log/journal/ad7a2547ac0e4342a342e62a34a3eae4/user-1000.journal: Journal file uses a different sequence number ID, rotating.
+kern  :warn  : [   24.871100] PEFILE: Unsigned PE binary
+kern  :err   : [   33.918091] snd_hda_intel 0000:00:1f.3: CORB reset timeout#2, CORBRP = 65535
+kern  :info  : [  144.931785] usb 3-3.1: device firmware changed
+kern  :info  : [  145.953248] usb 3-3.1: USB disconnect, device number 44
+kern  :info  : [  147.981859] usb 3-3.1: New USB device found, idVendor=17ef, idProduct=6047, bcdDevice= 3.30
diff --git a/tests/expected/dmesg/kmsg-delta b/tests/expected/dmesg/kmsg-delta
new file mode 100644
index 000000000..caea3e9db
--- /dev/null
+++ b/tests/expected/dmesg/kmsg-delta
@@ -0,0 +1,45 @@
+[    0.000000 <    0.000000>] Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000
+[    0.000001 <    0.000000>] Command line: initrd=\ucode.img initrd=\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system
+[    0.000002 <    0.000000>] BIOS-provided physical RAM map:
+[    0.000003 <    0.000000>] BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable
+[    0.000004 <    0.000000>] BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved
+[    0.000005 <    0.000000>] BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable
+[    0.000006 <    0.000000>] BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved
+[    0.000007 <    0.000000>] BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable
+[    0.000008 <    0.000000>] BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS
+[    0.000009 <    0.000000>] BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable
+[    0.000010 <    0.000000>] BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved
+[    0.201607 <    0.000000>] smp: Bringing up secondary CPUs ...
+[    0.201607 <    0.000000>] smpboot: x86: Booting SMP configuration:
+[    0.209670 <    0.000000>]   #1  #3  #5  #7
+[    0.212630 <    0.000000>] smp: Brought up 1 node, 16 CPUs
+[    0.215936 <    0.000000>] audit: type=2000 audit(1702926179.015:1): state=initialized audit_enabled=0 res=1
+[    0.215937 <    0.000000>] thermal_sys: Registered thermal governor 'fair_share'
+[    0.215966 <    0.000000>] ENERGY_PERF_BIAS: Set to 'normal', was 'performance'
+[    0.367657 <    0.000000>] ACPI: \_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+[    0.368615 <    0.000000>] ACPI: \_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+[    0.376316 <    0.000000>] ACPI: \_SB_.PRWL: New power resource
+[    0.376343 <    0.000000>] ACPI: \_SB_.PRWB: New power resource
+[    0.377373 <    0.000000>] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+[    0.377378 <    0.000000>] acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+[    0.377569 <    0.000000>] acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]
+[    0.377933 <    0.000000>] acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+[    0.378458 <    0.000000>] PCI host bridge to bus 0000:00
+[    0.378459 <    0.000000>] pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]
+[    0.378461 <    0.000000>] pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]
+[    9.398562 <    9.000000>] user network daemon initialization complete
+[   10.441520 <    1.000000>] systemd[1]: systemd 254.7-1.fc39 running in system mode
+[   11.441524 <    1.000000>] systemd[1]: Detected architecture x86-64.
+[   12.441525 <    1.000000>] systemd[1]: Running in initrd.
+[   13.541598 <    1.000000>] systemd[1]: Hostname set to <catalina>.
+[   15.641860 <    2.000000>] usb 3-3: New USB device found, idVendor=1a40, idProduct=0101, bcdDevice= 1.11
+[   16.690000 <    1.000000>] Serial bus multi instantiate pseudo device driver INT3515:00: error -ENXIO: IRQ index 1 not found.
+[   17.710000 <    1.000000>] snd_hda_intel 0000:00:1f.3: CORB reset timeout#2, CORBRP = 65535
+[   18.820000 <    1.000000>] systemd-journald[723]: Received client request to flush runtime journal.
+[   20.840000 <    2.000000>] systemd-journald[723]: File /var/log/journal/a124ea923b144109a12d557d5ac53179/system.journal corrupted or uncleanly shut down, renaming and replacing.
+[   21.852348 <    1.000000>] systemd-journald[723]: /var/log/journal/ad7a2547ac0e4342a342e62a34a3eae4/user-1000.journal: Journal file uses a different sequence number ID, rotating.
+[   24.871100 <    3.000000>] PEFILE: Unsigned PE binary
+[   33.918091 <    9.000000>] snd_hda_intel 0000:00:1f.3: CORB reset timeout#2, CORBRP = 65535
+[  144.931785 <  111.000000>] usb 3-3.1: device firmware changed
+[  145.953248 <    1.000000>] usb 3-3.1: USB disconnect, device number 44
+[  147.981859 <    2.000000>] usb 3-3.1: New USB device found, idVendor=17ef, idProduct=6047, bcdDevice= 3.30
diff --git a/tests/expected/dmesg/kmsg-facilities b/tests/expected/dmesg/kmsg-facilities
new file mode 100644
index 000000000..4b460951a
--- /dev/null
+++ b/tests/expected/dmesg/kmsg-facilities
@@ -0,0 +1,59 @@
+dmesg Facility: -1
+dmesg Facility: 0
+[    0.000000] Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000
+[    0.000001] Command line: initrd=\ucode.img initrd=\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system
+[    0.000002] BIOS-provided physical RAM map:
+[    0.000003] BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable
+[    0.000004] BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved
+[    0.000005] BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable
+[    0.000006] BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved
+[    0.000007] BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable
+[    0.000008] BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS
+[    0.000009] BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable
+[    0.000010] BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved
+[    0.201607] smp: Bringing up secondary CPUs ...
+[    0.201607] smpboot: x86: Booting SMP configuration:
+[    0.209670]   #1  #3  #5  #7
+[    0.212630] smp: Brought up 1 node, 16 CPUs
+[    0.215936] audit: type=2000 audit(1702926179.015:1): state=initialized audit_enabled=0 res=1
+[    0.215937] thermal_sys: Registered thermal governor 'fair_share'
+[    0.215966] ENERGY_PERF_BIAS: Set to 'normal', was 'performance'
+[    0.367657] ACPI: \_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+[    0.368615] ACPI: \_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+[    0.376316] ACPI: \_SB_.PRWL: New power resource
+[    0.376343] ACPI: \_SB_.PRWB: New power resource
+[    0.377373] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+[    0.377378] acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+[    0.377569] acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]
+[    0.377933] acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+[    0.378458] PCI host bridge to bus 0000:00
+[    0.378459] pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]
+[    0.378461] pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]
+[   15.641860] usb 3-3: New USB device found, idVendor=1a40, idProduct=0101, bcdDevice= 1.11
+[   16.690000] Serial bus multi instantiate pseudo device driver INT3515:00: error -ENXIO: IRQ index 1 not found.
+[   17.710000] snd_hda_intel 0000:00:1f.3: CORB reset timeout#2, CORBRP = 65535
+[   24.871100] PEFILE: Unsigned PE binary
+[   33.918091] snd_hda_intel 0000:00:1f.3: CORB reset timeout#2, CORBRP = 65535
+[  144.931785] usb 3-3.1: device firmware changed
+[  145.953248] usb 3-3.1: USB disconnect, device number 44
+[  147.981859] usb 3-3.1: New USB device found, idVendor=17ef, idProduct=6047, bcdDevice= 3.30
+dmesg Facility: 1
+[    9.398562] user network daemon initialization complete
+dmesg Facility: 2
+dmesg Facility: 3
+[   10.441520] systemd[1]: systemd 254.7-1.fc39 running in system mode
+[   11.441524] systemd[1]: Detected architecture x86-64.
+[   12.441525] systemd[1]: Running in initrd.
+[   13.541598] systemd[1]: Hostname set to <catalina>.
+dmesg Facility: 4
+dmesg Facility: 5
+[   18.820000] systemd-journald[723]: Received client request to flush runtime journal.
+[   20.840000] systemd-journald[723]: File /var/log/journal/a124ea923b144109a12d557d5ac53179/system.journal corrupted or uncleanly shut down, renaming and replacing.
+[   21.852348] systemd-journald[723]: /var/log/journal/ad7a2547ac0e4342a342e62a34a3eae4/user-1000.journal: Journal file uses a different sequence number ID, rotating.
+dmesg Facility: 6
+dmesg Facility: 7
+dmesg Facility: 8
+dmesg Facility: 9
+dmesg Facility: 10
+dmesg Facility: 11
+dmesg Facility: 12
diff --git a/tests/expected/dmesg/kmsg-indentation b/tests/expected/dmesg/kmsg-indentation
new file mode 100644
index 000000000..25f41b454
--- /dev/null
+++ b/tests/expected/dmesg/kmsg-indentation
@@ -0,0 +1,35 @@
+[    1.000000] line zero
+[    2.000000] line one
+[    4.000000] line two
+[    7.000000] line three
+[   11.000000] line four
+kern  :notice: [    1.000000] line zero
+user  :crit  : [    2.000000] line one
+mail  :warn  : [    4.000000] line two
+daemon:info  : [    7.000000] line three
+syslog:emerg : [   11.000000] line four
+[<    0.000000>] line zero
+[<    1.000000>] line one
+[<    2.000000>] line two
+[<    3.000000>] line three
+[<    4.000000>] line four
+line zero
+line one
+line two
+line three
+line four
+[Feb13 23:31] line zero
+[  +1.000000] line one
+[  +2.000000] line two
+[  +3.000000] line three
+[  +4.000000] line four
+[Fri Feb 13 23:31:31 2009] line zero
+[Fri Feb 13 23:31:32 2009] line one
+[Fri Feb 13 23:31:34 2009] line two
+[Fri Feb 13 23:31:37 2009] line three
+[Fri Feb 13 23:31:41 2009] line four
+2009-02-13T23:31:31,123456+00:00 line zero
+2009-02-13T23:31:32,123456+00:00 line one
+2009-02-13T23:31:34,123456+00:00 line two
+2009-02-13T23:31:37,123456+00:00 line three
+2009-02-13T23:31:41,123456+00:00 line four
diff --git a/tests/expected/dmesg/kmsg-limit b/tests/expected/dmesg/kmsg-limit
new file mode 100644
index 000000000..0c39b4762
--- /dev/null
+++ b/tests/expected/dmesg/kmsg-limit
@@ -0,0 +1,31 @@
+[    0.201607] smp: Bringing up secondary CPUs ...
+[    0.201607] smpboot: x86: Booting SMP configuration:
+[    0.209670]   #1  #3  #5  #7
+[    0.212630] smp: Brought up 1 node, 16 CPUs
+[    0.215936] audit: type=2000 audit(1702926179.015:1): state=initialized audit_enabled=0 res=1
+[    0.215937] thermal_sys: Registered thermal governor 'fair_share'
+[    0.215966] ENERGY_PERF_BIAS: Set to 'normal', was 'performance'
+[    0.367657] ACPI: \_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+[    0.368615] ACPI: \_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+[    0.376316] ACPI: \_SB_.PRWL: New power resource
+[    0.376343] ACPI: \_SB_.PRWB: New power resource
+[    0.377373] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+[    0.377378] acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+[    0.377569] acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]
+[    0.377933] acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+[    0.378458] PCI host bridge to bus 0000:00
+[    0.378459] pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]
+[    0.378461] pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]
+[    9.398562] user network daemon initialization complete
+[   10.441520] systemd[1]: systemd 254.7-1.fc39 running in system mode
+[   11.441524] systemd[1]: Detected architecture x86-64.
+[   12.441525] systemd[1]: Running in initrd.
+[   13.541598] systemd[1]: Hostname set to <catalina>.
+[   15.641860] usb 3-3: New USB device found, idVendor=1a40, idProduct=0101, bcdDevice= 1.11
+[   16.690000] Serial bus multi instantiate pseudo device driver INT3515:00: error -ENXIO: IRQ index 1 not found.
+[   17.710000] snd_hda_intel 0000:00:1f.3: CORB reset timeout#2, CORBRP = 65535
+[   18.820000] systemd-journald[723]: Received client request to flush runtime journal.
+[   20.840000] systemd-journald[723]: File /var/log/journal/a124ea923b144109a12d557d5ac53179/system.journal corrupted or uncleanly shut down, renaming and replacing.
+[   21.852348] systemd-journald[723]: /var/log/journal/ad7a2547ac0e4342a342e62a34a3eae4/user-1000.journal: Journal file uses a different sequence number ID, rotating.
+[   24.871100] PEFILE: Unsigned PE binary
+[   33.918091] snd_hda_intel 0000:00:1f.3: CORB reset timeout#2, CORBRP = 65535
diff --git a/tests/ts/dmesg/kmsg-colors b/tests/ts/dmesg/kmsg-colors
new file mode 100755
index 000000000..959e7b547
--- /dev/null
+++ b/tests/ts/dmesg/kmsg-colors
@@ -0,0 +1,29 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="kmsg-colors"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+ts_inhibit_custom_colorscheme
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG --color=always -K $TS_SELF/kmsg-input -x >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/kmsg-console-levels b/tests/ts/dmesg/kmsg-console-levels
new file mode 100755
index 000000000..36f8ec097
--- /dev/null
+++ b/tests/ts/dmesg/kmsg-console-levels
@@ -0,0 +1,43 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="kmsg-levels"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+for I in {-1..8}; do
+	$TS_HELPER_DMESG -F $TS_SELF/kmsg-input -l $I >> $TS_OUTPUT 2>/dev/null
+done
+
+echo "* Output level: err+" >> $TS_OUTPUT 2>/dev/null
+$TS_HELPER_DMESG -K $TS_SELF/kmsg-input -r -l err+ >> $TS_OUTPUT 2>/dev/null
+echo "* Output level: emerg+" >> $TS_OUTPUT 2>/dev/null
+$TS_HELPER_DMESG -K $TS_SELF/kmsg-input -r -l emerg+ >> $TS_OUTPUT 2>/dev/null
+echo "* Output level: +err" >> $TS_OUTPUT 2>/dev/null
+$TS_HELPER_DMESG -K $TS_SELF/kmsg-input -r -l +err >> $TS_OUTPUT 2>/dev/null
+echo "* Output level: +debug" >> $TS_OUTPUT 2>/dev/null
+$TS_HELPER_DMESG -K $TS_SELF/kmsg-input -r -l +debug >> $TS_OUTPUT 2>/dev/null
+echo "* Output level: notice" >> $TS_OUTPUT 2>/dev/null
+$TS_HELPER_DMESG -K $TS_SELF/kmsg-input -r -l notice >> $TS_OUTPUT 2>/dev/null
+echo "* Output level: +" >> $TS_OUTPUT 2>/dev/null
+$TS_HELPER_DMESG -K $TS_SELF/kmsg-input -r -l + 2>> $TS_OUTPUT >/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/kmsg-decode b/tests/ts/dmesg/kmsg-decode
new file mode 100755
index 000000000..51fef159d
--- /dev/null
+++ b/tests/ts/dmesg/kmsg-decode
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="kmsg-decode"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG -x -K $TS_SELF/kmsg-input >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/kmsg-delta b/tests/ts/dmesg/kmsg-delta
new file mode 100755
index 000000000..7ae082e76
--- /dev/null
+++ b/tests/ts/dmesg/kmsg-delta
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="kmsg-delta"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG -d -K $TS_SELF/kmsg-input >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/kmsg-facilities b/tests/ts/dmesg/kmsg-facilities
new file mode 100755
index 000000000..b274c5de4
--- /dev/null
+++ b/tests/ts/dmesg/kmsg-facilities
@@ -0,0 +1,31 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="kmsg-facilities"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+for I in {-1..12}; do
+        echo "dmesg Facility: $I" >> $TS_OUTPUT
+	$TS_HELPER_DMESG -K $TS_SELF/kmsg-input -f $I >> $TS_OUTPUT 2>/dev/null
+done
+
+ts_finalize
diff --git a/tests/ts/dmesg/kmsg-indentation b/tests/ts/dmesg/kmsg-indentation
new file mode 100755
index 000000000..16870158f
--- /dev/null
+++ b/tests/ts/dmesg/kmsg-indentation
@@ -0,0 +1,40 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="kmsg-indentation"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG -K $TS_SELF/kmsg-newlines >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG -K $TS_SELF/kmsg-newlines -x >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=delta --kmsg-file $TS_SELF/kmsg-newlines >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=notime --kmsg-file $TS_SELF/kmsg-newlines >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=reltime --kmsg-file $TS_SELF/kmsg-newlines >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=ctime --kmsg-file $TS_SELF/kmsg-newlines >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=iso --kmsg-file $TS_SELF/kmsg-newlines >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+ts_finalize
diff --git a/tests/ts/dmesg/kmsg-limit b/tests/ts/dmesg/kmsg-limit
new file mode 100755
index 000000000..ff70bcf83
--- /dev/null
+++ b/tests/ts/dmesg/kmsg-limit
@@ -0,0 +1,29 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="kmsg-limit"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG --since @1234567890.124 --until @1234567991 -K $TS_SELF/kmsg-input \
+	>> $TS_OUTPUT 2> $TS_ERRLOG
+
+ts_finalize
-- 
2.43.0


^ permalink raw reply related

* [PATCH] Add dmesg syslog interface caller_id tests Issue: #2637
From: Edward Chron @ 2023-12-31 18:27 UTC (permalink / raw)
  To: util-linux; +Cc: colona, echron, echron

Submission to Project: util-linux
Open Incident: #2637 at github.com/util-linux/util-linux/issues/2637
Component: util-linux/sys-utils
Files: tests/ts/dmesg syslog interface caller-id files, tests
       and related expected files
Testing on Fedora 39 with Linux-6.6.6 Kernel and CONFIG_PRINTK_CALLER
config option set.
Patch tested and generated with the latest util-linux code pulled.
Retro-fitted to merge on top of the patch for Issue: #2609

For Issue #2609 Thomas and Zak pointed out the we need tests to verify
that the dmesg command works correctly and to allow us to compare the
results from PRINTK_CALLER id field tests provided by #2609 with the
standard (syslog interface) dmesg tests.

Currently, dmesg only has standard syslog interface tests even though
dmesg -S the syslog interface supports the caller_id field. There
are no syslog caller-id tests.

We would like syslog caller-id tests both to validate that the dmesg
code works correctly with the caller-id field being present and also
to compare against the addition of dmesg kmsg caller_id support added
by Issue #2609.

These tests are for the dmesg syslog interface with caller-id follow the
existing test structure for dmesg tests. The existing dmesg -F interface
is used to input our test files.

Until Thomas added a dmesg kmsg interface for json format testing
there were no dmesg tests except the tests for the generic dmesg
syslog tests. So we're naming the syslog caller-id tests to follow
the test naming convention that Thomas introduced.

For caller_id tests we prefix the test name with cid- abbreviating
the caller_id name to keep the names short. There is no unqiue
indentifier for syslog tests, so syslog tests are currently:

colors, console-levels, decode, delta, facilities, indentation,
limit, json

The cid versions of these test files are just prefixed with cid-
The patch for Issue: #2609 has the files:
cid-input and cid-json and the expected file for cide-json

Additional new dmesg tests are found with Issue #2663 which add
standard dmesg kmsg interface tests providing equivalent tests to
the existing dmesg syslog interface tests.

Also, Issue #2609 introduces dmesg kmsg interface caller-id tests
equivalent to the dmesg syslog interface with caller-id tests introduced
here along with the necessary dmesg kmsg interface caller-id support
needed to accomodate the PRINTK_CALLER id field.

Just for reference, on a Linux system with the CONFIG_PRINTK_CALLER
configuration option set the output from dmesg -S looks like:

    [  520.899558] [   T3919] hub 3-3:1.0: USB hub found

on a system where the PRINTK_CALLER configuration option is not set the
output looks like:

    [  520.899558] hub 3-3:1.0: USB hub found

the additional field specifies either a Thread Id or CPU id depending on
the context of the task or thread at the time the printk that added the
message to the kernel ring buffer was executed.

Signed-off-by: Ivan Delalande <colona@arista.com>
Signed-off-by: Edward Chron <echron@arista.com>
---
 tests/expected/dmesg/cid-colors         | 106 ++++++++++
 tests/expected/dmesg/cid-console-levels | 253 ++++++++++++++++++++++++
 tests/expected/dmesg/cid-decode         | 106 ++++++++++
 tests/expected/dmesg/cid-delta          | 106 ++++++++++
 tests/expected/dmesg/cid-facilities     | 104 ++++++++++
 tests/expected/dmesg/cid-indentation    |  35 ++++
 tests/expected/dmesg/cid-limit          |   4 +
 tests/ts/dmesg/cid-colors               |  29 +++
 tests/ts/dmesg/cid-console-levels       |  36 ++++
 tests/ts/dmesg/cid-decode               |  28 +++
 tests/ts/dmesg/cid-delta                |  27 +++
 tests/ts/dmesg/cid-facilities           |  30 +++
 tests/ts/dmesg/cid-indentation          |  40 ++++
 tests/ts/dmesg/cid-limit                |  29 +++
 tests/ts/dmesg/cid-newlines             |   5 +
 15 files changed, 938 insertions(+)
 create mode 100644 tests/expected/dmesg/cid-colors
 create mode 100644 tests/expected/dmesg/cid-console-levels
 create mode 100644 tests/expected/dmesg/cid-decode
 create mode 100644 tests/expected/dmesg/cid-delta
 create mode 100644 tests/expected/dmesg/cid-facilities
 create mode 100644 tests/expected/dmesg/cid-indentation
 create mode 100644 tests/expected/dmesg/cid-limit
 create mode 100755 tests/ts/dmesg/cid-colors
 create mode 100755 tests/ts/dmesg/cid-console-levels
 create mode 100755 tests/ts/dmesg/cid-decode
 create mode 100755 tests/ts/dmesg/cid-delta
 create mode 100755 tests/ts/dmesg/cid-facilities
 create mode 100755 tests/ts/dmesg/cid-indentation
 create mode 100755 tests/ts/dmesg/cid-limit
 create mode 100644 tests/ts/dmesg/cid-newlines

diff --git a/tests/expected/dmesg/cid-colors b/tests/expected/dmesg/cid-colors
new file mode 100644
index 000000000..3b7aff6d7
--- /dev/null
+++ b/tests/expected/dmesg/cid-colors
@@ -0,0 +1,106 @@
+kern  :emerg : ^[[32m[    0.000000] ^[[0m[    T0] example[0]
+kern  :alert : ^[[32m[    1.000000] ^[[0m[    T1] ^[[7m^[[31mexample[1]^[[0m
+kern  :crit  : ^[[32m[    8.000000] ^[[0m[    T2] ^[[1m^[[31mexample[2]^[[0m
+kern  :err   : ^[[32m[   27.000000] ^[[0m[    T3] ^[[31mexample[3]^[[0m
+kern  :warn  : ^[[32m[   64.000000] ^[[0m[    T4] ^[[1mexample[4]^[[0m
+kern  :notice: ^[[32m[  125.000000] ^[[0m[    T5] example[5]
+kern  :info  : ^[[32m[  216.000000] ^[[0m[    T6] example[6]
+kern  :debug : ^[[32m[  343.000000] ^[[0m[    T7] example[7]
+user  :emerg : ^[[32m[  512.000000] ^[[0m[    T8] example[8]
+user  :alert : ^[[32m[  729.000000] ^[[0m[    T9] ^[[7m^[[31mexample[9]^[[0m
+user  :crit  : ^[[32m[ 1000.000000] ^[[0m[   T10] ^[[1m^[[31mexample[10]^[[0m
+user  :err   : ^[[32m[ 1331.000000] ^[[0m[   T11] ^[[31mexample[11]^[[0m
+user  :warn  : ^[[32m[ 1728.000000] ^[[0m[   T12] ^[[1mexample[12]^[[0m
+user  :notice: ^[[32m[ 2197.000000] ^[[0m[   T13] example[13]
+user  :info  : ^[[32m[ 2744.000000] ^[[0m[   T14] example[14]
+user  :debug : ^[[32m[ 3375.000000] ^[[0m[   T15] example[15]
+mail  :emerg : ^[[32m[ 4096.000000] ^[[0m[   T16] example[16]
+mail  :alert : ^[[32m[ 4913.000000] ^[[0m[   T17] ^[[7m^[[31mexample[17]^[[0m
+mail  :crit  : ^[[32m[ 5832.000000] ^[[0m[   T18] ^[[1m^[[31mexample[18]^[[0m
+mail  :err   : ^[[32m[ 6859.000000] ^[[0m[   T19] ^[[31mexample[19]^[[0m
+mail  :warn  : ^[[32m[ 8000.000000] ^[[0m[   T20] ^[[1mexample[20]^[[0m
+mail  :notice: ^[[32m[ 9261.000000] ^[[0m[   T21] example[21]
+mail  :info  : ^[[32m[10648.000000] ^[[0m[   T22] example[22]
+mail  :debug : ^[[32m[12167.000000] ^[[0m[   T23] example[23]
+daemon:emerg : ^[[32m[13824.000000] ^[[0m[   T24] example[24]
+daemon:alert : ^[[32m[15625.000000] ^[[0m[   T25] ^[[7m^[[31mexample[25]^[[0m
+daemon:crit  : ^[[32m[17576.000000] ^[[0m[   T26] ^[[1m^[[31mexample[26]^[[0m
+daemon:err   : ^[[32m[19683.000000] ^[[0m[   T27] ^[[31mexample[27]^[[0m
+daemon:warn  : ^[[32m[21952.000000] ^[[0m[   T28] ^[[1mexample[28]^[[0m
+daemon:notice: ^[[32m[24389.000000] ^[[0m[   T29] example[29]
+daemon:info  : ^[[32m[27000.000000] ^[[0m[   T10] example[30]
+daemon:debug : ^[[32m[29791.000000] ^[[0m[   T31] example[31]
+auth  :emerg : ^[[32m[32768.000000] ^[[0m[   T32] example[32]
+auth  :alert : ^[[32m[35937.000000] ^[[0m[   T33] ^[[7m^[[31mexample[33]^[[0m
+auth  :crit  : ^[[32m[39304.000000] ^[[0m[   T34] ^[[1m^[[31mexample[34]^[[0m
+auth  :err   : ^[[32m[42875.000000] ^[[0m[   T35] ^[[31mexample[35]^[[0m
+auth  :warn  : ^[[32m[46656.000000] ^[[0m[   T36] ^[[1mexample[36]^[[0m
+auth  :notice: ^[[32m[50653.000000] ^[[0m[   T37] example[37]
+auth  :info  : ^[[32m[54872.000000] ^[[0m[   T38] example[38]
+auth  :debug : ^[[32m[59319.000000] ^[[0m[   T39] example[39]
+syslog:emerg : ^[[32m[64000.000000] ^[[0m[   T40] example[40]
+syslog:alert : ^[[32m[68921.000000] ^[[0m[   T41] ^[[7m^[[31mexample[41]^[[0m
+syslog:crit  : ^[[32m[74088.000000] ^[[0m[   T42] ^[[1m^[[31mexample[42]^[[0m
+syslog:err   : ^[[32m[79507.000000] ^[[0m[   T43] ^[[31mexample[43]^[[0m
+syslog:warn  : ^[[32m[85184.000000] ^[[0m[   T44] ^[[1mexample[44]^[[0m
+syslog:notice: ^[[32m[91125.000000] ^[[0m[   T45] example[45]
+syslog:info  : ^[[32m[97336.000000] ^[[0m[   T46] example[46]
+syslog:debug : ^[[32m[103823.000000] ^[[0m[   T47] example[47]
+lpr   :emerg : ^[[32m[110592.000000] ^[[0m[   T48] example[48]
+lpr   :alert : ^[[32m[117649.000000] ^[[0m[   T49] ^[[7m^[[31mexample[49]^[[0m
+lpr   :crit  : ^[[32m[125000.000000] ^[[0m[   T50] ^[[1m^[[31mexample[50]^[[0m
+lpr   :err   : ^[[32m[132651.000000] ^[[0m[   T51] ^[[31mexample[51]^[[0m
+lpr   :warn  : ^[[32m[140608.000000] ^[[0m[   T52] ^[[1mexample[52]^[[0m
+lpr   :notice: ^[[32m[148877.000000] ^[[0m[   T53] example[53]
+lpr   :info  : ^[[32m[157464.000000] ^[[0m[   T54] example[54]
+lpr   :debug : ^[[32m[166375.000000] ^[[0m[   T55] example[55]
+news  :emerg : ^[[32m[175616.000000] ^[[0m[   T56] example[56]
+news  :alert : ^[[32m[185193.000000] ^[[0m[   T57] ^[[7m^[[31mexample[57]^[[0m
+news  :crit  : ^[[32m[195112.000000] ^[[0m[   T58] ^[[1m^[[31mexample[58]^[[0m
+news  :err   : ^[[32m[205379.000000] ^[[0m[   T59] ^[[31mexample[59]^[[0m
+news  :warn  : ^[[32m[216000.000000] ^[[0m[   T60] ^[[1mexample[60]^[[0m
+news  :notice: ^[[32m[226981.000000] ^[[0m[   T61] example[61]
+news  :info  : ^[[32m[238328.000000] ^[[0m[   T62] example[62]
+news  :debug : ^[[32m[250047.000000] ^[[0m[   T63] example[63]
+uucp  :emerg : ^[[32m[262144.000000] ^[[0m[   T64] example[64]
+uucp  :alert : ^[[32m[274625.000000] ^[[0m[   T65] ^[[7m^[[31mexample[65]^[[0m
+uucp  :crit  : ^[[32m[287496.000000] ^[[0m[   T66] ^[[1m^[[31mexample[66]^[[0m
+uucp  :err   : ^[[32m[300763.000000] ^[[0m[   T67] ^[[31mexample[67]^[[0m
+uucp  :warn  : ^[[32m[314432.000000] ^[[0m[   T68] ^[[1mexample[68]^[[0m
+uucp  :notice: ^[[32m[328509.000000] ^[[0m[   T69] example[69]
+uucp  :info  : ^[[32m[343000.000000] ^[[0m[   T70] example[70]
+uucp  :debug : ^[[32m[357911.000000] ^[[0m[   T71] example[71]
+cron  :emerg : ^[[32m[373248.000000] ^[[0m[   T72] example[72]
+cron  :alert : ^[[32m[389017.000000] ^[[0m[   T73] ^[[7m^[[31mexample[73]^[[0m
+cron  :crit  : ^[[32m[405224.000000] ^[[0m[   T74] ^[[1m^[[31mexample[74]^[[0m
+cron  :err   : ^[[32m[421875.000000] ^[[0m[   T75] ^[[31mexample[75]^[[0m
+cron  :warn  : ^[[32m[438976.000000] ^[[0m[   T76] ^[[1mexample[76]^[[0m
+cron  :notice: ^[[32m[456533.000000] ^[[0m[   T77] example[77]
+cron  :info  : ^[[32m[474552.000000] ^[[0m[   T78] example[78]
+cron  :debug : ^[[32m[493039.000000] ^[[0m[   T79] example[79]
+authpriv:emerg : ^[[32m[512000.000000] ^[[0m[   T80] example[80]
+authpriv:alert : ^[[32m[531441.000000] ^[[0m[   T81] ^[[7m^[[31mexample[81]^[[0m
+authpriv:crit  : ^[[32m[551368.000000] ^[[0m[   T82] ^[[1m^[[31mexample[82]^[[0m
+authpriv:err   : ^[[32m[571787.000000] ^[[0m[   T83] ^[[31mexample[83]^[[0m
+authpriv:warn  : ^[[32m[592704.000000] ^[[0m[   T84] ^[[1mexample[84]^[[0m
+authpriv:notice: ^[[32m[614125.000000] ^[[0m[   T85] example[85]
+authpriv:info  : ^[[32m[636056.000000] ^[[0m[   T86] example[86]
+authpriv:debug : ^[[32m[658503.000000] ^[[0m[   T87] example[87]
+ftp   :emerg : ^[[32m[681472.000000] ^[[0m[   T88] example[88]
+ftp   :alert : ^[[32m[704969.000000] ^[[0m[   T89] ^[[7m^[[31mexample[89]^[[0m
+ftp   :crit  : ^[[32m[729000.000000] ^[[0m[   T90] ^[[1m^[[31mexample[90]^[[0m
+ftp   :err   : ^[[32m[753571.000000] ^[[0m[   T91] ^[[31mexample[91]^[[0m
+ftp   :warn  : ^[[32m[778688.000000] ^[[0m[   T92] ^[[1mexample[92]^[[0m
+ftp   :notice: ^[[32m[804357.000000] ^[[0m[   T93] example[93]
+ftp   :info  : ^[[32m[830584.000000] ^[[0m[   T94] example[94]
+ftp   :debug : ^[[32m[857375.000000] ^[[0m[   T95] example[95]
+res0  :emerg : ^[[32m[884736.000000] ^[[0m[   T96] example[96]
+res0  :alert : ^[[32m[912673.000000] ^[[0m[   T97] ^[[7m^[[31mexample[97]^[[0m
+res0  :crit  : ^[[32m[941192.000000] ^[[0m[   T98] ^[[1m^[[31mexample[98]^[[0m
+res0  :err   : ^[[32m[970299.000000] ^[[0m[   T99] ^[[31mexample[99]^[[0m
+res0  :warn  : ^[[32m[1000000.000000] ^[[0m[  T100] ^[[1mexample[100]^[[0m
+res0  :notice: ^[[32m[1030301.000000] ^[[0m[  T101] example[101]
+res0  :info  : ^[[32m[1061208.000000] ^[[0m[  T102] example[102]
+res0  :debug : ^[[32m[1092727.000000] ^[[0m[  T103] example[103]
+res1  :emerg : ^[[32m[1124864.000000] ^[[0m[  T104] example[104]
+local2:info  : ^[[32m[4557523.000000] ^[[0m[  T105] example[105]
diff --git a/tests/expected/dmesg/cid-console-levels b/tests/expected/dmesg/cid-console-levels
new file mode 100644
index 000000000..9fe993b20
--- /dev/null
+++ b/tests/expected/dmesg/cid-console-levels
@@ -0,0 +1,253 @@
+[    0.000000] [    T0] example[0]
+[  512.000000] [    T8] example[8]
+[ 4096.000000] [   T16] example[16]
+[13824.000000] [   T24] example[24]
+[32768.000000] [   T32] example[32]
+[64000.000000] [   T40] example[40]
+[110592.000000] [   T48] example[48]
+[175616.000000] [   T56] example[56]
+[262144.000000] [   T64] example[64]
+[373248.000000] [   T72] example[72]
+[512000.000000] [   T80] example[80]
+[681472.000000] [   T88] example[88]
+[884736.000000] [   T96] example[96]
+[1124864.000000] [  T104] example[104]
+[    1.000000] [    T1] example[1]
+[  729.000000] [    T9] example[9]
+[ 4913.000000] [   T17] example[17]
+[15625.000000] [   T25] example[25]
+[35937.000000] [   T33] example[33]
+[68921.000000] [   T41] example[41]
+[117649.000000] [   T49] example[49]
+[185193.000000] [   T57] example[57]
+[274625.000000] [   T65] example[65]
+[389017.000000] [   T73] example[73]
+[531441.000000] [   T81] example[81]
+[704969.000000] [   T89] example[89]
+[912673.000000] [   T97] example[97]
+[    8.000000] [    T2] example[2]
+[ 1000.000000] [   T10] example[10]
+[ 5832.000000] [   T18] example[18]
+[17576.000000] [   T26] example[26]
+[39304.000000] [   T34] example[34]
+[74088.000000] [   T42] example[42]
+[125000.000000] [   T50] example[50]
+[195112.000000] [   T58] example[58]
+[287496.000000] [   T66] example[66]
+[405224.000000] [   T74] example[74]
+[551368.000000] [   T82] example[82]
+[729000.000000] [   T90] example[90]
+[941192.000000] [   T98] example[98]
+[   27.000000] [    T3] example[3]
+[ 1331.000000] [   T11] example[11]
+[ 6859.000000] [   T19] example[19]
+[19683.000000] [   T27] example[27]
+[42875.000000] [   T35] example[35]
+[79507.000000] [   T43] example[43]
+[132651.000000] [   T51] example[51]
+[205379.000000] [   T59] example[59]
+[300763.000000] [   T67] example[67]
+[421875.000000] [   T75] example[75]
+[571787.000000] [   T83] example[83]
+[753571.000000] [   T91] example[91]
+[970299.000000] [   T99] example[99]
+[   64.000000] [    T4] example[4]
+[ 1728.000000] [   T12] example[12]
+[ 8000.000000] [   T20] example[20]
+[21952.000000] [   T28] example[28]
+[46656.000000] [   T36] example[36]
+[85184.000000] [   T44] example[44]
+[140608.000000] [   T52] example[52]
+[216000.000000] [   T60] example[60]
+[314432.000000] [   T68] example[68]
+[438976.000000] [   T76] example[76]
+[592704.000000] [   T84] example[84]
+[778688.000000] [   T92] example[92]
+[1000000.000000] [  T100] example[100]
+[  125.000000] [    T5] example[5]
+[ 2197.000000] [   T13] example[13]
+[ 9261.000000] [   T21] example[21]
+[24389.000000] [   T29] example[29]
+[50653.000000] [   T37] example[37]
+[91125.000000] [   T45] example[45]
+[148877.000000] [   T53] example[53]
+[226981.000000] [   T61] example[61]
+[328509.000000] [   T69] example[69]
+[456533.000000] [   T77] example[77]
+[614125.000000] [   T85] example[85]
+[804357.000000] [   T93] example[93]
+[1030301.000000] [  T101] example[101]
+[  216.000000] [    T6] example[6]
+[ 2744.000000] [   T14] example[14]
+[10648.000000] [   T22] example[22]
+[27000.000000] [   T10] example[30]
+[54872.000000] [   T38] example[38]
+[97336.000000] [   T46] example[46]
+[157464.000000] [   T54] example[54]
+[238328.000000] [   T62] example[62]
+[343000.000000] [   T70] example[70]
+[474552.000000] [   T78] example[78]
+[636056.000000] [   T86] example[86]
+[830584.000000] [   T94] example[94]
+[1061208.000000] [  T102] example[102]
+[4557523.000000] [  T105] example[105]
+[  343.000000] [    T7] example[7]
+[ 3375.000000] [   T15] example[15]
+[12167.000000] [   T23] example[23]
+[29791.000000] [   T31] example[31]
+[59319.000000] [   T39] example[39]
+[103823.000000] [   T47] example[47]
+[166375.000000] [   T55] example[55]
+[250047.000000] [   T63] example[63]
+[357911.000000] [   T71] example[71]
+[493039.000000] [   T79] example[79]
+[658503.000000] [   T87] example[87]
+[857375.000000] [   T95] example[95]
+[1092727.000000] [  T103] example[103]
+[    0.000000] [    T0] example[0]
+[    1.000000] [    T1] example[1]
+[    8.000000] [    T2] example[2]
+[   27.000000] [    T3] example[3]
+[  512.000000] [    T8] example[8]
+[  729.000000] [    T9] example[9]
+[ 1000.000000] [   T10] example[10]
+[ 1331.000000] [   T11] example[11]
+[ 4096.000000] [   T16] example[16]
+[ 4913.000000] [   T17] example[17]
+[ 5832.000000] [   T18] example[18]
+[ 6859.000000] [   T19] example[19]
+[13824.000000] [   T24] example[24]
+[15625.000000] [   T25] example[25]
+[17576.000000] [   T26] example[26]
+[19683.000000] [   T27] example[27]
+[32768.000000] [   T32] example[32]
+[35937.000000] [   T33] example[33]
+[39304.000000] [   T34] example[34]
+[42875.000000] [   T35] example[35]
+[64000.000000] [   T40] example[40]
+[68921.000000] [   T41] example[41]
+[74088.000000] [   T42] example[42]
+[79507.000000] [   T43] example[43]
+[110592.000000] [   T48] example[48]
+[117649.000000] [   T49] example[49]
+[125000.000000] [   T50] example[50]
+[132651.000000] [   T51] example[51]
+[175616.000000] [   T56] example[56]
+[185193.000000] [   T57] example[57]
+[195112.000000] [   T58] example[58]
+[205379.000000] [   T59] example[59]
+[262144.000000] [   T64] example[64]
+[274625.000000] [   T65] example[65]
+[287496.000000] [   T66] example[66]
+[300763.000000] [   T67] example[67]
+[373248.000000] [   T72] example[72]
+[389017.000000] [   T73] example[73]
+[405224.000000] [   T74] example[74]
+[421875.000000] [   T75] example[75]
+[512000.000000] [   T80] example[80]
+[531441.000000] [   T81] example[81]
+[551368.000000] [   T82] example[82]
+[571787.000000] [   T83] example[83]
+[681472.000000] [   T88] example[88]
+[704969.000000] [   T89] example[89]
+[729000.000000] [   T90] example[90]
+[753571.000000] [   T91] example[91]
+[884736.000000] [   T96] example[96]
+[912673.000000] [   T97] example[97]
+[941192.000000] [   T98] example[98]
+[970299.000000] [   T99] example[99]
+[1124864.000000] [  T104] example[104]
+[    0.000000] [    T0] example[0]
+[  512.000000] [    T8] example[8]
+[ 4096.000000] [   T16] example[16]
+[13824.000000] [   T24] example[24]
+[32768.000000] [   T32] example[32]
+[64000.000000] [   T40] example[40]
+[110592.000000] [   T48] example[48]
+[175616.000000] [   T56] example[56]
+[262144.000000] [   T64] example[64]
+[373248.000000] [   T72] example[72]
+[512000.000000] [   T80] example[80]
+[681472.000000] [   T88] example[88]
+[884736.000000] [   T96] example[96]
+[1124864.000000] [  T104] example[104]
+[   27.000000] [    T3] example[3]
+[   64.000000] [    T4] example[4]
+[  125.000000] [    T5] example[5]
+[  216.000000] [    T6] example[6]
+[  343.000000] [    T7] example[7]
+[ 1331.000000] [   T11] example[11]
+[ 1728.000000] [   T12] example[12]
+[ 2197.000000] [   T13] example[13]
+[ 2744.000000] [   T14] example[14]
+[ 3375.000000] [   T15] example[15]
+[ 6859.000000] [   T19] example[19]
+[ 8000.000000] [   T20] example[20]
+[ 9261.000000] [   T21] example[21]
+[10648.000000] [   T22] example[22]
+[12167.000000] [   T23] example[23]
+[19683.000000] [   T27] example[27]
+[21952.000000] [   T28] example[28]
+[24389.000000] [   T29] example[29]
+[27000.000000] [   T10] example[30]
+[29791.000000] [   T31] example[31]
+[42875.000000] [   T35] example[35]
+[46656.000000] [   T36] example[36]
+[50653.000000] [   T37] example[37]
+[54872.000000] [   T38] example[38]
+[59319.000000] [   T39] example[39]
+[79507.000000] [   T43] example[43]
+[85184.000000] [   T44] example[44]
+[91125.000000] [   T45] example[45]
+[97336.000000] [   T46] example[46]
+[103823.000000] [   T47] example[47]
+[132651.000000] [   T51] example[51]
+[140608.000000] [   T52] example[52]
+[148877.000000] [   T53] example[53]
+[157464.000000] [   T54] example[54]
+[166375.000000] [   T55] example[55]
+[205379.000000] [   T59] example[59]
+[216000.000000] [   T60] example[60]
+[226981.000000] [   T61] example[61]
+[238328.000000] [   T62] example[62]
+[250047.000000] [   T63] example[63]
+[300763.000000] [   T67] example[67]
+[314432.000000] [   T68] example[68]
+[328509.000000] [   T69] example[69]
+[343000.000000] [   T70] example[70]
+[357911.000000] [   T71] example[71]
+[421875.000000] [   T75] example[75]
+[438976.000000] [   T76] example[76]
+[456533.000000] [   T77] example[77]
+[474552.000000] [   T78] example[78]
+[493039.000000] [   T79] example[79]
+[571787.000000] [   T83] example[83]
+[592704.000000] [   T84] example[84]
+[614125.000000] [   T85] example[85]
+[636056.000000] [   T86] example[86]
+[658503.000000] [   T87] example[87]
+[753571.000000] [   T91] example[91]
+[778688.000000] [   T92] example[92]
+[804357.000000] [   T93] example[93]
+[830584.000000] [   T94] example[94]
+[857375.000000] [   T95] example[95]
+[970299.000000] [   T99] example[99]
+[1000000.000000] [  T100] example[100]
+[1030301.000000] [  T101] example[101]
+[1061208.000000] [  T102] example[102]
+[1092727.000000] [  T103] example[103]
+[4557523.000000] [  T105] example[105]
+[  343.000000] [    T7] example[7]
+[ 3375.000000] [   T15] example[15]
+[12167.000000] [   T23] example[23]
+[29791.000000] [   T31] example[31]
+[59319.000000] [   T39] example[39]
+[103823.000000] [   T47] example[47]
+[166375.000000] [   T55] example[55]
+[250047.000000] [   T63] example[63]
+[357911.000000] [   T71] example[71]
+[493039.000000] [   T79] example[79]
+[658503.000000] [   T87] example[87]
+[857375.000000] [   T95] example[95]
+[1092727.000000] [  T103] example[103]
+test_dmesg: unknown level '+'
diff --git a/tests/expected/dmesg/cid-decode b/tests/expected/dmesg/cid-decode
new file mode 100644
index 000000000..757b9284d
--- /dev/null
+++ b/tests/expected/dmesg/cid-decode
@@ -0,0 +1,106 @@
+kern  :emerg : [    0.000000] [    T0] example[0]
+kern  :alert : [    1.000000] [    T1] example[1]
+kern  :crit  : [    8.000000] [    T2] example[2]
+kern  :err   : [   27.000000] [    T3] example[3]
+kern  :warn  : [   64.000000] [    T4] example[4]
+kern  :notice: [  125.000000] [    T5] example[5]
+kern  :info  : [  216.000000] [    T6] example[6]
+kern  :debug : [  343.000000] [    T7] example[7]
+user  :emerg : [  512.000000] [    T8] example[8]
+user  :alert : [  729.000000] [    T9] example[9]
+user  :crit  : [ 1000.000000] [   T10] example[10]
+user  :err   : [ 1331.000000] [   T11] example[11]
+user  :warn  : [ 1728.000000] [   T12] example[12]
+user  :notice: [ 2197.000000] [   T13] example[13]
+user  :info  : [ 2744.000000] [   T14] example[14]
+user  :debug : [ 3375.000000] [   T15] example[15]
+mail  :emerg : [ 4096.000000] [   T16] example[16]
+mail  :alert : [ 4913.000000] [   T17] example[17]
+mail  :crit  : [ 5832.000000] [   T18] example[18]
+mail  :err   : [ 6859.000000] [   T19] example[19]
+mail  :warn  : [ 8000.000000] [   T20] example[20]
+mail  :notice: [ 9261.000000] [   T21] example[21]
+mail  :info  : [10648.000000] [   T22] example[22]
+mail  :debug : [12167.000000] [   T23] example[23]
+daemon:emerg : [13824.000000] [   T24] example[24]
+daemon:alert : [15625.000000] [   T25] example[25]
+daemon:crit  : [17576.000000] [   T26] example[26]
+daemon:err   : [19683.000000] [   T27] example[27]
+daemon:warn  : [21952.000000] [   T28] example[28]
+daemon:notice: [24389.000000] [   T29] example[29]
+daemon:info  : [27000.000000] [   T10] example[30]
+daemon:debug : [29791.000000] [   T31] example[31]
+auth  :emerg : [32768.000000] [   T32] example[32]
+auth  :alert : [35937.000000] [   T33] example[33]
+auth  :crit  : [39304.000000] [   T34] example[34]
+auth  :err   : [42875.000000] [   T35] example[35]
+auth  :warn  : [46656.000000] [   T36] example[36]
+auth  :notice: [50653.000000] [   T37] example[37]
+auth  :info  : [54872.000000] [   T38] example[38]
+auth  :debug : [59319.000000] [   T39] example[39]
+syslog:emerg : [64000.000000] [   T40] example[40]
+syslog:alert : [68921.000000] [   T41] example[41]
+syslog:crit  : [74088.000000] [   T42] example[42]
+syslog:err   : [79507.000000] [   T43] example[43]
+syslog:warn  : [85184.000000] [   T44] example[44]
+syslog:notice: [91125.000000] [   T45] example[45]
+syslog:info  : [97336.000000] [   T46] example[46]
+syslog:debug : [103823.000000] [   T47] example[47]
+lpr   :emerg : [110592.000000] [   T48] example[48]
+lpr   :alert : [117649.000000] [   T49] example[49]
+lpr   :crit  : [125000.000000] [   T50] example[50]
+lpr   :err   : [132651.000000] [   T51] example[51]
+lpr   :warn  : [140608.000000] [   T52] example[52]
+lpr   :notice: [148877.000000] [   T53] example[53]
+lpr   :info  : [157464.000000] [   T54] example[54]
+lpr   :debug : [166375.000000] [   T55] example[55]
+news  :emerg : [175616.000000] [   T56] example[56]
+news  :alert : [185193.000000] [   T57] example[57]
+news  :crit  : [195112.000000] [   T58] example[58]
+news  :err   : [205379.000000] [   T59] example[59]
+news  :warn  : [216000.000000] [   T60] example[60]
+news  :notice: [226981.000000] [   T61] example[61]
+news  :info  : [238328.000000] [   T62] example[62]
+news  :debug : [250047.000000] [   T63] example[63]
+uucp  :emerg : [262144.000000] [   T64] example[64]
+uucp  :alert : [274625.000000] [   T65] example[65]
+uucp  :crit  : [287496.000000] [   T66] example[66]
+uucp  :err   : [300763.000000] [   T67] example[67]
+uucp  :warn  : [314432.000000] [   T68] example[68]
+uucp  :notice: [328509.000000] [   T69] example[69]
+uucp  :info  : [343000.000000] [   T70] example[70]
+uucp  :debug : [357911.000000] [   T71] example[71]
+cron  :emerg : [373248.000000] [   T72] example[72]
+cron  :alert : [389017.000000] [   T73] example[73]
+cron  :crit  : [405224.000000] [   T74] example[74]
+cron  :err   : [421875.000000] [   T75] example[75]
+cron  :warn  : [438976.000000] [   T76] example[76]
+cron  :notice: [456533.000000] [   T77] example[77]
+cron  :info  : [474552.000000] [   T78] example[78]
+cron  :debug : [493039.000000] [   T79] example[79]
+authpriv:emerg : [512000.000000] [   T80] example[80]
+authpriv:alert : [531441.000000] [   T81] example[81]
+authpriv:crit  : [551368.000000] [   T82] example[82]
+authpriv:err   : [571787.000000] [   T83] example[83]
+authpriv:warn  : [592704.000000] [   T84] example[84]
+authpriv:notice: [614125.000000] [   T85] example[85]
+authpriv:info  : [636056.000000] [   T86] example[86]
+authpriv:debug : [658503.000000] [   T87] example[87]
+ftp   :emerg : [681472.000000] [   T88] example[88]
+ftp   :alert : [704969.000000] [   T89] example[89]
+ftp   :crit  : [729000.000000] [   T90] example[90]
+ftp   :err   : [753571.000000] [   T91] example[91]
+ftp   :warn  : [778688.000000] [   T92] example[92]
+ftp   :notice: [804357.000000] [   T93] example[93]
+ftp   :info  : [830584.000000] [   T94] example[94]
+ftp   :debug : [857375.000000] [   T95] example[95]
+res0  :emerg : [884736.000000] [   T96] example[96]
+res0  :alert : [912673.000000] [   T97] example[97]
+res0  :crit  : [941192.000000] [   T98] example[98]
+res0  :err   : [970299.000000] [   T99] example[99]
+res0  :warn  : [1000000.000000] [  T100] example[100]
+res0  :notice: [1030301.000000] [  T101] example[101]
+res0  :info  : [1061208.000000] [  T102] example[102]
+res0  :debug : [1092727.000000] [  T103] example[103]
+res1  :emerg : [1124864.000000] [  T104] example[104]
+local2:info  : [4557523.000000] [  T105] example[105]
diff --git a/tests/expected/dmesg/cid-delta b/tests/expected/dmesg/cid-delta
new file mode 100644
index 000000000..9b75c63af
--- /dev/null
+++ b/tests/expected/dmesg/cid-delta
@@ -0,0 +1,106 @@
+[    0.000000 <    0.000000>] [    T0] example[0]
+[    1.000000 <    0.000000>] [    T1] example[1]
+[    8.000000 <    7.000000>] [    T2] example[2]
+[   27.000000 <   19.000000>] [    T3] example[3]
+[   64.000000 <   37.000000>] [    T4] example[4]
+[  125.000000 <   61.000000>] [    T5] example[5]
+[  216.000000 <   91.000000>] [    T6] example[6]
+[  343.000000 <  127.000000>] [    T7] example[7]
+[  512.000000 <  169.000000>] [    T8] example[8]
+[  729.000000 <  217.000000>] [    T9] example[9]
+[ 1000.000000 <  271.000000>] [   T10] example[10]
+[ 1331.000000 <  331.000000>] [   T11] example[11]
+[ 1728.000000 <  397.000000>] [   T12] example[12]
+[ 2197.000000 <  469.000000>] [   T13] example[13]
+[ 2744.000000 <  547.000000>] [   T14] example[14]
+[ 3375.000000 <  631.000000>] [   T15] example[15]
+[ 4096.000000 <  721.000000>] [   T16] example[16]
+[ 4913.000000 <  817.000000>] [   T17] example[17]
+[ 5832.000000 <  919.000000>] [   T18] example[18]
+[ 6859.000000 < 1027.000000>] [   T19] example[19]
+[ 8000.000000 < 1141.000000>] [   T20] example[20]
+[ 9261.000000 < 1261.000000>] [   T21] example[21]
+[10648.000000 < 1387.000000>] [   T22] example[22]
+[12167.000000 < 1519.000000>] [   T23] example[23]
+[13824.000000 < 1657.000000>] [   T24] example[24]
+[15625.000000 < 1801.000000>] [   T25] example[25]
+[17576.000000 < 1951.000000>] [   T26] example[26]
+[19683.000000 < 2107.000000>] [   T27] example[27]
+[21952.000000 < 2269.000000>] [   T28] example[28]
+[24389.000000 < 2437.000000>] [   T29] example[29]
+[27000.000000 < 2611.000000>] [   T10] example[30]
+[29791.000000 < 2791.000000>] [   T31] example[31]
+[32768.000000 < 2977.000000>] [   T32] example[32]
+[35937.000000 < 3169.000000>] [   T33] example[33]
+[39304.000000 < 3367.000000>] [   T34] example[34]
+[42875.000000 < 3571.000000>] [   T35] example[35]
+[46656.000000 < 3781.000000>] [   T36] example[36]
+[50653.000000 < 3997.000000>] [   T37] example[37]
+[54872.000000 < 4219.000000>] [   T38] example[38]
+[59319.000000 < 4447.000000>] [   T39] example[39]
+[64000.000000 < 4681.000000>] [   T40] example[40]
+[68921.000000 < 4921.000000>] [   T41] example[41]
+[74088.000000 < 5167.000000>] [   T42] example[42]
+[79507.000000 < 5419.000000>] [   T43] example[43]
+[85184.000000 < 5677.000000>] [   T44] example[44]
+[91125.000000 < 5941.000000>] [   T45] example[45]
+[97336.000000 < 6211.000000>] [   T46] example[46]
+[103823.000000 < 6487.000000>] [   T47] example[47]
+[110592.000000 < 6769.000000>] [   T48] example[48]
+[117649.000000 < 7057.000000>] [   T49] example[49]
+[125000.000000 < 7351.000000>] [   T50] example[50]
+[132651.000000 < 7651.000000>] [   T51] example[51]
+[140608.000000 < 7957.000000>] [   T52] example[52]
+[148877.000000 < 8269.000000>] [   T53] example[53]
+[157464.000000 < 8587.000000>] [   T54] example[54]
+[166375.000000 < 8911.000000>] [   T55] example[55]
+[175616.000000 < 9241.000000>] [   T56] example[56]
+[185193.000000 < 9577.000000>] [   T57] example[57]
+[195112.000000 < 9919.000000>] [   T58] example[58]
+[205379.000000 <10267.000000>] [   T59] example[59]
+[216000.000000 <10621.000000>] [   T60] example[60]
+[226981.000000 <10981.000000>] [   T61] example[61]
+[238328.000000 <11347.000000>] [   T62] example[62]
+[250047.000000 <11719.000000>] [   T63] example[63]
+[262144.000000 <12097.000000>] [   T64] example[64]
+[274625.000000 <12481.000000>] [   T65] example[65]
+[287496.000000 <12871.000000>] [   T66] example[66]
+[300763.000000 <13267.000000>] [   T67] example[67]
+[314432.000000 <13669.000000>] [   T68] example[68]
+[328509.000000 <14077.000000>] [   T69] example[69]
+[343000.000000 <14491.000000>] [   T70] example[70]
+[357911.000000 <14911.000000>] [   T71] example[71]
+[373248.000000 <15337.000000>] [   T72] example[72]
+[389017.000000 <15769.000000>] [   T73] example[73]
+[405224.000000 <16207.000000>] [   T74] example[74]
+[421875.000000 <16651.000000>] [   T75] example[75]
+[438976.000000 <17101.000000>] [   T76] example[76]
+[456533.000000 <17557.000000>] [   T77] example[77]
+[474552.000000 <18019.000000>] [   T78] example[78]
+[493039.000000 <18487.000000>] [   T79] example[79]
+[512000.000000 <18961.000000>] [   T80] example[80]
+[531441.000000 <19441.000000>] [   T81] example[81]
+[551368.000000 <19927.000000>] [   T82] example[82]
+[571787.000000 <20419.000000>] [   T83] example[83]
+[592704.000000 <20917.000000>] [   T84] example[84]
+[614125.000000 <21421.000000>] [   T85] example[85]
+[636056.000000 <21931.000000>] [   T86] example[86]
+[658503.000000 <22447.000000>] [   T87] example[87]
+[681472.000000 <22969.000000>] [   T88] example[88]
+[704969.000000 <23497.000000>] [   T89] example[89]
+[729000.000000 <24031.000000>] [   T90] example[90]
+[753571.000000 <24571.000000>] [   T91] example[91]
+[778688.000000 <25117.000000>] [   T92] example[92]
+[804357.000000 <25669.000000>] [   T93] example[93]
+[830584.000000 <26227.000000>] [   T94] example[94]
+[857375.000000 <26791.000000>] [   T95] example[95]
+[884736.000000 <27361.000000>] [   T96] example[96]
+[912673.000000 <27937.000000>] [   T97] example[97]
+[941192.000000 <28519.000000>] [   T98] example[98]
+[970299.000000 <29107.000000>] [   T99] example[99]
+[1000000.000000 <29701.000000>] [  T100] example[100]
+[1030301.000000 <30301.000000>] [  T101] example[101]
+[1061208.000000 <30907.000000>] [  T102] example[102]
+[1092727.000000 <31519.000000>] [  T103] example[103]
+[1124864.000000 <32137.000000>] [  T104] example[104]
+[4557523.000000 <3432659.000000>] [  T105] example[105]
diff --git a/tests/expected/dmesg/cid-facilities b/tests/expected/dmesg/cid-facilities
new file mode 100644
index 000000000..b8afa3809
--- /dev/null
+++ b/tests/expected/dmesg/cid-facilities
@@ -0,0 +1,104 @@
+[    0.000000] [    T0] example[0]
+[    1.000000] [    T1] example[1]
+[    8.000000] [    T2] example[2]
+[   27.000000] [    T3] example[3]
+[   64.000000] [    T4] example[4]
+[  125.000000] [    T5] example[5]
+[  216.000000] [    T6] example[6]
+[  343.000000] [    T7] example[7]
+[  512.000000] [    T8] example[8]
+[  729.000000] [    T9] example[9]
+[ 1000.000000] [   T10] example[10]
+[ 1331.000000] [   T11] example[11]
+[ 1728.000000] [   T12] example[12]
+[ 2197.000000] [   T13] example[13]
+[ 2744.000000] [   T14] example[14]
+[ 3375.000000] [   T15] example[15]
+[ 4096.000000] [   T16] example[16]
+[ 4913.000000] [   T17] example[17]
+[ 5832.000000] [   T18] example[18]
+[ 6859.000000] [   T19] example[19]
+[ 8000.000000] [   T20] example[20]
+[ 9261.000000] [   T21] example[21]
+[10648.000000] [   T22] example[22]
+[12167.000000] [   T23] example[23]
+[13824.000000] [   T24] example[24]
+[15625.000000] [   T25] example[25]
+[17576.000000] [   T26] example[26]
+[19683.000000] [   T27] example[27]
+[21952.000000] [   T28] example[28]
+[24389.000000] [   T29] example[29]
+[27000.000000] [   T10] example[30]
+[29791.000000] [   T31] example[31]
+[32768.000000] [   T32] example[32]
+[35937.000000] [   T33] example[33]
+[39304.000000] [   T34] example[34]
+[42875.000000] [   T35] example[35]
+[46656.000000] [   T36] example[36]
+[50653.000000] [   T37] example[37]
+[54872.000000] [   T38] example[38]
+[59319.000000] [   T39] example[39]
+[64000.000000] [   T40] example[40]
+[68921.000000] [   T41] example[41]
+[74088.000000] [   T42] example[42]
+[79507.000000] [   T43] example[43]
+[85184.000000] [   T44] example[44]
+[91125.000000] [   T45] example[45]
+[97336.000000] [   T46] example[46]
+[103823.000000] [   T47] example[47]
+[110592.000000] [   T48] example[48]
+[117649.000000] [   T49] example[49]
+[125000.000000] [   T50] example[50]
+[132651.000000] [   T51] example[51]
+[140608.000000] [   T52] example[52]
+[148877.000000] [   T53] example[53]
+[157464.000000] [   T54] example[54]
+[166375.000000] [   T55] example[55]
+[175616.000000] [   T56] example[56]
+[185193.000000] [   T57] example[57]
+[195112.000000] [   T58] example[58]
+[205379.000000] [   T59] example[59]
+[216000.000000] [   T60] example[60]
+[226981.000000] [   T61] example[61]
+[238328.000000] [   T62] example[62]
+[250047.000000] [   T63] example[63]
+[262144.000000] [   T64] example[64]
+[274625.000000] [   T65] example[65]
+[287496.000000] [   T66] example[66]
+[300763.000000] [   T67] example[67]
+[314432.000000] [   T68] example[68]
+[328509.000000] [   T69] example[69]
+[343000.000000] [   T70] example[70]
+[357911.000000] [   T71] example[71]
+[373248.000000] [   T72] example[72]
+[389017.000000] [   T73] example[73]
+[405224.000000] [   T74] example[74]
+[421875.000000] [   T75] example[75]
+[438976.000000] [   T76] example[76]
+[456533.000000] [   T77] example[77]
+[474552.000000] [   T78] example[78]
+[493039.000000] [   T79] example[79]
+[512000.000000] [   T80] example[80]
+[531441.000000] [   T81] example[81]
+[551368.000000] [   T82] example[82]
+[571787.000000] [   T83] example[83]
+[592704.000000] [   T84] example[84]
+[614125.000000] [   T85] example[85]
+[636056.000000] [   T86] example[86]
+[658503.000000] [   T87] example[87]
+[681472.000000] [   T88] example[88]
+[704969.000000] [   T89] example[89]
+[729000.000000] [   T90] example[90]
+[753571.000000] [   T91] example[91]
+[778688.000000] [   T92] example[92]
+[804357.000000] [   T93] example[93]
+[830584.000000] [   T94] example[94]
+[857375.000000] [   T95] example[95]
+[884736.000000] [   T96] example[96]
+[912673.000000] [   T97] example[97]
+[941192.000000] [   T98] example[98]
+[970299.000000] [   T99] example[99]
+[1000000.000000] [  T100] example[100]
+[1030301.000000] [  T101] example[101]
+[1061208.000000] [  T102] example[102]
+[1092727.000000] [  T103] example[103]
diff --git a/tests/expected/dmesg/cid-indentation b/tests/expected/dmesg/cid-indentation
new file mode 100644
index 000000000..573682795
--- /dev/null
+++ b/tests/expected/dmesg/cid-indentation
@@ -0,0 +1,35 @@
+[    1.000000] [    T1] new
+                        line
+[    2.000000] [    T2] two
+                        new
+                        lines
+user  :crit  : [    1.000000] [    T1] new
+                                       line
+mail  :warn  : [    2.000000] [    T2] two
+                                       new
+                                       lines
+[<    0.000000>] [    T1] new
+                          line
+[<    1.000000>] [    T2] two
+                          new
+                          lines
+[    T1] new
+         line
+[    T2] two
+         new
+         lines
+[Feb13 23:31] [    T1] new
+                       line
+[  +1.000000] [    T2] two
+                       new
+                       lines
+[Fri Feb 13 23:31:31 2009] [    T1] new
+                                    line
+[Fri Feb 13 23:31:32 2009] [    T2] two
+                                    new
+                                    lines
+2009-02-13T23:31:31,123456+00:00 [    T1] new
+                                          line
+2009-02-13T23:31:32,123456+00:00 [    T2] two
+                                          new
+                                          lines
diff --git a/tests/expected/dmesg/cid-limit b/tests/expected/dmesg/cid-limit
new file mode 100644
index 000000000..c30b4ac9a
--- /dev/null
+++ b/tests/expected/dmesg/cid-limit
@@ -0,0 +1,4 @@
+[    1.000000] [    T1] example[1]
+[    8.000000] [    T2] example[2]
+[   27.000000] [    T3] example[3]
+[   64.000000] [    T4] example[4]
diff --git a/tests/ts/dmesg/cid-colors b/tests/ts/dmesg/cid-colors
new file mode 100755
index 000000000..d17dd17c0
--- /dev/null
+++ b/tests/ts/dmesg/cid-colors
@@ -0,0 +1,29 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="cid-colors"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+ts_inhibit_custom_colorscheme
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG --color=always -F $TS_SELF/cid-input -x >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/cid-console-levels b/tests/ts/dmesg/cid-console-levels
new file mode 100755
index 000000000..e2f241bde
--- /dev/null
+++ b/tests/ts/dmesg/cid-console-levels
@@ -0,0 +1,36 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="cid-levels"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+for I in {-1..8}; do
+	$TS_HELPER_DMESG -F $TS_SELF/cid-input -l $I >> $TS_OUTPUT 2>/dev/null
+done
+
+$TS_HELPER_DMESG -F $TS_SELF/cid-input -l err+ >> $TS_OUTPUT 2>/dev/null
+$TS_HELPER_DMESG -F $TS_SELF/cid-input -l emerg+ >> $TS_OUTPUT 2>/dev/null
+$TS_HELPER_DMESG -F $TS_SELF/cid-input -l +err >> $TS_OUTPUT 2>/dev/null
+$TS_HELPER_DMESG -F $TS_SELF/cid-input -l +debug >> $TS_OUTPUT 2>/dev/null
+$TS_HELPER_DMESG -F $TS_SELF/cid-input -l + 2>> $TS_OUTPUT >/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/cid-decode b/tests/ts/dmesg/cid-decode
new file mode 100755
index 000000000..488f52a32
--- /dev/null
+++ b/tests/ts/dmesg/cid-decode
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="cid-decode"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG -x -F $TS_SELF/cid-input >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/cid-delta b/tests/ts/dmesg/cid-delta
new file mode 100755
index 000000000..8ba952a5d
--- /dev/null
+++ b/tests/ts/dmesg/cid-delta
@@ -0,0 +1,27 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="cid-delta"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+$TS_HELPER_DMESG -d -F $TS_SELF/cid-input >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/cid-facilities b/tests/ts/dmesg/cid-facilities
new file mode 100755
index 000000000..b4b613e8b
--- /dev/null
+++ b/tests/ts/dmesg/cid-facilities
@@ -0,0 +1,30 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="cid-facilities"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+for I in {-1..12}; do
+	$TS_HELPER_DMESG -F $TS_SELF/cid-input -f $I >> $TS_OUTPUT 2>/dev/null
+done
+
+ts_finalize
diff --git a/tests/ts/dmesg/cid-indentation b/tests/ts/dmesg/cid-indentation
new file mode 100755
index 000000000..434e1694b
--- /dev/null
+++ b/tests/ts/dmesg/cid-indentation
@@ -0,0 +1,40 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="cid-indentation"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG -F $TS_SELF/cid-newlines >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG -F $TS_SELF/cid-newlines -x >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=delta --file $TS_SELF/cid-newlines >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=notime --file $TS_SELF/cid-newlines >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=reltime --file $TS_SELF/cid-newlines >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=ctime --file $TS_SELF/cid-newlines >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=iso --file $TS_SELF/cid-newlines >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+ts_finalize
diff --git a/tests/ts/dmesg/cid-limit b/tests/ts/dmesg/cid-limit
new file mode 100755
index 000000000..34f928a9e
--- /dev/null
+++ b/tests/ts/dmesg/cid-limit
@@ -0,0 +1,29 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="cid-limit"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG --since @1234567890.124 --until @1234567991 \
+	-F $TS_SELF/cid-input >> $TS_OUTPUT 2> $TS_ERRLOG
+
+ts_finalize
diff --git a/tests/ts/dmesg/cid-newlines b/tests/ts/dmesg/cid-newlines
new file mode 100644
index 000000000..682ce40bb
--- /dev/null
+++ b/tests/ts/dmesg/cid-newlines
@@ -0,0 +1,5 @@
+<10>[    1.000000] [    T1] new
+line
+<20>[    2.000000] [    T2] two
+new
+lines
-- 
2.43.0


^ permalink raw reply related

* [PATCH] util-linux/sys-utils dmesg add PRINTK_CALLER support
From: Edward Chron @ 2023-12-31 18:27 UTC (permalink / raw)
  To: util-linux; +Cc: colona, echron, echron

Submission to Project: util-linux
Open Incident: #2609 at github.com/util-linux/util-linux/issues/2609
Component: util-linux/sys-utils
File: dmesg.c
Code level patch applied against: 2.39.3 - latest code pulled from
           git.github.com:util-linux/util-linux.git
Revision: #1 on 2023/12/08 per Review from Karel Zak
Revision: #2 on 2023/12/12 Adjust line offsets for master update and
                           Add caller_id_size init to dmesg -K
Revision: #3 on 2023/12/12 Use of sizeof for cidbuf and limit search
                           for caller_id to dmesg prefix to msg text
Revision: #4 on 2023/12/15 Ensure SYSLOG and kmsg inputs have
                           caller_id_size set appropriately
Revision: #5 on 2023/12/24 Make caller_id width consistent with
                           makedumpfile
Revision: #6 on 2023/12/30 Use updated test naming convention
                           Include expected results for new tests

Add support to standard dmesg command for the optional Linux Kernel
debug CONFIG option PRINTK_CALLER which adds an optional dmesg field
that contains the Thread Id or CPU Id that is issuing the printk to
add the message to the kernel ring buffer. This makes debugging simpler
as dmesg entries for a specific thread or CPU can be recognized.

The dmesg -S using the old syslog interface supports printing the
PRINTK_CALLER field but currently standard dmesg does not support
printing the field if present. There are utilities that use dmesg and
so it would be optimal if dmesg supported PRINTK_CALLER as well.

The additional field provided by PRINTK_CALLER is only present
if it was configured for the Linux kernel where the dmesg command
is run. It is a debug option and not configured by default so the
dmesg output will only change for those kernels where the option was
configured when the kernel was built. For users who went to the
trouble to configure PRINTK_CALLER and have the extra field available
for debugging, having dmesg print the field is very helpful.

Size of the PRINTK_CALLER field is determined by the maximum number
tasks that can be run on the system which is limited by the value of
/proc/sys/kernel/pid_max as pid values are from 0 to value - 1.
This value determines the number of id digits needed by the caller id.
The PRINTK_CALLER field is printed as T<id> for a Task Id or C<id>
for a CPU Id for a printk in CPU context. The values are left space
padded and enclosed in parentheses such as: [    T123] or [     C16]

For consistency with dmesg -S which supports the PRINTK_CALLER field
the field is printed followed by a space. For JSON format output the
PRINTK_CALLER field is identified as caller as that is consistent with
it's naming in /dev/kmsg. No space padding is used to reduce space
consumed by the JSON output. So the output from the command on a system
with PRINTK_CALLER field enabled in the Linux .config file the dmesg
output appears as:

> dmesg
...
[  520.897104] [   T3919] usb 3-3: Product: USB 2.0 Hub

and

> dmesg -x
...
kern  :info  : [  520.897104] [   T3919] usb 3-3: Product: USB 2.0 Hub

and

> dmesg -J
...
      },{
         "pri": 6,
         "time":    520.897104,
         "caller": "T3919",
         "msg": "usb 3-3: Product: USB 2.0 Hub"
      },{

and

> dmesg -J -x
...
      },{
         "fac": "kern",
         "pri": "info",
         "time":   520.897104,
         "caller": "T3919",
         "msg": "usb 3-3: Product: USB 2.0 Hub"
      },{

>

For comparison:

> dmesg -S
...
[  520.897104] [ T3919] usb 3-3: Product: USB 2.0 Hub

and

> dmesg -S -x
...
kern  :info  : [  520.897104] [ T3919] usb 3-3: Product: USB 2.0 Hub

Note: When dmesg uses the old syslog interface the reserved space for
      the PRINTK_CALLER field is capped at 5 digits because 32-bit
      kernels are capped at 32768 as the max number of PIDs. However,
      64-bit systems are currently capped at 2^22 PIDs (0 - 4194303).
      The PID cap is set by PID_MAX_LIMIT but the system limit can be
      less so we use /proc/sys/kernel/pid_max to determine the size
      needed to hold the maximum PID value size for the current system.
      Many 64-bit systems support 2^22 PIDs (0 - 4194303) and you see:

> dmesg -x
...
kern  :info  : [  520.899558] [   T3919] hub 3-3:1.0: USB hub found
...
kern  :info  : [ 9830.456898] [  T98982] cgroup: fork rejected by pids ...
kern  :info  : [14301.158878] [ T137336] cgroup: fork rejected by pids ...
kern  :info  : [18980.803190] [T1637865] cgroup: fork rejected by pids ...

> dmesg -S -x
...
kern  :info  : [  520.899558] [ T3919] hub 3-3:1.0: USB hub found
...
kern  :info  : [ 9830.456898] [T98982] cgroup: fork rejected by pids ...
kern  :info  : [14301.158878] [T137336] cgroup: fork rejected by pids ...
kern  :info  : [18980.803190] [T1637865] cgroup: fork rejected by pids ...

This is the only difference seen with PRINTK_CALLER configured and
printing between the dmesg /dev/kmsg interface and the dmesg -S syslog
interface.

Tests naming has been revised based on naming convention Thomas used to
introduce dmest json tests. The naming of test and input files that
reside in tests/ts/dmeg include:

<name> are existing dmesg syslog interface tests and input files.
cid-<name> are dmesg syslog interface caller_id tests and input files.
json-<name> are dmesg kmsg interface tests and input files.
cid-json-<name> are dmesg kmsg interface caller_id tests and input files.

Resulting expected files match the test names.

Signed-off-by: Ivan Delalande <colona@arista.com>
Signed-off-by: Edward Chron <echron@arista.com>
---
 include/pathnames.h                          |   3 +
 sys-utils/dmesg.c                            | 128 ++++-
 tests/expected/dmesg/cid-json                | 535 +++++++++++++++++++
 tests/expected/dmesg/cid-kmsg-colors         |  45 ++
 tests/expected/dmesg/cid-kmsg-console-levels |  97 ++++
 tests/expected/dmesg/cid-kmsg-decode         |  45 ++
 tests/expected/dmesg/cid-kmsg-delta          |  45 ++
 tests/expected/dmesg/cid-kmsg-facilities     |  45 ++
 tests/expected/dmesg/cid-kmsg-indentation    |  28 +
 tests/expected/dmesg/cid-kmsg-json           | 230 ++++++++
 tests/expected/dmesg/cid-kmsg-limit          |  31 ++
 tests/expected/dmesg/kmsg-file               | 126 ++++-
 tests/ts/dmesg/cid-input                     | 106 ++++
 tests/ts/dmesg/cid-json                      |  28 +
 tests/ts/dmesg/cid-kmsg-colors               |  29 +
 tests/ts/dmesg/cid-kmsg-console-levels       |  36 ++
 tests/ts/dmesg/cid-kmsg-decode               |  28 +
 tests/ts/dmesg/cid-kmsg-delta                |  28 +
 tests/ts/dmesg/cid-kmsg-facilities           |  30 ++
 tests/ts/dmesg/cid-kmsg-indentation          |  40 ++
 tests/ts/dmesg/cid-kmsg-input                | Bin 0 -> 4425 bytes
 tests/ts/dmesg/cid-kmsg-json                 |  28 +
 tests/ts/dmesg/cid-kmsg-limit                |  29 +
 tests/ts/dmesg/cid-kmsg-newlines             | Bin 0 -> 152 bytes
 tests/ts/dmesg/kmsg-input                    | Bin 1955 -> 3944 bytes
 25 files changed, 1720 insertions(+), 20 deletions(-)
 create mode 100644 tests/expected/dmesg/cid-json
 create mode 100644 tests/expected/dmesg/cid-kmsg-colors
 create mode 100644 tests/expected/dmesg/cid-kmsg-console-levels
 create mode 100644 tests/expected/dmesg/cid-kmsg-decode
 create mode 100644 tests/expected/dmesg/cid-kmsg-delta
 create mode 100644 tests/expected/dmesg/cid-kmsg-facilities
 create mode 100644 tests/expected/dmesg/cid-kmsg-indentation
 create mode 100644 tests/expected/dmesg/cid-kmsg-json
 create mode 100644 tests/expected/dmesg/cid-kmsg-limit
 create mode 100644 tests/ts/dmesg/cid-input
 create mode 100755 tests/ts/dmesg/cid-json
 create mode 100755 tests/ts/dmesg/cid-kmsg-colors
 create mode 100755 tests/ts/dmesg/cid-kmsg-console-levels
 create mode 100755 tests/ts/dmesg/cid-kmsg-decode
 create mode 100755 tests/ts/dmesg/cid-kmsg-delta
 create mode 100755 tests/ts/dmesg/cid-kmsg-facilities
 create mode 100755 tests/ts/dmesg/cid-kmsg-indentation
 create mode 100644 tests/ts/dmesg/cid-kmsg-input
 create mode 100755 tests/ts/dmesg/cid-kmsg-json
 create mode 100755 tests/ts/dmesg/cid-kmsg-limit
 create mode 100644 tests/ts/dmesg/cid-kmsg-newlines

diff --git a/include/pathnames.h b/include/pathnames.h
index caf0e63d4..81fa405f6 100644
--- a/include/pathnames.h
+++ b/include/pathnames.h
@@ -230,4 +230,7 @@
 /* cgroup path */
 #define _PATH_SYS_CGROUP	"/sys/fs/cgroup"
 
+/* Maximum number of PIDs system supports */
+#define _PATH_PROC_PIDMAX	"/proc/sys/kernel/pid_max"
+
 #endif /* PATHNAMES_H */
diff --git a/sys-utils/dmesg.c b/sys-utils/dmesg.c
index 77728b419..e27966b05 100644
--- a/sys-utils/dmesg.c
+++ b/sys-utils/dmesg.c
@@ -13,7 +13,9 @@
  */
 #include <stdio.h>
 #include <getopt.h>
+#include <stdbool.h>
 #include <stdlib.h>
+#include <string.h>
 #include <sys/klog.h>
 #include <sys/syslog.h>
 #include <sys/time.h>
@@ -41,6 +43,7 @@
 #include "mangle.h"
 #include "pager.h"
 #include "jsonwrt.h"
+#include "pathnames.h"
 
 /* Close the log.  Currently a NOP. */
 #define SYSLOG_ACTION_CLOSE          0
@@ -65,6 +68,12 @@
 /* Return size of the log buffer */
 #define SYSLOG_ACTION_SIZE_BUFFER   10
 
+#define PID_CHARS_MAX sizeof(stringify_value(LONG_MAX))
+#define PID_CHARS_DEFAULT sizeof(stringify_value(INT_MAX))
+#define SYSLOG_DEFAULT_CALLER_ID_CHARS sizeof(stringify_value(SHRT_MAX))-1
+#define DMESG_CALLER_PREFIX "caller="
+#define DMESG_CALLER_PREFIXSZ (sizeof(DMESG_CALLER_PREFIX)-1)
+
 /*
  * Color scheme
  */
@@ -233,6 +242,7 @@ struct dmesg_control {
 			force_prefix:1;	/* force timestamp and decode prefix
 					   on each line */
 	int		indent;		/* due to timestamps if newline */
+	size_t          caller_id_size;   /* PRINTK_CALLERID max field size */
 };
 
 struct dmesg_record {
@@ -242,6 +252,7 @@ struct dmesg_record {
 	int		level;
 	int		facility;
 	struct timeval  tv;
+	char		caller_id[PID_CHARS_MAX];
 
 	const char	*next;		/* buffer with next unparsed record */
 	size_t		next_size;	/* size of the next buffer */
@@ -254,6 +265,7 @@ struct dmesg_record {
 		(_r)->level = -1; \
 		(_r)->tv.tv_sec = 0; \
 		(_r)->tv.tv_usec = 0; \
+		(_r)->caller_id[0] = 0; \
 	} while (0)
 
 static int process_kmsg(struct dmesg_control *ctl);
@@ -551,6 +563,45 @@ static int get_syslog_buffer_size(void)
 	return n > 0 ? n : 0;
 }
 
+/*
+ * Get the number of characters needed to hold the maximum number
+ * of tasks this system supports. This size of string could hold
+ * a thread id large enough for the highest thread id.
+ * This is needed to determine the number of characters reserved for
+ * the PRINTK_CALLER field if it has been configured in the Linux Kernel.
+ *
+ * The number of digits sets the max value since the value can't exceed
+ * a value of that size. The /proc field defined by _PATH_PROC_PIDMAX
+ * holds the maximum number of PID values that may be ussed by the system,
+ * so 0 to that value minus one.
+ *
+ * For determining the size of the PRINTK_CALLER field, we make the safe
+ * assumption that the number of threads >= number of cpus. This because
+ * the PRINTK_CALLER field can hold either a thread id or a CPU id value.
+ *
+ * If we can't access the pid max kernel proc entry we assign a default
+ * field size of 5 characters as that is what the old syslog interface
+ * uses as the reserved field size. This is justified because 32-bit Linux
+ * systems are limited to PID values between (0-32767).
+ *
+ */
+static size_t max_threads_id_size(void)
+{
+	char taskmax[PID_CHARS_MAX] = {'\0'};
+	ssize_t rdsize;
+	int fd;
+
+	fd = open(_PATH_PROC_PIDMAX, O_RDONLY);
+	if (fd == -1)
+		return PID_CHARS_DEFAULT;
+
+	rdsize = read(fd, taskmax, sizeof(taskmax));
+	if (rdsize == -1)
+		return PID_CHARS_DEFAULT;
+
+	return strnlen(taskmax, sizeof(taskmax));
+}
+
 /*
  * Reads messages from regular file by mmap
  */
@@ -624,6 +675,8 @@ static ssize_t process_buffer(struct dmesg_control *ctl, char **buf)
 			ctl->bufsize = get_syslog_buffer_size();
 
 		n = read_syslog_buffer(ctl, buf);
+		/* Set number of PID characters for caller_id spacing */
+		ctl->caller_id_size = SYSLOG_DEFAULT_CALLER_ID_CHARS;
 		break;
 	case DMESG_METHOD_KMSG:
 		if (ctl->filename)
@@ -728,6 +781,39 @@ static const char *skip_item(const char *begin, const char *end, const char *sep
 	return begin;
 }
 
+/*
+ * Checks to see if the caller (caller id) field is present in the kmsg record.
+ * This is true if the PRINTK_CALLER config option has been set in the kernel.
+ *
+ * If the caller_id is found in the kmsg buffer then return the id and id type
+ * to the caller in dmesg caller_id. Returns string pointer to next value.
+ *
+ */
+static const char *parse_callerid(const char *p_str, const char *end,
+				  struct dmesg_record *p_drec)
+{
+	const char *p_after;
+	const char *p_next;
+	size_t cid_size;
+	char *p_scn;
+	char *p_cid;
+
+	/* Check for PRINTK_CALLER prefix, must be before msg text */
+	p_cid = strstr(p_str, DMESG_CALLER_PREFIX);
+	p_scn = strchr(p_str, ';');
+	if (p_cid != NULL && p_drec != NULL && p_scn != NULL && p_cid < p_scn) {
+		p_next = p_cid + DMESG_CALLER_PREFIXSZ;
+		p_after = skip_item(p_next, end, ",;");
+		cid_size = p_after - p_next;
+		if (cid_size < sizeof(p_drec->caller_id))
+			xstrncpy(p_drec->caller_id, p_next, cid_size);
+		else
+			return p_str;
+		return p_after;
+	}
+	return p_str;
+}
+
 /*
  * Parses one record from syslog(2) buffer
  */
@@ -795,8 +881,22 @@ static int get_next_syslog_record(struct dmesg_control *ctl,
 				begin++;
 		}
 
-		rec->mesg = begin;
-		rec->mesg_size = end - begin;
+		if (*begin == '[' && (*(begin + 1) == ' ' ||
+			(*(begin + 1) == 'T' || *(begin + 1) == 'C'))) {
+			const char *start = begin + 1;
+			size_t id_size;
+
+			start = start + strspn(start, " ");
+			begin = skip_item(begin, end, "]");
+			id_size = begin - start;
+			if (id_size < sizeof(rec->caller_id))
+				xstrncpy(rec->caller_id, start, id_size);
+			rec->mesg = begin + 1;
+			rec->mesg_size = end - begin - 1;
+		} else {
+			rec->mesg = begin;
+			rec->mesg_size = end - begin;
+		}
 
 		/* Don't count \n from the last message to the message size */
 		if (*end != '\n' && *(end - 1) == '\n')
@@ -1101,6 +1201,19 @@ full_output:
 			color_disable();
 	}
 
+	if (*rec->caller_id) {
+		if (ctl->json) {
+			ul_jsonwrt_value_s(&ctl->jfmt, "caller", rec->caller_id);
+		} else {
+			char cidbuf[PID_CHARS_MAX+3] = {'\0'};
+
+			sprintf(cidbuf, "[%*s] ",
+				(char)ctl->caller_id_size, rec->caller_id);
+			ctl->indent += strnlen(cidbuf, sizeof(cidbuf));
+			fputs(cidbuf, stdout);
+		}
+	}
+
 	/*
 	 * A kernel message may contain several lines of output, separated
 	 * by '\n'.  If the timestamp and decode outputs are forced then each
@@ -1284,7 +1397,10 @@ static int parse_kmsg_record(struct dmesg_control *ctl,
 		goto mesg;
 
 	/* D) optional fields (ignore) */
-	p = skip_item(p, end, ";");
+	p = skip_item(p, end, ",;");
+
+	/* Include optional PRINTK_CALLER field if it is present */
+	p = parse_callerid(p, end, rec);
 
 mesg:
 	/* E) message text */
@@ -1336,6 +1452,9 @@ static int process_kmsg(struct dmesg_control *ctl)
 	if (ctl->method != DMESG_METHOD_KMSG || ctl->kmsg < 0)
 		return -1;
 
+	/* Determine number of PID characters for caller_id spacing */
+	ctl->caller_id_size = max_threads_id_size();
+
 	/*
 	 * The very first read() call is done in kmsg_init() where we test
 	 * /dev/kmsg usability. The return code from the initial read() is
@@ -1446,6 +1565,7 @@ int main(int argc, char *argv[])
 		.kmsg = -1,
 		.time_fmt = DMESG_TIMEFTM_TIME,
 		.indent = 0,
+		.caller_id_size = 0,
 	};
 	int colormode = UL_COLORMODE_UNDEF;
 	enum {
@@ -1538,10 +1658,12 @@ int main(int argc, char *argv[])
 		case 'F':
 			ctl.filename = optarg;
 			ctl.method = DMESG_METHOD_MMAP;
+			ctl.caller_id_size = SYSLOG_DEFAULT_CALLER_ID_CHARS;
 			break;
 		case 'K':
 			ctl.filename = optarg;
 			ctl.method = DMESG_METHOD_KMSG;
+			ctl.caller_id_size = max_threads_id_size();
 			break;
 		case 'f':
 			ctl.fltr_fac = 1;
diff --git a/tests/expected/dmesg/cid-json b/tests/expected/dmesg/cid-json
new file mode 100644
index 000000000..8a4d0e23d
--- /dev/null
+++ b/tests/expected/dmesg/cid-json
@@ -0,0 +1,535 @@
+{
+   "dmesg": [
+      {
+         "pri": 0,
+         "time":     0.000000,
+         "caller": "T0",
+         "msg": "example[0]"
+      },{
+         "pri": 1,
+         "time":     1.000000,
+         "caller": "T1",
+         "msg": "example[1]"
+      },{
+         "pri": 2,
+         "time":     8.000000,
+         "caller": "T2",
+         "msg": "example[2]"
+      },{
+         "pri": 3,
+         "time":    27.000000,
+         "caller": "T3",
+         "msg": "example[3]"
+      },{
+         "pri": 4,
+         "time":    64.000000,
+         "caller": "T4",
+         "msg": "example[4]"
+      },{
+         "pri": 5,
+         "time":   125.000000,
+         "caller": "T5",
+         "msg": "example[5]"
+      },{
+         "pri": 6,
+         "time":   216.000000,
+         "caller": "T6",
+         "msg": "example[6]"
+      },{
+         "pri": 7,
+         "time":   343.000000,
+         "caller": "T7",
+         "msg": "example[7]"
+      },{
+         "pri": 8,
+         "time":   512.000000,
+         "caller": "T8",
+         "msg": "example[8]"
+      },{
+         "pri": 9,
+         "time":   729.000000,
+         "caller": "T9",
+         "msg": "example[9]"
+      },{
+         "pri": 10,
+         "time":  1000.000000,
+         "caller": "T10",
+         "msg": "example[10]"
+      },{
+         "pri": 11,
+         "time":  1331.000000,
+         "caller": "T11",
+         "msg": "example[11]"
+      },{
+         "pri": 12,
+         "time":  1728.000000,
+         "caller": "T12",
+         "msg": "example[12]"
+      },{
+         "pri": 13,
+         "time":  2197.000000,
+         "caller": "T13",
+         "msg": "example[13]"
+      },{
+         "pri": 14,
+         "time":  2744.000000,
+         "caller": "T14",
+         "msg": "example[14]"
+      },{
+         "pri": 15,
+         "time":  3375.000000,
+         "caller": "T15",
+         "msg": "example[15]"
+      },{
+         "pri": 16,
+         "time":  4096.000000,
+         "caller": "T16",
+         "msg": "example[16]"
+      },{
+         "pri": 17,
+         "time":  4913.000000,
+         "caller": "T17",
+         "msg": "example[17]"
+      },{
+         "pri": 18,
+         "time":  5832.000000,
+         "caller": "T18",
+         "msg": "example[18]"
+      },{
+         "pri": 19,
+         "time":  6859.000000,
+         "caller": "T19",
+         "msg": "example[19]"
+      },{
+         "pri": 20,
+         "time":  8000.000000,
+         "caller": "T20",
+         "msg": "example[20]"
+      },{
+         "pri": 21,
+         "time":  9261.000000,
+         "caller": "T21",
+         "msg": "example[21]"
+      },{
+         "pri": 22,
+         "time": 10648.000000,
+         "caller": "T22",
+         "msg": "example[22]"
+      },{
+         "pri": 23,
+         "time": 12167.000000,
+         "caller": "T23",
+         "msg": "example[23]"
+      },{
+         "pri": 24,
+         "time": 13824.000000,
+         "caller": "T24",
+         "msg": "example[24]"
+      },{
+         "pri": 25,
+         "time": 15625.000000,
+         "caller": "T25",
+         "msg": "example[25]"
+      },{
+         "pri": 26,
+         "time": 17576.000000,
+         "caller": "T26",
+         "msg": "example[26]"
+      },{
+         "pri": 27,
+         "time": 19683.000000,
+         "caller": "T27",
+         "msg": "example[27]"
+      },{
+         "pri": 28,
+         "time": 21952.000000,
+         "caller": "T28",
+         "msg": "example[28]"
+      },{
+         "pri": 29,
+         "time": 24389.000000,
+         "caller": "T29",
+         "msg": "example[29]"
+      },{
+         "pri": 30,
+         "time": 27000.000000,
+         "caller": "T10",
+         "msg": "example[30]"
+      },{
+         "pri": 31,
+         "time": 29791.000000,
+         "caller": "T31",
+         "msg": "example[31]"
+      },{
+         "pri": 32,
+         "time": 32768.000000,
+         "caller": "T32",
+         "msg": "example[32]"
+      },{
+         "pri": 33,
+         "time": 35937.000000,
+         "caller": "T33",
+         "msg": "example[33]"
+      },{
+         "pri": 34,
+         "time": 39304.000000,
+         "caller": "T34",
+         "msg": "example[34]"
+      },{
+         "pri": 35,
+         "time": 42875.000000,
+         "caller": "T35",
+         "msg": "example[35]"
+      },{
+         "pri": 36,
+         "time": 46656.000000,
+         "caller": "T36",
+         "msg": "example[36]"
+      },{
+         "pri": 37,
+         "time": 50653.000000,
+         "caller": "T37",
+         "msg": "example[37]"
+      },{
+         "pri": 38,
+         "time": 54872.000000,
+         "caller": "T38",
+         "msg": "example[38]"
+      },{
+         "pri": 39,
+         "time": 59319.000000,
+         "caller": "T39",
+         "msg": "example[39]"
+      },{
+         "pri": 40,
+         "time": 64000.000000,
+         "caller": "T40",
+         "msg": "example[40]"
+      },{
+         "pri": 41,
+         "time": 68921.000000,
+         "caller": "T41",
+         "msg": "example[41]"
+      },{
+         "pri": 42,
+         "time": 74088.000000,
+         "caller": "T42",
+         "msg": "example[42]"
+      },{
+         "pri": 43,
+         "time": 79507.000000,
+         "caller": "T43",
+         "msg": "example[43]"
+      },{
+         "pri": 44,
+         "time": 85184.000000,
+         "caller": "T44",
+         "msg": "example[44]"
+      },{
+         "pri": 45,
+         "time": 91125.000000,
+         "caller": "T45",
+         "msg": "example[45]"
+      },{
+         "pri": 46,
+         "time": 97336.000000,
+         "caller": "T46",
+         "msg": "example[46]"
+      },{
+         "pri": 47,
+         "time": 103823.000000,
+         "caller": "T47",
+         "msg": "example[47]"
+      },{
+         "pri": 48,
+         "time": 110592.000000,
+         "caller": "T48",
+         "msg": "example[48]"
+      },{
+         "pri": 49,
+         "time": 117649.000000,
+         "caller": "T49",
+         "msg": "example[49]"
+      },{
+         "pri": 50,
+         "time": 125000.000000,
+         "caller": "T50",
+         "msg": "example[50]"
+      },{
+         "pri": 51,
+         "time": 132651.000000,
+         "caller": "T51",
+         "msg": "example[51]"
+      },{
+         "pri": 52,
+         "time": 140608.000000,
+         "caller": "T52",
+         "msg": "example[52]"
+      },{
+         "pri": 53,
+         "time": 148877.000000,
+         "caller": "T53",
+         "msg": "example[53]"
+      },{
+         "pri": 54,
+         "time": 157464.000000,
+         "caller": "T54",
+         "msg": "example[54]"
+      },{
+         "pri": 55,
+         "time": 166375.000000,
+         "caller": "T55",
+         "msg": "example[55]"
+      },{
+         "pri": 56,
+         "time": 175616.000000,
+         "caller": "T56",
+         "msg": "example[56]"
+      },{
+         "pri": 57,
+         "time": 185193.000000,
+         "caller": "T57",
+         "msg": "example[57]"
+      },{
+         "pri": 58,
+         "time": 195112.000000,
+         "caller": "T58",
+         "msg": "example[58]"
+      },{
+         "pri": 59,
+         "time": 205379.000000,
+         "caller": "T59",
+         "msg": "example[59]"
+      },{
+         "pri": 60,
+         "time": 216000.000000,
+         "caller": "T60",
+         "msg": "example[60]"
+      },{
+         "pri": 61,
+         "time": 226981.000000,
+         "caller": "T61",
+         "msg": "example[61]"
+      },{
+         "pri": 62,
+         "time": 238328.000000,
+         "caller": "T62",
+         "msg": "example[62]"
+      },{
+         "pri": 63,
+         "time": 250047.000000,
+         "caller": "T63",
+         "msg": "example[63]"
+      },{
+         "pri": 64,
+         "time": 262144.000000,
+         "caller": "T64",
+         "msg": "example[64]"
+      },{
+         "pri": 65,
+         "time": 274625.000000,
+         "caller": "T65",
+         "msg": "example[65]"
+      },{
+         "pri": 66,
+         "time": 287496.000000,
+         "caller": "T66",
+         "msg": "example[66]"
+      },{
+         "pri": 67,
+         "time": 300763.000000,
+         "caller": "T67",
+         "msg": "example[67]"
+      },{
+         "pri": 68,
+         "time": 314432.000000,
+         "caller": "T68",
+         "msg": "example[68]"
+      },{
+         "pri": 69,
+         "time": 328509.000000,
+         "caller": "T69",
+         "msg": "example[69]"
+      },{
+         "pri": 70,
+         "time": 343000.000000,
+         "caller": "T70",
+         "msg": "example[70]"
+      },{
+         "pri": 71,
+         "time": 357911.000000,
+         "caller": "T71",
+         "msg": "example[71]"
+      },{
+         "pri": 72,
+         "time": 373248.000000,
+         "caller": "T72",
+         "msg": "example[72]"
+      },{
+         "pri": 73,
+         "time": 389017.000000,
+         "caller": "T73",
+         "msg": "example[73]"
+      },{
+         "pri": 74,
+         "time": 405224.000000,
+         "caller": "T74",
+         "msg": "example[74]"
+      },{
+         "pri": 75,
+         "time": 421875.000000,
+         "caller": "T75",
+         "msg": "example[75]"
+      },{
+         "pri": 76,
+         "time": 438976.000000,
+         "caller": "T76",
+         "msg": "example[76]"
+      },{
+         "pri": 77,
+         "time": 456533.000000,
+         "caller": "T77",
+         "msg": "example[77]"
+      },{
+         "pri": 78,
+         "time": 474552.000000,
+         "caller": "T78",
+         "msg": "example[78]"
+      },{
+         "pri": 79,
+         "time": 493039.000000,
+         "caller": "T79",
+         "msg": "example[79]"
+      },{
+         "pri": 80,
+         "time": 512000.000000,
+         "caller": "T80",
+         "msg": "example[80]"
+      },{
+         "pri": 81,
+         "time": 531441.000000,
+         "caller": "T81",
+         "msg": "example[81]"
+      },{
+         "pri": 82,
+         "time": 551368.000000,
+         "caller": "T82",
+         "msg": "example[82]"
+      },{
+         "pri": 83,
+         "time": 571787.000000,
+         "caller": "T83",
+         "msg": "example[83]"
+      },{
+         "pri": 84,
+         "time": 592704.000000,
+         "caller": "T84",
+         "msg": "example[84]"
+      },{
+         "pri": 85,
+         "time": 614125.000000,
+         "caller": "T85",
+         "msg": "example[85]"
+      },{
+         "pri": 86,
+         "time": 636056.000000,
+         "caller": "T86",
+         "msg": "example[86]"
+      },{
+         "pri": 87,
+         "time": 658503.000000,
+         "caller": "T87",
+         "msg": "example[87]"
+      },{
+         "pri": 88,
+         "time": 681472.000000,
+         "caller": "T88",
+         "msg": "example[88]"
+      },{
+         "pri": 89,
+         "time": 704969.000000,
+         "caller": "T89",
+         "msg": "example[89]"
+      },{
+         "pri": 90,
+         "time": 729000.000000,
+         "caller": "T90",
+         "msg": "example[90]"
+      },{
+         "pri": 91,
+         "time": 753571.000000,
+         "caller": "T91",
+         "msg": "example[91]"
+      },{
+         "pri": 92,
+         "time": 778688.000000,
+         "caller": "T92",
+         "msg": "example[92]"
+      },{
+         "pri": 93,
+         "time": 804357.000000,
+         "caller": "T93",
+         "msg": "example[93]"
+      },{
+         "pri": 94,
+         "time": 830584.000000,
+         "caller": "T94",
+         "msg": "example[94]"
+      },{
+         "pri": 95,
+         "time": 857375.000000,
+         "caller": "T95",
+         "msg": "example[95]"
+      },{
+         "pri": 96,
+         "time": 884736.000000,
+         "caller": "T96",
+         "msg": "example[96]"
+      },{
+         "pri": 97,
+         "time": 912673.000000,
+         "caller": "T97",
+         "msg": "example[97]"
+      },{
+         "pri": 98,
+         "time": 941192.000000,
+         "caller": "T98",
+         "msg": "example[98]"
+      },{
+         "pri": 99,
+         "time": 970299.000000,
+         "caller": "T99",
+         "msg": "example[99]"
+      },{
+         "pri": 100,
+         "time": 1000000.000000,
+         "caller": "T100",
+         "msg": "example[100]"
+      },{
+         "pri": 101,
+         "time": 1030301.000000,
+         "caller": "T101",
+         "msg": "example[101]"
+      },{
+         "pri": 102,
+         "time": 1061208.000000,
+         "caller": "T102",
+         "msg": "example[102]"
+      },{
+         "pri": 103,
+         "time": 1092727.000000,
+         "caller": "T103",
+         "msg": "example[103]"
+      },{
+         "pri": 104,
+         "time": 1124864.000000,
+         "caller": "T104",
+         "msg": "example[104]"
+      },{
+         "pri": 150,
+         "time": 4557523.000000,
+         "caller": "T105",
+         "msg": "example[105]"
+      }
+   ]
+}
diff --git a/tests/expected/dmesg/cid-kmsg-colors b/tests/expected/dmesg/cid-kmsg-colors
new file mode 100644
index 000000000..7d11dae33
--- /dev/null
+++ b/tests/expected/dmesg/cid-kmsg-colors
@@ -0,0 +1,45 @@
+kern  :emerg : ^[[32m[    0.000000] ^[[0m[      T1] Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000
+kern  :alert : ^[[32m[    0.000001] ^[[0m[      T2] ^[[33mCommand line: ^[[0m^[[7m^[[31minitrd=\ucode.img initrd=\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system^[[0m
+kern  :crit  : ^[[32m[    0.000002] ^[[0m[      T3] ^[[1m^[[31mBIOS-provided physical RAM map:^[[0m
+kern  :err   : ^[[32m[    0.000003] ^[[0m[      T4] ^[[33mBIOS-e820: ^[[0m^[[31m[mem 0x0000000000000000-0x000000000009efff] usable^[[0m
+kern  :warn  : ^[[32m[    0.000004] ^[[0m[      T5] ^[[33mBIOS-e820: ^[[0m^[[1m[mem 0x000000000009f000-0x00000000000bffff] reserved^[[0m
+kern  :notice: ^[[32m[    0.000005] ^[[0m[      T6] ^[[33mBIOS-e820: ^[[0m[mem 0x0000000000100000-0x0000000009afffff] usable
+kern  :info  : ^[[32m[    0.000006] ^[[0m[      T7] ^[[33mBIOS-e820: ^[[0m[mem 0x0000000009b00000-0x0000000009dfffff] reserved
+kern  :debug : ^[[32m[    0.000007] ^[[0m[      T8] ^[[33mBIOS-e820: ^[[0m[mem 0x0000000009e00000-0x0000000009efffff] usable
+kern  :info  : ^[[32m[    0.000008] ^[[0m[      T9] ^[[33mBIOS-e820: ^[[0m[mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS
+kern  :info  : ^[[32m[    0.000009] ^[[0m[     T10] ^[[33mBIOS-e820: ^[[0m[mem 0x0000000009f3c000-0x000000004235ffff] usable
+kern  :info  : ^[[32m[    0.000010] ^[[0m[     T11] ^[[33mBIOS-e820: ^[[0m[mem 0x0000000042360000-0x000000004455ffff] reserved
+kern  :info  : ^[[32m[    0.201607] ^[[0m[     T12] ^[[33msmp: ^[[0mBringing up secondary CPUs ...
+kern  :info  : ^[[32m[    0.201607] ^[[0m[     T13] ^[[33msmpboot: ^[[0mx86: Booting SMP configuration:
+kern  :warn  : ^[[32m[    0.209670] ^[[0m[     T14] ^[[1m  #1  #3  #5  #7^[[0m
+kern  :info  : ^[[32m[    0.212630] ^[[0m[     T15] ^[[33msmp: ^[[0mBrought up 1 node, 16 CPUs
+kern  :notice: ^[[32m[    0.215936] ^[[0m[     T16] ^[[33maudit: ^[[0mtype=2000 audit(1702926179.015:1): state=initialized audit_enabled=0 res=1
+kern  :info  : ^[[32m[    0.215937] ^[[0m[     T17] ^[[33mthermal_sys: ^[[0mRegistered thermal governor 'fair_share'
+kern  :warn  : ^[[32m[    0.215966] ^[[0m[     T18] ^[[33mENERGY_PERF_BIAS: ^[[0m^[[1mSet to 'normal', was 'performance'^[[0m
+kern  :info  : ^[[32m[    0.367657] ^[[0m[     T19] ^[[33mACPI: ^[[0m\_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+kern  :info  : ^[[32m[    0.368615] ^[[0m[     T20] ^[[33mACPI: ^[[0m\_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+kern  :info  : ^[[32m[    0.376316] ^[[0m[     T21] ^[[33mACPI: ^[[0m\_SB_.PRWL: New power resource
+kern  :info  : ^[[32m[    0.376343] ^[[0m[     T22] ^[[33mACPI: ^[[0m\_SB_.PRWB: New power resource
+kern  :info  : ^[[32m[    0.377373] ^[[0m[     T23] ^[[33mACPI: ^[[0mPCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+kern  :info  : ^[[32m[    0.377378] ^[[0m[     T24] ^[[33macpi PNP0A08:00: ^[[0m_OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+kern  :info  : ^[[32m[    0.377569] ^[[0m[     T25] ^[[33macpi PNP0A08:00: ^[[0m_OSC: platform does not support [SHPCHotplug AER]
+kern  :info  : ^[[32m[    0.377933] ^[[0m[     T26] ^[[33macpi PNP0A08:00: ^[[0m_OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+kern  :info  : ^[[32m[    0.378458] ^[[0m[     T27] PCI host bridge to bus 0000:00
+kern  :info  : ^[[32m[    0.378459] ^[[0m[     T28] ^[[33mpci_bus 0000:00: ^[[0mroot bus resource [io  0x0000-0x0cf7 window]
+kern  :info  : ^[[32m[    0.378461] ^[[0m[     T29] ^[[33mpci_bus 0000:00: ^[[0mroot bus resource [io  0x0d00-0xffff window]
+user  :notice: ^[[32m[    9.398562] ^[[0m[     T30] user network daemon initialization complete
+daemon:info  : ^[[32m[   10.441520] ^[[0m[     T31] ^[[33msystemd[1]: ^[[0msystemd 254.7-1.fc39 running in system mode
+daemon:info  : ^[[32m[   11.441524] ^[[0m[     T32] ^[[33msystemd[1]: ^[[0mDetected architecture x86-64.
+daemon:info  : ^[[32m[   12.441525] ^[[0m[     T33] ^[[33msystemd[1]: ^[[0mRunning in initrd.
+daemon:info  : ^[[32m[   13.541598] ^[[0m[     T34] ^[[33msystemd[1]: ^[[0mHostname set to <catalina>.
+kern  :info  : ^[[32m[   15.641860] ^[[0m[     T35] ^[[33musb 3-3: ^[[0mNew USB device found, idVendor=1a40, idProduct=0101, bcdDevice= 1.11
+kern  :err   : ^[[32m[   16.690000] ^[[0m[     T36] ^[[33mSerial bus multi instantiate pseudo device driver INT3515:00: ^[[0m^[[31merror -ENXIO: IRQ index 1 not found.^[[0m
+kern  :err   : ^[[32m[   17.710000] ^[[0m[     T37] ^[[33msnd_hda_intel 0000:00:1f.3: ^[[0m^[[31mCORB reset timeout#2, CORBRP = 65535^[[0m
+syslog:info  : ^[[32m[   18.820000] ^[[0m[     T38] ^[[33msystemd-journald[723]: ^[[0mReceived client request to flush runtime journal.
+syslog:warn  : ^[[32m[   20.840000] ^[[0m[     T39] ^[[33msystemd-journald[723]: ^[[0m^[[1mFile /var/log/journal/a124ea923b144109a12d557d5ac53179/system.journal corrupted or uncleanly shut down, renaming and replacing.^[[0m
+syslog:info  : ^[[32m[   21.852348] ^[[0m[     T40] ^[[33msystemd-journald[723]: ^[[0m/var/log/journal/ad7a2547ac0e4342a342e62a34a3eae4/user-1000.journal: Journal file uses a different sequence number ID, rotating.
+kern  :warn  : ^[[32m[   24.871100] ^[[0m[      41] ^[[33mPEFILE: ^[[0m^[[1mUnsigned PE binary^[[0m
+kern  :err   : ^[[32m[   33.918091] ^[[0m[      42] ^[[33msnd_hda_intel 0000:00:1f.3: ^[[0m^[[31mCORB reset timeout#2, CORBRP = 65535^[[0m
+kern  :info  : ^[[32m[  144.931785] ^[[0m[      C1] ^[[33musb 3-3.1: ^[[0mdevice firmware changed
+kern  :info  : ^[[32m[  145.953248] ^[[0m[      C2] ^[[33musb 3-3.1: ^[[0mUSB disconnect, device number 44
+kern  :info  : ^[[32m[  147.981859] ^[[0m[      C3] ^[[33musb 3-3.1: ^[[0mNew USB device found, idVendor=17ef, idProduct=6047, bcdDevice= 3.30
diff --git a/tests/expected/dmesg/cid-kmsg-console-levels b/tests/expected/dmesg/cid-kmsg-console-levels
new file mode 100644
index 000000000..59c343108
--- /dev/null
+++ b/tests/expected/dmesg/cid-kmsg-console-levels
@@ -0,0 +1,97 @@
+[    0.000000] [      T1] Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000
+[    0.000001] [      T2] Command line: initrd=\ucode.img initrd=\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system
+[    0.000002] [      T3] BIOS-provided physical RAM map:
+[    0.000003] [      T4] BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable
+[   16.690000] [     T36] Serial bus multi instantiate pseudo device driver INT3515:00: error -ENXIO: IRQ index 1 not found.
+[   17.710000] [     T37] snd_hda_intel 0000:00:1f.3: CORB reset timeout#2, CORBRP = 65535
+[   33.918091] [      42] snd_hda_intel 0000:00:1f.3: CORB reset timeout#2, CORBRP = 65535
+[    0.000004] [      T5] BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved
+[    0.209670] [     T14]   #1  #3  #5  #7
+[    0.215966] [     T18] ENERGY_PERF_BIAS: Set to 'normal', was 'performance'
+[   20.840000] [     T39] systemd-journald[723]: File /var/log/journal/a124ea923b144109a12d557d5ac53179/system.journal corrupted or uncleanly shut down, renaming and replacing.
+[   24.871100] [      41] PEFILE: Unsigned PE binary
+[    0.000005] [      T6] BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable
+[    0.215936] [     T16] audit: type=2000 audit(1702926179.015:1): state=initialized audit_enabled=0 res=1
+[    9.398562] [     T30] user network daemon initialization complete
+[    0.000006] [      T7] BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved
+[    0.000008] [      T9] BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS
+[    0.000009] [     T10] BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable
+[    0.000010] [     T11] BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved
+[    0.201607] [     T12] smp: Bringing up secondary CPUs ...
+[    0.201607] [     T13] smpboot: x86: Booting SMP configuration:
+[    0.212630] [     T15] smp: Brought up 1 node, 16 CPUs
+[    0.215937] [     T17] thermal_sys: Registered thermal governor 'fair_share'
+[    0.367657] [     T19] ACPI: \_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+[    0.368615] [     T20] ACPI: \_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+[    0.376316] [     T21] ACPI: \_SB_.PRWL: New power resource
+[    0.376343] [     T22] ACPI: \_SB_.PRWB: New power resource
+[    0.377373] [     T23] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+[    0.377378] [     T24] acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+[    0.377569] [     T25] acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]
+[    0.377933] [     T26] acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+[    0.378458] [     T27] PCI host bridge to bus 0000:00
+[    0.378459] [     T28] pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]
+[    0.378461] [     T29] pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]
+[   10.441520] [     T31] systemd[1]: systemd 254.7-1.fc39 running in system mode
+[   11.441524] [     T32] systemd[1]: Detected architecture x86-64.
+[   12.441525] [     T33] systemd[1]: Running in initrd.
+[   13.541598] [     T34] systemd[1]: Hostname set to <catalina>.
+[   15.641860] [     T35] usb 3-3: New USB device found, idVendor=1a40, idProduct=0101, bcdDevice= 1.11
+[   18.820000] [     T38] systemd-journald[723]: Received client request to flush runtime journal.
+[   21.852348] [     T40] systemd-journald[723]: /var/log/journal/ad7a2547ac0e4342a342e62a34a3eae4/user-1000.journal: Journal file uses a different sequence number ID, rotating.
+[  144.931785] [      C1] usb 3-3.1: device firmware changed
+[  145.953248] [      C2] usb 3-3.1: USB disconnect, device number 44
+[  147.981859] [      C3] usb 3-3.1: New USB device found, idVendor=17ef, idProduct=6047, bcdDevice= 3.30
+[    0.000007] [      T8] BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable
+[    0.000000] [      T1] Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000
+[    0.000001] [      T2] Command line: initrd=\ucode.img initrd=\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system
+[    0.000002] [      T3] BIOS-provided physical RAM map:
+[    0.000003] [      T4] BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable
+[   16.690000] [     T36] Serial bus multi instantiate pseudo device driver INT3515:00: error -ENXIO: IRQ index 1 not found.
+[   17.710000] [     T37] snd_hda_intel 0000:00:1f.3: CORB reset timeout#2, CORBRP = 65535
+[   33.918091] [      42] snd_hda_intel 0000:00:1f.3: CORB reset timeout#2, CORBRP = 65535
+[    0.000000] [      T1] Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000
+[    0.000003] [      T4] BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable
+[    0.000004] [      T5] BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved
+[    0.000005] [      T6] BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable
+[    0.000006] [      T7] BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved
+[    0.000007] [      T8] BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable
+[    0.000008] [      T9] BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS
+[    0.000009] [     T10] BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable
+[    0.000010] [     T11] BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved
+[    0.201607] [     T12] smp: Bringing up secondary CPUs ...
+[    0.201607] [     T13] smpboot: x86: Booting SMP configuration:
+[    0.209670] [     T14]   #1  #3  #5  #7
+[    0.212630] [     T15] smp: Brought up 1 node, 16 CPUs
+[    0.215936] [     T16] audit: type=2000 audit(1702926179.015:1): state=initialized audit_enabled=0 res=1
+[    0.215937] [     T17] thermal_sys: Registered thermal governor 'fair_share'
+[    0.215966] [     T18] ENERGY_PERF_BIAS: Set to 'normal', was 'performance'
+[    0.367657] [     T19] ACPI: \_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+[    0.368615] [     T20] ACPI: \_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+[    0.376316] [     T21] ACPI: \_SB_.PRWL: New power resource
+[    0.376343] [     T22] ACPI: \_SB_.PRWB: New power resource
+[    0.377373] [     T23] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+[    0.377378] [     T24] acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+[    0.377569] [     T25] acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]
+[    0.377933] [     T26] acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+[    0.378458] [     T27] PCI host bridge to bus 0000:00
+[    0.378459] [     T28] pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]
+[    0.378461] [     T29] pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]
+[    9.398562] [     T30] user network daemon initialization complete
+[   10.441520] [     T31] systemd[1]: systemd 254.7-1.fc39 running in system mode
+[   11.441524] [     T32] systemd[1]: Detected architecture x86-64.
+[   12.441525] [     T33] systemd[1]: Running in initrd.
+[   13.541598] [     T34] systemd[1]: Hostname set to <catalina>.
+[   15.641860] [     T35] usb 3-3: New USB device found, idVendor=1a40, idProduct=0101, bcdDevice= 1.11
+[   16.690000] [     T36] Serial bus multi instantiate pseudo device driver INT3515:00: error -ENXIO: IRQ index 1 not found.
+[   17.710000] [     T37] snd_hda_intel 0000:00:1f.3: CORB reset timeout#2, CORBRP = 65535
+[   18.820000] [     T38] systemd-journald[723]: Received client request to flush runtime journal.
+[   20.840000] [     T39] systemd-journald[723]: File /var/log/journal/a124ea923b144109a12d557d5ac53179/system.journal corrupted or uncleanly shut down, renaming and replacing.
+[   21.852348] [     T40] systemd-journald[723]: /var/log/journal/ad7a2547ac0e4342a342e62a34a3eae4/user-1000.journal: Journal file uses a different sequence number ID, rotating.
+[   24.871100] [      41] PEFILE: Unsigned PE binary
+[   33.918091] [      42] snd_hda_intel 0000:00:1f.3: CORB reset timeout#2, CORBRP = 65535
+[  144.931785] [      C1] usb 3-3.1: device firmware changed
+[  145.953248] [      C2] usb 3-3.1: USB disconnect, device number 44
+[  147.981859] [      C3] usb 3-3.1: New USB device found, idVendor=17ef, idProduct=6047, bcdDevice= 3.30
+[    0.000007] [      T8] BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable
+test_dmesg: unknown level '+'
diff --git a/tests/expected/dmesg/cid-kmsg-decode b/tests/expected/dmesg/cid-kmsg-decode
new file mode 100644
index 000000000..f9cdab620
--- /dev/null
+++ b/tests/expected/dmesg/cid-kmsg-decode
@@ -0,0 +1,45 @@
+kern  :emerg : [    0.000000] [      T1] Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000
+kern  :alert : [    0.000001] [      T2] Command line: initrd=\ucode.img initrd=\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system
+kern  :crit  : [    0.000002] [      T3] BIOS-provided physical RAM map:
+kern  :err   : [    0.000003] [      T4] BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable
+kern  :warn  : [    0.000004] [      T5] BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved
+kern  :notice: [    0.000005] [      T6] BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable
+kern  :info  : [    0.000006] [      T7] BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved
+kern  :debug : [    0.000007] [      T8] BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable
+kern  :info  : [    0.000008] [      T9] BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS
+kern  :info  : [    0.000009] [     T10] BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable
+kern  :info  : [    0.000010] [     T11] BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved
+kern  :info  : [    0.201607] [     T12] smp: Bringing up secondary CPUs ...
+kern  :info  : [    0.201607] [     T13] smpboot: x86: Booting SMP configuration:
+kern  :warn  : [    0.209670] [     T14]   #1  #3  #5  #7
+kern  :info  : [    0.212630] [     T15] smp: Brought up 1 node, 16 CPUs
+kern  :notice: [    0.215936] [     T16] audit: type=2000 audit(1702926179.015:1): state=initialized audit_enabled=0 res=1
+kern  :info  : [    0.215937] [     T17] thermal_sys: Registered thermal governor 'fair_share'
+kern  :warn  : [    0.215966] [     T18] ENERGY_PERF_BIAS: Set to 'normal', was 'performance'
+kern  :info  : [    0.367657] [     T19] ACPI: \_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+kern  :info  : [    0.368615] [     T20] ACPI: \_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+kern  :info  : [    0.376316] [     T21] ACPI: \_SB_.PRWL: New power resource
+kern  :info  : [    0.376343] [     T22] ACPI: \_SB_.PRWB: New power resource
+kern  :info  : [    0.377373] [     T23] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+kern  :info  : [    0.377378] [     T24] acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+kern  :info  : [    0.377569] [     T25] acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]
+kern  :info  : [    0.377933] [     T26] acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+kern  :info  : [    0.378458] [     T27] PCI host bridge to bus 0000:00
+kern  :info  : [    0.378459] [     T28] pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]
+kern  :info  : [    0.378461] [     T29] pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]
+user  :notice: [    9.398562] [     T30] user network daemon initialization complete
+daemon:info  : [   10.441520] [     T31] systemd[1]: systemd 254.7-1.fc39 running in system mode
+daemon:info  : [   11.441524] [     T32] systemd[1]: Detected architecture x86-64.
+daemon:info  : [   12.441525] [     T33] systemd[1]: Running in initrd.
+daemon:info  : [   13.541598] [     T34] systemd[1]: Hostname set to <catalina>.
+kern  :info  : [   15.641860] [     T35] usb 3-3: New USB device found, idVendor=1a40, idProduct=0101, bcdDevice= 1.11
+kern  :err   : [   16.690000] [     T36] Serial bus multi instantiate pseudo device driver INT3515:00: error -ENXIO: IRQ index 1 not found.
+kern  :err   : [   17.710000] [     T37] snd_hda_intel 0000:00:1f.3: CORB reset timeout#2, CORBRP = 65535
+syslog:info  : [   18.820000] [     T38] systemd-journald[723]: Received client request to flush runtime journal.
+syslog:warn  : [   20.840000] [     T39] systemd-journald[723]: File /var/log/journal/a124ea923b144109a12d557d5ac53179/system.journal corrupted or uncleanly shut down, renaming and replacing.
+syslog:info  : [   21.852348] [     T40] systemd-journald[723]: /var/log/journal/ad7a2547ac0e4342a342e62a34a3eae4/user-1000.journal: Journal file uses a different sequence number ID, rotating.
+kern  :warn  : [   24.871100] [      41] PEFILE: Unsigned PE binary
+kern  :err   : [   33.918091] [      42] snd_hda_intel 0000:00:1f.3: CORB reset timeout#2, CORBRP = 65535
+kern  :info  : [  144.931785] [      C1] usb 3-3.1: device firmware changed
+kern  :info  : [  145.953248] [      C2] usb 3-3.1: USB disconnect, device number 44
+kern  :info  : [  147.981859] [      C3] usb 3-3.1: New USB device found, idVendor=17ef, idProduct=6047, bcdDevice= 3.30
diff --git a/tests/expected/dmesg/cid-kmsg-delta b/tests/expected/dmesg/cid-kmsg-delta
new file mode 100644
index 000000000..25f6fb5e2
--- /dev/null
+++ b/tests/expected/dmesg/cid-kmsg-delta
@@ -0,0 +1,45 @@
+[    0.000000 <    0.000000>] [      T1] Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000
+[    0.000001 <    0.000000>] [      T2] Command line: initrd=\ucode.img initrd=\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system
+[    0.000002 <    0.000000>] [      T3] BIOS-provided physical RAM map:
+[    0.000003 <    0.000000>] [      T4] BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable
+[    0.000004 <    0.000000>] [      T5] BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved
+[    0.000005 <    0.000000>] [      T6] BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable
+[    0.000006 <    0.000000>] [      T7] BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved
+[    0.000007 <    0.000000>] [      T8] BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable
+[    0.000008 <    0.000000>] [      T9] BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS
+[    0.000009 <    0.000000>] [     T10] BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable
+[    0.000010 <    0.000000>] [     T11] BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved
+[    0.201607 <    0.000000>] [     T12] smp: Bringing up secondary CPUs ...
+[    0.201607 <    0.000000>] [     T13] smpboot: x86: Booting SMP configuration:
+[    0.209670 <    0.000000>] [     T14]   #1  #3  #5  #7
+[    0.212630 <    0.000000>] [     T15] smp: Brought up 1 node, 16 CPUs
+[    0.215936 <    0.000000>] [     T16] audit: type=2000 audit(1702926179.015:1): state=initialized audit_enabled=0 res=1
+[    0.215937 <    0.000000>] [     T17] thermal_sys: Registered thermal governor 'fair_share'
+[    0.215966 <    0.000000>] [     T18] ENERGY_PERF_BIAS: Set to 'normal', was 'performance'
+[    0.367657 <    0.000000>] [     T19] ACPI: \_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+[    0.368615 <    0.000000>] [     T20] ACPI: \_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+[    0.376316 <    0.000000>] [     T21] ACPI: \_SB_.PRWL: New power resource
+[    0.376343 <    0.000000>] [     T22] ACPI: \_SB_.PRWB: New power resource
+[    0.377373 <    0.000000>] [     T23] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+[    0.377378 <    0.000000>] [     T24] acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+[    0.377569 <    0.000000>] [     T25] acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]
+[    0.377933 <    0.000000>] [     T26] acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+[    0.378458 <    0.000000>] [     T27] PCI host bridge to bus 0000:00
+[    0.378459 <    0.000000>] [     T28] pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]
+[    0.378461 <    0.000000>] [     T29] pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]
+[    9.398562 <    9.000000>] [     T30] user network daemon initialization complete
+[   10.441520 <    1.000000>] [     T31] systemd[1]: systemd 254.7-1.fc39 running in system mode
+[   11.441524 <    1.000000>] [     T32] systemd[1]: Detected architecture x86-64.
+[   12.441525 <    1.000000>] [     T33] systemd[1]: Running in initrd.
+[   13.541598 <    1.000000>] [     T34] systemd[1]: Hostname set to <catalina>.
+[   15.641860 <    2.000000>] [     T35] usb 3-3: New USB device found, idVendor=1a40, idProduct=0101, bcdDevice= 1.11
+[   16.690000 <    1.000000>] [     T36] Serial bus multi instantiate pseudo device driver INT3515:00: error -ENXIO: IRQ index 1 not found.
+[   17.710000 <    1.000000>] [     T37] snd_hda_intel 0000:00:1f.3: CORB reset timeout#2, CORBRP = 65535
+[   18.820000 <    1.000000>] [     T38] systemd-journald[723]: Received client request to flush runtime journal.
+[   20.840000 <    2.000000>] [     T39] systemd-journald[723]: File /var/log/journal/a124ea923b144109a12d557d5ac53179/system.journal corrupted or uncleanly shut down, renaming and replacing.
+[   21.852348 <    1.000000>] [     T40] systemd-journald[723]: /var/log/journal/ad7a2547ac0e4342a342e62a34a3eae4/user-1000.journal: Journal file uses a different sequence number ID, rotating.
+[   24.871100 <    3.000000>] [      41] PEFILE: Unsigned PE binary
+[   33.918091 <    9.000000>] [      42] snd_hda_intel 0000:00:1f.3: CORB reset timeout#2, CORBRP = 65535
+[  144.931785 <  111.000000>] [      C1] usb 3-3.1: device firmware changed
+[  145.953248 <    1.000000>] [      C2] usb 3-3.1: USB disconnect, device number 44
+[  147.981859 <    2.000000>] [      C3] usb 3-3.1: New USB device found, idVendor=17ef, idProduct=6047, bcdDevice= 3.30
diff --git a/tests/expected/dmesg/cid-kmsg-facilities b/tests/expected/dmesg/cid-kmsg-facilities
new file mode 100644
index 000000000..118bd2449
--- /dev/null
+++ b/tests/expected/dmesg/cid-kmsg-facilities
@@ -0,0 +1,45 @@
+kern  :emerg : [    0.000000] [      T1] Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000
+kern  :alert : [    0.000001] [      T2] Command line: initrd=\ucode.img initrd=\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system
+kern  :crit  : [    0.000002] [      T3] BIOS-provided physical RAM map:
+kern  :err   : [    0.000003] [      T4] BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable
+kern  :warn  : [    0.000004] [      T5] BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved
+kern  :notice: [    0.000005] [      T6] BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable
+kern  :info  : [    0.000006] [      T7] BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved
+kern  :debug : [    0.000007] [      T8] BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable
+kern  :info  : [    0.000008] [      T9] BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS
+kern  :info  : [    0.000009] [     T10] BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable
+kern  :info  : [    0.000010] [     T11] BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved
+kern  :info  : [    0.201607] [     T12] smp: Bringing up secondary CPUs ...
+kern  :info  : [    0.201607] [     T13] smpboot: x86: Booting SMP configuration:
+kern  :warn  : [    0.209670] [     T14]   #1  #3  #5  #7
+kern  :info  : [    0.212630] [     T15] smp: Brought up 1 node, 16 CPUs
+kern  :notice: [    0.215936] [     T16] audit: type=2000 audit(1702926179.015:1): state=initialized audit_enabled=0 res=1
+kern  :info  : [    0.215937] [     T17] thermal_sys: Registered thermal governor 'fair_share'
+kern  :warn  : [    0.215966] [     T18] ENERGY_PERF_BIAS: Set to 'normal', was 'performance'
+kern  :info  : [    0.367657] [     T19] ACPI: \_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+kern  :info  : [    0.368615] [     T20] ACPI: \_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+kern  :info  : [    0.376316] [     T21] ACPI: \_SB_.PRWL: New power resource
+kern  :info  : [    0.376343] [     T22] ACPI: \_SB_.PRWB: New power resource
+kern  :info  : [    0.377373] [     T23] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+kern  :info  : [    0.377378] [     T24] acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+kern  :info  : [    0.377569] [     T25] acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]
+kern  :info  : [    0.377933] [     T26] acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+kern  :info  : [    0.378458] [     T27] PCI host bridge to bus 0000:00
+kern  :info  : [    0.378459] [     T28] pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]
+kern  :info  : [    0.378461] [     T29] pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]
+kern  :info  : [   15.641860] [     T35] usb 3-3: New USB device found, idVendor=1a40, idProduct=0101, bcdDevice= 1.11
+kern  :err   : [   16.690000] [     T36] Serial bus multi instantiate pseudo device driver INT3515:00: error -ENXIO: IRQ index 1 not found.
+kern  :err   : [   17.710000] [     T37] snd_hda_intel 0000:00:1f.3: CORB reset timeout#2, CORBRP = 65535
+kern  :warn  : [   24.871100] [      41] PEFILE: Unsigned PE binary
+kern  :err   : [   33.918091] [      42] snd_hda_intel 0000:00:1f.3: CORB reset timeout#2, CORBRP = 65535
+kern  :info  : [  144.931785] [      C1] usb 3-3.1: device firmware changed
+kern  :info  : [  145.953248] [      C2] usb 3-3.1: USB disconnect, device number 44
+kern  :info  : [  147.981859] [      C3] usb 3-3.1: New USB device found, idVendor=17ef, idProduct=6047, bcdDevice= 3.30
+user  :notice: [    9.398562] [     T30] user network daemon initialization complete
+daemon:info  : [   10.441520] [     T31] systemd[1]: systemd 254.7-1.fc39 running in system mode
+daemon:info  : [   11.441524] [     T32] systemd[1]: Detected architecture x86-64.
+daemon:info  : [   12.441525] [     T33] systemd[1]: Running in initrd.
+daemon:info  : [   13.541598] [     T34] systemd[1]: Hostname set to <catalina>.
+syslog:info  : [   18.820000] [     T38] systemd-journald[723]: Received client request to flush runtime journal.
+syslog:warn  : [   20.840000] [     T39] systemd-journald[723]: File /var/log/journal/a124ea923b144109a12d557d5ac53179/system.journal corrupted or uncleanly shut down, renaming and replacing.
+syslog:info  : [   21.852348] [     T40] systemd-journald[723]: /var/log/journal/ad7a2547ac0e4342a342e62a34a3eae4/user-1000.journal: Journal file uses a different sequence number ID, rotating.
diff --git a/tests/expected/dmesg/cid-kmsg-indentation b/tests/expected/dmesg/cid-kmsg-indentation
new file mode 100644
index 000000000..fe03a0e1e
--- /dev/null
+++ b/tests/expected/dmesg/cid-kmsg-indentation
@@ -0,0 +1,28 @@
+[    0.000000] [      T0] line zero
+[    1.000000] [      T1] new
+[    2.000000] [      T2] two
+[    3.000000] [      T3] three
+[    0.000000] [      T0] line zero
+[    1.000000] [      T1] new
+[    2.000000] [      T2] two
+[    3.000000] [      T3] three
+[<    0.000000>] [      T0] line zero
+[<    0.000000>] [      T1] new
+[<    1.000000>] [      T2] two
+[<    1.000000>] [      T3] three
+[      T0] line zero
+[      T1] new
+[      T2] two
+[      T3] three
+[Feb13 23:31] [      T0] line zero
+[  +0.000000] [      T1] new
+[  +1.000000] [      T2] two
+[  +1.000000] [      T3] three
+[Fri Feb 13 23:31:30 2009] [      T0] line zero
+[Fri Feb 13 23:31:31 2009] [      T1] new
+[Fri Feb 13 23:31:32 2009] [      T2] two
+[Fri Feb 13 23:31:33 2009] [      T3] three
+2009-02-13T23:31:30,123456+00:00 [      T0] line zero
+2009-02-13T23:31:31,123456+00:00 [      T1] new
+2009-02-13T23:31:32,123456+00:00 [      T2] two
+2009-02-13T23:31:33,123456+00:00 [      T3] three
diff --git a/tests/expected/dmesg/cid-kmsg-json b/tests/expected/dmesg/cid-kmsg-json
new file mode 100644
index 000000000..578efd720
--- /dev/null
+++ b/tests/expected/dmesg/cid-kmsg-json
@@ -0,0 +1,230 @@
+{
+   "dmesg": [
+      {
+         "pri": 0,
+         "time":     0.000000,
+         "caller": "T1",
+         "msg": "Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000"
+      },{
+         "pri": 1,
+         "time":     0.000001,
+         "caller": "T2",
+         "msg": "Command line: initrd=\\ucode.img initrd=\\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system"
+      },{
+         "pri": 2,
+         "time":     0.000002,
+         "caller": "T3",
+         "msg": "BIOS-provided physical RAM map:"
+      },{
+         "pri": 3,
+         "time":     0.000003,
+         "caller": "T4",
+         "msg": "BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable"
+      },{
+         "pri": 4,
+         "time":     0.000004,
+         "caller": "T5",
+         "msg": "BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved"
+      },{
+         "pri": 5,
+         "time":     0.000005,
+         "caller": "T6",
+         "msg": "BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable"
+      },{
+         "pri": 6,
+         "time":     0.000006,
+         "caller": "T7",
+         "msg": "BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved"
+      },{
+         "pri": 7,
+         "time":     0.000007,
+         "caller": "T8",
+         "msg": "BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable"
+      },{
+         "pri": 6,
+         "time":     0.000008,
+         "caller": "T9",
+         "msg": "BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS"
+      },{
+         "pri": 6,
+         "time":     0.000009,
+         "caller": "T10",
+         "msg": "BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable"
+      },{
+         "pri": 6,
+         "time":     0.000010,
+         "caller": "T11",
+         "msg": "BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved"
+      },{
+         "pri": 6,
+         "time":     0.201607,
+         "caller": "T12",
+         "msg": "smp: Bringing up secondary CPUs ..."
+      },{
+         "pri": 6,
+         "time":     0.201607,
+         "caller": "T13",
+         "msg": "smpboot: x86: Booting SMP configuration:"
+      },{
+         "pri": 4,
+         "time":     0.209670,
+         "caller": "T14",
+         "msg": "  #1  #3  #5  #7"
+      },{
+         "pri": 6,
+         "time":     0.212630,
+         "caller": "T15",
+         "msg": "smp: Brought up 1 node, 16 CPUs"
+      },{
+         "pri": 5,
+         "time":     0.215936,
+         "caller": "T16",
+         "msg": "audit: type=2000 audit(1702926179.015:1): state=initialized audit_enabled=0 res=1"
+      },{
+         "pri": 6,
+         "time":     0.215937,
+         "caller": "T17",
+         "msg": "thermal_sys: Registered thermal governor 'fair_share'"
+      },{
+         "pri": 4,
+         "time":     0.215966,
+         "caller": "T18",
+         "msg": "ENERGY_PERF_BIAS: Set to 'normal', was 'performance'"
+      },{
+         "pri": 6,
+         "time":     0.367657,
+         "caller": "T19",
+         "msg": "ACPI: \\_SB_.PCI0.GP19.NHI1.PWRS: New power resource"
+      },{
+         "pri": 6,
+         "time":     0.368615,
+         "caller": "T20",
+         "msg": "ACPI: \\_SB_.PCI0.GP19.XHC4.PWRS: New power resource"
+      },{
+         "pri": 6,
+         "time":     0.376316,
+         "caller": "T21",
+         "msg": "ACPI: \\_SB_.PRWL: New power resource"
+      },{
+         "pri": 6,
+         "time":     0.376343,
+         "caller": "T22",
+         "msg": "ACPI: \\_SB_.PRWB: New power resource"
+      },{
+         "pri": 6,
+         "time":     0.377373,
+         "caller": "T23",
+         "msg": "ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])"
+      },{
+         "pri": 6,
+         "time":     0.377378,
+         "caller": "T24",
+         "msg": "acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]"
+      },{
+         "pri": 6,
+         "time":     0.377569,
+         "caller": "T25",
+         "msg": "acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]"
+      },{
+         "pri": 6,
+         "time":     0.377933,
+         "caller": "T26",
+         "msg": "acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]"
+      },{
+         "pri": 6,
+         "time":     0.378458,
+         "caller": "T27",
+         "msg": "PCI host bridge to bus 0000:00"
+      },{
+         "pri": 6,
+         "time":     0.378459,
+         "caller": "T28",
+         "msg": "pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]"
+      },{
+         "pri": 6,
+         "time":     0.378461,
+         "caller": "T29",
+         "msg": "pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]"
+      },{
+         "pri": 13,
+         "time":     9.398562,
+         "caller": "T30",
+         "msg": "user network daemon initialization complete"
+      },{
+         "pri": 30,
+         "time":    10.441520,
+         "caller": "T31",
+         "msg": "systemd[1]: systemd 254.7-1.fc39 running in system mode"
+      },{
+         "pri": 30,
+         "time":    11.441524,
+         "caller": "T32",
+         "msg": "systemd[1]: Detected architecture x86-64."
+      },{
+         "pri": 30,
+         "time":    12.441525,
+         "caller": "T33",
+         "msg": "systemd[1]: Running in initrd."
+      },{
+         "pri": 30,
+         "time":    13.541598,
+         "caller": "T34",
+         "msg": "systemd[1]: Hostname set to <catalina>."
+      },{
+         "pri": 6,
+         "time":    15.641860,
+         "caller": "T35",
+         "msg": "usb 3-3: New USB device found, idVendor=1a40, idProduct=0101, bcdDevice= 1.11"
+      },{
+         "pri": 3,
+         "time":    16.690000,
+         "caller": "T36",
+         "msg": "Serial bus multi instantiate pseudo device driver INT3515:00: error -ENXIO: IRQ index 1 not found."
+      },{
+         "pri": 3,
+         "time":    17.710000,
+         "caller": "T37",
+         "msg": "snd_hda_intel 0000:00:1f.3: CORB reset timeout#2, CORBRP = 65535"
+      },{
+         "pri": 46,
+         "time":    18.820000,
+         "caller": "T38",
+         "msg": "systemd-journald[723]: Received client request to flush runtime journal."
+      },{
+         "pri": 44,
+         "time":    20.840000,
+         "caller": "T39",
+         "msg": "systemd-journald[723]: File /var/log/journal/a124ea923b144109a12d557d5ac53179/system.journal corrupted or uncleanly shut down, renaming and replacing."
+      },{
+         "pri": 46,
+         "time":    21.852348,
+         "caller": "T40",
+         "msg": "systemd-journald[723]: /var/log/journal/ad7a2547ac0e4342a342e62a34a3eae4/user-1000.journal: Journal file uses a different sequence number ID, rotating."
+      },{
+         "pri": 4,
+         "time":    24.871100,
+         "caller": "41",
+         "msg": "PEFILE: Unsigned PE binary"
+      },{
+         "pri": 3,
+         "time":    33.918091,
+         "caller": "42",
+         "msg": "snd_hda_intel 0000:00:1f.3: CORB reset timeout#2, CORBRP = 65535"
+      },{
+         "pri": 6,
+         "time":   144.931785,
+         "caller": "C1",
+         "msg": "usb 3-3.1: device firmware changed"
+      },{
+         "pri": 6,
+         "time":   145.953248,
+         "caller": "C2",
+         "msg": "usb 3-3.1: USB disconnect, device number 44"
+      },{
+         "pri": 6,
+         "time":   147.981859,
+         "caller": "C3",
+         "msg": "usb 3-3.1: New USB device found, idVendor=17ef, idProduct=6047, bcdDevice= 3.30"
+      }
+   ]
+}
diff --git a/tests/expected/dmesg/cid-kmsg-limit b/tests/expected/dmesg/cid-kmsg-limit
new file mode 100644
index 000000000..8db1c9a65
--- /dev/null
+++ b/tests/expected/dmesg/cid-kmsg-limit
@@ -0,0 +1,31 @@
+[    0.201607] [     T12] smp: Bringing up secondary CPUs ...
+[    0.201607] [     T13] smpboot: x86: Booting SMP configuration:
+[    0.209670] [     T14]   #1  #3  #5  #7
+[    0.212630] [     T15] smp: Brought up 1 node, 16 CPUs
+[    0.215936] [     T16] audit: type=2000 audit(1702926179.015:1): state=initialized audit_enabled=0 res=1
+[    0.215937] [     T17] thermal_sys: Registered thermal governor 'fair_share'
+[    0.215966] [     T18] ENERGY_PERF_BIAS: Set to 'normal', was 'performance'
+[    0.367657] [     T19] ACPI: \_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+[    0.368615] [     T20] ACPI: \_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+[    0.376316] [     T21] ACPI: \_SB_.PRWL: New power resource
+[    0.376343] [     T22] ACPI: \_SB_.PRWB: New power resource
+[    0.377373] [     T23] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+[    0.377378] [     T24] acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+[    0.377569] [     T25] acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]
+[    0.377933] [     T26] acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+[    0.378458] [     T27] PCI host bridge to bus 0000:00
+[    0.378459] [     T28] pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]
+[    0.378461] [     T29] pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]
+[    9.398562] [     T30] user network daemon initialization complete
+[   10.441520] [     T31] systemd[1]: systemd 254.7-1.fc39 running in system mode
+[   11.441524] [     T32] systemd[1]: Detected architecture x86-64.
+[   12.441525] [     T33] systemd[1]: Running in initrd.
+[   13.541598] [     T34] systemd[1]: Hostname set to <catalina>.
+[   15.641860] [     T35] usb 3-3: New USB device found, idVendor=1a40, idProduct=0101, bcdDevice= 1.11
+[   16.690000] [     T36] Serial bus multi instantiate pseudo device driver INT3515:00: error -ENXIO: IRQ index 1 not found.
+[   17.710000] [     T37] snd_hda_intel 0000:00:1f.3: CORB reset timeout#2, CORBRP = 65535
+[   18.820000] [     T38] systemd-journald[723]: Received client request to flush runtime journal.
+[   20.840000] [     T39] systemd-journald[723]: File /var/log/journal/a124ea923b144109a12d557d5ac53179/system.journal corrupted or uncleanly shut down, renaming and replacing.
+[   21.852348] [     T40] systemd-journald[723]: /var/log/journal/ad7a2547ac0e4342a342e62a34a3eae4/user-1000.journal: Journal file uses a different sequence number ID, rotating.
+[   24.871100] [      41] PEFILE: Unsigned PE binary
+[   33.918091] [      42] snd_hda_intel 0000:00:1f.3: CORB reset timeout#2, CORBRP = 65535
diff --git a/tests/expected/dmesg/kmsg-file b/tests/expected/dmesg/kmsg-file
index 54b5e612d..984588e3e 100644
--- a/tests/expected/dmesg/kmsg-file
+++ b/tests/expected/dmesg/kmsg-file
@@ -1,49 +1,77 @@
 {
    "dmesg": [
       {
-         "pri": 5,
+         "pri": 0,
          "time":     0.000000,
          "msg": "Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000"
       },{
-         "pri": 6,
-         "time":     0.000000,
+         "pri": 1,
+         "time":     0.000001,
          "msg": "Command line: initrd=\\ucode.img initrd=\\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system"
       },{
-         "pri": 6,
-         "time":     0.000000,
+         "pri": 2,
+         "time":     0.000002,
          "msg": "BIOS-provided physical RAM map:"
       },{
-         "pri": 6,
-         "time":     0.000000,
+         "pri": 3,
+         "time":     0.000003,
          "msg": "BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable"
       },{
-         "pri": 6,
-         "time":     0.000000,
+         "pri": 4,
+         "time":     0.000004,
          "msg": "BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved"
       },{
-         "pri": 6,
-         "time":     0.000000,
+         "pri": 5,
+         "time":     0.000005,
          "msg": "BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable"
       },{
          "pri": 6,
-         "time":     0.000000,
+         "time":     0.000006,
          "msg": "BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved"
       },{
-         "pri": 6,
-         "time":     0.000000,
+         "pri": 7,
+         "time":     0.000007,
          "msg": "BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable"
       },{
          "pri": 6,
-         "time":     0.000000,
+         "time":     0.000008,
          "msg": "BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS"
       },{
          "pri": 6,
-         "time":     0.000000,
+         "time":     0.000009,
          "msg": "BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable"
       },{
          "pri": 6,
-         "time":     0.000000,
+         "time":     0.000010,
          "msg": "BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved"
+      },{
+         "pri": 6,
+         "time":     0.201607,
+         "msg": "smp: Bringing up secondary CPUs ..."
+      },{
+         "pri": 6,
+         "time":     0.201607,
+         "msg": "smpboot: x86: Booting SMP configuration:"
+      },{
+         "pri": 4,
+         "time":     0.209670,
+         "msg": "  #1  #3  #5  #7"
+      },{
+         "pri": 6,
+         "time":     0.212630,
+         "msg": "smp: Brought up 1 node, 16 CPUs"
+      },{
+         "pri": 5,
+         "time":     0.215936,
+         "msg": "audit: type=2000 audit(1702926179.015:1): state=initialized audit_enabled=0 res=1"
+      },{
+         "pri": 6,
+         "time":     0.215937,
+         "msg": "thermal_sys: Registered thermal governor 'fair_share'"
+      },{
+         "pri": 4,
+         "time":     0.215966,
+         "msg": "ENERGY_PERF_BIAS: Set to 'normal', was 'performance'"
       },{
          "pri": 6,
          "time":     0.367657,
@@ -88,6 +116,70 @@
          "pri": 6,
          "time":     0.378461,
          "msg": "pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]"
+      },{
+         "pri": 13,
+         "time":     9.398562,
+         "msg": "user network daemon initialization complete"
+      },{
+         "pri": 30,
+         "time":    10.441520,
+         "msg": "systemd[1]: systemd 254.7-1.fc39 running in system mode"
+      },{
+         "pri": 30,
+         "time":    11.441524,
+         "msg": "systemd[1]: Detected architecture x86-64."
+      },{
+         "pri": 30,
+         "time":    12.441525,
+         "msg": "systemd[1]: Running in initrd."
+      },{
+         "pri": 30,
+         "time":    13.541598,
+         "msg": "systemd[1]: Hostname set to <catalina>."
+      },{
+         "pri": 6,
+         "time":    15.641860,
+         "msg": "usb 3-3: New USB device found, idVendor=1a40, idProduct=0101, bcdDevice= 1.11"
+      },{
+         "pri": 3,
+         "time":    16.690000,
+         "msg": "Serial bus multi instantiate pseudo device driver INT3515:00: error -ENXIO: IRQ index 1 not found."
+      },{
+         "pri": 3,
+         "time":    17.710000,
+         "msg": "snd_hda_intel 0000:00:1f.3: CORB reset timeout#2, CORBRP = 65535"
+      },{
+         "pri": 46,
+         "time":    18.820000,
+         "msg": "systemd-journald[723]: Received client request to flush runtime journal."
+      },{
+         "pri": 44,
+         "time":    20.840000,
+         "msg": "systemd-journald[723]: File /var/log/journal/a124ea923b144109a12d557d5ac53179/system.journal corrupted or uncleanly shut down, renaming and replacing."
+      },{
+         "pri": 46,
+         "time":    21.852348,
+         "msg": "systemd-journald[723]: /var/log/journal/ad7a2547ac0e4342a342e62a34a3eae4/user-1000.journal: Journal file uses a different sequence number ID, rotating."
+      },{
+         "pri": 4,
+         "time":    24.871100,
+         "msg": "PEFILE: Unsigned PE binary"
+      },{
+         "pri": 3,
+         "time":    33.918091,
+         "msg": "snd_hda_intel 0000:00:1f.3: CORB reset timeout#2, CORBRP = 65535"
+      },{
+         "pri": 6,
+         "time":   144.931785,
+         "msg": "usb 3-3.1: device firmware changed"
+      },{
+         "pri": 6,
+         "time":   145.953248,
+         "msg": "usb 3-3.1: USB disconnect, device number 44"
+      },{
+         "pri": 6,
+         "time":   147.981859,
+         "msg": "usb 3-3.1: New USB device found, idVendor=17ef, idProduct=6047, bcdDevice= 3.30"
       }
    ]
 }
diff --git a/tests/ts/dmesg/cid-input b/tests/ts/dmesg/cid-input
new file mode 100644
index 000000000..7dbd89d8f
--- /dev/null
+++ b/tests/ts/dmesg/cid-input
@@ -0,0 +1,106 @@
+<0>[    0.000000] [    T0] example[0]
+<1>[    1.000000] [    T1] example[1]
+<2>[    8.000000] [    T2] example[2]
+<3>[   27.000000] [    T3] example[3]
+<4>[   64.000000] [    T4] example[4]
+<5>[  125.000000] [    T5] example[5]
+<6>[  216.000000] [    T6] example[6]
+<7>[  343.000000] [    T7] example[7]
+<8>[  512.000000] [    T8] example[8]
+<9>[  729.000000] [    T9] example[9]
+<10>[ 1000.000000] [   T10] example[10]
+<11>[ 1331.000000] [   T11] example[11]
+<12>[ 1728.000000] [   T12] example[12]
+<13>[ 2197.000000] [   T13] example[13]
+<14>[ 2744.000000] [   T14] example[14]
+<15>[ 3375.000000] [   T15] example[15]
+<16>[ 4096.000000] [   T16] example[16]
+<17>[ 4913.000000] [   T17] example[17]
+<18>[ 5832.000000] [   T18] example[18]
+<19>[ 6859.000000] [   T19] example[19]
+<20>[ 8000.000000] [   T20] example[20]
+<21>[ 9261.000000] [   T21] example[21]
+<22>[10648.000000] [   T22] example[22]
+<23>[12167.000000] [   T23] example[23]
+<24>[13824.000000] [   T24] example[24]
+<25>[15625.000000] [   T25] example[25]
+<26>[17576.000000] [   T26] example[26]
+<27>[19683.000000] [   T27] example[27]
+<28>[21952.000000] [   T28] example[28]
+<29>[24389.000000] [   T29] example[29]
+<30>[27000.000000] [   T10] example[30]
+<31>[29791.000000] [   T31] example[31]
+<32>[32768.000000] [   T32] example[32]
+<33>[35937.000000] [   T33] example[33]
+<34>[39304.000000] [   T34] example[34]
+<35>[42875.000000] [   T35] example[35]
+<36>[46656.000000] [   T36] example[36]
+<37>[50653.000000] [   T37] example[37]
+<38>[54872.000000] [   T38] example[38]
+<39>[59319.000000] [   T39] example[39]
+<40>[64000.000000] [   T40] example[40]
+<41>[68921.000000] [   T41] example[41]
+<42>[74088.000000] [   T42] example[42]
+<43>[79507.000000] [   T43] example[43]
+<44>[85184.000000] [   T44] example[44]
+<45>[91125.000000] [   T45] example[45]
+<46>[97336.000000] [   T46] example[46]
+<47>[103823.000000] [   T47] example[47]
+<48>[110592.000000] [   T48] example[48]
+<49>[117649.000000] [   T49] example[49]
+<50>[125000.000000] [   T50] example[50]
+<51>[132651.000000] [   T51] example[51]
+<52>[140608.000000] [   T52] example[52]
+<53>[148877.000000] [   T53] example[53]
+<54>[157464.000000] [   T54] example[54]
+<55>[166375.000000] [   T55] example[55]
+<56>[175616.000000] [   T56] example[56]
+<57>[185193.000000] [   T57] example[57]
+<58>[195112.000000] [   T58] example[58]
+<59>[205379.000000] [   T59] example[59]
+<60>[216000.000000] [   T60] example[60]
+<61>[226981.000000] [   T61] example[61]
+<62>[238328.000000] [   T62] example[62]
+<63>[250047.000000] [   T63] example[63]
+<64>[262144.000000] [   T64] example[64]
+<65>[274625.000000] [   T65] example[65]
+<66>[287496.000000] [   T66] example[66]
+<67>[300763.000000] [   T67] example[67]
+<68>[314432.000000] [   T68] example[68]
+<69>[328509.000000] [   T69] example[69]
+<70>[343000.000000] [   T70] example[70]
+<71>[357911.000000] [   T71] example[71]
+<72>[373248.000000] [   T72] example[72]
+<73>[389017.000000] [   T73] example[73]
+<74>[405224.000000] [   T74] example[74]
+<75>[421875.000000] [   T75] example[75]
+<76>[438976.000000] [   T76] example[76]
+<77>[456533.000000] [   T77] example[77]
+<78>[474552.000000] [   T78] example[78]
+<79>[493039.000000] [   T79] example[79]
+<80>[512000.000000] [   T80] example[80]
+<81>[531441.000000] [   T81] example[81]
+<82>[551368.000000] [   T82] example[82]
+<83>[571787.000000] [   T83] example[83]
+<84>[592704.000000] [   T84] example[84]
+<85>[614125.000000] [   T85] example[85]
+<86>[636056.000000] [   T86] example[86]
+<87>[658503.000000] [   T87] example[87]
+<88>[681472.000000] [   T88] example[88]
+<89>[704969.000000] [   T89] example[89]
+<90>[729000.000000] [   T90] example[90]
+<91>[753571.000000] [   T91] example[91]
+<92>[778688.000000] [   T92] example[92]
+<93>[804357.000000] [   T93] example[93]
+<94>[830584.000000] [   T94] example[94]
+<95>[857375.000000] [   T95] example[95]
+<96>[884736.000000] [   T96] example[96]
+<97>[912673.000000] [   T97] example[97]
+<98>[941192.000000] [   T98] example[98]
+<99>[970299.000000] [   T99] example[99]
+<100>[1000000.000000] [  T100] example[100]
+<101>[1030301.000000] [  T101] example[101]
+<102>[1061208.000000] [  T102] example[102]
+<103>[1092727.000000] [  T103] example[103]
+<104>[1124864.000000] [  T104] example[104]
+<150>[4557523.000000] [  T105] example[105]
diff --git a/tests/ts/dmesg/cid-json b/tests/ts/dmesg/cid-json
new file mode 100755
index 000000000..78363793d
--- /dev/null
+++ b/tests/ts/dmesg/cid-json
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="cid-json"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG -J -F $TS_SELF/cid-input >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/cid-kmsg-colors b/tests/ts/dmesg/cid-kmsg-colors
new file mode 100755
index 000000000..90a593354
--- /dev/null
+++ b/tests/ts/dmesg/cid-kmsg-colors
@@ -0,0 +1,29 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="cid-kmsg-colors"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+ts_inhibit_custom_colorscheme
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG --color=always -K $TS_SELF/cid-kmsg-input -x >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/cid-kmsg-console-levels b/tests/ts/dmesg/cid-kmsg-console-levels
new file mode 100755
index 000000000..2cd445d05
--- /dev/null
+++ b/tests/ts/dmesg/cid-kmsg-console-levels
@@ -0,0 +1,36 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="cid-kmsg-levels"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+for I in {-1..8}; do
+	$TS_HELPER_DMESG -K $TS_SELF/cid-kmsg-input -l $I >> $TS_OUTPUT 2>/dev/null
+done
+
+$TS_HELPER_DMESG -K $TS_SELF/cid-kmsg-input -l err+ >> $TS_OUTPUT 2>/dev/null
+$TS_HELPER_DMESG -K $TS_SELF/cid-kmsg-input -l emerg+ >> $TS_OUTPUT 2>/dev/null
+$TS_HELPER_DMESG -K $TS_SELF/cid-kmsg-input -l +err >> $TS_OUTPUT 2>/dev/null
+$TS_HELPER_DMESG -K $TS_SELF/cid-kmsg-input -l +debug >> $TS_OUTPUT 2>/dev/null
+$TS_HELPER_DMESG -K $TS_SELF/cid-kmsg-input -l + 2>> $TS_OUTPUT >/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/cid-kmsg-decode b/tests/ts/dmesg/cid-kmsg-decode
new file mode 100755
index 000000000..316fb2079
--- /dev/null
+++ b/tests/ts/dmesg/cid-kmsg-decode
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="cid-kmsg-decode"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG -x -K $TS_SELF/cid-kmsg-input >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/cid-kmsg-delta b/tests/ts/dmesg/cid-kmsg-delta
new file mode 100755
index 000000000..64c2e6933
--- /dev/null
+++ b/tests/ts/dmesg/cid-kmsg-delta
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="cid-kmsg-delta"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG -d -K $TS_SELF/cid-kmsg-input >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/cid-kmsg-facilities b/tests/ts/dmesg/cid-kmsg-facilities
new file mode 100755
index 000000000..f50f2b73d
--- /dev/null
+++ b/tests/ts/dmesg/cid-kmsg-facilities
@@ -0,0 +1,30 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="cid-kmsg-facilities"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+for I in {-1..12}; do
+	$TS_HELPER_DMESG -K $TS_SELF/cid-kmsg-input -f $I -x >> $TS_OUTPUT 2>/dev/null
+done
+
+ts_finalize
diff --git a/tests/ts/dmesg/cid-kmsg-indentation b/tests/ts/dmesg/cid-kmsg-indentation
new file mode 100755
index 000000000..d45e1e30b
--- /dev/null
+++ b/tests/ts/dmesg/cid-kmsg-indentation
@@ -0,0 +1,40 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="cid-kmsg-indentation"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG -K $TS_SELF/cid-kmsg-newlines >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG -K $TS_SELF/cid-kmsg-newlines >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=delta --kmsg-file $TS_SELF/cid-kmsg-newlines >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=notime --kmsg-file $TS_SELF/cid-kmsg-newlines >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=reltime --kmsg-file $TS_SELF/cid-kmsg-newlines >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=ctime --kmsg-file $TS_SELF/cid-kmsg-newlines >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=iso --kmsg-file $TS_SELF/cid-kmsg-newlines >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+ts_finalize
diff --git a/tests/ts/dmesg/cid-kmsg-input b/tests/ts/dmesg/cid-kmsg-input
new file mode 100644
index 0000000000000000000000000000000000000000..8ebfb5170e647b57d1f3f504150ddb3def3b4247
GIT binary patch
literal 4425
zcmbtXYjfht5%p*PimuuZwrho~(dbP`#m4NK)Y>Ls@7*oOMGevbx>paPhadU%IU`^Z
z>)6RA43yAgPM_)NKHV}j1EZsbB1vS?yJg)kaaKRmqb$le&&bgo-Rg)UT(S<M<3!#3
zi#l!oozU?j4C(lDzkfoE>!!}gG)!)I2Gi*C^&KS<?&5fkiB+7GCuHgt(~T4Qz-V$c
zqS1ITxEkF~FTP)&T@Cwmm1i0m7G21&fg-~QOg~^geKhbnJYbp{JH}?WpQowFA_65D
zP@Kh85%vE5Y=?E2M^cZ|Mf+lNU!?Q0(=4I6T|7}(ysWB7KE|Q!o#J?!J*Lvg*op_`
zOIgV@h~hF7MMOoOSL;Vov0BOEbbbHuz|_>(G2`9y;mxG8D)PrTk`b+zFJ%lz)A;O)
zFgG|n;F=n{Db{+5^h_h5`&6c6Jga55Kb^fxzMRkJ4^)?8mdL{cOH*S9Xul8W&w;!T
zI0GI43t7tIQAURcwx-4o(s>t>HB{S>zEFrQj*h0r4$yrM(4V~qj5dHfj;^N04$^xU
zQoe>%Ufk#CX<iG^e-}`Bao>;roGV8@&{=;pr0cJf!vjb2F?Jl8@jfOG_c1M#+dq?J
zhK6qolf8op0Ou#3mSt}+cfNEqZWx+rFvn=Sl$qT!T?KSr#MuI0s#jFXFwY`Uyik91
zSCX#lYMC6#|9U!C(`U$?fSx@EIQXkzln4N29xv)bRL~rxg{5((Fnq@~v~VX*R+p4+
z&<Bp6ji1}tW5_#ZI(*L)_Lgp5FP4>J%P4~$XvCa`u8M4Kx|nMFyd96s>54jvL9}{V
z$({+HQFGy#xrXVR4s(6oV0OSx0xBy}$(|CGSS0a3k><^#Q<<rRjCzL3q#kQ{n%>&j
zo?G2+wUk9Fk|}f~ps`%UkedQPo9nd5p~hKW(9vAP#k5?CLLN0v;%oNK9(%7lxE_o@
zf1i#9<4@D`;n^ghiL9u~=?EyWbfnRfDCr2|HCGq1P~kb6#i2%y>)3k){jQ4PfRv(6
zC+Aar)E^r9=MnSu>&qe2N573>;aWb?Du0rNT5nz#A;d@_Vk;fbVQm31jkgiMUG}a2
zfQVgl9nRWoHrXr0@o!(=CWROUgw<AF)BHCO=Wj!}fN;6H2f;TGa1f0V-YQq3g`|7s
zu?ISi@>IkbDjEXnepZ+G*MUZytUcwe5!<R`T3r#YVj5kKj5EUvPzz~#GwBC(Goi9x
zt@5HO>3;BB$qW^y-=q<pO-5JLPx9~&94B&-$_!6kO@=hM7}MqGTjv&W%^wbFa(6!Y
zKDixS^^}=Ix)^*N_6NO>>MYn9UGwu5Kig?bm}$SoZ<UBj#TG@mERlEBmM+~-E=T>#
zyjmsog3boxU!-9fiiVF!-Kn05gniRZS&rhKXH}6Wa20k!ZjFzw2BgmWVkKsA5?3$u
z<#tRLqyDdQV&LRi_TJXHT@?n)ysT)p4g)0MdegCus*^!_Smt`>o>RT<DvYPCM}wy4
zXeMuyi|*r`HqC)5w&C2Rr#Or9r#<c)pxw@HF2H_^1hO9VoxQHg{}mEZQ~XqM`rk+}
zuDL#{BlkVq*=wPUZjC;KGFd(4#UB(2nW8KGA-7Gz!1kuAL{?B7lmL&LsEL-vY_nYt
zIP0$awCJ8aK(?EnE+W&mbhpFwdB}Y#>MT<w2|2pHPbmt<29;}!HK^_OilZp5ks8zs
zkO(VP1JEJI>VI8GRqi^Dh0@rtvovNlIBiMfsE#e1@s7y4o!w5hHO6f$&2NVqxArDq
zBIGiWN>t}Y^#2r!3Z*F%e{QO?hg!#M$6}td=N}uMo)PcxwdUPT&S~8a(>$-UNTWFV
z3YE!=9ur7HoQ{e-s>7;hFxBnP!sue%J`>X!Yl{nje?(x&JU=jP6mE{Kay8~Sz6!=x
zI&-Hxkp;?W6Y*)CR57*$g*HQttt72VSx5PnT~x#<k2Ji#<u+=vl1Nz;sFt0<^|#?o
zK*RChFg=pbO#@J^m!r4&ZN=&b$&cGB!46gt_R%gd*KK;-Het70X3=yRiD{fwGHDcE
zF=2BZ?(E-;&zpW4+YzTSud5HH)?6Krs7H=%a~tIx{h^Il8xOtzPyX<>``h^)l{FJd
zbnluRQ9PER#OfmolNcfoBmbx+1P4kpPwH~1B3hZG%{&BvWx)*kCBw6RHsil#=2M(V
zI(-zyX_7BaH&~|vaV&*z@|nsD!^e4K+iqlw(B^27Ht$9H=6PgkQPeAy9oU>Y3lk}_
z<b}#*U7<=m;kB<o)0C<NRBv;I#3qC|Q>2w|IGQKVHo4V~eam=@^lQG6E0FH42n~t8
z#1!~RM;!#0LRzOvX*z0ex0D0=>)PKmS02Fqk_1KZe2)GM?k<(P(L7OBr!y6U7g$4%
zhH%3gq%F;~JeL7=7cUm;js~BGUj_l)Wo5j`;F8gRW=PTEMTHqN5oetH%rpF!C|eMl
z|2xba4gD)*#Ik&BlGhTUKHDmQ&Vp@r&Eq0{LcdAjQe+Ff4z_xR*J<ths;a>NB*wC_
zWmx=f-F>rdpb;3nQs-F)oz%7lH?Fj-|I(5VORn!BGFmmX&)b$%Yx<s?xpLl?Gsm#p
QJvrk#H{NA~_oc&s0T4C|J^%m!

literal 0
HcmV?d00001

diff --git a/tests/ts/dmesg/cid-kmsg-json b/tests/ts/dmesg/cid-kmsg-json
new file mode 100755
index 000000000..ad1e3e785
--- /dev/null
+++ b/tests/ts/dmesg/cid-kmsg-json
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="cid-kmsg-json"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG -J -K $TS_SELF/cid-kmsg-input >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/cid-kmsg-limit b/tests/ts/dmesg/cid-kmsg-limit
new file mode 100755
index 000000000..884d4f8ce
--- /dev/null
+++ b/tests/ts/dmesg/cid-kmsg-limit
@@ -0,0 +1,29 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="cid-kmsg-limit"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG --since @1234567890.124 --until @1234567991 -K $TS_SELF/cid-kmsg-input \
+	>> $TS_OUTPUT 2> $TS_ERRLOG
+
+ts_finalize
diff --git a/tests/ts/dmesg/cid-kmsg-newlines b/tests/ts/dmesg/cid-kmsg-newlines
new file mode 100644
index 0000000000000000000000000000000000000000..574d2177796677b73f1efcf273005169ed832c60
GIT binary patch
literal 152
zcmXrjF#tkco#e!voYW%Q5CiL+%)C^Es??%<E(Svb9YY;M128~RV`!b1TFwPh$Hia-
tQeuRm#K^j&Jf91MLCT7`7>o^cjC71K)EQfsWE7>QazV)4{GwE-1^{d2D<=Q|

literal 0
HcmV?d00001

diff --git a/tests/ts/dmesg/kmsg-input b/tests/ts/dmesg/kmsg-input
index b000f4c951ccdcec96c820d37efc64ac8b68a93c..c08331dbf2bfdc9622105e120be99e448cfa89ea 100644
GIT binary patch
literal 3944
zcmbtXYg5};66G_$qO0-&sK`QBZz=1o1>*#71<=}%Ns6Uh*V47E89lsu@R(mer)3jN
zD9C0P;j&(R`rN*Ky4!|k;OKq$oEGgp-Kwfi%Yt0p)$N|F;-%;b+RymmKlrjcJD~kV
z9Mk@%!Qg;|rJK4S(=aW=H-tu?&aWs-@D$(2Fl^GSJ|I)Kg>D?sJ3*7Ph@$aucotnw
zPrjWWos9-`Ru&o=Hl3)rgCfHS%^(y3y*Kc;yCXC{dLIU5p35R35K$qeMcPzJ|KImc
z+{R_1^fX^=-|U{td|vlD;@#uwj^gTJ)g<aRjaB~;--pF*u8cygtgwEl8<mGiTF0_V
zs4B~5{YoxZD^(q?pYQIN8Xvt6$D@l$Z&j7IX`&KZEg$MMmKlwY&IlIa?vADLv3XJX
zrV-M0u5vQ&d12dsy=S)qHJ{IKsIBEJQ@cC1#>Y=!f;sS>!_0sJm`c^Ex>d>Uj-&DM
zHjwCOZ36|8aklul8Xs@M1hbbg$p+?$kEikRHjsJ=#L;=q$JhLyz;JY)$0wLu9H1LI
z8bl*H|1#O#akT))+kEC${2a(OE$2r*!qD*l77(o59~jxTvjKXFkgHjSp_zto4GvVD
zuR=Pm(qe&sYFAXNxGWM`J<uS!s!7*%UWElMZrjX|$syhQE{t)?wk$-L&eKI($p*Sd
zy4sp0*f4NCLyJEU3zptl_&E4@9kM{`3)8iDbsIKiyI3|%Mo<AAY9!o_4d<I>dU)Rn
zEY26%CMkF{4=dF-v3Tlk><iB@1Je~=pc}#o#X(4QBOBFc1*bAg|Ae}_SEs6AMI?QL
zle#ZDMy9{^!0~C8s>)?Hg;GNrt3?VySFqmPr$vb>SCkd)&1G6m>!qyJUbk>-&C_L`
z!}H<z)3<3f9Dkf1kB%lGO;kfoNqaB_{GLX4vZg)MggM_RVg_+F+k)I(&vlpzXH`gC
zou-rHsU8hRhW;rMfqs5E5_<I87_jH+j#lNJs(3kNTg4DN!(by^-xVy?S7E-M4(y-6
zApD+d30~5VFyr4ozwRCh1Us86*Gs$O*X=ymd6xHNhegvE3CAg$EEHXH6mDogDRY??
zsPo8y>sedltOq3?tXJ=^VOY^JUZoVBN5+xihiD5ly_gI_x|mSiu2yB$)O0<(Z&ZN-
zJm|8SjwaC=4YD%+1K$(1$W?*2&L$%oo{Z@<`r5lh{#iG>G`TvSe4AVj&-(0UmrjOX
zMuTDhJzs@SPS>OYCgr$X9bO@|%4EaoKuM`;D4}`eNY|6oXmDCKtE^qn(Qy2WzHNhj
z2S~10eIp=6iQZNgO;u(H3IeSjJw|6k;_HE2$yu7E%>#YD9MefO_*EhTM10%fo#Cxr
zmUTn3_0~ci>y5-NanD8?+vfUpj@c?sr(4g%uDNy=kC{)`X-S*T$lWKNdvuo;NqP5-
z<p$_!w>CH6bjvez2%;_z4Zq+y=^6yr^8d}Vurx0~2eAU*ad|*!(Ris)&0SgjL5Wm3
z#;fl|t*g4&vV4`P2Es>4^(_;9!?uNEcJ;NJN0MuCgNnF5C)2TYuP5|*Yz0)cMZv`!
zT3SD+90hm-WobfmP&_(p%sZ$PxQiREsTk@~K5r|<-J$2&XdfL9TN7qy%r$7+c>LsY
zJ%Bx0IGV5=Fb_C8wk=MPC56ltdR13M{}#&zMZJ)J?|PMw)*u|$7QV}CZtEFYJ!@TL
zt|rH{9@S`Gwnd^*ntXxS%c?IVWP!`5Dw8&D`i9{7a~3Bj>(P#cF2uIR0sK8_V&Mm&
z>7b)oh`FZ;*9|y-;D4ejw45$8^EPWz#1_q{Kp$!pt!mXK<s+q}O3_Vdbbe_$=v!Q#
zR8^t5^oHkOM;9TD#{YtOqVBuS*sRx}Z<Bhg8Q+<`f4mbu!7|GLeN=c}H=J>Ni)6Y?
z<TNcBm34KL-HW-7zzr_O$KA|_Xs5X<+vc6Ab$7=R^~rS{%R$S-tm9y;_A!;NSH9V^
z-tTBch0Ky`&$N(uV-+i`God(3QA&aQpH@Nl5d1uA>m?^4`=N~;Hr2L)jXA;a?YFT%
zrkSF{TUi}u<>GJya43;_N(QDi<NP%OTqlm>C60_83sb^o4%avDLqb*6t~j9)`?iQP
zC5!BV>Sf!Y7T@8=MTNN`XQA+~he{#FF|L>?N5R7U;5(*eZ)NU}QFuu*@g%h9$=Fb6
z*rvosx%?$9C6#^1+VAmxJ@O3cpX<odoR^K~HAza+`5Yq(0$X!nF-lO;<}=Q#6A&*k
z2yLi>sjZo|?+KtH2cqG}(dS`ES4EvJ3amaF(hRby9ynoyiHxzVK=?+$W$^#c7+1rL
z29?`(fL-vpFl@xCi||ns^R&wEFjP^zl*IzSIkvj&O9ci2HwwU_1lSIC0?T_2+f@Mk
z9xICibxM15vk8%H|Cjgy@V&stHghxDqRkW7TUEwW^X)3*8n*YW%2>K(yvYIM`|e+I
CU~KgO

delta 113
zcmaDMx0s*NbRy$&Rx=$#9fOH$yMYWN9fQfXj4CW<I>tJa<Cx_pH#4dNIVKR!DMoc5
m#}vX5X3_+!h++Z>nnMH^Lj_+kX@ez=nYDnl`{n@F|I7fH$sSVx

-- 
2.43.0


^ permalink raw reply related

* [PATCH] util-linux dmesg add PRINTK_CALLER support Issue:2609
From: Edward Chron @ 2023-12-31  2:09 UTC (permalink / raw)
  To: util-linux; +Cc: colona, echron, echron

Submission to Project: util-linux
Open Incident: #2609 at github.com/util-linux/util-linux/issues/2609
Component: util-linux/sys-utils
File: dmesg.c
Code level patch applied against: 2.39.3 - latest code pulled from
           git.github.com:util-linux/util-linux.git
Revision: #1 on 2023/12/08 per Review from Karel Zak
Revision: #2 on 2023/12/12 Adjust line offsets for master update and
                           Add caller_id_size init to dmesg -K
Revision: #3 on 2023/12/12 Use of sizeof for cidbuf and limit search
                           for caller_id to dmesg prefix to msg text
Revision: #4 on 2023/12/15 Ensure SYSLOG and kmsg inputs have
                           caller_id_size set appropriately
Revision: #5 on 2023/12/24 Make caller_id width consistent with
                           makedumpfile
Revision: #6 on 2023/12/30 Use updated test naming convention

Add support to standard dmesg command for the optional Linux Kernel
debug CONFIG option PRINTK_CALLER which adds an optional dmesg field
that contains the Thread Id or CPU Id that is issuing the printk to
add the message to the kernel ring buffer. This makes debugging simpler
as dmesg entries for a specific thread or CPU can be recognized.

The dmesg -S using the old syslog interface supports printing the
PRINTK_CALLER field but currently standard dmesg does not support
printing the field if present. There are utilities that use dmesg and
so it would be optimal if dmesg supported PRINTK_CALLER as well.

The additional field provided by PRINTK_CALLER is only present
if it was configured for the Linux kernel where the dmesg command
is run. It is a debug option and not configured by default so the
dmesg output will only change for those kernels where the option was
configured when the kernel was built. For users who went to the
trouble to configure PRINTK_CALLER and have the extra field available
for debugging, having dmesg print the field is very helpful.

Size of the PRINTK_CALLER field is determined by the maximum number
tasks that can be run on the system which is limited by the value of
/proc/sys/kernel/pid_max as pid values are from 0 to value - 1.
This value determines the number of id digits needed by the caller id.
The PRINTK_CALLER field is printed as T<id> for a Task Id or C<id>
for a CPU Id for a printk in CPU context. The values are left space
padded and enclosed in parentheses such as: [    T123] or [     C16]

For consistency with dmesg -S which supports the PRINTK_CALLER field
the field is printed followed by a space. For JSON format output the
PRINTK_CALLER field is identified as caller as that is consistent with
it's naming in /dev/kmsg. No space padding is used to reduce space
consumed by the JSON output. So the output from the command on a system
with PRINTK_CALLER field enabled in the Linux .config file the dmesg
output appears as:

> dmesg
...
[  520.897104] [   T3919] usb 3-3: Product: USB 2.0 Hub

and

> dmesg -x
...
kern  :info  : [  520.897104] [   T3919] usb 3-3: Product: USB 2.0 Hub

and

> dmesg -J
...
      },{
         "pri": 6,
         "time":    520.897104,
         "caller": "T3919",
         "msg": "usb 3-3: Product: USB 2.0 Hub"
      },{

and

> dmesg -J -x
...
      },{
         "fac": "kern",
         "pri": "info",
         "time":   520.897104,
         "caller": "T3919",
         "msg": "usb 3-3: Product: USB 2.0 Hub"
      },{

>

For comparison:

> dmesg -S
...
[  520.897104] [ T3919] usb 3-3: Product: USB 2.0 Hub

and

> dmesg -S -x
...
kern  :info  : [  520.897104] [ T3919] usb 3-3: Product: USB 2.0 Hub

Note: When dmesg uses the old syslog interface the reserved space for
      the PRINTK_CALLER field is capped at 5 digits because 32-bit
      kernels are capped at 32768 as the max number of PIDs. However,
      64-bit systems are currently capped at 2^22 PIDs (0 - 4194303).
      The PID cap is set by PID_MAX_LIMIT but the system limit can be
      less so we use /proc/sys/kernel/pid_max to determine the size
      needed to hold the maximum PID value size for the current system.
      Many 64-bit systems support 2^22 PIDs (0 - 4194303) and you see:

> dmesg -x
...
kern  :info  : [  520.899558] [   T3919] hub 3-3:1.0: USB hub found
...
kern  :info  : [ 9830.456898] [  T98982] cgroup: fork rejected by pids ...
kern  :info  : [14301.158878] [ T137336] cgroup: fork rejected by pids ...
kern  :info  : [18980.803190] [T1637865] cgroup: fork rejected by pids ...

> dmesg -S -x
...
kern  :info  : [  520.899558] [ T3919] hub 3-3:1.0: USB hub found
...
kern  :info  : [ 9830.456898] [T98982] cgroup: fork rejected by pids ...
kern  :info  : [14301.158878] [T137336] cgroup: fork rejected by pids ...
kern  :info  : [18980.803190] [T1637865] cgroup: fork rejected by pids ...

This is the only difference seen with PRINTK_CALLER configured and
printing between the dmesg /dev/kmsg interface and the dmesg -S syslog
interface.

Tests naming has been revised based on naming convention Thomas used to
introduce dmest json tests. The naming of test and input files that
reside in tests/ts/dmeg include:

<name> are existing dmesg syslog interface tests and input files.
cid-<name> are dmesg syslog interface caller_id tests and input files.
json-<name> are dmesg kmsg interface tests and input files.
cid-json-<name> are dmesg kmsg interface caller_id tests and input files.

Resulting expected files match the test names.

Signed-off-by: Ivan Delalande <colona@arista.com>
Signed-off-by: Edward Chron <echron@arista.com>
---
 include/pathnames.h                    |   3 +
 sys-utils/dmesg.c                      | 128 ++++++++++++++++++++++++-
 tests/expected/dmesg/kmsg-file         | 126 ++++++++++++++++++++----
 tests/ts/dmesg/cid-input               | 106 ++++++++++++++++++++
 tests/ts/dmesg/cid-json                |  28 ++++++
 tests/ts/dmesg/cid-kmsg-colors         |  29 ++++++
 tests/ts/dmesg/cid-kmsg-console-levels |  36 +++++++
 tests/ts/dmesg/cid-kmsg-decode         |  28 ++++++
 tests/ts/dmesg/cid-kmsg-delta          |  28 ++++++
 tests/ts/dmesg/cid-kmsg-facilities     |  30 ++++++
 tests/ts/dmesg/cid-kmsg-indentation    |  40 ++++++++
 tests/ts/dmesg/cid-kmsg-input          | Bin 0 -> 4425 bytes
 tests/ts/dmesg/cid-kmsg-json           |  28 ++++++
 tests/ts/dmesg/cid-kmsg-limit          |  29 ++++++
 tests/ts/dmesg/cid-kmsg-newlines       | Bin 0 -> 152 bytes
 tests/ts/dmesg/kmsg-input              | Bin 1955 -> 3944 bytes
 16 files changed, 619 insertions(+), 20 deletions(-)
 create mode 100644 tests/ts/dmesg/cid-input
 create mode 100755 tests/ts/dmesg/cid-json
 create mode 100755 tests/ts/dmesg/cid-kmsg-colors
 create mode 100755 tests/ts/dmesg/cid-kmsg-console-levels
 create mode 100755 tests/ts/dmesg/cid-kmsg-decode
 create mode 100755 tests/ts/dmesg/cid-kmsg-delta
 create mode 100755 tests/ts/dmesg/cid-kmsg-facilities
 create mode 100755 tests/ts/dmesg/cid-kmsg-indentation
 create mode 100644 tests/ts/dmesg/cid-kmsg-input
 create mode 100755 tests/ts/dmesg/cid-kmsg-json
 create mode 100755 tests/ts/dmesg/cid-kmsg-limit
 create mode 100644 tests/ts/dmesg/cid-kmsg-newlines

diff --git a/include/pathnames.h b/include/pathnames.h
index caf0e63d4..81fa405f6 100644
--- a/include/pathnames.h
+++ b/include/pathnames.h
@@ -230,4 +230,7 @@
 /* cgroup path */
 #define _PATH_SYS_CGROUP	"/sys/fs/cgroup"
 
+/* Maximum number of PIDs system supports */
+#define _PATH_PROC_PIDMAX	"/proc/sys/kernel/pid_max"
+
 #endif /* PATHNAMES_H */
diff --git a/sys-utils/dmesg.c b/sys-utils/dmesg.c
index 77728b419..e27966b05 100644
--- a/sys-utils/dmesg.c
+++ b/sys-utils/dmesg.c
@@ -13,7 +13,9 @@
  */
 #include <stdio.h>
 #include <getopt.h>
+#include <stdbool.h>
 #include <stdlib.h>
+#include <string.h>
 #include <sys/klog.h>
 #include <sys/syslog.h>
 #include <sys/time.h>
@@ -41,6 +43,7 @@
 #include "mangle.h"
 #include "pager.h"
 #include "jsonwrt.h"
+#include "pathnames.h"
 
 /* Close the log.  Currently a NOP. */
 #define SYSLOG_ACTION_CLOSE          0
@@ -65,6 +68,12 @@
 /* Return size of the log buffer */
 #define SYSLOG_ACTION_SIZE_BUFFER   10
 
+#define PID_CHARS_MAX sizeof(stringify_value(LONG_MAX))
+#define PID_CHARS_DEFAULT sizeof(stringify_value(INT_MAX))
+#define SYSLOG_DEFAULT_CALLER_ID_CHARS sizeof(stringify_value(SHRT_MAX))-1
+#define DMESG_CALLER_PREFIX "caller="
+#define DMESG_CALLER_PREFIXSZ (sizeof(DMESG_CALLER_PREFIX)-1)
+
 /*
  * Color scheme
  */
@@ -233,6 +242,7 @@ struct dmesg_control {
 			force_prefix:1;	/* force timestamp and decode prefix
 					   on each line */
 	int		indent;		/* due to timestamps if newline */
+	size_t          caller_id_size;   /* PRINTK_CALLERID max field size */
 };
 
 struct dmesg_record {
@@ -242,6 +252,7 @@ struct dmesg_record {
 	int		level;
 	int		facility;
 	struct timeval  tv;
+	char		caller_id[PID_CHARS_MAX];
 
 	const char	*next;		/* buffer with next unparsed record */
 	size_t		next_size;	/* size of the next buffer */
@@ -254,6 +265,7 @@ struct dmesg_record {
 		(_r)->level = -1; \
 		(_r)->tv.tv_sec = 0; \
 		(_r)->tv.tv_usec = 0; \
+		(_r)->caller_id[0] = 0; \
 	} while (0)
 
 static int process_kmsg(struct dmesg_control *ctl);
@@ -551,6 +563,45 @@ static int get_syslog_buffer_size(void)
 	return n > 0 ? n : 0;
 }
 
+/*
+ * Get the number of characters needed to hold the maximum number
+ * of tasks this system supports. This size of string could hold
+ * a thread id large enough for the highest thread id.
+ * This is needed to determine the number of characters reserved for
+ * the PRINTK_CALLER field if it has been configured in the Linux Kernel.
+ *
+ * The number of digits sets the max value since the value can't exceed
+ * a value of that size. The /proc field defined by _PATH_PROC_PIDMAX
+ * holds the maximum number of PID values that may be ussed by the system,
+ * so 0 to that value minus one.
+ *
+ * For determining the size of the PRINTK_CALLER field, we make the safe
+ * assumption that the number of threads >= number of cpus. This because
+ * the PRINTK_CALLER field can hold either a thread id or a CPU id value.
+ *
+ * If we can't access the pid max kernel proc entry we assign a default
+ * field size of 5 characters as that is what the old syslog interface
+ * uses as the reserved field size. This is justified because 32-bit Linux
+ * systems are limited to PID values between (0-32767).
+ *
+ */
+static size_t max_threads_id_size(void)
+{
+	char taskmax[PID_CHARS_MAX] = {'\0'};
+	ssize_t rdsize;
+	int fd;
+
+	fd = open(_PATH_PROC_PIDMAX, O_RDONLY);
+	if (fd == -1)
+		return PID_CHARS_DEFAULT;
+
+	rdsize = read(fd, taskmax, sizeof(taskmax));
+	if (rdsize == -1)
+		return PID_CHARS_DEFAULT;
+
+	return strnlen(taskmax, sizeof(taskmax));
+}
+
 /*
  * Reads messages from regular file by mmap
  */
@@ -624,6 +675,8 @@ static ssize_t process_buffer(struct dmesg_control *ctl, char **buf)
 			ctl->bufsize = get_syslog_buffer_size();
 
 		n = read_syslog_buffer(ctl, buf);
+		/* Set number of PID characters for caller_id spacing */
+		ctl->caller_id_size = SYSLOG_DEFAULT_CALLER_ID_CHARS;
 		break;
 	case DMESG_METHOD_KMSG:
 		if (ctl->filename)
@@ -728,6 +781,39 @@ static const char *skip_item(const char *begin, const char *end, const char *sep
 	return begin;
 }
 
+/*
+ * Checks to see if the caller (caller id) field is present in the kmsg record.
+ * This is true if the PRINTK_CALLER config option has been set in the kernel.
+ *
+ * If the caller_id is found in the kmsg buffer then return the id and id type
+ * to the caller in dmesg caller_id. Returns string pointer to next value.
+ *
+ */
+static const char *parse_callerid(const char *p_str, const char *end,
+				  struct dmesg_record *p_drec)
+{
+	const char *p_after;
+	const char *p_next;
+	size_t cid_size;
+	char *p_scn;
+	char *p_cid;
+
+	/* Check for PRINTK_CALLER prefix, must be before msg text */
+	p_cid = strstr(p_str, DMESG_CALLER_PREFIX);
+	p_scn = strchr(p_str, ';');
+	if (p_cid != NULL && p_drec != NULL && p_scn != NULL && p_cid < p_scn) {
+		p_next = p_cid + DMESG_CALLER_PREFIXSZ;
+		p_after = skip_item(p_next, end, ",;");
+		cid_size = p_after - p_next;
+		if (cid_size < sizeof(p_drec->caller_id))
+			xstrncpy(p_drec->caller_id, p_next, cid_size);
+		else
+			return p_str;
+		return p_after;
+	}
+	return p_str;
+}
+
 /*
  * Parses one record from syslog(2) buffer
  */
@@ -795,8 +881,22 @@ static int get_next_syslog_record(struct dmesg_control *ctl,
 				begin++;
 		}
 
-		rec->mesg = begin;
-		rec->mesg_size = end - begin;
+		if (*begin == '[' && (*(begin + 1) == ' ' ||
+			(*(begin + 1) == 'T' || *(begin + 1) == 'C'))) {
+			const char *start = begin + 1;
+			size_t id_size;
+
+			start = start + strspn(start, " ");
+			begin = skip_item(begin, end, "]");
+			id_size = begin - start;
+			if (id_size < sizeof(rec->caller_id))
+				xstrncpy(rec->caller_id, start, id_size);
+			rec->mesg = begin + 1;
+			rec->mesg_size = end - begin - 1;
+		} else {
+			rec->mesg = begin;
+			rec->mesg_size = end - begin;
+		}
 
 		/* Don't count \n from the last message to the message size */
 		if (*end != '\n' && *(end - 1) == '\n')
@@ -1101,6 +1201,19 @@ full_output:
 			color_disable();
 	}
 
+	if (*rec->caller_id) {
+		if (ctl->json) {
+			ul_jsonwrt_value_s(&ctl->jfmt, "caller", rec->caller_id);
+		} else {
+			char cidbuf[PID_CHARS_MAX+3] = {'\0'};
+
+			sprintf(cidbuf, "[%*s] ",
+				(char)ctl->caller_id_size, rec->caller_id);
+			ctl->indent += strnlen(cidbuf, sizeof(cidbuf));
+			fputs(cidbuf, stdout);
+		}
+	}
+
 	/*
 	 * A kernel message may contain several lines of output, separated
 	 * by '\n'.  If the timestamp and decode outputs are forced then each
@@ -1284,7 +1397,10 @@ static int parse_kmsg_record(struct dmesg_control *ctl,
 		goto mesg;
 
 	/* D) optional fields (ignore) */
-	p = skip_item(p, end, ";");
+	p = skip_item(p, end, ",;");
+
+	/* Include optional PRINTK_CALLER field if it is present */
+	p = parse_callerid(p, end, rec);
 
 mesg:
 	/* E) message text */
@@ -1336,6 +1452,9 @@ static int process_kmsg(struct dmesg_control *ctl)
 	if (ctl->method != DMESG_METHOD_KMSG || ctl->kmsg < 0)
 		return -1;
 
+	/* Determine number of PID characters for caller_id spacing */
+	ctl->caller_id_size = max_threads_id_size();
+
 	/*
 	 * The very first read() call is done in kmsg_init() where we test
 	 * /dev/kmsg usability. The return code from the initial read() is
@@ -1446,6 +1565,7 @@ int main(int argc, char *argv[])
 		.kmsg = -1,
 		.time_fmt = DMESG_TIMEFTM_TIME,
 		.indent = 0,
+		.caller_id_size = 0,
 	};
 	int colormode = UL_COLORMODE_UNDEF;
 	enum {
@@ -1538,10 +1658,12 @@ int main(int argc, char *argv[])
 		case 'F':
 			ctl.filename = optarg;
 			ctl.method = DMESG_METHOD_MMAP;
+			ctl.caller_id_size = SYSLOG_DEFAULT_CALLER_ID_CHARS;
 			break;
 		case 'K':
 			ctl.filename = optarg;
 			ctl.method = DMESG_METHOD_KMSG;
+			ctl.caller_id_size = max_threads_id_size();
 			break;
 		case 'f':
 			ctl.fltr_fac = 1;
diff --git a/tests/expected/dmesg/kmsg-file b/tests/expected/dmesg/kmsg-file
index 54b5e612d..984588e3e 100644
--- a/tests/expected/dmesg/kmsg-file
+++ b/tests/expected/dmesg/kmsg-file
@@ -1,49 +1,77 @@
 {
    "dmesg": [
       {
-         "pri": 5,
+         "pri": 0,
          "time":     0.000000,
          "msg": "Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000"
       },{
-         "pri": 6,
-         "time":     0.000000,
+         "pri": 1,
+         "time":     0.000001,
          "msg": "Command line: initrd=\\ucode.img initrd=\\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system"
       },{
-         "pri": 6,
-         "time":     0.000000,
+         "pri": 2,
+         "time":     0.000002,
          "msg": "BIOS-provided physical RAM map:"
       },{
-         "pri": 6,
-         "time":     0.000000,
+         "pri": 3,
+         "time":     0.000003,
          "msg": "BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable"
       },{
-         "pri": 6,
-         "time":     0.000000,
+         "pri": 4,
+         "time":     0.000004,
          "msg": "BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved"
       },{
-         "pri": 6,
-         "time":     0.000000,
+         "pri": 5,
+         "time":     0.000005,
          "msg": "BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable"
       },{
          "pri": 6,
-         "time":     0.000000,
+         "time":     0.000006,
          "msg": "BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved"
       },{
-         "pri": 6,
-         "time":     0.000000,
+         "pri": 7,
+         "time":     0.000007,
          "msg": "BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable"
       },{
          "pri": 6,
-         "time":     0.000000,
+         "time":     0.000008,
          "msg": "BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS"
       },{
          "pri": 6,
-         "time":     0.000000,
+         "time":     0.000009,
          "msg": "BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable"
       },{
          "pri": 6,
-         "time":     0.000000,
+         "time":     0.000010,
          "msg": "BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved"
+      },{
+         "pri": 6,
+         "time":     0.201607,
+         "msg": "smp: Bringing up secondary CPUs ..."
+      },{
+         "pri": 6,
+         "time":     0.201607,
+         "msg": "smpboot: x86: Booting SMP configuration:"
+      },{
+         "pri": 4,
+         "time":     0.209670,
+         "msg": "  #1  #3  #5  #7"
+      },{
+         "pri": 6,
+         "time":     0.212630,
+         "msg": "smp: Brought up 1 node, 16 CPUs"
+      },{
+         "pri": 5,
+         "time":     0.215936,
+         "msg": "audit: type=2000 audit(1702926179.015:1): state=initialized audit_enabled=0 res=1"
+      },{
+         "pri": 6,
+         "time":     0.215937,
+         "msg": "thermal_sys: Registered thermal governor 'fair_share'"
+      },{
+         "pri": 4,
+         "time":     0.215966,
+         "msg": "ENERGY_PERF_BIAS: Set to 'normal', was 'performance'"
       },{
          "pri": 6,
          "time":     0.367657,
@@ -88,6 +116,70 @@
          "pri": 6,
          "time":     0.378461,
          "msg": "pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]"
+      },{
+         "pri": 13,
+         "time":     9.398562,
+         "msg": "user network daemon initialization complete"
+      },{
+         "pri": 30,
+         "time":    10.441520,
+         "msg": "systemd[1]: systemd 254.7-1.fc39 running in system mode"
+      },{
+         "pri": 30,
+         "time":    11.441524,
+         "msg": "systemd[1]: Detected architecture x86-64."
+      },{
+         "pri": 30,
+         "time":    12.441525,
+         "msg": "systemd[1]: Running in initrd."
+      },{
+         "pri": 30,
+         "time":    13.541598,
+         "msg": "systemd[1]: Hostname set to <catalina>."
+      },{
+         "pri": 6,
+         "time":    15.641860,
+         "msg": "usb 3-3: New USB device found, idVendor=1a40, idProduct=0101, bcdDevice= 1.11"
+      },{
+         "pri": 3,
+         "time":    16.690000,
+         "msg": "Serial bus multi instantiate pseudo device driver INT3515:00: error -ENXIO: IRQ index 1 not found."
+      },{
+         "pri": 3,
+         "time":    17.710000,
+         "msg": "snd_hda_intel 0000:00:1f.3: CORB reset timeout#2, CORBRP = 65535"
+      },{
+         "pri": 46,
+         "time":    18.820000,
+         "msg": "systemd-journald[723]: Received client request to flush runtime journal."
+      },{
+         "pri": 44,
+         "time":    20.840000,
+         "msg": "systemd-journald[723]: File /var/log/journal/a124ea923b144109a12d557d5ac53179/system.journal corrupted or uncleanly shut down, renaming and replacing."
+      },{
+         "pri": 46,
+         "time":    21.852348,
+         "msg": "systemd-journald[723]: /var/log/journal/ad7a2547ac0e4342a342e62a34a3eae4/user-1000.journal: Journal file uses a different sequence number ID, rotating."
+      },{
+         "pri": 4,
+         "time":    24.871100,
+         "msg": "PEFILE: Unsigned PE binary"
+      },{
+         "pri": 3,
+         "time":    33.918091,
+         "msg": "snd_hda_intel 0000:00:1f.3: CORB reset timeout#2, CORBRP = 65535"
+      },{
+         "pri": 6,
+         "time":   144.931785,
+         "msg": "usb 3-3.1: device firmware changed"
+      },{
+         "pri": 6,
+         "time":   145.953248,
+         "msg": "usb 3-3.1: USB disconnect, device number 44"
+      },{
+         "pri": 6,
+         "time":   147.981859,
+         "msg": "usb 3-3.1: New USB device found, idVendor=17ef, idProduct=6047, bcdDevice= 3.30"
       }
    ]
 }
diff --git a/tests/ts/dmesg/cid-input b/tests/ts/dmesg/cid-input
new file mode 100644
index 000000000..7dbd89d8f
--- /dev/null
+++ b/tests/ts/dmesg/cid-input
@@ -0,0 +1,106 @@
+<0>[    0.000000] [    T0] example[0]
+<1>[    1.000000] [    T1] example[1]
+<2>[    8.000000] [    T2] example[2]
+<3>[   27.000000] [    T3] example[3]
+<4>[   64.000000] [    T4] example[4]
+<5>[  125.000000] [    T5] example[5]
+<6>[  216.000000] [    T6] example[6]
+<7>[  343.000000] [    T7] example[7]
+<8>[  512.000000] [    T8] example[8]
+<9>[  729.000000] [    T9] example[9]
+<10>[ 1000.000000] [   T10] example[10]
+<11>[ 1331.000000] [   T11] example[11]
+<12>[ 1728.000000] [   T12] example[12]
+<13>[ 2197.000000] [   T13] example[13]
+<14>[ 2744.000000] [   T14] example[14]
+<15>[ 3375.000000] [   T15] example[15]
+<16>[ 4096.000000] [   T16] example[16]
+<17>[ 4913.000000] [   T17] example[17]
+<18>[ 5832.000000] [   T18] example[18]
+<19>[ 6859.000000] [   T19] example[19]
+<20>[ 8000.000000] [   T20] example[20]
+<21>[ 9261.000000] [   T21] example[21]
+<22>[10648.000000] [   T22] example[22]
+<23>[12167.000000] [   T23] example[23]
+<24>[13824.000000] [   T24] example[24]
+<25>[15625.000000] [   T25] example[25]
+<26>[17576.000000] [   T26] example[26]
+<27>[19683.000000] [   T27] example[27]
+<28>[21952.000000] [   T28] example[28]
+<29>[24389.000000] [   T29] example[29]
+<30>[27000.000000] [   T10] example[30]
+<31>[29791.000000] [   T31] example[31]
+<32>[32768.000000] [   T32] example[32]
+<33>[35937.000000] [   T33] example[33]
+<34>[39304.000000] [   T34] example[34]
+<35>[42875.000000] [   T35] example[35]
+<36>[46656.000000] [   T36] example[36]
+<37>[50653.000000] [   T37] example[37]
+<38>[54872.000000] [   T38] example[38]
+<39>[59319.000000] [   T39] example[39]
+<40>[64000.000000] [   T40] example[40]
+<41>[68921.000000] [   T41] example[41]
+<42>[74088.000000] [   T42] example[42]
+<43>[79507.000000] [   T43] example[43]
+<44>[85184.000000] [   T44] example[44]
+<45>[91125.000000] [   T45] example[45]
+<46>[97336.000000] [   T46] example[46]
+<47>[103823.000000] [   T47] example[47]
+<48>[110592.000000] [   T48] example[48]
+<49>[117649.000000] [   T49] example[49]
+<50>[125000.000000] [   T50] example[50]
+<51>[132651.000000] [   T51] example[51]
+<52>[140608.000000] [   T52] example[52]
+<53>[148877.000000] [   T53] example[53]
+<54>[157464.000000] [   T54] example[54]
+<55>[166375.000000] [   T55] example[55]
+<56>[175616.000000] [   T56] example[56]
+<57>[185193.000000] [   T57] example[57]
+<58>[195112.000000] [   T58] example[58]
+<59>[205379.000000] [   T59] example[59]
+<60>[216000.000000] [   T60] example[60]
+<61>[226981.000000] [   T61] example[61]
+<62>[238328.000000] [   T62] example[62]
+<63>[250047.000000] [   T63] example[63]
+<64>[262144.000000] [   T64] example[64]
+<65>[274625.000000] [   T65] example[65]
+<66>[287496.000000] [   T66] example[66]
+<67>[300763.000000] [   T67] example[67]
+<68>[314432.000000] [   T68] example[68]
+<69>[328509.000000] [   T69] example[69]
+<70>[343000.000000] [   T70] example[70]
+<71>[357911.000000] [   T71] example[71]
+<72>[373248.000000] [   T72] example[72]
+<73>[389017.000000] [   T73] example[73]
+<74>[405224.000000] [   T74] example[74]
+<75>[421875.000000] [   T75] example[75]
+<76>[438976.000000] [   T76] example[76]
+<77>[456533.000000] [   T77] example[77]
+<78>[474552.000000] [   T78] example[78]
+<79>[493039.000000] [   T79] example[79]
+<80>[512000.000000] [   T80] example[80]
+<81>[531441.000000] [   T81] example[81]
+<82>[551368.000000] [   T82] example[82]
+<83>[571787.000000] [   T83] example[83]
+<84>[592704.000000] [   T84] example[84]
+<85>[614125.000000] [   T85] example[85]
+<86>[636056.000000] [   T86] example[86]
+<87>[658503.000000] [   T87] example[87]
+<88>[681472.000000] [   T88] example[88]
+<89>[704969.000000] [   T89] example[89]
+<90>[729000.000000] [   T90] example[90]
+<91>[753571.000000] [   T91] example[91]
+<92>[778688.000000] [   T92] example[92]
+<93>[804357.000000] [   T93] example[93]
+<94>[830584.000000] [   T94] example[94]
+<95>[857375.000000] [   T95] example[95]
+<96>[884736.000000] [   T96] example[96]
+<97>[912673.000000] [   T97] example[97]
+<98>[941192.000000] [   T98] example[98]
+<99>[970299.000000] [   T99] example[99]
+<100>[1000000.000000] [  T100] example[100]
+<101>[1030301.000000] [  T101] example[101]
+<102>[1061208.000000] [  T102] example[102]
+<103>[1092727.000000] [  T103] example[103]
+<104>[1124864.000000] [  T104] example[104]
+<150>[4557523.000000] [  T105] example[105]
diff --git a/tests/ts/dmesg/cid-json b/tests/ts/dmesg/cid-json
new file mode 100755
index 000000000..78363793d
--- /dev/null
+++ b/tests/ts/dmesg/cid-json
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="cid-json"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG -J -F $TS_SELF/cid-input >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/cid-kmsg-colors b/tests/ts/dmesg/cid-kmsg-colors
new file mode 100755
index 000000000..90a593354
--- /dev/null
+++ b/tests/ts/dmesg/cid-kmsg-colors
@@ -0,0 +1,29 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="cid-kmsg-colors"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+ts_inhibit_custom_colorscheme
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG --color=always -K $TS_SELF/cid-kmsg-input -x >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/cid-kmsg-console-levels b/tests/ts/dmesg/cid-kmsg-console-levels
new file mode 100755
index 000000000..2cd445d05
--- /dev/null
+++ b/tests/ts/dmesg/cid-kmsg-console-levels
@@ -0,0 +1,36 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="cid-kmsg-levels"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+for I in {-1..8}; do
+	$TS_HELPER_DMESG -K $TS_SELF/cid-kmsg-input -l $I >> $TS_OUTPUT 2>/dev/null
+done
+
+$TS_HELPER_DMESG -K $TS_SELF/cid-kmsg-input -l err+ >> $TS_OUTPUT 2>/dev/null
+$TS_HELPER_DMESG -K $TS_SELF/cid-kmsg-input -l emerg+ >> $TS_OUTPUT 2>/dev/null
+$TS_HELPER_DMESG -K $TS_SELF/cid-kmsg-input -l +err >> $TS_OUTPUT 2>/dev/null
+$TS_HELPER_DMESG -K $TS_SELF/cid-kmsg-input -l +debug >> $TS_OUTPUT 2>/dev/null
+$TS_HELPER_DMESG -K $TS_SELF/cid-kmsg-input -l + 2>> $TS_OUTPUT >/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/cid-kmsg-decode b/tests/ts/dmesg/cid-kmsg-decode
new file mode 100755
index 000000000..316fb2079
--- /dev/null
+++ b/tests/ts/dmesg/cid-kmsg-decode
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="cid-kmsg-decode"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG -x -K $TS_SELF/cid-kmsg-input >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/cid-kmsg-delta b/tests/ts/dmesg/cid-kmsg-delta
new file mode 100755
index 000000000..64c2e6933
--- /dev/null
+++ b/tests/ts/dmesg/cid-kmsg-delta
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="cid-kmsg-delta"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG -d -K $TS_SELF/cid-kmsg-input >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/cid-kmsg-facilities b/tests/ts/dmesg/cid-kmsg-facilities
new file mode 100755
index 000000000..f50f2b73d
--- /dev/null
+++ b/tests/ts/dmesg/cid-kmsg-facilities
@@ -0,0 +1,30 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="cid-kmsg-facilities"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+for I in {-1..12}; do
+	$TS_HELPER_DMESG -K $TS_SELF/cid-kmsg-input -f $I -x >> $TS_OUTPUT 2>/dev/null
+done
+
+ts_finalize
diff --git a/tests/ts/dmesg/cid-kmsg-indentation b/tests/ts/dmesg/cid-kmsg-indentation
new file mode 100755
index 000000000..d45e1e30b
--- /dev/null
+++ b/tests/ts/dmesg/cid-kmsg-indentation
@@ -0,0 +1,40 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="cid-kmsg-indentation"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG -K $TS_SELF/cid-kmsg-newlines >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG -K $TS_SELF/cid-kmsg-newlines >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=delta --kmsg-file $TS_SELF/cid-kmsg-newlines >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=notime --kmsg-file $TS_SELF/cid-kmsg-newlines >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=reltime --kmsg-file $TS_SELF/cid-kmsg-newlines >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=ctime --kmsg-file $TS_SELF/cid-kmsg-newlines >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=iso --kmsg-file $TS_SELF/cid-kmsg-newlines >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+ts_finalize
diff --git a/tests/ts/dmesg/cid-kmsg-input b/tests/ts/dmesg/cid-kmsg-input
new file mode 100644
index 0000000000000000000000000000000000000000..8ebfb5170e647b57d1f3f504150ddb3def3b4247
GIT binary patch
literal 4425
zcmbtXYjfht5%p*PimuuZwrho~(dbP`#m4NK)Y>Ls@7*oOMGevbx>paPhadU%IU`^Z
z>)6RA43yAgPM_)NKHV}j1EZsbB1vS?yJg)kaaKRmqb$le&&bgo-Rg)UT(S<M<3!#3
zi#l!oozU?j4C(lDzkfoE>!!}gG)!)I2Gi*C^&KS<?&5fkiB+7GCuHgt(~T4Qz-V$c
zqS1ITxEkF~FTP)&T@Cwmm1i0m7G21&fg-~QOg~^geKhbnJYbp{JH}?WpQowFA_65D
zP@Kh85%vE5Y=?E2M^cZ|Mf+lNU!?Q0(=4I6T|7}(ysWB7KE|Q!o#J?!J*Lvg*op_`
zOIgV@h~hF7MMOoOSL;Vov0BOEbbbHuz|_>(G2`9y;mxG8D)PrTk`b+zFJ%lz)A;O)
zFgG|n;F=n{Db{+5^h_h5`&6c6Jga55Kb^fxzMRkJ4^)?8mdL{cOH*S9Xul8W&w;!T
zI0GI43t7tIQAURcwx-4o(s>t>HB{S>zEFrQj*h0r4$yrM(4V~qj5dHfj;^N04$^xU
zQoe>%Ufk#CX<iG^e-}`Bao>;roGV8@&{=;pr0cJf!vjb2F?Jl8@jfOG_c1M#+dq?J
zhK6qolf8op0Ou#3mSt}+cfNEqZWx+rFvn=Sl$qT!T?KSr#MuI0s#jFXFwY`Uyik91
zSCX#lYMC6#|9U!C(`U$?fSx@EIQXkzln4N29xv)bRL~rxg{5((Fnq@~v~VX*R+p4+
z&<Bp6ji1}tW5_#ZI(*L)_Lgp5FP4>J%P4~$XvCa`u8M4Kx|nMFyd96s>54jvL9}{V
z$({+HQFGy#xrXVR4s(6oV0OSx0xBy}$(|CGSS0a3k><^#Q<<rRjCzL3q#kQ{n%>&j
zo?G2+wUk9Fk|}f~ps`%UkedQPo9nd5p~hKW(9vAP#k5?CLLN0v;%oNK9(%7lxE_o@
zf1i#9<4@D`;n^ghiL9u~=?EyWbfnRfDCr2|HCGq1P~kb6#i2%y>)3k){jQ4PfRv(6
zC+Aar)E^r9=MnSu>&qe2N573>;aWb?Du0rNT5nz#A;d@_Vk;fbVQm31jkgiMUG}a2
zfQVgl9nRWoHrXr0@o!(=CWROUgw<AF)BHCO=Wj!}fN;6H2f;TGa1f0V-YQq3g`|7s
zu?ISi@>IkbDjEXnepZ+G*MUZytUcwe5!<R`T3r#YVj5kKj5EUvPzz~#GwBC(Goi9x
zt@5HO>3;BB$qW^y-=q<pO-5JLPx9~&94B&-$_!6kO@=hM7}MqGTjv&W%^wbFa(6!Y
zKDixS^^}=Ix)^*N_6NO>>MYn9UGwu5Kig?bm}$SoZ<UBj#TG@mERlEBmM+~-E=T>#
zyjmsog3boxU!-9fiiVF!-Kn05gniRZS&rhKXH}6Wa20k!ZjFzw2BgmWVkKsA5?3$u
z<#tRLqyDdQV&LRi_TJXHT@?n)ysT)p4g)0MdegCus*^!_Smt`>o>RT<DvYPCM}wy4
zXeMuyi|*r`HqC)5w&C2Rr#Or9r#<c)pxw@HF2H_^1hO9VoxQHg{}mEZQ~XqM`rk+}
zuDL#{BlkVq*=wPUZjC;KGFd(4#UB(2nW8KGA-7Gz!1kuAL{?B7lmL&LsEL-vY_nYt
zIP0$awCJ8aK(?EnE+W&mbhpFwdB}Y#>MT<w2|2pHPbmt<29;}!HK^_OilZp5ks8zs
zkO(VP1JEJI>VI8GRqi^Dh0@rtvovNlIBiMfsE#e1@s7y4o!w5hHO6f$&2NVqxArDq
zBIGiWN>t}Y^#2r!3Z*F%e{QO?hg!#M$6}td=N}uMo)PcxwdUPT&S~8a(>$-UNTWFV
z3YE!=9ur7HoQ{e-s>7;hFxBnP!sue%J`>X!Yl{nje?(x&JU=jP6mE{Kay8~Sz6!=x
zI&-Hxkp;?W6Y*)CR57*$g*HQttt72VSx5PnT~x#<k2Ji#<u+=vl1Nz;sFt0<^|#?o
zK*RChFg=pbO#@J^m!r4&ZN=&b$&cGB!46gt_R%gd*KK;-Het70X3=yRiD{fwGHDcE
zF=2BZ?(E-;&zpW4+YzTSud5HH)?6Krs7H=%a~tIx{h^Il8xOtzPyX<>``h^)l{FJd
zbnluRQ9PER#OfmolNcfoBmbx+1P4kpPwH~1B3hZG%{&BvWx)*kCBw6RHsil#=2M(V
zI(-zyX_7BaH&~|vaV&*z@|nsD!^e4K+iqlw(B^27Ht$9H=6PgkQPeAy9oU>Y3lk}_
z<b}#*U7<=m;kB<o)0C<NRBv;I#3qC|Q>2w|IGQKVHo4V~eam=@^lQG6E0FH42n~t8
z#1!~RM;!#0LRzOvX*z0ex0D0=>)PKmS02Fqk_1KZe2)GM?k<(P(L7OBr!y6U7g$4%
zhH%3gq%F;~JeL7=7cUm;js~BGUj_l)Wo5j`;F8gRW=PTEMTHqN5oetH%rpF!C|eMl
z|2xba4gD)*#Ik&BlGhTUKHDmQ&Vp@r&Eq0{LcdAjQe+Ff4z_xR*J<ths;a>NB*wC_
zWmx=f-F>rdpb;3nQs-F)oz%7lH?Fj-|I(5VORn!BGFmmX&)b$%Yx<s?xpLl?Gsm#p
QJvrk#H{NA~_oc&s0T4C|J^%m!

literal 0
HcmV?d00001

diff --git a/tests/ts/dmesg/cid-kmsg-json b/tests/ts/dmesg/cid-kmsg-json
new file mode 100755
index 000000000..ad1e3e785
--- /dev/null
+++ b/tests/ts/dmesg/cid-kmsg-json
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="cid-kmsg-json"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG -J -K $TS_SELF/cid-kmsg-input >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/cid-kmsg-limit b/tests/ts/dmesg/cid-kmsg-limit
new file mode 100755
index 000000000..884d4f8ce
--- /dev/null
+++ b/tests/ts/dmesg/cid-kmsg-limit
@@ -0,0 +1,29 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="cid-kmsg-limit"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG --since @1234567890.124 --until @1234567991 -K $TS_SELF/cid-kmsg-input \
+	>> $TS_OUTPUT 2> $TS_ERRLOG
+
+ts_finalize
diff --git a/tests/ts/dmesg/cid-kmsg-newlines b/tests/ts/dmesg/cid-kmsg-newlines
new file mode 100644
index 0000000000000000000000000000000000000000..574d2177796677b73f1efcf273005169ed832c60
GIT binary patch
literal 152
zcmXrjF#tkco#e!voYW%Q5CiL+%)C^Es??%<E(Svb9YY;M128~RV`!b1TFwPh$Hia-
tQeuRm#K^j&Jf91MLCT7`7>o^cjC71K)EQfsWE7>QazV)4{GwE-1^{d2D<=Q|

literal 0
HcmV?d00001

diff --git a/tests/ts/dmesg/kmsg-input b/tests/ts/dmesg/kmsg-input
index b000f4c951ccdcec96c820d37efc64ac8b68a93c..c08331dbf2bfdc9622105e120be99e448cfa89ea 100644
GIT binary patch
literal 3944
zcmbtXYg5};66G_$qO0-&sK`QBZz=1o1>*#71<=}%Ns6Uh*V47E89lsu@R(mer)3jN
zD9C0P;j&(R`rN*Ky4!|k;OKq$oEGgp-Kwfi%Yt0p)$N|F;-%;b+RymmKlrjcJD~kV
z9Mk@%!Qg;|rJK4S(=aW=H-tu?&aWs-@D$(2Fl^GSJ|I)Kg>D?sJ3*7Ph@$aucotnw
zPrjWWos9-`Ru&o=Hl3)rgCfHS%^(y3y*Kc;yCXC{dLIU5p35R35K$qeMcPzJ|KImc
z+{R_1^fX^=-|U{td|vlD;@#uwj^gTJ)g<aRjaB~;--pF*u8cygtgwEl8<mGiTF0_V
zs4B~5{YoxZD^(q?pYQIN8Xvt6$D@l$Z&j7IX`&KZEg$MMmKlwY&IlIa?vADLv3XJX
zrV-M0u5vQ&d12dsy=S)qHJ{IKsIBEJQ@cC1#>Y=!f;sS>!_0sJm`c^Ex>d>Uj-&DM
zHjwCOZ36|8aklul8Xs@M1hbbg$p+?$kEikRHjsJ=#L;=q$JhLyz;JY)$0wLu9H1LI
z8bl*H|1#O#akT))+kEC${2a(OE$2r*!qD*l77(o59~jxTvjKXFkgHjSp_zto4GvVD
zuR=Pm(qe&sYFAXNxGWM`J<uS!s!7*%UWElMZrjX|$syhQE{t)?wk$-L&eKI($p*Sd
zy4sp0*f4NCLyJEU3zptl_&E4@9kM{`3)8iDbsIKiyI3|%Mo<AAY9!o_4d<I>dU)Rn
zEY26%CMkF{4=dF-v3Tlk><iB@1Je~=pc}#o#X(4QBOBFc1*bAg|Ae}_SEs6AMI?QL
zle#ZDMy9{^!0~C8s>)?Hg;GNrt3?VySFqmPr$vb>SCkd)&1G6m>!qyJUbk>-&C_L`
z!}H<z)3<3f9Dkf1kB%lGO;kfoNqaB_{GLX4vZg)MggM_RVg_+F+k)I(&vlpzXH`gC
zou-rHsU8hRhW;rMfqs5E5_<I87_jH+j#lNJs(3kNTg4DN!(by^-xVy?S7E-M4(y-6
zApD+d30~5VFyr4ozwRCh1Us86*Gs$O*X=ymd6xHNhegvE3CAg$EEHXH6mDogDRY??
zsPo8y>sedltOq3?tXJ=^VOY^JUZoVBN5+xihiD5ly_gI_x|mSiu2yB$)O0<(Z&ZN-
zJm|8SjwaC=4YD%+1K$(1$W?*2&L$%oo{Z@<`r5lh{#iG>G`TvSe4AVj&-(0UmrjOX
zMuTDhJzs@SPS>OYCgr$X9bO@|%4EaoKuM`;D4}`eNY|6oXmDCKtE^qn(Qy2WzHNhj
z2S~10eIp=6iQZNgO;u(H3IeSjJw|6k;_HE2$yu7E%>#YD9MefO_*EhTM10%fo#Cxr
zmUTn3_0~ci>y5-NanD8?+vfUpj@c?sr(4g%uDNy=kC{)`X-S*T$lWKNdvuo;NqP5-
z<p$_!w>CH6bjvez2%;_z4Zq+y=^6yr^8d}Vurx0~2eAU*ad|*!(Ris)&0SgjL5Wm3
z#;fl|t*g4&vV4`P2Es>4^(_;9!?uNEcJ;NJN0MuCgNnF5C)2TYuP5|*Yz0)cMZv`!
zT3SD+90hm-WobfmP&_(p%sZ$PxQiREsTk@~K5r|<-J$2&XdfL9TN7qy%r$7+c>LsY
zJ%Bx0IGV5=Fb_C8wk=MPC56ltdR13M{}#&zMZJ)J?|PMw)*u|$7QV}CZtEFYJ!@TL
zt|rH{9@S`Gwnd^*ntXxS%c?IVWP!`5Dw8&D`i9{7a~3Bj>(P#cF2uIR0sK8_V&Mm&
z>7b)oh`FZ;*9|y-;D4ejw45$8^EPWz#1_q{Kp$!pt!mXK<s+q}O3_Vdbbe_$=v!Q#
zR8^t5^oHkOM;9TD#{YtOqVBuS*sRx}Z<Bhg8Q+<`f4mbu!7|GLeN=c}H=J>Ni)6Y?
z<TNcBm34KL-HW-7zzr_O$KA|_Xs5X<+vc6Ab$7=R^~rS{%R$S-tm9y;_A!;NSH9V^
z-tTBch0Ky`&$N(uV-+i`God(3QA&aQpH@Nl5d1uA>m?^4`=N~;Hr2L)jXA;a?YFT%
zrkSF{TUi}u<>GJya43;_N(QDi<NP%OTqlm>C60_83sb^o4%avDLqb*6t~j9)`?iQP
zC5!BV>Sf!Y7T@8=MTNN`XQA+~he{#FF|L>?N5R7U;5(*eZ)NU}QFuu*@g%h9$=Fb6
z*rvosx%?$9C6#^1+VAmxJ@O3cpX<odoR^K~HAza+`5Yq(0$X!nF-lO;<}=Q#6A&*k
z2yLi>sjZo|?+KtH2cqG}(dS`ES4EvJ3amaF(hRby9ynoyiHxzVK=?+$W$^#c7+1rL
z29?`(fL-vpFl@xCi||ns^R&wEFjP^zl*IzSIkvj&O9ci2HwwU_1lSIC0?T_2+f@Mk
z9xICibxM15vk8%H|Cjgy@V&stHghxDqRkW7TUEwW^X)3*8n*YW%2>K(yvYIM`|e+I
CU~KgO

delta 113
zcmaDMx0s*NbRy$&Rx=$#9fOH$yMYWN9fQfXj4CW<I>tJa<Cx_pH#4dNIVKR!DMoc5
m#}vX5X3_+!h++Z>nnMH^Lj_+kX@ez=nYDnl`{n@F|I7fH$sSVx

-- 
2.43.0


^ permalink raw reply related

* [PATCH] Add dmesg syslog interface caller_id tests Issue: #2637
From: Edward Chron @ 2023-12-30 22:22 UTC (permalink / raw)
  To: util-linux; +Cc: colona, echron, echron

Submission to Project: util-linux
Open Incident: #2637 at github.com/util-linux/util-linux/issues/2637
Component: util-linux/sys-utils
Files: tests/ts/dmesg syslog interface caller-id files, tests
       and related expected files
Testing on Fedora 39 with Linux-6.6.6 Kernel and CONFIG_PRINTK_CALLER
config option set.
Patch tested and generated with the latest util-linux code pulled.

For Issue #2609 Thomas and Zak pointed out the we need tests to verify
that the dmesg command works correctly and to allow us to compare the
results from PRINTK_CALLER id field tests provided by #2609 with the
standard (syslog interface) dmesg tests.

Currently, dmesg only has standard syslog interface tests even though
dmesg -S the syslog interface supports the caller_id field. There
are no syslog caller-id tests.

We would like syslog caller-id tests both to validate that the dmesg
code works correctly with the caller-id field being present and also
to compare against the addition of dmesg kmsg caller_id support added
by Issue #2609.

These tests are for the dmesg syslog interface with caller-id follow the
existing test structure for dmesg tests. The existing dmesg -F interface
is used to input our test files.

Until Thomas added a dmesg kmsg interface for json format testing
there were no dmesg tests except the tests for the generic dmesg
syslog tests. So we're naming the syslog caller-id tests to follow
the test naming convention that Thomas introduced.

For caller_id tests we prefix the test name with cid- abbreviating
the caller_id name to keep the names short. There is no unqiue
indentifier for syslog tests, so syslog tests are currently:

colors, console-levels, decode, delta, facilities, indentation,
limit, json

The cid versions of these test files are just prefixed with cid-

Note: The cid-json output given here is not strictly correct because
      the caller-id field is treated as part of the message text.
      This error is corrected by the patch for Issue #2609
      That patch has the code needed to produce the correct
      output for dmesg -J -F and has the corrected expected file
      which is tests/expected/dmesg/cid-json and that expected
      file should replace the expected file provided here.

Additional new dmesg tests are found with Issue #2663 which add
standard dmesg kmsg interface tests providing equivalent tests to
the existing dmesg syslog interface tests.

Also, Issue #2609 introduces dmesg kmsg interface caller-id tests
equivalent to the dmesg syslog interface with caller-id tests introduced
here along with the necessary dmesg kmsg interface caller-id support
needed to accomodate the PRINTK_CALLER id field.

Just for reference, on a Linux system with the CONFIG_PRINTK_CALLER
configuration option set the output from dmesg -S looks like:

    [  520.899558] [   T3919] hub 3-3:1.0: USB hub found

on a system where the PRINTK_CALLER configuration option is not set the
output looks like:

    [  520.899558] hub 3-3:1.0: USB hub found

the additional field specifies either a Thread Id or CPU id depending on
the context of the task or thread at the time the printk that added the
message to the kernel ring buffer was executed.

Signed-off-by: Ivan Delalande <colona@arista.com>
Signed-off-by: Edward Chron <echron@arista.com>
---
 tests/expected/dmesg/cid-colors         | 106 ++++++
 tests/expected/dmesg/cid-console-levels | 253 ++++++++++++++
 tests/expected/dmesg/cid-decode         | 106 ++++++
 tests/expected/dmesg/cid-delta          | 106 ++++++
 tests/expected/dmesg/cid-facilities     | 104 ++++++
 tests/expected/dmesg/cid-indentation    |  35 ++
 tests/expected/dmesg/cid-json           | 429 ++++++++++++++++++++++++
 tests/expected/dmesg/cid-limit          |   4 +
 tests/ts/dmesg/cid-colors               |  29 ++
 tests/ts/dmesg/cid-console-levels       |  36 ++
 tests/ts/dmesg/cid-decode               |  28 ++
 tests/ts/dmesg/cid-delta                |  27 ++
 tests/ts/dmesg/cid-facilities           |  30 ++
 tests/ts/dmesg/cid-indentation          |  40 +++
 tests/ts/dmesg/cid-input                | 106 ++++++
 tests/ts/dmesg/cid-json                 |  28 ++
 tests/ts/dmesg/cid-limit                |  29 ++
 tests/ts/dmesg/cid-newlines             |   5 +
 18 files changed, 1501 insertions(+)
 create mode 100644 tests/expected/dmesg/cid-colors
 create mode 100644 tests/expected/dmesg/cid-console-levels
 create mode 100644 tests/expected/dmesg/cid-decode
 create mode 100644 tests/expected/dmesg/cid-delta
 create mode 100644 tests/expected/dmesg/cid-facilities
 create mode 100644 tests/expected/dmesg/cid-indentation
 create mode 100644 tests/expected/dmesg/cid-json
 create mode 100644 tests/expected/dmesg/cid-limit
 create mode 100755 tests/ts/dmesg/cid-colors
 create mode 100755 tests/ts/dmesg/cid-console-levels
 create mode 100755 tests/ts/dmesg/cid-decode
 create mode 100755 tests/ts/dmesg/cid-delta
 create mode 100755 tests/ts/dmesg/cid-facilities
 create mode 100755 tests/ts/dmesg/cid-indentation
 create mode 100644 tests/ts/dmesg/cid-input
 create mode 100755 tests/ts/dmesg/cid-json
 create mode 100755 tests/ts/dmesg/cid-limit
 create mode 100644 tests/ts/dmesg/cid-newlines

diff --git a/tests/expected/dmesg/cid-colors b/tests/expected/dmesg/cid-colors
new file mode 100644
index 000000000..1ddbb4449
--- /dev/null
+++ b/tests/expected/dmesg/cid-colors
@@ -0,0 +1,106 @@
+kern  :emerg : ^[[32m[    0.000000] ^[[0m[    T0] example[0]
+kern  :alert : ^[[32m[    1.000000] ^[[0m^[[7m^[[31m[    T1] example[1]^[[0m
+kern  :crit  : ^[[32m[    8.000000] ^[[0m^[[1m^[[31m[    T2] example[2]^[[0m
+kern  :err   : ^[[32m[   27.000000] ^[[0m^[[31m[    T3] example[3]^[[0m
+kern  :warn  : ^[[32m[   64.000000] ^[[0m^[[1m[    T4] example[4]^[[0m
+kern  :notice: ^[[32m[  125.000000] ^[[0m[    T5] example[5]
+kern  :info  : ^[[32m[  216.000000] ^[[0m[    T6] example[6]
+kern  :debug : ^[[32m[  343.000000] ^[[0m[    T7] example[7]
+user  :emerg : ^[[32m[  512.000000] ^[[0m[    T8] example[8]
+user  :alert : ^[[32m[  729.000000] ^[[0m^[[7m^[[31m[    T9] example[9]^[[0m
+user  :crit  : ^[[32m[ 1000.000000] ^[[0m^[[1m^[[31m[   T10] example[10]^[[0m
+user  :err   : ^[[32m[ 1331.000000] ^[[0m^[[31m[   T11] example[11]^[[0m
+user  :warn  : ^[[32m[ 1728.000000] ^[[0m^[[1m[   T12] example[12]^[[0m
+user  :notice: ^[[32m[ 2197.000000] ^[[0m[   T13] example[13]
+user  :info  : ^[[32m[ 2744.000000] ^[[0m[   T14] example[14]
+user  :debug : ^[[32m[ 3375.000000] ^[[0m[   T15] example[15]
+mail  :emerg : ^[[32m[ 4096.000000] ^[[0m[   T16] example[16]
+mail  :alert : ^[[32m[ 4913.000000] ^[[0m^[[7m^[[31m[   T17] example[17]^[[0m
+mail  :crit  : ^[[32m[ 5832.000000] ^[[0m^[[1m^[[31m[   T18] example[18]^[[0m
+mail  :err   : ^[[32m[ 6859.000000] ^[[0m^[[31m[   T19] example[19]^[[0m
+mail  :warn  : ^[[32m[ 8000.000000] ^[[0m^[[1m[   T20] example[20]^[[0m
+mail  :notice: ^[[32m[ 9261.000000] ^[[0m[   T21] example[21]
+mail  :info  : ^[[32m[10648.000000] ^[[0m[   T22] example[22]
+mail  :debug : ^[[32m[12167.000000] ^[[0m[   T23] example[23]
+daemon:emerg : ^[[32m[13824.000000] ^[[0m[   T24] example[24]
+daemon:alert : ^[[32m[15625.000000] ^[[0m^[[7m^[[31m[   T25] example[25]^[[0m
+daemon:crit  : ^[[32m[17576.000000] ^[[0m^[[1m^[[31m[   T26] example[26]^[[0m
+daemon:err   : ^[[32m[19683.000000] ^[[0m^[[31m[   T27] example[27]^[[0m
+daemon:warn  : ^[[32m[21952.000000] ^[[0m^[[1m[   T28] example[28]^[[0m
+daemon:notice: ^[[32m[24389.000000] ^[[0m[   T29] example[29]
+daemon:info  : ^[[32m[27000.000000] ^[[0m[   T10] example[30]
+daemon:debug : ^[[32m[29791.000000] ^[[0m[   T31] example[31]
+auth  :emerg : ^[[32m[32768.000000] ^[[0m[   T32] example[32]
+auth  :alert : ^[[32m[35937.000000] ^[[0m^[[7m^[[31m[   T33] example[33]^[[0m
+auth  :crit  : ^[[32m[39304.000000] ^[[0m^[[1m^[[31m[   T34] example[34]^[[0m
+auth  :err   : ^[[32m[42875.000000] ^[[0m^[[31m[   T35] example[35]^[[0m
+auth  :warn  : ^[[32m[46656.000000] ^[[0m^[[1m[   T36] example[36]^[[0m
+auth  :notice: ^[[32m[50653.000000] ^[[0m[   T37] example[37]
+auth  :info  : ^[[32m[54872.000000] ^[[0m[   T38] example[38]
+auth  :debug : ^[[32m[59319.000000] ^[[0m[   T39] example[39]
+syslog:emerg : ^[[32m[64000.000000] ^[[0m[   T40] example[40]
+syslog:alert : ^[[32m[68921.000000] ^[[0m^[[7m^[[31m[   T41] example[41]^[[0m
+syslog:crit  : ^[[32m[74088.000000] ^[[0m^[[1m^[[31m[   T42] example[42]^[[0m
+syslog:err   : ^[[32m[79507.000000] ^[[0m^[[31m[   T43] example[43]^[[0m
+syslog:warn  : ^[[32m[85184.000000] ^[[0m^[[1m[   T44] example[44]^[[0m
+syslog:notice: ^[[32m[91125.000000] ^[[0m[   T45] example[45]
+syslog:info  : ^[[32m[97336.000000] ^[[0m[   T46] example[46]
+syslog:debug : ^[[32m[103823.000000] ^[[0m[   T47] example[47]
+lpr   :emerg : ^[[32m[110592.000000] ^[[0m[   T48] example[48]
+lpr   :alert : ^[[32m[117649.000000] ^[[0m^[[7m^[[31m[   T49] example[49]^[[0m
+lpr   :crit  : ^[[32m[125000.000000] ^[[0m^[[1m^[[31m[   T50] example[50]^[[0m
+lpr   :err   : ^[[32m[132651.000000] ^[[0m^[[31m[   T51] example[51]^[[0m
+lpr   :warn  : ^[[32m[140608.000000] ^[[0m^[[1m[   T52] example[52]^[[0m
+lpr   :notice: ^[[32m[148877.000000] ^[[0m[   T53] example[53]
+lpr   :info  : ^[[32m[157464.000000] ^[[0m[   T54] example[54]
+lpr   :debug : ^[[32m[166375.000000] ^[[0m[   T55] example[55]
+news  :emerg : ^[[32m[175616.000000] ^[[0m[   T56] example[56]
+news  :alert : ^[[32m[185193.000000] ^[[0m^[[7m^[[31m[   T57] example[57]^[[0m
+news  :crit  : ^[[32m[195112.000000] ^[[0m^[[1m^[[31m[   T58] example[58]^[[0m
+news  :err   : ^[[32m[205379.000000] ^[[0m^[[31m[   T59] example[59]^[[0m
+news  :warn  : ^[[32m[216000.000000] ^[[0m^[[1m[   T60] example[60]^[[0m
+news  :notice: ^[[32m[226981.000000] ^[[0m[   T61] example[61]
+news  :info  : ^[[32m[238328.000000] ^[[0m[   T62] example[62]
+news  :debug : ^[[32m[250047.000000] ^[[0m[   T63] example[63]
+uucp  :emerg : ^[[32m[262144.000000] ^[[0m[   T64] example[64]
+uucp  :alert : ^[[32m[274625.000000] ^[[0m^[[7m^[[31m[   T65] example[65]^[[0m
+uucp  :crit  : ^[[32m[287496.000000] ^[[0m^[[1m^[[31m[   T66] example[66]^[[0m
+uucp  :err   : ^[[32m[300763.000000] ^[[0m^[[31m[   T67] example[67]^[[0m
+uucp  :warn  : ^[[32m[314432.000000] ^[[0m^[[1m[   T68] example[68]^[[0m
+uucp  :notice: ^[[32m[328509.000000] ^[[0m[   T69] example[69]
+uucp  :info  : ^[[32m[343000.000000] ^[[0m[   T70] example[70]
+uucp  :debug : ^[[32m[357911.000000] ^[[0m[   T71] example[71]
+cron  :emerg : ^[[32m[373248.000000] ^[[0m[   T72] example[72]
+cron  :alert : ^[[32m[389017.000000] ^[[0m^[[7m^[[31m[   T73] example[73]^[[0m
+cron  :crit  : ^[[32m[405224.000000] ^[[0m^[[1m^[[31m[   T74] example[74]^[[0m
+cron  :err   : ^[[32m[421875.000000] ^[[0m^[[31m[   T75] example[75]^[[0m
+cron  :warn  : ^[[32m[438976.000000] ^[[0m^[[1m[   T76] example[76]^[[0m
+cron  :notice: ^[[32m[456533.000000] ^[[0m[   T77] example[77]
+cron  :info  : ^[[32m[474552.000000] ^[[0m[   T78] example[78]
+cron  :debug : ^[[32m[493039.000000] ^[[0m[   T79] example[79]
+authpriv:emerg : ^[[32m[512000.000000] ^[[0m[   T80] example[80]
+authpriv:alert : ^[[32m[531441.000000] ^[[0m^[[7m^[[31m[   T81] example[81]^[[0m
+authpriv:crit  : ^[[32m[551368.000000] ^[[0m^[[1m^[[31m[   T82] example[82]^[[0m
+authpriv:err   : ^[[32m[571787.000000] ^[[0m^[[31m[   T83] example[83]^[[0m
+authpriv:warn  : ^[[32m[592704.000000] ^[[0m^[[1m[   T84] example[84]^[[0m
+authpriv:notice: ^[[32m[614125.000000] ^[[0m[   T85] example[85]
+authpriv:info  : ^[[32m[636056.000000] ^[[0m[   T86] example[86]
+authpriv:debug : ^[[32m[658503.000000] ^[[0m[   T87] example[87]
+ftp   :emerg : ^[[32m[681472.000000] ^[[0m[   T88] example[88]
+ftp   :alert : ^[[32m[704969.000000] ^[[0m^[[7m^[[31m[   T89] example[89]^[[0m
+ftp   :crit  : ^[[32m[729000.000000] ^[[0m^[[1m^[[31m[   T90] example[90]^[[0m
+ftp   :err   : ^[[32m[753571.000000] ^[[0m^[[31m[   T91] example[91]^[[0m
+ftp   :warn  : ^[[32m[778688.000000] ^[[0m^[[1m[   T92] example[92]^[[0m
+ftp   :notice: ^[[32m[804357.000000] ^[[0m[   T93] example[93]
+ftp   :info  : ^[[32m[830584.000000] ^[[0m[   T94] example[94]
+ftp   :debug : ^[[32m[857375.000000] ^[[0m[   T95] example[95]
+res0  :emerg : ^[[32m[884736.000000] ^[[0m[   T96] example[96]
+res0  :alert : ^[[32m[912673.000000] ^[[0m^[[7m^[[31m[   T97] example[97]^[[0m
+res0  :crit  : ^[[32m[941192.000000] ^[[0m^[[1m^[[31m[   T98] example[98]^[[0m
+res0  :err   : ^[[32m[970299.000000] ^[[0m^[[31m[   T99] example[99]^[[0m
+res0  :warn  : ^[[32m[1000000.000000] ^[[0m^[[1m[  T100] example[100]^[[0m
+res0  :notice: ^[[32m[1030301.000000] ^[[0m[  T101] example[101]
+res0  :info  : ^[[32m[1061208.000000] ^[[0m[  T102] example[102]
+res0  :debug : ^[[32m[1092727.000000] ^[[0m[  T103] example[103]
+res1  :emerg : ^[[32m[1124864.000000] ^[[0m[  T104] example[104]
+local2:info  : ^[[32m[4557523.000000] ^[[0m[  T105] example[105]
diff --git a/tests/expected/dmesg/cid-console-levels b/tests/expected/dmesg/cid-console-levels
new file mode 100644
index 000000000..9fe993b20
--- /dev/null
+++ b/tests/expected/dmesg/cid-console-levels
@@ -0,0 +1,253 @@
+[    0.000000] [    T0] example[0]
+[  512.000000] [    T8] example[8]
+[ 4096.000000] [   T16] example[16]
+[13824.000000] [   T24] example[24]
+[32768.000000] [   T32] example[32]
+[64000.000000] [   T40] example[40]
+[110592.000000] [   T48] example[48]
+[175616.000000] [   T56] example[56]
+[262144.000000] [   T64] example[64]
+[373248.000000] [   T72] example[72]
+[512000.000000] [   T80] example[80]
+[681472.000000] [   T88] example[88]
+[884736.000000] [   T96] example[96]
+[1124864.000000] [  T104] example[104]
+[    1.000000] [    T1] example[1]
+[  729.000000] [    T9] example[9]
+[ 4913.000000] [   T17] example[17]
+[15625.000000] [   T25] example[25]
+[35937.000000] [   T33] example[33]
+[68921.000000] [   T41] example[41]
+[117649.000000] [   T49] example[49]
+[185193.000000] [   T57] example[57]
+[274625.000000] [   T65] example[65]
+[389017.000000] [   T73] example[73]
+[531441.000000] [   T81] example[81]
+[704969.000000] [   T89] example[89]
+[912673.000000] [   T97] example[97]
+[    8.000000] [    T2] example[2]
+[ 1000.000000] [   T10] example[10]
+[ 5832.000000] [   T18] example[18]
+[17576.000000] [   T26] example[26]
+[39304.000000] [   T34] example[34]
+[74088.000000] [   T42] example[42]
+[125000.000000] [   T50] example[50]
+[195112.000000] [   T58] example[58]
+[287496.000000] [   T66] example[66]
+[405224.000000] [   T74] example[74]
+[551368.000000] [   T82] example[82]
+[729000.000000] [   T90] example[90]
+[941192.000000] [   T98] example[98]
+[   27.000000] [    T3] example[3]
+[ 1331.000000] [   T11] example[11]
+[ 6859.000000] [   T19] example[19]
+[19683.000000] [   T27] example[27]
+[42875.000000] [   T35] example[35]
+[79507.000000] [   T43] example[43]
+[132651.000000] [   T51] example[51]
+[205379.000000] [   T59] example[59]
+[300763.000000] [   T67] example[67]
+[421875.000000] [   T75] example[75]
+[571787.000000] [   T83] example[83]
+[753571.000000] [   T91] example[91]
+[970299.000000] [   T99] example[99]
+[   64.000000] [    T4] example[4]
+[ 1728.000000] [   T12] example[12]
+[ 8000.000000] [   T20] example[20]
+[21952.000000] [   T28] example[28]
+[46656.000000] [   T36] example[36]
+[85184.000000] [   T44] example[44]
+[140608.000000] [   T52] example[52]
+[216000.000000] [   T60] example[60]
+[314432.000000] [   T68] example[68]
+[438976.000000] [   T76] example[76]
+[592704.000000] [   T84] example[84]
+[778688.000000] [   T92] example[92]
+[1000000.000000] [  T100] example[100]
+[  125.000000] [    T5] example[5]
+[ 2197.000000] [   T13] example[13]
+[ 9261.000000] [   T21] example[21]
+[24389.000000] [   T29] example[29]
+[50653.000000] [   T37] example[37]
+[91125.000000] [   T45] example[45]
+[148877.000000] [   T53] example[53]
+[226981.000000] [   T61] example[61]
+[328509.000000] [   T69] example[69]
+[456533.000000] [   T77] example[77]
+[614125.000000] [   T85] example[85]
+[804357.000000] [   T93] example[93]
+[1030301.000000] [  T101] example[101]
+[  216.000000] [    T6] example[6]
+[ 2744.000000] [   T14] example[14]
+[10648.000000] [   T22] example[22]
+[27000.000000] [   T10] example[30]
+[54872.000000] [   T38] example[38]
+[97336.000000] [   T46] example[46]
+[157464.000000] [   T54] example[54]
+[238328.000000] [   T62] example[62]
+[343000.000000] [   T70] example[70]
+[474552.000000] [   T78] example[78]
+[636056.000000] [   T86] example[86]
+[830584.000000] [   T94] example[94]
+[1061208.000000] [  T102] example[102]
+[4557523.000000] [  T105] example[105]
+[  343.000000] [    T7] example[7]
+[ 3375.000000] [   T15] example[15]
+[12167.000000] [   T23] example[23]
+[29791.000000] [   T31] example[31]
+[59319.000000] [   T39] example[39]
+[103823.000000] [   T47] example[47]
+[166375.000000] [   T55] example[55]
+[250047.000000] [   T63] example[63]
+[357911.000000] [   T71] example[71]
+[493039.000000] [   T79] example[79]
+[658503.000000] [   T87] example[87]
+[857375.000000] [   T95] example[95]
+[1092727.000000] [  T103] example[103]
+[    0.000000] [    T0] example[0]
+[    1.000000] [    T1] example[1]
+[    8.000000] [    T2] example[2]
+[   27.000000] [    T3] example[3]
+[  512.000000] [    T8] example[8]
+[  729.000000] [    T9] example[9]
+[ 1000.000000] [   T10] example[10]
+[ 1331.000000] [   T11] example[11]
+[ 4096.000000] [   T16] example[16]
+[ 4913.000000] [   T17] example[17]
+[ 5832.000000] [   T18] example[18]
+[ 6859.000000] [   T19] example[19]
+[13824.000000] [   T24] example[24]
+[15625.000000] [   T25] example[25]
+[17576.000000] [   T26] example[26]
+[19683.000000] [   T27] example[27]
+[32768.000000] [   T32] example[32]
+[35937.000000] [   T33] example[33]
+[39304.000000] [   T34] example[34]
+[42875.000000] [   T35] example[35]
+[64000.000000] [   T40] example[40]
+[68921.000000] [   T41] example[41]
+[74088.000000] [   T42] example[42]
+[79507.000000] [   T43] example[43]
+[110592.000000] [   T48] example[48]
+[117649.000000] [   T49] example[49]
+[125000.000000] [   T50] example[50]
+[132651.000000] [   T51] example[51]
+[175616.000000] [   T56] example[56]
+[185193.000000] [   T57] example[57]
+[195112.000000] [   T58] example[58]
+[205379.000000] [   T59] example[59]
+[262144.000000] [   T64] example[64]
+[274625.000000] [   T65] example[65]
+[287496.000000] [   T66] example[66]
+[300763.000000] [   T67] example[67]
+[373248.000000] [   T72] example[72]
+[389017.000000] [   T73] example[73]
+[405224.000000] [   T74] example[74]
+[421875.000000] [   T75] example[75]
+[512000.000000] [   T80] example[80]
+[531441.000000] [   T81] example[81]
+[551368.000000] [   T82] example[82]
+[571787.000000] [   T83] example[83]
+[681472.000000] [   T88] example[88]
+[704969.000000] [   T89] example[89]
+[729000.000000] [   T90] example[90]
+[753571.000000] [   T91] example[91]
+[884736.000000] [   T96] example[96]
+[912673.000000] [   T97] example[97]
+[941192.000000] [   T98] example[98]
+[970299.000000] [   T99] example[99]
+[1124864.000000] [  T104] example[104]
+[    0.000000] [    T0] example[0]
+[  512.000000] [    T8] example[8]
+[ 4096.000000] [   T16] example[16]
+[13824.000000] [   T24] example[24]
+[32768.000000] [   T32] example[32]
+[64000.000000] [   T40] example[40]
+[110592.000000] [   T48] example[48]
+[175616.000000] [   T56] example[56]
+[262144.000000] [   T64] example[64]
+[373248.000000] [   T72] example[72]
+[512000.000000] [   T80] example[80]
+[681472.000000] [   T88] example[88]
+[884736.000000] [   T96] example[96]
+[1124864.000000] [  T104] example[104]
+[   27.000000] [    T3] example[3]
+[   64.000000] [    T4] example[4]
+[  125.000000] [    T5] example[5]
+[  216.000000] [    T6] example[6]
+[  343.000000] [    T7] example[7]
+[ 1331.000000] [   T11] example[11]
+[ 1728.000000] [   T12] example[12]
+[ 2197.000000] [   T13] example[13]
+[ 2744.000000] [   T14] example[14]
+[ 3375.000000] [   T15] example[15]
+[ 6859.000000] [   T19] example[19]
+[ 8000.000000] [   T20] example[20]
+[ 9261.000000] [   T21] example[21]
+[10648.000000] [   T22] example[22]
+[12167.000000] [   T23] example[23]
+[19683.000000] [   T27] example[27]
+[21952.000000] [   T28] example[28]
+[24389.000000] [   T29] example[29]
+[27000.000000] [   T10] example[30]
+[29791.000000] [   T31] example[31]
+[42875.000000] [   T35] example[35]
+[46656.000000] [   T36] example[36]
+[50653.000000] [   T37] example[37]
+[54872.000000] [   T38] example[38]
+[59319.000000] [   T39] example[39]
+[79507.000000] [   T43] example[43]
+[85184.000000] [   T44] example[44]
+[91125.000000] [   T45] example[45]
+[97336.000000] [   T46] example[46]
+[103823.000000] [   T47] example[47]
+[132651.000000] [   T51] example[51]
+[140608.000000] [   T52] example[52]
+[148877.000000] [   T53] example[53]
+[157464.000000] [   T54] example[54]
+[166375.000000] [   T55] example[55]
+[205379.000000] [   T59] example[59]
+[216000.000000] [   T60] example[60]
+[226981.000000] [   T61] example[61]
+[238328.000000] [   T62] example[62]
+[250047.000000] [   T63] example[63]
+[300763.000000] [   T67] example[67]
+[314432.000000] [   T68] example[68]
+[328509.000000] [   T69] example[69]
+[343000.000000] [   T70] example[70]
+[357911.000000] [   T71] example[71]
+[421875.000000] [   T75] example[75]
+[438976.000000] [   T76] example[76]
+[456533.000000] [   T77] example[77]
+[474552.000000] [   T78] example[78]
+[493039.000000] [   T79] example[79]
+[571787.000000] [   T83] example[83]
+[592704.000000] [   T84] example[84]
+[614125.000000] [   T85] example[85]
+[636056.000000] [   T86] example[86]
+[658503.000000] [   T87] example[87]
+[753571.000000] [   T91] example[91]
+[778688.000000] [   T92] example[92]
+[804357.000000] [   T93] example[93]
+[830584.000000] [   T94] example[94]
+[857375.000000] [   T95] example[95]
+[970299.000000] [   T99] example[99]
+[1000000.000000] [  T100] example[100]
+[1030301.000000] [  T101] example[101]
+[1061208.000000] [  T102] example[102]
+[1092727.000000] [  T103] example[103]
+[4557523.000000] [  T105] example[105]
+[  343.000000] [    T7] example[7]
+[ 3375.000000] [   T15] example[15]
+[12167.000000] [   T23] example[23]
+[29791.000000] [   T31] example[31]
+[59319.000000] [   T39] example[39]
+[103823.000000] [   T47] example[47]
+[166375.000000] [   T55] example[55]
+[250047.000000] [   T63] example[63]
+[357911.000000] [   T71] example[71]
+[493039.000000] [   T79] example[79]
+[658503.000000] [   T87] example[87]
+[857375.000000] [   T95] example[95]
+[1092727.000000] [  T103] example[103]
+test_dmesg: unknown level '+'
diff --git a/tests/expected/dmesg/cid-decode b/tests/expected/dmesg/cid-decode
new file mode 100644
index 000000000..757b9284d
--- /dev/null
+++ b/tests/expected/dmesg/cid-decode
@@ -0,0 +1,106 @@
+kern  :emerg : [    0.000000] [    T0] example[0]
+kern  :alert : [    1.000000] [    T1] example[1]
+kern  :crit  : [    8.000000] [    T2] example[2]
+kern  :err   : [   27.000000] [    T3] example[3]
+kern  :warn  : [   64.000000] [    T4] example[4]
+kern  :notice: [  125.000000] [    T5] example[5]
+kern  :info  : [  216.000000] [    T6] example[6]
+kern  :debug : [  343.000000] [    T7] example[7]
+user  :emerg : [  512.000000] [    T8] example[8]
+user  :alert : [  729.000000] [    T9] example[9]
+user  :crit  : [ 1000.000000] [   T10] example[10]
+user  :err   : [ 1331.000000] [   T11] example[11]
+user  :warn  : [ 1728.000000] [   T12] example[12]
+user  :notice: [ 2197.000000] [   T13] example[13]
+user  :info  : [ 2744.000000] [   T14] example[14]
+user  :debug : [ 3375.000000] [   T15] example[15]
+mail  :emerg : [ 4096.000000] [   T16] example[16]
+mail  :alert : [ 4913.000000] [   T17] example[17]
+mail  :crit  : [ 5832.000000] [   T18] example[18]
+mail  :err   : [ 6859.000000] [   T19] example[19]
+mail  :warn  : [ 8000.000000] [   T20] example[20]
+mail  :notice: [ 9261.000000] [   T21] example[21]
+mail  :info  : [10648.000000] [   T22] example[22]
+mail  :debug : [12167.000000] [   T23] example[23]
+daemon:emerg : [13824.000000] [   T24] example[24]
+daemon:alert : [15625.000000] [   T25] example[25]
+daemon:crit  : [17576.000000] [   T26] example[26]
+daemon:err   : [19683.000000] [   T27] example[27]
+daemon:warn  : [21952.000000] [   T28] example[28]
+daemon:notice: [24389.000000] [   T29] example[29]
+daemon:info  : [27000.000000] [   T10] example[30]
+daemon:debug : [29791.000000] [   T31] example[31]
+auth  :emerg : [32768.000000] [   T32] example[32]
+auth  :alert : [35937.000000] [   T33] example[33]
+auth  :crit  : [39304.000000] [   T34] example[34]
+auth  :err   : [42875.000000] [   T35] example[35]
+auth  :warn  : [46656.000000] [   T36] example[36]
+auth  :notice: [50653.000000] [   T37] example[37]
+auth  :info  : [54872.000000] [   T38] example[38]
+auth  :debug : [59319.000000] [   T39] example[39]
+syslog:emerg : [64000.000000] [   T40] example[40]
+syslog:alert : [68921.000000] [   T41] example[41]
+syslog:crit  : [74088.000000] [   T42] example[42]
+syslog:err   : [79507.000000] [   T43] example[43]
+syslog:warn  : [85184.000000] [   T44] example[44]
+syslog:notice: [91125.000000] [   T45] example[45]
+syslog:info  : [97336.000000] [   T46] example[46]
+syslog:debug : [103823.000000] [   T47] example[47]
+lpr   :emerg : [110592.000000] [   T48] example[48]
+lpr   :alert : [117649.000000] [   T49] example[49]
+lpr   :crit  : [125000.000000] [   T50] example[50]
+lpr   :err   : [132651.000000] [   T51] example[51]
+lpr   :warn  : [140608.000000] [   T52] example[52]
+lpr   :notice: [148877.000000] [   T53] example[53]
+lpr   :info  : [157464.000000] [   T54] example[54]
+lpr   :debug : [166375.000000] [   T55] example[55]
+news  :emerg : [175616.000000] [   T56] example[56]
+news  :alert : [185193.000000] [   T57] example[57]
+news  :crit  : [195112.000000] [   T58] example[58]
+news  :err   : [205379.000000] [   T59] example[59]
+news  :warn  : [216000.000000] [   T60] example[60]
+news  :notice: [226981.000000] [   T61] example[61]
+news  :info  : [238328.000000] [   T62] example[62]
+news  :debug : [250047.000000] [   T63] example[63]
+uucp  :emerg : [262144.000000] [   T64] example[64]
+uucp  :alert : [274625.000000] [   T65] example[65]
+uucp  :crit  : [287496.000000] [   T66] example[66]
+uucp  :err   : [300763.000000] [   T67] example[67]
+uucp  :warn  : [314432.000000] [   T68] example[68]
+uucp  :notice: [328509.000000] [   T69] example[69]
+uucp  :info  : [343000.000000] [   T70] example[70]
+uucp  :debug : [357911.000000] [   T71] example[71]
+cron  :emerg : [373248.000000] [   T72] example[72]
+cron  :alert : [389017.000000] [   T73] example[73]
+cron  :crit  : [405224.000000] [   T74] example[74]
+cron  :err   : [421875.000000] [   T75] example[75]
+cron  :warn  : [438976.000000] [   T76] example[76]
+cron  :notice: [456533.000000] [   T77] example[77]
+cron  :info  : [474552.000000] [   T78] example[78]
+cron  :debug : [493039.000000] [   T79] example[79]
+authpriv:emerg : [512000.000000] [   T80] example[80]
+authpriv:alert : [531441.000000] [   T81] example[81]
+authpriv:crit  : [551368.000000] [   T82] example[82]
+authpriv:err   : [571787.000000] [   T83] example[83]
+authpriv:warn  : [592704.000000] [   T84] example[84]
+authpriv:notice: [614125.000000] [   T85] example[85]
+authpriv:info  : [636056.000000] [   T86] example[86]
+authpriv:debug : [658503.000000] [   T87] example[87]
+ftp   :emerg : [681472.000000] [   T88] example[88]
+ftp   :alert : [704969.000000] [   T89] example[89]
+ftp   :crit  : [729000.000000] [   T90] example[90]
+ftp   :err   : [753571.000000] [   T91] example[91]
+ftp   :warn  : [778688.000000] [   T92] example[92]
+ftp   :notice: [804357.000000] [   T93] example[93]
+ftp   :info  : [830584.000000] [   T94] example[94]
+ftp   :debug : [857375.000000] [   T95] example[95]
+res0  :emerg : [884736.000000] [   T96] example[96]
+res0  :alert : [912673.000000] [   T97] example[97]
+res0  :crit  : [941192.000000] [   T98] example[98]
+res0  :err   : [970299.000000] [   T99] example[99]
+res0  :warn  : [1000000.000000] [  T100] example[100]
+res0  :notice: [1030301.000000] [  T101] example[101]
+res0  :info  : [1061208.000000] [  T102] example[102]
+res0  :debug : [1092727.000000] [  T103] example[103]
+res1  :emerg : [1124864.000000] [  T104] example[104]
+local2:info  : [4557523.000000] [  T105] example[105]
diff --git a/tests/expected/dmesg/cid-delta b/tests/expected/dmesg/cid-delta
new file mode 100644
index 000000000..9b75c63af
--- /dev/null
+++ b/tests/expected/dmesg/cid-delta
@@ -0,0 +1,106 @@
+[    0.000000 <    0.000000>] [    T0] example[0]
+[    1.000000 <    0.000000>] [    T1] example[1]
+[    8.000000 <    7.000000>] [    T2] example[2]
+[   27.000000 <   19.000000>] [    T3] example[3]
+[   64.000000 <   37.000000>] [    T4] example[4]
+[  125.000000 <   61.000000>] [    T5] example[5]
+[  216.000000 <   91.000000>] [    T6] example[6]
+[  343.000000 <  127.000000>] [    T7] example[7]
+[  512.000000 <  169.000000>] [    T8] example[8]
+[  729.000000 <  217.000000>] [    T9] example[9]
+[ 1000.000000 <  271.000000>] [   T10] example[10]
+[ 1331.000000 <  331.000000>] [   T11] example[11]
+[ 1728.000000 <  397.000000>] [   T12] example[12]
+[ 2197.000000 <  469.000000>] [   T13] example[13]
+[ 2744.000000 <  547.000000>] [   T14] example[14]
+[ 3375.000000 <  631.000000>] [   T15] example[15]
+[ 4096.000000 <  721.000000>] [   T16] example[16]
+[ 4913.000000 <  817.000000>] [   T17] example[17]
+[ 5832.000000 <  919.000000>] [   T18] example[18]
+[ 6859.000000 < 1027.000000>] [   T19] example[19]
+[ 8000.000000 < 1141.000000>] [   T20] example[20]
+[ 9261.000000 < 1261.000000>] [   T21] example[21]
+[10648.000000 < 1387.000000>] [   T22] example[22]
+[12167.000000 < 1519.000000>] [   T23] example[23]
+[13824.000000 < 1657.000000>] [   T24] example[24]
+[15625.000000 < 1801.000000>] [   T25] example[25]
+[17576.000000 < 1951.000000>] [   T26] example[26]
+[19683.000000 < 2107.000000>] [   T27] example[27]
+[21952.000000 < 2269.000000>] [   T28] example[28]
+[24389.000000 < 2437.000000>] [   T29] example[29]
+[27000.000000 < 2611.000000>] [   T10] example[30]
+[29791.000000 < 2791.000000>] [   T31] example[31]
+[32768.000000 < 2977.000000>] [   T32] example[32]
+[35937.000000 < 3169.000000>] [   T33] example[33]
+[39304.000000 < 3367.000000>] [   T34] example[34]
+[42875.000000 < 3571.000000>] [   T35] example[35]
+[46656.000000 < 3781.000000>] [   T36] example[36]
+[50653.000000 < 3997.000000>] [   T37] example[37]
+[54872.000000 < 4219.000000>] [   T38] example[38]
+[59319.000000 < 4447.000000>] [   T39] example[39]
+[64000.000000 < 4681.000000>] [   T40] example[40]
+[68921.000000 < 4921.000000>] [   T41] example[41]
+[74088.000000 < 5167.000000>] [   T42] example[42]
+[79507.000000 < 5419.000000>] [   T43] example[43]
+[85184.000000 < 5677.000000>] [   T44] example[44]
+[91125.000000 < 5941.000000>] [   T45] example[45]
+[97336.000000 < 6211.000000>] [   T46] example[46]
+[103823.000000 < 6487.000000>] [   T47] example[47]
+[110592.000000 < 6769.000000>] [   T48] example[48]
+[117649.000000 < 7057.000000>] [   T49] example[49]
+[125000.000000 < 7351.000000>] [   T50] example[50]
+[132651.000000 < 7651.000000>] [   T51] example[51]
+[140608.000000 < 7957.000000>] [   T52] example[52]
+[148877.000000 < 8269.000000>] [   T53] example[53]
+[157464.000000 < 8587.000000>] [   T54] example[54]
+[166375.000000 < 8911.000000>] [   T55] example[55]
+[175616.000000 < 9241.000000>] [   T56] example[56]
+[185193.000000 < 9577.000000>] [   T57] example[57]
+[195112.000000 < 9919.000000>] [   T58] example[58]
+[205379.000000 <10267.000000>] [   T59] example[59]
+[216000.000000 <10621.000000>] [   T60] example[60]
+[226981.000000 <10981.000000>] [   T61] example[61]
+[238328.000000 <11347.000000>] [   T62] example[62]
+[250047.000000 <11719.000000>] [   T63] example[63]
+[262144.000000 <12097.000000>] [   T64] example[64]
+[274625.000000 <12481.000000>] [   T65] example[65]
+[287496.000000 <12871.000000>] [   T66] example[66]
+[300763.000000 <13267.000000>] [   T67] example[67]
+[314432.000000 <13669.000000>] [   T68] example[68]
+[328509.000000 <14077.000000>] [   T69] example[69]
+[343000.000000 <14491.000000>] [   T70] example[70]
+[357911.000000 <14911.000000>] [   T71] example[71]
+[373248.000000 <15337.000000>] [   T72] example[72]
+[389017.000000 <15769.000000>] [   T73] example[73]
+[405224.000000 <16207.000000>] [   T74] example[74]
+[421875.000000 <16651.000000>] [   T75] example[75]
+[438976.000000 <17101.000000>] [   T76] example[76]
+[456533.000000 <17557.000000>] [   T77] example[77]
+[474552.000000 <18019.000000>] [   T78] example[78]
+[493039.000000 <18487.000000>] [   T79] example[79]
+[512000.000000 <18961.000000>] [   T80] example[80]
+[531441.000000 <19441.000000>] [   T81] example[81]
+[551368.000000 <19927.000000>] [   T82] example[82]
+[571787.000000 <20419.000000>] [   T83] example[83]
+[592704.000000 <20917.000000>] [   T84] example[84]
+[614125.000000 <21421.000000>] [   T85] example[85]
+[636056.000000 <21931.000000>] [   T86] example[86]
+[658503.000000 <22447.000000>] [   T87] example[87]
+[681472.000000 <22969.000000>] [   T88] example[88]
+[704969.000000 <23497.000000>] [   T89] example[89]
+[729000.000000 <24031.000000>] [   T90] example[90]
+[753571.000000 <24571.000000>] [   T91] example[91]
+[778688.000000 <25117.000000>] [   T92] example[92]
+[804357.000000 <25669.000000>] [   T93] example[93]
+[830584.000000 <26227.000000>] [   T94] example[94]
+[857375.000000 <26791.000000>] [   T95] example[95]
+[884736.000000 <27361.000000>] [   T96] example[96]
+[912673.000000 <27937.000000>] [   T97] example[97]
+[941192.000000 <28519.000000>] [   T98] example[98]
+[970299.000000 <29107.000000>] [   T99] example[99]
+[1000000.000000 <29701.000000>] [  T100] example[100]
+[1030301.000000 <30301.000000>] [  T101] example[101]
+[1061208.000000 <30907.000000>] [  T102] example[102]
+[1092727.000000 <31519.000000>] [  T103] example[103]
+[1124864.000000 <32137.000000>] [  T104] example[104]
+[4557523.000000 <3432659.000000>] [  T105] example[105]
diff --git a/tests/expected/dmesg/cid-facilities b/tests/expected/dmesg/cid-facilities
new file mode 100644
index 000000000..b8afa3809
--- /dev/null
+++ b/tests/expected/dmesg/cid-facilities
@@ -0,0 +1,104 @@
+[    0.000000] [    T0] example[0]
+[    1.000000] [    T1] example[1]
+[    8.000000] [    T2] example[2]
+[   27.000000] [    T3] example[3]
+[   64.000000] [    T4] example[4]
+[  125.000000] [    T5] example[5]
+[  216.000000] [    T6] example[6]
+[  343.000000] [    T7] example[7]
+[  512.000000] [    T8] example[8]
+[  729.000000] [    T9] example[9]
+[ 1000.000000] [   T10] example[10]
+[ 1331.000000] [   T11] example[11]
+[ 1728.000000] [   T12] example[12]
+[ 2197.000000] [   T13] example[13]
+[ 2744.000000] [   T14] example[14]
+[ 3375.000000] [   T15] example[15]
+[ 4096.000000] [   T16] example[16]
+[ 4913.000000] [   T17] example[17]
+[ 5832.000000] [   T18] example[18]
+[ 6859.000000] [   T19] example[19]
+[ 8000.000000] [   T20] example[20]
+[ 9261.000000] [   T21] example[21]
+[10648.000000] [   T22] example[22]
+[12167.000000] [   T23] example[23]
+[13824.000000] [   T24] example[24]
+[15625.000000] [   T25] example[25]
+[17576.000000] [   T26] example[26]
+[19683.000000] [   T27] example[27]
+[21952.000000] [   T28] example[28]
+[24389.000000] [   T29] example[29]
+[27000.000000] [   T10] example[30]
+[29791.000000] [   T31] example[31]
+[32768.000000] [   T32] example[32]
+[35937.000000] [   T33] example[33]
+[39304.000000] [   T34] example[34]
+[42875.000000] [   T35] example[35]
+[46656.000000] [   T36] example[36]
+[50653.000000] [   T37] example[37]
+[54872.000000] [   T38] example[38]
+[59319.000000] [   T39] example[39]
+[64000.000000] [   T40] example[40]
+[68921.000000] [   T41] example[41]
+[74088.000000] [   T42] example[42]
+[79507.000000] [   T43] example[43]
+[85184.000000] [   T44] example[44]
+[91125.000000] [   T45] example[45]
+[97336.000000] [   T46] example[46]
+[103823.000000] [   T47] example[47]
+[110592.000000] [   T48] example[48]
+[117649.000000] [   T49] example[49]
+[125000.000000] [   T50] example[50]
+[132651.000000] [   T51] example[51]
+[140608.000000] [   T52] example[52]
+[148877.000000] [   T53] example[53]
+[157464.000000] [   T54] example[54]
+[166375.000000] [   T55] example[55]
+[175616.000000] [   T56] example[56]
+[185193.000000] [   T57] example[57]
+[195112.000000] [   T58] example[58]
+[205379.000000] [   T59] example[59]
+[216000.000000] [   T60] example[60]
+[226981.000000] [   T61] example[61]
+[238328.000000] [   T62] example[62]
+[250047.000000] [   T63] example[63]
+[262144.000000] [   T64] example[64]
+[274625.000000] [   T65] example[65]
+[287496.000000] [   T66] example[66]
+[300763.000000] [   T67] example[67]
+[314432.000000] [   T68] example[68]
+[328509.000000] [   T69] example[69]
+[343000.000000] [   T70] example[70]
+[357911.000000] [   T71] example[71]
+[373248.000000] [   T72] example[72]
+[389017.000000] [   T73] example[73]
+[405224.000000] [   T74] example[74]
+[421875.000000] [   T75] example[75]
+[438976.000000] [   T76] example[76]
+[456533.000000] [   T77] example[77]
+[474552.000000] [   T78] example[78]
+[493039.000000] [   T79] example[79]
+[512000.000000] [   T80] example[80]
+[531441.000000] [   T81] example[81]
+[551368.000000] [   T82] example[82]
+[571787.000000] [   T83] example[83]
+[592704.000000] [   T84] example[84]
+[614125.000000] [   T85] example[85]
+[636056.000000] [   T86] example[86]
+[658503.000000] [   T87] example[87]
+[681472.000000] [   T88] example[88]
+[704969.000000] [   T89] example[89]
+[729000.000000] [   T90] example[90]
+[753571.000000] [   T91] example[91]
+[778688.000000] [   T92] example[92]
+[804357.000000] [   T93] example[93]
+[830584.000000] [   T94] example[94]
+[857375.000000] [   T95] example[95]
+[884736.000000] [   T96] example[96]
+[912673.000000] [   T97] example[97]
+[941192.000000] [   T98] example[98]
+[970299.000000] [   T99] example[99]
+[1000000.000000] [  T100] example[100]
+[1030301.000000] [  T101] example[101]
+[1061208.000000] [  T102] example[102]
+[1092727.000000] [  T103] example[103]
diff --git a/tests/expected/dmesg/cid-indentation b/tests/expected/dmesg/cid-indentation
new file mode 100644
index 000000000..b2219671e
--- /dev/null
+++ b/tests/expected/dmesg/cid-indentation
@@ -0,0 +1,35 @@
+[    1.000000] [    T1] new
+               line
+[    2.000000] [    T2] two
+               new
+               lines
+user  :crit  : [    1.000000] [    T1] new
+                              line
+mail  :warn  : [    2.000000] [    T2] two
+                              new
+                              lines
+[<    0.000000>] [    T1] new
+                 line
+[<    1.000000>] [    T2] two
+                 new
+                 lines
+[    T1] new
+line
+[    T2] two
+new
+lines
+[Feb13 23:31] [    T1] new
+              line
+[  +1.000000] [    T2] two
+              new
+              lines
+[Fri Feb 13 23:31:31 2009] [    T1] new
+                           line
+[Fri Feb 13 23:31:32 2009] [    T2] two
+                           new
+                           lines
+2009-02-13T23:31:31,123456+00:00 [    T1] new
+                                 line
+2009-02-13T23:31:32,123456+00:00 [    T2] two
+                                 new
+                                 lines
diff --git a/tests/expected/dmesg/cid-json b/tests/expected/dmesg/cid-json
new file mode 100644
index 000000000..cb0451b3c
--- /dev/null
+++ b/tests/expected/dmesg/cid-json
@@ -0,0 +1,429 @@
+{
+   "dmesg": [
+      {
+         "pri": 0,
+         "time":     0.000000,
+         "msg": "[    T0] example[0]"
+      },{
+         "pri": 1,
+         "time":     1.000000,
+         "msg": "[    T1] example[1]"
+      },{
+         "pri": 2,
+         "time":     8.000000,
+         "msg": "[    T2] example[2]"
+      },{
+         "pri": 3,
+         "time":    27.000000,
+         "msg": "[    T3] example[3]"
+      },{
+         "pri": 4,
+         "time":    64.000000,
+         "msg": "[    T4] example[4]"
+      },{
+         "pri": 5,
+         "time":   125.000000,
+         "msg": "[    T5] example[5]"
+      },{
+         "pri": 6,
+         "time":   216.000000,
+         "msg": "[    T6] example[6]"
+      },{
+         "pri": 7,
+         "time":   343.000000,
+         "msg": "[    T7] example[7]"
+      },{
+         "pri": 8,
+         "time":   512.000000,
+         "msg": "[    T8] example[8]"
+      },{
+         "pri": 9,
+         "time":   729.000000,
+         "msg": "[    T9] example[9]"
+      },{
+         "pri": 10,
+         "time":  1000.000000,
+         "msg": "[   T10] example[10]"
+      },{
+         "pri": 11,
+         "time":  1331.000000,
+         "msg": "[   T11] example[11]"
+      },{
+         "pri": 12,
+         "time":  1728.000000,
+         "msg": "[   T12] example[12]"
+      },{
+         "pri": 13,
+         "time":  2197.000000,
+         "msg": "[   T13] example[13]"
+      },{
+         "pri": 14,
+         "time":  2744.000000,
+         "msg": "[   T14] example[14]"
+      },{
+         "pri": 15,
+         "time":  3375.000000,
+         "msg": "[   T15] example[15]"
+      },{
+         "pri": 16,
+         "time":  4096.000000,
+         "msg": "[   T16] example[16]"
+      },{
+         "pri": 17,
+         "time":  4913.000000,
+         "msg": "[   T17] example[17]"
+      },{
+         "pri": 18,
+         "time":  5832.000000,
+         "msg": "[   T18] example[18]"
+      },{
+         "pri": 19,
+         "time":  6859.000000,
+         "msg": "[   T19] example[19]"
+      },{
+         "pri": 20,
+         "time":  8000.000000,
+         "msg": "[   T20] example[20]"
+      },{
+         "pri": 21,
+         "time":  9261.000000,
+         "msg": "[   T21] example[21]"
+      },{
+         "pri": 22,
+         "time": 10648.000000,
+         "msg": "[   T22] example[22]"
+      },{
+         "pri": 23,
+         "time": 12167.000000,
+         "msg": "[   T23] example[23]"
+      },{
+         "pri": 24,
+         "time": 13824.000000,
+         "msg": "[   T24] example[24]"
+      },{
+         "pri": 25,
+         "time": 15625.000000,
+         "msg": "[   T25] example[25]"
+      },{
+         "pri": 26,
+         "time": 17576.000000,
+         "msg": "[   T26] example[26]"
+      },{
+         "pri": 27,
+         "time": 19683.000000,
+         "msg": "[   T27] example[27]"
+      },{
+         "pri": 28,
+         "time": 21952.000000,
+         "msg": "[   T28] example[28]"
+      },{
+         "pri": 29,
+         "time": 24389.000000,
+         "msg": "[   T29] example[29]"
+      },{
+         "pri": 30,
+         "time": 27000.000000,
+         "msg": "[   T10] example[30]"
+      },{
+         "pri": 31,
+         "time": 29791.000000,
+         "msg": "[   T31] example[31]"
+      },{
+         "pri": 32,
+         "time": 32768.000000,
+         "msg": "[   T32] example[32]"
+      },{
+         "pri": 33,
+         "time": 35937.000000,
+         "msg": "[   T33] example[33]"
+      },{
+         "pri": 34,
+         "time": 39304.000000,
+         "msg": "[   T34] example[34]"
+      },{
+         "pri": 35,
+         "time": 42875.000000,
+         "msg": "[   T35] example[35]"
+      },{
+         "pri": 36,
+         "time": 46656.000000,
+         "msg": "[   T36] example[36]"
+      },{
+         "pri": 37,
+         "time": 50653.000000,
+         "msg": "[   T37] example[37]"
+      },{
+         "pri": 38,
+         "time": 54872.000000,
+         "msg": "[   T38] example[38]"
+      },{
+         "pri": 39,
+         "time": 59319.000000,
+         "msg": "[   T39] example[39]"
+      },{
+         "pri": 40,
+         "time": 64000.000000,
+         "msg": "[   T40] example[40]"
+      },{
+         "pri": 41,
+         "time": 68921.000000,
+         "msg": "[   T41] example[41]"
+      },{
+         "pri": 42,
+         "time": 74088.000000,
+         "msg": "[   T42] example[42]"
+      },{
+         "pri": 43,
+         "time": 79507.000000,
+         "msg": "[   T43] example[43]"
+      },{
+         "pri": 44,
+         "time": 85184.000000,
+         "msg": "[   T44] example[44]"
+      },{
+         "pri": 45,
+         "time": 91125.000000,
+         "msg": "[   T45] example[45]"
+      },{
+         "pri": 46,
+         "time": 97336.000000,
+         "msg": "[   T46] example[46]"
+      },{
+         "pri": 47,
+         "time": 103823.000000,
+         "msg": "[   T47] example[47]"
+      },{
+         "pri": 48,
+         "time": 110592.000000,
+         "msg": "[   T48] example[48]"
+      },{
+         "pri": 49,
+         "time": 117649.000000,
+         "msg": "[   T49] example[49]"
+      },{
+         "pri": 50,
+         "time": 125000.000000,
+         "msg": "[   T50] example[50]"
+      },{
+         "pri": 51,
+         "time": 132651.000000,
+         "msg": "[   T51] example[51]"
+      },{
+         "pri": 52,
+         "time": 140608.000000,
+         "msg": "[   T52] example[52]"
+      },{
+         "pri": 53,
+         "time": 148877.000000,
+         "msg": "[   T53] example[53]"
+      },{
+         "pri": 54,
+         "time": 157464.000000,
+         "msg": "[   T54] example[54]"
+      },{
+         "pri": 55,
+         "time": 166375.000000,
+         "msg": "[   T55] example[55]"
+      },{
+         "pri": 56,
+         "time": 175616.000000,
+         "msg": "[   T56] example[56]"
+      },{
+         "pri": 57,
+         "time": 185193.000000,
+         "msg": "[   T57] example[57]"
+      },{
+         "pri": 58,
+         "time": 195112.000000,
+         "msg": "[   T58] example[58]"
+      },{
+         "pri": 59,
+         "time": 205379.000000,
+         "msg": "[   T59] example[59]"
+      },{
+         "pri": 60,
+         "time": 216000.000000,
+         "msg": "[   T60] example[60]"
+      },{
+         "pri": 61,
+         "time": 226981.000000,
+         "msg": "[   T61] example[61]"
+      },{
+         "pri": 62,
+         "time": 238328.000000,
+         "msg": "[   T62] example[62]"
+      },{
+         "pri": 63,
+         "time": 250047.000000,
+         "msg": "[   T63] example[63]"
+      },{
+         "pri": 64,
+         "time": 262144.000000,
+         "msg": "[   T64] example[64]"
+      },{
+         "pri": 65,
+         "time": 274625.000000,
+         "msg": "[   T65] example[65]"
+      },{
+         "pri": 66,
+         "time": 287496.000000,
+         "msg": "[   T66] example[66]"
+      },{
+         "pri": 67,
+         "time": 300763.000000,
+         "msg": "[   T67] example[67]"
+      },{
+         "pri": 68,
+         "time": 314432.000000,
+         "msg": "[   T68] example[68]"
+      },{
+         "pri": 69,
+         "time": 328509.000000,
+         "msg": "[   T69] example[69]"
+      },{
+         "pri": 70,
+         "time": 343000.000000,
+         "msg": "[   T70] example[70]"
+      },{
+         "pri": 71,
+         "time": 357911.000000,
+         "msg": "[   T71] example[71]"
+      },{
+         "pri": 72,
+         "time": 373248.000000,
+         "msg": "[   T72] example[72]"
+      },{
+         "pri": 73,
+         "time": 389017.000000,
+         "msg": "[   T73] example[73]"
+      },{
+         "pri": 74,
+         "time": 405224.000000,
+         "msg": "[   T74] example[74]"
+      },{
+         "pri": 75,
+         "time": 421875.000000,
+         "msg": "[   T75] example[75]"
+      },{
+         "pri": 76,
+         "time": 438976.000000,
+         "msg": "[   T76] example[76]"
+      },{
+         "pri": 77,
+         "time": 456533.000000,
+         "msg": "[   T77] example[77]"
+      },{
+         "pri": 78,
+         "time": 474552.000000,
+         "msg": "[   T78] example[78]"
+      },{
+         "pri": 79,
+         "time": 493039.000000,
+         "msg": "[   T79] example[79]"
+      },{
+         "pri": 80,
+         "time": 512000.000000,
+         "msg": "[   T80] example[80]"
+      },{
+         "pri": 81,
+         "time": 531441.000000,
+         "msg": "[   T81] example[81]"
+      },{
+         "pri": 82,
+         "time": 551368.000000,
+         "msg": "[   T82] example[82]"
+      },{
+         "pri": 83,
+         "time": 571787.000000,
+         "msg": "[   T83] example[83]"
+      },{
+         "pri": 84,
+         "time": 592704.000000,
+         "msg": "[   T84] example[84]"
+      },{
+         "pri": 85,
+         "time": 614125.000000,
+         "msg": "[   T85] example[85]"
+      },{
+         "pri": 86,
+         "time": 636056.000000,
+         "msg": "[   T86] example[86]"
+      },{
+         "pri": 87,
+         "time": 658503.000000,
+         "msg": "[   T87] example[87]"
+      },{
+         "pri": 88,
+         "time": 681472.000000,
+         "msg": "[   T88] example[88]"
+      },{
+         "pri": 89,
+         "time": 704969.000000,
+         "msg": "[   T89] example[89]"
+      },{
+         "pri": 90,
+         "time": 729000.000000,
+         "msg": "[   T90] example[90]"
+      },{
+         "pri": 91,
+         "time": 753571.000000,
+         "msg": "[   T91] example[91]"
+      },{
+         "pri": 92,
+         "time": 778688.000000,
+         "msg": "[   T92] example[92]"
+      },{
+         "pri": 93,
+         "time": 804357.000000,
+         "msg": "[   T93] example[93]"
+      },{
+         "pri": 94,
+         "time": 830584.000000,
+         "msg": "[   T94] example[94]"
+      },{
+         "pri": 95,
+         "time": 857375.000000,
+         "msg": "[   T95] example[95]"
+      },{
+         "pri": 96,
+         "time": 884736.000000,
+         "msg": "[   T96] example[96]"
+      },{
+         "pri": 97,
+         "time": 912673.000000,
+         "msg": "[   T97] example[97]"
+      },{
+         "pri": 98,
+         "time": 941192.000000,
+         "msg": "[   T98] example[98]"
+      },{
+         "pri": 99,
+         "time": 970299.000000,
+         "msg": "[   T99] example[99]"
+      },{
+         "pri": 100,
+         "time": 1000000.000000,
+         "msg": "[  T100] example[100]"
+      },{
+         "pri": 101,
+         "time": 1030301.000000,
+         "msg": "[  T101] example[101]"
+      },{
+         "pri": 102,
+         "time": 1061208.000000,
+         "msg": "[  T102] example[102]"
+      },{
+         "pri": 103,
+         "time": 1092727.000000,
+         "msg": "[  T103] example[103]"
+      },{
+         "pri": 104,
+         "time": 1124864.000000,
+         "msg": "[  T104] example[104]"
+      },{
+         "pri": 150,
+         "time": 4557523.000000,
+         "msg": "[  T105] example[105]"
+      }
+   ]
+}
diff --git a/tests/expected/dmesg/cid-limit b/tests/expected/dmesg/cid-limit
new file mode 100644
index 000000000..c30b4ac9a
--- /dev/null
+++ b/tests/expected/dmesg/cid-limit
@@ -0,0 +1,4 @@
+[    1.000000] [    T1] example[1]
+[    8.000000] [    T2] example[2]
+[   27.000000] [    T3] example[3]
+[   64.000000] [    T4] example[4]
diff --git a/tests/ts/dmesg/cid-colors b/tests/ts/dmesg/cid-colors
new file mode 100755
index 000000000..d17dd17c0
--- /dev/null
+++ b/tests/ts/dmesg/cid-colors
@@ -0,0 +1,29 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="cid-colors"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+ts_inhibit_custom_colorscheme
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG --color=always -F $TS_SELF/cid-input -x >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/cid-console-levels b/tests/ts/dmesg/cid-console-levels
new file mode 100755
index 000000000..e2f241bde
--- /dev/null
+++ b/tests/ts/dmesg/cid-console-levels
@@ -0,0 +1,36 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="cid-levels"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+for I in {-1..8}; do
+	$TS_HELPER_DMESG -F $TS_SELF/cid-input -l $I >> $TS_OUTPUT 2>/dev/null
+done
+
+$TS_HELPER_DMESG -F $TS_SELF/cid-input -l err+ >> $TS_OUTPUT 2>/dev/null
+$TS_HELPER_DMESG -F $TS_SELF/cid-input -l emerg+ >> $TS_OUTPUT 2>/dev/null
+$TS_HELPER_DMESG -F $TS_SELF/cid-input -l +err >> $TS_OUTPUT 2>/dev/null
+$TS_HELPER_DMESG -F $TS_SELF/cid-input -l +debug >> $TS_OUTPUT 2>/dev/null
+$TS_HELPER_DMESG -F $TS_SELF/cid-input -l + 2>> $TS_OUTPUT >/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/cid-decode b/tests/ts/dmesg/cid-decode
new file mode 100755
index 000000000..488f52a32
--- /dev/null
+++ b/tests/ts/dmesg/cid-decode
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="cid-decode"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG -x -F $TS_SELF/cid-input >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/cid-delta b/tests/ts/dmesg/cid-delta
new file mode 100755
index 000000000..8ba952a5d
--- /dev/null
+++ b/tests/ts/dmesg/cid-delta
@@ -0,0 +1,27 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="cid-delta"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+$TS_HELPER_DMESG -d -F $TS_SELF/cid-input >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/cid-facilities b/tests/ts/dmesg/cid-facilities
new file mode 100755
index 000000000..b4b613e8b
--- /dev/null
+++ b/tests/ts/dmesg/cid-facilities
@@ -0,0 +1,30 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="cid-facilities"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+for I in {-1..12}; do
+	$TS_HELPER_DMESG -F $TS_SELF/cid-input -f $I >> $TS_OUTPUT 2>/dev/null
+done
+
+ts_finalize
diff --git a/tests/ts/dmesg/cid-indentation b/tests/ts/dmesg/cid-indentation
new file mode 100755
index 000000000..434e1694b
--- /dev/null
+++ b/tests/ts/dmesg/cid-indentation
@@ -0,0 +1,40 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="cid-indentation"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG -F $TS_SELF/cid-newlines >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG -F $TS_SELF/cid-newlines -x >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=delta --file $TS_SELF/cid-newlines >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=notime --file $TS_SELF/cid-newlines >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=reltime --file $TS_SELF/cid-newlines >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=ctime --file $TS_SELF/cid-newlines >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=iso --file $TS_SELF/cid-newlines >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+ts_finalize
diff --git a/tests/ts/dmesg/cid-input b/tests/ts/dmesg/cid-input
new file mode 100644
index 000000000..7dbd89d8f
--- /dev/null
+++ b/tests/ts/dmesg/cid-input
@@ -0,0 +1,106 @@
+<0>[    0.000000] [    T0] example[0]
+<1>[    1.000000] [    T1] example[1]
+<2>[    8.000000] [    T2] example[2]
+<3>[   27.000000] [    T3] example[3]
+<4>[   64.000000] [    T4] example[4]
+<5>[  125.000000] [    T5] example[5]
+<6>[  216.000000] [    T6] example[6]
+<7>[  343.000000] [    T7] example[7]
+<8>[  512.000000] [    T8] example[8]
+<9>[  729.000000] [    T9] example[9]
+<10>[ 1000.000000] [   T10] example[10]
+<11>[ 1331.000000] [   T11] example[11]
+<12>[ 1728.000000] [   T12] example[12]
+<13>[ 2197.000000] [   T13] example[13]
+<14>[ 2744.000000] [   T14] example[14]
+<15>[ 3375.000000] [   T15] example[15]
+<16>[ 4096.000000] [   T16] example[16]
+<17>[ 4913.000000] [   T17] example[17]
+<18>[ 5832.000000] [   T18] example[18]
+<19>[ 6859.000000] [   T19] example[19]
+<20>[ 8000.000000] [   T20] example[20]
+<21>[ 9261.000000] [   T21] example[21]
+<22>[10648.000000] [   T22] example[22]
+<23>[12167.000000] [   T23] example[23]
+<24>[13824.000000] [   T24] example[24]
+<25>[15625.000000] [   T25] example[25]
+<26>[17576.000000] [   T26] example[26]
+<27>[19683.000000] [   T27] example[27]
+<28>[21952.000000] [   T28] example[28]
+<29>[24389.000000] [   T29] example[29]
+<30>[27000.000000] [   T10] example[30]
+<31>[29791.000000] [   T31] example[31]
+<32>[32768.000000] [   T32] example[32]
+<33>[35937.000000] [   T33] example[33]
+<34>[39304.000000] [   T34] example[34]
+<35>[42875.000000] [   T35] example[35]
+<36>[46656.000000] [   T36] example[36]
+<37>[50653.000000] [   T37] example[37]
+<38>[54872.000000] [   T38] example[38]
+<39>[59319.000000] [   T39] example[39]
+<40>[64000.000000] [   T40] example[40]
+<41>[68921.000000] [   T41] example[41]
+<42>[74088.000000] [   T42] example[42]
+<43>[79507.000000] [   T43] example[43]
+<44>[85184.000000] [   T44] example[44]
+<45>[91125.000000] [   T45] example[45]
+<46>[97336.000000] [   T46] example[46]
+<47>[103823.000000] [   T47] example[47]
+<48>[110592.000000] [   T48] example[48]
+<49>[117649.000000] [   T49] example[49]
+<50>[125000.000000] [   T50] example[50]
+<51>[132651.000000] [   T51] example[51]
+<52>[140608.000000] [   T52] example[52]
+<53>[148877.000000] [   T53] example[53]
+<54>[157464.000000] [   T54] example[54]
+<55>[166375.000000] [   T55] example[55]
+<56>[175616.000000] [   T56] example[56]
+<57>[185193.000000] [   T57] example[57]
+<58>[195112.000000] [   T58] example[58]
+<59>[205379.000000] [   T59] example[59]
+<60>[216000.000000] [   T60] example[60]
+<61>[226981.000000] [   T61] example[61]
+<62>[238328.000000] [   T62] example[62]
+<63>[250047.000000] [   T63] example[63]
+<64>[262144.000000] [   T64] example[64]
+<65>[274625.000000] [   T65] example[65]
+<66>[287496.000000] [   T66] example[66]
+<67>[300763.000000] [   T67] example[67]
+<68>[314432.000000] [   T68] example[68]
+<69>[328509.000000] [   T69] example[69]
+<70>[343000.000000] [   T70] example[70]
+<71>[357911.000000] [   T71] example[71]
+<72>[373248.000000] [   T72] example[72]
+<73>[389017.000000] [   T73] example[73]
+<74>[405224.000000] [   T74] example[74]
+<75>[421875.000000] [   T75] example[75]
+<76>[438976.000000] [   T76] example[76]
+<77>[456533.000000] [   T77] example[77]
+<78>[474552.000000] [   T78] example[78]
+<79>[493039.000000] [   T79] example[79]
+<80>[512000.000000] [   T80] example[80]
+<81>[531441.000000] [   T81] example[81]
+<82>[551368.000000] [   T82] example[82]
+<83>[571787.000000] [   T83] example[83]
+<84>[592704.000000] [   T84] example[84]
+<85>[614125.000000] [   T85] example[85]
+<86>[636056.000000] [   T86] example[86]
+<87>[658503.000000] [   T87] example[87]
+<88>[681472.000000] [   T88] example[88]
+<89>[704969.000000] [   T89] example[89]
+<90>[729000.000000] [   T90] example[90]
+<91>[753571.000000] [   T91] example[91]
+<92>[778688.000000] [   T92] example[92]
+<93>[804357.000000] [   T93] example[93]
+<94>[830584.000000] [   T94] example[94]
+<95>[857375.000000] [   T95] example[95]
+<96>[884736.000000] [   T96] example[96]
+<97>[912673.000000] [   T97] example[97]
+<98>[941192.000000] [   T98] example[98]
+<99>[970299.000000] [   T99] example[99]
+<100>[1000000.000000] [  T100] example[100]
+<101>[1030301.000000] [  T101] example[101]
+<102>[1061208.000000] [  T102] example[102]
+<103>[1092727.000000] [  T103] example[103]
+<104>[1124864.000000] [  T104] example[104]
+<150>[4557523.000000] [  T105] example[105]
diff --git a/tests/ts/dmesg/cid-json b/tests/ts/dmesg/cid-json
new file mode 100755
index 000000000..78363793d
--- /dev/null
+++ b/tests/ts/dmesg/cid-json
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="cid-json"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG -J -F $TS_SELF/cid-input >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/cid-limit b/tests/ts/dmesg/cid-limit
new file mode 100755
index 000000000..34f928a9e
--- /dev/null
+++ b/tests/ts/dmesg/cid-limit
@@ -0,0 +1,29 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="cid-limit"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG --since @1234567890.124 --until @1234567991 \
+	-F $TS_SELF/cid-input >> $TS_OUTPUT 2> $TS_ERRLOG
+
+ts_finalize
diff --git a/tests/ts/dmesg/cid-newlines b/tests/ts/dmesg/cid-newlines
new file mode 100644
index 000000000..682ce40bb
--- /dev/null
+++ b/tests/ts/dmesg/cid-newlines
@@ -0,0 +1,5 @@
+<10>[    1.000000] [    T1] new
+line
+<20>[    2.000000] [    T2] two
+new
+lines
-- 
2.43.0


^ permalink raw reply related

* [PATCH] Add standard dmesg kmsg interface tests Issue: #2663
From: Edward Chron @ 2023-12-30  1:46 UTC (permalink / raw)
  To: util-linux; +Cc: colona, echron, echron

Submission to Project: util-linux
Open Incident: #2663 at github.com/util-linux/util-linux/issues/2663
Component: util-linux/sys-utils
Files: tests/ts/dmesg kmsg interface files and related expected files

For issue #2609 Thomas and Zak pointed out the we need tests to verify
that the dmesg command works correctly and to allow us to compare the
results from PRINTK_CALLER id field tests provided by #2609 with the
standard (syslog interface) dmesg tests.

Except for a kmsg json test that Thomas added recently we don't have
basic dmesg tests for the kmsg interface to compare results against.

We added tests for the dmesg SYSLOG PRINTK_CALLER id interface so we
can compare against those tests.
Those tests were submitted with Issue #2637.

Those tests were created before Thomas added the new dmesg kmsg test
and I will rename those tests to match the naming scheme that Thomas
is using for tests that are specific to syslog interface and specific
to kmsg interface.

Issue #2609 introduces dmesg kmsg interface support for the PRINTK_CALLER
id field and provides tests to compare against the SYSLOG interface tests
added by #2637. Those tests also need to renamed to be consistent Thomas's
test naming scheme.

Here we've created tests for the dmesg kmsg interface following the
existing test structure for dmesg tests.

With the addition of this set of tests, we have tests for SYSLOG and
SYSLOG PRINTK_CALLER id field to compare against the kmsg and kmsg
PRINTK_CALLER id field tests.

Currently the only kmsg interface specific test that exists is the
kmsg-file test that Thomas added to test the dmesg kmsg interface for
json support.

Thomas also added code for the -K file interface to process dmesg ksmg
interface files for testing so we utilize that code here and add to it.

The kmsg-input file is expanded to provide statements and fields to
completely test the kmsg interface with tests that are equivalent to the
SYSLOG interface dmesg tests.

Additionally a ksmg-newlines file is added which provides kmsg format
for testing with indentation.

The output of the existing kmsg-file test is adjusted to match the
expanded kmsg-input file.

All tests follow the standard util-linux tests format used by dmesg for
unit tests.

Note: git doesn't handle binary files all that well and two files here
      are binary files kmsg-input and kmsg-newlines because the format
      of dmesg kmsg interface files requires binary format.
      So those two files can't be sent in this patch file
      Instead I will gzip those files and attach them to the Issue #2663
      Please gunzip them and install them in your tests/ts/dmesg
      directory that also holds the dmesg test files included here so
      that the tests will pass. Sorry for the inconvenience of having
      the binary files in separate gziped files.

Signed-off-by: Ivan Delalande <colona@arista.com>
Signed-off-by: Edward Chron <echron@arista.com>
---
 tests/expected/dmesg/kmsg-colors         |  45 ++++++++
 tests/expected/dmesg/kmsg-console-levels |  61 +++++++++++
 tests/expected/dmesg/kmsg-decode         |  45 ++++++++
 tests/expected/dmesg/kmsg-delta          |  45 ++++++++
 tests/expected/dmesg/kmsg-facilities     |  59 +++++++++++
 tests/expected/dmesg/kmsg-file           | 126 ++++++++++++++++++++---
 tests/expected/dmesg/kmsg-indentation    |  35 +++++++
 tests/expected/dmesg/kmsg-limit          |  31 ++++++
 tests/ts/dmesg/kmsg-colors               |  29 ++++++
 tests/ts/dmesg/kmsg-console-levels       |  43 ++++++++
 tests/ts/dmesg/kmsg-decode               |  28 +++++
 tests/ts/dmesg/kmsg-delta                |  28 +++++
 tests/ts/dmesg/kmsg-facilities           |  31 ++++++
 tests/ts/dmesg/kmsg-indentation          |  40 +++++++
 tests/ts/dmesg/kmsg-limit                |  29 ++++++
 18 files changed, 663 insertions(+), 17 deletions(-)
 create mode 100644 tests/expected/dmesg/kmsg-colors
 create mode 100644 tests/expected/dmesg/kmsg-console-levels
 create mode 100644 tests/expected/dmesg/kmsg-decode
 create mode 100644 tests/expected/dmesg/kmsg-delta
 create mode 100644 tests/expected/dmesg/kmsg-facilities
 create mode 100644 tests/expected/dmesg/kmsg-indentation
 create mode 100644 tests/expected/dmesg/kmsg-limit
 create mode 100755 tests/ts/dmesg/kmsg-colors
 create mode 100755 tests/ts/dmesg/kmsg-console-levels
 create mode 100755 tests/ts/dmesg/kmsg-decode
 create mode 100755 tests/ts/dmesg/kmsg-delta
 create mode 100755 tests/ts/dmesg/kmsg-facilities
 create mode 100755 tests/ts/dmesg/kmsg-indentation
 create mode 100755 tests/ts/dmesg/kmsg-limit
 create mode 100644 tests/ts/dmesg/kmsg-newlines

diff --git a/tests/expected/dmesg/kmsg-colors b/tests/expected/dmesg/kmsg-colors
new file mode 100644
index 000000000..35294c5fa
--- /dev/null
+++ b/tests/expected/dmesg/kmsg-colors
@@ -0,0 +1,45 @@
+kern  :emerg : ^[[32m[    0.000000] ^[[0mLinux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000
+kern  :alert : ^[[32m[    0.000001] ^[[0m^[[33mCommand line: ^[[0m^[[7m^[[31minitrd=\ucode.img initrd=\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system^[[0m
+kern  :crit  : ^[[32m[    0.000002] ^[[0m^[[1m^[[31mBIOS-provided physical RAM map:^[[0m
+kern  :err   : ^[[32m[    0.000003] ^[[0m^[[33mBIOS-e820: ^[[0m^[[31m[mem 0x0000000000000000-0x000000000009efff] usable^[[0m
+kern  :warn  : ^[[32m[    0.000004] ^[[0m^[[33mBIOS-e820: ^[[0m^[[1m[mem 0x000000000009f000-0x00000000000bffff] reserved^[[0m
+kern  :notice: ^[[32m[    0.000005] ^[[0m^[[33mBIOS-e820: ^[[0m[mem 0x0000000000100000-0x0000000009afffff] usable
+kern  :info  : ^[[32m[    0.000006] ^[[0m^[[33mBIOS-e820: ^[[0m[mem 0x0000000009b00000-0x0000000009dfffff] reserved
+kern  :debug : ^[[32m[    0.000007] ^[[0m^[[33mBIOS-e820: ^[[0m[mem 0x0000000009e00000-0x0000000009efffff] usable
+kern  :info  : ^[[32m[    0.000008] ^[[0m^[[33mBIOS-e820: ^[[0m[mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS
+kern  :info  : ^[[32m[    0.000009] ^[[0m^[[33mBIOS-e820: ^[[0m[mem 0x0000000009f3c000-0x000000004235ffff] usable
+kern  :info  : ^[[32m[    0.000010] ^[[0m^[[33mBIOS-e820: ^[[0m[mem 0x0000000042360000-0x000000004455ffff] reserved
+kern  :info  : ^[[32m[    0.201607] ^[[0m^[[33msmp: ^[[0mBringing up secondary CPUs ...
+kern  :info  : ^[[32m[    0.201607] ^[[0m^[[33msmpboot: ^[[0mx86: Booting SMP configuration:
+kern  :warn  : ^[[32m[    0.209670] ^[[0m^[[1m  #1  #3  #5  #7^[[0m
+kern  :info  : ^[[32m[    0.212630] ^[[0m^[[33msmp: ^[[0mBrought up 1 node, 16 CPUs
+kern  :notice: ^[[32m[    0.215936] ^[[0m^[[33maudit: ^[[0mtype=2000 audit(1702926179.015:1): state=initialized audit_enabled=0 res=1
+kern  :info  : ^[[32m[    0.215937] ^[[0m^[[33mthermal_sys: ^[[0mRegistered thermal governor 'fair_share'
+kern  :warn  : ^[[32m[    0.215966] ^[[0m^[[33mENERGY_PERF_BIAS: ^[[0m^[[1mSet to 'normal', was 'performance'^[[0m
+kern  :info  : ^[[32m[    0.367657] ^[[0m^[[33mACPI: ^[[0m\_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+kern  :info  : ^[[32m[    0.368615] ^[[0m^[[33mACPI: ^[[0m\_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+kern  :info  : ^[[32m[    0.376316] ^[[0m^[[33mACPI: ^[[0m\_SB_.PRWL: New power resource
+kern  :info  : ^[[32m[    0.376343] ^[[0m^[[33mACPI: ^[[0m\_SB_.PRWB: New power resource
+kern  :info  : ^[[32m[    0.377373] ^[[0m^[[33mACPI: ^[[0mPCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+kern  :info  : ^[[32m[    0.377378] ^[[0m^[[33macpi PNP0A08:00: ^[[0m_OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+kern  :info  : ^[[32m[    0.377569] ^[[0m^[[33macpi PNP0A08:00: ^[[0m_OSC: platform does not support [SHPCHotplug AER]
+kern  :info  : ^[[32m[    0.377933] ^[[0m^[[33macpi PNP0A08:00: ^[[0m_OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+kern  :info  : ^[[32m[    0.378458] ^[[0mPCI host bridge to bus 0000:00
+kern  :info  : ^[[32m[    0.378459] ^[[0m^[[33mpci_bus 0000:00: ^[[0mroot bus resource [io  0x0000-0x0cf7 window]
+kern  :info  : ^[[32m[    0.378461] ^[[0m^[[33mpci_bus 0000:00: ^[[0mroot bus resource [io  0x0d00-0xffff window]
+user  :notice: ^[[32m[    9.398562] ^[[0muser network daemon initialization complete
+daemon:info  : ^[[32m[   10.441520] ^[[0m^[[33msystemd[1]: ^[[0msystemd 254.7-1.fc39 running in system mode
+daemon:info  : ^[[32m[   11.441524] ^[[0m^[[33msystemd[1]: ^[[0mDetected architecture x86-64.
+daemon:info  : ^[[32m[   12.441525] ^[[0m^[[33msystemd[1]: ^[[0mRunning in initrd.
+daemon:info  : ^[[32m[   13.541598] ^[[0m^[[33msystemd[1]: ^[[0mHostname set to <catalina>.
+kern  :info  : ^[[32m[   15.641860] ^[[0m^[[33musb 3-3: ^[[0mNew USB device found, idVendor=1a40, idProduct=0101, bcdDevice= 1.11
+kern  :err   : ^[[32m[   16.690000] ^[[0m^[[33mSerial bus multi instantiate pseudo device driver INT3515:00: ^[[0m^[[31merror -ENXIO: IRQ index 1 not found.^[[0m
+kern  :err   : ^[[32m[   17.710000] ^[[0m^[[33msnd_hda_intel 0000:00:1f.3: ^[[0m^[[31mCORB reset timeout#2, CORBRP = 65535^[[0m
+syslog:info  : ^[[32m[   18.820000] ^[[0m^[[33msystemd-journald[723]: ^[[0mReceived client request to flush runtime journal.
+syslog:warn  : ^[[32m[   20.840000] ^[[0m^[[33msystemd-journald[723]: ^[[0m^[[1mFile /var/log/journal/a124ea923b144109a12d557d5ac53179/system.journal corrupted or uncleanly shut down, renaming and replacing.^[[0m
+syslog:info  : ^[[32m[   21.852348] ^[[0m^[[33msystemd-journald[723]: ^[[0m/var/log/journal/ad7a2547ac0e4342a342e62a34a3eae4/user-1000.journal: Journal file uses a different sequence number ID, rotating.
+kern  :warn  : ^[[32m[   24.871100] ^[[0m^[[33mPEFILE: ^[[0m^[[1mUnsigned PE binary^[[0m
+kern  :err   : ^[[32m[   33.918091] ^[[0m^[[33msnd_hda_intel 0000:00:1f.3: ^[[0m^[[31mCORB reset timeout#2, CORBRP = 65535^[[0m
+kern  :info  : ^[[32m[  144.931785] ^[[0m^[[33musb 3-3.1: ^[[0mdevice firmware changed
+kern  :info  : ^[[32m[  145.953248] ^[[0m^[[33musb 3-3.1: ^[[0mUSB disconnect, device number 44
+kern  :info  : ^[[32m[  147.981859] ^[[0m^[[33musb 3-3.1: ^[[0mNew USB device found, idVendor=17ef, idProduct=6047, bcdDevice= 3.30
diff --git a/tests/expected/dmesg/kmsg-console-levels b/tests/expected/dmesg/kmsg-console-levels
new file mode 100644
index 000000000..d48312510
--- /dev/null
+++ b/tests/expected/dmesg/kmsg-console-levels
@@ -0,0 +1,61 @@
+* Output level: err+
+<0>[    0.000000] Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000
+<1>[    0.000001] Command line: initrd=\ucode.img initrd=\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system
+<2>[    0.000002] BIOS-provided physical RAM map:
+<3>[    0.000003] BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable
+<3>[   16.690000] Serial bus multi instantiate pseudo device driver INT3515:00: error -ENXIO: IRQ index 1 not found.
+<3>[   17.710000] snd_hda_intel 0000:00:1f.3: CORB reset timeout#2, CORBRP = 65535
+<3>[   33.918091] snd_hda_intel 0000:00:1f.3: CORB reset timeout#2, CORBRP = 65535
+* Output level: emerg+
+<0>[    0.000000] Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000
+* Output level: +err
+<3>[    0.000003] BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable
+<4>[    0.000004] BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved
+<5>[    0.000005] BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable
+<6>[    0.000006] BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved
+<7>[    0.000007] BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable
+<6>[    0.000008] BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS
+<6>[    0.000009] BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable
+<6>[    0.000010] BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved
+<6>[    0.201607] smp: Bringing up secondary CPUs ...
+<6>[    0.201607] smpboot: x86: Booting SMP configuration:
+<4>[    0.209670]   #1  #3  #5  #7
+<6>[    0.212630] smp: Brought up 1 node, 16 CPUs
+<5>[    0.215936] audit: type=2000 audit(1702926179.015:1): state=initialized audit_enabled=0 res=1
+<6>[    0.215937] thermal_sys: Registered thermal governor 'fair_share'
+<4>[    0.215966] ENERGY_PERF_BIAS: Set to 'normal', was 'performance'
+<6>[    0.367657] ACPI: \_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+<6>[    0.368615] ACPI: \_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+<6>[    0.376316] ACPI: \_SB_.PRWL: New power resource
+<6>[    0.376343] ACPI: \_SB_.PRWB: New power resource
+<6>[    0.377373] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+<6>[    0.377378] acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+<6>[    0.377569] acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]
+<6>[    0.377933] acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+<6>[    0.378458] PCI host bridge to bus 0000:00
+<6>[    0.378459] pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]
+<6>[    0.378461] pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]
+<13>[    9.398562] user network daemon initialization complete
+<30>[   10.441520] systemd[1]: systemd 254.7-1.fc39 running in system mode
+<30>[   11.441524] systemd[1]: Detected architecture x86-64.
+<30>[   12.441525] systemd[1]: Running in initrd.
+<30>[   13.541598] systemd[1]: Hostname set to <catalina>.
+<6>[   15.641860] usb 3-3: New USB device found, idVendor=1a40, idProduct=0101, bcdDevice= 1.11
+<3>[   16.690000] Serial bus multi instantiate pseudo device driver INT3515:00: error -ENXIO: IRQ index 1 not found.
+<3>[   17.710000] snd_hda_intel 0000:00:1f.3: CORB reset timeout#2, CORBRP = 65535
+<46>[   18.820000] systemd-journald[723]: Received client request to flush runtime journal.
+<44>[   20.840000] systemd-journald[723]: File /var/log/journal/a124ea923b144109a12d557d5ac53179/system.journal corrupted or uncleanly shut down, renaming and replacing.
+<46>[   21.852348] systemd-journald[723]: /var/log/journal/ad7a2547ac0e4342a342e62a34a3eae4/user-1000.journal: Journal file uses a different sequence number ID, rotating.
+<4>[   24.871100] PEFILE: Unsigned PE binary
+<3>[   33.918091] snd_hda_intel 0000:00:1f.3: CORB reset timeout#2, CORBRP = 65535
+<6>[  144.931785] usb 3-3.1: device firmware changed
+<6>[  145.953248] usb 3-3.1: USB disconnect, device number 44
+<6>[  147.981859] usb 3-3.1: New USB device found, idVendor=17ef, idProduct=6047, bcdDevice= 3.30
+* Output level: +debug
+<7>[    0.000007] BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable
+* Output level: notice
+<5>[    0.000005] BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable
+<5>[    0.215936] audit: type=2000 audit(1702926179.015:1): state=initialized audit_enabled=0 res=1
+<13>[    9.398562] user network daemon initialization complete
+* Output level: +
+test_dmesg: unknown level '+'
diff --git a/tests/expected/dmesg/kmsg-decode b/tests/expected/dmesg/kmsg-decode
new file mode 100644
index 000000000..85a664a61
--- /dev/null
+++ b/tests/expected/dmesg/kmsg-decode
@@ -0,0 +1,45 @@
+kern  :emerg : [    0.000000] Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000
+kern  :alert : [    0.000001] Command line: initrd=\ucode.img initrd=\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system
+kern  :crit  : [    0.000002] BIOS-provided physical RAM map:
+kern  :err   : [    0.000003] BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable
+kern  :warn  : [    0.000004] BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved
+kern  :notice: [    0.000005] BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable
+kern  :info  : [    0.000006] BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved
+kern  :debug : [    0.000007] BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable
+kern  :info  : [    0.000008] BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS
+kern  :info  : [    0.000009] BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable
+kern  :info  : [    0.000010] BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved
+kern  :info  : [    0.201607] smp: Bringing up secondary CPUs ...
+kern  :info  : [    0.201607] smpboot: x86: Booting SMP configuration:
+kern  :warn  : [    0.209670]   #1  #3  #5  #7
+kern  :info  : [    0.212630] smp: Brought up 1 node, 16 CPUs
+kern  :notice: [    0.215936] audit: type=2000 audit(1702926179.015:1): state=initialized audit_enabled=0 res=1
+kern  :info  : [    0.215937] thermal_sys: Registered thermal governor 'fair_share'
+kern  :warn  : [    0.215966] ENERGY_PERF_BIAS: Set to 'normal', was 'performance'
+kern  :info  : [    0.367657] ACPI: \_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+kern  :info  : [    0.368615] ACPI: \_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+kern  :info  : [    0.376316] ACPI: \_SB_.PRWL: New power resource
+kern  :info  : [    0.376343] ACPI: \_SB_.PRWB: New power resource
+kern  :info  : [    0.377373] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+kern  :info  : [    0.377378] acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+kern  :info  : [    0.377569] acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]
+kern  :info  : [    0.377933] acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+kern  :info  : [    0.378458] PCI host bridge to bus 0000:00
+kern  :info  : [    0.378459] pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]
+kern  :info  : [    0.378461] pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]
+user  :notice: [    9.398562] user network daemon initialization complete
+daemon:info  : [   10.441520] systemd[1]: systemd 254.7-1.fc39 running in system mode
+daemon:info  : [   11.441524] systemd[1]: Detected architecture x86-64.
+daemon:info  : [   12.441525] systemd[1]: Running in initrd.
+daemon:info  : [   13.541598] systemd[1]: Hostname set to <catalina>.
+kern  :info  : [   15.641860] usb 3-3: New USB device found, idVendor=1a40, idProduct=0101, bcdDevice= 1.11
+kern  :err   : [   16.690000] Serial bus multi instantiate pseudo device driver INT3515:00: error -ENXIO: IRQ index 1 not found.
+kern  :err   : [   17.710000] snd_hda_intel 0000:00:1f.3: CORB reset timeout#2, CORBRP = 65535
+syslog:info  : [   18.820000] systemd-journald[723]: Received client request to flush runtime journal.
+syslog:warn  : [   20.840000] systemd-journald[723]: File /var/log/journal/a124ea923b144109a12d557d5ac53179/system.journal corrupted or uncleanly shut down, renaming and replacing.
+syslog:info  : [   21.852348] systemd-journald[723]: /var/log/journal/ad7a2547ac0e4342a342e62a34a3eae4/user-1000.journal: Journal file uses a different sequence number ID, rotating.
+kern  :warn  : [   24.871100] PEFILE: Unsigned PE binary
+kern  :err   : [   33.918091] snd_hda_intel 0000:00:1f.3: CORB reset timeout#2, CORBRP = 65535
+kern  :info  : [  144.931785] usb 3-3.1: device firmware changed
+kern  :info  : [  145.953248] usb 3-3.1: USB disconnect, device number 44
+kern  :info  : [  147.981859] usb 3-3.1: New USB device found, idVendor=17ef, idProduct=6047, bcdDevice= 3.30
diff --git a/tests/expected/dmesg/kmsg-delta b/tests/expected/dmesg/kmsg-delta
new file mode 100644
index 000000000..caea3e9db
--- /dev/null
+++ b/tests/expected/dmesg/kmsg-delta
@@ -0,0 +1,45 @@
+[    0.000000 <    0.000000>] Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000
+[    0.000001 <    0.000000>] Command line: initrd=\ucode.img initrd=\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system
+[    0.000002 <    0.000000>] BIOS-provided physical RAM map:
+[    0.000003 <    0.000000>] BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable
+[    0.000004 <    0.000000>] BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved
+[    0.000005 <    0.000000>] BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable
+[    0.000006 <    0.000000>] BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved
+[    0.000007 <    0.000000>] BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable
+[    0.000008 <    0.000000>] BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS
+[    0.000009 <    0.000000>] BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable
+[    0.000010 <    0.000000>] BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved
+[    0.201607 <    0.000000>] smp: Bringing up secondary CPUs ...
+[    0.201607 <    0.000000>] smpboot: x86: Booting SMP configuration:
+[    0.209670 <    0.000000>]   #1  #3  #5  #7
+[    0.212630 <    0.000000>] smp: Brought up 1 node, 16 CPUs
+[    0.215936 <    0.000000>] audit: type=2000 audit(1702926179.015:1): state=initialized audit_enabled=0 res=1
+[    0.215937 <    0.000000>] thermal_sys: Registered thermal governor 'fair_share'
+[    0.215966 <    0.000000>] ENERGY_PERF_BIAS: Set to 'normal', was 'performance'
+[    0.367657 <    0.000000>] ACPI: \_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+[    0.368615 <    0.000000>] ACPI: \_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+[    0.376316 <    0.000000>] ACPI: \_SB_.PRWL: New power resource
+[    0.376343 <    0.000000>] ACPI: \_SB_.PRWB: New power resource
+[    0.377373 <    0.000000>] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+[    0.377378 <    0.000000>] acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+[    0.377569 <    0.000000>] acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]
+[    0.377933 <    0.000000>] acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+[    0.378458 <    0.000000>] PCI host bridge to bus 0000:00
+[    0.378459 <    0.000000>] pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]
+[    0.378461 <    0.000000>] pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]
+[    9.398562 <    9.000000>] user network daemon initialization complete
+[   10.441520 <    1.000000>] systemd[1]: systemd 254.7-1.fc39 running in system mode
+[   11.441524 <    1.000000>] systemd[1]: Detected architecture x86-64.
+[   12.441525 <    1.000000>] systemd[1]: Running in initrd.
+[   13.541598 <    1.000000>] systemd[1]: Hostname set to <catalina>.
+[   15.641860 <    2.000000>] usb 3-3: New USB device found, idVendor=1a40, idProduct=0101, bcdDevice= 1.11
+[   16.690000 <    1.000000>] Serial bus multi instantiate pseudo device driver INT3515:00: error -ENXIO: IRQ index 1 not found.
+[   17.710000 <    1.000000>] snd_hda_intel 0000:00:1f.3: CORB reset timeout#2, CORBRP = 65535
+[   18.820000 <    1.000000>] systemd-journald[723]: Received client request to flush runtime journal.
+[   20.840000 <    2.000000>] systemd-journald[723]: File /var/log/journal/a124ea923b144109a12d557d5ac53179/system.journal corrupted or uncleanly shut down, renaming and replacing.
+[   21.852348 <    1.000000>] systemd-journald[723]: /var/log/journal/ad7a2547ac0e4342a342e62a34a3eae4/user-1000.journal: Journal file uses a different sequence number ID, rotating.
+[   24.871100 <    3.000000>] PEFILE: Unsigned PE binary
+[   33.918091 <    9.000000>] snd_hda_intel 0000:00:1f.3: CORB reset timeout#2, CORBRP = 65535
+[  144.931785 <  111.000000>] usb 3-3.1: device firmware changed
+[  145.953248 <    1.000000>] usb 3-3.1: USB disconnect, device number 44
+[  147.981859 <    2.000000>] usb 3-3.1: New USB device found, idVendor=17ef, idProduct=6047, bcdDevice= 3.30
diff --git a/tests/expected/dmesg/kmsg-facilities b/tests/expected/dmesg/kmsg-facilities
new file mode 100644
index 000000000..4b460951a
--- /dev/null
+++ b/tests/expected/dmesg/kmsg-facilities
@@ -0,0 +1,59 @@
+dmesg Facility: -1
+dmesg Facility: 0
+[    0.000000] Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000
+[    0.000001] Command line: initrd=\ucode.img initrd=\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system
+[    0.000002] BIOS-provided physical RAM map:
+[    0.000003] BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable
+[    0.000004] BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved
+[    0.000005] BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable
+[    0.000006] BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved
+[    0.000007] BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable
+[    0.000008] BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS
+[    0.000009] BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable
+[    0.000010] BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved
+[    0.201607] smp: Bringing up secondary CPUs ...
+[    0.201607] smpboot: x86: Booting SMP configuration:
+[    0.209670]   #1  #3  #5  #7
+[    0.212630] smp: Brought up 1 node, 16 CPUs
+[    0.215936] audit: type=2000 audit(1702926179.015:1): state=initialized audit_enabled=0 res=1
+[    0.215937] thermal_sys: Registered thermal governor 'fair_share'
+[    0.215966] ENERGY_PERF_BIAS: Set to 'normal', was 'performance'
+[    0.367657] ACPI: \_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+[    0.368615] ACPI: \_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+[    0.376316] ACPI: \_SB_.PRWL: New power resource
+[    0.376343] ACPI: \_SB_.PRWB: New power resource
+[    0.377373] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+[    0.377378] acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+[    0.377569] acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]
+[    0.377933] acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+[    0.378458] PCI host bridge to bus 0000:00
+[    0.378459] pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]
+[    0.378461] pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]
+[   15.641860] usb 3-3: New USB device found, idVendor=1a40, idProduct=0101, bcdDevice= 1.11
+[   16.690000] Serial bus multi instantiate pseudo device driver INT3515:00: error -ENXIO: IRQ index 1 not found.
+[   17.710000] snd_hda_intel 0000:00:1f.3: CORB reset timeout#2, CORBRP = 65535
+[   24.871100] PEFILE: Unsigned PE binary
+[   33.918091] snd_hda_intel 0000:00:1f.3: CORB reset timeout#2, CORBRP = 65535
+[  144.931785] usb 3-3.1: device firmware changed
+[  145.953248] usb 3-3.1: USB disconnect, device number 44
+[  147.981859] usb 3-3.1: New USB device found, idVendor=17ef, idProduct=6047, bcdDevice= 3.30
+dmesg Facility: 1
+[    9.398562] user network daemon initialization complete
+dmesg Facility: 2
+dmesg Facility: 3
+[   10.441520] systemd[1]: systemd 254.7-1.fc39 running in system mode
+[   11.441524] systemd[1]: Detected architecture x86-64.
+[   12.441525] systemd[1]: Running in initrd.
+[   13.541598] systemd[1]: Hostname set to <catalina>.
+dmesg Facility: 4
+dmesg Facility: 5
+[   18.820000] systemd-journald[723]: Received client request to flush runtime journal.
+[   20.840000] systemd-journald[723]: File /var/log/journal/a124ea923b144109a12d557d5ac53179/system.journal corrupted or uncleanly shut down, renaming and replacing.
+[   21.852348] systemd-journald[723]: /var/log/journal/ad7a2547ac0e4342a342e62a34a3eae4/user-1000.journal: Journal file uses a different sequence number ID, rotating.
+dmesg Facility: 6
+dmesg Facility: 7
+dmesg Facility: 8
+dmesg Facility: 9
+dmesg Facility: 10
+dmesg Facility: 11
+dmesg Facility: 12
diff --git a/tests/expected/dmesg/kmsg-file b/tests/expected/dmesg/kmsg-file
index 54b5e612d..984588e3e 100644
--- a/tests/expected/dmesg/kmsg-file
+++ b/tests/expected/dmesg/kmsg-file
@@ -1,49 +1,77 @@
 {
    "dmesg": [
       {
-         "pri": 5,
+         "pri": 0,
          "time":     0.000000,
          "msg": "Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000"
       },{
-         "pri": 6,
-         "time":     0.000000,
+         "pri": 1,
+         "time":     0.000001,
          "msg": "Command line: initrd=\\ucode.img initrd=\\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system"
       },{
-         "pri": 6,
-         "time":     0.000000,
+         "pri": 2,
+         "time":     0.000002,
          "msg": "BIOS-provided physical RAM map:"
       },{
-         "pri": 6,
-         "time":     0.000000,
+         "pri": 3,
+         "time":     0.000003,
          "msg": "BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable"
       },{
-         "pri": 6,
-         "time":     0.000000,
+         "pri": 4,
+         "time":     0.000004,
          "msg": "BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved"
       },{
-         "pri": 6,
-         "time":     0.000000,
+         "pri": 5,
+         "time":     0.000005,
          "msg": "BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable"
       },{
          "pri": 6,
-         "time":     0.000000,
+         "time":     0.000006,
          "msg": "BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved"
       },{
-         "pri": 6,
-         "time":     0.000000,
+         "pri": 7,
+         "time":     0.000007,
          "msg": "BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable"
       },{
          "pri": 6,
-         "time":     0.000000,
+         "time":     0.000008,
          "msg": "BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS"
       },{
          "pri": 6,
-         "time":     0.000000,
+         "time":     0.000009,
          "msg": "BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable"
       },{
          "pri": 6,
-         "time":     0.000000,
+         "time":     0.000010,
          "msg": "BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved"
+      },{
+         "pri": 6,
+         "time":     0.201607,
+         "msg": "smp: Bringing up secondary CPUs ..."
+      },{
+         "pri": 6,
+         "time":     0.201607,
+         "msg": "smpboot: x86: Booting SMP configuration:"
+      },{
+         "pri": 4,
+         "time":     0.209670,
+         "msg": "  #1  #3  #5  #7"
+      },{
+         "pri": 6,
+         "time":     0.212630,
+         "msg": "smp: Brought up 1 node, 16 CPUs"
+      },{
+         "pri": 5,
+         "time":     0.215936,
+         "msg": "audit: type=2000 audit(1702926179.015:1): state=initialized audit_enabled=0 res=1"
+      },{
+         "pri": 6,
+         "time":     0.215937,
+         "msg": "thermal_sys: Registered thermal governor 'fair_share'"
+      },{
+         "pri": 4,
+         "time":     0.215966,
+         "msg": "ENERGY_PERF_BIAS: Set to 'normal', was 'performance'"
       },{
          "pri": 6,
          "time":     0.367657,
@@ -88,6 +116,70 @@
          "pri": 6,
          "time":     0.378461,
          "msg": "pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]"
+      },{
+         "pri": 13,
+         "time":     9.398562,
+         "msg": "user network daemon initialization complete"
+      },{
+         "pri": 30,
+         "time":    10.441520,
+         "msg": "systemd[1]: systemd 254.7-1.fc39 running in system mode"
+      },{
+         "pri": 30,
+         "time":    11.441524,
+         "msg": "systemd[1]: Detected architecture x86-64."
+      },{
+         "pri": 30,
+         "time":    12.441525,
+         "msg": "systemd[1]: Running in initrd."
+      },{
+         "pri": 30,
+         "time":    13.541598,
+         "msg": "systemd[1]: Hostname set to <catalina>."
+      },{
+         "pri": 6,
+         "time":    15.641860,
+         "msg": "usb 3-3: New USB device found, idVendor=1a40, idProduct=0101, bcdDevice= 1.11"
+      },{
+         "pri": 3,
+         "time":    16.690000,
+         "msg": "Serial bus multi instantiate pseudo device driver INT3515:00: error -ENXIO: IRQ index 1 not found."
+      },{
+         "pri": 3,
+         "time":    17.710000,
+         "msg": "snd_hda_intel 0000:00:1f.3: CORB reset timeout#2, CORBRP = 65535"
+      },{
+         "pri": 46,
+         "time":    18.820000,
+         "msg": "systemd-journald[723]: Received client request to flush runtime journal."
+      },{
+         "pri": 44,
+         "time":    20.840000,
+         "msg": "systemd-journald[723]: File /var/log/journal/a124ea923b144109a12d557d5ac53179/system.journal corrupted or uncleanly shut down, renaming and replacing."
+      },{
+         "pri": 46,
+         "time":    21.852348,
+         "msg": "systemd-journald[723]: /var/log/journal/ad7a2547ac0e4342a342e62a34a3eae4/user-1000.journal: Journal file uses a different sequence number ID, rotating."
+      },{
+         "pri": 4,
+         "time":    24.871100,
+         "msg": "PEFILE: Unsigned PE binary"
+      },{
+         "pri": 3,
+         "time":    33.918091,
+         "msg": "snd_hda_intel 0000:00:1f.3: CORB reset timeout#2, CORBRP = 65535"
+      },{
+         "pri": 6,
+         "time":   144.931785,
+         "msg": "usb 3-3.1: device firmware changed"
+      },{
+         "pri": 6,
+         "time":   145.953248,
+         "msg": "usb 3-3.1: USB disconnect, device number 44"
+      },{
+         "pri": 6,
+         "time":   147.981859,
+         "msg": "usb 3-3.1: New USB device found, idVendor=17ef, idProduct=6047, bcdDevice= 3.30"
       }
    ]
 }
diff --git a/tests/expected/dmesg/kmsg-indentation b/tests/expected/dmesg/kmsg-indentation
new file mode 100644
index 000000000..25f41b454
--- /dev/null
+++ b/tests/expected/dmesg/kmsg-indentation
@@ -0,0 +1,35 @@
+[    1.000000] line zero
+[    2.000000] line one
+[    4.000000] line two
+[    7.000000] line three
+[   11.000000] line four
+kern  :notice: [    1.000000] line zero
+user  :crit  : [    2.000000] line one
+mail  :warn  : [    4.000000] line two
+daemon:info  : [    7.000000] line three
+syslog:emerg : [   11.000000] line four
+[<    0.000000>] line zero
+[<    1.000000>] line one
+[<    2.000000>] line two
+[<    3.000000>] line three
+[<    4.000000>] line four
+line zero
+line one
+line two
+line three
+line four
+[Feb13 23:31] line zero
+[  +1.000000] line one
+[  +2.000000] line two
+[  +3.000000] line three
+[  +4.000000] line four
+[Fri Feb 13 23:31:31 2009] line zero
+[Fri Feb 13 23:31:32 2009] line one
+[Fri Feb 13 23:31:34 2009] line two
+[Fri Feb 13 23:31:37 2009] line three
+[Fri Feb 13 23:31:41 2009] line four
+2009-02-13T23:31:31,123456+00:00 line zero
+2009-02-13T23:31:32,123456+00:00 line one
+2009-02-13T23:31:34,123456+00:00 line two
+2009-02-13T23:31:37,123456+00:00 line three
+2009-02-13T23:31:41,123456+00:00 line four
diff --git a/tests/expected/dmesg/kmsg-limit b/tests/expected/dmesg/kmsg-limit
new file mode 100644
index 000000000..0c39b4762
--- /dev/null
+++ b/tests/expected/dmesg/kmsg-limit
@@ -0,0 +1,31 @@
+[    0.201607] smp: Bringing up secondary CPUs ...
+[    0.201607] smpboot: x86: Booting SMP configuration:
+[    0.209670]   #1  #3  #5  #7
+[    0.212630] smp: Brought up 1 node, 16 CPUs
+[    0.215936] audit: type=2000 audit(1702926179.015:1): state=initialized audit_enabled=0 res=1
+[    0.215937] thermal_sys: Registered thermal governor 'fair_share'
+[    0.215966] ENERGY_PERF_BIAS: Set to 'normal', was 'performance'
+[    0.367657] ACPI: \_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+[    0.368615] ACPI: \_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+[    0.376316] ACPI: \_SB_.PRWL: New power resource
+[    0.376343] ACPI: \_SB_.PRWB: New power resource
+[    0.377373] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+[    0.377378] acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+[    0.377569] acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]
+[    0.377933] acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+[    0.378458] PCI host bridge to bus 0000:00
+[    0.378459] pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]
+[    0.378461] pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]
+[    9.398562] user network daemon initialization complete
+[   10.441520] systemd[1]: systemd 254.7-1.fc39 running in system mode
+[   11.441524] systemd[1]: Detected architecture x86-64.
+[   12.441525] systemd[1]: Running in initrd.
+[   13.541598] systemd[1]: Hostname set to <catalina>.
+[   15.641860] usb 3-3: New USB device found, idVendor=1a40, idProduct=0101, bcdDevice= 1.11
+[   16.690000] Serial bus multi instantiate pseudo device driver INT3515:00: error -ENXIO: IRQ index 1 not found.
+[   17.710000] snd_hda_intel 0000:00:1f.3: CORB reset timeout#2, CORBRP = 65535
+[   18.820000] systemd-journald[723]: Received client request to flush runtime journal.
+[   20.840000] systemd-journald[723]: File /var/log/journal/a124ea923b144109a12d557d5ac53179/system.journal corrupted or uncleanly shut down, renaming and replacing.
+[   21.852348] systemd-journald[723]: /var/log/journal/ad7a2547ac0e4342a342e62a34a3eae4/user-1000.journal: Journal file uses a different sequence number ID, rotating.
+[   24.871100] PEFILE: Unsigned PE binary
+[   33.918091] snd_hda_intel 0000:00:1f.3: CORB reset timeout#2, CORBRP = 65535
diff --git a/tests/ts/dmesg/kmsg-colors b/tests/ts/dmesg/kmsg-colors
new file mode 100755
index 000000000..959e7b547
--- /dev/null
+++ b/tests/ts/dmesg/kmsg-colors
@@ -0,0 +1,29 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="kmsg-colors"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+ts_inhibit_custom_colorscheme
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG --color=always -K $TS_SELF/kmsg-input -x >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/kmsg-console-levels b/tests/ts/dmesg/kmsg-console-levels
new file mode 100755
index 000000000..36f8ec097
--- /dev/null
+++ b/tests/ts/dmesg/kmsg-console-levels
@@ -0,0 +1,43 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="kmsg-levels"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+for I in {-1..8}; do
+	$TS_HELPER_DMESG -F $TS_SELF/kmsg-input -l $I >> $TS_OUTPUT 2>/dev/null
+done
+
+echo "* Output level: err+" >> $TS_OUTPUT 2>/dev/null
+$TS_HELPER_DMESG -K $TS_SELF/kmsg-input -r -l err+ >> $TS_OUTPUT 2>/dev/null
+echo "* Output level: emerg+" >> $TS_OUTPUT 2>/dev/null
+$TS_HELPER_DMESG -K $TS_SELF/kmsg-input -r -l emerg+ >> $TS_OUTPUT 2>/dev/null
+echo "* Output level: +err" >> $TS_OUTPUT 2>/dev/null
+$TS_HELPER_DMESG -K $TS_SELF/kmsg-input -r -l +err >> $TS_OUTPUT 2>/dev/null
+echo "* Output level: +debug" >> $TS_OUTPUT 2>/dev/null
+$TS_HELPER_DMESG -K $TS_SELF/kmsg-input -r -l +debug >> $TS_OUTPUT 2>/dev/null
+echo "* Output level: notice" >> $TS_OUTPUT 2>/dev/null
+$TS_HELPER_DMESG -K $TS_SELF/kmsg-input -r -l notice >> $TS_OUTPUT 2>/dev/null
+echo "* Output level: +" >> $TS_OUTPUT 2>/dev/null
+$TS_HELPER_DMESG -K $TS_SELF/kmsg-input -r -l + 2>> $TS_OUTPUT >/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/kmsg-decode b/tests/ts/dmesg/kmsg-decode
new file mode 100755
index 000000000..51fef159d
--- /dev/null
+++ b/tests/ts/dmesg/kmsg-decode
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="kmsg-decode"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG -x -K $TS_SELF/kmsg-input >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/kmsg-delta b/tests/ts/dmesg/kmsg-delta
new file mode 100755
index 000000000..7ae082e76
--- /dev/null
+++ b/tests/ts/dmesg/kmsg-delta
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="kmsg-delta"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG -d -K $TS_SELF/kmsg-input >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/kmsg-facilities b/tests/ts/dmesg/kmsg-facilities
new file mode 100755
index 000000000..b274c5de4
--- /dev/null
+++ b/tests/ts/dmesg/kmsg-facilities
@@ -0,0 +1,31 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="kmsg-facilities"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+for I in {-1..12}; do
+        echo "dmesg Facility: $I" >> $TS_OUTPUT
+	$TS_HELPER_DMESG -K $TS_SELF/kmsg-input -f $I >> $TS_OUTPUT 2>/dev/null
+done
+
+ts_finalize
diff --git a/tests/ts/dmesg/kmsg-indentation b/tests/ts/dmesg/kmsg-indentation
new file mode 100755
index 000000000..16870158f
--- /dev/null
+++ b/tests/ts/dmesg/kmsg-indentation
@@ -0,0 +1,40 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="kmsg-indentation"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG -K $TS_SELF/kmsg-newlines >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG -K $TS_SELF/kmsg-newlines -x >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=delta --kmsg-file $TS_SELF/kmsg-newlines >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=notime --kmsg-file $TS_SELF/kmsg-newlines >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=reltime --kmsg-file $TS_SELF/kmsg-newlines >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=ctime --kmsg-file $TS_SELF/kmsg-newlines >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=iso --kmsg-file $TS_SELF/kmsg-newlines >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+ts_finalize
diff --git a/tests/ts/dmesg/kmsg-limit b/tests/ts/dmesg/kmsg-limit
new file mode 100755
index 000000000..ff70bcf83
--- /dev/null
+++ b/tests/ts/dmesg/kmsg-limit
@@ -0,0 +1,29 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="kmsg-limit"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG --since @1234567890.124 --until @1234567991 -K $TS_SELF/kmsg-input \
+	>> $TS_OUTPUT 2> $TS_ERRLOG
+
+ts_finalize
-- 
2.43.0


^ permalink raw reply related

* [PATCH] util-linux/sys-utils dmesg add PRINTK_CALLER support
From: Edward Chron @ 2023-12-28 20:31 UTC (permalink / raw)
  To: util-linux; +Cc: colona, echron, echron

Submission to Project: util-linux
Open Incident: #2609 at github.com/util-linux/util-linux/issues/2609
Component: util-linux/sys-utils
File: dmesg.c
Code level patch applied against: 2.39.3 - latest code pulled from
           git.github.com:util-linux/util-linux.git
Revision: #1 on 2023/12/08 per Review from Karel Zak
Revision: #2 on 2023/12/12 Adjust line offsets for master update and
                           Add caller_id_size init to dmesg -K
Revision: #3 on 2023/12/12 Use of sizeof for cidbuf and limit search
                           for caller_id to dmesg prefix to msg text
Revision: #4 on 2023/12/15 Ensure SYSLOG and kmsg inputs have
                           caller_id_size set appropriately
Revision: #5 on 2023/12/24 Make caller_id width consistent with
                           makedumpfile

Add support to standard dmesg command for the optional Linux Kernel
debug CONFIG option PRINTK_CALLER which adds an optional dmesg field
that contains the Thread Id or CPU Id that is issuing the printk to
add the message to the kernel ring buffer. This makes debugging simpler
as dmesg entries for a specific thread or CPU can be recognized.

The dmesg -S using the old syslog interface supports printing the
PRINTK_CALLER field but currently standard dmesg does not support
printing the field if present. There are utilities that use dmesg and
so it would be optimal if dmesg supported PRINTK_CALLER as well.

The additional field provided by PRINTK_CALLER is only present
if it was configured for the Linux kernel where the dmesg command
is run. It is a debug option and not configured by default so the
dmesg output will only change for those kernels where the option was
configured when the kernel was built. For users who went to the
trouble to configure PRINTK_CALLER and have the extra field available
for debugging, having dmesg print the field is very helpful.

Size of the PRINTK_CALLER field is determined by the maximum number
tasks that can be run on the system which is limited by the value of
/proc/sys/kernel/pid_max as pid values are from 0 to value - 1.
This value determines the number of id digits needed by the caller id.
The PRINTK_CALLER field is printed as T<id> for a Task Id or C<id>
for a CPU Id for a printk in CPU context. The values are left space
padded and enclosed in parentheses such as: [    T123] or [     C16]

For consistency with dmesg -S which supports the PRINTK_CALLER field
the field is printed followed by a space. For JSON format output the
PRINTK_CALLER field is identified as caller as that is consistent with
it's naming in /dev/kmsg. No space padding is used to reduce space
consumed by the JSON output. So the output from the command on a system
with PRINTK_CALLER field enabled in the Linux .config file the dmesg
output appears as:

> dmesg
...
[  520.897104] [   T3919] usb 3-3: Product: USB 2.0 Hub

and

> dmesg -x
...
kern  :info  : [  520.897104] [   T3919] usb 3-3: Product: USB 2.0 Hub

and

> dmesg -J
...
      },{
         "pri": 6,
         "time":    520.897104,
         "caller": "T3919",
         "msg": "usb 3-3: Product: USB 2.0 Hub"
      },{

and

> dmesg -J -x
...
      },{
         "fac": "kern",
         "pri": "info",
         "time":   520.897104,
         "caller": "T3919",
         "msg": "usb 3-3: Product: USB 2.0 Hub"
      },{

>

For comparison:

> dmesg -S
...
[  520.897104] [ T3919] usb 3-3: Product: USB 2.0 Hub

and

> dmesg -S -x
...
kern  :info  : [  520.897104] [ T3919] usb 3-3: Product: USB 2.0 Hub

Note: When dmesg uses the old syslog interface the reserved space for
      the PRINTK_CALLER field is capped at 5 digits because 32-bit
      kernels are capped at 32768 as the max number of PIDs. However,
      64-bit systems are currently capped at 2^22 PIDs (0 - 4194303).
      The PID cap is set by PID_MAX_LIMIT but the system limit can be
      less so we use /proc/sys/kernel/pid_max to determine the size
      needed to hold the maximum PID value size for the current system.
      Many 64-bit systems support 2^22 PIDs (0 - 4194303) and you see:

> dmesg -x
...
kern  :info  : [  520.899558] [   T3919] hub 3-3:1.0: USB hub found
...
kern  :info  : [ 9830.456898] [  T98982] cgroup: fork rejected by pids ...
kern  :info  : [14301.158878] [ T137336] cgroup: fork rejected by pids ...
kern  :info  : [18980.803190] [T1637865] cgroup: fork rejected by pids ...

> dmesg -S -x
...
kern  :info  : [  520.899558] [ T3919] hub 3-3:1.0: USB hub found
...
kern  :info  : [ 9830.456898] [T98982] cgroup: fork rejected by pids ...
kern  :info  : [14301.158878] [T137336] cgroup: fork rejected by pids ...
kern  :info  : [18980.803190] [T1637865] cgroup: fork rejected by pids ...

This is the only difference seen with PRINTK_CALLER configured and
printing between the dmesg /dev/kmsg interface and the dmesg -S syslog
interface.

Signed-off-by: Ivan Delalande <colona@arista.com>
Signed-off-by: Edward Chron <echron@arista.com>
---
 include/pathnames.h                           |   3 +
 sys-utils/dmesg.c                             | 128 ++++-
 .../expected/dmesg/colors-kmsg-printk-caller  |  22 +
 .../dmesg/console-levels-kmsg-printk-caller   |  45 ++
 .../expected/dmesg/decode-kmsg-printk-caller  |  22 +
 tests/expected/dmesg/delta-kmsg-printk-caller |  22 +
 .../dmesg/facilities-kmsg-printk-caller       |  22 +
 .../dmesg/indentation-kmsg-printk-caller      |  28 +
 tests/expected/dmesg/json-kmsg-printk-caller  | 115 ++++
 .../expected/dmesg/json-syslog-printk-caller  | 530 ++++++++++++++++++
 tests/expected/dmesg/kmsg-file-printk-caller  | 115 ++++
 tests/expected/dmesg/limit-kmsg-printk-caller |  11 +
 tests/ts/dmesg/colors-kmsg-printk-caller      |  29 +
 .../dmesg/console-levels-kmsg-printk-caller   |  36 ++
 tests/ts/dmesg/decode-kmsg-printk-caller      |  28 +
 tests/ts/dmesg/delta-kmsg-printk-caller       |  28 +
 tests/ts/dmesg/facilities-kmsg-printk-caller  |  30 +
 tests/ts/dmesg/indentation-kmsg-printk-caller |  40 ++
 tests/ts/dmesg/input-syslog-printk-caller     | 105 ++++
 tests/ts/dmesg/json-kmsg-printk-caller        |  28 +
 tests/ts/dmesg/json-syslog-printk-caller      |  28 +
 tests/ts/dmesg/kmsg-file-printk-caller        |  28 +
 tests/ts/dmesg/kmsg-input-printk-caller       | Bin 0 -> 2187 bytes
 tests/ts/dmesg/limit-kmsg-printk-caller       |  29 +
 tests/ts/dmesg/newlines-kmsg-printk-caller    | Bin 0 -> 152 bytes
 25 files changed, 1469 insertions(+), 3 deletions(-)
 create mode 100644 tests/expected/dmesg/colors-kmsg-printk-caller
 create mode 100644 tests/expected/dmesg/console-levels-kmsg-printk-caller
 create mode 100644 tests/expected/dmesg/decode-kmsg-printk-caller
 create mode 100644 tests/expected/dmesg/delta-kmsg-printk-caller
 create mode 100644 tests/expected/dmesg/facilities-kmsg-printk-caller
 create mode 100644 tests/expected/dmesg/indentation-kmsg-printk-caller
 create mode 100644 tests/expected/dmesg/json-kmsg-printk-caller
 create mode 100644 tests/expected/dmesg/json-syslog-printk-caller
 create mode 100644 tests/expected/dmesg/kmsg-file-printk-caller
 create mode 100644 tests/expected/dmesg/limit-kmsg-printk-caller
 create mode 100755 tests/ts/dmesg/colors-kmsg-printk-caller
 create mode 100755 tests/ts/dmesg/console-levels-kmsg-printk-caller
 create mode 100755 tests/ts/dmesg/decode-kmsg-printk-caller
 create mode 100755 tests/ts/dmesg/delta-kmsg-printk-caller
 create mode 100755 tests/ts/dmesg/facilities-kmsg-printk-caller
 create mode 100755 tests/ts/dmesg/indentation-kmsg-printk-caller
 create mode 100644 tests/ts/dmesg/input-syslog-printk-caller
 create mode 100755 tests/ts/dmesg/json-kmsg-printk-caller
 create mode 100755 tests/ts/dmesg/json-syslog-printk-caller
 create mode 100755 tests/ts/dmesg/kmsg-file-printk-caller
 create mode 100644 tests/ts/dmesg/kmsg-input-printk-caller
 create mode 100755 tests/ts/dmesg/limit-kmsg-printk-caller
 create mode 100644 tests/ts/dmesg/newlines-kmsg-printk-caller

diff --git a/include/pathnames.h b/include/pathnames.h
index caf0e63d4..81fa405f6 100644
--- a/include/pathnames.h
+++ b/include/pathnames.h
@@ -230,4 +230,7 @@
 /* cgroup path */
 #define _PATH_SYS_CGROUP	"/sys/fs/cgroup"
 
+/* Maximum number of PIDs system supports */
+#define _PATH_PROC_PIDMAX	"/proc/sys/kernel/pid_max"
+
 #endif /* PATHNAMES_H */
diff --git a/sys-utils/dmesg.c b/sys-utils/dmesg.c
index 77728b419..e27966b05 100644
--- a/sys-utils/dmesg.c
+++ b/sys-utils/dmesg.c
@@ -13,7 +13,9 @@
  */
 #include <stdio.h>
 #include <getopt.h>
+#include <stdbool.h>
 #include <stdlib.h>
+#include <string.h>
 #include <sys/klog.h>
 #include <sys/syslog.h>
 #include <sys/time.h>
@@ -41,6 +43,7 @@
 #include "mangle.h"
 #include "pager.h"
 #include "jsonwrt.h"
+#include "pathnames.h"
 
 /* Close the log.  Currently a NOP. */
 #define SYSLOG_ACTION_CLOSE          0
@@ -65,6 +68,12 @@
 /* Return size of the log buffer */
 #define SYSLOG_ACTION_SIZE_BUFFER   10
 
+#define PID_CHARS_MAX sizeof(stringify_value(LONG_MAX))
+#define PID_CHARS_DEFAULT sizeof(stringify_value(INT_MAX))
+#define SYSLOG_DEFAULT_CALLER_ID_CHARS sizeof(stringify_value(SHRT_MAX))-1
+#define DMESG_CALLER_PREFIX "caller="
+#define DMESG_CALLER_PREFIXSZ (sizeof(DMESG_CALLER_PREFIX)-1)
+
 /*
  * Color scheme
  */
@@ -233,6 +242,7 @@ struct dmesg_control {
 			force_prefix:1;	/* force timestamp and decode prefix
 					   on each line */
 	int		indent;		/* due to timestamps if newline */
+	size_t          caller_id_size;   /* PRINTK_CALLERID max field size */
 };
 
 struct dmesg_record {
@@ -242,6 +252,7 @@ struct dmesg_record {
 	int		level;
 	int		facility;
 	struct timeval  tv;
+	char		caller_id[PID_CHARS_MAX];
 
 	const char	*next;		/* buffer with next unparsed record */
 	size_t		next_size;	/* size of the next buffer */
@@ -254,6 +265,7 @@ struct dmesg_record {
 		(_r)->level = -1; \
 		(_r)->tv.tv_sec = 0; \
 		(_r)->tv.tv_usec = 0; \
+		(_r)->caller_id[0] = 0; \
 	} while (0)
 
 static int process_kmsg(struct dmesg_control *ctl);
@@ -551,6 +563,45 @@ static int get_syslog_buffer_size(void)
 	return n > 0 ? n : 0;
 }
 
+/*
+ * Get the number of characters needed to hold the maximum number
+ * of tasks this system supports. This size of string could hold
+ * a thread id large enough for the highest thread id.
+ * This is needed to determine the number of characters reserved for
+ * the PRINTK_CALLER field if it has been configured in the Linux Kernel.
+ *
+ * The number of digits sets the max value since the value can't exceed
+ * a value of that size. The /proc field defined by _PATH_PROC_PIDMAX
+ * holds the maximum number of PID values that may be ussed by the system,
+ * so 0 to that value minus one.
+ *
+ * For determining the size of the PRINTK_CALLER field, we make the safe
+ * assumption that the number of threads >= number of cpus. This because
+ * the PRINTK_CALLER field can hold either a thread id or a CPU id value.
+ *
+ * If we can't access the pid max kernel proc entry we assign a default
+ * field size of 5 characters as that is what the old syslog interface
+ * uses as the reserved field size. This is justified because 32-bit Linux
+ * systems are limited to PID values between (0-32767).
+ *
+ */
+static size_t max_threads_id_size(void)
+{
+	char taskmax[PID_CHARS_MAX] = {'\0'};
+	ssize_t rdsize;
+	int fd;
+
+	fd = open(_PATH_PROC_PIDMAX, O_RDONLY);
+	if (fd == -1)
+		return PID_CHARS_DEFAULT;
+
+	rdsize = read(fd, taskmax, sizeof(taskmax));
+	if (rdsize == -1)
+		return PID_CHARS_DEFAULT;
+
+	return strnlen(taskmax, sizeof(taskmax));
+}
+
 /*
  * Reads messages from regular file by mmap
  */
@@ -624,6 +675,8 @@ static ssize_t process_buffer(struct dmesg_control *ctl, char **buf)
 			ctl->bufsize = get_syslog_buffer_size();
 
 		n = read_syslog_buffer(ctl, buf);
+		/* Set number of PID characters for caller_id spacing */
+		ctl->caller_id_size = SYSLOG_DEFAULT_CALLER_ID_CHARS;
 		break;
 	case DMESG_METHOD_KMSG:
 		if (ctl->filename)
@@ -728,6 +781,39 @@ static const char *skip_item(const char *begin, const char *end, const char *sep
 	return begin;
 }
 
+/*
+ * Checks to see if the caller (caller id) field is present in the kmsg record.
+ * This is true if the PRINTK_CALLER config option has been set in the kernel.
+ *
+ * If the caller_id is found in the kmsg buffer then return the id and id type
+ * to the caller in dmesg caller_id. Returns string pointer to next value.
+ *
+ */
+static const char *parse_callerid(const char *p_str, const char *end,
+				  struct dmesg_record *p_drec)
+{
+	const char *p_after;
+	const char *p_next;
+	size_t cid_size;
+	char *p_scn;
+	char *p_cid;
+
+	/* Check for PRINTK_CALLER prefix, must be before msg text */
+	p_cid = strstr(p_str, DMESG_CALLER_PREFIX);
+	p_scn = strchr(p_str, ';');
+	if (p_cid != NULL && p_drec != NULL && p_scn != NULL && p_cid < p_scn) {
+		p_next = p_cid + DMESG_CALLER_PREFIXSZ;
+		p_after = skip_item(p_next, end, ",;");
+		cid_size = p_after - p_next;
+		if (cid_size < sizeof(p_drec->caller_id))
+			xstrncpy(p_drec->caller_id, p_next, cid_size);
+		else
+			return p_str;
+		return p_after;
+	}
+	return p_str;
+}
+
 /*
  * Parses one record from syslog(2) buffer
  */
@@ -795,8 +881,22 @@ static int get_next_syslog_record(struct dmesg_control *ctl,
 				begin++;
 		}
 
-		rec->mesg = begin;
-		rec->mesg_size = end - begin;
+		if (*begin == '[' && (*(begin + 1) == ' ' ||
+			(*(begin + 1) == 'T' || *(begin + 1) == 'C'))) {
+			const char *start = begin + 1;
+			size_t id_size;
+
+			start = start + strspn(start, " ");
+			begin = skip_item(begin, end, "]");
+			id_size = begin - start;
+			if (id_size < sizeof(rec->caller_id))
+				xstrncpy(rec->caller_id, start, id_size);
+			rec->mesg = begin + 1;
+			rec->mesg_size = end - begin - 1;
+		} else {
+			rec->mesg = begin;
+			rec->mesg_size = end - begin;
+		}
 
 		/* Don't count \n from the last message to the message size */
 		if (*end != '\n' && *(end - 1) == '\n')
@@ -1101,6 +1201,19 @@ full_output:
 			color_disable();
 	}
 
+	if (*rec->caller_id) {
+		if (ctl->json) {
+			ul_jsonwrt_value_s(&ctl->jfmt, "caller", rec->caller_id);
+		} else {
+			char cidbuf[PID_CHARS_MAX+3] = {'\0'};
+
+			sprintf(cidbuf, "[%*s] ",
+				(char)ctl->caller_id_size, rec->caller_id);
+			ctl->indent += strnlen(cidbuf, sizeof(cidbuf));
+			fputs(cidbuf, stdout);
+		}
+	}
+
 	/*
 	 * A kernel message may contain several lines of output, separated
 	 * by '\n'.  If the timestamp and decode outputs are forced then each
@@ -1284,7 +1397,10 @@ static int parse_kmsg_record(struct dmesg_control *ctl,
 		goto mesg;
 
 	/* D) optional fields (ignore) */
-	p = skip_item(p, end, ";");
+	p = skip_item(p, end, ",;");
+
+	/* Include optional PRINTK_CALLER field if it is present */
+	p = parse_callerid(p, end, rec);
 
 mesg:
 	/* E) message text */
@@ -1336,6 +1452,9 @@ static int process_kmsg(struct dmesg_control *ctl)
 	if (ctl->method != DMESG_METHOD_KMSG || ctl->kmsg < 0)
 		return -1;
 
+	/* Determine number of PID characters for caller_id spacing */
+	ctl->caller_id_size = max_threads_id_size();
+
 	/*
 	 * The very first read() call is done in kmsg_init() where we test
 	 * /dev/kmsg usability. The return code from the initial read() is
@@ -1446,6 +1565,7 @@ int main(int argc, char *argv[])
 		.kmsg = -1,
 		.time_fmt = DMESG_TIMEFTM_TIME,
 		.indent = 0,
+		.caller_id_size = 0,
 	};
 	int colormode = UL_COLORMODE_UNDEF;
 	enum {
@@ -1538,10 +1658,12 @@ int main(int argc, char *argv[])
 		case 'F':
 			ctl.filename = optarg;
 			ctl.method = DMESG_METHOD_MMAP;
+			ctl.caller_id_size = SYSLOG_DEFAULT_CALLER_ID_CHARS;
 			break;
 		case 'K':
 			ctl.filename = optarg;
 			ctl.method = DMESG_METHOD_KMSG;
+			ctl.caller_id_size = max_threads_id_size();
 			break;
 		case 'f':
 			ctl.fltr_fac = 1;
diff --git a/tests/expected/dmesg/colors-kmsg-printk-caller b/tests/expected/dmesg/colors-kmsg-printk-caller
new file mode 100644
index 000000000..c7bf6e8b7
--- /dev/null
+++ b/tests/expected/dmesg/colors-kmsg-printk-caller
@@ -0,0 +1,22 @@
+kern  :notice: ^[[32m[    0.000000] ^[[0m[     T0] Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000
+kern  :info  : ^[[32m[    0.000000] ^[[0m[     T1] ^[[33mCommand line: ^[[0minitrd=\ucode.img initrd=\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system
+kern  :info  : ^[[32m[    0.000000] ^[[0m[     T2] BIOS-provided physical RAM map:
+kern  :info  : ^[[32m[    0.000000] ^[[0m[     T3] ^[[33mBIOS-e820: ^[[0m[mem 0x0000000000000000-0x000000000009efff] usable
+kern  :info  : ^[[32m[    0.000000] ^[[0m[     T4] ^[[33mBIOS-e820: ^[[0m[mem 0x000000000009f000-0x00000000000bffff] reserved
+kern  :info  : ^[[32m[    0.000000] ^[[0m[     T5] ^[[33mBIOS-e820: ^[[0m[mem 0x0000000000100000-0x0000000009afffff] usable
+kern  :info  : ^[[32m[    0.000000] ^[[0m[     T6] ^[[33mBIOS-e820: ^[[0m[mem 0x0000000009b00000-0x0000000009dfffff] reserved
+kern  :info  : ^[[32m[    0.000000] ^[[0m[     T7] ^[[33mBIOS-e820: ^[[0m[mem 0x0000000009e00000-0x0000000009efffff] usable
+kern  :info  : ^[[32m[    0.000000] ^[[0m[     T8] ^[[33mBIOS-e820: ^[[0m[mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS
+kern  :info  : ^[[32m[    0.000000] ^[[0m[     T9] ^[[33mBIOS-e820: ^[[0m[mem 0x0000000009f3c000-0x000000004235ffff] usable
+kern  :info  : ^[[32m[    0.000000] ^[[0m[    T10] ^[[33mBIOS-e820: ^[[0m[mem 0x0000000042360000-0x000000004455ffff] reserved
+kern  :info  : ^[[32m[    0.367657] ^[[0m[    T11] ^[[33mACPI: ^[[0m\_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+kern  :info  : ^[[32m[    0.368615] ^[[0m[    T12] ^[[33mACPI: ^[[0m\_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+kern  :info  : ^[[32m[    0.376316] ^[[0m[    T13] ^[[33mACPI: ^[[0m\_SB_.PRWL: New power resource
+kern  :info  : ^[[32m[    0.376343] ^[[0m[    T14] ^[[33mACPI: ^[[0m\_SB_.PRWB: New power resource
+kern  :info  : ^[[32m[    0.377373] ^[[0m[    T15] ^[[33mACPI: ^[[0mPCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+kern  :info  : ^[[32m[    0.377378] ^[[0m[    T16] ^[[33macpi PNP0A08:00: ^[[0m_OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+kern  :info  : ^[[32m[    0.377569] ^[[0m[    T17] ^[[33macpi PNP0A08:00: ^[[0m_OSC: platform does not support [SHPCHotplug AER]
+kern  :info  : ^[[32m[    0.377933] ^[[0m[    T18] ^[[33macpi PNP0A08:00: ^[[0m_OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+kern  :info  : ^[[32m[    0.378458] ^[[0m[    T19] PCI host bridge to bus 0000:00
+kern  :info  : ^[[32m[    0.378459] ^[[0m[    T20] ^[[33mpci_bus 0000:00: ^[[0mroot bus resource [io  0x0000-0x0cf7 window]
+kern  :info  : ^[[32m[    0.378461] ^[[0m[    T21] ^[[33mpci_bus 0000:00: ^[[0mroot bus resource [io  0x0d00-0xffff window]
diff --git a/tests/expected/dmesg/console-levels-kmsg-printk-caller b/tests/expected/dmesg/console-levels-kmsg-printk-caller
new file mode 100644
index 000000000..1f6e9f178
--- /dev/null
+++ b/tests/expected/dmesg/console-levels-kmsg-printk-caller
@@ -0,0 +1,45 @@
+[    0.000000] [     T0] Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000
+[    0.000000] [     T1] Command line: initrd=\ucode.img initrd=\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system
+[    0.000000] [     T2] BIOS-provided physical RAM map:
+[    0.000000] [     T3] BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable
+[    0.000000] [     T4] BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved
+[    0.000000] [     T5] BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable
+[    0.000000] [     T6] BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved
+[    0.000000] [     T7] BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable
+[    0.000000] [     T8] BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS
+[    0.000000] [     T9] BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable
+[    0.000000] [    T10] BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved
+[    0.367657] [    T11] ACPI: \_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+[    0.368615] [    T12] ACPI: \_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+[    0.376316] [    T13] ACPI: \_SB_.PRWL: New power resource
+[    0.376343] [    T14] ACPI: \_SB_.PRWB: New power resource
+[    0.377373] [    T15] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+[    0.377378] [    T16] acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+[    0.377569] [    T17] acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]
+[    0.377933] [    T18] acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+[    0.378458] [    T19] PCI host bridge to bus 0000:00
+[    0.378459] [    T20] pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]
+[    0.378461] [    T21] pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]
+[    0.000000] [     T0] Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000
+[    0.000000] [     T1] Command line: initrd=\ucode.img initrd=\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system
+[    0.000000] [     T2] BIOS-provided physical RAM map:
+[    0.000000] [     T3] BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable
+[    0.000000] [     T4] BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved
+[    0.000000] [     T5] BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable
+[    0.000000] [     T6] BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved
+[    0.000000] [     T7] BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable
+[    0.000000] [     T8] BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS
+[    0.000000] [     T9] BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable
+[    0.000000] [    T10] BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved
+[    0.367657] [    T11] ACPI: \_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+[    0.368615] [    T12] ACPI: \_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+[    0.376316] [    T13] ACPI: \_SB_.PRWL: New power resource
+[    0.376343] [    T14] ACPI: \_SB_.PRWB: New power resource
+[    0.377373] [    T15] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+[    0.377378] [    T16] acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+[    0.377569] [    T17] acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]
+[    0.377933] [    T18] acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+[    0.378458] [    T19] PCI host bridge to bus 0000:00
+[    0.378459] [    T20] pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]
+[    0.378461] [    T21] pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]
+test_dmesg: unknown level '+'
diff --git a/tests/expected/dmesg/decode-kmsg-printk-caller b/tests/expected/dmesg/decode-kmsg-printk-caller
new file mode 100644
index 000000000..78c363389
--- /dev/null
+++ b/tests/expected/dmesg/decode-kmsg-printk-caller
@@ -0,0 +1,22 @@
+kern  :notice: [    0.000000] [     T0] Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000
+kern  :info  : [    0.000000] [     T1] Command line: initrd=\ucode.img initrd=\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system
+kern  :info  : [    0.000000] [     T2] BIOS-provided physical RAM map:
+kern  :info  : [    0.000000] [     T3] BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable
+kern  :info  : [    0.000000] [     T4] BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved
+kern  :info  : [    0.000000] [     T5] BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable
+kern  :info  : [    0.000000] [     T6] BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved
+kern  :info  : [    0.000000] [     T7] BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable
+kern  :info  : [    0.000000] [     T8] BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS
+kern  :info  : [    0.000000] [     T9] BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable
+kern  :info  : [    0.000000] [    T10] BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved
+kern  :info  : [    0.367657] [    T11] ACPI: \_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+kern  :info  : [    0.368615] [    T12] ACPI: \_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+kern  :info  : [    0.376316] [    T13] ACPI: \_SB_.PRWL: New power resource
+kern  :info  : [    0.376343] [    T14] ACPI: \_SB_.PRWB: New power resource
+kern  :info  : [    0.377373] [    T15] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+kern  :info  : [    0.377378] [    T16] acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+kern  :info  : [    0.377569] [    T17] acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]
+kern  :info  : [    0.377933] [    T18] acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+kern  :info  : [    0.378458] [    T19] PCI host bridge to bus 0000:00
+kern  :info  : [    0.378459] [    T20] pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]
+kern  :info  : [    0.378461] [    T21] pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]
diff --git a/tests/expected/dmesg/delta-kmsg-printk-caller b/tests/expected/dmesg/delta-kmsg-printk-caller
new file mode 100644
index 000000000..892d2dcea
--- /dev/null
+++ b/tests/expected/dmesg/delta-kmsg-printk-caller
@@ -0,0 +1,22 @@
+[    0.000000 <    0.000000>] [     T0] Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000
+[    0.000000 <    0.000000>] [     T1] Command line: initrd=\ucode.img initrd=\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system
+[    0.000000 <    0.000000>] [     T2] BIOS-provided physical RAM map:
+[    0.000000 <    0.000000>] [     T3] BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable
+[    0.000000 <    0.000000>] [     T4] BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved
+[    0.000000 <    0.000000>] [     T5] BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable
+[    0.000000 <    0.000000>] [     T6] BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved
+[    0.000000 <    0.000000>] [     T7] BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable
+[    0.000000 <    0.000000>] [     T8] BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS
+[    0.000000 <    0.000000>] [     T9] BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable
+[    0.000000 <    0.000000>] [    T10] BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved
+[    0.367657 <    0.000000>] [    T11] ACPI: \_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+[    0.368615 <    0.000000>] [    T12] ACPI: \_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+[    0.376316 <    0.000000>] [    T13] ACPI: \_SB_.PRWL: New power resource
+[    0.376343 <    0.000000>] [    T14] ACPI: \_SB_.PRWB: New power resource
+[    0.377373 <    0.000000>] [    T15] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+[    0.377378 <    0.000000>] [    T16] acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+[    0.377569 <    0.000000>] [    T17] acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]
+[    0.377933 <    0.000000>] [    T18] acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+[    0.378458 <    0.000000>] [    T19] PCI host bridge to bus 0000:00
+[    0.378459 <    0.000000>] [    T20] pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]
+[    0.378461 <    0.000000>] [    T21] pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]
diff --git a/tests/expected/dmesg/facilities-kmsg-printk-caller b/tests/expected/dmesg/facilities-kmsg-printk-caller
new file mode 100644
index 000000000..78c363389
--- /dev/null
+++ b/tests/expected/dmesg/facilities-kmsg-printk-caller
@@ -0,0 +1,22 @@
+kern  :notice: [    0.000000] [     T0] Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000
+kern  :info  : [    0.000000] [     T1] Command line: initrd=\ucode.img initrd=\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system
+kern  :info  : [    0.000000] [     T2] BIOS-provided physical RAM map:
+kern  :info  : [    0.000000] [     T3] BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable
+kern  :info  : [    0.000000] [     T4] BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved
+kern  :info  : [    0.000000] [     T5] BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable
+kern  :info  : [    0.000000] [     T6] BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved
+kern  :info  : [    0.000000] [     T7] BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable
+kern  :info  : [    0.000000] [     T8] BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS
+kern  :info  : [    0.000000] [     T9] BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable
+kern  :info  : [    0.000000] [    T10] BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved
+kern  :info  : [    0.367657] [    T11] ACPI: \_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+kern  :info  : [    0.368615] [    T12] ACPI: \_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+kern  :info  : [    0.376316] [    T13] ACPI: \_SB_.PRWL: New power resource
+kern  :info  : [    0.376343] [    T14] ACPI: \_SB_.PRWB: New power resource
+kern  :info  : [    0.377373] [    T15] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+kern  :info  : [    0.377378] [    T16] acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+kern  :info  : [    0.377569] [    T17] acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]
+kern  :info  : [    0.377933] [    T18] acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+kern  :info  : [    0.378458] [    T19] PCI host bridge to bus 0000:00
+kern  :info  : [    0.378459] [    T20] pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]
+kern  :info  : [    0.378461] [    T21] pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]
diff --git a/tests/expected/dmesg/indentation-kmsg-printk-caller b/tests/expected/dmesg/indentation-kmsg-printk-caller
new file mode 100644
index 000000000..47ad73f27
--- /dev/null
+++ b/tests/expected/dmesg/indentation-kmsg-printk-caller
@@ -0,0 +1,28 @@
+[    0.000000] [     T0] line zero
+[    1.000000] [     T1] new
+[    2.000000] [     T2] two
+[    3.000000] [     T3] three
+kern  :notice: [    0.000000] [     T0] line zero
+user  :crit  : [    1.000000] [     T1] new
+mail  :warn  : [    2.000000] [     T2] two
+daemon:info  : [    3.000000] [     T3] three
+[<    0.000000>] [     T0] line zero
+[<    0.000000>] [     T1] new
+[<    1.000000>] [     T2] two
+[<    1.000000>] [     T3] three
+[     T0] line zero
+[     T1] new
+[     T2] two
+[     T3] three
+[Feb13 23:31] [     T0] line zero
+[  +0.000000] [     T1] new
+[  +1.000000] [     T2] two
+[  +1.000000] [     T3] three
+[Fri Feb 13 23:31:30 2009] [     T0] line zero
+[Fri Feb 13 23:31:31 2009] [     T1] new
+[Fri Feb 13 23:31:32 2009] [     T2] two
+[Fri Feb 13 23:31:33 2009] [     T3] three
+2009-02-13T23:31:30,123456+00:00 [     T0] line zero
+2009-02-13T23:31:31,123456+00:00 [     T1] new
+2009-02-13T23:31:32,123456+00:00 [     T2] two
+2009-02-13T23:31:33,123456+00:00 [     T3] three
diff --git a/tests/expected/dmesg/json-kmsg-printk-caller b/tests/expected/dmesg/json-kmsg-printk-caller
new file mode 100644
index 000000000..785d730a5
--- /dev/null
+++ b/tests/expected/dmesg/json-kmsg-printk-caller
@@ -0,0 +1,115 @@
+{
+   "dmesg": [
+      {
+         "pri": 5,
+         "time":     0.000000,
+         "caller": "T0",
+         "msg": "Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T1",
+         "msg": "Command line: initrd=\\ucode.img initrd=\\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T2",
+         "msg": "BIOS-provided physical RAM map:"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T3",
+         "msg": "BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T4",
+         "msg": "BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T5",
+         "msg": "BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T6",
+         "msg": "BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T7",
+         "msg": "BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T8",
+         "msg": "BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T9",
+         "msg": "BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T10",
+         "msg": "BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved"
+      },{
+         "pri": 6,
+         "time":     0.367657,
+         "caller": "T11",
+         "msg": "ACPI: \\_SB_.PCI0.GP19.NHI1.PWRS: New power resource"
+      },{
+         "pri": 6,
+         "time":     0.368615,
+         "caller": "T12",
+         "msg": "ACPI: \\_SB_.PCI0.GP19.XHC4.PWRS: New power resource"
+      },{
+         "pri": 6,
+         "time":     0.376316,
+         "caller": "T13",
+         "msg": "ACPI: \\_SB_.PRWL: New power resource"
+      },{
+         "pri": 6,
+         "time":     0.376343,
+         "caller": "T14",
+         "msg": "ACPI: \\_SB_.PRWB: New power resource"
+      },{
+         "pri": 6,
+         "time":     0.377373,
+         "caller": "T15",
+         "msg": "ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])"
+      },{
+         "pri": 6,
+         "time":     0.377378,
+         "caller": "T16",
+         "msg": "acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]"
+      },{
+         "pri": 6,
+         "time":     0.377569,
+         "caller": "T17",
+         "msg": "acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]"
+      },{
+         "pri": 6,
+         "time":     0.377933,
+         "caller": "T18",
+         "msg": "acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]"
+      },{
+         "pri": 6,
+         "time":     0.378458,
+         "caller": "T19",
+         "msg": "PCI host bridge to bus 0000:00"
+      },{
+         "pri": 6,
+         "time":     0.378459,
+         "caller": "T20",
+         "msg": "pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]"
+      },{
+         "pri": 6,
+         "time":     0.378461,
+         "caller": "T21",
+         "msg": "pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]"
+      }
+   ]
+}
diff --git a/tests/expected/dmesg/json-syslog-printk-caller b/tests/expected/dmesg/json-syslog-printk-caller
new file mode 100644
index 000000000..40c98aa67
--- /dev/null
+++ b/tests/expected/dmesg/json-syslog-printk-caller
@@ -0,0 +1,530 @@
+{
+   "dmesg": [
+      {
+         "pri": 0,
+         "time":     0.000000,
+         "caller": "T0",
+         "msg": " example[0]"
+      },{
+         "pri": 1,
+         "time":     1.000000,
+         "caller": "T1",
+         "msg": " example[1]"
+      },{
+         "pri": 2,
+         "time":     8.000000,
+         "caller": "T2",
+         "msg": " example[2]"
+      },{
+         "pri": 3,
+         "time":    27.000000,
+         "caller": "T3",
+         "msg": " example[3]"
+      },{
+         "pri": 4,
+         "time":    64.000000,
+         "caller": "T4",
+         "msg": " example[4]"
+      },{
+         "pri": 5,
+         "time":   125.000000,
+         "caller": "T5",
+         "msg": " example[5]"
+      },{
+         "pri": 6,
+         "time":   216.000000,
+         "caller": "T6",
+         "msg": " example[6]"
+      },{
+         "pri": 7,
+         "time":   343.000000,
+         "caller": "T7",
+         "msg": " example[7]"
+      },{
+         "pri": 8,
+         "time":   512.000000,
+         "caller": "T8",
+         "msg": " example[8]"
+      },{
+         "pri": 9,
+         "time":   729.000000,
+         "caller": "T9",
+         "msg": " example[9]"
+      },{
+         "pri": 10,
+         "time":  1000.000000,
+         "caller": "T10",
+         "msg": " example[10]"
+      },{
+         "pri": 11,
+         "time":  1331.000000,
+         "caller": "T11",
+         "msg": " example[11]"
+      },{
+         "pri": 12,
+         "time":  1728.000000,
+         "caller": "T12",
+         "msg": " example[12]"
+      },{
+         "pri": 13,
+         "time":  2197.000000,
+         "caller": "T13",
+         "msg": " example[13]"
+      },{
+         "pri": 14,
+         "time":  2744.000000,
+         "caller": "T14",
+         "msg": " example[14]"
+      },{
+         "pri": 15,
+         "time":  3375.000000,
+         "caller": "T15",
+         "msg": " example[15]"
+      },{
+         "pri": 16,
+         "time":  4096.000000,
+         "caller": "T16",
+         "msg": " example[16]"
+      },{
+         "pri": 17,
+         "time":  4913.000000,
+         "caller": "T17",
+         "msg": " example[17]"
+      },{
+         "pri": 18,
+         "time":  5832.000000,
+         "caller": "T18",
+         "msg": " example[18]"
+      },{
+         "pri": 19,
+         "time":  6859.000000,
+         "caller": "T19",
+         "msg": " example[19]"
+      },{
+         "pri": 20,
+         "time":  8000.000000,
+         "caller": "T20",
+         "msg": " example[20]"
+      },{
+         "pri": 21,
+         "time":  9261.000000,
+         "caller": "T21",
+         "msg": " example[21]"
+      },{
+         "pri": 22,
+         "time": 10648.000000,
+         "caller": "T22",
+         "msg": " example[22]"
+      },{
+         "pri": 23,
+         "time": 12167.000000,
+         "caller": "T23",
+         "msg": " example[23]"
+      },{
+         "pri": 24,
+         "time": 13824.000000,
+         "caller": "T24",
+         "msg": " example[24]"
+      },{
+         "pri": 25,
+         "time": 15625.000000,
+         "caller": "T25",
+         "msg": " example[25]"
+      },{
+         "pri": 26,
+         "time": 17576.000000,
+         "caller": "T26",
+         "msg": " example[26]"
+      },{
+         "pri": 27,
+         "time": 19683.000000,
+         "caller": "T27",
+         "msg": " example[27]"
+      },{
+         "pri": 28,
+         "time": 21952.000000,
+         "caller": "T28",
+         "msg": " example[28]"
+      },{
+         "pri": 29,
+         "time": 24389.000000,
+         "caller": "T29",
+         "msg": " example[29]"
+      },{
+         "pri": 30,
+         "time": 27000.000000,
+         "caller": "T10",
+         "msg": " example[30]"
+      },{
+         "pri": 31,
+         "time": 29791.000000,
+         "caller": "T31",
+         "msg": " example[31]"
+      },{
+         "pri": 32,
+         "time": 32768.000000,
+         "caller": "T32",
+         "msg": " example[32]"
+      },{
+         "pri": 33,
+         "time": 35937.000000,
+         "caller": "T33",
+         "msg": " example[33]"
+      },{
+         "pri": 34,
+         "time": 39304.000000,
+         "caller": "T34",
+         "msg": " example[34]"
+      },{
+         "pri": 35,
+         "time": 42875.000000,
+         "caller": "T35",
+         "msg": " example[35]"
+      },{
+         "pri": 36,
+         "time": 46656.000000,
+         "caller": "T36",
+         "msg": " example[36]"
+      },{
+         "pri": 37,
+         "time": 50653.000000,
+         "caller": "T37",
+         "msg": " example[37]"
+      },{
+         "pri": 38,
+         "time": 54872.000000,
+         "caller": "T38",
+         "msg": " example[38]"
+      },{
+         "pri": 39,
+         "time": 59319.000000,
+         "caller": "T39",
+         "msg": " example[39]"
+      },{
+         "pri": 40,
+         "time": 64000.000000,
+         "caller": "T40",
+         "msg": " example[40]"
+      },{
+         "pri": 41,
+         "time": 68921.000000,
+         "caller": "T41",
+         "msg": " example[41]"
+      },{
+         "pri": 42,
+         "time": 74088.000000,
+         "caller": "T42",
+         "msg": " example[42]"
+      },{
+         "pri": 43,
+         "time": 79507.000000,
+         "caller": "T43",
+         "msg": " example[43]"
+      },{
+         "pri": 44,
+         "time": 85184.000000,
+         "caller": "T44",
+         "msg": " example[44]"
+      },{
+         "pri": 45,
+         "time": 91125.000000,
+         "caller": "T45",
+         "msg": " example[45]"
+      },{
+         "pri": 46,
+         "time": 97336.000000,
+         "caller": "T46",
+         "msg": " example[46]"
+      },{
+         "pri": 47,
+         "time": 103823.000000,
+         "caller": "T47",
+         "msg": " example[47]"
+      },{
+         "pri": 48,
+         "time": 110592.000000,
+         "caller": "T48",
+         "msg": " example[48]"
+      },{
+         "pri": 49,
+         "time": 117649.000000,
+         "caller": "T49",
+         "msg": " example[49]"
+      },{
+         "pri": 50,
+         "time": 125000.000000,
+         "caller": "T50",
+         "msg": " example[50]"
+      },{
+         "pri": 51,
+         "time": 132651.000000,
+         "caller": "T51",
+         "msg": " example[51]"
+      },{
+         "pri": 52,
+         "time": 140608.000000,
+         "caller": "T52",
+         "msg": " example[52]"
+      },{
+         "pri": 53,
+         "time": 148877.000000,
+         "caller": "T53",
+         "msg": " example[53]"
+      },{
+         "pri": 54,
+         "time": 157464.000000,
+         "caller": "T54",
+         "msg": " example[54]"
+      },{
+         "pri": 55,
+         "time": 166375.000000,
+         "caller": "T55",
+         "msg": " example[55]"
+      },{
+         "pri": 56,
+         "time": 175616.000000,
+         "caller": "T56",
+         "msg": " example[56]"
+      },{
+         "pri": 57,
+         "time": 185193.000000,
+         "caller": "T57",
+         "msg": " example[57]"
+      },{
+         "pri": 58,
+         "time": 195112.000000,
+         "caller": "T58",
+         "msg": " example[58]"
+      },{
+         "pri": 59,
+         "time": 205379.000000,
+         "caller": "T59",
+         "msg": " example[59]"
+      },{
+         "pri": 60,
+         "time": 216000.000000,
+         "caller": "T60",
+         "msg": " example[60]"
+      },{
+         "pri": 61,
+         "time": 226981.000000,
+         "caller": "T61",
+         "msg": " example[61]"
+      },{
+         "pri": 62,
+         "time": 238328.000000,
+         "caller": "T62",
+         "msg": " example[62]"
+      },{
+         "pri": 63,
+         "time": 250047.000000,
+         "caller": "T63",
+         "msg": " example[63]"
+      },{
+         "pri": 64,
+         "time": 262144.000000,
+         "caller": "T64",
+         "msg": " example[64]"
+      },{
+         "pri": 65,
+         "time": 274625.000000,
+         "caller": "T65",
+         "msg": " example[65]"
+      },{
+         "pri": 66,
+         "time": 287496.000000,
+         "caller": "T66",
+         "msg": " example[66]"
+      },{
+         "pri": 67,
+         "time": 300763.000000,
+         "caller": "T67",
+         "msg": " example[67]"
+      },{
+         "pri": 68,
+         "time": 314432.000000,
+         "caller": "T68",
+         "msg": " example[68]"
+      },{
+         "pri": 69,
+         "time": 328509.000000,
+         "caller": "T69",
+         "msg": " example[69]"
+      },{
+         "pri": 70,
+         "time": 343000.000000,
+         "caller": "T70",
+         "msg": " example[70]"
+      },{
+         "pri": 71,
+         "time": 357911.000000,
+         "caller": "T71",
+         "msg": " example[71]"
+      },{
+         "pri": 72,
+         "time": 373248.000000,
+         "caller": "T72",
+         "msg": " example[72]"
+      },{
+         "pri": 73,
+         "time": 389017.000000,
+         "caller": "T73",
+         "msg": " example[73]"
+      },{
+         "pri": 74,
+         "time": 405224.000000,
+         "caller": "T74",
+         "msg": " example[74]"
+      },{
+         "pri": 75,
+         "time": 421875.000000,
+         "caller": "T75",
+         "msg": " example[75]"
+      },{
+         "pri": 76,
+         "time": 438976.000000,
+         "caller": "T76",
+         "msg": " example[76]"
+      },{
+         "pri": 77,
+         "time": 456533.000000,
+         "caller": "T77",
+         "msg": " example[77]"
+      },{
+         "pri": 78,
+         "time": 474552.000000,
+         "caller": "T78",
+         "msg": " example[78]"
+      },{
+         "pri": 79,
+         "time": 493039.000000,
+         "caller": "T79",
+         "msg": " example[79]"
+      },{
+         "pri": 80,
+         "time": 512000.000000,
+         "caller": "T80",
+         "msg": " example[80]"
+      },{
+         "pri": 81,
+         "time": 531441.000000,
+         "caller": "T81",
+         "msg": " example[81]"
+      },{
+         "pri": 82,
+         "time": 551368.000000,
+         "caller": "T82",
+         "msg": " example[82]"
+      },{
+         "pri": 83,
+         "time": 571787.000000,
+         "caller": "T83",
+         "msg": " example[83]"
+      },{
+         "pri": 84,
+         "time": 592704.000000,
+         "caller": "T84",
+         "msg": " example[84]"
+      },{
+         "pri": 85,
+         "time": 614125.000000,
+         "caller": "T85",
+         "msg": " example[85]"
+      },{
+         "pri": 86,
+         "time": 636056.000000,
+         "caller": "T86",
+         "msg": " example[86]"
+      },{
+         "pri": 87,
+         "time": 658503.000000,
+         "caller": "T87",
+         "msg": " example[87]"
+      },{
+         "pri": 88,
+         "time": 681472.000000,
+         "caller": "T88",
+         "msg": " example[88]"
+      },{
+         "pri": 89,
+         "time": 704969.000000,
+         "caller": "T89",
+         "msg": " example[89]"
+      },{
+         "pri": 90,
+         "time": 729000.000000,
+         "caller": "T90",
+         "msg": " example[90]"
+      },{
+         "pri": 91,
+         "time": 753571.000000,
+         "caller": "T91",
+         "msg": " example[91]"
+      },{
+         "pri": 92,
+         "time": 778688.000000,
+         "caller": "T92",
+         "msg": " example[92]"
+      },{
+         "pri": 93,
+         "time": 804357.000000,
+         "caller": "T93",
+         "msg": " example[93]"
+      },{
+         "pri": 94,
+         "time": 830584.000000,
+         "caller": "T94",
+         "msg": " example[94]"
+      },{
+         "pri": 95,
+         "time": 857375.000000,
+         "caller": "T95",
+         "msg": " example[95]"
+      },{
+         "pri": 96,
+         "time": 884736.000000,
+         "caller": "T96",
+         "msg": " example[96]"
+      },{
+         "pri": 97,
+         "time": 912673.000000,
+         "caller": "T97",
+         "msg": " example[97]"
+      },{
+         "pri": 98,
+         "time": 941192.000000,
+         "caller": "T98",
+         "msg": " example[98]"
+      },{
+         "pri": 99,
+         "time": 970299.000000,
+         "caller": "T99",
+         "msg": " example[99]"
+      },{
+         "pri": 100,
+         "time": 1000000.000000,
+         "caller": "T100",
+         "msg": " example[100]"
+      },{
+         "pri": 101,
+         "time": 1030301.000000,
+         "caller": "T101",
+         "msg": " example[101]"
+      },{
+         "pri": 102,
+         "time": 1061208.000000,
+         "caller": "T102",
+         "msg": " example[102]"
+      },{
+         "pri": 103,
+         "time": 1092727.000000,
+         "caller": "T103",
+         "msg": " example[103]"
+      },{
+         "pri": 104,
+         "time": 1124864.000000,
+         "caller": "T104",
+         "msg": " example[104]"
+      }
+   ]
+}
diff --git a/tests/expected/dmesg/kmsg-file-printk-caller b/tests/expected/dmesg/kmsg-file-printk-caller
new file mode 100644
index 000000000..785d730a5
--- /dev/null
+++ b/tests/expected/dmesg/kmsg-file-printk-caller
@@ -0,0 +1,115 @@
+{
+   "dmesg": [
+      {
+         "pri": 5,
+         "time":     0.000000,
+         "caller": "T0",
+         "msg": "Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T1",
+         "msg": "Command line: initrd=\\ucode.img initrd=\\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T2",
+         "msg": "BIOS-provided physical RAM map:"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T3",
+         "msg": "BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T4",
+         "msg": "BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T5",
+         "msg": "BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T6",
+         "msg": "BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T7",
+         "msg": "BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T8",
+         "msg": "BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T9",
+         "msg": "BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T10",
+         "msg": "BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved"
+      },{
+         "pri": 6,
+         "time":     0.367657,
+         "caller": "T11",
+         "msg": "ACPI: \\_SB_.PCI0.GP19.NHI1.PWRS: New power resource"
+      },{
+         "pri": 6,
+         "time":     0.368615,
+         "caller": "T12",
+         "msg": "ACPI: \\_SB_.PCI0.GP19.XHC4.PWRS: New power resource"
+      },{
+         "pri": 6,
+         "time":     0.376316,
+         "caller": "T13",
+         "msg": "ACPI: \\_SB_.PRWL: New power resource"
+      },{
+         "pri": 6,
+         "time":     0.376343,
+         "caller": "T14",
+         "msg": "ACPI: \\_SB_.PRWB: New power resource"
+      },{
+         "pri": 6,
+         "time":     0.377373,
+         "caller": "T15",
+         "msg": "ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])"
+      },{
+         "pri": 6,
+         "time":     0.377378,
+         "caller": "T16",
+         "msg": "acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]"
+      },{
+         "pri": 6,
+         "time":     0.377569,
+         "caller": "T17",
+         "msg": "acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]"
+      },{
+         "pri": 6,
+         "time":     0.377933,
+         "caller": "T18",
+         "msg": "acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]"
+      },{
+         "pri": 6,
+         "time":     0.378458,
+         "caller": "T19",
+         "msg": "PCI host bridge to bus 0000:00"
+      },{
+         "pri": 6,
+         "time":     0.378459,
+         "caller": "T20",
+         "msg": "pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]"
+      },{
+         "pri": 6,
+         "time":     0.378461,
+         "caller": "T21",
+         "msg": "pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]"
+      }
+   ]
+}
diff --git a/tests/expected/dmesg/limit-kmsg-printk-caller b/tests/expected/dmesg/limit-kmsg-printk-caller
new file mode 100644
index 000000000..2ea07d4c8
--- /dev/null
+++ b/tests/expected/dmesg/limit-kmsg-printk-caller
@@ -0,0 +1,11 @@
+[    0.367657] [    T11] ACPI: \_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+[    0.368615] [    T12] ACPI: \_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+[    0.376316] [    T13] ACPI: \_SB_.PRWL: New power resource
+[    0.376343] [    T14] ACPI: \_SB_.PRWB: New power resource
+[    0.377373] [    T15] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+[    0.377378] [    T16] acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+[    0.377569] [    T17] acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]
+[    0.377933] [    T18] acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+[    0.378458] [    T19] PCI host bridge to bus 0000:00
+[    0.378459] [    T20] pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]
+[    0.378461] [    T21] pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]
diff --git a/tests/ts/dmesg/colors-kmsg-printk-caller b/tests/ts/dmesg/colors-kmsg-printk-caller
new file mode 100755
index 000000000..513ca82d4
--- /dev/null
+++ b/tests/ts/dmesg/colors-kmsg-printk-caller
@@ -0,0 +1,29 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="colors-kmsg-prtk-caller"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+ts_inhibit_custom_colorscheme
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG --color=always -K $TS_SELF/kmsg-input-printk-caller -x >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/console-levels-kmsg-printk-caller b/tests/ts/dmesg/console-levels-kmsg-printk-caller
new file mode 100755
index 000000000..00b8b3681
--- /dev/null
+++ b/tests/ts/dmesg/console-levels-kmsg-printk-caller
@@ -0,0 +1,36 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="levels-kmsg-prtk-caller"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+for I in {-1..8}; do
+	$TS_HELPER_DMESG -K $TS_SELF/kmsg-input-printk-caller -l $I >> $TS_OUTPUT 2>/dev/null
+done
+
+$TS_HELPER_DMESG -K $TS_SELF/kmsg-input-printk-caller -l err+ >> $TS_OUTPUT 2>/dev/null
+$TS_HELPER_DMESG -K $TS_SELF/kmsg-input-printk-caller -l emerg+ >> $TS_OUTPUT 2>/dev/null
+$TS_HELPER_DMESG -K $TS_SELF/kmsg-input-printk-caller -l +err >> $TS_OUTPUT 2>/dev/null
+$TS_HELPER_DMESG -K $TS_SELF/kmsg-input-printk-caller -l +debug >> $TS_OUTPUT 2>/dev/null
+$TS_HELPER_DMESG -K $TS_SELF/kmsg-input-printk-caller -l + 2>> $TS_OUTPUT >/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/decode-kmsg-printk-caller b/tests/ts/dmesg/decode-kmsg-printk-caller
new file mode 100755
index 000000000..d05b9fb68
--- /dev/null
+++ b/tests/ts/dmesg/decode-kmsg-printk-caller
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="decode-kmsg-prtk-caller"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG -x -K $TS_SELF/kmsg-input-printk-caller >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/delta-kmsg-printk-caller b/tests/ts/dmesg/delta-kmsg-printk-caller
new file mode 100755
index 000000000..020b82357
--- /dev/null
+++ b/tests/ts/dmesg/delta-kmsg-printk-caller
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="delta-kmsg-prtk-caller"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG -d -K $TS_SELF/kmsg-input-printk-caller >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/facilities-kmsg-printk-caller b/tests/ts/dmesg/facilities-kmsg-printk-caller
new file mode 100755
index 000000000..bec301516
--- /dev/null
+++ b/tests/ts/dmesg/facilities-kmsg-printk-caller
@@ -0,0 +1,30 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="facilities-kmsg-prtk-caller"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+for I in {-1..12}; do
+	$TS_HELPER_DMESG -K $TS_SELF/kmsg-input-printk-caller -f $I -x >> $TS_OUTPUT 2>/dev/null
+done
+
+ts_finalize
diff --git a/tests/ts/dmesg/indentation-kmsg-printk-caller b/tests/ts/dmesg/indentation-kmsg-printk-caller
new file mode 100755
index 000000000..53e549b62
--- /dev/null
+++ b/tests/ts/dmesg/indentation-kmsg-printk-caller
@@ -0,0 +1,40 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="indentation-kmsg-prtk-caller"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG -K $TS_SELF/newlines-kmsg-printk-caller >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG -K $TS_SELF/newlines-kmsg-printk-caller -x >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=delta --kmsg-file $TS_SELF/newlines-kmsg-printk-caller >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=notime --kmsg-file $TS_SELF/newlines-kmsg-printk-caller >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=reltime --kmsg-file $TS_SELF/newlines-kmsg-printk-caller >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=ctime --kmsg-file $TS_SELF/newlines-kmsg-printk-caller >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=iso --kmsg-file $TS_SELF/newlines-kmsg-printk-caller >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+ts_finalize
diff --git a/tests/ts/dmesg/input-syslog-printk-caller b/tests/ts/dmesg/input-syslog-printk-caller
new file mode 100644
index 000000000..5fcff6abe
--- /dev/null
+++ b/tests/ts/dmesg/input-syslog-printk-caller
@@ -0,0 +1,105 @@
+<0>[    0.000000] [    T0] example[0]
+<1>[    1.000000] [    T1] example[1]
+<2>[    8.000000] [    T2] example[2]
+<3>[   27.000000] [    T3] example[3]
+<4>[   64.000000] [    T4] example[4]
+<5>[  125.000000] [    T5] example[5]
+<6>[  216.000000] [    T6] example[6]
+<7>[  343.000000] [    T7] example[7]
+<8>[  512.000000] [    T8] example[8]
+<9>[  729.000000] [    T9] example[9]
+<10>[ 1000.000000] [   T10] example[10]
+<11>[ 1331.000000] [   T11] example[11]
+<12>[ 1728.000000] [   T12] example[12]
+<13>[ 2197.000000] [   T13] example[13]
+<14>[ 2744.000000] [   T14] example[14]
+<15>[ 3375.000000] [   T15] example[15]
+<16>[ 4096.000000] [   T16] example[16]
+<17>[ 4913.000000] [   T17] example[17]
+<18>[ 5832.000000] [   T18] example[18]
+<19>[ 6859.000000] [   T19] example[19]
+<20>[ 8000.000000] [   T20] example[20]
+<21>[ 9261.000000] [   T21] example[21]
+<22>[10648.000000] [   T22] example[22]
+<23>[12167.000000] [   T23] example[23]
+<24>[13824.000000] [   T24] example[24]
+<25>[15625.000000] [   T25] example[25]
+<26>[17576.000000] [   T26] example[26]
+<27>[19683.000000] [   T27] example[27]
+<28>[21952.000000] [   T28] example[28]
+<29>[24389.000000] [   T29] example[29]
+<30>[27000.000000] [   T10] example[30]
+<31>[29791.000000] [   T31] example[31]
+<32>[32768.000000] [   T32] example[32]
+<33>[35937.000000] [   T33] example[33]
+<34>[39304.000000] [   T34] example[34]
+<35>[42875.000000] [   T35] example[35]
+<36>[46656.000000] [   T36] example[36]
+<37>[50653.000000] [   T37] example[37]
+<38>[54872.000000] [   T38] example[38]
+<39>[59319.000000] [   T39] example[39]
+<40>[64000.000000] [   T40] example[40]
+<41>[68921.000000] [   T41] example[41]
+<42>[74088.000000] [   T42] example[42]
+<43>[79507.000000] [   T43] example[43]
+<44>[85184.000000] [   T44] example[44]
+<45>[91125.000000] [   T45] example[45]
+<46>[97336.000000] [   T46] example[46]
+<47>[103823.000000] [   T47] example[47]
+<48>[110592.000000] [   T48] example[48]
+<49>[117649.000000] [   T49] example[49]
+<50>[125000.000000] [   T50] example[50]
+<51>[132651.000000] [   T51] example[51]
+<52>[140608.000000] [   T52] example[52]
+<53>[148877.000000] [   T53] example[53]
+<54>[157464.000000] [   T54] example[54]
+<55>[166375.000000] [   T55] example[55]
+<56>[175616.000000] [   T56] example[56]
+<57>[185193.000000] [   T57] example[57]
+<58>[195112.000000] [   T58] example[58]
+<59>[205379.000000] [   T59] example[59]
+<60>[216000.000000] [   T60] example[60]
+<61>[226981.000000] [   T61] example[61]
+<62>[238328.000000] [   T62] example[62]
+<63>[250047.000000] [   T63] example[63]
+<64>[262144.000000] [   T64] example[64]
+<65>[274625.000000] [   T65] example[65]
+<66>[287496.000000] [   T66] example[66]
+<67>[300763.000000] [   T67] example[67]
+<68>[314432.000000] [   T68] example[68]
+<69>[328509.000000] [   T69] example[69]
+<70>[343000.000000] [   T70] example[70]
+<71>[357911.000000] [   T71] example[71]
+<72>[373248.000000] [   T72] example[72]
+<73>[389017.000000] [   T73] example[73]
+<74>[405224.000000] [   T74] example[74]
+<75>[421875.000000] [   T75] example[75]
+<76>[438976.000000] [   T76] example[76]
+<77>[456533.000000] [   T77] example[77]
+<78>[474552.000000] [   T78] example[78]
+<79>[493039.000000] [   T79] example[79]
+<80>[512000.000000] [   T80] example[80]
+<81>[531441.000000] [   T81] example[81]
+<82>[551368.000000] [   T82] example[82]
+<83>[571787.000000] [   T83] example[83]
+<84>[592704.000000] [   T84] example[84]
+<85>[614125.000000] [   T85] example[85]
+<86>[636056.000000] [   T86] example[86]
+<87>[658503.000000] [   T87] example[87]
+<88>[681472.000000] [   T88] example[88]
+<89>[704969.000000] [   T89] example[89]
+<90>[729000.000000] [   T90] example[90]
+<91>[753571.000000] [   T91] example[91]
+<92>[778688.000000] [   T92] example[92]
+<93>[804357.000000] [   T93] example[93]
+<94>[830584.000000] [   T94] example[94]
+<95>[857375.000000] [   T95] example[95]
+<96>[884736.000000] [   T96] example[96]
+<97>[912673.000000] [   T97] example[97]
+<98>[941192.000000] [   T98] example[98]
+<99>[970299.000000] [   T99] example[99]
+<100>[1000000.000000] [  T100] example[100]
+<101>[1030301.000000] [  T101] example[101]
+<102>[1061208.000000] [  T102] example[102]
+<103>[1092727.000000] [  T103] example[103]
+<104>[1124864.000000] [  T104] example[104]
diff --git a/tests/ts/dmesg/json-kmsg-printk-caller b/tests/ts/dmesg/json-kmsg-printk-caller
new file mode 100755
index 000000000..cb6c5e4a8
--- /dev/null
+++ b/tests/ts/dmesg/json-kmsg-printk-caller
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="json-kmsg-prtk-caller"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG -J -K $TS_SELF/kmsg-input-printk-caller >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/json-syslog-printk-caller b/tests/ts/dmesg/json-syslog-printk-caller
new file mode 100755
index 000000000..10dfaa423
--- /dev/null
+++ b/tests/ts/dmesg/json-syslog-printk-caller
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="json-syslog-prtk-caller"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG -J -F $TS_SELF/input-syslog-printk-caller >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/kmsg-file-printk-caller b/tests/ts/dmesg/kmsg-file-printk-caller
new file mode 100755
index 000000000..a01fc723f
--- /dev/null
+++ b/tests/ts/dmesg/kmsg-file-printk-caller
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="kmsg-file-prtk-caller"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG -J -K $TS_SELF/kmsg-input-printk-caller >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/kmsg-input-printk-caller b/tests/ts/dmesg/kmsg-input-printk-caller
new file mode 100644
index 0000000000000000000000000000000000000000..8d67f11cad7988469dd5e4a7c8589d2b744168bb
GIT binary patch
literal 2187
zcmbW2TW{hx6oB`+zv4*yQZ$g-aqb9dAw>nL(1<WMu@wr5q0uIBlmsaMe(Z!%<LSbv
zlRV_&oX=m5?PI-*_}S}*L6Xp7utfdGINQI%ffi-VGB6ZF(Rx7<zTh5)+e9?}BOdF!
z4&3g-5N;n_w*#0cs)9j9DnS;)U3i#(h9u&x{5s-+Rh*O^P!$a;r~`jv@Mj))i}85o
zE!X$o=fm05g&E7bfHb(LVT}TW9MyKP4WAG{ZvHa5STe?am!)ZtMZlG)1928tMKt*L
zRS)+ei>MN(yY|bvJxI4@ul|L)xi~^toboE7hd88zJAS>(4k<+$&WTf=%8I5=6qjL8
zL{KnRHJ_wGp3~y4X%}XyWTy5<(<i@|7wiy6G=lu)RK`5fuo%vO$2uZ}NFk&Np_Ymq
zSfw-t^eTS4ee|SPHr;Nw&#*6pO+p1wlYrWFpuOc}8Mxs*4lHO%ivx`WQkRhWRV1!e
z+ekYQM9I;RfW|eTy?GCe&cL>#DIv|PNctWrvM4)R641H|6j_w>Xm5!~<TDIiZwm7-
zzR063A?@o(63R$TCHk+9SYEssT|x4A;}=U!)6d9uCN)C3#4rurY}Eyf`{GX=5bJ8~
zkJgIkPLcB9VOyC`rdaX5E_?^(^awdS(n8E1wlBhFN)n9|Ed%RqqI#M5ZQ^RbA?jUX
z8U!0{B6&w#e0{tu#TOq(XrztM{s%F-j4(OEB&LMW&j_9%Snyf_qau!W6jmZ*&u|;D
zG>9`^*ARl$W?%BV9-k?ldhrsgAzE!IqaTEM4Bp&BLu5I;BEtH~cO7{0q1@*=E2<J!
z<JXF2yw12R+r~Q>`rZuOgoXd{t50_+&G=U{e+uLK1x&nez2zyV<oO2t&m;f4zZ}m7
zqMIAIAAgy;<H0BK<h*s-_}RiwH|(~bdC4zNf@;f(6e31T$apT!y0G#mo;zVxp6t2m
zc=16E4G9gK&(ycA3tN{oc$zZCOFYY}f+ajvd?e`4&b`?f#IqaZ!6r`P>I9F=1>Ae?
zN1ZTtvNT;9I=e5X!3!%Z*fi6iV$cjaAI4@s(=@e-Y$sJk{XC4<txuhL=c$8#E-qNb
x49;7GD7oR*gkzjV>?paPL2n~_e!=^1N$^$A^$pxgsfs@$5!EG7)Tlp__yL<dZm0kN

literal 0
HcmV?d00001

diff --git a/tests/ts/dmesg/limit-kmsg-printk-caller b/tests/ts/dmesg/limit-kmsg-printk-caller
new file mode 100755
index 000000000..4d4d9912d
--- /dev/null
+++ b/tests/ts/dmesg/limit-kmsg-printk-caller
@@ -0,0 +1,29 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="limit-kmsg-prtk-caller"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG --since @1234567890.124 --until @1234567991 -K $TS_SELF/kmsg-input-printk-caller \
+	>> $TS_OUTPUT 2> $TS_ERRLOG
+
+ts_finalize
diff --git a/tests/ts/dmesg/newlines-kmsg-printk-caller b/tests/ts/dmesg/newlines-kmsg-printk-caller
new file mode 100644
index 0000000000000000000000000000000000000000..574d2177796677b73f1efcf273005169ed832c60
GIT binary patch
literal 152
zcmXrjF#tkco#e!voYW%Q5CiL+%)C^Es??%<E(Svb9YY;M128~RV`!b1TFwPh$Hia-
tQeuRm#K^j&Jf91MLCT7`7>o^cjC71K)EQfsWE7>QazV)4{GwE-1^{d2D<=Q|

literal 0
HcmV?d00001

-- 
2.43.0


^ permalink raw reply related

* [PATCH] util-linux/sys-utils dmesg add PRINTK_CALLER support
From: Edward Chron @ 2023-12-18 15:11 UTC (permalink / raw)
  To: util-linux; +Cc: colona, echron

Submission to Project: util-linux
Open Incident: #2609 at github.com/util-linux/util-linux/issues/2609
Component: util-linux/sys-utils
File: dmesg.c
Code level patch applied against: 2.39.3 - latest code pulled from
           git.github.com:util-linux/util-linux.git
Revision: #1 on 2023/12/08 per Review from Karel Zak
Revision: #2 on 2023/12/12 Adjust line offsets for master update and
                           Add caller_id_size init to dmesg -K
Revision: #3 on 2023/12/12 Use of sizeof for cidbuf and limit search
                           for caller_id to dmesg prefix to msg text
Revision: #4 on 2023/12/15 Ensure SYSLOG and kmsg inputs have
                           caller_id_size set appropriately

Add support to standard dmesg command for the optional Linux Kernel
debug CONFIG option PRINTK_CALLER which adds an optional dmesg field
that contains the Thread Id or CPU Id that is issuing the printk to
add the message to the kernel ring buffer. This makes debugging simpler
as dmesg entries for a specific thread or CPU can be recognized.

The dmesg -S using the old syslog interface supports printing the
PRINTK_CALLER field but currently standard dmesg does not support
printing the field if present. There are utilities that use dmesg and
so it would be optimal if dmesg supported PRINTK_CALLER as well.

The additional field provided by PRINTK_CALLER is only present
if it was configured for the Linux kernel where the dmesg command
is run. It is a debug option and not configured by default so the
dmesg output will only change for those kernels where the option was
configured when the kernel was built. For users who went to the
trouble to configure PRINTK_CALLER and have the extra field available
for debugging, having dmesg print the field is very helpful.

Size of the PRINTK_CALLER field is determined by the maximum number
tasks that can be run on the system which is limited by the value of
/proc/sys/kernel/pid_max as pid values are from 0 to value - 1.
This value determines the number of id digits needed by the caller id.
The PRINTK_CALLER field is printed as T<id> for a Task Id or C<id>
for a CPU Id for a printk in CPU context. The values are left space
padded and enclosed in parentheses such as: [    T123] or [     C16]

For consistency with dmesg -S which supports the PRINTK_CALLER field
the field is printed followed by a space. For JSON format output the
PRINTK_CALLER field is identified as caller as that is consistent with
it's naming in /dev/kmsg. No space padding is used to reduce space
consumed by the JSON output. So the output from the command on a system
with PRINTK_CALLER field enabled in the Linux .config file the dmesg
output appears as:

> dmesg
...
[  520.897104] [   T3919] usb 3-3: Product: USB 2.0 Hub

and

> dmesg -x
...
kern  :info  : [  520.897104] [   T3919] usb 3-3: Product: USB 2.0 Hub

and

> dmesg -J
...
      },{
         "pri": 6,
         "time":    520.897104,
         "caller": "T3919",
         "msg": "usb 3-3: Product: USB 2.0 Hub"
      },{

and

> dmesg -J -x
...
      },{
         "fac": "kern",
         "pri": "info",
         "time":   520.897104,
         "caller": "T3919",
         "msg": "usb 3-3: Product: USB 2.0 Hub"
      },{

>

For comparison:

> dmesg -S
...
[  520.897104] [ T3919] usb 3-3: Product: USB 2.0 Hub

and

> dmesg -S -x
...
kern  :info  : [  520.897104] [ T3919] usb 3-3: Product: USB 2.0 Hub

Note: When dmesg uses the old syslog interface the reserved space for
      the PRINTK_CALLER field is capped at 5 digits because 32-bit
      kernels are capped at 32768 as the max number of PIDs. However,
      64-bit systems are currently capped at 2^22 PIDs (0 - 4194303).
      The PID cap is set by PID_MAX_LIMIT but the system limit can be
      less so we use /proc/sys/kernel/pid_max to determine the size
      needed to hold the maximum PID value size for the current system.
      Many 64-bit systems support 2^22 PIDs (0 - 4194303) and you see:

> dmesg -x
...
kern  :info  : [  520.899558] [   T3919] hub 3-3:1.0: USB hub found
...
kern  :info  : [ 9830.456898] [  T98982] cgroup: fork rejected by pids ...
kern  :info  : [14301.158878] [ T137336] cgroup: fork rejected by pids ...
kern  :info  : [18980.803190] [T1637865] cgroup: fork rejected by pids ...

> dmesg -S -x
...
kern  :info  : [  520.899558] [ T3919] hub 3-3:1.0: USB hub found
...
kern  :info  : [ 9830.456898] [T98982] cgroup: fork rejected by pids ...
kern  :info  : [14301.158878] [T137336] cgroup: fork rejected by pids ...
kern  :info  : [18980.803190] [T1637865] cgroup: fork rejected by pids ...

This is the only difference seen with PRINTK_CALLER configured and
printing between the dmesg /dev/kmsg interface and the dmesg -S syslog
interface.

Signed-off-by: Ivan Delalande <colona@arista.com>
Signed-off-by: Edward Chron <echron@arista.com>
---
 include/pathnames.h                           |   3 +
 sys-utils/dmesg.c                             | 124 +++-
 .../expected/dmesg/colors-kmsg-printk-caller  |  22 +
 .../dmesg/console-levels-kmsg-printk-caller   |  45 ++
 .../expected/dmesg/decode-kmsg-printk-caller  |  22 +
 tests/expected/dmesg/delta-kmsg-printk-caller |  22 +
 .../dmesg/facilities-kmsg-printk-caller       |  22 +
 .../dmesg/indentation-kmsg-printk-caller      |  28 +
 tests/expected/dmesg/json-kmsg-printk-caller  | 115 ++++
 .../expected/dmesg/json-syslog-printk-caller  | 530 ++++++++++++++++++
 tests/expected/dmesg/kmsg-file-printk-caller  | 115 ++++
 tests/expected/dmesg/limit-kmsg-printk-caller |  11 +
 tests/ts/dmesg/colors-kmsg-printk-caller      |  29 +
 .../dmesg/console-levels-kmsg-printk-caller   |  36 ++
 tests/ts/dmesg/decode-kmsg-printk-caller      |  28 +
 tests/ts/dmesg/delta-kmsg-printk-caller       |  28 +
 tests/ts/dmesg/facilities-kmsg-printk-caller  |  30 +
 tests/ts/dmesg/indentation-kmsg-printk-caller |  40 ++
 tests/ts/dmesg/input-syslog-printk-caller     | 105 ++++
 tests/ts/dmesg/json-kmsg-printk-caller        |  28 +
 tests/ts/dmesg/json-syslog-printk-caller      |  28 +
 tests/ts/dmesg/kmsg-file-printk-caller        |  28 +
 tests/ts/dmesg/kmsg-input-printk-caller       | Bin 0 -> 2187 bytes
 tests/ts/dmesg/limit-kmsg-printk-caller       |  29 +
 tests/ts/dmesg/newlines-kmsg-printk-caller    | Bin 0 -> 152 bytes
 25 files changed, 1466 insertions(+), 2 deletions(-)
 create mode 100644 tests/expected/dmesg/colors-kmsg-printk-caller
 create mode 100644 tests/expected/dmesg/console-levels-kmsg-printk-caller
 create mode 100644 tests/expected/dmesg/decode-kmsg-printk-caller
 create mode 100644 tests/expected/dmesg/delta-kmsg-printk-caller
 create mode 100644 tests/expected/dmesg/facilities-kmsg-printk-caller
 create mode 100644 tests/expected/dmesg/indentation-kmsg-printk-caller
 create mode 100644 tests/expected/dmesg/json-kmsg-printk-caller
 create mode 100644 tests/expected/dmesg/json-syslog-printk-caller
 create mode 100644 tests/expected/dmesg/kmsg-file-printk-caller
 create mode 100644 tests/expected/dmesg/limit-kmsg-printk-caller
 create mode 100755 tests/ts/dmesg/colors-kmsg-printk-caller
 create mode 100755 tests/ts/dmesg/console-levels-kmsg-printk-caller
 create mode 100755 tests/ts/dmesg/decode-kmsg-printk-caller
 create mode 100755 tests/ts/dmesg/delta-kmsg-printk-caller
 create mode 100755 tests/ts/dmesg/facilities-kmsg-printk-caller
 create mode 100755 tests/ts/dmesg/indentation-kmsg-printk-caller
 create mode 100644 tests/ts/dmesg/input-syslog-printk-caller
 create mode 100755 tests/ts/dmesg/json-kmsg-printk-caller
 create mode 100755 tests/ts/dmesg/json-syslog-printk-caller
 create mode 100755 tests/ts/dmesg/kmsg-file-printk-caller
 create mode 100644 tests/ts/dmesg/kmsg-input-printk-caller
 create mode 100755 tests/ts/dmesg/limit-kmsg-printk-caller
 create mode 100644 tests/ts/dmesg/newlines-kmsg-printk-caller

diff --git a/include/pathnames.h b/include/pathnames.h
index caf0e63d4..81fa405f6 100644
--- a/include/pathnames.h
+++ b/include/pathnames.h
@@ -230,4 +230,7 @@
 /* cgroup path */
 #define _PATH_SYS_CGROUP	"/sys/fs/cgroup"
 
+/* Maximum number of PIDs system supports */
+#define _PATH_PROC_PIDMAX	"/proc/sys/kernel/pid_max"
+
 #endif /* PATHNAMES_H */
diff --git a/sys-utils/dmesg.c b/sys-utils/dmesg.c
index 77728b419..520cfbf04 100644
--- a/sys-utils/dmesg.c
+++ b/sys-utils/dmesg.c
@@ -13,7 +13,9 @@
  */
 #include <stdio.h>
 #include <getopt.h>
+#include <stdbool.h>
 #include <stdlib.h>
+#include <string.h>
 #include <sys/klog.h>
 #include <sys/syslog.h>
 #include <sys/time.h>
@@ -41,6 +43,7 @@
 #include "mangle.h"
 #include "pager.h"
 #include "jsonwrt.h"
+#include "pathnames.h"
 
 /* Close the log.  Currently a NOP. */
 #define SYSLOG_ACTION_CLOSE          0
@@ -65,6 +68,12 @@
 /* Return size of the log buffer */
 #define SYSLOG_ACTION_SIZE_BUFFER   10
 
+#define PID_CHARS_MAX sizeof(stringify_value(LONG_MAX))
+#define PID_CHARS_DEFAULT sizeof(stringify_value(INT_MAX))
+#define SYSLOG_DEFAULT_CALLER_ID_CHARS sizeof(stringify_value(SHRT_MAX))
+#define DMESG_CALLER_PREFIX "caller="
+#define DMESG_CALLER_PREFIXSZ (sizeof(DMESG_CALLER_PREFIX)-1)
+
 /*
  * Color scheme
  */
@@ -233,6 +242,7 @@ struct dmesg_control {
 			force_prefix:1;	/* force timestamp and decode prefix
 					   on each line */
 	int		indent;		/* due to timestamps if newline */
+	size_t          caller_id_size;   /* PRINTK_CALLERID max field size */
 };
 
 struct dmesg_record {
@@ -242,6 +252,7 @@ struct dmesg_record {
 	int		level;
 	int		facility;
 	struct timeval  tv;
+	char		caller_id[PID_CHARS_MAX];
 
 	const char	*next;		/* buffer with next unparsed record */
 	size_t		next_size;	/* size of the next buffer */
@@ -254,6 +265,7 @@ struct dmesg_record {
 		(_r)->level = -1; \
 		(_r)->tv.tv_sec = 0; \
 		(_r)->tv.tv_usec = 0; \
+		(_r)->caller_id[0] = 0; \
 	} while (0)
 
 static int process_kmsg(struct dmesg_control *ctl);
@@ -551,6 +563,45 @@ static int get_syslog_buffer_size(void)
 	return n > 0 ? n : 0;
 }
 
+/*
+ * Get the number of characters needed to hold the maximum number
+ * of tasks this system supports. This size of string could hold
+ * a thread id large enough for the highest thread id.
+ * This is needed to determine the number of characters reserved for
+ * the PRINTK_CALLER field if it has been configured in the Linux Kernel.
+ *
+ * The number of digits sets the max value since the value can't exceed
+ * a value of that size. The /proc field defined by _PATH_PROC_PIDMAX
+ * holds the maximum number of PID values that may be ussed by the system,
+ * so 0 to that value minus one.
+ *
+ * For determining the size of the PRINTK_CALLER field, we make the safe
+ * assumption that the number of threads >= number of cpus. This because
+ * the PRINTK_CALLER field can hold either a thread id or a CPU id value.
+ *
+ * If we can't access the pid max kernel proc entry we assign a default
+ * field size of 5 characters as that is what the old syslog interface
+ * uses as the reserved field size. This is justified because 32-bit Linux
+ * systems are limited to PID values between (0-32767).
+ *
+ */
+static size_t max_threads_id_size(void)
+{
+	char taskmax[PID_CHARS_MAX] = {'\0'};
+	ssize_t rdsize;
+	int fd;
+
+	fd = open(_PATH_PROC_PIDMAX, O_RDONLY);
+	if (fd == -1)
+		return PID_CHARS_DEFAULT;
+
+	rdsize = read(fd, taskmax, sizeof(taskmax));
+	if (rdsize == -1)
+		return PID_CHARS_DEFAULT;
+
+	return strnlen(taskmax, sizeof(taskmax));
+}
+
 /*
  * Reads messages from regular file by mmap
  */
@@ -624,11 +675,13 @@ static ssize_t process_buffer(struct dmesg_control *ctl, char **buf)
 			ctl->bufsize = get_syslog_buffer_size();
 
 		n = read_syslog_buffer(ctl, buf);
+		/* Set number of PID characters for caller_id spacing */
+		ctl->caller_id_size = SYSLOG_DEFAULT_CALLER_ID_CHARS;
 		break;
 	case DMESG_METHOD_KMSG:
 		if (ctl->filename)
 			n = process_kmsg_file(ctl, buf);
-		else
+		else 
 			/*
 			 * Since kernel 3.5.0
 			 */
@@ -728,6 +781,39 @@ static const char *skip_item(const char *begin, const char *end, const char *sep
 	return begin;
 }
 
+/*
+ * Checks to see if the caller (caller id) field is present in the kmsg record.
+ * This is true if the PRINTK_CALLER config option has been set in the kernel.
+ *
+ * If the caller_id is found in the kmsg buffer then return the id and id type
+ * to the caller in dmesg caller_id. Returns string pointer to next value.
+ *
+ */
+static const char *parse_callerid(const char *p_str, const char *end,
+				  struct dmesg_record *p_drec)
+{
+	const char *p_after;
+	const char *p_next;
+	size_t cid_size;
+	char *p_scn;
+	char *p_cid;
+
+	/* Check for PRINTK_CALLER prefix, must be before msg text */
+	p_cid = strstr(p_str, DMESG_CALLER_PREFIX);
+	p_scn = strchr(p_str, ';');
+	if (p_cid != NULL && p_drec != NULL && p_scn != NULL && p_cid < p_scn) {
+		p_next = p_cid + DMESG_CALLER_PREFIXSZ;
+		p_after = skip_item(p_next, end, ",;");
+		cid_size = p_after - p_next;
+		if (cid_size < sizeof(p_drec->caller_id))
+			xstrncpy(p_drec->caller_id, p_next, cid_size);
+		else
+			return p_str;
+		return p_after;
+	}
+	return p_str;
+}
+
 /*
  * Parses one record from syslog(2) buffer
  */
@@ -795,6 +881,18 @@ static int get_next_syslog_record(struct dmesg_control *ctl,
 				begin++;
 		}
 
+		if (*begin == '[' && (*(begin + 1) == ' ' ||
+			(*(begin + 1) == 'T' || *(begin + 1) == 'C'))) {
+			const char *start = begin + 1;
+			size_t id_size;
+
+			start = start + strspn(start, " ");
+			begin = skip_item(begin, end, "]");
+			id_size = begin - start;
+			if (id_size < sizeof(rec->caller_id))
+				xstrncpy(rec->caller_id, start, id_size);
+		}
+
 		rec->mesg = begin;
 		rec->mesg_size = end - begin;
 
@@ -1101,6 +1199,19 @@ full_output:
 			color_disable();
 	}
 
+	if (*rec->caller_id) {
+		if (ctl->json) {
+			ul_jsonwrt_value_s(&ctl->jfmt, "caller", rec->caller_id);
+		} else {
+			char cidbuf[PID_CHARS_MAX+3] = {'\0'};
+
+			sprintf(cidbuf, "[%*s] ",
+				(char)ctl->caller_id_size - 1, rec->caller_id);
+			ctl->indent += strnlen(cidbuf, sizeof(cidbuf));
+			fputs(cidbuf, stdout);
+		}
+	}
+
 	/*
 	 * A kernel message may contain several lines of output, separated
 	 * by '\n'.  If the timestamp and decode outputs are forced then each
@@ -1284,7 +1395,10 @@ static int parse_kmsg_record(struct dmesg_control *ctl,
 		goto mesg;
 
 	/* D) optional fields (ignore) */
-	p = skip_item(p, end, ";");
+	p = skip_item(p, end, ",;");
+
+	/* Include optional PRINTK_CALLER field if it is present */
+	p = parse_callerid(p, end, rec);
 
 mesg:
 	/* E) message text */
@@ -1336,6 +1450,9 @@ static int process_kmsg(struct dmesg_control *ctl)
 	if (ctl->method != DMESG_METHOD_KMSG || ctl->kmsg < 0)
 		return -1;
 
+	/* Determine number of PID characters for caller_id spacing */
+	ctl->caller_id_size = max_threads_id_size();
+
 	/*
 	 * The very first read() call is done in kmsg_init() where we test
 	 * /dev/kmsg usability. The return code from the initial read() is
@@ -1446,6 +1563,7 @@ int main(int argc, char *argv[])
 		.kmsg = -1,
 		.time_fmt = DMESG_TIMEFTM_TIME,
 		.indent = 0,
+		.caller_id_size = 0,
 	};
 	int colormode = UL_COLORMODE_UNDEF;
 	enum {
@@ -1538,10 +1656,12 @@ int main(int argc, char *argv[])
 		case 'F':
 			ctl.filename = optarg;
 			ctl.method = DMESG_METHOD_MMAP;
+			ctl.caller_id_size = SYSLOG_DEFAULT_CALLER_ID_CHARS;
 			break;
 		case 'K':
 			ctl.filename = optarg;
 			ctl.method = DMESG_METHOD_KMSG;
+			ctl.caller_id_size = max_threads_id_size();
 			break;
 		case 'f':
 			ctl.fltr_fac = 1;
diff --git a/tests/expected/dmesg/colors-kmsg-printk-caller b/tests/expected/dmesg/colors-kmsg-printk-caller
new file mode 100644
index 000000000..c7bf6e8b7
--- /dev/null
+++ b/tests/expected/dmesg/colors-kmsg-printk-caller
@@ -0,0 +1,22 @@
+kern  :notice: ^[[32m[    0.000000] ^[[0m[     T0] Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000
+kern  :info  : ^[[32m[    0.000000] ^[[0m[     T1] ^[[33mCommand line: ^[[0minitrd=\ucode.img initrd=\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system
+kern  :info  : ^[[32m[    0.000000] ^[[0m[     T2] BIOS-provided physical RAM map:
+kern  :info  : ^[[32m[    0.000000] ^[[0m[     T3] ^[[33mBIOS-e820: ^[[0m[mem 0x0000000000000000-0x000000000009efff] usable
+kern  :info  : ^[[32m[    0.000000] ^[[0m[     T4] ^[[33mBIOS-e820: ^[[0m[mem 0x000000000009f000-0x00000000000bffff] reserved
+kern  :info  : ^[[32m[    0.000000] ^[[0m[     T5] ^[[33mBIOS-e820: ^[[0m[mem 0x0000000000100000-0x0000000009afffff] usable
+kern  :info  : ^[[32m[    0.000000] ^[[0m[     T6] ^[[33mBIOS-e820: ^[[0m[mem 0x0000000009b00000-0x0000000009dfffff] reserved
+kern  :info  : ^[[32m[    0.000000] ^[[0m[     T7] ^[[33mBIOS-e820: ^[[0m[mem 0x0000000009e00000-0x0000000009efffff] usable
+kern  :info  : ^[[32m[    0.000000] ^[[0m[     T8] ^[[33mBIOS-e820: ^[[0m[mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS
+kern  :info  : ^[[32m[    0.000000] ^[[0m[     T9] ^[[33mBIOS-e820: ^[[0m[mem 0x0000000009f3c000-0x000000004235ffff] usable
+kern  :info  : ^[[32m[    0.000000] ^[[0m[    T10] ^[[33mBIOS-e820: ^[[0m[mem 0x0000000042360000-0x000000004455ffff] reserved
+kern  :info  : ^[[32m[    0.367657] ^[[0m[    T11] ^[[33mACPI: ^[[0m\_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+kern  :info  : ^[[32m[    0.368615] ^[[0m[    T12] ^[[33mACPI: ^[[0m\_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+kern  :info  : ^[[32m[    0.376316] ^[[0m[    T13] ^[[33mACPI: ^[[0m\_SB_.PRWL: New power resource
+kern  :info  : ^[[32m[    0.376343] ^[[0m[    T14] ^[[33mACPI: ^[[0m\_SB_.PRWB: New power resource
+kern  :info  : ^[[32m[    0.377373] ^[[0m[    T15] ^[[33mACPI: ^[[0mPCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+kern  :info  : ^[[32m[    0.377378] ^[[0m[    T16] ^[[33macpi PNP0A08:00: ^[[0m_OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+kern  :info  : ^[[32m[    0.377569] ^[[0m[    T17] ^[[33macpi PNP0A08:00: ^[[0m_OSC: platform does not support [SHPCHotplug AER]
+kern  :info  : ^[[32m[    0.377933] ^[[0m[    T18] ^[[33macpi PNP0A08:00: ^[[0m_OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+kern  :info  : ^[[32m[    0.378458] ^[[0m[    T19] PCI host bridge to bus 0000:00
+kern  :info  : ^[[32m[    0.378459] ^[[0m[    T20] ^[[33mpci_bus 0000:00: ^[[0mroot bus resource [io  0x0000-0x0cf7 window]
+kern  :info  : ^[[32m[    0.378461] ^[[0m[    T21] ^[[33mpci_bus 0000:00: ^[[0mroot bus resource [io  0x0d00-0xffff window]
diff --git a/tests/expected/dmesg/console-levels-kmsg-printk-caller b/tests/expected/dmesg/console-levels-kmsg-printk-caller
new file mode 100644
index 000000000..1f6e9f178
--- /dev/null
+++ b/tests/expected/dmesg/console-levels-kmsg-printk-caller
@@ -0,0 +1,45 @@
+[    0.000000] [     T0] Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000
+[    0.000000] [     T1] Command line: initrd=\ucode.img initrd=\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system
+[    0.000000] [     T2] BIOS-provided physical RAM map:
+[    0.000000] [     T3] BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable
+[    0.000000] [     T4] BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved
+[    0.000000] [     T5] BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable
+[    0.000000] [     T6] BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved
+[    0.000000] [     T7] BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable
+[    0.000000] [     T8] BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS
+[    0.000000] [     T9] BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable
+[    0.000000] [    T10] BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved
+[    0.367657] [    T11] ACPI: \_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+[    0.368615] [    T12] ACPI: \_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+[    0.376316] [    T13] ACPI: \_SB_.PRWL: New power resource
+[    0.376343] [    T14] ACPI: \_SB_.PRWB: New power resource
+[    0.377373] [    T15] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+[    0.377378] [    T16] acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+[    0.377569] [    T17] acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]
+[    0.377933] [    T18] acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+[    0.378458] [    T19] PCI host bridge to bus 0000:00
+[    0.378459] [    T20] pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]
+[    0.378461] [    T21] pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]
+[    0.000000] [     T0] Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000
+[    0.000000] [     T1] Command line: initrd=\ucode.img initrd=\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system
+[    0.000000] [     T2] BIOS-provided physical RAM map:
+[    0.000000] [     T3] BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable
+[    0.000000] [     T4] BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved
+[    0.000000] [     T5] BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable
+[    0.000000] [     T6] BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved
+[    0.000000] [     T7] BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable
+[    0.000000] [     T8] BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS
+[    0.000000] [     T9] BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable
+[    0.000000] [    T10] BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved
+[    0.367657] [    T11] ACPI: \_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+[    0.368615] [    T12] ACPI: \_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+[    0.376316] [    T13] ACPI: \_SB_.PRWL: New power resource
+[    0.376343] [    T14] ACPI: \_SB_.PRWB: New power resource
+[    0.377373] [    T15] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+[    0.377378] [    T16] acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+[    0.377569] [    T17] acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]
+[    0.377933] [    T18] acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+[    0.378458] [    T19] PCI host bridge to bus 0000:00
+[    0.378459] [    T20] pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]
+[    0.378461] [    T21] pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]
+test_dmesg: unknown level '+'
diff --git a/tests/expected/dmesg/decode-kmsg-printk-caller b/tests/expected/dmesg/decode-kmsg-printk-caller
new file mode 100644
index 000000000..78c363389
--- /dev/null
+++ b/tests/expected/dmesg/decode-kmsg-printk-caller
@@ -0,0 +1,22 @@
+kern  :notice: [    0.000000] [     T0] Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000
+kern  :info  : [    0.000000] [     T1] Command line: initrd=\ucode.img initrd=\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system
+kern  :info  : [    0.000000] [     T2] BIOS-provided physical RAM map:
+kern  :info  : [    0.000000] [     T3] BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable
+kern  :info  : [    0.000000] [     T4] BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved
+kern  :info  : [    0.000000] [     T5] BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable
+kern  :info  : [    0.000000] [     T6] BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved
+kern  :info  : [    0.000000] [     T7] BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable
+kern  :info  : [    0.000000] [     T8] BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS
+kern  :info  : [    0.000000] [     T9] BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable
+kern  :info  : [    0.000000] [    T10] BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved
+kern  :info  : [    0.367657] [    T11] ACPI: \_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+kern  :info  : [    0.368615] [    T12] ACPI: \_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+kern  :info  : [    0.376316] [    T13] ACPI: \_SB_.PRWL: New power resource
+kern  :info  : [    0.376343] [    T14] ACPI: \_SB_.PRWB: New power resource
+kern  :info  : [    0.377373] [    T15] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+kern  :info  : [    0.377378] [    T16] acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+kern  :info  : [    0.377569] [    T17] acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]
+kern  :info  : [    0.377933] [    T18] acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+kern  :info  : [    0.378458] [    T19] PCI host bridge to bus 0000:00
+kern  :info  : [    0.378459] [    T20] pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]
+kern  :info  : [    0.378461] [    T21] pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]
diff --git a/tests/expected/dmesg/delta-kmsg-printk-caller b/tests/expected/dmesg/delta-kmsg-printk-caller
new file mode 100644
index 000000000..892d2dcea
--- /dev/null
+++ b/tests/expected/dmesg/delta-kmsg-printk-caller
@@ -0,0 +1,22 @@
+[    0.000000 <    0.000000>] [     T0] Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000
+[    0.000000 <    0.000000>] [     T1] Command line: initrd=\ucode.img initrd=\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system
+[    0.000000 <    0.000000>] [     T2] BIOS-provided physical RAM map:
+[    0.000000 <    0.000000>] [     T3] BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable
+[    0.000000 <    0.000000>] [     T4] BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved
+[    0.000000 <    0.000000>] [     T5] BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable
+[    0.000000 <    0.000000>] [     T6] BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved
+[    0.000000 <    0.000000>] [     T7] BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable
+[    0.000000 <    0.000000>] [     T8] BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS
+[    0.000000 <    0.000000>] [     T9] BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable
+[    0.000000 <    0.000000>] [    T10] BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved
+[    0.367657 <    0.000000>] [    T11] ACPI: \_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+[    0.368615 <    0.000000>] [    T12] ACPI: \_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+[    0.376316 <    0.000000>] [    T13] ACPI: \_SB_.PRWL: New power resource
+[    0.376343 <    0.000000>] [    T14] ACPI: \_SB_.PRWB: New power resource
+[    0.377373 <    0.000000>] [    T15] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+[    0.377378 <    0.000000>] [    T16] acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+[    0.377569 <    0.000000>] [    T17] acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]
+[    0.377933 <    0.000000>] [    T18] acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+[    0.378458 <    0.000000>] [    T19] PCI host bridge to bus 0000:00
+[    0.378459 <    0.000000>] [    T20] pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]
+[    0.378461 <    0.000000>] [    T21] pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]
diff --git a/tests/expected/dmesg/facilities-kmsg-printk-caller b/tests/expected/dmesg/facilities-kmsg-printk-caller
new file mode 100644
index 000000000..78c363389
--- /dev/null
+++ b/tests/expected/dmesg/facilities-kmsg-printk-caller
@@ -0,0 +1,22 @@
+kern  :notice: [    0.000000] [     T0] Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000
+kern  :info  : [    0.000000] [     T1] Command line: initrd=\ucode.img initrd=\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system
+kern  :info  : [    0.000000] [     T2] BIOS-provided physical RAM map:
+kern  :info  : [    0.000000] [     T3] BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable
+kern  :info  : [    0.000000] [     T4] BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved
+kern  :info  : [    0.000000] [     T5] BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable
+kern  :info  : [    0.000000] [     T6] BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved
+kern  :info  : [    0.000000] [     T7] BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable
+kern  :info  : [    0.000000] [     T8] BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS
+kern  :info  : [    0.000000] [     T9] BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable
+kern  :info  : [    0.000000] [    T10] BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved
+kern  :info  : [    0.367657] [    T11] ACPI: \_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+kern  :info  : [    0.368615] [    T12] ACPI: \_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+kern  :info  : [    0.376316] [    T13] ACPI: \_SB_.PRWL: New power resource
+kern  :info  : [    0.376343] [    T14] ACPI: \_SB_.PRWB: New power resource
+kern  :info  : [    0.377373] [    T15] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+kern  :info  : [    0.377378] [    T16] acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+kern  :info  : [    0.377569] [    T17] acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]
+kern  :info  : [    0.377933] [    T18] acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+kern  :info  : [    0.378458] [    T19] PCI host bridge to bus 0000:00
+kern  :info  : [    0.378459] [    T20] pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]
+kern  :info  : [    0.378461] [    T21] pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]
diff --git a/tests/expected/dmesg/indentation-kmsg-printk-caller b/tests/expected/dmesg/indentation-kmsg-printk-caller
new file mode 100644
index 000000000..47ad73f27
--- /dev/null
+++ b/tests/expected/dmesg/indentation-kmsg-printk-caller
@@ -0,0 +1,28 @@
+[    0.000000] [     T0] line zero
+[    1.000000] [     T1] new
+[    2.000000] [     T2] two
+[    3.000000] [     T3] three
+kern  :notice: [    0.000000] [     T0] line zero
+user  :crit  : [    1.000000] [     T1] new
+mail  :warn  : [    2.000000] [     T2] two
+daemon:info  : [    3.000000] [     T3] three
+[<    0.000000>] [     T0] line zero
+[<    0.000000>] [     T1] new
+[<    1.000000>] [     T2] two
+[<    1.000000>] [     T3] three
+[     T0] line zero
+[     T1] new
+[     T2] two
+[     T3] three
+[Feb13 23:31] [     T0] line zero
+[  +0.000000] [     T1] new
+[  +1.000000] [     T2] two
+[  +1.000000] [     T3] three
+[Fri Feb 13 23:31:30 2009] [     T0] line zero
+[Fri Feb 13 23:31:31 2009] [     T1] new
+[Fri Feb 13 23:31:32 2009] [     T2] two
+[Fri Feb 13 23:31:33 2009] [     T3] three
+2009-02-13T23:31:30,123456+00:00 [     T0] line zero
+2009-02-13T23:31:31,123456+00:00 [     T1] new
+2009-02-13T23:31:32,123456+00:00 [     T2] two
+2009-02-13T23:31:33,123456+00:00 [     T3] three
diff --git a/tests/expected/dmesg/json-kmsg-printk-caller b/tests/expected/dmesg/json-kmsg-printk-caller
new file mode 100644
index 000000000..785d730a5
--- /dev/null
+++ b/tests/expected/dmesg/json-kmsg-printk-caller
@@ -0,0 +1,115 @@
+{
+   "dmesg": [
+      {
+         "pri": 5,
+         "time":     0.000000,
+         "caller": "T0",
+         "msg": "Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T1",
+         "msg": "Command line: initrd=\\ucode.img initrd=\\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T2",
+         "msg": "BIOS-provided physical RAM map:"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T3",
+         "msg": "BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T4",
+         "msg": "BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T5",
+         "msg": "BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T6",
+         "msg": "BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T7",
+         "msg": "BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T8",
+         "msg": "BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T9",
+         "msg": "BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T10",
+         "msg": "BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved"
+      },{
+         "pri": 6,
+         "time":     0.367657,
+         "caller": "T11",
+         "msg": "ACPI: \\_SB_.PCI0.GP19.NHI1.PWRS: New power resource"
+      },{
+         "pri": 6,
+         "time":     0.368615,
+         "caller": "T12",
+         "msg": "ACPI: \\_SB_.PCI0.GP19.XHC4.PWRS: New power resource"
+      },{
+         "pri": 6,
+         "time":     0.376316,
+         "caller": "T13",
+         "msg": "ACPI: \\_SB_.PRWL: New power resource"
+      },{
+         "pri": 6,
+         "time":     0.376343,
+         "caller": "T14",
+         "msg": "ACPI: \\_SB_.PRWB: New power resource"
+      },{
+         "pri": 6,
+         "time":     0.377373,
+         "caller": "T15",
+         "msg": "ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])"
+      },{
+         "pri": 6,
+         "time":     0.377378,
+         "caller": "T16",
+         "msg": "acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]"
+      },{
+         "pri": 6,
+         "time":     0.377569,
+         "caller": "T17",
+         "msg": "acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]"
+      },{
+         "pri": 6,
+         "time":     0.377933,
+         "caller": "T18",
+         "msg": "acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]"
+      },{
+         "pri": 6,
+         "time":     0.378458,
+         "caller": "T19",
+         "msg": "PCI host bridge to bus 0000:00"
+      },{
+         "pri": 6,
+         "time":     0.378459,
+         "caller": "T20",
+         "msg": "pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]"
+      },{
+         "pri": 6,
+         "time":     0.378461,
+         "caller": "T21",
+         "msg": "pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]"
+      }
+   ]
+}
diff --git a/tests/expected/dmesg/json-syslog-printk-caller b/tests/expected/dmesg/json-syslog-printk-caller
new file mode 100644
index 000000000..40c98aa67
--- /dev/null
+++ b/tests/expected/dmesg/json-syslog-printk-caller
@@ -0,0 +1,530 @@
+{
+   "dmesg": [
+      {
+         "pri": 0,
+         "time":     0.000000,
+         "caller": "T0",
+         "msg": " example[0]"
+      },{
+         "pri": 1,
+         "time":     1.000000,
+         "caller": "T1",
+         "msg": " example[1]"
+      },{
+         "pri": 2,
+         "time":     8.000000,
+         "caller": "T2",
+         "msg": " example[2]"
+      },{
+         "pri": 3,
+         "time":    27.000000,
+         "caller": "T3",
+         "msg": " example[3]"
+      },{
+         "pri": 4,
+         "time":    64.000000,
+         "caller": "T4",
+         "msg": " example[4]"
+      },{
+         "pri": 5,
+         "time":   125.000000,
+         "caller": "T5",
+         "msg": " example[5]"
+      },{
+         "pri": 6,
+         "time":   216.000000,
+         "caller": "T6",
+         "msg": " example[6]"
+      },{
+         "pri": 7,
+         "time":   343.000000,
+         "caller": "T7",
+         "msg": " example[7]"
+      },{
+         "pri": 8,
+         "time":   512.000000,
+         "caller": "T8",
+         "msg": " example[8]"
+      },{
+         "pri": 9,
+         "time":   729.000000,
+         "caller": "T9",
+         "msg": " example[9]"
+      },{
+         "pri": 10,
+         "time":  1000.000000,
+         "caller": "T10",
+         "msg": " example[10]"
+      },{
+         "pri": 11,
+         "time":  1331.000000,
+         "caller": "T11",
+         "msg": " example[11]"
+      },{
+         "pri": 12,
+         "time":  1728.000000,
+         "caller": "T12",
+         "msg": " example[12]"
+      },{
+         "pri": 13,
+         "time":  2197.000000,
+         "caller": "T13",
+         "msg": " example[13]"
+      },{
+         "pri": 14,
+         "time":  2744.000000,
+         "caller": "T14",
+         "msg": " example[14]"
+      },{
+         "pri": 15,
+         "time":  3375.000000,
+         "caller": "T15",
+         "msg": " example[15]"
+      },{
+         "pri": 16,
+         "time":  4096.000000,
+         "caller": "T16",
+         "msg": " example[16]"
+      },{
+         "pri": 17,
+         "time":  4913.000000,
+         "caller": "T17",
+         "msg": " example[17]"
+      },{
+         "pri": 18,
+         "time":  5832.000000,
+         "caller": "T18",
+         "msg": " example[18]"
+      },{
+         "pri": 19,
+         "time":  6859.000000,
+         "caller": "T19",
+         "msg": " example[19]"
+      },{
+         "pri": 20,
+         "time":  8000.000000,
+         "caller": "T20",
+         "msg": " example[20]"
+      },{
+         "pri": 21,
+         "time":  9261.000000,
+         "caller": "T21",
+         "msg": " example[21]"
+      },{
+         "pri": 22,
+         "time": 10648.000000,
+         "caller": "T22",
+         "msg": " example[22]"
+      },{
+         "pri": 23,
+         "time": 12167.000000,
+         "caller": "T23",
+         "msg": " example[23]"
+      },{
+         "pri": 24,
+         "time": 13824.000000,
+         "caller": "T24",
+         "msg": " example[24]"
+      },{
+         "pri": 25,
+         "time": 15625.000000,
+         "caller": "T25",
+         "msg": " example[25]"
+      },{
+         "pri": 26,
+         "time": 17576.000000,
+         "caller": "T26",
+         "msg": " example[26]"
+      },{
+         "pri": 27,
+         "time": 19683.000000,
+         "caller": "T27",
+         "msg": " example[27]"
+      },{
+         "pri": 28,
+         "time": 21952.000000,
+         "caller": "T28",
+         "msg": " example[28]"
+      },{
+         "pri": 29,
+         "time": 24389.000000,
+         "caller": "T29",
+         "msg": " example[29]"
+      },{
+         "pri": 30,
+         "time": 27000.000000,
+         "caller": "T10",
+         "msg": " example[30]"
+      },{
+         "pri": 31,
+         "time": 29791.000000,
+         "caller": "T31",
+         "msg": " example[31]"
+      },{
+         "pri": 32,
+         "time": 32768.000000,
+         "caller": "T32",
+         "msg": " example[32]"
+      },{
+         "pri": 33,
+         "time": 35937.000000,
+         "caller": "T33",
+         "msg": " example[33]"
+      },{
+         "pri": 34,
+         "time": 39304.000000,
+         "caller": "T34",
+         "msg": " example[34]"
+      },{
+         "pri": 35,
+         "time": 42875.000000,
+         "caller": "T35",
+         "msg": " example[35]"
+      },{
+         "pri": 36,
+         "time": 46656.000000,
+         "caller": "T36",
+         "msg": " example[36]"
+      },{
+         "pri": 37,
+         "time": 50653.000000,
+         "caller": "T37",
+         "msg": " example[37]"
+      },{
+         "pri": 38,
+         "time": 54872.000000,
+         "caller": "T38",
+         "msg": " example[38]"
+      },{
+         "pri": 39,
+         "time": 59319.000000,
+         "caller": "T39",
+         "msg": " example[39]"
+      },{
+         "pri": 40,
+         "time": 64000.000000,
+         "caller": "T40",
+         "msg": " example[40]"
+      },{
+         "pri": 41,
+         "time": 68921.000000,
+         "caller": "T41",
+         "msg": " example[41]"
+      },{
+         "pri": 42,
+         "time": 74088.000000,
+         "caller": "T42",
+         "msg": " example[42]"
+      },{
+         "pri": 43,
+         "time": 79507.000000,
+         "caller": "T43",
+         "msg": " example[43]"
+      },{
+         "pri": 44,
+         "time": 85184.000000,
+         "caller": "T44",
+         "msg": " example[44]"
+      },{
+         "pri": 45,
+         "time": 91125.000000,
+         "caller": "T45",
+         "msg": " example[45]"
+      },{
+         "pri": 46,
+         "time": 97336.000000,
+         "caller": "T46",
+         "msg": " example[46]"
+      },{
+         "pri": 47,
+         "time": 103823.000000,
+         "caller": "T47",
+         "msg": " example[47]"
+      },{
+         "pri": 48,
+         "time": 110592.000000,
+         "caller": "T48",
+         "msg": " example[48]"
+      },{
+         "pri": 49,
+         "time": 117649.000000,
+         "caller": "T49",
+         "msg": " example[49]"
+      },{
+         "pri": 50,
+         "time": 125000.000000,
+         "caller": "T50",
+         "msg": " example[50]"
+      },{
+         "pri": 51,
+         "time": 132651.000000,
+         "caller": "T51",
+         "msg": " example[51]"
+      },{
+         "pri": 52,
+         "time": 140608.000000,
+         "caller": "T52",
+         "msg": " example[52]"
+      },{
+         "pri": 53,
+         "time": 148877.000000,
+         "caller": "T53",
+         "msg": " example[53]"
+      },{
+         "pri": 54,
+         "time": 157464.000000,
+         "caller": "T54",
+         "msg": " example[54]"
+      },{
+         "pri": 55,
+         "time": 166375.000000,
+         "caller": "T55",
+         "msg": " example[55]"
+      },{
+         "pri": 56,
+         "time": 175616.000000,
+         "caller": "T56",
+         "msg": " example[56]"
+      },{
+         "pri": 57,
+         "time": 185193.000000,
+         "caller": "T57",
+         "msg": " example[57]"
+      },{
+         "pri": 58,
+         "time": 195112.000000,
+         "caller": "T58",
+         "msg": " example[58]"
+      },{
+         "pri": 59,
+         "time": 205379.000000,
+         "caller": "T59",
+         "msg": " example[59]"
+      },{
+         "pri": 60,
+         "time": 216000.000000,
+         "caller": "T60",
+         "msg": " example[60]"
+      },{
+         "pri": 61,
+         "time": 226981.000000,
+         "caller": "T61",
+         "msg": " example[61]"
+      },{
+         "pri": 62,
+         "time": 238328.000000,
+         "caller": "T62",
+         "msg": " example[62]"
+      },{
+         "pri": 63,
+         "time": 250047.000000,
+         "caller": "T63",
+         "msg": " example[63]"
+      },{
+         "pri": 64,
+         "time": 262144.000000,
+         "caller": "T64",
+         "msg": " example[64]"
+      },{
+         "pri": 65,
+         "time": 274625.000000,
+         "caller": "T65",
+         "msg": " example[65]"
+      },{
+         "pri": 66,
+         "time": 287496.000000,
+         "caller": "T66",
+         "msg": " example[66]"
+      },{
+         "pri": 67,
+         "time": 300763.000000,
+         "caller": "T67",
+         "msg": " example[67]"
+      },{
+         "pri": 68,
+         "time": 314432.000000,
+         "caller": "T68",
+         "msg": " example[68]"
+      },{
+         "pri": 69,
+         "time": 328509.000000,
+         "caller": "T69",
+         "msg": " example[69]"
+      },{
+         "pri": 70,
+         "time": 343000.000000,
+         "caller": "T70",
+         "msg": " example[70]"
+      },{
+         "pri": 71,
+         "time": 357911.000000,
+         "caller": "T71",
+         "msg": " example[71]"
+      },{
+         "pri": 72,
+         "time": 373248.000000,
+         "caller": "T72",
+         "msg": " example[72]"
+      },{
+         "pri": 73,
+         "time": 389017.000000,
+         "caller": "T73",
+         "msg": " example[73]"
+      },{
+         "pri": 74,
+         "time": 405224.000000,
+         "caller": "T74",
+         "msg": " example[74]"
+      },{
+         "pri": 75,
+         "time": 421875.000000,
+         "caller": "T75",
+         "msg": " example[75]"
+      },{
+         "pri": 76,
+         "time": 438976.000000,
+         "caller": "T76",
+         "msg": " example[76]"
+      },{
+         "pri": 77,
+         "time": 456533.000000,
+         "caller": "T77",
+         "msg": " example[77]"
+      },{
+         "pri": 78,
+         "time": 474552.000000,
+         "caller": "T78",
+         "msg": " example[78]"
+      },{
+         "pri": 79,
+         "time": 493039.000000,
+         "caller": "T79",
+         "msg": " example[79]"
+      },{
+         "pri": 80,
+         "time": 512000.000000,
+         "caller": "T80",
+         "msg": " example[80]"
+      },{
+         "pri": 81,
+         "time": 531441.000000,
+         "caller": "T81",
+         "msg": " example[81]"
+      },{
+         "pri": 82,
+         "time": 551368.000000,
+         "caller": "T82",
+         "msg": " example[82]"
+      },{
+         "pri": 83,
+         "time": 571787.000000,
+         "caller": "T83",
+         "msg": " example[83]"
+      },{
+         "pri": 84,
+         "time": 592704.000000,
+         "caller": "T84",
+         "msg": " example[84]"
+      },{
+         "pri": 85,
+         "time": 614125.000000,
+         "caller": "T85",
+         "msg": " example[85]"
+      },{
+         "pri": 86,
+         "time": 636056.000000,
+         "caller": "T86",
+         "msg": " example[86]"
+      },{
+         "pri": 87,
+         "time": 658503.000000,
+         "caller": "T87",
+         "msg": " example[87]"
+      },{
+         "pri": 88,
+         "time": 681472.000000,
+         "caller": "T88",
+         "msg": " example[88]"
+      },{
+         "pri": 89,
+         "time": 704969.000000,
+         "caller": "T89",
+         "msg": " example[89]"
+      },{
+         "pri": 90,
+         "time": 729000.000000,
+         "caller": "T90",
+         "msg": " example[90]"
+      },{
+         "pri": 91,
+         "time": 753571.000000,
+         "caller": "T91",
+         "msg": " example[91]"
+      },{
+         "pri": 92,
+         "time": 778688.000000,
+         "caller": "T92",
+         "msg": " example[92]"
+      },{
+         "pri": 93,
+         "time": 804357.000000,
+         "caller": "T93",
+         "msg": " example[93]"
+      },{
+         "pri": 94,
+         "time": 830584.000000,
+         "caller": "T94",
+         "msg": " example[94]"
+      },{
+         "pri": 95,
+         "time": 857375.000000,
+         "caller": "T95",
+         "msg": " example[95]"
+      },{
+         "pri": 96,
+         "time": 884736.000000,
+         "caller": "T96",
+         "msg": " example[96]"
+      },{
+         "pri": 97,
+         "time": 912673.000000,
+         "caller": "T97",
+         "msg": " example[97]"
+      },{
+         "pri": 98,
+         "time": 941192.000000,
+         "caller": "T98",
+         "msg": " example[98]"
+      },{
+         "pri": 99,
+         "time": 970299.000000,
+         "caller": "T99",
+         "msg": " example[99]"
+      },{
+         "pri": 100,
+         "time": 1000000.000000,
+         "caller": "T100",
+         "msg": " example[100]"
+      },{
+         "pri": 101,
+         "time": 1030301.000000,
+         "caller": "T101",
+         "msg": " example[101]"
+      },{
+         "pri": 102,
+         "time": 1061208.000000,
+         "caller": "T102",
+         "msg": " example[102]"
+      },{
+         "pri": 103,
+         "time": 1092727.000000,
+         "caller": "T103",
+         "msg": " example[103]"
+      },{
+         "pri": 104,
+         "time": 1124864.000000,
+         "caller": "T104",
+         "msg": " example[104]"
+      }
+   ]
+}
diff --git a/tests/expected/dmesg/kmsg-file-printk-caller b/tests/expected/dmesg/kmsg-file-printk-caller
new file mode 100644
index 000000000..785d730a5
--- /dev/null
+++ b/tests/expected/dmesg/kmsg-file-printk-caller
@@ -0,0 +1,115 @@
+{
+   "dmesg": [
+      {
+         "pri": 5,
+         "time":     0.000000,
+         "caller": "T0",
+         "msg": "Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T1",
+         "msg": "Command line: initrd=\\ucode.img initrd=\\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T2",
+         "msg": "BIOS-provided physical RAM map:"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T3",
+         "msg": "BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T4",
+         "msg": "BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T5",
+         "msg": "BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T6",
+         "msg": "BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T7",
+         "msg": "BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T8",
+         "msg": "BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T9",
+         "msg": "BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T10",
+         "msg": "BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved"
+      },{
+         "pri": 6,
+         "time":     0.367657,
+         "caller": "T11",
+         "msg": "ACPI: \\_SB_.PCI0.GP19.NHI1.PWRS: New power resource"
+      },{
+         "pri": 6,
+         "time":     0.368615,
+         "caller": "T12",
+         "msg": "ACPI: \\_SB_.PCI0.GP19.XHC4.PWRS: New power resource"
+      },{
+         "pri": 6,
+         "time":     0.376316,
+         "caller": "T13",
+         "msg": "ACPI: \\_SB_.PRWL: New power resource"
+      },{
+         "pri": 6,
+         "time":     0.376343,
+         "caller": "T14",
+         "msg": "ACPI: \\_SB_.PRWB: New power resource"
+      },{
+         "pri": 6,
+         "time":     0.377373,
+         "caller": "T15",
+         "msg": "ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])"
+      },{
+         "pri": 6,
+         "time":     0.377378,
+         "caller": "T16",
+         "msg": "acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]"
+      },{
+         "pri": 6,
+         "time":     0.377569,
+         "caller": "T17",
+         "msg": "acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]"
+      },{
+         "pri": 6,
+         "time":     0.377933,
+         "caller": "T18",
+         "msg": "acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]"
+      },{
+         "pri": 6,
+         "time":     0.378458,
+         "caller": "T19",
+         "msg": "PCI host bridge to bus 0000:00"
+      },{
+         "pri": 6,
+         "time":     0.378459,
+         "caller": "T20",
+         "msg": "pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]"
+      },{
+         "pri": 6,
+         "time":     0.378461,
+         "caller": "T21",
+         "msg": "pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]"
+      }
+   ]
+}
diff --git a/tests/expected/dmesg/limit-kmsg-printk-caller b/tests/expected/dmesg/limit-kmsg-printk-caller
new file mode 100644
index 000000000..2ea07d4c8
--- /dev/null
+++ b/tests/expected/dmesg/limit-kmsg-printk-caller
@@ -0,0 +1,11 @@
+[    0.367657] [    T11] ACPI: \_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+[    0.368615] [    T12] ACPI: \_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+[    0.376316] [    T13] ACPI: \_SB_.PRWL: New power resource
+[    0.376343] [    T14] ACPI: \_SB_.PRWB: New power resource
+[    0.377373] [    T15] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+[    0.377378] [    T16] acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+[    0.377569] [    T17] acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]
+[    0.377933] [    T18] acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+[    0.378458] [    T19] PCI host bridge to bus 0000:00
+[    0.378459] [    T20] pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]
+[    0.378461] [    T21] pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]
diff --git a/tests/ts/dmesg/colors-kmsg-printk-caller b/tests/ts/dmesg/colors-kmsg-printk-caller
new file mode 100755
index 000000000..513ca82d4
--- /dev/null
+++ b/tests/ts/dmesg/colors-kmsg-printk-caller
@@ -0,0 +1,29 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="colors-kmsg-prtk-caller"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+ts_inhibit_custom_colorscheme
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG --color=always -K $TS_SELF/kmsg-input-printk-caller -x >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/console-levels-kmsg-printk-caller b/tests/ts/dmesg/console-levels-kmsg-printk-caller
new file mode 100755
index 000000000..00b8b3681
--- /dev/null
+++ b/tests/ts/dmesg/console-levels-kmsg-printk-caller
@@ -0,0 +1,36 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="levels-kmsg-prtk-caller"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+for I in {-1..8}; do
+	$TS_HELPER_DMESG -K $TS_SELF/kmsg-input-printk-caller -l $I >> $TS_OUTPUT 2>/dev/null
+done
+
+$TS_HELPER_DMESG -K $TS_SELF/kmsg-input-printk-caller -l err+ >> $TS_OUTPUT 2>/dev/null
+$TS_HELPER_DMESG -K $TS_SELF/kmsg-input-printk-caller -l emerg+ >> $TS_OUTPUT 2>/dev/null
+$TS_HELPER_DMESG -K $TS_SELF/kmsg-input-printk-caller -l +err >> $TS_OUTPUT 2>/dev/null
+$TS_HELPER_DMESG -K $TS_SELF/kmsg-input-printk-caller -l +debug >> $TS_OUTPUT 2>/dev/null
+$TS_HELPER_DMESG -K $TS_SELF/kmsg-input-printk-caller -l + 2>> $TS_OUTPUT >/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/decode-kmsg-printk-caller b/tests/ts/dmesg/decode-kmsg-printk-caller
new file mode 100755
index 000000000..d05b9fb68
--- /dev/null
+++ b/tests/ts/dmesg/decode-kmsg-printk-caller
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="decode-kmsg-prtk-caller"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG -x -K $TS_SELF/kmsg-input-printk-caller >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/delta-kmsg-printk-caller b/tests/ts/dmesg/delta-kmsg-printk-caller
new file mode 100755
index 000000000..020b82357
--- /dev/null
+++ b/tests/ts/dmesg/delta-kmsg-printk-caller
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="delta-kmsg-prtk-caller"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG -d -K $TS_SELF/kmsg-input-printk-caller >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/facilities-kmsg-printk-caller b/tests/ts/dmesg/facilities-kmsg-printk-caller
new file mode 100755
index 000000000..bec301516
--- /dev/null
+++ b/tests/ts/dmesg/facilities-kmsg-printk-caller
@@ -0,0 +1,30 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="facilities-kmsg-prtk-caller"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+for I in {-1..12}; do
+	$TS_HELPER_DMESG -K $TS_SELF/kmsg-input-printk-caller -f $I -x >> $TS_OUTPUT 2>/dev/null
+done
+
+ts_finalize
diff --git a/tests/ts/dmesg/indentation-kmsg-printk-caller b/tests/ts/dmesg/indentation-kmsg-printk-caller
new file mode 100755
index 000000000..53e549b62
--- /dev/null
+++ b/tests/ts/dmesg/indentation-kmsg-printk-caller
@@ -0,0 +1,40 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="indentation-kmsg-prtk-caller"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG -K $TS_SELF/newlines-kmsg-printk-caller >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG -K $TS_SELF/newlines-kmsg-printk-caller -x >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=delta --kmsg-file $TS_SELF/newlines-kmsg-printk-caller >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=notime --kmsg-file $TS_SELF/newlines-kmsg-printk-caller >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=reltime --kmsg-file $TS_SELF/newlines-kmsg-printk-caller >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=ctime --kmsg-file $TS_SELF/newlines-kmsg-printk-caller >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=iso --kmsg-file $TS_SELF/newlines-kmsg-printk-caller >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+ts_finalize
diff --git a/tests/ts/dmesg/input-syslog-printk-caller b/tests/ts/dmesg/input-syslog-printk-caller
new file mode 100644
index 000000000..5fcff6abe
--- /dev/null
+++ b/tests/ts/dmesg/input-syslog-printk-caller
@@ -0,0 +1,105 @@
+<0>[    0.000000] [    T0] example[0]
+<1>[    1.000000] [    T1] example[1]
+<2>[    8.000000] [    T2] example[2]
+<3>[   27.000000] [    T3] example[3]
+<4>[   64.000000] [    T4] example[4]
+<5>[  125.000000] [    T5] example[5]
+<6>[  216.000000] [    T6] example[6]
+<7>[  343.000000] [    T7] example[7]
+<8>[  512.000000] [    T8] example[8]
+<9>[  729.000000] [    T9] example[9]
+<10>[ 1000.000000] [   T10] example[10]
+<11>[ 1331.000000] [   T11] example[11]
+<12>[ 1728.000000] [   T12] example[12]
+<13>[ 2197.000000] [   T13] example[13]
+<14>[ 2744.000000] [   T14] example[14]
+<15>[ 3375.000000] [   T15] example[15]
+<16>[ 4096.000000] [   T16] example[16]
+<17>[ 4913.000000] [   T17] example[17]
+<18>[ 5832.000000] [   T18] example[18]
+<19>[ 6859.000000] [   T19] example[19]
+<20>[ 8000.000000] [   T20] example[20]
+<21>[ 9261.000000] [   T21] example[21]
+<22>[10648.000000] [   T22] example[22]
+<23>[12167.000000] [   T23] example[23]
+<24>[13824.000000] [   T24] example[24]
+<25>[15625.000000] [   T25] example[25]
+<26>[17576.000000] [   T26] example[26]
+<27>[19683.000000] [   T27] example[27]
+<28>[21952.000000] [   T28] example[28]
+<29>[24389.000000] [   T29] example[29]
+<30>[27000.000000] [   T10] example[30]
+<31>[29791.000000] [   T31] example[31]
+<32>[32768.000000] [   T32] example[32]
+<33>[35937.000000] [   T33] example[33]
+<34>[39304.000000] [   T34] example[34]
+<35>[42875.000000] [   T35] example[35]
+<36>[46656.000000] [   T36] example[36]
+<37>[50653.000000] [   T37] example[37]
+<38>[54872.000000] [   T38] example[38]
+<39>[59319.000000] [   T39] example[39]
+<40>[64000.000000] [   T40] example[40]
+<41>[68921.000000] [   T41] example[41]
+<42>[74088.000000] [   T42] example[42]
+<43>[79507.000000] [   T43] example[43]
+<44>[85184.000000] [   T44] example[44]
+<45>[91125.000000] [   T45] example[45]
+<46>[97336.000000] [   T46] example[46]
+<47>[103823.000000] [   T47] example[47]
+<48>[110592.000000] [   T48] example[48]
+<49>[117649.000000] [   T49] example[49]
+<50>[125000.000000] [   T50] example[50]
+<51>[132651.000000] [   T51] example[51]
+<52>[140608.000000] [   T52] example[52]
+<53>[148877.000000] [   T53] example[53]
+<54>[157464.000000] [   T54] example[54]
+<55>[166375.000000] [   T55] example[55]
+<56>[175616.000000] [   T56] example[56]
+<57>[185193.000000] [   T57] example[57]
+<58>[195112.000000] [   T58] example[58]
+<59>[205379.000000] [   T59] example[59]
+<60>[216000.000000] [   T60] example[60]
+<61>[226981.000000] [   T61] example[61]
+<62>[238328.000000] [   T62] example[62]
+<63>[250047.000000] [   T63] example[63]
+<64>[262144.000000] [   T64] example[64]
+<65>[274625.000000] [   T65] example[65]
+<66>[287496.000000] [   T66] example[66]
+<67>[300763.000000] [   T67] example[67]
+<68>[314432.000000] [   T68] example[68]
+<69>[328509.000000] [   T69] example[69]
+<70>[343000.000000] [   T70] example[70]
+<71>[357911.000000] [   T71] example[71]
+<72>[373248.000000] [   T72] example[72]
+<73>[389017.000000] [   T73] example[73]
+<74>[405224.000000] [   T74] example[74]
+<75>[421875.000000] [   T75] example[75]
+<76>[438976.000000] [   T76] example[76]
+<77>[456533.000000] [   T77] example[77]
+<78>[474552.000000] [   T78] example[78]
+<79>[493039.000000] [   T79] example[79]
+<80>[512000.000000] [   T80] example[80]
+<81>[531441.000000] [   T81] example[81]
+<82>[551368.000000] [   T82] example[82]
+<83>[571787.000000] [   T83] example[83]
+<84>[592704.000000] [   T84] example[84]
+<85>[614125.000000] [   T85] example[85]
+<86>[636056.000000] [   T86] example[86]
+<87>[658503.000000] [   T87] example[87]
+<88>[681472.000000] [   T88] example[88]
+<89>[704969.000000] [   T89] example[89]
+<90>[729000.000000] [   T90] example[90]
+<91>[753571.000000] [   T91] example[91]
+<92>[778688.000000] [   T92] example[92]
+<93>[804357.000000] [   T93] example[93]
+<94>[830584.000000] [   T94] example[94]
+<95>[857375.000000] [   T95] example[95]
+<96>[884736.000000] [   T96] example[96]
+<97>[912673.000000] [   T97] example[97]
+<98>[941192.000000] [   T98] example[98]
+<99>[970299.000000] [   T99] example[99]
+<100>[1000000.000000] [  T100] example[100]
+<101>[1030301.000000] [  T101] example[101]
+<102>[1061208.000000] [  T102] example[102]
+<103>[1092727.000000] [  T103] example[103]
+<104>[1124864.000000] [  T104] example[104]
diff --git a/tests/ts/dmesg/json-kmsg-printk-caller b/tests/ts/dmesg/json-kmsg-printk-caller
new file mode 100755
index 000000000..cb6c5e4a8
--- /dev/null
+++ b/tests/ts/dmesg/json-kmsg-printk-caller
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="json-kmsg-prtk-caller"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG -J -K $TS_SELF/kmsg-input-printk-caller >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/json-syslog-printk-caller b/tests/ts/dmesg/json-syslog-printk-caller
new file mode 100755
index 000000000..10dfaa423
--- /dev/null
+++ b/tests/ts/dmesg/json-syslog-printk-caller
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="json-syslog-prtk-caller"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG -J -F $TS_SELF/input-syslog-printk-caller >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/kmsg-file-printk-caller b/tests/ts/dmesg/kmsg-file-printk-caller
new file mode 100755
index 000000000..a01fc723f
--- /dev/null
+++ b/tests/ts/dmesg/kmsg-file-printk-caller
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="kmsg-file-prtk-caller"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG -J -K $TS_SELF/kmsg-input-printk-caller >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/kmsg-input-printk-caller b/tests/ts/dmesg/kmsg-input-printk-caller
new file mode 100644
index 0000000000000000000000000000000000000000..8d67f11cad7988469dd5e4a7c8589d2b744168bb
GIT binary patch
literal 2187
zcmbW2TW{hx6oB`+zv4*yQZ$g-aqb9dAw>nL(1<WMu@wr5q0uIBlmsaMe(Z!%<LSbv
zlRV_&oX=m5?PI-*_}S}*L6Xp7utfdGINQI%ffi-VGB6ZF(Rx7<zTh5)+e9?}BOdF!
z4&3g-5N;n_w*#0cs)9j9DnS;)U3i#(h9u&x{5s-+Rh*O^P!$a;r~`jv@Mj))i}85o
zE!X$o=fm05g&E7bfHb(LVT}TW9MyKP4WAG{ZvHa5STe?am!)ZtMZlG)1928tMKt*L
zRS)+ei>MN(yY|bvJxI4@ul|L)xi~^toboE7hd88zJAS>(4k<+$&WTf=%8I5=6qjL8
zL{KnRHJ_wGp3~y4X%}XyWTy5<(<i@|7wiy6G=lu)RK`5fuo%vO$2uZ}NFk&Np_Ymq
zSfw-t^eTS4ee|SPHr;Nw&#*6pO+p1wlYrWFpuOc}8Mxs*4lHO%ivx`WQkRhWRV1!e
z+ekYQM9I;RfW|eTy?GCe&cL>#DIv|PNctWrvM4)R641H|6j_w>Xm5!~<TDIiZwm7-
zzR063A?@o(63R$TCHk+9SYEssT|x4A;}=U!)6d9uCN)C3#4rurY}Eyf`{GX=5bJ8~
zkJgIkPLcB9VOyC`rdaX5E_?^(^awdS(n8E1wlBhFN)n9|Ed%RqqI#M5ZQ^RbA?jUX
z8U!0{B6&w#e0{tu#TOq(XrztM{s%F-j4(OEB&LMW&j_9%Snyf_qau!W6jmZ*&u|;D
zG>9`^*ARl$W?%BV9-k?ldhrsgAzE!IqaTEM4Bp&BLu5I;BEtH~cO7{0q1@*=E2<J!
z<JXF2yw12R+r~Q>`rZuOgoXd{t50_+&G=U{e+uLK1x&nez2zyV<oO2t&m;f4zZ}m7
zqMIAIAAgy;<H0BK<h*s-_}RiwH|(~bdC4zNf@;f(6e31T$apT!y0G#mo;zVxp6t2m
zc=16E4G9gK&(ycA3tN{oc$zZCOFYY}f+ajvd?e`4&b`?f#IqaZ!6r`P>I9F=1>Ae?
zN1ZTtvNT;9I=e5X!3!%Z*fi6iV$cjaAI4@s(=@e-Y$sJk{XC4<txuhL=c$8#E-qNb
x49;7GD7oR*gkzjV>?paPL2n~_e!=^1N$^$A^$pxgsfs@$5!EG7)Tlp__yL<dZm0kN

literal 0
HcmV?d00001

diff --git a/tests/ts/dmesg/limit-kmsg-printk-caller b/tests/ts/dmesg/limit-kmsg-printk-caller
new file mode 100755
index 000000000..4d4d9912d
--- /dev/null
+++ b/tests/ts/dmesg/limit-kmsg-printk-caller
@@ -0,0 +1,29 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="limit-kmsg-prtk-caller"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG --since @1234567890.124 --until @1234567991 -K $TS_SELF/kmsg-input-printk-caller \
+	>> $TS_OUTPUT 2> $TS_ERRLOG
+
+ts_finalize
diff --git a/tests/ts/dmesg/newlines-kmsg-printk-caller b/tests/ts/dmesg/newlines-kmsg-printk-caller
new file mode 100644
index 0000000000000000000000000000000000000000..574d2177796677b73f1efcf273005169ed832c60
GIT binary patch
literal 152
zcmXrjF#tkco#e!voYW%Q5CiL+%)C^Es??%<E(Svb9YY;M128~RV`!b1TFwPh$Hia-
tQeuRm#K^j&Jf91MLCT7`7>o^cjC71K)EQfsWE7>QazV)4{GwE-1^{d2D<=Q|

literal 0
HcmV?d00001

-- 
2.43.0


^ permalink raw reply related

* PATCH] util-linux/sys-utils dmesg add PRINTK_CALLER support
From: Edward Chron @ 2023-12-18 14:15 UTC (permalink / raw)
  To: util-linux; +Cc: colona, echron

Submission to Project: util-linux
Open Incident: #2609 at github.com/util-linux/util-linux/issues/2609
Component: util-linux/sys-utils
File: dmesg.c
Code level patch applied against: 2.39.3 - latest code pulled from
           git.github.com:util-linux/util-linux.git
Revision: #1 on 2023/12/08 per Review from Karel Zak
Revision: #2 on 2023/12/12 Adjust line offsets for master update and
                           Add caller_id_size init to dmesg -K
Revision: #3 on 2023/12/12 Use of sizeof for cidbuf and limit search
                           for caller_id to dmesg prefix to msg text
Revision: #4 on 2023/12/15 Ensure SYSLOG and kmsg inputs have
                           caller_id_size set appropriately

Add support to standard dmesg command for the optional Linux Kernel
debug CONFIG option PRINTK_CALLER which adds an optional dmesg field
that contains the Thread Id or CPU Id that is issuing the printk to
add the message to the kernel ring buffer. This makes debugging simpler
as dmesg entries for a specific thread or CPU can be recognized.

The dmesg -S using the old syslog interface supports printing the
PRINTK_CALLER field but currently standard dmesg does not support
printing the field if present. There are utilities that use dmesg and
so it would be optimal if dmesg supported PRINTK_CALLER as well.

The additional field provided by PRINTK_CALLER is only present
if it was configured for the Linux kernel where the dmesg command
is run. It is a debug option and not configured by default so the
dmesg output will only change for those kernels where the option was
configured when the kernel was built. For users who went to the
trouble to configure PRINTK_CALLER and have the extra field available
for debugging, having dmesg print the field is very helpful.

Size of the PRINTK_CALLER field is determined by the maximum number
tasks that can be run on the system which is limited by the value of
/proc/sys/kernel/pid_max as pid values are from 0 to value - 1.
This value determines the number of id digits needed by the caller id.
The PRINTK_CALLER field is printed as T<id> for a Task Id or C<id>
for a CPU Id for a printk in CPU context. The values are left space
padded and enclosed in parentheses such as: [    T123] or [     C16]

For consistency with dmesg -S which supports the PRINTK_CALLER field
the field is printed followed by a space. For JSON format output the
PRINTK_CALLER field is identified as caller as that is consistent with
it's naming in /dev/kmsg. No space padding is used to reduce space
consumed by the JSON output. So the output from the command on a system
with PRINTK_CALLER field enabled in the Linux .config file the dmesg
output appears as:

> dmesg
...
[  520.897104] [   T3919] usb 3-3: Product: USB 2.0 Hub

and

> dmesg -x
...
kern  :info  : [  520.897104] [   T3919] usb 3-3: Product: USB 2.0 Hub

and

> dmesg -J
...
      },{
         "pri": 6,
         "time":    520.897104,
         "caller": "T3919",
         "msg": "usb 3-3: Product: USB 2.0 Hub"
      },{

and

> dmesg -J -x
...
      },{
         "fac": "kern",
         "pri": "info",
         "time":   520.897104,
         "caller": "T3919",
         "msg": "usb 3-3: Product: USB 2.0 Hub"
      },{

>

For comparison:

> dmesg -S
...
[  520.897104] [ T3919] usb 3-3: Product: USB 2.0 Hub

and

> dmesg -S -x
...
kern  :info  : [  520.897104] [ T3919] usb 3-3: Product: USB 2.0 Hub

Note: When dmesg uses the old syslog interface the reserved space for
      the PRINTK_CALLER field is capped at 5 digits because 32-bit
      kernels are capped at 32768 as the max number of PIDs. However,
      64-bit systems are currently capped at 2^22 PIDs (0 - 4194303).
      The PID cap is set by PID_MAX_LIMIT but the system limit can be
      less so we use /proc/sys/kernel/pid_max to determine the size
      needed to hold the maximum PID value size for the current system.
      Many 64-bit systems support 2^22 PIDs (0 - 4194303) and you see:

> dmesg -x
...
kern  :info  : [  520.899558] [   T3919] hub 3-3:1.0: USB hub found
...
kern  :info  : [ 9830.456898] [  T98982] cgroup: fork rejected by pids ...
kern  :info  : [14301.158878] [ T137336] cgroup: fork rejected by pids ...
kern  :info  : [18980.803190] [T1637865] cgroup: fork rejected by pids ...

> dmesg -S -x
...
kern  :info  : [  520.899558] [ T3919] hub 3-3:1.0: USB hub found
...
kern  :info  : [ 9830.456898] [T98982] cgroup: fork rejected by pids ...
kern  :info  : [14301.158878] [T137336] cgroup: fork rejected by pids ...
kern  :info  : [18980.803190] [T1637865] cgroup: fork rejected by pids ...

This is the only difference seen with PRINTK_CALLER configured and
printing between the dmesg /dev/kmsg interface and the dmesg -S syslog
interface.

Signed-off-by: Ivan Delalande <colona@arista.com>
Signed-off-by: Edward Chron <echron@arista.com>
---
 include/pathnames.h                           |   3 +
 sys-utils/dmesg.c                             | 124 +++-
 .../expected/dmesg/colors-kmsg-printk-caller  |  22 +
 .../dmesg/console-levels-kmsg-printk-caller   |  45 ++
 .../expected/dmesg/decode-kmsg-printk-caller  |  22 +
 tests/expected/dmesg/delta-kmsg-printk-caller |  22 +
 .../dmesg/facilities-kmsg-printk-caller       |  22 +
 .../dmesg/indentation-kmsg-printk-caller      |  28 +
 tests/expected/dmesg/json-kmsg-printk-caller  | 115 ++++
 .../expected/dmesg/json-syslog-printk-caller  | 530 ++++++++++++++++++
 tests/expected/dmesg/kmsg-file-printk-caller  | 115 ++++
 tests/expected/dmesg/limit-kmsg-printk-caller |  11 +
 tests/ts/dmesg/colors-kmsg-printk-caller      |  29 +
 .../dmesg/console-levels-kmsg-printk-caller   |  36 ++
 tests/ts/dmesg/decode-kmsg-printk-caller      |  28 +
 tests/ts/dmesg/delta-kmsg-printk-caller       |  28 +
 tests/ts/dmesg/facilities-kmsg-printk-caller  |  30 +
 tests/ts/dmesg/indentation-kmsg-printk-caller |  40 ++
 tests/ts/dmesg/input-syslog-printk-caller     | 105 ++++
 tests/ts/dmesg/json-kmsg-printk-caller        |  28 +
 tests/ts/dmesg/json-syslog-printk-caller      |  28 +
 tests/ts/dmesg/kmsg-file-printk-caller        |  28 +
 tests/ts/dmesg/kmsg-input-printk-caller       | Bin 0 -> 2187 bytes
 tests/ts/dmesg/limit-kmsg-printk-caller       |  29 +
 tests/ts/dmesg/newlines-kmsg-printk-caller    | Bin 0 -> 152 bytes
 25 files changed, 1466 insertions(+), 2 deletions(-)
 create mode 100644 tests/expected/dmesg/colors-kmsg-printk-caller
 create mode 100644 tests/expected/dmesg/console-levels-kmsg-printk-caller
 create mode 100644 tests/expected/dmesg/decode-kmsg-printk-caller
 create mode 100644 tests/expected/dmesg/delta-kmsg-printk-caller
 create mode 100644 tests/expected/dmesg/facilities-kmsg-printk-caller
 create mode 100644 tests/expected/dmesg/indentation-kmsg-printk-caller
 create mode 100644 tests/expected/dmesg/json-kmsg-printk-caller
 create mode 100644 tests/expected/dmesg/json-syslog-printk-caller
 create mode 100644 tests/expected/dmesg/kmsg-file-printk-caller
 create mode 100644 tests/expected/dmesg/limit-kmsg-printk-caller
 create mode 100755 tests/ts/dmesg/colors-kmsg-printk-caller
 create mode 100755 tests/ts/dmesg/console-levels-kmsg-printk-caller
 create mode 100755 tests/ts/dmesg/decode-kmsg-printk-caller
 create mode 100755 tests/ts/dmesg/delta-kmsg-printk-caller
 create mode 100755 tests/ts/dmesg/facilities-kmsg-printk-caller
 create mode 100755 tests/ts/dmesg/indentation-kmsg-printk-caller
 create mode 100644 tests/ts/dmesg/input-syslog-printk-caller
 create mode 100755 tests/ts/dmesg/json-kmsg-printk-caller
 create mode 100755 tests/ts/dmesg/json-syslog-printk-caller
 create mode 100755 tests/ts/dmesg/kmsg-file-printk-caller
 create mode 100644 tests/ts/dmesg/kmsg-input-printk-caller
 create mode 100755 tests/ts/dmesg/limit-kmsg-printk-caller
 create mode 100644 tests/ts/dmesg/newlines-kmsg-printk-caller

diff --git a/include/pathnames.h b/include/pathnames.h
index caf0e63d4..81fa405f6 100644
--- a/include/pathnames.h
+++ b/include/pathnames.h
@@ -230,4 +230,7 @@
 /* cgroup path */
 #define _PATH_SYS_CGROUP	"/sys/fs/cgroup"
 
+/* Maximum number of PIDs system supports */
+#define _PATH_PROC_PIDMAX	"/proc/sys/kernel/pid_max"
+
 #endif /* PATHNAMES_H */
diff --git a/sys-utils/dmesg.c b/sys-utils/dmesg.c
index 77728b419..520cfbf04 100644
--- a/sys-utils/dmesg.c
+++ b/sys-utils/dmesg.c
@@ -13,7 +13,9 @@
  */
 #include <stdio.h>
 #include <getopt.h>
+#include <stdbool.h>
 #include <stdlib.h>
+#include <string.h>
 #include <sys/klog.h>
 #include <sys/syslog.h>
 #include <sys/time.h>
@@ -41,6 +43,7 @@
 #include "mangle.h"
 #include "pager.h"
 #include "jsonwrt.h"
+#include "pathnames.h"
 
 /* Close the log.  Currently a NOP. */
 #define SYSLOG_ACTION_CLOSE          0
@@ -65,6 +68,12 @@
 /* Return size of the log buffer */
 #define SYSLOG_ACTION_SIZE_BUFFER   10
 
+#define PID_CHARS_MAX sizeof(stringify_value(LONG_MAX))
+#define PID_CHARS_DEFAULT sizeof(stringify_value(INT_MAX))
+#define SYSLOG_DEFAULT_CALLER_ID_CHARS sizeof(stringify_value(SHRT_MAX))
+#define DMESG_CALLER_PREFIX "caller="
+#define DMESG_CALLER_PREFIXSZ (sizeof(DMESG_CALLER_PREFIX)-1)
+
 /*
  * Color scheme
  */
@@ -233,6 +242,7 @@ struct dmesg_control {
 			force_prefix:1;	/* force timestamp and decode prefix
 					   on each line */
 	int		indent;		/* due to timestamps if newline */
+	size_t          caller_id_size;   /* PRINTK_CALLERID max field size */
 };
 
 struct dmesg_record {
@@ -242,6 +252,7 @@ struct dmesg_record {
 	int		level;
 	int		facility;
 	struct timeval  tv;
+	char		caller_id[PID_CHARS_MAX];
 
 	const char	*next;		/* buffer with next unparsed record */
 	size_t		next_size;	/* size of the next buffer */
@@ -254,6 +265,7 @@ struct dmesg_record {
 		(_r)->level = -1; \
 		(_r)->tv.tv_sec = 0; \
 		(_r)->tv.tv_usec = 0; \
+		(_r)->caller_id[0] = 0; \
 	} while (0)
 
 static int process_kmsg(struct dmesg_control *ctl);
@@ -551,6 +563,45 @@ static int get_syslog_buffer_size(void)
 	return n > 0 ? n : 0;
 }
 
+/*
+ * Get the number of characters needed to hold the maximum number
+ * of tasks this system supports. This size of string could hold
+ * a thread id large enough for the highest thread id.
+ * This is needed to determine the number of characters reserved for
+ * the PRINTK_CALLER field if it has been configured in the Linux Kernel.
+ *
+ * The number of digits sets the max value since the value can't exceed
+ * a value of that size. The /proc field defined by _PATH_PROC_PIDMAX
+ * holds the maximum number of PID values that may be ussed by the system,
+ * so 0 to that value minus one.
+ *
+ * For determining the size of the PRINTK_CALLER field, we make the safe
+ * assumption that the number of threads >= number of cpus. This because
+ * the PRINTK_CALLER field can hold either a thread id or a CPU id value.
+ *
+ * If we can't access the pid max kernel proc entry we assign a default
+ * field size of 5 characters as that is what the old syslog interface
+ * uses as the reserved field size. This is justified because 32-bit Linux
+ * systems are limited to PID values between (0-32767).
+ *
+ */
+static size_t max_threads_id_size(void)
+{
+	char taskmax[PID_CHARS_MAX] = {'\0'};
+	ssize_t rdsize;
+	int fd;
+
+	fd = open(_PATH_PROC_PIDMAX, O_RDONLY);
+	if (fd == -1)
+		return PID_CHARS_DEFAULT;
+
+	rdsize = read(fd, taskmax, sizeof(taskmax));
+	if (rdsize == -1)
+		return PID_CHARS_DEFAULT;
+
+	return strnlen(taskmax, sizeof(taskmax));
+}
+
 /*
  * Reads messages from regular file by mmap
  */
@@ -624,11 +675,13 @@ static ssize_t process_buffer(struct dmesg_control *ctl, char **buf)
 			ctl->bufsize = get_syslog_buffer_size();
 
 		n = read_syslog_buffer(ctl, buf);
+		/* Set number of PID characters for caller_id spacing */
+		ctl->caller_id_size = SYSLOG_DEFAULT_CALLER_ID_CHARS;
 		break;
 	case DMESG_METHOD_KMSG:
 		if (ctl->filename)
 			n = process_kmsg_file(ctl, buf);
-		else
+		else 
 			/*
 			 * Since kernel 3.5.0
 			 */
@@ -728,6 +781,39 @@ static const char *skip_item(const char *begin, const char *end, const char *sep
 	return begin;
 }
 
+/*
+ * Checks to see if the caller (caller id) field is present in the kmsg record.
+ * This is true if the PRINTK_CALLER config option has been set in the kernel.
+ *
+ * If the caller_id is found in the kmsg buffer then return the id and id type
+ * to the caller in dmesg caller_id. Returns string pointer to next value.
+ *
+ */
+static const char *parse_callerid(const char *p_str, const char *end,
+				  struct dmesg_record *p_drec)
+{
+	const char *p_after;
+	const char *p_next;
+	size_t cid_size;
+	char *p_scn;
+	char *p_cid;
+
+	/* Check for PRINTK_CALLER prefix, must be before msg text */
+	p_cid = strstr(p_str, DMESG_CALLER_PREFIX);
+	p_scn = strchr(p_str, ';');
+	if (p_cid != NULL && p_drec != NULL && p_scn != NULL && p_cid < p_scn) {
+		p_next = p_cid + DMESG_CALLER_PREFIXSZ;
+		p_after = skip_item(p_next, end, ",;");
+		cid_size = p_after - p_next;
+		if (cid_size < sizeof(p_drec->caller_id))
+			xstrncpy(p_drec->caller_id, p_next, cid_size);
+		else
+			return p_str;
+		return p_after;
+	}
+	return p_str;
+}
+
 /*
  * Parses one record from syslog(2) buffer
  */
@@ -795,6 +881,18 @@ static int get_next_syslog_record(struct dmesg_control *ctl,
 				begin++;
 		}
 
+		if (*begin == '[' && (*(begin + 1) == ' ' ||
+			(*(begin + 1) == 'T' || *(begin + 1) == 'C'))) {
+			const char *start = begin + 1;
+			size_t id_size;
+
+			start = start + strspn(start, " ");
+			begin = skip_item(begin, end, "]");
+			id_size = begin - start;
+			if (id_size < sizeof(rec->caller_id))
+				xstrncpy(rec->caller_id, start, id_size);
+		}
+
 		rec->mesg = begin;
 		rec->mesg_size = end - begin;
 
@@ -1101,6 +1199,19 @@ full_output:
 			color_disable();
 	}
 
+	if (*rec->caller_id) {
+		if (ctl->json) {
+			ul_jsonwrt_value_s(&ctl->jfmt, "caller", rec->caller_id);
+		} else {
+			char cidbuf[PID_CHARS_MAX+3] = {'\0'};
+
+			sprintf(cidbuf, "[%*s] ",
+				(char)ctl->caller_id_size - 1, rec->caller_id);
+			ctl->indent += strnlen(cidbuf, sizeof(cidbuf));
+			fputs(cidbuf, stdout);
+		}
+	}
+
 	/*
 	 * A kernel message may contain several lines of output, separated
 	 * by '\n'.  If the timestamp and decode outputs are forced then each
@@ -1284,7 +1395,10 @@ static int parse_kmsg_record(struct dmesg_control *ctl,
 		goto mesg;
 
 	/* D) optional fields (ignore) */
-	p = skip_item(p, end, ";");
+	p = skip_item(p, end, ",;");
+
+	/* Include optional PRINTK_CALLER field if it is present */
+	p = parse_callerid(p, end, rec);
 
 mesg:
 	/* E) message text */
@@ -1336,6 +1450,9 @@ static int process_kmsg(struct dmesg_control *ctl)
 	if (ctl->method != DMESG_METHOD_KMSG || ctl->kmsg < 0)
 		return -1;
 
+	/* Determine number of PID characters for caller_id spacing */
+	ctl->caller_id_size = max_threads_id_size();
+
 	/*
 	 * The very first read() call is done in kmsg_init() where we test
 	 * /dev/kmsg usability. The return code from the initial read() is
@@ -1446,6 +1563,7 @@ int main(int argc, char *argv[])
 		.kmsg = -1,
 		.time_fmt = DMESG_TIMEFTM_TIME,
 		.indent = 0,
+		.caller_id_size = 0,
 	};
 	int colormode = UL_COLORMODE_UNDEF;
 	enum {
@@ -1538,10 +1656,12 @@ int main(int argc, char *argv[])
 		case 'F':
 			ctl.filename = optarg;
 			ctl.method = DMESG_METHOD_MMAP;
+			ctl.caller_id_size = SYSLOG_DEFAULT_CALLER_ID_CHARS;
 			break;
 		case 'K':
 			ctl.filename = optarg;
 			ctl.method = DMESG_METHOD_KMSG;
+			ctl.caller_id_size = max_threads_id_size();
 			break;
 		case 'f':
 			ctl.fltr_fac = 1;
diff --git a/tests/expected/dmesg/colors-kmsg-printk-caller b/tests/expected/dmesg/colors-kmsg-printk-caller
new file mode 100644
index 000000000..c7bf6e8b7
--- /dev/null
+++ b/tests/expected/dmesg/colors-kmsg-printk-caller
@@ -0,0 +1,22 @@
+kern  :notice: ^[[32m[    0.000000] ^[[0m[     T0] Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000
+kern  :info  : ^[[32m[    0.000000] ^[[0m[     T1] ^[[33mCommand line: ^[[0minitrd=\ucode.img initrd=\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system
+kern  :info  : ^[[32m[    0.000000] ^[[0m[     T2] BIOS-provided physical RAM map:
+kern  :info  : ^[[32m[    0.000000] ^[[0m[     T3] ^[[33mBIOS-e820: ^[[0m[mem 0x0000000000000000-0x000000000009efff] usable
+kern  :info  : ^[[32m[    0.000000] ^[[0m[     T4] ^[[33mBIOS-e820: ^[[0m[mem 0x000000000009f000-0x00000000000bffff] reserved
+kern  :info  : ^[[32m[    0.000000] ^[[0m[     T5] ^[[33mBIOS-e820: ^[[0m[mem 0x0000000000100000-0x0000000009afffff] usable
+kern  :info  : ^[[32m[    0.000000] ^[[0m[     T6] ^[[33mBIOS-e820: ^[[0m[mem 0x0000000009b00000-0x0000000009dfffff] reserved
+kern  :info  : ^[[32m[    0.000000] ^[[0m[     T7] ^[[33mBIOS-e820: ^[[0m[mem 0x0000000009e00000-0x0000000009efffff] usable
+kern  :info  : ^[[32m[    0.000000] ^[[0m[     T8] ^[[33mBIOS-e820: ^[[0m[mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS
+kern  :info  : ^[[32m[    0.000000] ^[[0m[     T9] ^[[33mBIOS-e820: ^[[0m[mem 0x0000000009f3c000-0x000000004235ffff] usable
+kern  :info  : ^[[32m[    0.000000] ^[[0m[    T10] ^[[33mBIOS-e820: ^[[0m[mem 0x0000000042360000-0x000000004455ffff] reserved
+kern  :info  : ^[[32m[    0.367657] ^[[0m[    T11] ^[[33mACPI: ^[[0m\_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+kern  :info  : ^[[32m[    0.368615] ^[[0m[    T12] ^[[33mACPI: ^[[0m\_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+kern  :info  : ^[[32m[    0.376316] ^[[0m[    T13] ^[[33mACPI: ^[[0m\_SB_.PRWL: New power resource
+kern  :info  : ^[[32m[    0.376343] ^[[0m[    T14] ^[[33mACPI: ^[[0m\_SB_.PRWB: New power resource
+kern  :info  : ^[[32m[    0.377373] ^[[0m[    T15] ^[[33mACPI: ^[[0mPCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+kern  :info  : ^[[32m[    0.377378] ^[[0m[    T16] ^[[33macpi PNP0A08:00: ^[[0m_OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+kern  :info  : ^[[32m[    0.377569] ^[[0m[    T17] ^[[33macpi PNP0A08:00: ^[[0m_OSC: platform does not support [SHPCHotplug AER]
+kern  :info  : ^[[32m[    0.377933] ^[[0m[    T18] ^[[33macpi PNP0A08:00: ^[[0m_OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+kern  :info  : ^[[32m[    0.378458] ^[[0m[    T19] PCI host bridge to bus 0000:00
+kern  :info  : ^[[32m[    0.378459] ^[[0m[    T20] ^[[33mpci_bus 0000:00: ^[[0mroot bus resource [io  0x0000-0x0cf7 window]
+kern  :info  : ^[[32m[    0.378461] ^[[0m[    T21] ^[[33mpci_bus 0000:00: ^[[0mroot bus resource [io  0x0d00-0xffff window]
diff --git a/tests/expected/dmesg/console-levels-kmsg-printk-caller b/tests/expected/dmesg/console-levels-kmsg-printk-caller
new file mode 100644
index 000000000..1f6e9f178
--- /dev/null
+++ b/tests/expected/dmesg/console-levels-kmsg-printk-caller
@@ -0,0 +1,45 @@
+[    0.000000] [     T0] Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000
+[    0.000000] [     T1] Command line: initrd=\ucode.img initrd=\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system
+[    0.000000] [     T2] BIOS-provided physical RAM map:
+[    0.000000] [     T3] BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable
+[    0.000000] [     T4] BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved
+[    0.000000] [     T5] BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable
+[    0.000000] [     T6] BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved
+[    0.000000] [     T7] BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable
+[    0.000000] [     T8] BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS
+[    0.000000] [     T9] BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable
+[    0.000000] [    T10] BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved
+[    0.367657] [    T11] ACPI: \_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+[    0.368615] [    T12] ACPI: \_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+[    0.376316] [    T13] ACPI: \_SB_.PRWL: New power resource
+[    0.376343] [    T14] ACPI: \_SB_.PRWB: New power resource
+[    0.377373] [    T15] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+[    0.377378] [    T16] acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+[    0.377569] [    T17] acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]
+[    0.377933] [    T18] acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+[    0.378458] [    T19] PCI host bridge to bus 0000:00
+[    0.378459] [    T20] pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]
+[    0.378461] [    T21] pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]
+[    0.000000] [     T0] Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000
+[    0.000000] [     T1] Command line: initrd=\ucode.img initrd=\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system
+[    0.000000] [     T2] BIOS-provided physical RAM map:
+[    0.000000] [     T3] BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable
+[    0.000000] [     T4] BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved
+[    0.000000] [     T5] BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable
+[    0.000000] [     T6] BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved
+[    0.000000] [     T7] BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable
+[    0.000000] [     T8] BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS
+[    0.000000] [     T9] BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable
+[    0.000000] [    T10] BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved
+[    0.367657] [    T11] ACPI: \_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+[    0.368615] [    T12] ACPI: \_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+[    0.376316] [    T13] ACPI: \_SB_.PRWL: New power resource
+[    0.376343] [    T14] ACPI: \_SB_.PRWB: New power resource
+[    0.377373] [    T15] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+[    0.377378] [    T16] acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+[    0.377569] [    T17] acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]
+[    0.377933] [    T18] acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+[    0.378458] [    T19] PCI host bridge to bus 0000:00
+[    0.378459] [    T20] pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]
+[    0.378461] [    T21] pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]
+test_dmesg: unknown level '+'
diff --git a/tests/expected/dmesg/decode-kmsg-printk-caller b/tests/expected/dmesg/decode-kmsg-printk-caller
new file mode 100644
index 000000000..78c363389
--- /dev/null
+++ b/tests/expected/dmesg/decode-kmsg-printk-caller
@@ -0,0 +1,22 @@
+kern  :notice: [    0.000000] [     T0] Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000
+kern  :info  : [    0.000000] [     T1] Command line: initrd=\ucode.img initrd=\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system
+kern  :info  : [    0.000000] [     T2] BIOS-provided physical RAM map:
+kern  :info  : [    0.000000] [     T3] BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable
+kern  :info  : [    0.000000] [     T4] BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved
+kern  :info  : [    0.000000] [     T5] BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable
+kern  :info  : [    0.000000] [     T6] BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved
+kern  :info  : [    0.000000] [     T7] BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable
+kern  :info  : [    0.000000] [     T8] BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS
+kern  :info  : [    0.000000] [     T9] BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable
+kern  :info  : [    0.000000] [    T10] BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved
+kern  :info  : [    0.367657] [    T11] ACPI: \_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+kern  :info  : [    0.368615] [    T12] ACPI: \_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+kern  :info  : [    0.376316] [    T13] ACPI: \_SB_.PRWL: New power resource
+kern  :info  : [    0.376343] [    T14] ACPI: \_SB_.PRWB: New power resource
+kern  :info  : [    0.377373] [    T15] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+kern  :info  : [    0.377378] [    T16] acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+kern  :info  : [    0.377569] [    T17] acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]
+kern  :info  : [    0.377933] [    T18] acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+kern  :info  : [    0.378458] [    T19] PCI host bridge to bus 0000:00
+kern  :info  : [    0.378459] [    T20] pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]
+kern  :info  : [    0.378461] [    T21] pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]
diff --git a/tests/expected/dmesg/delta-kmsg-printk-caller b/tests/expected/dmesg/delta-kmsg-printk-caller
new file mode 100644
index 000000000..892d2dcea
--- /dev/null
+++ b/tests/expected/dmesg/delta-kmsg-printk-caller
@@ -0,0 +1,22 @@
+[    0.000000 <    0.000000>] [     T0] Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000
+[    0.000000 <    0.000000>] [     T1] Command line: initrd=\ucode.img initrd=\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system
+[    0.000000 <    0.000000>] [     T2] BIOS-provided physical RAM map:
+[    0.000000 <    0.000000>] [     T3] BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable
+[    0.000000 <    0.000000>] [     T4] BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved
+[    0.000000 <    0.000000>] [     T5] BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable
+[    0.000000 <    0.000000>] [     T6] BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved
+[    0.000000 <    0.000000>] [     T7] BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable
+[    0.000000 <    0.000000>] [     T8] BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS
+[    0.000000 <    0.000000>] [     T9] BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable
+[    0.000000 <    0.000000>] [    T10] BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved
+[    0.367657 <    0.000000>] [    T11] ACPI: \_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+[    0.368615 <    0.000000>] [    T12] ACPI: \_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+[    0.376316 <    0.000000>] [    T13] ACPI: \_SB_.PRWL: New power resource
+[    0.376343 <    0.000000>] [    T14] ACPI: \_SB_.PRWB: New power resource
+[    0.377373 <    0.000000>] [    T15] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+[    0.377378 <    0.000000>] [    T16] acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+[    0.377569 <    0.000000>] [    T17] acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]
+[    0.377933 <    0.000000>] [    T18] acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+[    0.378458 <    0.000000>] [    T19] PCI host bridge to bus 0000:00
+[    0.378459 <    0.000000>] [    T20] pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]
+[    0.378461 <    0.000000>] [    T21] pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]
diff --git a/tests/expected/dmesg/facilities-kmsg-printk-caller b/tests/expected/dmesg/facilities-kmsg-printk-caller
new file mode 100644
index 000000000..78c363389
--- /dev/null
+++ b/tests/expected/dmesg/facilities-kmsg-printk-caller
@@ -0,0 +1,22 @@
+kern  :notice: [    0.000000] [     T0] Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000
+kern  :info  : [    0.000000] [     T1] Command line: initrd=\ucode.img initrd=\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system
+kern  :info  : [    0.000000] [     T2] BIOS-provided physical RAM map:
+kern  :info  : [    0.000000] [     T3] BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable
+kern  :info  : [    0.000000] [     T4] BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved
+kern  :info  : [    0.000000] [     T5] BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable
+kern  :info  : [    0.000000] [     T6] BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved
+kern  :info  : [    0.000000] [     T7] BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable
+kern  :info  : [    0.000000] [     T8] BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS
+kern  :info  : [    0.000000] [     T9] BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable
+kern  :info  : [    0.000000] [    T10] BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved
+kern  :info  : [    0.367657] [    T11] ACPI: \_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+kern  :info  : [    0.368615] [    T12] ACPI: \_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+kern  :info  : [    0.376316] [    T13] ACPI: \_SB_.PRWL: New power resource
+kern  :info  : [    0.376343] [    T14] ACPI: \_SB_.PRWB: New power resource
+kern  :info  : [    0.377373] [    T15] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+kern  :info  : [    0.377378] [    T16] acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+kern  :info  : [    0.377569] [    T17] acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]
+kern  :info  : [    0.377933] [    T18] acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+kern  :info  : [    0.378458] [    T19] PCI host bridge to bus 0000:00
+kern  :info  : [    0.378459] [    T20] pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]
+kern  :info  : [    0.378461] [    T21] pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]
diff --git a/tests/expected/dmesg/indentation-kmsg-printk-caller b/tests/expected/dmesg/indentation-kmsg-printk-caller
new file mode 100644
index 000000000..47ad73f27
--- /dev/null
+++ b/tests/expected/dmesg/indentation-kmsg-printk-caller
@@ -0,0 +1,28 @@
+[    0.000000] [     T0] line zero
+[    1.000000] [     T1] new
+[    2.000000] [     T2] two
+[    3.000000] [     T3] three
+kern  :notice: [    0.000000] [     T0] line zero
+user  :crit  : [    1.000000] [     T1] new
+mail  :warn  : [    2.000000] [     T2] two
+daemon:info  : [    3.000000] [     T3] three
+[<    0.000000>] [     T0] line zero
+[<    0.000000>] [     T1] new
+[<    1.000000>] [     T2] two
+[<    1.000000>] [     T3] three
+[     T0] line zero
+[     T1] new
+[     T2] two
+[     T3] three
+[Feb13 23:31] [     T0] line zero
+[  +0.000000] [     T1] new
+[  +1.000000] [     T2] two
+[  +1.000000] [     T3] three
+[Fri Feb 13 23:31:30 2009] [     T0] line zero
+[Fri Feb 13 23:31:31 2009] [     T1] new
+[Fri Feb 13 23:31:32 2009] [     T2] two
+[Fri Feb 13 23:31:33 2009] [     T3] three
+2009-02-13T23:31:30,123456+00:00 [     T0] line zero
+2009-02-13T23:31:31,123456+00:00 [     T1] new
+2009-02-13T23:31:32,123456+00:00 [     T2] two
+2009-02-13T23:31:33,123456+00:00 [     T3] three
diff --git a/tests/expected/dmesg/json-kmsg-printk-caller b/tests/expected/dmesg/json-kmsg-printk-caller
new file mode 100644
index 000000000..785d730a5
--- /dev/null
+++ b/tests/expected/dmesg/json-kmsg-printk-caller
@@ -0,0 +1,115 @@
+{
+   "dmesg": [
+      {
+         "pri": 5,
+         "time":     0.000000,
+         "caller": "T0",
+         "msg": "Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T1",
+         "msg": "Command line: initrd=\\ucode.img initrd=\\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T2",
+         "msg": "BIOS-provided physical RAM map:"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T3",
+         "msg": "BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T4",
+         "msg": "BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T5",
+         "msg": "BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T6",
+         "msg": "BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T7",
+         "msg": "BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T8",
+         "msg": "BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T9",
+         "msg": "BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T10",
+         "msg": "BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved"
+      },{
+         "pri": 6,
+         "time":     0.367657,
+         "caller": "T11",
+         "msg": "ACPI: \\_SB_.PCI0.GP19.NHI1.PWRS: New power resource"
+      },{
+         "pri": 6,
+         "time":     0.368615,
+         "caller": "T12",
+         "msg": "ACPI: \\_SB_.PCI0.GP19.XHC4.PWRS: New power resource"
+      },{
+         "pri": 6,
+         "time":     0.376316,
+         "caller": "T13",
+         "msg": "ACPI: \\_SB_.PRWL: New power resource"
+      },{
+         "pri": 6,
+         "time":     0.376343,
+         "caller": "T14",
+         "msg": "ACPI: \\_SB_.PRWB: New power resource"
+      },{
+         "pri": 6,
+         "time":     0.377373,
+         "caller": "T15",
+         "msg": "ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])"
+      },{
+         "pri": 6,
+         "time":     0.377378,
+         "caller": "T16",
+         "msg": "acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]"
+      },{
+         "pri": 6,
+         "time":     0.377569,
+         "caller": "T17",
+         "msg": "acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]"
+      },{
+         "pri": 6,
+         "time":     0.377933,
+         "caller": "T18",
+         "msg": "acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]"
+      },{
+         "pri": 6,
+         "time":     0.378458,
+         "caller": "T19",
+         "msg": "PCI host bridge to bus 0000:00"
+      },{
+         "pri": 6,
+         "time":     0.378459,
+         "caller": "T20",
+         "msg": "pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]"
+      },{
+         "pri": 6,
+         "time":     0.378461,
+         "caller": "T21",
+         "msg": "pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]"
+      }
+   ]
+}
diff --git a/tests/expected/dmesg/json-syslog-printk-caller b/tests/expected/dmesg/json-syslog-printk-caller
new file mode 100644
index 000000000..40c98aa67
--- /dev/null
+++ b/tests/expected/dmesg/json-syslog-printk-caller
@@ -0,0 +1,530 @@
+{
+   "dmesg": [
+      {
+         "pri": 0,
+         "time":     0.000000,
+         "caller": "T0",
+         "msg": " example[0]"
+      },{
+         "pri": 1,
+         "time":     1.000000,
+         "caller": "T1",
+         "msg": " example[1]"
+      },{
+         "pri": 2,
+         "time":     8.000000,
+         "caller": "T2",
+         "msg": " example[2]"
+      },{
+         "pri": 3,
+         "time":    27.000000,
+         "caller": "T3",
+         "msg": " example[3]"
+      },{
+         "pri": 4,
+         "time":    64.000000,
+         "caller": "T4",
+         "msg": " example[4]"
+      },{
+         "pri": 5,
+         "time":   125.000000,
+         "caller": "T5",
+         "msg": " example[5]"
+      },{
+         "pri": 6,
+         "time":   216.000000,
+         "caller": "T6",
+         "msg": " example[6]"
+      },{
+         "pri": 7,
+         "time":   343.000000,
+         "caller": "T7",
+         "msg": " example[7]"
+      },{
+         "pri": 8,
+         "time":   512.000000,
+         "caller": "T8",
+         "msg": " example[8]"
+      },{
+         "pri": 9,
+         "time":   729.000000,
+         "caller": "T9",
+         "msg": " example[9]"
+      },{
+         "pri": 10,
+         "time":  1000.000000,
+         "caller": "T10",
+         "msg": " example[10]"
+      },{
+         "pri": 11,
+         "time":  1331.000000,
+         "caller": "T11",
+         "msg": " example[11]"
+      },{
+         "pri": 12,
+         "time":  1728.000000,
+         "caller": "T12",
+         "msg": " example[12]"
+      },{
+         "pri": 13,
+         "time":  2197.000000,
+         "caller": "T13",
+         "msg": " example[13]"
+      },{
+         "pri": 14,
+         "time":  2744.000000,
+         "caller": "T14",
+         "msg": " example[14]"
+      },{
+         "pri": 15,
+         "time":  3375.000000,
+         "caller": "T15",
+         "msg": " example[15]"
+      },{
+         "pri": 16,
+         "time":  4096.000000,
+         "caller": "T16",
+         "msg": " example[16]"
+      },{
+         "pri": 17,
+         "time":  4913.000000,
+         "caller": "T17",
+         "msg": " example[17]"
+      },{
+         "pri": 18,
+         "time":  5832.000000,
+         "caller": "T18",
+         "msg": " example[18]"
+      },{
+         "pri": 19,
+         "time":  6859.000000,
+         "caller": "T19",
+         "msg": " example[19]"
+      },{
+         "pri": 20,
+         "time":  8000.000000,
+         "caller": "T20",
+         "msg": " example[20]"
+      },{
+         "pri": 21,
+         "time":  9261.000000,
+         "caller": "T21",
+         "msg": " example[21]"
+      },{
+         "pri": 22,
+         "time": 10648.000000,
+         "caller": "T22",
+         "msg": " example[22]"
+      },{
+         "pri": 23,
+         "time": 12167.000000,
+         "caller": "T23",
+         "msg": " example[23]"
+      },{
+         "pri": 24,
+         "time": 13824.000000,
+         "caller": "T24",
+         "msg": " example[24]"
+      },{
+         "pri": 25,
+         "time": 15625.000000,
+         "caller": "T25",
+         "msg": " example[25]"
+      },{
+         "pri": 26,
+         "time": 17576.000000,
+         "caller": "T26",
+         "msg": " example[26]"
+      },{
+         "pri": 27,
+         "time": 19683.000000,
+         "caller": "T27",
+         "msg": " example[27]"
+      },{
+         "pri": 28,
+         "time": 21952.000000,
+         "caller": "T28",
+         "msg": " example[28]"
+      },{
+         "pri": 29,
+         "time": 24389.000000,
+         "caller": "T29",
+         "msg": " example[29]"
+      },{
+         "pri": 30,
+         "time": 27000.000000,
+         "caller": "T10",
+         "msg": " example[30]"
+      },{
+         "pri": 31,
+         "time": 29791.000000,
+         "caller": "T31",
+         "msg": " example[31]"
+      },{
+         "pri": 32,
+         "time": 32768.000000,
+         "caller": "T32",
+         "msg": " example[32]"
+      },{
+         "pri": 33,
+         "time": 35937.000000,
+         "caller": "T33",
+         "msg": " example[33]"
+      },{
+         "pri": 34,
+         "time": 39304.000000,
+         "caller": "T34",
+         "msg": " example[34]"
+      },{
+         "pri": 35,
+         "time": 42875.000000,
+         "caller": "T35",
+         "msg": " example[35]"
+      },{
+         "pri": 36,
+         "time": 46656.000000,
+         "caller": "T36",
+         "msg": " example[36]"
+      },{
+         "pri": 37,
+         "time": 50653.000000,
+         "caller": "T37",
+         "msg": " example[37]"
+      },{
+         "pri": 38,
+         "time": 54872.000000,
+         "caller": "T38",
+         "msg": " example[38]"
+      },{
+         "pri": 39,
+         "time": 59319.000000,
+         "caller": "T39",
+         "msg": " example[39]"
+      },{
+         "pri": 40,
+         "time": 64000.000000,
+         "caller": "T40",
+         "msg": " example[40]"
+      },{
+         "pri": 41,
+         "time": 68921.000000,
+         "caller": "T41",
+         "msg": " example[41]"
+      },{
+         "pri": 42,
+         "time": 74088.000000,
+         "caller": "T42",
+         "msg": " example[42]"
+      },{
+         "pri": 43,
+         "time": 79507.000000,
+         "caller": "T43",
+         "msg": " example[43]"
+      },{
+         "pri": 44,
+         "time": 85184.000000,
+         "caller": "T44",
+         "msg": " example[44]"
+      },{
+         "pri": 45,
+         "time": 91125.000000,
+         "caller": "T45",
+         "msg": " example[45]"
+      },{
+         "pri": 46,
+         "time": 97336.000000,
+         "caller": "T46",
+         "msg": " example[46]"
+      },{
+         "pri": 47,
+         "time": 103823.000000,
+         "caller": "T47",
+         "msg": " example[47]"
+      },{
+         "pri": 48,
+         "time": 110592.000000,
+         "caller": "T48",
+         "msg": " example[48]"
+      },{
+         "pri": 49,
+         "time": 117649.000000,
+         "caller": "T49",
+         "msg": " example[49]"
+      },{
+         "pri": 50,
+         "time": 125000.000000,
+         "caller": "T50",
+         "msg": " example[50]"
+      },{
+         "pri": 51,
+         "time": 132651.000000,
+         "caller": "T51",
+         "msg": " example[51]"
+      },{
+         "pri": 52,
+         "time": 140608.000000,
+         "caller": "T52",
+         "msg": " example[52]"
+      },{
+         "pri": 53,
+         "time": 148877.000000,
+         "caller": "T53",
+         "msg": " example[53]"
+      },{
+         "pri": 54,
+         "time": 157464.000000,
+         "caller": "T54",
+         "msg": " example[54]"
+      },{
+         "pri": 55,
+         "time": 166375.000000,
+         "caller": "T55",
+         "msg": " example[55]"
+      },{
+         "pri": 56,
+         "time": 175616.000000,
+         "caller": "T56",
+         "msg": " example[56]"
+      },{
+         "pri": 57,
+         "time": 185193.000000,
+         "caller": "T57",
+         "msg": " example[57]"
+      },{
+         "pri": 58,
+         "time": 195112.000000,
+         "caller": "T58",
+         "msg": " example[58]"
+      },{
+         "pri": 59,
+         "time": 205379.000000,
+         "caller": "T59",
+         "msg": " example[59]"
+      },{
+         "pri": 60,
+         "time": 216000.000000,
+         "caller": "T60",
+         "msg": " example[60]"
+      },{
+         "pri": 61,
+         "time": 226981.000000,
+         "caller": "T61",
+         "msg": " example[61]"
+      },{
+         "pri": 62,
+         "time": 238328.000000,
+         "caller": "T62",
+         "msg": " example[62]"
+      },{
+         "pri": 63,
+         "time": 250047.000000,
+         "caller": "T63",
+         "msg": " example[63]"
+      },{
+         "pri": 64,
+         "time": 262144.000000,
+         "caller": "T64",
+         "msg": " example[64]"
+      },{
+         "pri": 65,
+         "time": 274625.000000,
+         "caller": "T65",
+         "msg": " example[65]"
+      },{
+         "pri": 66,
+         "time": 287496.000000,
+         "caller": "T66",
+         "msg": " example[66]"
+      },{
+         "pri": 67,
+         "time": 300763.000000,
+         "caller": "T67",
+         "msg": " example[67]"
+      },{
+         "pri": 68,
+         "time": 314432.000000,
+         "caller": "T68",
+         "msg": " example[68]"
+      },{
+         "pri": 69,
+         "time": 328509.000000,
+         "caller": "T69",
+         "msg": " example[69]"
+      },{
+         "pri": 70,
+         "time": 343000.000000,
+         "caller": "T70",
+         "msg": " example[70]"
+      },{
+         "pri": 71,
+         "time": 357911.000000,
+         "caller": "T71",
+         "msg": " example[71]"
+      },{
+         "pri": 72,
+         "time": 373248.000000,
+         "caller": "T72",
+         "msg": " example[72]"
+      },{
+         "pri": 73,
+         "time": 389017.000000,
+         "caller": "T73",
+         "msg": " example[73]"
+      },{
+         "pri": 74,
+         "time": 405224.000000,
+         "caller": "T74",
+         "msg": " example[74]"
+      },{
+         "pri": 75,
+         "time": 421875.000000,
+         "caller": "T75",
+         "msg": " example[75]"
+      },{
+         "pri": 76,
+         "time": 438976.000000,
+         "caller": "T76",
+         "msg": " example[76]"
+      },{
+         "pri": 77,
+         "time": 456533.000000,
+         "caller": "T77",
+         "msg": " example[77]"
+      },{
+         "pri": 78,
+         "time": 474552.000000,
+         "caller": "T78",
+         "msg": " example[78]"
+      },{
+         "pri": 79,
+         "time": 493039.000000,
+         "caller": "T79",
+         "msg": " example[79]"
+      },{
+         "pri": 80,
+         "time": 512000.000000,
+         "caller": "T80",
+         "msg": " example[80]"
+      },{
+         "pri": 81,
+         "time": 531441.000000,
+         "caller": "T81",
+         "msg": " example[81]"
+      },{
+         "pri": 82,
+         "time": 551368.000000,
+         "caller": "T82",
+         "msg": " example[82]"
+      },{
+         "pri": 83,
+         "time": 571787.000000,
+         "caller": "T83",
+         "msg": " example[83]"
+      },{
+         "pri": 84,
+         "time": 592704.000000,
+         "caller": "T84",
+         "msg": " example[84]"
+      },{
+         "pri": 85,
+         "time": 614125.000000,
+         "caller": "T85",
+         "msg": " example[85]"
+      },{
+         "pri": 86,
+         "time": 636056.000000,
+         "caller": "T86",
+         "msg": " example[86]"
+      },{
+         "pri": 87,
+         "time": 658503.000000,
+         "caller": "T87",
+         "msg": " example[87]"
+      },{
+         "pri": 88,
+         "time": 681472.000000,
+         "caller": "T88",
+         "msg": " example[88]"
+      },{
+         "pri": 89,
+         "time": 704969.000000,
+         "caller": "T89",
+         "msg": " example[89]"
+      },{
+         "pri": 90,
+         "time": 729000.000000,
+         "caller": "T90",
+         "msg": " example[90]"
+      },{
+         "pri": 91,
+         "time": 753571.000000,
+         "caller": "T91",
+         "msg": " example[91]"
+      },{
+         "pri": 92,
+         "time": 778688.000000,
+         "caller": "T92",
+         "msg": " example[92]"
+      },{
+         "pri": 93,
+         "time": 804357.000000,
+         "caller": "T93",
+         "msg": " example[93]"
+      },{
+         "pri": 94,
+         "time": 830584.000000,
+         "caller": "T94",
+         "msg": " example[94]"
+      },{
+         "pri": 95,
+         "time": 857375.000000,
+         "caller": "T95",
+         "msg": " example[95]"
+      },{
+         "pri": 96,
+         "time": 884736.000000,
+         "caller": "T96",
+         "msg": " example[96]"
+      },{
+         "pri": 97,
+         "time": 912673.000000,
+         "caller": "T97",
+         "msg": " example[97]"
+      },{
+         "pri": 98,
+         "time": 941192.000000,
+         "caller": "T98",
+         "msg": " example[98]"
+      },{
+         "pri": 99,
+         "time": 970299.000000,
+         "caller": "T99",
+         "msg": " example[99]"
+      },{
+         "pri": 100,
+         "time": 1000000.000000,
+         "caller": "T100",
+         "msg": " example[100]"
+      },{
+         "pri": 101,
+         "time": 1030301.000000,
+         "caller": "T101",
+         "msg": " example[101]"
+      },{
+         "pri": 102,
+         "time": 1061208.000000,
+         "caller": "T102",
+         "msg": " example[102]"
+      },{
+         "pri": 103,
+         "time": 1092727.000000,
+         "caller": "T103",
+         "msg": " example[103]"
+      },{
+         "pri": 104,
+         "time": 1124864.000000,
+         "caller": "T104",
+         "msg": " example[104]"
+      }
+   ]
+}
diff --git a/tests/expected/dmesg/kmsg-file-printk-caller b/tests/expected/dmesg/kmsg-file-printk-caller
new file mode 100644
index 000000000..785d730a5
--- /dev/null
+++ b/tests/expected/dmesg/kmsg-file-printk-caller
@@ -0,0 +1,115 @@
+{
+   "dmesg": [
+      {
+         "pri": 5,
+         "time":     0.000000,
+         "caller": "T0",
+         "msg": "Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T1",
+         "msg": "Command line: initrd=\\ucode.img initrd=\\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T2",
+         "msg": "BIOS-provided physical RAM map:"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T3",
+         "msg": "BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T4",
+         "msg": "BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T5",
+         "msg": "BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T6",
+         "msg": "BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T7",
+         "msg": "BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T8",
+         "msg": "BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T9",
+         "msg": "BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T10",
+         "msg": "BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved"
+      },{
+         "pri": 6,
+         "time":     0.367657,
+         "caller": "T11",
+         "msg": "ACPI: \\_SB_.PCI0.GP19.NHI1.PWRS: New power resource"
+      },{
+         "pri": 6,
+         "time":     0.368615,
+         "caller": "T12",
+         "msg": "ACPI: \\_SB_.PCI0.GP19.XHC4.PWRS: New power resource"
+      },{
+         "pri": 6,
+         "time":     0.376316,
+         "caller": "T13",
+         "msg": "ACPI: \\_SB_.PRWL: New power resource"
+      },{
+         "pri": 6,
+         "time":     0.376343,
+         "caller": "T14",
+         "msg": "ACPI: \\_SB_.PRWB: New power resource"
+      },{
+         "pri": 6,
+         "time":     0.377373,
+         "caller": "T15",
+         "msg": "ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])"
+      },{
+         "pri": 6,
+         "time":     0.377378,
+         "caller": "T16",
+         "msg": "acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]"
+      },{
+         "pri": 6,
+         "time":     0.377569,
+         "caller": "T17",
+         "msg": "acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]"
+      },{
+         "pri": 6,
+         "time":     0.377933,
+         "caller": "T18",
+         "msg": "acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]"
+      },{
+         "pri": 6,
+         "time":     0.378458,
+         "caller": "T19",
+         "msg": "PCI host bridge to bus 0000:00"
+      },{
+         "pri": 6,
+         "time":     0.378459,
+         "caller": "T20",
+         "msg": "pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]"
+      },{
+         "pri": 6,
+         "time":     0.378461,
+         "caller": "T21",
+         "msg": "pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]"
+      }
+   ]
+}
diff --git a/tests/expected/dmesg/limit-kmsg-printk-caller b/tests/expected/dmesg/limit-kmsg-printk-caller
new file mode 100644
index 000000000..2ea07d4c8
--- /dev/null
+++ b/tests/expected/dmesg/limit-kmsg-printk-caller
@@ -0,0 +1,11 @@
+[    0.367657] [    T11] ACPI: \_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+[    0.368615] [    T12] ACPI: \_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+[    0.376316] [    T13] ACPI: \_SB_.PRWL: New power resource
+[    0.376343] [    T14] ACPI: \_SB_.PRWB: New power resource
+[    0.377373] [    T15] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+[    0.377378] [    T16] acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+[    0.377569] [    T17] acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]
+[    0.377933] [    T18] acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+[    0.378458] [    T19] PCI host bridge to bus 0000:00
+[    0.378459] [    T20] pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]
+[    0.378461] [    T21] pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]
diff --git a/tests/ts/dmesg/colors-kmsg-printk-caller b/tests/ts/dmesg/colors-kmsg-printk-caller
new file mode 100755
index 000000000..513ca82d4
--- /dev/null
+++ b/tests/ts/dmesg/colors-kmsg-printk-caller
@@ -0,0 +1,29 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="colors-kmsg-prtk-caller"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+ts_inhibit_custom_colorscheme
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG --color=always -K $TS_SELF/kmsg-input-printk-caller -x >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/console-levels-kmsg-printk-caller b/tests/ts/dmesg/console-levels-kmsg-printk-caller
new file mode 100755
index 000000000..00b8b3681
--- /dev/null
+++ b/tests/ts/dmesg/console-levels-kmsg-printk-caller
@@ -0,0 +1,36 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="levels-kmsg-prtk-caller"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+for I in {-1..8}; do
+	$TS_HELPER_DMESG -K $TS_SELF/kmsg-input-printk-caller -l $I >> $TS_OUTPUT 2>/dev/null
+done
+
+$TS_HELPER_DMESG -K $TS_SELF/kmsg-input-printk-caller -l err+ >> $TS_OUTPUT 2>/dev/null
+$TS_HELPER_DMESG -K $TS_SELF/kmsg-input-printk-caller -l emerg+ >> $TS_OUTPUT 2>/dev/null
+$TS_HELPER_DMESG -K $TS_SELF/kmsg-input-printk-caller -l +err >> $TS_OUTPUT 2>/dev/null
+$TS_HELPER_DMESG -K $TS_SELF/kmsg-input-printk-caller -l +debug >> $TS_OUTPUT 2>/dev/null
+$TS_HELPER_DMESG -K $TS_SELF/kmsg-input-printk-caller -l + 2>> $TS_OUTPUT >/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/decode-kmsg-printk-caller b/tests/ts/dmesg/decode-kmsg-printk-caller
new file mode 100755
index 000000000..d05b9fb68
--- /dev/null
+++ b/tests/ts/dmesg/decode-kmsg-printk-caller
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="decode-kmsg-prtk-caller"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG -x -K $TS_SELF/kmsg-input-printk-caller >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/delta-kmsg-printk-caller b/tests/ts/dmesg/delta-kmsg-printk-caller
new file mode 100755
index 000000000..020b82357
--- /dev/null
+++ b/tests/ts/dmesg/delta-kmsg-printk-caller
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="delta-kmsg-prtk-caller"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG -d -K $TS_SELF/kmsg-input-printk-caller >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/facilities-kmsg-printk-caller b/tests/ts/dmesg/facilities-kmsg-printk-caller
new file mode 100755
index 000000000..bec301516
--- /dev/null
+++ b/tests/ts/dmesg/facilities-kmsg-printk-caller
@@ -0,0 +1,30 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="facilities-kmsg-prtk-caller"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+for I in {-1..12}; do
+	$TS_HELPER_DMESG -K $TS_SELF/kmsg-input-printk-caller -f $I -x >> $TS_OUTPUT 2>/dev/null
+done
+
+ts_finalize
diff --git a/tests/ts/dmesg/indentation-kmsg-printk-caller b/tests/ts/dmesg/indentation-kmsg-printk-caller
new file mode 100755
index 000000000..53e549b62
--- /dev/null
+++ b/tests/ts/dmesg/indentation-kmsg-printk-caller
@@ -0,0 +1,40 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="indentation-kmsg-prtk-caller"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG -K $TS_SELF/newlines-kmsg-printk-caller >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG -K $TS_SELF/newlines-kmsg-printk-caller -x >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=delta --kmsg-file $TS_SELF/newlines-kmsg-printk-caller >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=notime --kmsg-file $TS_SELF/newlines-kmsg-printk-caller >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=reltime --kmsg-file $TS_SELF/newlines-kmsg-printk-caller >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=ctime --kmsg-file $TS_SELF/newlines-kmsg-printk-caller >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=iso --kmsg-file $TS_SELF/newlines-kmsg-printk-caller >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+ts_finalize
diff --git a/tests/ts/dmesg/input-syslog-printk-caller b/tests/ts/dmesg/input-syslog-printk-caller
new file mode 100644
index 000000000..5fcff6abe
--- /dev/null
+++ b/tests/ts/dmesg/input-syslog-printk-caller
@@ -0,0 +1,105 @@
+<0>[    0.000000] [    T0] example[0]
+<1>[    1.000000] [    T1] example[1]
+<2>[    8.000000] [    T2] example[2]
+<3>[   27.000000] [    T3] example[3]
+<4>[   64.000000] [    T4] example[4]
+<5>[  125.000000] [    T5] example[5]
+<6>[  216.000000] [    T6] example[6]
+<7>[  343.000000] [    T7] example[7]
+<8>[  512.000000] [    T8] example[8]
+<9>[  729.000000] [    T9] example[9]
+<10>[ 1000.000000] [   T10] example[10]
+<11>[ 1331.000000] [   T11] example[11]
+<12>[ 1728.000000] [   T12] example[12]
+<13>[ 2197.000000] [   T13] example[13]
+<14>[ 2744.000000] [   T14] example[14]
+<15>[ 3375.000000] [   T15] example[15]
+<16>[ 4096.000000] [   T16] example[16]
+<17>[ 4913.000000] [   T17] example[17]
+<18>[ 5832.000000] [   T18] example[18]
+<19>[ 6859.000000] [   T19] example[19]
+<20>[ 8000.000000] [   T20] example[20]
+<21>[ 9261.000000] [   T21] example[21]
+<22>[10648.000000] [   T22] example[22]
+<23>[12167.000000] [   T23] example[23]
+<24>[13824.000000] [   T24] example[24]
+<25>[15625.000000] [   T25] example[25]
+<26>[17576.000000] [   T26] example[26]
+<27>[19683.000000] [   T27] example[27]
+<28>[21952.000000] [   T28] example[28]
+<29>[24389.000000] [   T29] example[29]
+<30>[27000.000000] [   T10] example[30]
+<31>[29791.000000] [   T31] example[31]
+<32>[32768.000000] [   T32] example[32]
+<33>[35937.000000] [   T33] example[33]
+<34>[39304.000000] [   T34] example[34]
+<35>[42875.000000] [   T35] example[35]
+<36>[46656.000000] [   T36] example[36]
+<37>[50653.000000] [   T37] example[37]
+<38>[54872.000000] [   T38] example[38]
+<39>[59319.000000] [   T39] example[39]
+<40>[64000.000000] [   T40] example[40]
+<41>[68921.000000] [   T41] example[41]
+<42>[74088.000000] [   T42] example[42]
+<43>[79507.000000] [   T43] example[43]
+<44>[85184.000000] [   T44] example[44]
+<45>[91125.000000] [   T45] example[45]
+<46>[97336.000000] [   T46] example[46]
+<47>[103823.000000] [   T47] example[47]
+<48>[110592.000000] [   T48] example[48]
+<49>[117649.000000] [   T49] example[49]
+<50>[125000.000000] [   T50] example[50]
+<51>[132651.000000] [   T51] example[51]
+<52>[140608.000000] [   T52] example[52]
+<53>[148877.000000] [   T53] example[53]
+<54>[157464.000000] [   T54] example[54]
+<55>[166375.000000] [   T55] example[55]
+<56>[175616.000000] [   T56] example[56]
+<57>[185193.000000] [   T57] example[57]
+<58>[195112.000000] [   T58] example[58]
+<59>[205379.000000] [   T59] example[59]
+<60>[216000.000000] [   T60] example[60]
+<61>[226981.000000] [   T61] example[61]
+<62>[238328.000000] [   T62] example[62]
+<63>[250047.000000] [   T63] example[63]
+<64>[262144.000000] [   T64] example[64]
+<65>[274625.000000] [   T65] example[65]
+<66>[287496.000000] [   T66] example[66]
+<67>[300763.000000] [   T67] example[67]
+<68>[314432.000000] [   T68] example[68]
+<69>[328509.000000] [   T69] example[69]
+<70>[343000.000000] [   T70] example[70]
+<71>[357911.000000] [   T71] example[71]
+<72>[373248.000000] [   T72] example[72]
+<73>[389017.000000] [   T73] example[73]
+<74>[405224.000000] [   T74] example[74]
+<75>[421875.000000] [   T75] example[75]
+<76>[438976.000000] [   T76] example[76]
+<77>[456533.000000] [   T77] example[77]
+<78>[474552.000000] [   T78] example[78]
+<79>[493039.000000] [   T79] example[79]
+<80>[512000.000000] [   T80] example[80]
+<81>[531441.000000] [   T81] example[81]
+<82>[551368.000000] [   T82] example[82]
+<83>[571787.000000] [   T83] example[83]
+<84>[592704.000000] [   T84] example[84]
+<85>[614125.000000] [   T85] example[85]
+<86>[636056.000000] [   T86] example[86]
+<87>[658503.000000] [   T87] example[87]
+<88>[681472.000000] [   T88] example[88]
+<89>[704969.000000] [   T89] example[89]
+<90>[729000.000000] [   T90] example[90]
+<91>[753571.000000] [   T91] example[91]
+<92>[778688.000000] [   T92] example[92]
+<93>[804357.000000] [   T93] example[93]
+<94>[830584.000000] [   T94] example[94]
+<95>[857375.000000] [   T95] example[95]
+<96>[884736.000000] [   T96] example[96]
+<97>[912673.000000] [   T97] example[97]
+<98>[941192.000000] [   T98] example[98]
+<99>[970299.000000] [   T99] example[99]
+<100>[1000000.000000] [  T100] example[100]
+<101>[1030301.000000] [  T101] example[101]
+<102>[1061208.000000] [  T102] example[102]
+<103>[1092727.000000] [  T103] example[103]
+<104>[1124864.000000] [  T104] example[104]
diff --git a/tests/ts/dmesg/json-kmsg-printk-caller b/tests/ts/dmesg/json-kmsg-printk-caller
new file mode 100755
index 000000000..cb6c5e4a8
--- /dev/null
+++ b/tests/ts/dmesg/json-kmsg-printk-caller
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="json-kmsg-prtk-caller"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG -J -K $TS_SELF/kmsg-input-printk-caller >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/json-syslog-printk-caller b/tests/ts/dmesg/json-syslog-printk-caller
new file mode 100755
index 000000000..10dfaa423
--- /dev/null
+++ b/tests/ts/dmesg/json-syslog-printk-caller
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="json-syslog-prtk-caller"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG -J -F $TS_SELF/input-syslog-printk-caller >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/kmsg-file-printk-caller b/tests/ts/dmesg/kmsg-file-printk-caller
new file mode 100755
index 000000000..a01fc723f
--- /dev/null
+++ b/tests/ts/dmesg/kmsg-file-printk-caller
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="kmsg-file-prtk-caller"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG -J -K $TS_SELF/kmsg-input-printk-caller >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/kmsg-input-printk-caller b/tests/ts/dmesg/kmsg-input-printk-caller
new file mode 100644
index 0000000000000000000000000000000000000000..8d67f11cad7988469dd5e4a7c8589d2b744168bb
GIT binary patch
literal 2187
zcmbW2TW{hx6oB`+zv4*yQZ$g-aqb9dAw>nL(1<WMu@wr5q0uIBlmsaMe(Z!%<LSbv
zlRV_&oX=m5?PI-*_}S}*L6Xp7utfdGINQI%ffi-VGB6ZF(Rx7<zTh5)+e9?}BOdF!
z4&3g-5N;n_w*#0cs)9j9DnS;)U3i#(h9u&x{5s-+Rh*O^P!$a;r~`jv@Mj))i}85o
zE!X$o=fm05g&E7bfHb(LVT}TW9MyKP4WAG{ZvHa5STe?am!)ZtMZlG)1928tMKt*L
zRS)+ei>MN(yY|bvJxI4@ul|L)xi~^toboE7hd88zJAS>(4k<+$&WTf=%8I5=6qjL8
zL{KnRHJ_wGp3~y4X%}XyWTy5<(<i@|7wiy6G=lu)RK`5fuo%vO$2uZ}NFk&Np_Ymq
zSfw-t^eTS4ee|SPHr;Nw&#*6pO+p1wlYrWFpuOc}8Mxs*4lHO%ivx`WQkRhWRV1!e
z+ekYQM9I;RfW|eTy?GCe&cL>#DIv|PNctWrvM4)R641H|6j_w>Xm5!~<TDIiZwm7-
zzR063A?@o(63R$TCHk+9SYEssT|x4A;}=U!)6d9uCN)C3#4rurY}Eyf`{GX=5bJ8~
zkJgIkPLcB9VOyC`rdaX5E_?^(^awdS(n8E1wlBhFN)n9|Ed%RqqI#M5ZQ^RbA?jUX
z8U!0{B6&w#e0{tu#TOq(XrztM{s%F-j4(OEB&LMW&j_9%Snyf_qau!W6jmZ*&u|;D
zG>9`^*ARl$W?%BV9-k?ldhrsgAzE!IqaTEM4Bp&BLu5I;BEtH~cO7{0q1@*=E2<J!
z<JXF2yw12R+r~Q>`rZuOgoXd{t50_+&G=U{e+uLK1x&nez2zyV<oO2t&m;f4zZ}m7
zqMIAIAAgy;<H0BK<h*s-_}RiwH|(~bdC4zNf@;f(6e31T$apT!y0G#mo;zVxp6t2m
zc=16E4G9gK&(ycA3tN{oc$zZCOFYY}f+ajvd?e`4&b`?f#IqaZ!6r`P>I9F=1>Ae?
zN1ZTtvNT;9I=e5X!3!%Z*fi6iV$cjaAI4@s(=@e-Y$sJk{XC4<txuhL=c$8#E-qNb
x49;7GD7oR*gkzjV>?paPL2n~_e!=^1N$^$A^$pxgsfs@$5!EG7)Tlp__yL<dZm0kN

literal 0
HcmV?d00001

diff --git a/tests/ts/dmesg/limit-kmsg-printk-caller b/tests/ts/dmesg/limit-kmsg-printk-caller
new file mode 100755
index 000000000..4d4d9912d
--- /dev/null
+++ b/tests/ts/dmesg/limit-kmsg-printk-caller
@@ -0,0 +1,29 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="limit-kmsg-prtk-caller"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG --since @1234567890.124 --until @1234567991 -K $TS_SELF/kmsg-input-printk-caller \
+	>> $TS_OUTPUT 2> $TS_ERRLOG
+
+ts_finalize
diff --git a/tests/ts/dmesg/newlines-kmsg-printk-caller b/tests/ts/dmesg/newlines-kmsg-printk-caller
new file mode 100644
index 0000000000000000000000000000000000000000..574d2177796677b73f1efcf273005169ed832c60
GIT binary patch
literal 152
zcmXrjF#tkco#e!voYW%Q5CiL+%)C^Es??%<E(Svb9YY;M128~RV`!b1TFwPh$Hia-
tQeuRm#K^j&Jf91MLCT7`7>o^cjC71K)EQfsWE7>QazV)4{GwE-1^{d2D<=Q|

literal 0
HcmV?d00001

-- 
2.43.0


^ permalink raw reply related

* [PATCH] uuidd: add cont_clock persistence
From: Michael Trapp @ 2023-12-15 22:18 UTC (permalink / raw)
  To: util-linux; +Cc: kzak

cont_clock requires a correct time setup and therefore it
must be possible to detect a step back between uuidd starts.

Reserving the next 10 seconds in clock-cont.txt is sufficient
and should not have a noticeable performance impact.
It will also provide the possibility to start with the clock_reg
from the previous session when the system was rebooted.

Whith that, the early cont_clock initialization in uuidd
should be removed because writing the cont_clock persitence
when -C was not set is useless and might be confusing.
---
 libuuid/src/gen_uuid.c | 78 ++++++++++++++++++++++++++++++++++++------
 libuuid/src/uuidP.h    |  1 +
 misc-utils/uuidd.c     |  9 -----
 3 files changed, 69 insertions(+), 19 deletions(-)

diff --git a/libuuid/src/gen_uuid.c b/libuuid/src/gen_uuid.c
index 826cd2245..94b99f1bd 100644
--- a/libuuid/src/gen_uuid.c
+++ b/libuuid/src/gen_uuid.c
@@ -355,44 +355,102 @@ static uint64_t get_clock_counter(void)
 /*
  * Get continuous clock value.
  *
- * Return -1 if there is no further clock counter available,
+ * Return -1 if there is no valid clock counter available,
  * otherwise return 0.
  *
  * This implementation doesn't deliver clock counters based on
  * the current time because last_clock_reg is only incremented
  * by the number of requested UUIDs.
  * max_clock_offset is used to limit the offset of last_clock_reg.
+ * used/reserved UUIDs are written to LIBUUID_CLOCK_CONT_FILE.
  */
 static int get_clock_cont(uint32_t *clock_high,
 			  uint32_t *clock_low,
 			  int num,
 			  uint32_t max_clock_offset)
 {
-	/* 100ns based time offset according to RFC 4122. 4.1.4. */
+	/* all 64bit clock_reg values in this function represent '100ns ticks'
+         * due to the combination of tv_usec + MAX_ADJUSTMENT */
+
+	enum { fd_init = -2, fd_error = -1 };
+	/* time offset according to RFC 4122. 4.1.4. */
 	const uint64_t reg_offset = (((uint64_t) 0x01B21DD2) << 32) + 0x13814000;
 	static uint64_t last_clock_reg = 0;
-	uint64_t clock_reg;
+	static uint64_t saved_clock_reg = 0;
+	static int state_fd = fd_init;
+	static FILE *state_f = NULL;
+	uint64_t clock_reg, next_clock_reg;
 
-	if (last_clock_reg == 0)
-		last_clock_reg = get_clock_counter();
+	if (state_fd == fd_error)
+		return -1;
 
 	clock_reg = get_clock_counter();
+
+	if (state_fd == fd_init) {
+		mode_t save_umask;
+		struct stat st;
+
+		save_umask = umask(0);
+		state_fd = open(LIBUUID_CLOCK_CONT_FILE, O_RDWR|O_CREAT|O_CLOEXEC, 0660);
+		(void) umask(save_umask);
+		if (state_fd == fd_error)
+			return -1;
+
+		state_f = fdopen(state_fd, "r+" UL_CLOEXECSTR);
+		if (!state_f)
+			goto error;
+
+		if (fstat(state_fd, &st))
+			goto error;
+
+		if (st.st_size) {
+			rewind(state_f);
+			if (fscanf(state_f, "cont: %lu\n", &last_clock_reg) != 1)
+				goto error;
+		} else
+			last_clock_reg = clock_reg;
+
+		saved_clock_reg = last_clock_reg;
+	}
+
 	if (max_clock_offset) {
-		uint64_t clock_offset = max_clock_offset * 10000000ULL;
-		if (last_clock_reg < (clock_reg - clock_offset))
-			last_clock_reg = clock_reg - clock_offset;
+		uint64_t co = 10000000ULL * (uint64_t)max_clock_offset;	// clock_offset in [100ns]
+
+		if ((last_clock_reg + co) < clock_reg)
+			last_clock_reg = clock_reg - co;
 	}
 
 	clock_reg += MAX_ADJUSTMENT;
 
-	if ((last_clock_reg + num) >= clock_reg)
+	next_clock_reg = last_clock_reg + (uint64_t)num;
+	if (next_clock_reg >= clock_reg)
 		return -1;
 
+	if (next_clock_reg >= saved_clock_reg) {
+		uint64_t cl = next_clock_reg + 100000000ULL;	// 10s interval in [100ns]
+		int l;
+
+		rewind(state_f);
+		l = fprintf(state_f, "cont: %020lu                   \n", cl);
+		if (l < 30 || fflush(state_f))
+			goto error;
+		saved_clock_reg = cl;
+	}
+
 	*clock_high = (last_clock_reg + reg_offset) >> 32;
 	*clock_low = last_clock_reg + reg_offset;
-	last_clock_reg += num;
+	last_clock_reg = next_clock_reg;
 
 	return 0;
+
+error:
+	if (state_fd >= 0)
+		close(state_fd);
+	if (state_f)
+		fclose(state_f);
+	state_fd = fd_error;
+	state_f = NULL;
+	return -1;
 }
 
 #if defined(HAVE_UUIDD) && defined(HAVE_SYS_UN_H)
diff --git a/libuuid/src/uuidP.h b/libuuid/src/uuidP.h
index 200702c1e..fef7e6cb5 100644
--- a/libuuid/src/uuidP.h
+++ b/libuuid/src/uuidP.h
@@ -40,6 +40,7 @@
 #include "uuid.h"
 
 #define LIBUUID_CLOCK_FILE	"/var/lib/libuuid/clock.txt"
+#define LIBUUID_CLOCK_CONT_FILE	"/var/lib/libuuid/clock-cont.txt"
 
 /*
  * Offset between 15-Oct-1582 and 1-Jan-70
diff --git a/misc-utils/uuidd.c b/misc-utils/uuidd.c
index fd121c5bc..42a252dd0 100644
--- a/misc-utils/uuidd.c
+++ b/misc-utils/uuidd.c
@@ -442,15 +442,6 @@ static void server_loop(const char *socket_path, const char *pidfile_path,
 	pfd[POLLFD_SOCKET].fd = s;
 	pfd[POLLFD_SIGNAL].events = pfd[POLLFD_SOCKET].events = POLLIN | POLLERR | POLLHUP;
 
-	num = 1;
-	if (uuidd_cxt->cont_clock_offset) {
-		/* trigger initialization */
-		(void) __uuid_generate_time_cont(uu, &num, uuidd_cxt->cont_clock_offset);
-		if (uuidd_cxt->debug)
-			fprintf(stderr, _("max_clock_offset = %u sec\n"),
-				uuidd_cxt->cont_clock_offset);
-	}
-
 	while (1) {
 		ret = poll(pfd, ARRAY_SIZE(pfd),
 				uuidd_cxt->timeout ?
-- 
2.39.3 (Apple Git-145)


^ permalink raw reply related

* [PATCH] util-linux/sys-utils dmesg add PRINTK_CALLER support
From: Edward Chron @ 2023-12-13  6:34 UTC (permalink / raw)
  To: util-linux; +Cc: colona, echron

Submission to Project: util-linux
Open Incident: #2609 at github.com/util-linux/util-linux/issues/2609
Component: util-linux/sys-utils
File: dmesg.c
Code level patch applied against: 2.39.3 - latest code pulled from
           git.github.com:util-linux/util-linux.git
Revision: #1 on 2023/12/08 per Review from Karel Zak
Revision: #2 on 2023/12/12 Adjust line offsets for master update and
                           Add caller_id_size init to dmesg -K
Revision: #3 on 2023/12/12 Use of sizeof for cidbuf and limit search
                           for caller_id to dmesg prefix to msg text

Add support to standard dmesg command for the optional Linux Kernel
debug CONFIG option PRINTK_CALLER which adds an optional dmesg field
that contains the Thread Id or CPU Id that is issuing the printk to
add the message to the kernel ring buffer. This makes debugging simpler
as dmesg entries for a specific thread or CPU can be recognized.

The dmesg -S using the old syslog interface supports printing the
PRINTK_CALLER field but currently standard dmesg does not support
printing the field if present. There are utilities that use dmesg and
so it would be optimal if dmesg supported PRINTK_CALLER as well.

The additional field provided by PRINTK_CALLER is only present
if it was configured for the Linux kernel where the dmesg command
is run. It is a debug option and not configured by default so the
dmesg output will only change for those kernels where the option was
configured when the kernel was built. For users who went to the
trouble to configure PRINTK_CALLER and have the extra field available
for debugging, having dmesg print the field is very helpful.

Size of the PRINTK_CALLER field is determined by the maximum number
tasks that can be run on the system which is limited by the value of
/proc/sys/kernel/pid_max as pid values are from 0 to value - 1.
This value determines the number of id digits needed by the caller id.
The PRINTK_CALLER field is printed as T<id> for a Task Id or C<id>
for a CPU Id for a printk in CPU context. The values are left space
padded and enclosed in parentheses such as: [    T123] or [     C16]

For consistency with dmesg -S which supports the PRINTK_CALLER field
the field is printed followed by a space. For JSON format output the
PRINTK_CALLER field is identified as caller as that is consistent with
it's naming in /dev/kmsg. No space padding is used to reduce space
consumed by the JSON output. So the output from the command on a system
with PRINTK_CALLER field enabled in the Linux .config file the dmesg
output appears as:

> dmesg
...
[  520.897104] [   T3919] usb 3-3: Product: USB 2.0 Hub

and

> dmesg -x
...
kern  :info  : [  520.897104] [   T3919] usb 3-3: Product: USB 2.0 Hub

and

> dmesg -J
...
      },{
         "pri": 6,
         "time":    520.897104,
         "caller": "T3919",
         "msg": "usb 3-3: Product: USB 2.0 Hub"
      },{

and

> dmesg -J -x
...
      },{
         "fac": "kern",
         "pri": "info",
         "time":   520.897104,
         "caller": "T3919",
         "msg": "usb 3-3: Product: USB 2.0 Hub"
      },{

>

For comparison:

> dmesg -S
...
[  520.897104] [ T3919] usb 3-3: Product: USB 2.0 Hub

and

> dmesg -S -x
...
kern  :info  : [  520.897104] [ T3919] usb 3-3: Product: USB 2.0 Hub

Note: When dmesg uses the old syslog interface the reserved space for
      the PRINTK_CALLER field is capped at 5 digits because 32-bit
      kernels are capped at 32768 as the max number of PIDs. However,
      64-bit systems are currently capped at 2^22 PIDs (0 - 4194303).
      The PID cap is set by PID_MAX_LIMIT but the system limit can be
      less so we use /proc/sys/kernel/pid_max to determine the size
      needed to hold the maximum PID value size for the current system.
      Many 64-bit systems support 2^22 PIDs (0 - 4194303) and you see:

> dmesg -x
...
kern  :info  : [  520.899558] [   T3919] hub 3-3:1.0: USB hub found
...
kern  :info  : [ 9830.456898] [  T98982] cgroup: fork rejected by pids ...
kern  :info  : [14301.158878] [ T137336] cgroup: fork rejected by pids ...
kern  :info  : [18980.803190] [T1637865] cgroup: fork rejected by pids ...

> dmesg -S -x
...
kern  :info  : [  520.899558] [ T3919] hub 3-3:1.0: USB hub found
...
kern  :info  : [ 9830.456898] [T98982] cgroup: fork rejected by pids ...
kern  :info  : [14301.158878] [T137336] cgroup: fork rejected by pids ...
kern  :info  : [18980.803190] [T1637865] cgroup: fork rejected by pids ...

This is the only difference seen with PRINTK_CALLER configured and
printing between the dmesg /dev/kmsg interface and the dmesg -S syslog
interface.

Signed-off-by: Ivan Delalande <colona@arista.com>
Signed-off-by: Edward Chron <echron@arista.com>
---
 include/pathnames.h                           |   3 +
 sys-utils/dmesg.c                             | 117 +++-
 .../expected/dmesg/colors-kmsg-printk-caller  |  22 +
 .../dmesg/console-levels-kmsg-printk-caller   |  45 ++
 .../expected/dmesg/decode-kmsg-printk-caller  |  22 +
 tests/expected/dmesg/delta-kmsg-printk-caller |  22 +
 .../dmesg/facilities-kmsg-printk-caller       |  22 +
 .../dmesg/indentation-kmsg-printk-caller      |  28 +
 tests/expected/dmesg/json-kmsg-printk-caller  | 115 ++++
 .../expected/dmesg/json-syslog-printk-caller  | 530 ++++++++++++++++++
 tests/expected/dmesg/kmsg-file-printk-caller  | 115 ++++
 tests/expected/dmesg/limit-kmsg-printk-caller |  11 +
 tests/ts/dmesg/colors-kmsg-printk-caller      |  29 +
 .../dmesg/console-levels-kmsg-printk-caller   |  36 ++
 tests/ts/dmesg/decode-kmsg-printk-caller      |  28 +
 tests/ts/dmesg/delta-kmsg-printk-caller       |  28 +
 tests/ts/dmesg/facilities-kmsg-printk-caller  |  30 +
 tests/ts/dmesg/indentation-kmsg-printk-caller |  40 ++
 tests/ts/dmesg/input-syslog-printk-caller     | 105 ++++
 tests/ts/dmesg/json-kmsg-printk-caller        |  28 +
 tests/ts/dmesg/json-syslog-printk-caller      |  28 +
 tests/ts/dmesg/kmsg-file-printk-caller        |  28 +
 tests/ts/dmesg/kmsg-input-printk-caller       | Bin 0 -> 2187 bytes
 tests/ts/dmesg/limit-kmsg-printk-caller       |  29 +
 tests/ts/dmesg/newlines-kmsg-printk-caller    | Bin 0 -> 152 bytes
 25 files changed, 1460 insertions(+), 1 deletion(-)
 create mode 100644 tests/expected/dmesg/colors-kmsg-printk-caller
 create mode 100644 tests/expected/dmesg/console-levels-kmsg-printk-caller
 create mode 100644 tests/expected/dmesg/decode-kmsg-printk-caller
 create mode 100644 tests/expected/dmesg/delta-kmsg-printk-caller
 create mode 100644 tests/expected/dmesg/facilities-kmsg-printk-caller
 create mode 100644 tests/expected/dmesg/indentation-kmsg-printk-caller
 create mode 100644 tests/expected/dmesg/json-kmsg-printk-caller
 create mode 100644 tests/expected/dmesg/json-syslog-printk-caller
 create mode 100644 tests/expected/dmesg/kmsg-file-printk-caller
 create mode 100644 tests/expected/dmesg/limit-kmsg-printk-caller
 create mode 100755 tests/ts/dmesg/colors-kmsg-printk-caller
 create mode 100755 tests/ts/dmesg/console-levels-kmsg-printk-caller
 create mode 100755 tests/ts/dmesg/decode-kmsg-printk-caller
 create mode 100755 tests/ts/dmesg/delta-kmsg-printk-caller
 create mode 100755 tests/ts/dmesg/facilities-kmsg-printk-caller
 create mode 100755 tests/ts/dmesg/indentation-kmsg-printk-caller
 create mode 100644 tests/ts/dmesg/input-syslog-printk-caller
 create mode 100755 tests/ts/dmesg/json-kmsg-printk-caller
 create mode 100755 tests/ts/dmesg/json-syslog-printk-caller
 create mode 100755 tests/ts/dmesg/kmsg-file-printk-caller
 create mode 100644 tests/ts/dmesg/kmsg-input-printk-caller
 create mode 100755 tests/ts/dmesg/limit-kmsg-printk-caller
 create mode 100644 tests/ts/dmesg/newlines-kmsg-printk-caller

diff --git a/include/pathnames.h b/include/pathnames.h
index caf0e63d4..81fa405f6 100644
--- a/include/pathnames.h
+++ b/include/pathnames.h
@@ -230,4 +230,7 @@
 /* cgroup path */
 #define _PATH_SYS_CGROUP	"/sys/fs/cgroup"
 
+/* Maximum number of PIDs system supports */
+#define _PATH_PROC_PIDMAX	"/proc/sys/kernel/pid_max"
+
 #endif /* PATHNAMES_H */
diff --git a/sys-utils/dmesg.c b/sys-utils/dmesg.c
index 77728b419..b0caecbba 100644
--- a/sys-utils/dmesg.c
+++ b/sys-utils/dmesg.c
@@ -13,7 +13,9 @@
  */
 #include <stdio.h>
 #include <getopt.h>
+#include <stdbool.h>
 #include <stdlib.h>
+#include <string.h>
 #include <sys/klog.h>
 #include <sys/syslog.h>
 #include <sys/time.h>
@@ -41,6 +43,7 @@
 #include "mangle.h"
 #include "pager.h"
 #include "jsonwrt.h"
+#include "pathnames.h"
 
 /* Close the log.  Currently a NOP. */
 #define SYSLOG_ACTION_CLOSE          0
@@ -65,6 +68,11 @@
 /* Return size of the log buffer */
 #define SYSLOG_ACTION_SIZE_BUFFER   10
 
+#define PID_CHARS_MAX sizeof(stringify_value(LONG_MAX))
+#define PID_CHARS_DEFAULT sizeof(stringify_value(INT_MAX))
+#define DMESG_CALLER_PREFIX "caller="
+#define DMESG_CALLER_PREFIXSZ (sizeof(DMESG_CALLER_PREFIX)-1)
+
 /*
  * Color scheme
  */
@@ -233,6 +241,7 @@ struct dmesg_control {
 			force_prefix:1;	/* force timestamp and decode prefix
 					   on each line */
 	int		indent;		/* due to timestamps if newline */
+	size_t          caller_id_size;   /* PRINTK_CALLERID max field size */
 };
 
 struct dmesg_record {
@@ -242,6 +251,7 @@ struct dmesg_record {
 	int		level;
 	int		facility;
 	struct timeval  tv;
+	char		caller_id[PID_CHARS_MAX];
 
 	const char	*next;		/* buffer with next unparsed record */
 	size_t		next_size;	/* size of the next buffer */
@@ -254,6 +264,7 @@ struct dmesg_record {
 		(_r)->level = -1; \
 		(_r)->tv.tv_sec = 0; \
 		(_r)->tv.tv_usec = 0; \
+		(_r)->caller_id[0] = 0; \
 	} while (0)
 
 static int process_kmsg(struct dmesg_control *ctl);
@@ -551,6 +562,45 @@ static int get_syslog_buffer_size(void)
 	return n > 0 ? n : 0;
 }
 
+/*
+ * Get the number of characters needed to hold the maximum number
+ * of tasks this system supports. This size of string could hold
+ * a thread id large enough for the highest thread id.
+ * This is needed to determine the number of characters reserved for
+ * the PRINTK_CALLER field if it has been configured in the Linux Kernel.
+ *
+ * The number of digits sets the max value since the value can't exceed
+ * a value of that size. The /proc field defined by _PATH_PROC_PIDMAX
+ * holds the maximum number of PID values that may be ussed by the system,
+ * so 0 to that value minus one.
+ *
+ * For determining the size of the PRINTK_CALLER field, we make the safe
+ * assumption that the number of threads >= number of cpus. This because
+ * the PRINTK_CALLER field can hold either a thread id or a CPU id value.
+ *
+ * If we can't access the pid max kernel proc entry we assign a default
+ * field size of 5 characters as that is what the old syslog interface
+ * uses as the reserved field size. This is justified because 32-bit Linux
+ * systems are limited to PID values between (0-32767).
+ *
+ */
+static size_t max_threads_id_size(void)
+{
+	char taskmax[PID_CHARS_MAX] = {'\0'};
+	ssize_t rdsize;
+	int fd;
+
+	fd = open(_PATH_PROC_PIDMAX, O_RDONLY);
+	if (fd == -1)
+		return PID_CHARS_DEFAULT;
+
+	rdsize = read(fd, taskmax, sizeof(taskmax));
+	if (rdsize == -1)
+		return PID_CHARS_DEFAULT;
+
+	return strnlen(taskmax, sizeof(taskmax));
+}
+
 /*
  * Reads messages from regular file by mmap
  */
@@ -728,6 +778,39 @@ static const char *skip_item(const char *begin, const char *end, const char *sep
 	return begin;
 }
 
+/*
+ * Checks to see if the caller (caller id) field is present in the kmsg record.
+ * This is true if the PRINTK_CALLER config option has been set in the kernel.
+ *
+ * If the caller_id is found in the kmsg buffer then return the id and id type
+ * to the caller in dmesg caller_id. Returns string pointer to next value.
+ *
+ */
+static const char *parse_callerid(const char *p_str, const char *end,
+				  struct dmesg_record *p_drec)
+{
+	const char *p_after;
+	const char *p_next;
+	size_t cid_size;
+	char *p_scn;
+	char *p_cid;
+
+	/* Check for PRINTK_CALLER prefix, must be before msg text */
+	p_cid = strstr(p_str, DMESG_CALLER_PREFIX);
+	p_scn = strchr(p_str, ';');
+	if (p_cid != NULL && p_drec != NULL && p_scn != NULL && p_cid < p_scn) {
+		p_next = p_cid + DMESG_CALLER_PREFIXSZ;
+		p_after = skip_item(p_next, end, ",;");
+		cid_size = p_after - p_next;
+		if (cid_size < sizeof(p_drec->caller_id))
+			xstrncpy(p_drec->caller_id, p_next, cid_size);
+		else
+			return p_str;
+		return p_after;
+	}
+	return p_str;
+}
+
 /*
  * Parses one record from syslog(2) buffer
  */
@@ -795,6 +878,18 @@ static int get_next_syslog_record(struct dmesg_control *ctl,
 				begin++;
 		}
 
+		if (*begin == '[' && (*(begin + 1) == ' ' ||
+			(*(begin + 1) == 'T' || *(begin + 1) == 'C'))) {
+			const char *start = begin + 1;
+			size_t id_size;
+
+			start = start + strspn(start, " ");
+			begin = skip_item(begin, end, "]");
+			id_size = begin - start;
+			if (id_size < sizeof(rec->caller_id))
+				xstrncpy(rec->caller_id, start, id_size);
+		}
+
 		rec->mesg = begin;
 		rec->mesg_size = end - begin;
 
@@ -1101,6 +1196,19 @@ full_output:
 			color_disable();
 	}
 
+	if (*rec->caller_id) {
+		if (ctl->json) {
+			ul_jsonwrt_value_s(&ctl->jfmt, "caller", rec->caller_id);
+		} else {
+			char cidbuf[PID_CHARS_MAX+3] = {'\0'};
+
+			sprintf(cidbuf, "[%*s] ",
+				(char)ctl->caller_id_size - 1, rec->caller_id);
+			ctl->indent += strnlen(cidbuf, sizeof(cidbuf));
+			fputs(cidbuf, stdout);
+		}
+	}
+
 	/*
 	 * A kernel message may contain several lines of output, separated
 	 * by '\n'.  If the timestamp and decode outputs are forced then each
@@ -1229,6 +1337,8 @@ static int init_kmsg(struct dmesg_control *ctl)
 		return -1;
 	}
 
+	ctl->caller_id_size = max_threads_id_size();
+
 	return 0;
 }
 
@@ -1284,7 +1394,10 @@ static int parse_kmsg_record(struct dmesg_control *ctl,
 		goto mesg;
 
 	/* D) optional fields (ignore) */
-	p = skip_item(p, end, ";");
+	p = skip_item(p, end, ",;");
+
+	/* Include optional PRINTK_CALLER field if it is present */
+	p = parse_callerid(p, end, rec);
 
 mesg:
 	/* E) message text */
@@ -1446,6 +1559,7 @@ int main(int argc, char *argv[])
 		.kmsg = -1,
 		.time_fmt = DMESG_TIMEFTM_TIME,
 		.indent = 0,
+		.caller_id_size = 0,
 	};
 	int colormode = UL_COLORMODE_UNDEF;
 	enum {
@@ -1542,6 +1656,7 @@ int main(int argc, char *argv[])
 		case 'K':
 			ctl.filename = optarg;
 			ctl.method = DMESG_METHOD_KMSG;
+			ctl.caller_id_size = max_threads_id_size();
 			break;
 		case 'f':
 			ctl.fltr_fac = 1;
diff --git a/tests/expected/dmesg/colors-kmsg-printk-caller b/tests/expected/dmesg/colors-kmsg-printk-caller
new file mode 100644
index 000000000..c7bf6e8b7
--- /dev/null
+++ b/tests/expected/dmesg/colors-kmsg-printk-caller
@@ -0,0 +1,22 @@
+kern  :notice: ^[[32m[    0.000000] ^[[0m[     T0] Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000
+kern  :info  : ^[[32m[    0.000000] ^[[0m[     T1] ^[[33mCommand line: ^[[0minitrd=\ucode.img initrd=\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system
+kern  :info  : ^[[32m[    0.000000] ^[[0m[     T2] BIOS-provided physical RAM map:
+kern  :info  : ^[[32m[    0.000000] ^[[0m[     T3] ^[[33mBIOS-e820: ^[[0m[mem 0x0000000000000000-0x000000000009efff] usable
+kern  :info  : ^[[32m[    0.000000] ^[[0m[     T4] ^[[33mBIOS-e820: ^[[0m[mem 0x000000000009f000-0x00000000000bffff] reserved
+kern  :info  : ^[[32m[    0.000000] ^[[0m[     T5] ^[[33mBIOS-e820: ^[[0m[mem 0x0000000000100000-0x0000000009afffff] usable
+kern  :info  : ^[[32m[    0.000000] ^[[0m[     T6] ^[[33mBIOS-e820: ^[[0m[mem 0x0000000009b00000-0x0000000009dfffff] reserved
+kern  :info  : ^[[32m[    0.000000] ^[[0m[     T7] ^[[33mBIOS-e820: ^[[0m[mem 0x0000000009e00000-0x0000000009efffff] usable
+kern  :info  : ^[[32m[    0.000000] ^[[0m[     T8] ^[[33mBIOS-e820: ^[[0m[mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS
+kern  :info  : ^[[32m[    0.000000] ^[[0m[     T9] ^[[33mBIOS-e820: ^[[0m[mem 0x0000000009f3c000-0x000000004235ffff] usable
+kern  :info  : ^[[32m[    0.000000] ^[[0m[    T10] ^[[33mBIOS-e820: ^[[0m[mem 0x0000000042360000-0x000000004455ffff] reserved
+kern  :info  : ^[[32m[    0.367657] ^[[0m[    T11] ^[[33mACPI: ^[[0m\_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+kern  :info  : ^[[32m[    0.368615] ^[[0m[    T12] ^[[33mACPI: ^[[0m\_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+kern  :info  : ^[[32m[    0.376316] ^[[0m[    T13] ^[[33mACPI: ^[[0m\_SB_.PRWL: New power resource
+kern  :info  : ^[[32m[    0.376343] ^[[0m[    T14] ^[[33mACPI: ^[[0m\_SB_.PRWB: New power resource
+kern  :info  : ^[[32m[    0.377373] ^[[0m[    T15] ^[[33mACPI: ^[[0mPCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+kern  :info  : ^[[32m[    0.377378] ^[[0m[    T16] ^[[33macpi PNP0A08:00: ^[[0m_OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+kern  :info  : ^[[32m[    0.377569] ^[[0m[    T17] ^[[33macpi PNP0A08:00: ^[[0m_OSC: platform does not support [SHPCHotplug AER]
+kern  :info  : ^[[32m[    0.377933] ^[[0m[    T18] ^[[33macpi PNP0A08:00: ^[[0m_OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+kern  :info  : ^[[32m[    0.378458] ^[[0m[    T19] PCI host bridge to bus 0000:00
+kern  :info  : ^[[32m[    0.378459] ^[[0m[    T20] ^[[33mpci_bus 0000:00: ^[[0mroot bus resource [io  0x0000-0x0cf7 window]
+kern  :info  : ^[[32m[    0.378461] ^[[0m[    T21] ^[[33mpci_bus 0000:00: ^[[0mroot bus resource [io  0x0d00-0xffff window]
diff --git a/tests/expected/dmesg/console-levels-kmsg-printk-caller b/tests/expected/dmesg/console-levels-kmsg-printk-caller
new file mode 100644
index 000000000..1f6e9f178
--- /dev/null
+++ b/tests/expected/dmesg/console-levels-kmsg-printk-caller
@@ -0,0 +1,45 @@
+[    0.000000] [     T0] Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000
+[    0.000000] [     T1] Command line: initrd=\ucode.img initrd=\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system
+[    0.000000] [     T2] BIOS-provided physical RAM map:
+[    0.000000] [     T3] BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable
+[    0.000000] [     T4] BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved
+[    0.000000] [     T5] BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable
+[    0.000000] [     T6] BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved
+[    0.000000] [     T7] BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable
+[    0.000000] [     T8] BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS
+[    0.000000] [     T9] BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable
+[    0.000000] [    T10] BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved
+[    0.367657] [    T11] ACPI: \_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+[    0.368615] [    T12] ACPI: \_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+[    0.376316] [    T13] ACPI: \_SB_.PRWL: New power resource
+[    0.376343] [    T14] ACPI: \_SB_.PRWB: New power resource
+[    0.377373] [    T15] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+[    0.377378] [    T16] acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+[    0.377569] [    T17] acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]
+[    0.377933] [    T18] acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+[    0.378458] [    T19] PCI host bridge to bus 0000:00
+[    0.378459] [    T20] pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]
+[    0.378461] [    T21] pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]
+[    0.000000] [     T0] Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000
+[    0.000000] [     T1] Command line: initrd=\ucode.img initrd=\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system
+[    0.000000] [     T2] BIOS-provided physical RAM map:
+[    0.000000] [     T3] BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable
+[    0.000000] [     T4] BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved
+[    0.000000] [     T5] BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable
+[    0.000000] [     T6] BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved
+[    0.000000] [     T7] BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable
+[    0.000000] [     T8] BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS
+[    0.000000] [     T9] BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable
+[    0.000000] [    T10] BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved
+[    0.367657] [    T11] ACPI: \_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+[    0.368615] [    T12] ACPI: \_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+[    0.376316] [    T13] ACPI: \_SB_.PRWL: New power resource
+[    0.376343] [    T14] ACPI: \_SB_.PRWB: New power resource
+[    0.377373] [    T15] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+[    0.377378] [    T16] acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+[    0.377569] [    T17] acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]
+[    0.377933] [    T18] acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+[    0.378458] [    T19] PCI host bridge to bus 0000:00
+[    0.378459] [    T20] pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]
+[    0.378461] [    T21] pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]
+test_dmesg: unknown level '+'
diff --git a/tests/expected/dmesg/decode-kmsg-printk-caller b/tests/expected/dmesg/decode-kmsg-printk-caller
new file mode 100644
index 000000000..78c363389
--- /dev/null
+++ b/tests/expected/dmesg/decode-kmsg-printk-caller
@@ -0,0 +1,22 @@
+kern  :notice: [    0.000000] [     T0] Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000
+kern  :info  : [    0.000000] [     T1] Command line: initrd=\ucode.img initrd=\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system
+kern  :info  : [    0.000000] [     T2] BIOS-provided physical RAM map:
+kern  :info  : [    0.000000] [     T3] BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable
+kern  :info  : [    0.000000] [     T4] BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved
+kern  :info  : [    0.000000] [     T5] BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable
+kern  :info  : [    0.000000] [     T6] BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved
+kern  :info  : [    0.000000] [     T7] BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable
+kern  :info  : [    0.000000] [     T8] BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS
+kern  :info  : [    0.000000] [     T9] BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable
+kern  :info  : [    0.000000] [    T10] BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved
+kern  :info  : [    0.367657] [    T11] ACPI: \_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+kern  :info  : [    0.368615] [    T12] ACPI: \_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+kern  :info  : [    0.376316] [    T13] ACPI: \_SB_.PRWL: New power resource
+kern  :info  : [    0.376343] [    T14] ACPI: \_SB_.PRWB: New power resource
+kern  :info  : [    0.377373] [    T15] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+kern  :info  : [    0.377378] [    T16] acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+kern  :info  : [    0.377569] [    T17] acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]
+kern  :info  : [    0.377933] [    T18] acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+kern  :info  : [    0.378458] [    T19] PCI host bridge to bus 0000:00
+kern  :info  : [    0.378459] [    T20] pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]
+kern  :info  : [    0.378461] [    T21] pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]
diff --git a/tests/expected/dmesg/delta-kmsg-printk-caller b/tests/expected/dmesg/delta-kmsg-printk-caller
new file mode 100644
index 000000000..892d2dcea
--- /dev/null
+++ b/tests/expected/dmesg/delta-kmsg-printk-caller
@@ -0,0 +1,22 @@
+[    0.000000 <    0.000000>] [     T0] Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000
+[    0.000000 <    0.000000>] [     T1] Command line: initrd=\ucode.img initrd=\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system
+[    0.000000 <    0.000000>] [     T2] BIOS-provided physical RAM map:
+[    0.000000 <    0.000000>] [     T3] BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable
+[    0.000000 <    0.000000>] [     T4] BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved
+[    0.000000 <    0.000000>] [     T5] BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable
+[    0.000000 <    0.000000>] [     T6] BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved
+[    0.000000 <    0.000000>] [     T7] BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable
+[    0.000000 <    0.000000>] [     T8] BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS
+[    0.000000 <    0.000000>] [     T9] BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable
+[    0.000000 <    0.000000>] [    T10] BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved
+[    0.367657 <    0.000000>] [    T11] ACPI: \_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+[    0.368615 <    0.000000>] [    T12] ACPI: \_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+[    0.376316 <    0.000000>] [    T13] ACPI: \_SB_.PRWL: New power resource
+[    0.376343 <    0.000000>] [    T14] ACPI: \_SB_.PRWB: New power resource
+[    0.377373 <    0.000000>] [    T15] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+[    0.377378 <    0.000000>] [    T16] acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+[    0.377569 <    0.000000>] [    T17] acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]
+[    0.377933 <    0.000000>] [    T18] acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+[    0.378458 <    0.000000>] [    T19] PCI host bridge to bus 0000:00
+[    0.378459 <    0.000000>] [    T20] pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]
+[    0.378461 <    0.000000>] [    T21] pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]
diff --git a/tests/expected/dmesg/facilities-kmsg-printk-caller b/tests/expected/dmesg/facilities-kmsg-printk-caller
new file mode 100644
index 000000000..78c363389
--- /dev/null
+++ b/tests/expected/dmesg/facilities-kmsg-printk-caller
@@ -0,0 +1,22 @@
+kern  :notice: [    0.000000] [     T0] Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000
+kern  :info  : [    0.000000] [     T1] Command line: initrd=\ucode.img initrd=\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system
+kern  :info  : [    0.000000] [     T2] BIOS-provided physical RAM map:
+kern  :info  : [    0.000000] [     T3] BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable
+kern  :info  : [    0.000000] [     T4] BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved
+kern  :info  : [    0.000000] [     T5] BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable
+kern  :info  : [    0.000000] [     T6] BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved
+kern  :info  : [    0.000000] [     T7] BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable
+kern  :info  : [    0.000000] [     T8] BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS
+kern  :info  : [    0.000000] [     T9] BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable
+kern  :info  : [    0.000000] [    T10] BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved
+kern  :info  : [    0.367657] [    T11] ACPI: \_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+kern  :info  : [    0.368615] [    T12] ACPI: \_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+kern  :info  : [    0.376316] [    T13] ACPI: \_SB_.PRWL: New power resource
+kern  :info  : [    0.376343] [    T14] ACPI: \_SB_.PRWB: New power resource
+kern  :info  : [    0.377373] [    T15] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+kern  :info  : [    0.377378] [    T16] acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+kern  :info  : [    0.377569] [    T17] acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]
+kern  :info  : [    0.377933] [    T18] acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+kern  :info  : [    0.378458] [    T19] PCI host bridge to bus 0000:00
+kern  :info  : [    0.378459] [    T20] pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]
+kern  :info  : [    0.378461] [    T21] pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]
diff --git a/tests/expected/dmesg/indentation-kmsg-printk-caller b/tests/expected/dmesg/indentation-kmsg-printk-caller
new file mode 100644
index 000000000..47ad73f27
--- /dev/null
+++ b/tests/expected/dmesg/indentation-kmsg-printk-caller
@@ -0,0 +1,28 @@
+[    0.000000] [     T0] line zero
+[    1.000000] [     T1] new
+[    2.000000] [     T2] two
+[    3.000000] [     T3] three
+kern  :notice: [    0.000000] [     T0] line zero
+user  :crit  : [    1.000000] [     T1] new
+mail  :warn  : [    2.000000] [     T2] two
+daemon:info  : [    3.000000] [     T3] three
+[<    0.000000>] [     T0] line zero
+[<    0.000000>] [     T1] new
+[<    1.000000>] [     T2] two
+[<    1.000000>] [     T3] three
+[     T0] line zero
+[     T1] new
+[     T2] two
+[     T3] three
+[Feb13 23:31] [     T0] line zero
+[  +0.000000] [     T1] new
+[  +1.000000] [     T2] two
+[  +1.000000] [     T3] three
+[Fri Feb 13 23:31:30 2009] [     T0] line zero
+[Fri Feb 13 23:31:31 2009] [     T1] new
+[Fri Feb 13 23:31:32 2009] [     T2] two
+[Fri Feb 13 23:31:33 2009] [     T3] three
+2009-02-13T23:31:30,123456+00:00 [     T0] line zero
+2009-02-13T23:31:31,123456+00:00 [     T1] new
+2009-02-13T23:31:32,123456+00:00 [     T2] two
+2009-02-13T23:31:33,123456+00:00 [     T3] three
diff --git a/tests/expected/dmesg/json-kmsg-printk-caller b/tests/expected/dmesg/json-kmsg-printk-caller
new file mode 100644
index 000000000..785d730a5
--- /dev/null
+++ b/tests/expected/dmesg/json-kmsg-printk-caller
@@ -0,0 +1,115 @@
+{
+   "dmesg": [
+      {
+         "pri": 5,
+         "time":     0.000000,
+         "caller": "T0",
+         "msg": "Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T1",
+         "msg": "Command line: initrd=\\ucode.img initrd=\\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T2",
+         "msg": "BIOS-provided physical RAM map:"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T3",
+         "msg": "BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T4",
+         "msg": "BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T5",
+         "msg": "BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T6",
+         "msg": "BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T7",
+         "msg": "BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T8",
+         "msg": "BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T9",
+         "msg": "BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T10",
+         "msg": "BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved"
+      },{
+         "pri": 6,
+         "time":     0.367657,
+         "caller": "T11",
+         "msg": "ACPI: \\_SB_.PCI0.GP19.NHI1.PWRS: New power resource"
+      },{
+         "pri": 6,
+         "time":     0.368615,
+         "caller": "T12",
+         "msg": "ACPI: \\_SB_.PCI0.GP19.XHC4.PWRS: New power resource"
+      },{
+         "pri": 6,
+         "time":     0.376316,
+         "caller": "T13",
+         "msg": "ACPI: \\_SB_.PRWL: New power resource"
+      },{
+         "pri": 6,
+         "time":     0.376343,
+         "caller": "T14",
+         "msg": "ACPI: \\_SB_.PRWB: New power resource"
+      },{
+         "pri": 6,
+         "time":     0.377373,
+         "caller": "T15",
+         "msg": "ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])"
+      },{
+         "pri": 6,
+         "time":     0.377378,
+         "caller": "T16",
+         "msg": "acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]"
+      },{
+         "pri": 6,
+         "time":     0.377569,
+         "caller": "T17",
+         "msg": "acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]"
+      },{
+         "pri": 6,
+         "time":     0.377933,
+         "caller": "T18",
+         "msg": "acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]"
+      },{
+         "pri": 6,
+         "time":     0.378458,
+         "caller": "T19",
+         "msg": "PCI host bridge to bus 0000:00"
+      },{
+         "pri": 6,
+         "time":     0.378459,
+         "caller": "T20",
+         "msg": "pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]"
+      },{
+         "pri": 6,
+         "time":     0.378461,
+         "caller": "T21",
+         "msg": "pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]"
+      }
+   ]
+}
diff --git a/tests/expected/dmesg/json-syslog-printk-caller b/tests/expected/dmesg/json-syslog-printk-caller
new file mode 100644
index 000000000..40c98aa67
--- /dev/null
+++ b/tests/expected/dmesg/json-syslog-printk-caller
@@ -0,0 +1,530 @@
+{
+   "dmesg": [
+      {
+         "pri": 0,
+         "time":     0.000000,
+         "caller": "T0",
+         "msg": " example[0]"
+      },{
+         "pri": 1,
+         "time":     1.000000,
+         "caller": "T1",
+         "msg": " example[1]"
+      },{
+         "pri": 2,
+         "time":     8.000000,
+         "caller": "T2",
+         "msg": " example[2]"
+      },{
+         "pri": 3,
+         "time":    27.000000,
+         "caller": "T3",
+         "msg": " example[3]"
+      },{
+         "pri": 4,
+         "time":    64.000000,
+         "caller": "T4",
+         "msg": " example[4]"
+      },{
+         "pri": 5,
+         "time":   125.000000,
+         "caller": "T5",
+         "msg": " example[5]"
+      },{
+         "pri": 6,
+         "time":   216.000000,
+         "caller": "T6",
+         "msg": " example[6]"
+      },{
+         "pri": 7,
+         "time":   343.000000,
+         "caller": "T7",
+         "msg": " example[7]"
+      },{
+         "pri": 8,
+         "time":   512.000000,
+         "caller": "T8",
+         "msg": " example[8]"
+      },{
+         "pri": 9,
+         "time":   729.000000,
+         "caller": "T9",
+         "msg": " example[9]"
+      },{
+         "pri": 10,
+         "time":  1000.000000,
+         "caller": "T10",
+         "msg": " example[10]"
+      },{
+         "pri": 11,
+         "time":  1331.000000,
+         "caller": "T11",
+         "msg": " example[11]"
+      },{
+         "pri": 12,
+         "time":  1728.000000,
+         "caller": "T12",
+         "msg": " example[12]"
+      },{
+         "pri": 13,
+         "time":  2197.000000,
+         "caller": "T13",
+         "msg": " example[13]"
+      },{
+         "pri": 14,
+         "time":  2744.000000,
+         "caller": "T14",
+         "msg": " example[14]"
+      },{
+         "pri": 15,
+         "time":  3375.000000,
+         "caller": "T15",
+         "msg": " example[15]"
+      },{
+         "pri": 16,
+         "time":  4096.000000,
+         "caller": "T16",
+         "msg": " example[16]"
+      },{
+         "pri": 17,
+         "time":  4913.000000,
+         "caller": "T17",
+         "msg": " example[17]"
+      },{
+         "pri": 18,
+         "time":  5832.000000,
+         "caller": "T18",
+         "msg": " example[18]"
+      },{
+         "pri": 19,
+         "time":  6859.000000,
+         "caller": "T19",
+         "msg": " example[19]"
+      },{
+         "pri": 20,
+         "time":  8000.000000,
+         "caller": "T20",
+         "msg": " example[20]"
+      },{
+         "pri": 21,
+         "time":  9261.000000,
+         "caller": "T21",
+         "msg": " example[21]"
+      },{
+         "pri": 22,
+         "time": 10648.000000,
+         "caller": "T22",
+         "msg": " example[22]"
+      },{
+         "pri": 23,
+         "time": 12167.000000,
+         "caller": "T23",
+         "msg": " example[23]"
+      },{
+         "pri": 24,
+         "time": 13824.000000,
+         "caller": "T24",
+         "msg": " example[24]"
+      },{
+         "pri": 25,
+         "time": 15625.000000,
+         "caller": "T25",
+         "msg": " example[25]"
+      },{
+         "pri": 26,
+         "time": 17576.000000,
+         "caller": "T26",
+         "msg": " example[26]"
+      },{
+         "pri": 27,
+         "time": 19683.000000,
+         "caller": "T27",
+         "msg": " example[27]"
+      },{
+         "pri": 28,
+         "time": 21952.000000,
+         "caller": "T28",
+         "msg": " example[28]"
+      },{
+         "pri": 29,
+         "time": 24389.000000,
+         "caller": "T29",
+         "msg": " example[29]"
+      },{
+         "pri": 30,
+         "time": 27000.000000,
+         "caller": "T10",
+         "msg": " example[30]"
+      },{
+         "pri": 31,
+         "time": 29791.000000,
+         "caller": "T31",
+         "msg": " example[31]"
+      },{
+         "pri": 32,
+         "time": 32768.000000,
+         "caller": "T32",
+         "msg": " example[32]"
+      },{
+         "pri": 33,
+         "time": 35937.000000,
+         "caller": "T33",
+         "msg": " example[33]"
+      },{
+         "pri": 34,
+         "time": 39304.000000,
+         "caller": "T34",
+         "msg": " example[34]"
+      },{
+         "pri": 35,
+         "time": 42875.000000,
+         "caller": "T35",
+         "msg": " example[35]"
+      },{
+         "pri": 36,
+         "time": 46656.000000,
+         "caller": "T36",
+         "msg": " example[36]"
+      },{
+         "pri": 37,
+         "time": 50653.000000,
+         "caller": "T37",
+         "msg": " example[37]"
+      },{
+         "pri": 38,
+         "time": 54872.000000,
+         "caller": "T38",
+         "msg": " example[38]"
+      },{
+         "pri": 39,
+         "time": 59319.000000,
+         "caller": "T39",
+         "msg": " example[39]"
+      },{
+         "pri": 40,
+         "time": 64000.000000,
+         "caller": "T40",
+         "msg": " example[40]"
+      },{
+         "pri": 41,
+         "time": 68921.000000,
+         "caller": "T41",
+         "msg": " example[41]"
+      },{
+         "pri": 42,
+         "time": 74088.000000,
+         "caller": "T42",
+         "msg": " example[42]"
+      },{
+         "pri": 43,
+         "time": 79507.000000,
+         "caller": "T43",
+         "msg": " example[43]"
+      },{
+         "pri": 44,
+         "time": 85184.000000,
+         "caller": "T44",
+         "msg": " example[44]"
+      },{
+         "pri": 45,
+         "time": 91125.000000,
+         "caller": "T45",
+         "msg": " example[45]"
+      },{
+         "pri": 46,
+         "time": 97336.000000,
+         "caller": "T46",
+         "msg": " example[46]"
+      },{
+         "pri": 47,
+         "time": 103823.000000,
+         "caller": "T47",
+         "msg": " example[47]"
+      },{
+         "pri": 48,
+         "time": 110592.000000,
+         "caller": "T48",
+         "msg": " example[48]"
+      },{
+         "pri": 49,
+         "time": 117649.000000,
+         "caller": "T49",
+         "msg": " example[49]"
+      },{
+         "pri": 50,
+         "time": 125000.000000,
+         "caller": "T50",
+         "msg": " example[50]"
+      },{
+         "pri": 51,
+         "time": 132651.000000,
+         "caller": "T51",
+         "msg": " example[51]"
+      },{
+         "pri": 52,
+         "time": 140608.000000,
+         "caller": "T52",
+         "msg": " example[52]"
+      },{
+         "pri": 53,
+         "time": 148877.000000,
+         "caller": "T53",
+         "msg": " example[53]"
+      },{
+         "pri": 54,
+         "time": 157464.000000,
+         "caller": "T54",
+         "msg": " example[54]"
+      },{
+         "pri": 55,
+         "time": 166375.000000,
+         "caller": "T55",
+         "msg": " example[55]"
+      },{
+         "pri": 56,
+         "time": 175616.000000,
+         "caller": "T56",
+         "msg": " example[56]"
+      },{
+         "pri": 57,
+         "time": 185193.000000,
+         "caller": "T57",
+         "msg": " example[57]"
+      },{
+         "pri": 58,
+         "time": 195112.000000,
+         "caller": "T58",
+         "msg": " example[58]"
+      },{
+         "pri": 59,
+         "time": 205379.000000,
+         "caller": "T59",
+         "msg": " example[59]"
+      },{
+         "pri": 60,
+         "time": 216000.000000,
+         "caller": "T60",
+         "msg": " example[60]"
+      },{
+         "pri": 61,
+         "time": 226981.000000,
+         "caller": "T61",
+         "msg": " example[61]"
+      },{
+         "pri": 62,
+         "time": 238328.000000,
+         "caller": "T62",
+         "msg": " example[62]"
+      },{
+         "pri": 63,
+         "time": 250047.000000,
+         "caller": "T63",
+         "msg": " example[63]"
+      },{
+         "pri": 64,
+         "time": 262144.000000,
+         "caller": "T64",
+         "msg": " example[64]"
+      },{
+         "pri": 65,
+         "time": 274625.000000,
+         "caller": "T65",
+         "msg": " example[65]"
+      },{
+         "pri": 66,
+         "time": 287496.000000,
+         "caller": "T66",
+         "msg": " example[66]"
+      },{
+         "pri": 67,
+         "time": 300763.000000,
+         "caller": "T67",
+         "msg": " example[67]"
+      },{
+         "pri": 68,
+         "time": 314432.000000,
+         "caller": "T68",
+         "msg": " example[68]"
+      },{
+         "pri": 69,
+         "time": 328509.000000,
+         "caller": "T69",
+         "msg": " example[69]"
+      },{
+         "pri": 70,
+         "time": 343000.000000,
+         "caller": "T70",
+         "msg": " example[70]"
+      },{
+         "pri": 71,
+         "time": 357911.000000,
+         "caller": "T71",
+         "msg": " example[71]"
+      },{
+         "pri": 72,
+         "time": 373248.000000,
+         "caller": "T72",
+         "msg": " example[72]"
+      },{
+         "pri": 73,
+         "time": 389017.000000,
+         "caller": "T73",
+         "msg": " example[73]"
+      },{
+         "pri": 74,
+         "time": 405224.000000,
+         "caller": "T74",
+         "msg": " example[74]"
+      },{
+         "pri": 75,
+         "time": 421875.000000,
+         "caller": "T75",
+         "msg": " example[75]"
+      },{
+         "pri": 76,
+         "time": 438976.000000,
+         "caller": "T76",
+         "msg": " example[76]"
+      },{
+         "pri": 77,
+         "time": 456533.000000,
+         "caller": "T77",
+         "msg": " example[77]"
+      },{
+         "pri": 78,
+         "time": 474552.000000,
+         "caller": "T78",
+         "msg": " example[78]"
+      },{
+         "pri": 79,
+         "time": 493039.000000,
+         "caller": "T79",
+         "msg": " example[79]"
+      },{
+         "pri": 80,
+         "time": 512000.000000,
+         "caller": "T80",
+         "msg": " example[80]"
+      },{
+         "pri": 81,
+         "time": 531441.000000,
+         "caller": "T81",
+         "msg": " example[81]"
+      },{
+         "pri": 82,
+         "time": 551368.000000,
+         "caller": "T82",
+         "msg": " example[82]"
+      },{
+         "pri": 83,
+         "time": 571787.000000,
+         "caller": "T83",
+         "msg": " example[83]"
+      },{
+         "pri": 84,
+         "time": 592704.000000,
+         "caller": "T84",
+         "msg": " example[84]"
+      },{
+         "pri": 85,
+         "time": 614125.000000,
+         "caller": "T85",
+         "msg": " example[85]"
+      },{
+         "pri": 86,
+         "time": 636056.000000,
+         "caller": "T86",
+         "msg": " example[86]"
+      },{
+         "pri": 87,
+         "time": 658503.000000,
+         "caller": "T87",
+         "msg": " example[87]"
+      },{
+         "pri": 88,
+         "time": 681472.000000,
+         "caller": "T88",
+         "msg": " example[88]"
+      },{
+         "pri": 89,
+         "time": 704969.000000,
+         "caller": "T89",
+         "msg": " example[89]"
+      },{
+         "pri": 90,
+         "time": 729000.000000,
+         "caller": "T90",
+         "msg": " example[90]"
+      },{
+         "pri": 91,
+         "time": 753571.000000,
+         "caller": "T91",
+         "msg": " example[91]"
+      },{
+         "pri": 92,
+         "time": 778688.000000,
+         "caller": "T92",
+         "msg": " example[92]"
+      },{
+         "pri": 93,
+         "time": 804357.000000,
+         "caller": "T93",
+         "msg": " example[93]"
+      },{
+         "pri": 94,
+         "time": 830584.000000,
+         "caller": "T94",
+         "msg": " example[94]"
+      },{
+         "pri": 95,
+         "time": 857375.000000,
+         "caller": "T95",
+         "msg": " example[95]"
+      },{
+         "pri": 96,
+         "time": 884736.000000,
+         "caller": "T96",
+         "msg": " example[96]"
+      },{
+         "pri": 97,
+         "time": 912673.000000,
+         "caller": "T97",
+         "msg": " example[97]"
+      },{
+         "pri": 98,
+         "time": 941192.000000,
+         "caller": "T98",
+         "msg": " example[98]"
+      },{
+         "pri": 99,
+         "time": 970299.000000,
+         "caller": "T99",
+         "msg": " example[99]"
+      },{
+         "pri": 100,
+         "time": 1000000.000000,
+         "caller": "T100",
+         "msg": " example[100]"
+      },{
+         "pri": 101,
+         "time": 1030301.000000,
+         "caller": "T101",
+         "msg": " example[101]"
+      },{
+         "pri": 102,
+         "time": 1061208.000000,
+         "caller": "T102",
+         "msg": " example[102]"
+      },{
+         "pri": 103,
+         "time": 1092727.000000,
+         "caller": "T103",
+         "msg": " example[103]"
+      },{
+         "pri": 104,
+         "time": 1124864.000000,
+         "caller": "T104",
+         "msg": " example[104]"
+      }
+   ]
+}
diff --git a/tests/expected/dmesg/kmsg-file-printk-caller b/tests/expected/dmesg/kmsg-file-printk-caller
new file mode 100644
index 000000000..785d730a5
--- /dev/null
+++ b/tests/expected/dmesg/kmsg-file-printk-caller
@@ -0,0 +1,115 @@
+{
+   "dmesg": [
+      {
+         "pri": 5,
+         "time":     0.000000,
+         "caller": "T0",
+         "msg": "Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T1",
+         "msg": "Command line: initrd=\\ucode.img initrd=\\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T2",
+         "msg": "BIOS-provided physical RAM map:"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T3",
+         "msg": "BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T4",
+         "msg": "BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T5",
+         "msg": "BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T6",
+         "msg": "BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T7",
+         "msg": "BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T8",
+         "msg": "BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T9",
+         "msg": "BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T10",
+         "msg": "BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved"
+      },{
+         "pri": 6,
+         "time":     0.367657,
+         "caller": "T11",
+         "msg": "ACPI: \\_SB_.PCI0.GP19.NHI1.PWRS: New power resource"
+      },{
+         "pri": 6,
+         "time":     0.368615,
+         "caller": "T12",
+         "msg": "ACPI: \\_SB_.PCI0.GP19.XHC4.PWRS: New power resource"
+      },{
+         "pri": 6,
+         "time":     0.376316,
+         "caller": "T13",
+         "msg": "ACPI: \\_SB_.PRWL: New power resource"
+      },{
+         "pri": 6,
+         "time":     0.376343,
+         "caller": "T14",
+         "msg": "ACPI: \\_SB_.PRWB: New power resource"
+      },{
+         "pri": 6,
+         "time":     0.377373,
+         "caller": "T15",
+         "msg": "ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])"
+      },{
+         "pri": 6,
+         "time":     0.377378,
+         "caller": "T16",
+         "msg": "acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]"
+      },{
+         "pri": 6,
+         "time":     0.377569,
+         "caller": "T17",
+         "msg": "acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]"
+      },{
+         "pri": 6,
+         "time":     0.377933,
+         "caller": "T18",
+         "msg": "acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]"
+      },{
+         "pri": 6,
+         "time":     0.378458,
+         "caller": "T19",
+         "msg": "PCI host bridge to bus 0000:00"
+      },{
+         "pri": 6,
+         "time":     0.378459,
+         "caller": "T20",
+         "msg": "pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]"
+      },{
+         "pri": 6,
+         "time":     0.378461,
+         "caller": "T21",
+         "msg": "pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]"
+      }
+   ]
+}
diff --git a/tests/expected/dmesg/limit-kmsg-printk-caller b/tests/expected/dmesg/limit-kmsg-printk-caller
new file mode 100644
index 000000000..2ea07d4c8
--- /dev/null
+++ b/tests/expected/dmesg/limit-kmsg-printk-caller
@@ -0,0 +1,11 @@
+[    0.367657] [    T11] ACPI: \_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+[    0.368615] [    T12] ACPI: \_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+[    0.376316] [    T13] ACPI: \_SB_.PRWL: New power resource
+[    0.376343] [    T14] ACPI: \_SB_.PRWB: New power resource
+[    0.377373] [    T15] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+[    0.377378] [    T16] acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+[    0.377569] [    T17] acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]
+[    0.377933] [    T18] acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+[    0.378458] [    T19] PCI host bridge to bus 0000:00
+[    0.378459] [    T20] pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]
+[    0.378461] [    T21] pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]
diff --git a/tests/ts/dmesg/colors-kmsg-printk-caller b/tests/ts/dmesg/colors-kmsg-printk-caller
new file mode 100755
index 000000000..513ca82d4
--- /dev/null
+++ b/tests/ts/dmesg/colors-kmsg-printk-caller
@@ -0,0 +1,29 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="colors-kmsg-prtk-caller"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+ts_inhibit_custom_colorscheme
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG --color=always -K $TS_SELF/kmsg-input-printk-caller -x >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/console-levels-kmsg-printk-caller b/tests/ts/dmesg/console-levels-kmsg-printk-caller
new file mode 100755
index 000000000..00b8b3681
--- /dev/null
+++ b/tests/ts/dmesg/console-levels-kmsg-printk-caller
@@ -0,0 +1,36 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="levels-kmsg-prtk-caller"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+for I in {-1..8}; do
+	$TS_HELPER_DMESG -K $TS_SELF/kmsg-input-printk-caller -l $I >> $TS_OUTPUT 2>/dev/null
+done
+
+$TS_HELPER_DMESG -K $TS_SELF/kmsg-input-printk-caller -l err+ >> $TS_OUTPUT 2>/dev/null
+$TS_HELPER_DMESG -K $TS_SELF/kmsg-input-printk-caller -l emerg+ >> $TS_OUTPUT 2>/dev/null
+$TS_HELPER_DMESG -K $TS_SELF/kmsg-input-printk-caller -l +err >> $TS_OUTPUT 2>/dev/null
+$TS_HELPER_DMESG -K $TS_SELF/kmsg-input-printk-caller -l +debug >> $TS_OUTPUT 2>/dev/null
+$TS_HELPER_DMESG -K $TS_SELF/kmsg-input-printk-caller -l + 2>> $TS_OUTPUT >/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/decode-kmsg-printk-caller b/tests/ts/dmesg/decode-kmsg-printk-caller
new file mode 100755
index 000000000..d05b9fb68
--- /dev/null
+++ b/tests/ts/dmesg/decode-kmsg-printk-caller
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="decode-kmsg-prtk-caller"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG -x -K $TS_SELF/kmsg-input-printk-caller >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/delta-kmsg-printk-caller b/tests/ts/dmesg/delta-kmsg-printk-caller
new file mode 100755
index 000000000..020b82357
--- /dev/null
+++ b/tests/ts/dmesg/delta-kmsg-printk-caller
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="delta-kmsg-prtk-caller"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG -d -K $TS_SELF/kmsg-input-printk-caller >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/facilities-kmsg-printk-caller b/tests/ts/dmesg/facilities-kmsg-printk-caller
new file mode 100755
index 000000000..bec301516
--- /dev/null
+++ b/tests/ts/dmesg/facilities-kmsg-printk-caller
@@ -0,0 +1,30 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="facilities-kmsg-prtk-caller"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+for I in {-1..12}; do
+	$TS_HELPER_DMESG -K $TS_SELF/kmsg-input-printk-caller -f $I -x >> $TS_OUTPUT 2>/dev/null
+done
+
+ts_finalize
diff --git a/tests/ts/dmesg/indentation-kmsg-printk-caller b/tests/ts/dmesg/indentation-kmsg-printk-caller
new file mode 100755
index 000000000..53e549b62
--- /dev/null
+++ b/tests/ts/dmesg/indentation-kmsg-printk-caller
@@ -0,0 +1,40 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="indentation-kmsg-prtk-caller"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG -K $TS_SELF/newlines-kmsg-printk-caller >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG -K $TS_SELF/newlines-kmsg-printk-caller -x >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=delta --kmsg-file $TS_SELF/newlines-kmsg-printk-caller >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=notime --kmsg-file $TS_SELF/newlines-kmsg-printk-caller >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=reltime --kmsg-file $TS_SELF/newlines-kmsg-printk-caller >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=ctime --kmsg-file $TS_SELF/newlines-kmsg-printk-caller >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=iso --kmsg-file $TS_SELF/newlines-kmsg-printk-caller >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+ts_finalize
diff --git a/tests/ts/dmesg/input-syslog-printk-caller b/tests/ts/dmesg/input-syslog-printk-caller
new file mode 100644
index 000000000..5fcff6abe
--- /dev/null
+++ b/tests/ts/dmesg/input-syslog-printk-caller
@@ -0,0 +1,105 @@
+<0>[    0.000000] [    T0] example[0]
+<1>[    1.000000] [    T1] example[1]
+<2>[    8.000000] [    T2] example[2]
+<3>[   27.000000] [    T3] example[3]
+<4>[   64.000000] [    T4] example[4]
+<5>[  125.000000] [    T5] example[5]
+<6>[  216.000000] [    T6] example[6]
+<7>[  343.000000] [    T7] example[7]
+<8>[  512.000000] [    T8] example[8]
+<9>[  729.000000] [    T9] example[9]
+<10>[ 1000.000000] [   T10] example[10]
+<11>[ 1331.000000] [   T11] example[11]
+<12>[ 1728.000000] [   T12] example[12]
+<13>[ 2197.000000] [   T13] example[13]
+<14>[ 2744.000000] [   T14] example[14]
+<15>[ 3375.000000] [   T15] example[15]
+<16>[ 4096.000000] [   T16] example[16]
+<17>[ 4913.000000] [   T17] example[17]
+<18>[ 5832.000000] [   T18] example[18]
+<19>[ 6859.000000] [   T19] example[19]
+<20>[ 8000.000000] [   T20] example[20]
+<21>[ 9261.000000] [   T21] example[21]
+<22>[10648.000000] [   T22] example[22]
+<23>[12167.000000] [   T23] example[23]
+<24>[13824.000000] [   T24] example[24]
+<25>[15625.000000] [   T25] example[25]
+<26>[17576.000000] [   T26] example[26]
+<27>[19683.000000] [   T27] example[27]
+<28>[21952.000000] [   T28] example[28]
+<29>[24389.000000] [   T29] example[29]
+<30>[27000.000000] [   T10] example[30]
+<31>[29791.000000] [   T31] example[31]
+<32>[32768.000000] [   T32] example[32]
+<33>[35937.000000] [   T33] example[33]
+<34>[39304.000000] [   T34] example[34]
+<35>[42875.000000] [   T35] example[35]
+<36>[46656.000000] [   T36] example[36]
+<37>[50653.000000] [   T37] example[37]
+<38>[54872.000000] [   T38] example[38]
+<39>[59319.000000] [   T39] example[39]
+<40>[64000.000000] [   T40] example[40]
+<41>[68921.000000] [   T41] example[41]
+<42>[74088.000000] [   T42] example[42]
+<43>[79507.000000] [   T43] example[43]
+<44>[85184.000000] [   T44] example[44]
+<45>[91125.000000] [   T45] example[45]
+<46>[97336.000000] [   T46] example[46]
+<47>[103823.000000] [   T47] example[47]
+<48>[110592.000000] [   T48] example[48]
+<49>[117649.000000] [   T49] example[49]
+<50>[125000.000000] [   T50] example[50]
+<51>[132651.000000] [   T51] example[51]
+<52>[140608.000000] [   T52] example[52]
+<53>[148877.000000] [   T53] example[53]
+<54>[157464.000000] [   T54] example[54]
+<55>[166375.000000] [   T55] example[55]
+<56>[175616.000000] [   T56] example[56]
+<57>[185193.000000] [   T57] example[57]
+<58>[195112.000000] [   T58] example[58]
+<59>[205379.000000] [   T59] example[59]
+<60>[216000.000000] [   T60] example[60]
+<61>[226981.000000] [   T61] example[61]
+<62>[238328.000000] [   T62] example[62]
+<63>[250047.000000] [   T63] example[63]
+<64>[262144.000000] [   T64] example[64]
+<65>[274625.000000] [   T65] example[65]
+<66>[287496.000000] [   T66] example[66]
+<67>[300763.000000] [   T67] example[67]
+<68>[314432.000000] [   T68] example[68]
+<69>[328509.000000] [   T69] example[69]
+<70>[343000.000000] [   T70] example[70]
+<71>[357911.000000] [   T71] example[71]
+<72>[373248.000000] [   T72] example[72]
+<73>[389017.000000] [   T73] example[73]
+<74>[405224.000000] [   T74] example[74]
+<75>[421875.000000] [   T75] example[75]
+<76>[438976.000000] [   T76] example[76]
+<77>[456533.000000] [   T77] example[77]
+<78>[474552.000000] [   T78] example[78]
+<79>[493039.000000] [   T79] example[79]
+<80>[512000.000000] [   T80] example[80]
+<81>[531441.000000] [   T81] example[81]
+<82>[551368.000000] [   T82] example[82]
+<83>[571787.000000] [   T83] example[83]
+<84>[592704.000000] [   T84] example[84]
+<85>[614125.000000] [   T85] example[85]
+<86>[636056.000000] [   T86] example[86]
+<87>[658503.000000] [   T87] example[87]
+<88>[681472.000000] [   T88] example[88]
+<89>[704969.000000] [   T89] example[89]
+<90>[729000.000000] [   T90] example[90]
+<91>[753571.000000] [   T91] example[91]
+<92>[778688.000000] [   T92] example[92]
+<93>[804357.000000] [   T93] example[93]
+<94>[830584.000000] [   T94] example[94]
+<95>[857375.000000] [   T95] example[95]
+<96>[884736.000000] [   T96] example[96]
+<97>[912673.000000] [   T97] example[97]
+<98>[941192.000000] [   T98] example[98]
+<99>[970299.000000] [   T99] example[99]
+<100>[1000000.000000] [  T100] example[100]
+<101>[1030301.000000] [  T101] example[101]
+<102>[1061208.000000] [  T102] example[102]
+<103>[1092727.000000] [  T103] example[103]
+<104>[1124864.000000] [  T104] example[104]
diff --git a/tests/ts/dmesg/json-kmsg-printk-caller b/tests/ts/dmesg/json-kmsg-printk-caller
new file mode 100755
index 000000000..cb6c5e4a8
--- /dev/null
+++ b/tests/ts/dmesg/json-kmsg-printk-caller
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="json-kmsg-prtk-caller"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG -J -K $TS_SELF/kmsg-input-printk-caller >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/json-syslog-printk-caller b/tests/ts/dmesg/json-syslog-printk-caller
new file mode 100755
index 000000000..10dfaa423
--- /dev/null
+++ b/tests/ts/dmesg/json-syslog-printk-caller
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="json-syslog-prtk-caller"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG -J -F $TS_SELF/input-syslog-printk-caller >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/kmsg-file-printk-caller b/tests/ts/dmesg/kmsg-file-printk-caller
new file mode 100755
index 000000000..a01fc723f
--- /dev/null
+++ b/tests/ts/dmesg/kmsg-file-printk-caller
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="kmsg-file-prtk-caller"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG -J -K $TS_SELF/kmsg-input-printk-caller >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/kmsg-input-printk-caller b/tests/ts/dmesg/kmsg-input-printk-caller
new file mode 100644
index 0000000000000000000000000000000000000000..8d67f11cad7988469dd5e4a7c8589d2b744168bb
GIT binary patch
literal 2187
zcmbW2TW{hx6oB`+zv4*yQZ$g-aqb9dAw>nL(1<WMu@wr5q0uIBlmsaMe(Z!%<LSbv
zlRV_&oX=m5?PI-*_}S}*L6Xp7utfdGINQI%ffi-VGB6ZF(Rx7<zTh5)+e9?}BOdF!
z4&3g-5N;n_w*#0cs)9j9DnS;)U3i#(h9u&x{5s-+Rh*O^P!$a;r~`jv@Mj))i}85o
zE!X$o=fm05g&E7bfHb(LVT}TW9MyKP4WAG{ZvHa5STe?am!)ZtMZlG)1928tMKt*L
zRS)+ei>MN(yY|bvJxI4@ul|L)xi~^toboE7hd88zJAS>(4k<+$&WTf=%8I5=6qjL8
zL{KnRHJ_wGp3~y4X%}XyWTy5<(<i@|7wiy6G=lu)RK`5fuo%vO$2uZ}NFk&Np_Ymq
zSfw-t^eTS4ee|SPHr;Nw&#*6pO+p1wlYrWFpuOc}8Mxs*4lHO%ivx`WQkRhWRV1!e
z+ekYQM9I;RfW|eTy?GCe&cL>#DIv|PNctWrvM4)R641H|6j_w>Xm5!~<TDIiZwm7-
zzR063A?@o(63R$TCHk+9SYEssT|x4A;}=U!)6d9uCN)C3#4rurY}Eyf`{GX=5bJ8~
zkJgIkPLcB9VOyC`rdaX5E_?^(^awdS(n8E1wlBhFN)n9|Ed%RqqI#M5ZQ^RbA?jUX
z8U!0{B6&w#e0{tu#TOq(XrztM{s%F-j4(OEB&LMW&j_9%Snyf_qau!W6jmZ*&u|;D
zG>9`^*ARl$W?%BV9-k?ldhrsgAzE!IqaTEM4Bp&BLu5I;BEtH~cO7{0q1@*=E2<J!
z<JXF2yw12R+r~Q>`rZuOgoXd{t50_+&G=U{e+uLK1x&nez2zyV<oO2t&m;f4zZ}m7
zqMIAIAAgy;<H0BK<h*s-_}RiwH|(~bdC4zNf@;f(6e31T$apT!y0G#mo;zVxp6t2m
zc=16E4G9gK&(ycA3tN{oc$zZCOFYY}f+ajvd?e`4&b`?f#IqaZ!6r`P>I9F=1>Ae?
zN1ZTtvNT;9I=e5X!3!%Z*fi6iV$cjaAI4@s(=@e-Y$sJk{XC4<txuhL=c$8#E-qNb
x49;7GD7oR*gkzjV>?paPL2n~_e!=^1N$^$A^$pxgsfs@$5!EG7)Tlp__yL<dZm0kN

literal 0
HcmV?d00001

diff --git a/tests/ts/dmesg/limit-kmsg-printk-caller b/tests/ts/dmesg/limit-kmsg-printk-caller
new file mode 100755
index 000000000..4d4d9912d
--- /dev/null
+++ b/tests/ts/dmesg/limit-kmsg-printk-caller
@@ -0,0 +1,29 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="limit-kmsg-prtk-caller"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG --since @1234567890.124 --until @1234567991 -K $TS_SELF/kmsg-input-printk-caller \
+	>> $TS_OUTPUT 2> $TS_ERRLOG
+
+ts_finalize
diff --git a/tests/ts/dmesg/newlines-kmsg-printk-caller b/tests/ts/dmesg/newlines-kmsg-printk-caller
new file mode 100644
index 0000000000000000000000000000000000000000..574d2177796677b73f1efcf273005169ed832c60
GIT binary patch
literal 152
zcmXrjF#tkco#e!voYW%Q5CiL+%)C^Es??%<E(Svb9YY;M128~RV`!b1TFwPh$Hia-
tQeuRm#K^j&Jf91MLCT7`7>o^cjC71K)EQfsWE7>QazV)4{GwE-1^{d2D<=Q|

literal 0
HcmV?d00001

-- 
2.43.0


^ permalink raw reply related

* [PATCH] util-linux/sys-utils dmesg add PRINTK_CALLER support
From: Edward Chron @ 2023-12-13  0:09 UTC (permalink / raw)
  To: util-linux; +Cc: colona, echron

Submission to Project: util-linux
Open Incident: #2609 at github.com/util-linux/util-linux/issues/2609
Component: util-linux/sys-utils
File: dmesg.c
Code level patch applied against: 2.39.3 - latest code pulled from
           git.github.com:util-linux/util-linux.git
Revision: #1 on 2023/12/08 per Review from Karel Zak
Revision: #2 on 2023/12/12 Adjust line offsets for master update and
                           Add caller_id_size init to dmesg -K and
                           Add support for required dmesg tests

Add support to standard dmesg command for the optional Linux Kernel
debug CONFIG option PRINTK_CALLER which adds an optional dmesg field
that contains the Thread Id or CPU Id that is issuing the printk to
add the message to the kernel ring buffer. This makes debugging simpler
as dmesg entries for a specific thread or CPU can be recognized.

The dmesg -S using the old syslog interface supports printing the
PRINTK_CALLER field but currently standard dmesg does not support
printing the field if present. There are utilities that use dmesg and
so it would be optimal if dmesg supported PRINTK_CALLER as well.

The additional field provided by PRINTK_CALLER is only present
if it was configured for the Linux kernel where the dmesg command
is run. It is a debug option and not configured by default so the
dmesg output will only change for those kernels where the option was
configured when the kernel was built. For users who went to the
trouble to configure PRINTK_CALLER and have the extra field available
for debugging, having dmesg print the field is very helpful.

Size of the PRINTK_CALLER field is determined by the maximum number
tasks that can be run on the system which is limited by the value of
/proc/sys/kernel/pid_max as pid values are from 0 to value - 1.
This value determines the number of id digits needed by the caller id.
The PRINTK_CALLER field is printed as T<id> for a Task Id or C<id>
for a CPU Id for a printk in CPU context. The values are left space
padded and enclosed in parentheses such as: [    T123] or [     C16]

For consistency with dmesg -S which supports the PRINTK_CALLER field
the field is printed followed by a space. For JSON format output the
PRINTK_CALLER field is identified as caller as that is consistent with
it's naming in /dev/kmsg. No space padding is used to reduce space
consumed by the JSON output. So the output from the command on a system
with PRINTK_CALLER field enabled in the Linux .config file the dmesg
output appears as:

> dmesg
...
[  520.897104] [   T3919] usb 3-3: Product: USB 2.0 Hub

and

> dmesg -x
...
kern  :info  : [  520.897104] [   T3919] usb 3-3: Product: USB 2.0 Hub

and

> dmesg -J
...
      },{
         "pri": 6,
         "time":    520.897104,
         "caller": "T3919",
         "msg": "usb 3-3: Product: USB 2.0 Hub"
      },{

and

> dmesg -J -x
...
      },{
         "fac": "kern",
         "pri": "info",
         "time":   520.897104,
         "caller": "T3919",
         "msg": "usb 3-3: Product: USB 2.0 Hub"
      },{

>

For comparison:

> dmesg -S
...
[  520.897104] [ T3919] usb 3-3: Product: USB 2.0 Hub

and

> dmesg -S -x
...
kern  :info  : [  520.897104] [ T3919] usb 3-3: Product: USB 2.0 Hub

Note: When dmesg uses the old syslog interface the reserved space for
      the PRINTK_CALLER field is capped at 5 digits because 32-bit
      kernels are capped at 32768 as the max number of PIDs. However,
      64-bit systems are currently capped at 2^22 PIDs (0 - 4194303).
      The PID cap is set by PID_MAX_LIMIT but the system limit can be
      less so we use /proc/sys/kernel/pid_max to determine the size
      needed to hold the maximum PID value size for the current system.
      Many 64-bit systems support 2^22 PIDs (0 - 4194303) and you see:

> dmesg -x
...
kern  :info  : [  520.899558] [   T3919] hub 3-3:1.0: USB hub found
...
kern  :info  : [ 9830.456898] [  T98982] cgroup: fork rejected by pids ...
kern  :info  : [14301.158878] [ T137336] cgroup: fork rejected by pids ...
kern  :info  : [18980.803190] [T1637865] cgroup: fork rejected by pids ...

> dmesg -S -x
...
kern  :info  : [  520.899558] [ T3919] hub 3-3:1.0: USB hub found
...
kern  :info  : [ 9830.456898] [T98982] cgroup: fork rejected by pids ...
kern  :info  : [14301.158878] [T137336] cgroup: fork rejected by pids ...
kern  :info  : [18980.803190] [T1637865] cgroup: fork rejected by pids ...

This is the only difference seen with PRINTK_CALLER configured and
printing between the dmesg /dev/kmsg interface and the dmesg -S syslog
interface.

Signed-off-by: Ivan Delalande <colona@arista.com>
Signed-off-by: Edward Chron <echron@arista.com>
---
 include/pathnames.h                           |   3 +
 sys-utils/dmesg.c                             | 114 +++-
 .../expected/dmesg/colors-kmsg-printk-caller  |  22 +
 .../dmesg/console-levels-kmsg-printk-caller   |  45 ++
 .../expected/dmesg/decode-kmsg-printk-caller  |  22 +
 tests/expected/dmesg/delta-kmsg-printk-caller |  22 +
 .../dmesg/facilities-kmsg-printk-caller       |  22 +
 .../dmesg/indentation-kmsg-printk-caller      |  28 +
 tests/expected/dmesg/json-kmsg-printk-caller  | 115 ++++
 .../expected/dmesg/json-syslog-printk-caller  | 530 ++++++++++++++++++
 tests/expected/dmesg/kmsg-file-printk-caller  | 115 ++++
 tests/expected/dmesg/limit-kmsg-printk-caller |  11 +
 tests/ts/dmesg/colors-kmsg-printk-caller      |  29 +
 .../dmesg/console-levels-kmsg-printk-caller   |  36 ++
 tests/ts/dmesg/decode-kmsg-printk-caller      |  28 +
 tests/ts/dmesg/delta-kmsg-printk-caller       |  28 +
 tests/ts/dmesg/facilities-kmsg-printk-caller  |  30 +
 tests/ts/dmesg/indentation-kmsg-printk-caller |  40 ++
 tests/ts/dmesg/input-syslog-printk-caller     | 105 ++++
 tests/ts/dmesg/json-kmsg-printk-caller        |  28 +
 tests/ts/dmesg/json-syslog-printk-caller      |  28 +
 tests/ts/dmesg/kmsg-file-printk-caller        |  28 +
 tests/ts/dmesg/kmsg-input-printk-caller       | Bin 0 -> 2187 bytes
 tests/ts/dmesg/limit-kmsg-printk-caller       |  29 +
 tests/ts/dmesg/newlines-kmsg-printk-caller    | Bin 0 -> 152 bytes
 25 files changed, 1457 insertions(+), 1 deletion(-)
 create mode 100644 tests/expected/dmesg/colors-kmsg-printk-caller
 create mode 100644 tests/expected/dmesg/console-levels-kmsg-printk-caller
 create mode 100644 tests/expected/dmesg/decode-kmsg-printk-caller
 create mode 100644 tests/expected/dmesg/delta-kmsg-printk-caller
 create mode 100644 tests/expected/dmesg/facilities-kmsg-printk-caller
 create mode 100644 tests/expected/dmesg/indentation-kmsg-printk-caller
 create mode 100644 tests/expected/dmesg/json-kmsg-printk-caller
 create mode 100644 tests/expected/dmesg/json-syslog-printk-caller
 create mode 100644 tests/expected/dmesg/kmsg-file-printk-caller
 create mode 100644 tests/expected/dmesg/limit-kmsg-printk-caller
 create mode 100755 tests/ts/dmesg/colors-kmsg-printk-caller
 create mode 100755 tests/ts/dmesg/console-levels-kmsg-printk-caller
 create mode 100755 tests/ts/dmesg/decode-kmsg-printk-caller
 create mode 100755 tests/ts/dmesg/delta-kmsg-printk-caller
 create mode 100755 tests/ts/dmesg/facilities-kmsg-printk-caller
 create mode 100755 tests/ts/dmesg/indentation-kmsg-printk-caller
 create mode 100644 tests/ts/dmesg/input-syslog-printk-caller
 create mode 100755 tests/ts/dmesg/json-kmsg-printk-caller
 create mode 100755 tests/ts/dmesg/json-syslog-printk-caller
 create mode 100755 tests/ts/dmesg/kmsg-file-printk-caller
 create mode 100644 tests/ts/dmesg/kmsg-input-printk-caller
 create mode 100755 tests/ts/dmesg/limit-kmsg-printk-caller
 create mode 100644 tests/ts/dmesg/newlines-kmsg-printk-caller

diff --git a/include/pathnames.h b/include/pathnames.h
index caf0e63d4..81fa405f6 100644
--- a/include/pathnames.h
+++ b/include/pathnames.h
@@ -230,4 +230,7 @@
 /* cgroup path */
 #define _PATH_SYS_CGROUP	"/sys/fs/cgroup"
 
+/* Maximum number of PIDs system supports */
+#define _PATH_PROC_PIDMAX	"/proc/sys/kernel/pid_max"
+
 #endif /* PATHNAMES_H */
diff --git a/sys-utils/dmesg.c b/sys-utils/dmesg.c
index 77728b419..5a04af3e6 100644
--- a/sys-utils/dmesg.c
+++ b/sys-utils/dmesg.c
@@ -13,7 +13,9 @@
  */
 #include <stdio.h>
 #include <getopt.h>
+#include <stdbool.h>
 #include <stdlib.h>
+#include <string.h>
 #include <sys/klog.h>
 #include <sys/syslog.h>
 #include <sys/time.h>
@@ -41,6 +43,7 @@
 #include "mangle.h"
 #include "pager.h"
 #include "jsonwrt.h"
+#include "pathnames.h"
 
 /* Close the log.  Currently a NOP. */
 #define SYSLOG_ACTION_CLOSE          0
@@ -65,6 +68,11 @@
 /* Return size of the log buffer */
 #define SYSLOG_ACTION_SIZE_BUFFER   10
 
+#define PID_CHARS_MAX sizeof(stringify_value(LONG_MAX))
+#define PID_CHARS_DEFAULT sizeof(stringify_value(INT_MAX))
+#define DMESG_CALLER_PREFIX "caller="
+#define DMESG_CALLER_PREFIXSZ (sizeof(DMESG_CALLER_PREFIX)-1)
+
 /*
  * Color scheme
  */
@@ -233,6 +241,7 @@ struct dmesg_control {
 			force_prefix:1;	/* force timestamp and decode prefix
 					   on each line */
 	int		indent;		/* due to timestamps if newline */
+	size_t          caller_id_size;   /* PRINTK_CALLERID max field size */
 };
 
 struct dmesg_record {
@@ -242,6 +251,7 @@ struct dmesg_record {
 	int		level;
 	int		facility;
 	struct timeval  tv;
+	char		caller_id[PID_CHARS_MAX];
 
 	const char	*next;		/* buffer with next unparsed record */
 	size_t		next_size;	/* size of the next buffer */
@@ -254,6 +264,7 @@ struct dmesg_record {
 		(_r)->level = -1; \
 		(_r)->tv.tv_sec = 0; \
 		(_r)->tv.tv_usec = 0; \
+		(_r)->caller_id[0] = 0; \
 	} while (0)
 
 static int process_kmsg(struct dmesg_control *ctl);
@@ -551,6 +562,45 @@ static int get_syslog_buffer_size(void)
 	return n > 0 ? n : 0;
 }
 
+/*
+ * Get the number of characters needed to hold the maximum number
+ * of tasks this system supports. This size of string could hold
+ * a thread id large enough for the highest thread id.
+ * This is needed to determine the number of characters reserved for
+ * the PRINTK_CALLER field if it has been configured in the Linux Kernel.
+ *
+ * The number of digits sets the max value since the value can't exceed
+ * a value of that size. The /proc field defined by _PATH_PROC_PIDMAX
+ * holds the maximum number of PID values that may be ussed by the system,
+ * so 0 to that value minus one.
+ *
+ * For determining the size of the PRINTK_CALLER field, we make the safe
+ * assumption that the number of threads >= number of cpus. This because
+ * the PRINTK_CALLER field can hold either a thread id or a CPU id value.
+ *
+ * If we can't access the pid max kernel proc entry we assign a default
+ * field size of 5 characters as that is what the old syslog interface
+ * uses as the reserved field size. This is justified because 32-bit Linux
+ * systems are limited to PID values between (0-32767).
+ *
+ */
+static size_t max_threads_id_size(void)
+{
+	char taskmax[PID_CHARS_MAX] = {'\0'};
+	ssize_t rdsize;
+	int fd;
+
+	fd = open(_PATH_PROC_PIDMAX, O_RDONLY);
+	if (fd == -1)
+		return PID_CHARS_DEFAULT;
+
+	rdsize = read(fd, taskmax, sizeof(taskmax));
+	if (rdsize == -1)
+		return PID_CHARS_DEFAULT;
+
+	return strnlen(taskmax, sizeof(taskmax));
+}
+
 /*
  * Reads messages from regular file by mmap
  */
@@ -728,6 +778,36 @@ static const char *skip_item(const char *begin, const char *end, const char *sep
 	return begin;
 }
 
+/*
+ * Checks to see if the caller (caller id) field is present in the kmsg record.
+ * This is true if the PRINTK_CALLER config option has been set in the kernel.
+ *
+ * If the caller_id is found in the kmsg buffer then return the id and id type
+ * to the caller in dmesg caller_id. Returns string pointer to next value.
+ *
+ */
+static const char *parse_callerid(const char *p_str, const char *end,
+				  struct dmesg_record *p_drec)
+{
+	const char *p_after;
+	const char *p_next;
+	size_t cid_size;
+	char *p_cid;
+
+	p_cid = strstr(p_str, DMESG_CALLER_PREFIX);
+	if (p_cid != NULL && p_drec != NULL) {
+		p_next = p_cid + DMESG_CALLER_PREFIXSZ;
+		p_after = skip_item(p_next, end, ",;");
+		cid_size = p_after - p_next;
+		if (cid_size < sizeof(p_drec->caller_id))
+			xstrncpy(p_drec->caller_id, p_next, cid_size);
+		else
+			return p_str;
+		return p_after;
+	}
+	return p_str;
+}
+
 /*
  * Parses one record from syslog(2) buffer
  */
@@ -795,6 +875,18 @@ static int get_next_syslog_record(struct dmesg_control *ctl,
 				begin++;
 		}
 
+		if (*begin == '[' && (*(begin + 1) == ' ' ||
+			(*(begin + 1) == 'T' || *(begin + 1) == 'C'))) {
+			const char *start = begin + 1;
+			size_t id_size;
+
+			start = start + strspn(start, " ");
+			begin = skip_item(begin, end, "]");
+			id_size = begin - start;
+			if (id_size < sizeof(rec->caller_id))
+				xstrncpy(rec->caller_id, start, id_size);
+		}
+
 		rec->mesg = begin;
 		rec->mesg_size = end - begin;
 
@@ -1101,6 +1193,19 @@ full_output:
 			color_disable();
 	}
 
+	if (*rec->caller_id) {
+		if (ctl->json) {
+			ul_jsonwrt_value_s(&ctl->jfmt, "caller", rec->caller_id);
+		} else {
+			char cidbuf[PID_CHARS_MAX+3] = {'\0'};
+
+			sprintf(cidbuf, "[%*s] ",
+				(char)ctl->caller_id_size - 1, rec->caller_id);
+			ctl->indent += strnlen(cidbuf, PID_CHARS_MAX+3);
+			fputs(cidbuf, stdout);
+		}
+	}
+
 	/*
 	 * A kernel message may contain several lines of output, separated
 	 * by '\n'.  If the timestamp and decode outputs are forced then each
@@ -1229,6 +1334,8 @@ static int init_kmsg(struct dmesg_control *ctl)
 		return -1;
 	}
 
+	ctl->caller_id_size = max_threads_id_size();
+
 	return 0;
 }
 
@@ -1284,7 +1391,10 @@ static int parse_kmsg_record(struct dmesg_control *ctl,
 		goto mesg;
 
 	/* D) optional fields (ignore) */
-	p = skip_item(p, end, ";");
+	p = skip_item(p, end, ",;");
+
+	/* Include optional PRINTK_CALLER field if it is present */
+	p = parse_callerid(p, end, rec);
 
 mesg:
 	/* E) message text */
@@ -1446,6 +1556,7 @@ int main(int argc, char *argv[])
 		.kmsg = -1,
 		.time_fmt = DMESG_TIMEFTM_TIME,
 		.indent = 0,
+		.caller_id_size = 0,
 	};
 	int colormode = UL_COLORMODE_UNDEF;
 	enum {
@@ -1542,6 +1653,7 @@ int main(int argc, char *argv[])
 		case 'K':
 			ctl.filename = optarg;
 			ctl.method = DMESG_METHOD_KMSG;
+			ctl.caller_id_size = max_threads_id_size();
 			break;
 		case 'f':
 			ctl.fltr_fac = 1;
diff --git a/tests/expected/dmesg/colors-kmsg-printk-caller b/tests/expected/dmesg/colors-kmsg-printk-caller
new file mode 100644
index 000000000..c7bf6e8b7
--- /dev/null
+++ b/tests/expected/dmesg/colors-kmsg-printk-caller
@@ -0,0 +1,22 @@
+kern  :notice: ^[[32m[    0.000000] ^[[0m[     T0] Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000
+kern  :info  : ^[[32m[    0.000000] ^[[0m[     T1] ^[[33mCommand line: ^[[0minitrd=\ucode.img initrd=\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system
+kern  :info  : ^[[32m[    0.000000] ^[[0m[     T2] BIOS-provided physical RAM map:
+kern  :info  : ^[[32m[    0.000000] ^[[0m[     T3] ^[[33mBIOS-e820: ^[[0m[mem 0x0000000000000000-0x000000000009efff] usable
+kern  :info  : ^[[32m[    0.000000] ^[[0m[     T4] ^[[33mBIOS-e820: ^[[0m[mem 0x000000000009f000-0x00000000000bffff] reserved
+kern  :info  : ^[[32m[    0.000000] ^[[0m[     T5] ^[[33mBIOS-e820: ^[[0m[mem 0x0000000000100000-0x0000000009afffff] usable
+kern  :info  : ^[[32m[    0.000000] ^[[0m[     T6] ^[[33mBIOS-e820: ^[[0m[mem 0x0000000009b00000-0x0000000009dfffff] reserved
+kern  :info  : ^[[32m[    0.000000] ^[[0m[     T7] ^[[33mBIOS-e820: ^[[0m[mem 0x0000000009e00000-0x0000000009efffff] usable
+kern  :info  : ^[[32m[    0.000000] ^[[0m[     T8] ^[[33mBIOS-e820: ^[[0m[mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS
+kern  :info  : ^[[32m[    0.000000] ^[[0m[     T9] ^[[33mBIOS-e820: ^[[0m[mem 0x0000000009f3c000-0x000000004235ffff] usable
+kern  :info  : ^[[32m[    0.000000] ^[[0m[    T10] ^[[33mBIOS-e820: ^[[0m[mem 0x0000000042360000-0x000000004455ffff] reserved
+kern  :info  : ^[[32m[    0.367657] ^[[0m[    T11] ^[[33mACPI: ^[[0m\_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+kern  :info  : ^[[32m[    0.368615] ^[[0m[    T12] ^[[33mACPI: ^[[0m\_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+kern  :info  : ^[[32m[    0.376316] ^[[0m[    T13] ^[[33mACPI: ^[[0m\_SB_.PRWL: New power resource
+kern  :info  : ^[[32m[    0.376343] ^[[0m[    T14] ^[[33mACPI: ^[[0m\_SB_.PRWB: New power resource
+kern  :info  : ^[[32m[    0.377373] ^[[0m[    T15] ^[[33mACPI: ^[[0mPCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+kern  :info  : ^[[32m[    0.377378] ^[[0m[    T16] ^[[33macpi PNP0A08:00: ^[[0m_OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+kern  :info  : ^[[32m[    0.377569] ^[[0m[    T17] ^[[33macpi PNP0A08:00: ^[[0m_OSC: platform does not support [SHPCHotplug AER]
+kern  :info  : ^[[32m[    0.377933] ^[[0m[    T18] ^[[33macpi PNP0A08:00: ^[[0m_OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+kern  :info  : ^[[32m[    0.378458] ^[[0m[    T19] PCI host bridge to bus 0000:00
+kern  :info  : ^[[32m[    0.378459] ^[[0m[    T20] ^[[33mpci_bus 0000:00: ^[[0mroot bus resource [io  0x0000-0x0cf7 window]
+kern  :info  : ^[[32m[    0.378461] ^[[0m[    T21] ^[[33mpci_bus 0000:00: ^[[0mroot bus resource [io  0x0d00-0xffff window]
diff --git a/tests/expected/dmesg/console-levels-kmsg-printk-caller b/tests/expected/dmesg/console-levels-kmsg-printk-caller
new file mode 100644
index 000000000..1f6e9f178
--- /dev/null
+++ b/tests/expected/dmesg/console-levels-kmsg-printk-caller
@@ -0,0 +1,45 @@
+[    0.000000] [     T0] Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000
+[    0.000000] [     T1] Command line: initrd=\ucode.img initrd=\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system
+[    0.000000] [     T2] BIOS-provided physical RAM map:
+[    0.000000] [     T3] BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable
+[    0.000000] [     T4] BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved
+[    0.000000] [     T5] BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable
+[    0.000000] [     T6] BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved
+[    0.000000] [     T7] BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable
+[    0.000000] [     T8] BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS
+[    0.000000] [     T9] BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable
+[    0.000000] [    T10] BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved
+[    0.367657] [    T11] ACPI: \_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+[    0.368615] [    T12] ACPI: \_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+[    0.376316] [    T13] ACPI: \_SB_.PRWL: New power resource
+[    0.376343] [    T14] ACPI: \_SB_.PRWB: New power resource
+[    0.377373] [    T15] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+[    0.377378] [    T16] acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+[    0.377569] [    T17] acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]
+[    0.377933] [    T18] acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+[    0.378458] [    T19] PCI host bridge to bus 0000:00
+[    0.378459] [    T20] pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]
+[    0.378461] [    T21] pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]
+[    0.000000] [     T0] Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000
+[    0.000000] [     T1] Command line: initrd=\ucode.img initrd=\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system
+[    0.000000] [     T2] BIOS-provided physical RAM map:
+[    0.000000] [     T3] BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable
+[    0.000000] [     T4] BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved
+[    0.000000] [     T5] BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable
+[    0.000000] [     T6] BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved
+[    0.000000] [     T7] BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable
+[    0.000000] [     T8] BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS
+[    0.000000] [     T9] BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable
+[    0.000000] [    T10] BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved
+[    0.367657] [    T11] ACPI: \_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+[    0.368615] [    T12] ACPI: \_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+[    0.376316] [    T13] ACPI: \_SB_.PRWL: New power resource
+[    0.376343] [    T14] ACPI: \_SB_.PRWB: New power resource
+[    0.377373] [    T15] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+[    0.377378] [    T16] acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+[    0.377569] [    T17] acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]
+[    0.377933] [    T18] acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+[    0.378458] [    T19] PCI host bridge to bus 0000:00
+[    0.378459] [    T20] pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]
+[    0.378461] [    T21] pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]
+test_dmesg: unknown level '+'
diff --git a/tests/expected/dmesg/decode-kmsg-printk-caller b/tests/expected/dmesg/decode-kmsg-printk-caller
new file mode 100644
index 000000000..78c363389
--- /dev/null
+++ b/tests/expected/dmesg/decode-kmsg-printk-caller
@@ -0,0 +1,22 @@
+kern  :notice: [    0.000000] [     T0] Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000
+kern  :info  : [    0.000000] [     T1] Command line: initrd=\ucode.img initrd=\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system
+kern  :info  : [    0.000000] [     T2] BIOS-provided physical RAM map:
+kern  :info  : [    0.000000] [     T3] BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable
+kern  :info  : [    0.000000] [     T4] BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved
+kern  :info  : [    0.000000] [     T5] BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable
+kern  :info  : [    0.000000] [     T6] BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved
+kern  :info  : [    0.000000] [     T7] BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable
+kern  :info  : [    0.000000] [     T8] BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS
+kern  :info  : [    0.000000] [     T9] BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable
+kern  :info  : [    0.000000] [    T10] BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved
+kern  :info  : [    0.367657] [    T11] ACPI: \_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+kern  :info  : [    0.368615] [    T12] ACPI: \_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+kern  :info  : [    0.376316] [    T13] ACPI: \_SB_.PRWL: New power resource
+kern  :info  : [    0.376343] [    T14] ACPI: \_SB_.PRWB: New power resource
+kern  :info  : [    0.377373] [    T15] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+kern  :info  : [    0.377378] [    T16] acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+kern  :info  : [    0.377569] [    T17] acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]
+kern  :info  : [    0.377933] [    T18] acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+kern  :info  : [    0.378458] [    T19] PCI host bridge to bus 0000:00
+kern  :info  : [    0.378459] [    T20] pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]
+kern  :info  : [    0.378461] [    T21] pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]
diff --git a/tests/expected/dmesg/delta-kmsg-printk-caller b/tests/expected/dmesg/delta-kmsg-printk-caller
new file mode 100644
index 000000000..892d2dcea
--- /dev/null
+++ b/tests/expected/dmesg/delta-kmsg-printk-caller
@@ -0,0 +1,22 @@
+[    0.000000 <    0.000000>] [     T0] Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000
+[    0.000000 <    0.000000>] [     T1] Command line: initrd=\ucode.img initrd=\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system
+[    0.000000 <    0.000000>] [     T2] BIOS-provided physical RAM map:
+[    0.000000 <    0.000000>] [     T3] BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable
+[    0.000000 <    0.000000>] [     T4] BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved
+[    0.000000 <    0.000000>] [     T5] BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable
+[    0.000000 <    0.000000>] [     T6] BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved
+[    0.000000 <    0.000000>] [     T7] BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable
+[    0.000000 <    0.000000>] [     T8] BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS
+[    0.000000 <    0.000000>] [     T9] BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable
+[    0.000000 <    0.000000>] [    T10] BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved
+[    0.367657 <    0.000000>] [    T11] ACPI: \_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+[    0.368615 <    0.000000>] [    T12] ACPI: \_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+[    0.376316 <    0.000000>] [    T13] ACPI: \_SB_.PRWL: New power resource
+[    0.376343 <    0.000000>] [    T14] ACPI: \_SB_.PRWB: New power resource
+[    0.377373 <    0.000000>] [    T15] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+[    0.377378 <    0.000000>] [    T16] acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+[    0.377569 <    0.000000>] [    T17] acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]
+[    0.377933 <    0.000000>] [    T18] acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+[    0.378458 <    0.000000>] [    T19] PCI host bridge to bus 0000:00
+[    0.378459 <    0.000000>] [    T20] pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]
+[    0.378461 <    0.000000>] [    T21] pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]
diff --git a/tests/expected/dmesg/facilities-kmsg-printk-caller b/tests/expected/dmesg/facilities-kmsg-printk-caller
new file mode 100644
index 000000000..78c363389
--- /dev/null
+++ b/tests/expected/dmesg/facilities-kmsg-printk-caller
@@ -0,0 +1,22 @@
+kern  :notice: [    0.000000] [     T0] Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000
+kern  :info  : [    0.000000] [     T1] Command line: initrd=\ucode.img initrd=\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system
+kern  :info  : [    0.000000] [     T2] BIOS-provided physical RAM map:
+kern  :info  : [    0.000000] [     T3] BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable
+kern  :info  : [    0.000000] [     T4] BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved
+kern  :info  : [    0.000000] [     T5] BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable
+kern  :info  : [    0.000000] [     T6] BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved
+kern  :info  : [    0.000000] [     T7] BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable
+kern  :info  : [    0.000000] [     T8] BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS
+kern  :info  : [    0.000000] [     T9] BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable
+kern  :info  : [    0.000000] [    T10] BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved
+kern  :info  : [    0.367657] [    T11] ACPI: \_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+kern  :info  : [    0.368615] [    T12] ACPI: \_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+kern  :info  : [    0.376316] [    T13] ACPI: \_SB_.PRWL: New power resource
+kern  :info  : [    0.376343] [    T14] ACPI: \_SB_.PRWB: New power resource
+kern  :info  : [    0.377373] [    T15] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+kern  :info  : [    0.377378] [    T16] acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+kern  :info  : [    0.377569] [    T17] acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]
+kern  :info  : [    0.377933] [    T18] acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+kern  :info  : [    0.378458] [    T19] PCI host bridge to bus 0000:00
+kern  :info  : [    0.378459] [    T20] pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]
+kern  :info  : [    0.378461] [    T21] pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]
diff --git a/tests/expected/dmesg/indentation-kmsg-printk-caller b/tests/expected/dmesg/indentation-kmsg-printk-caller
new file mode 100644
index 000000000..47ad73f27
--- /dev/null
+++ b/tests/expected/dmesg/indentation-kmsg-printk-caller
@@ -0,0 +1,28 @@
+[    0.000000] [     T0] line zero
+[    1.000000] [     T1] new
+[    2.000000] [     T2] two
+[    3.000000] [     T3] three
+kern  :notice: [    0.000000] [     T0] line zero
+user  :crit  : [    1.000000] [     T1] new
+mail  :warn  : [    2.000000] [     T2] two
+daemon:info  : [    3.000000] [     T3] three
+[<    0.000000>] [     T0] line zero
+[<    0.000000>] [     T1] new
+[<    1.000000>] [     T2] two
+[<    1.000000>] [     T3] three
+[     T0] line zero
+[     T1] new
+[     T2] two
+[     T3] three
+[Feb13 23:31] [     T0] line zero
+[  +0.000000] [     T1] new
+[  +1.000000] [     T2] two
+[  +1.000000] [     T3] three
+[Fri Feb 13 23:31:30 2009] [     T0] line zero
+[Fri Feb 13 23:31:31 2009] [     T1] new
+[Fri Feb 13 23:31:32 2009] [     T2] two
+[Fri Feb 13 23:31:33 2009] [     T3] three
+2009-02-13T23:31:30,123456+00:00 [     T0] line zero
+2009-02-13T23:31:31,123456+00:00 [     T1] new
+2009-02-13T23:31:32,123456+00:00 [     T2] two
+2009-02-13T23:31:33,123456+00:00 [     T3] three
diff --git a/tests/expected/dmesg/json-kmsg-printk-caller b/tests/expected/dmesg/json-kmsg-printk-caller
new file mode 100644
index 000000000..785d730a5
--- /dev/null
+++ b/tests/expected/dmesg/json-kmsg-printk-caller
@@ -0,0 +1,115 @@
+{
+   "dmesg": [
+      {
+         "pri": 5,
+         "time":     0.000000,
+         "caller": "T0",
+         "msg": "Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T1",
+         "msg": "Command line: initrd=\\ucode.img initrd=\\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T2",
+         "msg": "BIOS-provided physical RAM map:"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T3",
+         "msg": "BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T4",
+         "msg": "BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T5",
+         "msg": "BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T6",
+         "msg": "BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T7",
+         "msg": "BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T8",
+         "msg": "BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T9",
+         "msg": "BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T10",
+         "msg": "BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved"
+      },{
+         "pri": 6,
+         "time":     0.367657,
+         "caller": "T11",
+         "msg": "ACPI: \\_SB_.PCI0.GP19.NHI1.PWRS: New power resource"
+      },{
+         "pri": 6,
+         "time":     0.368615,
+         "caller": "T12",
+         "msg": "ACPI: \\_SB_.PCI0.GP19.XHC4.PWRS: New power resource"
+      },{
+         "pri": 6,
+         "time":     0.376316,
+         "caller": "T13",
+         "msg": "ACPI: \\_SB_.PRWL: New power resource"
+      },{
+         "pri": 6,
+         "time":     0.376343,
+         "caller": "T14",
+         "msg": "ACPI: \\_SB_.PRWB: New power resource"
+      },{
+         "pri": 6,
+         "time":     0.377373,
+         "caller": "T15",
+         "msg": "ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])"
+      },{
+         "pri": 6,
+         "time":     0.377378,
+         "caller": "T16",
+         "msg": "acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]"
+      },{
+         "pri": 6,
+         "time":     0.377569,
+         "caller": "T17",
+         "msg": "acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]"
+      },{
+         "pri": 6,
+         "time":     0.377933,
+         "caller": "T18",
+         "msg": "acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]"
+      },{
+         "pri": 6,
+         "time":     0.378458,
+         "caller": "T19",
+         "msg": "PCI host bridge to bus 0000:00"
+      },{
+         "pri": 6,
+         "time":     0.378459,
+         "caller": "T20",
+         "msg": "pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]"
+      },{
+         "pri": 6,
+         "time":     0.378461,
+         "caller": "T21",
+         "msg": "pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]"
+      }
+   ]
+}
diff --git a/tests/expected/dmesg/json-syslog-printk-caller b/tests/expected/dmesg/json-syslog-printk-caller
new file mode 100644
index 000000000..40c98aa67
--- /dev/null
+++ b/tests/expected/dmesg/json-syslog-printk-caller
@@ -0,0 +1,530 @@
+{
+   "dmesg": [
+      {
+         "pri": 0,
+         "time":     0.000000,
+         "caller": "T0",
+         "msg": " example[0]"
+      },{
+         "pri": 1,
+         "time":     1.000000,
+         "caller": "T1",
+         "msg": " example[1]"
+      },{
+         "pri": 2,
+         "time":     8.000000,
+         "caller": "T2",
+         "msg": " example[2]"
+      },{
+         "pri": 3,
+         "time":    27.000000,
+         "caller": "T3",
+         "msg": " example[3]"
+      },{
+         "pri": 4,
+         "time":    64.000000,
+         "caller": "T4",
+         "msg": " example[4]"
+      },{
+         "pri": 5,
+         "time":   125.000000,
+         "caller": "T5",
+         "msg": " example[5]"
+      },{
+         "pri": 6,
+         "time":   216.000000,
+         "caller": "T6",
+         "msg": " example[6]"
+      },{
+         "pri": 7,
+         "time":   343.000000,
+         "caller": "T7",
+         "msg": " example[7]"
+      },{
+         "pri": 8,
+         "time":   512.000000,
+         "caller": "T8",
+         "msg": " example[8]"
+      },{
+         "pri": 9,
+         "time":   729.000000,
+         "caller": "T9",
+         "msg": " example[9]"
+      },{
+         "pri": 10,
+         "time":  1000.000000,
+         "caller": "T10",
+         "msg": " example[10]"
+      },{
+         "pri": 11,
+         "time":  1331.000000,
+         "caller": "T11",
+         "msg": " example[11]"
+      },{
+         "pri": 12,
+         "time":  1728.000000,
+         "caller": "T12",
+         "msg": " example[12]"
+      },{
+         "pri": 13,
+         "time":  2197.000000,
+         "caller": "T13",
+         "msg": " example[13]"
+      },{
+         "pri": 14,
+         "time":  2744.000000,
+         "caller": "T14",
+         "msg": " example[14]"
+      },{
+         "pri": 15,
+         "time":  3375.000000,
+         "caller": "T15",
+         "msg": " example[15]"
+      },{
+         "pri": 16,
+         "time":  4096.000000,
+         "caller": "T16",
+         "msg": " example[16]"
+      },{
+         "pri": 17,
+         "time":  4913.000000,
+         "caller": "T17",
+         "msg": " example[17]"
+      },{
+         "pri": 18,
+         "time":  5832.000000,
+         "caller": "T18",
+         "msg": " example[18]"
+      },{
+         "pri": 19,
+         "time":  6859.000000,
+         "caller": "T19",
+         "msg": " example[19]"
+      },{
+         "pri": 20,
+         "time":  8000.000000,
+         "caller": "T20",
+         "msg": " example[20]"
+      },{
+         "pri": 21,
+         "time":  9261.000000,
+         "caller": "T21",
+         "msg": " example[21]"
+      },{
+         "pri": 22,
+         "time": 10648.000000,
+         "caller": "T22",
+         "msg": " example[22]"
+      },{
+         "pri": 23,
+         "time": 12167.000000,
+         "caller": "T23",
+         "msg": " example[23]"
+      },{
+         "pri": 24,
+         "time": 13824.000000,
+         "caller": "T24",
+         "msg": " example[24]"
+      },{
+         "pri": 25,
+         "time": 15625.000000,
+         "caller": "T25",
+         "msg": " example[25]"
+      },{
+         "pri": 26,
+         "time": 17576.000000,
+         "caller": "T26",
+         "msg": " example[26]"
+      },{
+         "pri": 27,
+         "time": 19683.000000,
+         "caller": "T27",
+         "msg": " example[27]"
+      },{
+         "pri": 28,
+         "time": 21952.000000,
+         "caller": "T28",
+         "msg": " example[28]"
+      },{
+         "pri": 29,
+         "time": 24389.000000,
+         "caller": "T29",
+         "msg": " example[29]"
+      },{
+         "pri": 30,
+         "time": 27000.000000,
+         "caller": "T10",
+         "msg": " example[30]"
+      },{
+         "pri": 31,
+         "time": 29791.000000,
+         "caller": "T31",
+         "msg": " example[31]"
+      },{
+         "pri": 32,
+         "time": 32768.000000,
+         "caller": "T32",
+         "msg": " example[32]"
+      },{
+         "pri": 33,
+         "time": 35937.000000,
+         "caller": "T33",
+         "msg": " example[33]"
+      },{
+         "pri": 34,
+         "time": 39304.000000,
+         "caller": "T34",
+         "msg": " example[34]"
+      },{
+         "pri": 35,
+         "time": 42875.000000,
+         "caller": "T35",
+         "msg": " example[35]"
+      },{
+         "pri": 36,
+         "time": 46656.000000,
+         "caller": "T36",
+         "msg": " example[36]"
+      },{
+         "pri": 37,
+         "time": 50653.000000,
+         "caller": "T37",
+         "msg": " example[37]"
+      },{
+         "pri": 38,
+         "time": 54872.000000,
+         "caller": "T38",
+         "msg": " example[38]"
+      },{
+         "pri": 39,
+         "time": 59319.000000,
+         "caller": "T39",
+         "msg": " example[39]"
+      },{
+         "pri": 40,
+         "time": 64000.000000,
+         "caller": "T40",
+         "msg": " example[40]"
+      },{
+         "pri": 41,
+         "time": 68921.000000,
+         "caller": "T41",
+         "msg": " example[41]"
+      },{
+         "pri": 42,
+         "time": 74088.000000,
+         "caller": "T42",
+         "msg": " example[42]"
+      },{
+         "pri": 43,
+         "time": 79507.000000,
+         "caller": "T43",
+         "msg": " example[43]"
+      },{
+         "pri": 44,
+         "time": 85184.000000,
+         "caller": "T44",
+         "msg": " example[44]"
+      },{
+         "pri": 45,
+         "time": 91125.000000,
+         "caller": "T45",
+         "msg": " example[45]"
+      },{
+         "pri": 46,
+         "time": 97336.000000,
+         "caller": "T46",
+         "msg": " example[46]"
+      },{
+         "pri": 47,
+         "time": 103823.000000,
+         "caller": "T47",
+         "msg": " example[47]"
+      },{
+         "pri": 48,
+         "time": 110592.000000,
+         "caller": "T48",
+         "msg": " example[48]"
+      },{
+         "pri": 49,
+         "time": 117649.000000,
+         "caller": "T49",
+         "msg": " example[49]"
+      },{
+         "pri": 50,
+         "time": 125000.000000,
+         "caller": "T50",
+         "msg": " example[50]"
+      },{
+         "pri": 51,
+         "time": 132651.000000,
+         "caller": "T51",
+         "msg": " example[51]"
+      },{
+         "pri": 52,
+         "time": 140608.000000,
+         "caller": "T52",
+         "msg": " example[52]"
+      },{
+         "pri": 53,
+         "time": 148877.000000,
+         "caller": "T53",
+         "msg": " example[53]"
+      },{
+         "pri": 54,
+         "time": 157464.000000,
+         "caller": "T54",
+         "msg": " example[54]"
+      },{
+         "pri": 55,
+         "time": 166375.000000,
+         "caller": "T55",
+         "msg": " example[55]"
+      },{
+         "pri": 56,
+         "time": 175616.000000,
+         "caller": "T56",
+         "msg": " example[56]"
+      },{
+         "pri": 57,
+         "time": 185193.000000,
+         "caller": "T57",
+         "msg": " example[57]"
+      },{
+         "pri": 58,
+         "time": 195112.000000,
+         "caller": "T58",
+         "msg": " example[58]"
+      },{
+         "pri": 59,
+         "time": 205379.000000,
+         "caller": "T59",
+         "msg": " example[59]"
+      },{
+         "pri": 60,
+         "time": 216000.000000,
+         "caller": "T60",
+         "msg": " example[60]"
+      },{
+         "pri": 61,
+         "time": 226981.000000,
+         "caller": "T61",
+         "msg": " example[61]"
+      },{
+         "pri": 62,
+         "time": 238328.000000,
+         "caller": "T62",
+         "msg": " example[62]"
+      },{
+         "pri": 63,
+         "time": 250047.000000,
+         "caller": "T63",
+         "msg": " example[63]"
+      },{
+         "pri": 64,
+         "time": 262144.000000,
+         "caller": "T64",
+         "msg": " example[64]"
+      },{
+         "pri": 65,
+         "time": 274625.000000,
+         "caller": "T65",
+         "msg": " example[65]"
+      },{
+         "pri": 66,
+         "time": 287496.000000,
+         "caller": "T66",
+         "msg": " example[66]"
+      },{
+         "pri": 67,
+         "time": 300763.000000,
+         "caller": "T67",
+         "msg": " example[67]"
+      },{
+         "pri": 68,
+         "time": 314432.000000,
+         "caller": "T68",
+         "msg": " example[68]"
+      },{
+         "pri": 69,
+         "time": 328509.000000,
+         "caller": "T69",
+         "msg": " example[69]"
+      },{
+         "pri": 70,
+         "time": 343000.000000,
+         "caller": "T70",
+         "msg": " example[70]"
+      },{
+         "pri": 71,
+         "time": 357911.000000,
+         "caller": "T71",
+         "msg": " example[71]"
+      },{
+         "pri": 72,
+         "time": 373248.000000,
+         "caller": "T72",
+         "msg": " example[72]"
+      },{
+         "pri": 73,
+         "time": 389017.000000,
+         "caller": "T73",
+         "msg": " example[73]"
+      },{
+         "pri": 74,
+         "time": 405224.000000,
+         "caller": "T74",
+         "msg": " example[74]"
+      },{
+         "pri": 75,
+         "time": 421875.000000,
+         "caller": "T75",
+         "msg": " example[75]"
+      },{
+         "pri": 76,
+         "time": 438976.000000,
+         "caller": "T76",
+         "msg": " example[76]"
+      },{
+         "pri": 77,
+         "time": 456533.000000,
+         "caller": "T77",
+         "msg": " example[77]"
+      },{
+         "pri": 78,
+         "time": 474552.000000,
+         "caller": "T78",
+         "msg": " example[78]"
+      },{
+         "pri": 79,
+         "time": 493039.000000,
+         "caller": "T79",
+         "msg": " example[79]"
+      },{
+         "pri": 80,
+         "time": 512000.000000,
+         "caller": "T80",
+         "msg": " example[80]"
+      },{
+         "pri": 81,
+         "time": 531441.000000,
+         "caller": "T81",
+         "msg": " example[81]"
+      },{
+         "pri": 82,
+         "time": 551368.000000,
+         "caller": "T82",
+         "msg": " example[82]"
+      },{
+         "pri": 83,
+         "time": 571787.000000,
+         "caller": "T83",
+         "msg": " example[83]"
+      },{
+         "pri": 84,
+         "time": 592704.000000,
+         "caller": "T84",
+         "msg": " example[84]"
+      },{
+         "pri": 85,
+         "time": 614125.000000,
+         "caller": "T85",
+         "msg": " example[85]"
+      },{
+         "pri": 86,
+         "time": 636056.000000,
+         "caller": "T86",
+         "msg": " example[86]"
+      },{
+         "pri": 87,
+         "time": 658503.000000,
+         "caller": "T87",
+         "msg": " example[87]"
+      },{
+         "pri": 88,
+         "time": 681472.000000,
+         "caller": "T88",
+         "msg": " example[88]"
+      },{
+         "pri": 89,
+         "time": 704969.000000,
+         "caller": "T89",
+         "msg": " example[89]"
+      },{
+         "pri": 90,
+         "time": 729000.000000,
+         "caller": "T90",
+         "msg": " example[90]"
+      },{
+         "pri": 91,
+         "time": 753571.000000,
+         "caller": "T91",
+         "msg": " example[91]"
+      },{
+         "pri": 92,
+         "time": 778688.000000,
+         "caller": "T92",
+         "msg": " example[92]"
+      },{
+         "pri": 93,
+         "time": 804357.000000,
+         "caller": "T93",
+         "msg": " example[93]"
+      },{
+         "pri": 94,
+         "time": 830584.000000,
+         "caller": "T94",
+         "msg": " example[94]"
+      },{
+         "pri": 95,
+         "time": 857375.000000,
+         "caller": "T95",
+         "msg": " example[95]"
+      },{
+         "pri": 96,
+         "time": 884736.000000,
+         "caller": "T96",
+         "msg": " example[96]"
+      },{
+         "pri": 97,
+         "time": 912673.000000,
+         "caller": "T97",
+         "msg": " example[97]"
+      },{
+         "pri": 98,
+         "time": 941192.000000,
+         "caller": "T98",
+         "msg": " example[98]"
+      },{
+         "pri": 99,
+         "time": 970299.000000,
+         "caller": "T99",
+         "msg": " example[99]"
+      },{
+         "pri": 100,
+         "time": 1000000.000000,
+         "caller": "T100",
+         "msg": " example[100]"
+      },{
+         "pri": 101,
+         "time": 1030301.000000,
+         "caller": "T101",
+         "msg": " example[101]"
+      },{
+         "pri": 102,
+         "time": 1061208.000000,
+         "caller": "T102",
+         "msg": " example[102]"
+      },{
+         "pri": 103,
+         "time": 1092727.000000,
+         "caller": "T103",
+         "msg": " example[103]"
+      },{
+         "pri": 104,
+         "time": 1124864.000000,
+         "caller": "T104",
+         "msg": " example[104]"
+      }
+   ]
+}
diff --git a/tests/expected/dmesg/kmsg-file-printk-caller b/tests/expected/dmesg/kmsg-file-printk-caller
new file mode 100644
index 000000000..785d730a5
--- /dev/null
+++ b/tests/expected/dmesg/kmsg-file-printk-caller
@@ -0,0 +1,115 @@
+{
+   "dmesg": [
+      {
+         "pri": 5,
+         "time":     0.000000,
+         "caller": "T0",
+         "msg": "Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T1",
+         "msg": "Command line: initrd=\\ucode.img initrd=\\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T2",
+         "msg": "BIOS-provided physical RAM map:"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T3",
+         "msg": "BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T4",
+         "msg": "BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T5",
+         "msg": "BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T6",
+         "msg": "BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T7",
+         "msg": "BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T8",
+         "msg": "BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T9",
+         "msg": "BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T10",
+         "msg": "BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved"
+      },{
+         "pri": 6,
+         "time":     0.367657,
+         "caller": "T11",
+         "msg": "ACPI: \\_SB_.PCI0.GP19.NHI1.PWRS: New power resource"
+      },{
+         "pri": 6,
+         "time":     0.368615,
+         "caller": "T12",
+         "msg": "ACPI: \\_SB_.PCI0.GP19.XHC4.PWRS: New power resource"
+      },{
+         "pri": 6,
+         "time":     0.376316,
+         "caller": "T13",
+         "msg": "ACPI: \\_SB_.PRWL: New power resource"
+      },{
+         "pri": 6,
+         "time":     0.376343,
+         "caller": "T14",
+         "msg": "ACPI: \\_SB_.PRWB: New power resource"
+      },{
+         "pri": 6,
+         "time":     0.377373,
+         "caller": "T15",
+         "msg": "ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])"
+      },{
+         "pri": 6,
+         "time":     0.377378,
+         "caller": "T16",
+         "msg": "acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]"
+      },{
+         "pri": 6,
+         "time":     0.377569,
+         "caller": "T17",
+         "msg": "acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]"
+      },{
+         "pri": 6,
+         "time":     0.377933,
+         "caller": "T18",
+         "msg": "acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]"
+      },{
+         "pri": 6,
+         "time":     0.378458,
+         "caller": "T19",
+         "msg": "PCI host bridge to bus 0000:00"
+      },{
+         "pri": 6,
+         "time":     0.378459,
+         "caller": "T20",
+         "msg": "pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]"
+      },{
+         "pri": 6,
+         "time":     0.378461,
+         "caller": "T21",
+         "msg": "pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]"
+      }
+   ]
+}
diff --git a/tests/expected/dmesg/limit-kmsg-printk-caller b/tests/expected/dmesg/limit-kmsg-printk-caller
new file mode 100644
index 000000000..2ea07d4c8
--- /dev/null
+++ b/tests/expected/dmesg/limit-kmsg-printk-caller
@@ -0,0 +1,11 @@
+[    0.367657] [    T11] ACPI: \_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+[    0.368615] [    T12] ACPI: \_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+[    0.376316] [    T13] ACPI: \_SB_.PRWL: New power resource
+[    0.376343] [    T14] ACPI: \_SB_.PRWB: New power resource
+[    0.377373] [    T15] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+[    0.377378] [    T16] acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+[    0.377569] [    T17] acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]
+[    0.377933] [    T18] acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+[    0.378458] [    T19] PCI host bridge to bus 0000:00
+[    0.378459] [    T20] pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]
+[    0.378461] [    T21] pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]
diff --git a/tests/ts/dmesg/colors-kmsg-printk-caller b/tests/ts/dmesg/colors-kmsg-printk-caller
new file mode 100755
index 000000000..513ca82d4
--- /dev/null
+++ b/tests/ts/dmesg/colors-kmsg-printk-caller
@@ -0,0 +1,29 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="colors-kmsg-prtk-caller"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+ts_inhibit_custom_colorscheme
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG --color=always -K $TS_SELF/kmsg-input-printk-caller -x >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/console-levels-kmsg-printk-caller b/tests/ts/dmesg/console-levels-kmsg-printk-caller
new file mode 100755
index 000000000..00b8b3681
--- /dev/null
+++ b/tests/ts/dmesg/console-levels-kmsg-printk-caller
@@ -0,0 +1,36 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="levels-kmsg-prtk-caller"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+for I in {-1..8}; do
+	$TS_HELPER_DMESG -K $TS_SELF/kmsg-input-printk-caller -l $I >> $TS_OUTPUT 2>/dev/null
+done
+
+$TS_HELPER_DMESG -K $TS_SELF/kmsg-input-printk-caller -l err+ >> $TS_OUTPUT 2>/dev/null
+$TS_HELPER_DMESG -K $TS_SELF/kmsg-input-printk-caller -l emerg+ >> $TS_OUTPUT 2>/dev/null
+$TS_HELPER_DMESG -K $TS_SELF/kmsg-input-printk-caller -l +err >> $TS_OUTPUT 2>/dev/null
+$TS_HELPER_DMESG -K $TS_SELF/kmsg-input-printk-caller -l +debug >> $TS_OUTPUT 2>/dev/null
+$TS_HELPER_DMESG -K $TS_SELF/kmsg-input-printk-caller -l + 2>> $TS_OUTPUT >/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/decode-kmsg-printk-caller b/tests/ts/dmesg/decode-kmsg-printk-caller
new file mode 100755
index 000000000..d05b9fb68
--- /dev/null
+++ b/tests/ts/dmesg/decode-kmsg-printk-caller
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="decode-kmsg-prtk-caller"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG -x -K $TS_SELF/kmsg-input-printk-caller >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/delta-kmsg-printk-caller b/tests/ts/dmesg/delta-kmsg-printk-caller
new file mode 100755
index 000000000..020b82357
--- /dev/null
+++ b/tests/ts/dmesg/delta-kmsg-printk-caller
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="delta-kmsg-prtk-caller"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG -d -K $TS_SELF/kmsg-input-printk-caller >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/facilities-kmsg-printk-caller b/tests/ts/dmesg/facilities-kmsg-printk-caller
new file mode 100755
index 000000000..bec301516
--- /dev/null
+++ b/tests/ts/dmesg/facilities-kmsg-printk-caller
@@ -0,0 +1,30 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="facilities-kmsg-prtk-caller"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+for I in {-1..12}; do
+	$TS_HELPER_DMESG -K $TS_SELF/kmsg-input-printk-caller -f $I -x >> $TS_OUTPUT 2>/dev/null
+done
+
+ts_finalize
diff --git a/tests/ts/dmesg/indentation-kmsg-printk-caller b/tests/ts/dmesg/indentation-kmsg-printk-caller
new file mode 100755
index 000000000..53e549b62
--- /dev/null
+++ b/tests/ts/dmesg/indentation-kmsg-printk-caller
@@ -0,0 +1,40 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="indentation-kmsg-prtk-caller"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG -K $TS_SELF/newlines-kmsg-printk-caller >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG -K $TS_SELF/newlines-kmsg-printk-caller -x >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=delta --kmsg-file $TS_SELF/newlines-kmsg-printk-caller >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=notime --kmsg-file $TS_SELF/newlines-kmsg-printk-caller >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=reltime --kmsg-file $TS_SELF/newlines-kmsg-printk-caller >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=ctime --kmsg-file $TS_SELF/newlines-kmsg-printk-caller >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=iso --kmsg-file $TS_SELF/newlines-kmsg-printk-caller >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+ts_finalize
diff --git a/tests/ts/dmesg/input-syslog-printk-caller b/tests/ts/dmesg/input-syslog-printk-caller
new file mode 100644
index 000000000..5fcff6abe
--- /dev/null
+++ b/tests/ts/dmesg/input-syslog-printk-caller
@@ -0,0 +1,105 @@
+<0>[    0.000000] [    T0] example[0]
+<1>[    1.000000] [    T1] example[1]
+<2>[    8.000000] [    T2] example[2]
+<3>[   27.000000] [    T3] example[3]
+<4>[   64.000000] [    T4] example[4]
+<5>[  125.000000] [    T5] example[5]
+<6>[  216.000000] [    T6] example[6]
+<7>[  343.000000] [    T7] example[7]
+<8>[  512.000000] [    T8] example[8]
+<9>[  729.000000] [    T9] example[9]
+<10>[ 1000.000000] [   T10] example[10]
+<11>[ 1331.000000] [   T11] example[11]
+<12>[ 1728.000000] [   T12] example[12]
+<13>[ 2197.000000] [   T13] example[13]
+<14>[ 2744.000000] [   T14] example[14]
+<15>[ 3375.000000] [   T15] example[15]
+<16>[ 4096.000000] [   T16] example[16]
+<17>[ 4913.000000] [   T17] example[17]
+<18>[ 5832.000000] [   T18] example[18]
+<19>[ 6859.000000] [   T19] example[19]
+<20>[ 8000.000000] [   T20] example[20]
+<21>[ 9261.000000] [   T21] example[21]
+<22>[10648.000000] [   T22] example[22]
+<23>[12167.000000] [   T23] example[23]
+<24>[13824.000000] [   T24] example[24]
+<25>[15625.000000] [   T25] example[25]
+<26>[17576.000000] [   T26] example[26]
+<27>[19683.000000] [   T27] example[27]
+<28>[21952.000000] [   T28] example[28]
+<29>[24389.000000] [   T29] example[29]
+<30>[27000.000000] [   T10] example[30]
+<31>[29791.000000] [   T31] example[31]
+<32>[32768.000000] [   T32] example[32]
+<33>[35937.000000] [   T33] example[33]
+<34>[39304.000000] [   T34] example[34]
+<35>[42875.000000] [   T35] example[35]
+<36>[46656.000000] [   T36] example[36]
+<37>[50653.000000] [   T37] example[37]
+<38>[54872.000000] [   T38] example[38]
+<39>[59319.000000] [   T39] example[39]
+<40>[64000.000000] [   T40] example[40]
+<41>[68921.000000] [   T41] example[41]
+<42>[74088.000000] [   T42] example[42]
+<43>[79507.000000] [   T43] example[43]
+<44>[85184.000000] [   T44] example[44]
+<45>[91125.000000] [   T45] example[45]
+<46>[97336.000000] [   T46] example[46]
+<47>[103823.000000] [   T47] example[47]
+<48>[110592.000000] [   T48] example[48]
+<49>[117649.000000] [   T49] example[49]
+<50>[125000.000000] [   T50] example[50]
+<51>[132651.000000] [   T51] example[51]
+<52>[140608.000000] [   T52] example[52]
+<53>[148877.000000] [   T53] example[53]
+<54>[157464.000000] [   T54] example[54]
+<55>[166375.000000] [   T55] example[55]
+<56>[175616.000000] [   T56] example[56]
+<57>[185193.000000] [   T57] example[57]
+<58>[195112.000000] [   T58] example[58]
+<59>[205379.000000] [   T59] example[59]
+<60>[216000.000000] [   T60] example[60]
+<61>[226981.000000] [   T61] example[61]
+<62>[238328.000000] [   T62] example[62]
+<63>[250047.000000] [   T63] example[63]
+<64>[262144.000000] [   T64] example[64]
+<65>[274625.000000] [   T65] example[65]
+<66>[287496.000000] [   T66] example[66]
+<67>[300763.000000] [   T67] example[67]
+<68>[314432.000000] [   T68] example[68]
+<69>[328509.000000] [   T69] example[69]
+<70>[343000.000000] [   T70] example[70]
+<71>[357911.000000] [   T71] example[71]
+<72>[373248.000000] [   T72] example[72]
+<73>[389017.000000] [   T73] example[73]
+<74>[405224.000000] [   T74] example[74]
+<75>[421875.000000] [   T75] example[75]
+<76>[438976.000000] [   T76] example[76]
+<77>[456533.000000] [   T77] example[77]
+<78>[474552.000000] [   T78] example[78]
+<79>[493039.000000] [   T79] example[79]
+<80>[512000.000000] [   T80] example[80]
+<81>[531441.000000] [   T81] example[81]
+<82>[551368.000000] [   T82] example[82]
+<83>[571787.000000] [   T83] example[83]
+<84>[592704.000000] [   T84] example[84]
+<85>[614125.000000] [   T85] example[85]
+<86>[636056.000000] [   T86] example[86]
+<87>[658503.000000] [   T87] example[87]
+<88>[681472.000000] [   T88] example[88]
+<89>[704969.000000] [   T89] example[89]
+<90>[729000.000000] [   T90] example[90]
+<91>[753571.000000] [   T91] example[91]
+<92>[778688.000000] [   T92] example[92]
+<93>[804357.000000] [   T93] example[93]
+<94>[830584.000000] [   T94] example[94]
+<95>[857375.000000] [   T95] example[95]
+<96>[884736.000000] [   T96] example[96]
+<97>[912673.000000] [   T97] example[97]
+<98>[941192.000000] [   T98] example[98]
+<99>[970299.000000] [   T99] example[99]
+<100>[1000000.000000] [  T100] example[100]
+<101>[1030301.000000] [  T101] example[101]
+<102>[1061208.000000] [  T102] example[102]
+<103>[1092727.000000] [  T103] example[103]
+<104>[1124864.000000] [  T104] example[104]
diff --git a/tests/ts/dmesg/json-kmsg-printk-caller b/tests/ts/dmesg/json-kmsg-printk-caller
new file mode 100755
index 000000000..cb6c5e4a8
--- /dev/null
+++ b/tests/ts/dmesg/json-kmsg-printk-caller
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="json-kmsg-prtk-caller"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG -J -K $TS_SELF/kmsg-input-printk-caller >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/json-syslog-printk-caller b/tests/ts/dmesg/json-syslog-printk-caller
new file mode 100755
index 000000000..10dfaa423
--- /dev/null
+++ b/tests/ts/dmesg/json-syslog-printk-caller
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="json-syslog-prtk-caller"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG -J -F $TS_SELF/input-syslog-printk-caller >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/kmsg-file-printk-caller b/tests/ts/dmesg/kmsg-file-printk-caller
new file mode 100755
index 000000000..a01fc723f
--- /dev/null
+++ b/tests/ts/dmesg/kmsg-file-printk-caller
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="kmsg-file-prtk-caller"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG -J -K $TS_SELF/kmsg-input-printk-caller >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/kmsg-input-printk-caller b/tests/ts/dmesg/kmsg-input-printk-caller
new file mode 100644
index 0000000000000000000000000000000000000000..8d67f11cad7988469dd5e4a7c8589d2b744168bb
GIT binary patch
literal 2187
zcmbW2TW{hx6oB`+zv4*yQZ$g-aqb9dAw>nL(1<WMu@wr5q0uIBlmsaMe(Z!%<LSbv
zlRV_&oX=m5?PI-*_}S}*L6Xp7utfdGINQI%ffi-VGB6ZF(Rx7<zTh5)+e9?}BOdF!
z4&3g-5N;n_w*#0cs)9j9DnS;)U3i#(h9u&x{5s-+Rh*O^P!$a;r~`jv@Mj))i}85o
zE!X$o=fm05g&E7bfHb(LVT}TW9MyKP4WAG{ZvHa5STe?am!)ZtMZlG)1928tMKt*L
zRS)+ei>MN(yY|bvJxI4@ul|L)xi~^toboE7hd88zJAS>(4k<+$&WTf=%8I5=6qjL8
zL{KnRHJ_wGp3~y4X%}XyWTy5<(<i@|7wiy6G=lu)RK`5fuo%vO$2uZ}NFk&Np_Ymq
zSfw-t^eTS4ee|SPHr;Nw&#*6pO+p1wlYrWFpuOc}8Mxs*4lHO%ivx`WQkRhWRV1!e
z+ekYQM9I;RfW|eTy?GCe&cL>#DIv|PNctWrvM4)R641H|6j_w>Xm5!~<TDIiZwm7-
zzR063A?@o(63R$TCHk+9SYEssT|x4A;}=U!)6d9uCN)C3#4rurY}Eyf`{GX=5bJ8~
zkJgIkPLcB9VOyC`rdaX5E_?^(^awdS(n8E1wlBhFN)n9|Ed%RqqI#M5ZQ^RbA?jUX
z8U!0{B6&w#e0{tu#TOq(XrztM{s%F-j4(OEB&LMW&j_9%Snyf_qau!W6jmZ*&u|;D
zG>9`^*ARl$W?%BV9-k?ldhrsgAzE!IqaTEM4Bp&BLu5I;BEtH~cO7{0q1@*=E2<J!
z<JXF2yw12R+r~Q>`rZuOgoXd{t50_+&G=U{e+uLK1x&nez2zyV<oO2t&m;f4zZ}m7
zqMIAIAAgy;<H0BK<h*s-_}RiwH|(~bdC4zNf@;f(6e31T$apT!y0G#mo;zVxp6t2m
zc=16E4G9gK&(ycA3tN{oc$zZCOFYY}f+ajvd?e`4&b`?f#IqaZ!6r`P>I9F=1>Ae?
zN1ZTtvNT;9I=e5X!3!%Z*fi6iV$cjaAI4@s(=@e-Y$sJk{XC4<txuhL=c$8#E-qNb
x49;7GD7oR*gkzjV>?paPL2n~_e!=^1N$^$A^$pxgsfs@$5!EG7)Tlp__yL<dZm0kN

literal 0
HcmV?d00001

diff --git a/tests/ts/dmesg/limit-kmsg-printk-caller b/tests/ts/dmesg/limit-kmsg-printk-caller
new file mode 100755
index 000000000..4d4d9912d
--- /dev/null
+++ b/tests/ts/dmesg/limit-kmsg-printk-caller
@@ -0,0 +1,29 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="limit-kmsg-prtk-caller"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG --since @1234567890.124 --until @1234567991 -K $TS_SELF/kmsg-input-printk-caller \
+	>> $TS_OUTPUT 2> $TS_ERRLOG
+
+ts_finalize
diff --git a/tests/ts/dmesg/newlines-kmsg-printk-caller b/tests/ts/dmesg/newlines-kmsg-printk-caller
new file mode 100644
index 0000000000000000000000000000000000000000..574d2177796677b73f1efcf273005169ed832c60
GIT binary patch
literal 152
zcmXrjF#tkco#e!voYW%Q5CiL+%)C^Es??%<E(Svb9YY;M128~RV`!b1TFwPh$Hia-
tQeuRm#K^j&Jf91MLCT7`7>o^cjC71K)EQfsWE7>QazV)4{GwE-1^{d2D<=Q|

literal 0
HcmV?d00001

-- 
2.43.0


^ permalink raw reply related

* [PATCH] util-linux/sys-utils dmesg add PRINTK_CALLER support
From: Edward Chron @ 2023-12-13  0:06 UTC (permalink / raw)
  To: util-linux; +Cc: colona, echron

Submission to Project: util-linux
Open Incident: #2906 at github.com/util-linux/util-linux/issues/2906
Component: util-linux/sys-utils
File: dmesg.c
Code level patch applied against: 2.39.3 - latest code pulled from
           git.github.com:util-linux/util-linux.git
Revision: #1 on 2023/12/08 per Review from Karel Zak
Revision: #2 on 2023/12/12 Adjust line offsets for master update and
                           Add caller_id_size init to dmesg -K and
                           Add support for required dmesg tests

Add support to standard dmesg command for the optional Linux Kernel
debug CONFIG option PRINTK_CALLER which adds an optional dmesg field
that contains the Thread Id or CPU Id that is issuing the printk to
add the message to the kernel ring buffer. This makes debugging simpler
as dmesg entries for a specific thread or CPU can be recognized.

The dmesg -S using the old syslog interface supports printing the
PRINTK_CALLER field but currently standard dmesg does not support
printing the field if present. There are utilities that use dmesg and
so it would be optimal if dmesg supported PRINTK_CALLER as well.

The additional field provided by PRINTK_CALLER is only present
if it was configured for the Linux kernel where the dmesg command
is run. It is a debug option and not configured by default so the
dmesg output will only change for those kernels where the option was
configured when the kernel was built. For users who went to the
trouble to configure PRINTK_CALLER and have the extra field available
for debugging, having dmesg print the field is very helpful.

Size of the PRINTK_CALLER field is determined by the maximum number
tasks that can be run on the system which is limited by the value of
/proc/sys/kernel/pid_max as pid values are from 0 to value - 1.
This value determines the number of id digits needed by the caller id.
The PRINTK_CALLER field is printed as T<id> for a Task Id or C<id>
for a CPU Id for a printk in CPU context. The values are left space
padded and enclosed in parentheses such as: [    T123] or [     C16]

For consistency with dmesg -S which supports the PRINTK_CALLER field
the field is printed followed by a space. For JSON format output the
PRINTK_CALLER field is identified as caller as that is consistent with
it's naming in /dev/kmsg. No space padding is used to reduce space
consumed by the JSON output. So the output from the command on a system
with PRINTK_CALLER field enabled in the Linux .config file the dmesg
output appears as:

> dmesg
...
[  520.897104] [   T3919] usb 3-3: Product: USB 2.0 Hub

and

> dmesg -x
...
kern  :info  : [  520.897104] [   T3919] usb 3-3: Product: USB 2.0 Hub

and

> dmesg -J
...
      },{
         "pri": 6,
         "time":    520.897104,
         "caller": "T3919",
         "msg": "usb 3-3: Product: USB 2.0 Hub"
      },{

and

> dmesg -J -x
...
      },{
         "fac": "kern",
         "pri": "info",
         "time":   520.897104,
         "caller": "T3919",
         "msg": "usb 3-3: Product: USB 2.0 Hub"
      },{

>

For comparison:

> dmesg -S
...
[  520.897104] [ T3919] usb 3-3: Product: USB 2.0 Hub

and

> dmesg -S -x
...
kern  :info  : [  520.897104] [ T3919] usb 3-3: Product: USB 2.0 Hub

Note: When dmesg uses the old syslog interface the reserved space for
      the PRINTK_CALLER field is capped at 5 digits because 32-bit
      kernels are capped at 32768 as the max number of PIDs. However,
      64-bit systems are currently capped at 2^22 PIDs (0 - 4194303).
      The PID cap is set by PID_MAX_LIMIT but the system limit can be
      less so we use /proc/sys/kernel/pid_max to determine the size
      needed to hold the maximum PID value size for the current system.
      Many 64-bit systems support 2^22 PIDs (0 - 4194303) and you see:

> dmesg -x
...
kern  :info  : [  520.899558] [   T3919] hub 3-3:1.0: USB hub found
...
kern  :info  : [ 9830.456898] [  T98982] cgroup: fork rejected by pids ...
kern  :info  : [14301.158878] [ T137336] cgroup: fork rejected by pids ...
kern  :info  : [18980.803190] [T1637865] cgroup: fork rejected by pids ...

> dmesg -S -x
...
kern  :info  : [  520.899558] [ T3919] hub 3-3:1.0: USB hub found
...
kern  :info  : [ 9830.456898] [T98982] cgroup: fork rejected by pids ...
kern  :info  : [14301.158878] [T137336] cgroup: fork rejected by pids ...
kern  :info  : [18980.803190] [T1637865] cgroup: fork rejected by pids ...

This is the only difference seen with PRINTK_CALLER configured and
printing between the dmesg /dev/kmsg interface and the dmesg -S syslog
interface.

Signed-off-by: Ivan Delalande <colona@arista.com>
Signed-off-by: Edward Chron <echron@arista.com>
---
 include/pathnames.h                           |   3 +
 sys-utils/dmesg.c                             | 114 +++-
 .../expected/dmesg/colors-kmsg-printk-caller  |  22 +
 .../dmesg/console-levels-kmsg-printk-caller   |  45 ++
 .../expected/dmesg/decode-kmsg-printk-caller  |  22 +
 tests/expected/dmesg/delta-kmsg-printk-caller |  22 +
 .../dmesg/facilities-kmsg-printk-caller       |  22 +
 .../dmesg/indentation-kmsg-printk-caller      |  28 +
 tests/expected/dmesg/json-kmsg-printk-caller  | 115 ++++
 .../expected/dmesg/json-syslog-printk-caller  | 530 ++++++++++++++++++
 tests/expected/dmesg/kmsg-file-printk-caller  | 115 ++++
 tests/expected/dmesg/limit-kmsg-printk-caller |  11 +
 tests/ts/dmesg/colors-kmsg-printk-caller      |  29 +
 .../dmesg/console-levels-kmsg-printk-caller   |  36 ++
 tests/ts/dmesg/decode-kmsg-printk-caller      |  28 +
 tests/ts/dmesg/delta-kmsg-printk-caller       |  28 +
 tests/ts/dmesg/facilities-kmsg-printk-caller  |  30 +
 tests/ts/dmesg/indentation-kmsg-printk-caller |  40 ++
 tests/ts/dmesg/input-syslog-printk-caller     | 105 ++++
 tests/ts/dmesg/json-kmsg-printk-caller        |  28 +
 tests/ts/dmesg/json-syslog-printk-caller      |  28 +
 tests/ts/dmesg/kmsg-file-printk-caller        |  28 +
 tests/ts/dmesg/kmsg-input-printk-caller       | Bin 0 -> 2187 bytes
 tests/ts/dmesg/limit-kmsg-printk-caller       |  29 +
 tests/ts/dmesg/newlines-kmsg-printk-caller    | Bin 0 -> 152 bytes
 25 files changed, 1457 insertions(+), 1 deletion(-)
 create mode 100644 tests/expected/dmesg/colors-kmsg-printk-caller
 create mode 100644 tests/expected/dmesg/console-levels-kmsg-printk-caller
 create mode 100644 tests/expected/dmesg/decode-kmsg-printk-caller
 create mode 100644 tests/expected/dmesg/delta-kmsg-printk-caller
 create mode 100644 tests/expected/dmesg/facilities-kmsg-printk-caller
 create mode 100644 tests/expected/dmesg/indentation-kmsg-printk-caller
 create mode 100644 tests/expected/dmesg/json-kmsg-printk-caller
 create mode 100644 tests/expected/dmesg/json-syslog-printk-caller
 create mode 100644 tests/expected/dmesg/kmsg-file-printk-caller
 create mode 100644 tests/expected/dmesg/limit-kmsg-printk-caller
 create mode 100755 tests/ts/dmesg/colors-kmsg-printk-caller
 create mode 100755 tests/ts/dmesg/console-levels-kmsg-printk-caller
 create mode 100755 tests/ts/dmesg/decode-kmsg-printk-caller
 create mode 100755 tests/ts/dmesg/delta-kmsg-printk-caller
 create mode 100755 tests/ts/dmesg/facilities-kmsg-printk-caller
 create mode 100755 tests/ts/dmesg/indentation-kmsg-printk-caller
 create mode 100644 tests/ts/dmesg/input-syslog-printk-caller
 create mode 100755 tests/ts/dmesg/json-kmsg-printk-caller
 create mode 100755 tests/ts/dmesg/json-syslog-printk-caller
 create mode 100755 tests/ts/dmesg/kmsg-file-printk-caller
 create mode 100644 tests/ts/dmesg/kmsg-input-printk-caller
 create mode 100755 tests/ts/dmesg/limit-kmsg-printk-caller
 create mode 100644 tests/ts/dmesg/newlines-kmsg-printk-caller

diff --git a/include/pathnames.h b/include/pathnames.h
index caf0e63d4..81fa405f6 100644
--- a/include/pathnames.h
+++ b/include/pathnames.h
@@ -230,4 +230,7 @@
 /* cgroup path */
 #define _PATH_SYS_CGROUP	"/sys/fs/cgroup"
 
+/* Maximum number of PIDs system supports */
+#define _PATH_PROC_PIDMAX	"/proc/sys/kernel/pid_max"
+
 #endif /* PATHNAMES_H */
diff --git a/sys-utils/dmesg.c b/sys-utils/dmesg.c
index 77728b419..5a04af3e6 100644
--- a/sys-utils/dmesg.c
+++ b/sys-utils/dmesg.c
@@ -13,7 +13,9 @@
  */
 #include <stdio.h>
 #include <getopt.h>
+#include <stdbool.h>
 #include <stdlib.h>
+#include <string.h>
 #include <sys/klog.h>
 #include <sys/syslog.h>
 #include <sys/time.h>
@@ -41,6 +43,7 @@
 #include "mangle.h"
 #include "pager.h"
 #include "jsonwrt.h"
+#include "pathnames.h"
 
 /* Close the log.  Currently a NOP. */
 #define SYSLOG_ACTION_CLOSE          0
@@ -65,6 +68,11 @@
 /* Return size of the log buffer */
 #define SYSLOG_ACTION_SIZE_BUFFER   10
 
+#define PID_CHARS_MAX sizeof(stringify_value(LONG_MAX))
+#define PID_CHARS_DEFAULT sizeof(stringify_value(INT_MAX))
+#define DMESG_CALLER_PREFIX "caller="
+#define DMESG_CALLER_PREFIXSZ (sizeof(DMESG_CALLER_PREFIX)-1)
+
 /*
  * Color scheme
  */
@@ -233,6 +241,7 @@ struct dmesg_control {
 			force_prefix:1;	/* force timestamp and decode prefix
 					   on each line */
 	int		indent;		/* due to timestamps if newline */
+	size_t          caller_id_size;   /* PRINTK_CALLERID max field size */
 };
 
 struct dmesg_record {
@@ -242,6 +251,7 @@ struct dmesg_record {
 	int		level;
 	int		facility;
 	struct timeval  tv;
+	char		caller_id[PID_CHARS_MAX];
 
 	const char	*next;		/* buffer with next unparsed record */
 	size_t		next_size;	/* size of the next buffer */
@@ -254,6 +264,7 @@ struct dmesg_record {
 		(_r)->level = -1; \
 		(_r)->tv.tv_sec = 0; \
 		(_r)->tv.tv_usec = 0; \
+		(_r)->caller_id[0] = 0; \
 	} while (0)
 
 static int process_kmsg(struct dmesg_control *ctl);
@@ -551,6 +562,45 @@ static int get_syslog_buffer_size(void)
 	return n > 0 ? n : 0;
 }
 
+/*
+ * Get the number of characters needed to hold the maximum number
+ * of tasks this system supports. This size of string could hold
+ * a thread id large enough for the highest thread id.
+ * This is needed to determine the number of characters reserved for
+ * the PRINTK_CALLER field if it has been configured in the Linux Kernel.
+ *
+ * The number of digits sets the max value since the value can't exceed
+ * a value of that size. The /proc field defined by _PATH_PROC_PIDMAX
+ * holds the maximum number of PID values that may be ussed by the system,
+ * so 0 to that value minus one.
+ *
+ * For determining the size of the PRINTK_CALLER field, we make the safe
+ * assumption that the number of threads >= number of cpus. This because
+ * the PRINTK_CALLER field can hold either a thread id or a CPU id value.
+ *
+ * If we can't access the pid max kernel proc entry we assign a default
+ * field size of 5 characters as that is what the old syslog interface
+ * uses as the reserved field size. This is justified because 32-bit Linux
+ * systems are limited to PID values between (0-32767).
+ *
+ */
+static size_t max_threads_id_size(void)
+{
+	char taskmax[PID_CHARS_MAX] = {'\0'};
+	ssize_t rdsize;
+	int fd;
+
+	fd = open(_PATH_PROC_PIDMAX, O_RDONLY);
+	if (fd == -1)
+		return PID_CHARS_DEFAULT;
+
+	rdsize = read(fd, taskmax, sizeof(taskmax));
+	if (rdsize == -1)
+		return PID_CHARS_DEFAULT;
+
+	return strnlen(taskmax, sizeof(taskmax));
+}
+
 /*
  * Reads messages from regular file by mmap
  */
@@ -728,6 +778,36 @@ static const char *skip_item(const char *begin, const char *end, const char *sep
 	return begin;
 }
 
+/*
+ * Checks to see if the caller (caller id) field is present in the kmsg record.
+ * This is true if the PRINTK_CALLER config option has been set in the kernel.
+ *
+ * If the caller_id is found in the kmsg buffer then return the id and id type
+ * to the caller in dmesg caller_id. Returns string pointer to next value.
+ *
+ */
+static const char *parse_callerid(const char *p_str, const char *end,
+				  struct dmesg_record *p_drec)
+{
+	const char *p_after;
+	const char *p_next;
+	size_t cid_size;
+	char *p_cid;
+
+	p_cid = strstr(p_str, DMESG_CALLER_PREFIX);
+	if (p_cid != NULL && p_drec != NULL) {
+		p_next = p_cid + DMESG_CALLER_PREFIXSZ;
+		p_after = skip_item(p_next, end, ",;");
+		cid_size = p_after - p_next;
+		if (cid_size < sizeof(p_drec->caller_id))
+			xstrncpy(p_drec->caller_id, p_next, cid_size);
+		else
+			return p_str;
+		return p_after;
+	}
+	return p_str;
+}
+
 /*
  * Parses one record from syslog(2) buffer
  */
@@ -795,6 +875,18 @@ static int get_next_syslog_record(struct dmesg_control *ctl,
 				begin++;
 		}
 
+		if (*begin == '[' && (*(begin + 1) == ' ' ||
+			(*(begin + 1) == 'T' || *(begin + 1) == 'C'))) {
+			const char *start = begin + 1;
+			size_t id_size;
+
+			start = start + strspn(start, " ");
+			begin = skip_item(begin, end, "]");
+			id_size = begin - start;
+			if (id_size < sizeof(rec->caller_id))
+				xstrncpy(rec->caller_id, start, id_size);
+		}
+
 		rec->mesg = begin;
 		rec->mesg_size = end - begin;
 
@@ -1101,6 +1193,19 @@ full_output:
 			color_disable();
 	}
 
+	if (*rec->caller_id) {
+		if (ctl->json) {
+			ul_jsonwrt_value_s(&ctl->jfmt, "caller", rec->caller_id);
+		} else {
+			char cidbuf[PID_CHARS_MAX+3] = {'\0'};
+
+			sprintf(cidbuf, "[%*s] ",
+				(char)ctl->caller_id_size - 1, rec->caller_id);
+			ctl->indent += strnlen(cidbuf, PID_CHARS_MAX+3);
+			fputs(cidbuf, stdout);
+		}
+	}
+
 	/*
 	 * A kernel message may contain several lines of output, separated
 	 * by '\n'.  If the timestamp and decode outputs are forced then each
@@ -1229,6 +1334,8 @@ static int init_kmsg(struct dmesg_control *ctl)
 		return -1;
 	}
 
+	ctl->caller_id_size = max_threads_id_size();
+
 	return 0;
 }
 
@@ -1284,7 +1391,10 @@ static int parse_kmsg_record(struct dmesg_control *ctl,
 		goto mesg;
 
 	/* D) optional fields (ignore) */
-	p = skip_item(p, end, ";");
+	p = skip_item(p, end, ",;");
+
+	/* Include optional PRINTK_CALLER field if it is present */
+	p = parse_callerid(p, end, rec);
 
 mesg:
 	/* E) message text */
@@ -1446,6 +1556,7 @@ int main(int argc, char *argv[])
 		.kmsg = -1,
 		.time_fmt = DMESG_TIMEFTM_TIME,
 		.indent = 0,
+		.caller_id_size = 0,
 	};
 	int colormode = UL_COLORMODE_UNDEF;
 	enum {
@@ -1542,6 +1653,7 @@ int main(int argc, char *argv[])
 		case 'K':
 			ctl.filename = optarg;
 			ctl.method = DMESG_METHOD_KMSG;
+			ctl.caller_id_size = max_threads_id_size();
 			break;
 		case 'f':
 			ctl.fltr_fac = 1;
diff --git a/tests/expected/dmesg/colors-kmsg-printk-caller b/tests/expected/dmesg/colors-kmsg-printk-caller
new file mode 100644
index 000000000..c7bf6e8b7
--- /dev/null
+++ b/tests/expected/dmesg/colors-kmsg-printk-caller
@@ -0,0 +1,22 @@
+kern  :notice: ^[[32m[    0.000000] ^[[0m[     T0] Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000
+kern  :info  : ^[[32m[    0.000000] ^[[0m[     T1] ^[[33mCommand line: ^[[0minitrd=\ucode.img initrd=\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system
+kern  :info  : ^[[32m[    0.000000] ^[[0m[     T2] BIOS-provided physical RAM map:
+kern  :info  : ^[[32m[    0.000000] ^[[0m[     T3] ^[[33mBIOS-e820: ^[[0m[mem 0x0000000000000000-0x000000000009efff] usable
+kern  :info  : ^[[32m[    0.000000] ^[[0m[     T4] ^[[33mBIOS-e820: ^[[0m[mem 0x000000000009f000-0x00000000000bffff] reserved
+kern  :info  : ^[[32m[    0.000000] ^[[0m[     T5] ^[[33mBIOS-e820: ^[[0m[mem 0x0000000000100000-0x0000000009afffff] usable
+kern  :info  : ^[[32m[    0.000000] ^[[0m[     T6] ^[[33mBIOS-e820: ^[[0m[mem 0x0000000009b00000-0x0000000009dfffff] reserved
+kern  :info  : ^[[32m[    0.000000] ^[[0m[     T7] ^[[33mBIOS-e820: ^[[0m[mem 0x0000000009e00000-0x0000000009efffff] usable
+kern  :info  : ^[[32m[    0.000000] ^[[0m[     T8] ^[[33mBIOS-e820: ^[[0m[mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS
+kern  :info  : ^[[32m[    0.000000] ^[[0m[     T9] ^[[33mBIOS-e820: ^[[0m[mem 0x0000000009f3c000-0x000000004235ffff] usable
+kern  :info  : ^[[32m[    0.000000] ^[[0m[    T10] ^[[33mBIOS-e820: ^[[0m[mem 0x0000000042360000-0x000000004455ffff] reserved
+kern  :info  : ^[[32m[    0.367657] ^[[0m[    T11] ^[[33mACPI: ^[[0m\_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+kern  :info  : ^[[32m[    0.368615] ^[[0m[    T12] ^[[33mACPI: ^[[0m\_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+kern  :info  : ^[[32m[    0.376316] ^[[0m[    T13] ^[[33mACPI: ^[[0m\_SB_.PRWL: New power resource
+kern  :info  : ^[[32m[    0.376343] ^[[0m[    T14] ^[[33mACPI: ^[[0m\_SB_.PRWB: New power resource
+kern  :info  : ^[[32m[    0.377373] ^[[0m[    T15] ^[[33mACPI: ^[[0mPCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+kern  :info  : ^[[32m[    0.377378] ^[[0m[    T16] ^[[33macpi PNP0A08:00: ^[[0m_OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+kern  :info  : ^[[32m[    0.377569] ^[[0m[    T17] ^[[33macpi PNP0A08:00: ^[[0m_OSC: platform does not support [SHPCHotplug AER]
+kern  :info  : ^[[32m[    0.377933] ^[[0m[    T18] ^[[33macpi PNP0A08:00: ^[[0m_OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+kern  :info  : ^[[32m[    0.378458] ^[[0m[    T19] PCI host bridge to bus 0000:00
+kern  :info  : ^[[32m[    0.378459] ^[[0m[    T20] ^[[33mpci_bus 0000:00: ^[[0mroot bus resource [io  0x0000-0x0cf7 window]
+kern  :info  : ^[[32m[    0.378461] ^[[0m[    T21] ^[[33mpci_bus 0000:00: ^[[0mroot bus resource [io  0x0d00-0xffff window]
diff --git a/tests/expected/dmesg/console-levels-kmsg-printk-caller b/tests/expected/dmesg/console-levels-kmsg-printk-caller
new file mode 100644
index 000000000..1f6e9f178
--- /dev/null
+++ b/tests/expected/dmesg/console-levels-kmsg-printk-caller
@@ -0,0 +1,45 @@
+[    0.000000] [     T0] Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000
+[    0.000000] [     T1] Command line: initrd=\ucode.img initrd=\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system
+[    0.000000] [     T2] BIOS-provided physical RAM map:
+[    0.000000] [     T3] BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable
+[    0.000000] [     T4] BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved
+[    0.000000] [     T5] BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable
+[    0.000000] [     T6] BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved
+[    0.000000] [     T7] BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable
+[    0.000000] [     T8] BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS
+[    0.000000] [     T9] BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable
+[    0.000000] [    T10] BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved
+[    0.367657] [    T11] ACPI: \_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+[    0.368615] [    T12] ACPI: \_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+[    0.376316] [    T13] ACPI: \_SB_.PRWL: New power resource
+[    0.376343] [    T14] ACPI: \_SB_.PRWB: New power resource
+[    0.377373] [    T15] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+[    0.377378] [    T16] acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+[    0.377569] [    T17] acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]
+[    0.377933] [    T18] acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+[    0.378458] [    T19] PCI host bridge to bus 0000:00
+[    0.378459] [    T20] pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]
+[    0.378461] [    T21] pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]
+[    0.000000] [     T0] Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000
+[    0.000000] [     T1] Command line: initrd=\ucode.img initrd=\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system
+[    0.000000] [     T2] BIOS-provided physical RAM map:
+[    0.000000] [     T3] BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable
+[    0.000000] [     T4] BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved
+[    0.000000] [     T5] BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable
+[    0.000000] [     T6] BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved
+[    0.000000] [     T7] BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable
+[    0.000000] [     T8] BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS
+[    0.000000] [     T9] BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable
+[    0.000000] [    T10] BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved
+[    0.367657] [    T11] ACPI: \_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+[    0.368615] [    T12] ACPI: \_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+[    0.376316] [    T13] ACPI: \_SB_.PRWL: New power resource
+[    0.376343] [    T14] ACPI: \_SB_.PRWB: New power resource
+[    0.377373] [    T15] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+[    0.377378] [    T16] acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+[    0.377569] [    T17] acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]
+[    0.377933] [    T18] acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+[    0.378458] [    T19] PCI host bridge to bus 0000:00
+[    0.378459] [    T20] pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]
+[    0.378461] [    T21] pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]
+test_dmesg: unknown level '+'
diff --git a/tests/expected/dmesg/decode-kmsg-printk-caller b/tests/expected/dmesg/decode-kmsg-printk-caller
new file mode 100644
index 000000000..78c363389
--- /dev/null
+++ b/tests/expected/dmesg/decode-kmsg-printk-caller
@@ -0,0 +1,22 @@
+kern  :notice: [    0.000000] [     T0] Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000
+kern  :info  : [    0.000000] [     T1] Command line: initrd=\ucode.img initrd=\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system
+kern  :info  : [    0.000000] [     T2] BIOS-provided physical RAM map:
+kern  :info  : [    0.000000] [     T3] BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable
+kern  :info  : [    0.000000] [     T4] BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved
+kern  :info  : [    0.000000] [     T5] BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable
+kern  :info  : [    0.000000] [     T6] BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved
+kern  :info  : [    0.000000] [     T7] BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable
+kern  :info  : [    0.000000] [     T8] BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS
+kern  :info  : [    0.000000] [     T9] BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable
+kern  :info  : [    0.000000] [    T10] BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved
+kern  :info  : [    0.367657] [    T11] ACPI: \_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+kern  :info  : [    0.368615] [    T12] ACPI: \_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+kern  :info  : [    0.376316] [    T13] ACPI: \_SB_.PRWL: New power resource
+kern  :info  : [    0.376343] [    T14] ACPI: \_SB_.PRWB: New power resource
+kern  :info  : [    0.377373] [    T15] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+kern  :info  : [    0.377378] [    T16] acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+kern  :info  : [    0.377569] [    T17] acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]
+kern  :info  : [    0.377933] [    T18] acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+kern  :info  : [    0.378458] [    T19] PCI host bridge to bus 0000:00
+kern  :info  : [    0.378459] [    T20] pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]
+kern  :info  : [    0.378461] [    T21] pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]
diff --git a/tests/expected/dmesg/delta-kmsg-printk-caller b/tests/expected/dmesg/delta-kmsg-printk-caller
new file mode 100644
index 000000000..892d2dcea
--- /dev/null
+++ b/tests/expected/dmesg/delta-kmsg-printk-caller
@@ -0,0 +1,22 @@
+[    0.000000 <    0.000000>] [     T0] Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000
+[    0.000000 <    0.000000>] [     T1] Command line: initrd=\ucode.img initrd=\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system
+[    0.000000 <    0.000000>] [     T2] BIOS-provided physical RAM map:
+[    0.000000 <    0.000000>] [     T3] BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable
+[    0.000000 <    0.000000>] [     T4] BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved
+[    0.000000 <    0.000000>] [     T5] BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable
+[    0.000000 <    0.000000>] [     T6] BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved
+[    0.000000 <    0.000000>] [     T7] BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable
+[    0.000000 <    0.000000>] [     T8] BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS
+[    0.000000 <    0.000000>] [     T9] BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable
+[    0.000000 <    0.000000>] [    T10] BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved
+[    0.367657 <    0.000000>] [    T11] ACPI: \_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+[    0.368615 <    0.000000>] [    T12] ACPI: \_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+[    0.376316 <    0.000000>] [    T13] ACPI: \_SB_.PRWL: New power resource
+[    0.376343 <    0.000000>] [    T14] ACPI: \_SB_.PRWB: New power resource
+[    0.377373 <    0.000000>] [    T15] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+[    0.377378 <    0.000000>] [    T16] acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+[    0.377569 <    0.000000>] [    T17] acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]
+[    0.377933 <    0.000000>] [    T18] acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+[    0.378458 <    0.000000>] [    T19] PCI host bridge to bus 0000:00
+[    0.378459 <    0.000000>] [    T20] pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]
+[    0.378461 <    0.000000>] [    T21] pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]
diff --git a/tests/expected/dmesg/facilities-kmsg-printk-caller b/tests/expected/dmesg/facilities-kmsg-printk-caller
new file mode 100644
index 000000000..78c363389
--- /dev/null
+++ b/tests/expected/dmesg/facilities-kmsg-printk-caller
@@ -0,0 +1,22 @@
+kern  :notice: [    0.000000] [     T0] Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000
+kern  :info  : [    0.000000] [     T1] Command line: initrd=\ucode.img initrd=\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system
+kern  :info  : [    0.000000] [     T2] BIOS-provided physical RAM map:
+kern  :info  : [    0.000000] [     T3] BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable
+kern  :info  : [    0.000000] [     T4] BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved
+kern  :info  : [    0.000000] [     T5] BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable
+kern  :info  : [    0.000000] [     T6] BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved
+kern  :info  : [    0.000000] [     T7] BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable
+kern  :info  : [    0.000000] [     T8] BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS
+kern  :info  : [    0.000000] [     T9] BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable
+kern  :info  : [    0.000000] [    T10] BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved
+kern  :info  : [    0.367657] [    T11] ACPI: \_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+kern  :info  : [    0.368615] [    T12] ACPI: \_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+kern  :info  : [    0.376316] [    T13] ACPI: \_SB_.PRWL: New power resource
+kern  :info  : [    0.376343] [    T14] ACPI: \_SB_.PRWB: New power resource
+kern  :info  : [    0.377373] [    T15] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+kern  :info  : [    0.377378] [    T16] acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+kern  :info  : [    0.377569] [    T17] acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]
+kern  :info  : [    0.377933] [    T18] acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+kern  :info  : [    0.378458] [    T19] PCI host bridge to bus 0000:00
+kern  :info  : [    0.378459] [    T20] pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]
+kern  :info  : [    0.378461] [    T21] pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]
diff --git a/tests/expected/dmesg/indentation-kmsg-printk-caller b/tests/expected/dmesg/indentation-kmsg-printk-caller
new file mode 100644
index 000000000..47ad73f27
--- /dev/null
+++ b/tests/expected/dmesg/indentation-kmsg-printk-caller
@@ -0,0 +1,28 @@
+[    0.000000] [     T0] line zero
+[    1.000000] [     T1] new
+[    2.000000] [     T2] two
+[    3.000000] [     T3] three
+kern  :notice: [    0.000000] [     T0] line zero
+user  :crit  : [    1.000000] [     T1] new
+mail  :warn  : [    2.000000] [     T2] two
+daemon:info  : [    3.000000] [     T3] three
+[<    0.000000>] [     T0] line zero
+[<    0.000000>] [     T1] new
+[<    1.000000>] [     T2] two
+[<    1.000000>] [     T3] three
+[     T0] line zero
+[     T1] new
+[     T2] two
+[     T3] three
+[Feb13 23:31] [     T0] line zero
+[  +0.000000] [     T1] new
+[  +1.000000] [     T2] two
+[  +1.000000] [     T3] three
+[Fri Feb 13 23:31:30 2009] [     T0] line zero
+[Fri Feb 13 23:31:31 2009] [     T1] new
+[Fri Feb 13 23:31:32 2009] [     T2] two
+[Fri Feb 13 23:31:33 2009] [     T3] three
+2009-02-13T23:31:30,123456+00:00 [     T0] line zero
+2009-02-13T23:31:31,123456+00:00 [     T1] new
+2009-02-13T23:31:32,123456+00:00 [     T2] two
+2009-02-13T23:31:33,123456+00:00 [     T3] three
diff --git a/tests/expected/dmesg/json-kmsg-printk-caller b/tests/expected/dmesg/json-kmsg-printk-caller
new file mode 100644
index 000000000..785d730a5
--- /dev/null
+++ b/tests/expected/dmesg/json-kmsg-printk-caller
@@ -0,0 +1,115 @@
+{
+   "dmesg": [
+      {
+         "pri": 5,
+         "time":     0.000000,
+         "caller": "T0",
+         "msg": "Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T1",
+         "msg": "Command line: initrd=\\ucode.img initrd=\\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T2",
+         "msg": "BIOS-provided physical RAM map:"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T3",
+         "msg": "BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T4",
+         "msg": "BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T5",
+         "msg": "BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T6",
+         "msg": "BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T7",
+         "msg": "BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T8",
+         "msg": "BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T9",
+         "msg": "BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T10",
+         "msg": "BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved"
+      },{
+         "pri": 6,
+         "time":     0.367657,
+         "caller": "T11",
+         "msg": "ACPI: \\_SB_.PCI0.GP19.NHI1.PWRS: New power resource"
+      },{
+         "pri": 6,
+         "time":     0.368615,
+         "caller": "T12",
+         "msg": "ACPI: \\_SB_.PCI0.GP19.XHC4.PWRS: New power resource"
+      },{
+         "pri": 6,
+         "time":     0.376316,
+         "caller": "T13",
+         "msg": "ACPI: \\_SB_.PRWL: New power resource"
+      },{
+         "pri": 6,
+         "time":     0.376343,
+         "caller": "T14",
+         "msg": "ACPI: \\_SB_.PRWB: New power resource"
+      },{
+         "pri": 6,
+         "time":     0.377373,
+         "caller": "T15",
+         "msg": "ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])"
+      },{
+         "pri": 6,
+         "time":     0.377378,
+         "caller": "T16",
+         "msg": "acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]"
+      },{
+         "pri": 6,
+         "time":     0.377569,
+         "caller": "T17",
+         "msg": "acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]"
+      },{
+         "pri": 6,
+         "time":     0.377933,
+         "caller": "T18",
+         "msg": "acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]"
+      },{
+         "pri": 6,
+         "time":     0.378458,
+         "caller": "T19",
+         "msg": "PCI host bridge to bus 0000:00"
+      },{
+         "pri": 6,
+         "time":     0.378459,
+         "caller": "T20",
+         "msg": "pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]"
+      },{
+         "pri": 6,
+         "time":     0.378461,
+         "caller": "T21",
+         "msg": "pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]"
+      }
+   ]
+}
diff --git a/tests/expected/dmesg/json-syslog-printk-caller b/tests/expected/dmesg/json-syslog-printk-caller
new file mode 100644
index 000000000..40c98aa67
--- /dev/null
+++ b/tests/expected/dmesg/json-syslog-printk-caller
@@ -0,0 +1,530 @@
+{
+   "dmesg": [
+      {
+         "pri": 0,
+         "time":     0.000000,
+         "caller": "T0",
+         "msg": " example[0]"
+      },{
+         "pri": 1,
+         "time":     1.000000,
+         "caller": "T1",
+         "msg": " example[1]"
+      },{
+         "pri": 2,
+         "time":     8.000000,
+         "caller": "T2",
+         "msg": " example[2]"
+      },{
+         "pri": 3,
+         "time":    27.000000,
+         "caller": "T3",
+         "msg": " example[3]"
+      },{
+         "pri": 4,
+         "time":    64.000000,
+         "caller": "T4",
+         "msg": " example[4]"
+      },{
+         "pri": 5,
+         "time":   125.000000,
+         "caller": "T5",
+         "msg": " example[5]"
+      },{
+         "pri": 6,
+         "time":   216.000000,
+         "caller": "T6",
+         "msg": " example[6]"
+      },{
+         "pri": 7,
+         "time":   343.000000,
+         "caller": "T7",
+         "msg": " example[7]"
+      },{
+         "pri": 8,
+         "time":   512.000000,
+         "caller": "T8",
+         "msg": " example[8]"
+      },{
+         "pri": 9,
+         "time":   729.000000,
+         "caller": "T9",
+         "msg": " example[9]"
+      },{
+         "pri": 10,
+         "time":  1000.000000,
+         "caller": "T10",
+         "msg": " example[10]"
+      },{
+         "pri": 11,
+         "time":  1331.000000,
+         "caller": "T11",
+         "msg": " example[11]"
+      },{
+         "pri": 12,
+         "time":  1728.000000,
+         "caller": "T12",
+         "msg": " example[12]"
+      },{
+         "pri": 13,
+         "time":  2197.000000,
+         "caller": "T13",
+         "msg": " example[13]"
+      },{
+         "pri": 14,
+         "time":  2744.000000,
+         "caller": "T14",
+         "msg": " example[14]"
+      },{
+         "pri": 15,
+         "time":  3375.000000,
+         "caller": "T15",
+         "msg": " example[15]"
+      },{
+         "pri": 16,
+         "time":  4096.000000,
+         "caller": "T16",
+         "msg": " example[16]"
+      },{
+         "pri": 17,
+         "time":  4913.000000,
+         "caller": "T17",
+         "msg": " example[17]"
+      },{
+         "pri": 18,
+         "time":  5832.000000,
+         "caller": "T18",
+         "msg": " example[18]"
+      },{
+         "pri": 19,
+         "time":  6859.000000,
+         "caller": "T19",
+         "msg": " example[19]"
+      },{
+         "pri": 20,
+         "time":  8000.000000,
+         "caller": "T20",
+         "msg": " example[20]"
+      },{
+         "pri": 21,
+         "time":  9261.000000,
+         "caller": "T21",
+         "msg": " example[21]"
+      },{
+         "pri": 22,
+         "time": 10648.000000,
+         "caller": "T22",
+         "msg": " example[22]"
+      },{
+         "pri": 23,
+         "time": 12167.000000,
+         "caller": "T23",
+         "msg": " example[23]"
+      },{
+         "pri": 24,
+         "time": 13824.000000,
+         "caller": "T24",
+         "msg": " example[24]"
+      },{
+         "pri": 25,
+         "time": 15625.000000,
+         "caller": "T25",
+         "msg": " example[25]"
+      },{
+         "pri": 26,
+         "time": 17576.000000,
+         "caller": "T26",
+         "msg": " example[26]"
+      },{
+         "pri": 27,
+         "time": 19683.000000,
+         "caller": "T27",
+         "msg": " example[27]"
+      },{
+         "pri": 28,
+         "time": 21952.000000,
+         "caller": "T28",
+         "msg": " example[28]"
+      },{
+         "pri": 29,
+         "time": 24389.000000,
+         "caller": "T29",
+         "msg": " example[29]"
+      },{
+         "pri": 30,
+         "time": 27000.000000,
+         "caller": "T10",
+         "msg": " example[30]"
+      },{
+         "pri": 31,
+         "time": 29791.000000,
+         "caller": "T31",
+         "msg": " example[31]"
+      },{
+         "pri": 32,
+         "time": 32768.000000,
+         "caller": "T32",
+         "msg": " example[32]"
+      },{
+         "pri": 33,
+         "time": 35937.000000,
+         "caller": "T33",
+         "msg": " example[33]"
+      },{
+         "pri": 34,
+         "time": 39304.000000,
+         "caller": "T34",
+         "msg": " example[34]"
+      },{
+         "pri": 35,
+         "time": 42875.000000,
+         "caller": "T35",
+         "msg": " example[35]"
+      },{
+         "pri": 36,
+         "time": 46656.000000,
+         "caller": "T36",
+         "msg": " example[36]"
+      },{
+         "pri": 37,
+         "time": 50653.000000,
+         "caller": "T37",
+         "msg": " example[37]"
+      },{
+         "pri": 38,
+         "time": 54872.000000,
+         "caller": "T38",
+         "msg": " example[38]"
+      },{
+         "pri": 39,
+         "time": 59319.000000,
+         "caller": "T39",
+         "msg": " example[39]"
+      },{
+         "pri": 40,
+         "time": 64000.000000,
+         "caller": "T40",
+         "msg": " example[40]"
+      },{
+         "pri": 41,
+         "time": 68921.000000,
+         "caller": "T41",
+         "msg": " example[41]"
+      },{
+         "pri": 42,
+         "time": 74088.000000,
+         "caller": "T42",
+         "msg": " example[42]"
+      },{
+         "pri": 43,
+         "time": 79507.000000,
+         "caller": "T43",
+         "msg": " example[43]"
+      },{
+         "pri": 44,
+         "time": 85184.000000,
+         "caller": "T44",
+         "msg": " example[44]"
+      },{
+         "pri": 45,
+         "time": 91125.000000,
+         "caller": "T45",
+         "msg": " example[45]"
+      },{
+         "pri": 46,
+         "time": 97336.000000,
+         "caller": "T46",
+         "msg": " example[46]"
+      },{
+         "pri": 47,
+         "time": 103823.000000,
+         "caller": "T47",
+         "msg": " example[47]"
+      },{
+         "pri": 48,
+         "time": 110592.000000,
+         "caller": "T48",
+         "msg": " example[48]"
+      },{
+         "pri": 49,
+         "time": 117649.000000,
+         "caller": "T49",
+         "msg": " example[49]"
+      },{
+         "pri": 50,
+         "time": 125000.000000,
+         "caller": "T50",
+         "msg": " example[50]"
+      },{
+         "pri": 51,
+         "time": 132651.000000,
+         "caller": "T51",
+         "msg": " example[51]"
+      },{
+         "pri": 52,
+         "time": 140608.000000,
+         "caller": "T52",
+         "msg": " example[52]"
+      },{
+         "pri": 53,
+         "time": 148877.000000,
+         "caller": "T53",
+         "msg": " example[53]"
+      },{
+         "pri": 54,
+         "time": 157464.000000,
+         "caller": "T54",
+         "msg": " example[54]"
+      },{
+         "pri": 55,
+         "time": 166375.000000,
+         "caller": "T55",
+         "msg": " example[55]"
+      },{
+         "pri": 56,
+         "time": 175616.000000,
+         "caller": "T56",
+         "msg": " example[56]"
+      },{
+         "pri": 57,
+         "time": 185193.000000,
+         "caller": "T57",
+         "msg": " example[57]"
+      },{
+         "pri": 58,
+         "time": 195112.000000,
+         "caller": "T58",
+         "msg": " example[58]"
+      },{
+         "pri": 59,
+         "time": 205379.000000,
+         "caller": "T59",
+         "msg": " example[59]"
+      },{
+         "pri": 60,
+         "time": 216000.000000,
+         "caller": "T60",
+         "msg": " example[60]"
+      },{
+         "pri": 61,
+         "time": 226981.000000,
+         "caller": "T61",
+         "msg": " example[61]"
+      },{
+         "pri": 62,
+         "time": 238328.000000,
+         "caller": "T62",
+         "msg": " example[62]"
+      },{
+         "pri": 63,
+         "time": 250047.000000,
+         "caller": "T63",
+         "msg": " example[63]"
+      },{
+         "pri": 64,
+         "time": 262144.000000,
+         "caller": "T64",
+         "msg": " example[64]"
+      },{
+         "pri": 65,
+         "time": 274625.000000,
+         "caller": "T65",
+         "msg": " example[65]"
+      },{
+         "pri": 66,
+         "time": 287496.000000,
+         "caller": "T66",
+         "msg": " example[66]"
+      },{
+         "pri": 67,
+         "time": 300763.000000,
+         "caller": "T67",
+         "msg": " example[67]"
+      },{
+         "pri": 68,
+         "time": 314432.000000,
+         "caller": "T68",
+         "msg": " example[68]"
+      },{
+         "pri": 69,
+         "time": 328509.000000,
+         "caller": "T69",
+         "msg": " example[69]"
+      },{
+         "pri": 70,
+         "time": 343000.000000,
+         "caller": "T70",
+         "msg": " example[70]"
+      },{
+         "pri": 71,
+         "time": 357911.000000,
+         "caller": "T71",
+         "msg": " example[71]"
+      },{
+         "pri": 72,
+         "time": 373248.000000,
+         "caller": "T72",
+         "msg": " example[72]"
+      },{
+         "pri": 73,
+         "time": 389017.000000,
+         "caller": "T73",
+         "msg": " example[73]"
+      },{
+         "pri": 74,
+         "time": 405224.000000,
+         "caller": "T74",
+         "msg": " example[74]"
+      },{
+         "pri": 75,
+         "time": 421875.000000,
+         "caller": "T75",
+         "msg": " example[75]"
+      },{
+         "pri": 76,
+         "time": 438976.000000,
+         "caller": "T76",
+         "msg": " example[76]"
+      },{
+         "pri": 77,
+         "time": 456533.000000,
+         "caller": "T77",
+         "msg": " example[77]"
+      },{
+         "pri": 78,
+         "time": 474552.000000,
+         "caller": "T78",
+         "msg": " example[78]"
+      },{
+         "pri": 79,
+         "time": 493039.000000,
+         "caller": "T79",
+         "msg": " example[79]"
+      },{
+         "pri": 80,
+         "time": 512000.000000,
+         "caller": "T80",
+         "msg": " example[80]"
+      },{
+         "pri": 81,
+         "time": 531441.000000,
+         "caller": "T81",
+         "msg": " example[81]"
+      },{
+         "pri": 82,
+         "time": 551368.000000,
+         "caller": "T82",
+         "msg": " example[82]"
+      },{
+         "pri": 83,
+         "time": 571787.000000,
+         "caller": "T83",
+         "msg": " example[83]"
+      },{
+         "pri": 84,
+         "time": 592704.000000,
+         "caller": "T84",
+         "msg": " example[84]"
+      },{
+         "pri": 85,
+         "time": 614125.000000,
+         "caller": "T85",
+         "msg": " example[85]"
+      },{
+         "pri": 86,
+         "time": 636056.000000,
+         "caller": "T86",
+         "msg": " example[86]"
+      },{
+         "pri": 87,
+         "time": 658503.000000,
+         "caller": "T87",
+         "msg": " example[87]"
+      },{
+         "pri": 88,
+         "time": 681472.000000,
+         "caller": "T88",
+         "msg": " example[88]"
+      },{
+         "pri": 89,
+         "time": 704969.000000,
+         "caller": "T89",
+         "msg": " example[89]"
+      },{
+         "pri": 90,
+         "time": 729000.000000,
+         "caller": "T90",
+         "msg": " example[90]"
+      },{
+         "pri": 91,
+         "time": 753571.000000,
+         "caller": "T91",
+         "msg": " example[91]"
+      },{
+         "pri": 92,
+         "time": 778688.000000,
+         "caller": "T92",
+         "msg": " example[92]"
+      },{
+         "pri": 93,
+         "time": 804357.000000,
+         "caller": "T93",
+         "msg": " example[93]"
+      },{
+         "pri": 94,
+         "time": 830584.000000,
+         "caller": "T94",
+         "msg": " example[94]"
+      },{
+         "pri": 95,
+         "time": 857375.000000,
+         "caller": "T95",
+         "msg": " example[95]"
+      },{
+         "pri": 96,
+         "time": 884736.000000,
+         "caller": "T96",
+         "msg": " example[96]"
+      },{
+         "pri": 97,
+         "time": 912673.000000,
+         "caller": "T97",
+         "msg": " example[97]"
+      },{
+         "pri": 98,
+         "time": 941192.000000,
+         "caller": "T98",
+         "msg": " example[98]"
+      },{
+         "pri": 99,
+         "time": 970299.000000,
+         "caller": "T99",
+         "msg": " example[99]"
+      },{
+         "pri": 100,
+         "time": 1000000.000000,
+         "caller": "T100",
+         "msg": " example[100]"
+      },{
+         "pri": 101,
+         "time": 1030301.000000,
+         "caller": "T101",
+         "msg": " example[101]"
+      },{
+         "pri": 102,
+         "time": 1061208.000000,
+         "caller": "T102",
+         "msg": " example[102]"
+      },{
+         "pri": 103,
+         "time": 1092727.000000,
+         "caller": "T103",
+         "msg": " example[103]"
+      },{
+         "pri": 104,
+         "time": 1124864.000000,
+         "caller": "T104",
+         "msg": " example[104]"
+      }
+   ]
+}
diff --git a/tests/expected/dmesg/kmsg-file-printk-caller b/tests/expected/dmesg/kmsg-file-printk-caller
new file mode 100644
index 000000000..785d730a5
--- /dev/null
+++ b/tests/expected/dmesg/kmsg-file-printk-caller
@@ -0,0 +1,115 @@
+{
+   "dmesg": [
+      {
+         "pri": 5,
+         "time":     0.000000,
+         "caller": "T0",
+         "msg": "Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T1",
+         "msg": "Command line: initrd=\\ucode.img initrd=\\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T2",
+         "msg": "BIOS-provided physical RAM map:"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T3",
+         "msg": "BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T4",
+         "msg": "BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T5",
+         "msg": "BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T6",
+         "msg": "BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T7",
+         "msg": "BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T8",
+         "msg": "BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T9",
+         "msg": "BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T10",
+         "msg": "BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved"
+      },{
+         "pri": 6,
+         "time":     0.367657,
+         "caller": "T11",
+         "msg": "ACPI: \\_SB_.PCI0.GP19.NHI1.PWRS: New power resource"
+      },{
+         "pri": 6,
+         "time":     0.368615,
+         "caller": "T12",
+         "msg": "ACPI: \\_SB_.PCI0.GP19.XHC4.PWRS: New power resource"
+      },{
+         "pri": 6,
+         "time":     0.376316,
+         "caller": "T13",
+         "msg": "ACPI: \\_SB_.PRWL: New power resource"
+      },{
+         "pri": 6,
+         "time":     0.376343,
+         "caller": "T14",
+         "msg": "ACPI: \\_SB_.PRWB: New power resource"
+      },{
+         "pri": 6,
+         "time":     0.377373,
+         "caller": "T15",
+         "msg": "ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])"
+      },{
+         "pri": 6,
+         "time":     0.377378,
+         "caller": "T16",
+         "msg": "acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]"
+      },{
+         "pri": 6,
+         "time":     0.377569,
+         "caller": "T17",
+         "msg": "acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]"
+      },{
+         "pri": 6,
+         "time":     0.377933,
+         "caller": "T18",
+         "msg": "acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]"
+      },{
+         "pri": 6,
+         "time":     0.378458,
+         "caller": "T19",
+         "msg": "PCI host bridge to bus 0000:00"
+      },{
+         "pri": 6,
+         "time":     0.378459,
+         "caller": "T20",
+         "msg": "pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]"
+      },{
+         "pri": 6,
+         "time":     0.378461,
+         "caller": "T21",
+         "msg": "pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]"
+      }
+   ]
+}
diff --git a/tests/expected/dmesg/limit-kmsg-printk-caller b/tests/expected/dmesg/limit-kmsg-printk-caller
new file mode 100644
index 000000000..2ea07d4c8
--- /dev/null
+++ b/tests/expected/dmesg/limit-kmsg-printk-caller
@@ -0,0 +1,11 @@
+[    0.367657] [    T11] ACPI: \_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+[    0.368615] [    T12] ACPI: \_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+[    0.376316] [    T13] ACPI: \_SB_.PRWL: New power resource
+[    0.376343] [    T14] ACPI: \_SB_.PRWB: New power resource
+[    0.377373] [    T15] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+[    0.377378] [    T16] acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+[    0.377569] [    T17] acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]
+[    0.377933] [    T18] acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+[    0.378458] [    T19] PCI host bridge to bus 0000:00
+[    0.378459] [    T20] pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]
+[    0.378461] [    T21] pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]
diff --git a/tests/ts/dmesg/colors-kmsg-printk-caller b/tests/ts/dmesg/colors-kmsg-printk-caller
new file mode 100755
index 000000000..513ca82d4
--- /dev/null
+++ b/tests/ts/dmesg/colors-kmsg-printk-caller
@@ -0,0 +1,29 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="colors-kmsg-prtk-caller"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+ts_inhibit_custom_colorscheme
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG --color=always -K $TS_SELF/kmsg-input-printk-caller -x >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/console-levels-kmsg-printk-caller b/tests/ts/dmesg/console-levels-kmsg-printk-caller
new file mode 100755
index 000000000..00b8b3681
--- /dev/null
+++ b/tests/ts/dmesg/console-levels-kmsg-printk-caller
@@ -0,0 +1,36 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="levels-kmsg-prtk-caller"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+for I in {-1..8}; do
+	$TS_HELPER_DMESG -K $TS_SELF/kmsg-input-printk-caller -l $I >> $TS_OUTPUT 2>/dev/null
+done
+
+$TS_HELPER_DMESG -K $TS_SELF/kmsg-input-printk-caller -l err+ >> $TS_OUTPUT 2>/dev/null
+$TS_HELPER_DMESG -K $TS_SELF/kmsg-input-printk-caller -l emerg+ >> $TS_OUTPUT 2>/dev/null
+$TS_HELPER_DMESG -K $TS_SELF/kmsg-input-printk-caller -l +err >> $TS_OUTPUT 2>/dev/null
+$TS_HELPER_DMESG -K $TS_SELF/kmsg-input-printk-caller -l +debug >> $TS_OUTPUT 2>/dev/null
+$TS_HELPER_DMESG -K $TS_SELF/kmsg-input-printk-caller -l + 2>> $TS_OUTPUT >/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/decode-kmsg-printk-caller b/tests/ts/dmesg/decode-kmsg-printk-caller
new file mode 100755
index 000000000..d05b9fb68
--- /dev/null
+++ b/tests/ts/dmesg/decode-kmsg-printk-caller
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="decode-kmsg-prtk-caller"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG -x -K $TS_SELF/kmsg-input-printk-caller >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/delta-kmsg-printk-caller b/tests/ts/dmesg/delta-kmsg-printk-caller
new file mode 100755
index 000000000..020b82357
--- /dev/null
+++ b/tests/ts/dmesg/delta-kmsg-printk-caller
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="delta-kmsg-prtk-caller"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG -d -K $TS_SELF/kmsg-input-printk-caller >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/facilities-kmsg-printk-caller b/tests/ts/dmesg/facilities-kmsg-printk-caller
new file mode 100755
index 000000000..bec301516
--- /dev/null
+++ b/tests/ts/dmesg/facilities-kmsg-printk-caller
@@ -0,0 +1,30 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="facilities-kmsg-prtk-caller"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+for I in {-1..12}; do
+	$TS_HELPER_DMESG -K $TS_SELF/kmsg-input-printk-caller -f $I -x >> $TS_OUTPUT 2>/dev/null
+done
+
+ts_finalize
diff --git a/tests/ts/dmesg/indentation-kmsg-printk-caller b/tests/ts/dmesg/indentation-kmsg-printk-caller
new file mode 100755
index 000000000..53e549b62
--- /dev/null
+++ b/tests/ts/dmesg/indentation-kmsg-printk-caller
@@ -0,0 +1,40 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="indentation-kmsg-prtk-caller"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG -K $TS_SELF/newlines-kmsg-printk-caller >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG -K $TS_SELF/newlines-kmsg-printk-caller -x >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=delta --kmsg-file $TS_SELF/newlines-kmsg-printk-caller >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=notime --kmsg-file $TS_SELF/newlines-kmsg-printk-caller >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=reltime --kmsg-file $TS_SELF/newlines-kmsg-printk-caller >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=ctime --kmsg-file $TS_SELF/newlines-kmsg-printk-caller >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=iso --kmsg-file $TS_SELF/newlines-kmsg-printk-caller >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+ts_finalize
diff --git a/tests/ts/dmesg/input-syslog-printk-caller b/tests/ts/dmesg/input-syslog-printk-caller
new file mode 100644
index 000000000..5fcff6abe
--- /dev/null
+++ b/tests/ts/dmesg/input-syslog-printk-caller
@@ -0,0 +1,105 @@
+<0>[    0.000000] [    T0] example[0]
+<1>[    1.000000] [    T1] example[1]
+<2>[    8.000000] [    T2] example[2]
+<3>[   27.000000] [    T3] example[3]
+<4>[   64.000000] [    T4] example[4]
+<5>[  125.000000] [    T5] example[5]
+<6>[  216.000000] [    T6] example[6]
+<7>[  343.000000] [    T7] example[7]
+<8>[  512.000000] [    T8] example[8]
+<9>[  729.000000] [    T9] example[9]
+<10>[ 1000.000000] [   T10] example[10]
+<11>[ 1331.000000] [   T11] example[11]
+<12>[ 1728.000000] [   T12] example[12]
+<13>[ 2197.000000] [   T13] example[13]
+<14>[ 2744.000000] [   T14] example[14]
+<15>[ 3375.000000] [   T15] example[15]
+<16>[ 4096.000000] [   T16] example[16]
+<17>[ 4913.000000] [   T17] example[17]
+<18>[ 5832.000000] [   T18] example[18]
+<19>[ 6859.000000] [   T19] example[19]
+<20>[ 8000.000000] [   T20] example[20]
+<21>[ 9261.000000] [   T21] example[21]
+<22>[10648.000000] [   T22] example[22]
+<23>[12167.000000] [   T23] example[23]
+<24>[13824.000000] [   T24] example[24]
+<25>[15625.000000] [   T25] example[25]
+<26>[17576.000000] [   T26] example[26]
+<27>[19683.000000] [   T27] example[27]
+<28>[21952.000000] [   T28] example[28]
+<29>[24389.000000] [   T29] example[29]
+<30>[27000.000000] [   T10] example[30]
+<31>[29791.000000] [   T31] example[31]
+<32>[32768.000000] [   T32] example[32]
+<33>[35937.000000] [   T33] example[33]
+<34>[39304.000000] [   T34] example[34]
+<35>[42875.000000] [   T35] example[35]
+<36>[46656.000000] [   T36] example[36]
+<37>[50653.000000] [   T37] example[37]
+<38>[54872.000000] [   T38] example[38]
+<39>[59319.000000] [   T39] example[39]
+<40>[64000.000000] [   T40] example[40]
+<41>[68921.000000] [   T41] example[41]
+<42>[74088.000000] [   T42] example[42]
+<43>[79507.000000] [   T43] example[43]
+<44>[85184.000000] [   T44] example[44]
+<45>[91125.000000] [   T45] example[45]
+<46>[97336.000000] [   T46] example[46]
+<47>[103823.000000] [   T47] example[47]
+<48>[110592.000000] [   T48] example[48]
+<49>[117649.000000] [   T49] example[49]
+<50>[125000.000000] [   T50] example[50]
+<51>[132651.000000] [   T51] example[51]
+<52>[140608.000000] [   T52] example[52]
+<53>[148877.000000] [   T53] example[53]
+<54>[157464.000000] [   T54] example[54]
+<55>[166375.000000] [   T55] example[55]
+<56>[175616.000000] [   T56] example[56]
+<57>[185193.000000] [   T57] example[57]
+<58>[195112.000000] [   T58] example[58]
+<59>[205379.000000] [   T59] example[59]
+<60>[216000.000000] [   T60] example[60]
+<61>[226981.000000] [   T61] example[61]
+<62>[238328.000000] [   T62] example[62]
+<63>[250047.000000] [   T63] example[63]
+<64>[262144.000000] [   T64] example[64]
+<65>[274625.000000] [   T65] example[65]
+<66>[287496.000000] [   T66] example[66]
+<67>[300763.000000] [   T67] example[67]
+<68>[314432.000000] [   T68] example[68]
+<69>[328509.000000] [   T69] example[69]
+<70>[343000.000000] [   T70] example[70]
+<71>[357911.000000] [   T71] example[71]
+<72>[373248.000000] [   T72] example[72]
+<73>[389017.000000] [   T73] example[73]
+<74>[405224.000000] [   T74] example[74]
+<75>[421875.000000] [   T75] example[75]
+<76>[438976.000000] [   T76] example[76]
+<77>[456533.000000] [   T77] example[77]
+<78>[474552.000000] [   T78] example[78]
+<79>[493039.000000] [   T79] example[79]
+<80>[512000.000000] [   T80] example[80]
+<81>[531441.000000] [   T81] example[81]
+<82>[551368.000000] [   T82] example[82]
+<83>[571787.000000] [   T83] example[83]
+<84>[592704.000000] [   T84] example[84]
+<85>[614125.000000] [   T85] example[85]
+<86>[636056.000000] [   T86] example[86]
+<87>[658503.000000] [   T87] example[87]
+<88>[681472.000000] [   T88] example[88]
+<89>[704969.000000] [   T89] example[89]
+<90>[729000.000000] [   T90] example[90]
+<91>[753571.000000] [   T91] example[91]
+<92>[778688.000000] [   T92] example[92]
+<93>[804357.000000] [   T93] example[93]
+<94>[830584.000000] [   T94] example[94]
+<95>[857375.000000] [   T95] example[95]
+<96>[884736.000000] [   T96] example[96]
+<97>[912673.000000] [   T97] example[97]
+<98>[941192.000000] [   T98] example[98]
+<99>[970299.000000] [   T99] example[99]
+<100>[1000000.000000] [  T100] example[100]
+<101>[1030301.000000] [  T101] example[101]
+<102>[1061208.000000] [  T102] example[102]
+<103>[1092727.000000] [  T103] example[103]
+<104>[1124864.000000] [  T104] example[104]
diff --git a/tests/ts/dmesg/json-kmsg-printk-caller b/tests/ts/dmesg/json-kmsg-printk-caller
new file mode 100755
index 000000000..cb6c5e4a8
--- /dev/null
+++ b/tests/ts/dmesg/json-kmsg-printk-caller
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="json-kmsg-prtk-caller"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG -J -K $TS_SELF/kmsg-input-printk-caller >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/json-syslog-printk-caller b/tests/ts/dmesg/json-syslog-printk-caller
new file mode 100755
index 000000000..10dfaa423
--- /dev/null
+++ b/tests/ts/dmesg/json-syslog-printk-caller
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="json-syslog-prtk-caller"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG -J -F $TS_SELF/input-syslog-printk-caller >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/kmsg-file-printk-caller b/tests/ts/dmesg/kmsg-file-printk-caller
new file mode 100755
index 000000000..a01fc723f
--- /dev/null
+++ b/tests/ts/dmesg/kmsg-file-printk-caller
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="kmsg-file-prtk-caller"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG -J -K $TS_SELF/kmsg-input-printk-caller >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/kmsg-input-printk-caller b/tests/ts/dmesg/kmsg-input-printk-caller
new file mode 100644
index 0000000000000000000000000000000000000000..8d67f11cad7988469dd5e4a7c8589d2b744168bb
GIT binary patch
literal 2187
zcmbW2TW{hx6oB`+zv4*yQZ$g-aqb9dAw>nL(1<WMu@wr5q0uIBlmsaMe(Z!%<LSbv
zlRV_&oX=m5?PI-*_}S}*L6Xp7utfdGINQI%ffi-VGB6ZF(Rx7<zTh5)+e9?}BOdF!
z4&3g-5N;n_w*#0cs)9j9DnS;)U3i#(h9u&x{5s-+Rh*O^P!$a;r~`jv@Mj))i}85o
zE!X$o=fm05g&E7bfHb(LVT}TW9MyKP4WAG{ZvHa5STe?am!)ZtMZlG)1928tMKt*L
zRS)+ei>MN(yY|bvJxI4@ul|L)xi~^toboE7hd88zJAS>(4k<+$&WTf=%8I5=6qjL8
zL{KnRHJ_wGp3~y4X%}XyWTy5<(<i@|7wiy6G=lu)RK`5fuo%vO$2uZ}NFk&Np_Ymq
zSfw-t^eTS4ee|SPHr;Nw&#*6pO+p1wlYrWFpuOc}8Mxs*4lHO%ivx`WQkRhWRV1!e
z+ekYQM9I;RfW|eTy?GCe&cL>#DIv|PNctWrvM4)R641H|6j_w>Xm5!~<TDIiZwm7-
zzR063A?@o(63R$TCHk+9SYEssT|x4A;}=U!)6d9uCN)C3#4rurY}Eyf`{GX=5bJ8~
zkJgIkPLcB9VOyC`rdaX5E_?^(^awdS(n8E1wlBhFN)n9|Ed%RqqI#M5ZQ^RbA?jUX
z8U!0{B6&w#e0{tu#TOq(XrztM{s%F-j4(OEB&LMW&j_9%Snyf_qau!W6jmZ*&u|;D
zG>9`^*ARl$W?%BV9-k?ldhrsgAzE!IqaTEM4Bp&BLu5I;BEtH~cO7{0q1@*=E2<J!
z<JXF2yw12R+r~Q>`rZuOgoXd{t50_+&G=U{e+uLK1x&nez2zyV<oO2t&m;f4zZ}m7
zqMIAIAAgy;<H0BK<h*s-_}RiwH|(~bdC4zNf@;f(6e31T$apT!y0G#mo;zVxp6t2m
zc=16E4G9gK&(ycA3tN{oc$zZCOFYY}f+ajvd?e`4&b`?f#IqaZ!6r`P>I9F=1>Ae?
zN1ZTtvNT;9I=e5X!3!%Z*fi6iV$cjaAI4@s(=@e-Y$sJk{XC4<txuhL=c$8#E-qNb
x49;7GD7oR*gkzjV>?paPL2n~_e!=^1N$^$A^$pxgsfs@$5!EG7)Tlp__yL<dZm0kN

literal 0
HcmV?d00001

diff --git a/tests/ts/dmesg/limit-kmsg-printk-caller b/tests/ts/dmesg/limit-kmsg-printk-caller
new file mode 100755
index 000000000..4d4d9912d
--- /dev/null
+++ b/tests/ts/dmesg/limit-kmsg-printk-caller
@@ -0,0 +1,29 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="limit-kmsg-prtk-caller"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG --since @1234567890.124 --until @1234567991 -K $TS_SELF/kmsg-input-printk-caller \
+	>> $TS_OUTPUT 2> $TS_ERRLOG
+
+ts_finalize
diff --git a/tests/ts/dmesg/newlines-kmsg-printk-caller b/tests/ts/dmesg/newlines-kmsg-printk-caller
new file mode 100644
index 0000000000000000000000000000000000000000..574d2177796677b73f1efcf273005169ed832c60
GIT binary patch
literal 152
zcmXrjF#tkco#e!voYW%Q5CiL+%)C^Es??%<E(Svb9YY;M128~RV`!b1TFwPh$Hia-
tQeuRm#K^j&Jf91MLCT7`7>o^cjC71K)EQfsWE7>QazV)4{GwE-1^{d2D<=Q|

literal 0
HcmV?d00001

-- 
2.43.0


^ permalink raw reply related

* [PATCH] util-linux/sys-utils dmesg add PRINTK_CALLER support
From: Edward Chron @ 2023-12-13  0:04 UTC (permalink / raw)
  To: util-linux; +Cc: colona, echron

Submission to Project: util-linux
Open Incident: #2906 at github.com/util-linux/util-linux/issues/2906
Component: util-linux/sys-utils
File: dmesg.c
Code level patch applied against: 2.39.3 - latest code pulled from
           git.github.com:util-linux/util-linux.git
Revision: #1 on 2023/12/08 per Review from Karel Zak
Revision: #2 on 2023/12/12 Adjust line offsets for master update and
                           Add caller_id_size init to dmesg -K and
                           Add support for required dmesg tests

Add support to standard dmesg command for the optional Linux Kernel
debug CONFIG option PRINTK_CALLER which adds an optional dmesg field
that contains the Thread Id or CPU Id that is issuing the printk to
add the message to the kernel ring buffer. This makes debugging simpler
as dmesg entries for a specific thread or CPU can be recognized.

The dmesg -S using the old syslog interface supports printing the
PRINTK_CALLER field but currently standard dmesg does not support
printing the field if present. There are utilities that use dmesg and
so it would be optimal if dmesg supported PRINTK_CALLER as well.

The additional field provided by PRINTK_CALLER is only present
if it was configured for the Linux kernel where the dmesg command
is run. It is a debug option and not configured by default so the
dmesg output will only change for those kernels where the option was
configured when the kernel was built. For users who went to the
trouble to configure PRINTK_CALLER and have the extra field available
for debugging, having dmesg print the field is very helpful.

Size of the PRINTK_CALLER field is determined by the maximum number
tasks that can be run on the system which is limited by the value of
/proc/sys/kernel/pid_max as pid values are from 0 to value - 1.
This value determines the number of id digits needed by the caller id.
The PRINTK_CALLER field is printed as T<id> for a Task Id or C<id>
for a CPU Id for a printk in CPU context. The values are left space
padded and enclosed in parentheses such as: [    T123] or [     C16]

For consistency with dmesg -S which supports the PRINTK_CALLER field
the field is printed followed by a space. For JSON format output the
PRINTK_CALLER field is identified as caller as that is consistent with
it's naming in /dev/kmsg. No space padding is used to reduce space
consumed by the JSON output. So the output from the command on a system
with PRINTK_CALLER field enabled in the Linux .config file the dmesg
output appears as:

> dmesg
...
[  520.897104] [   T3919] usb 3-3: Product: USB 2.0 Hub

and

> dmesg -x
...
kern  :info  : [  520.897104] [   T3919] usb 3-3: Product: USB 2.0 Hub

and

> dmesg -J
...
      },{
         "pri": 6,
         "time":    520.897104,
         "caller": "T3919",
         "msg": "usb 3-3: Product: USB 2.0 Hub"
      },{

and

> dmesg -J -x
...
      },{
         "fac": "kern",
         "pri": "info",
         "time":   520.897104,
         "caller": "T3919",
         "msg": "usb 3-3: Product: USB 2.0 Hub"
      },{

>

For comparison:

> dmesg -S
...
[  520.897104] [ T3919] usb 3-3: Product: USB 2.0 Hub

and

> dmesg -S -x
...
kern  :info  : [  520.897104] [ T3919] usb 3-3: Product: USB 2.0 Hub

Note: When dmesg uses the old syslog interface the reserved space for
      the PRINTK_CALLER field is capped at 5 digits because 32-bit
      kernels are capped at 32768 as the max number of PIDs. However,
      64-bit systems are currently capped at 2^22 PIDs (0 - 4194303).
      The PID cap is set by PID_MAX_LIMIT but the system limit can be
      less so we use /proc/sys/kernel/pid_max to determine the size
      needed to hold the maximum PID value size for the current system.
      Many 64-bit systems support 2^22 PIDs (0 - 4194303) and you see:

> dmesg -x
...
kern  :info  : [  520.899558] [   T3919] hub 3-3:1.0: USB hub found
...
kern  :info  : [ 9830.456898] [  T98982] cgroup: fork rejected by pids ...
kern  :info  : [14301.158878] [ T137336] cgroup: fork rejected by pids ...
kern  :info  : [18980.803190] [T1637865] cgroup: fork rejected by pids ...

> dmesg -S -x
...
kern  :info  : [  520.899558] [ T3919] hub 3-3:1.0: USB hub found
...
kern  :info  : [ 9830.456898] [T98982] cgroup: fork rejected by pids ...
kern  :info  : [14301.158878] [T137336] cgroup: fork rejected by pids ...
kern  :info  : [18980.803190] [T1637865] cgroup: fork rejected by pids ...

This is the only difference seen with PRINTK_CALLER configured and
printing between the dmesg /dev/kmsg interface and the dmesg -S syslog
interface.

Signed-off-by: Ivan Delalande <colona@arista.com>
Signed-off-by: Edward Chron <echron@arista.com>
---
 include/pathnames.h                           |   3 +
 sys-utils/dmesg.c                             | 114 +++-
 .../expected/dmesg/colors-kmsg-printk-caller  |  22 +
 .../dmesg/console-levels-kmsg-printk-caller   |  45 ++
 .../expected/dmesg/decode-kmsg-printk-caller  |  22 +
 tests/expected/dmesg/delta-kmsg-printk-caller |  22 +
 .../dmesg/facilities-kmsg-printk-caller       |  22 +
 .../dmesg/indentation-kmsg-printk-caller      |  28 +
 tests/expected/dmesg/json-kmsg-printk-caller  | 115 ++++
 .../expected/dmesg/json-syslog-printk-caller  | 530 ++++++++++++++++++
 tests/expected/dmesg/kmsg-file-printk-caller  | 115 ++++
 tests/expected/dmesg/limit-kmsg-printk-caller |  11 +
 tests/ts/dmesg/colors-kmsg-printk-caller      |  29 +
 .../dmesg/console-levels-kmsg-printk-caller   |  36 ++
 tests/ts/dmesg/decode-kmsg-printk-caller      |  28 +
 tests/ts/dmesg/delta-kmsg-printk-caller       |  28 +
 tests/ts/dmesg/facilities-kmsg-printk-caller  |  30 +
 tests/ts/dmesg/indentation-kmsg-printk-caller |  40 ++
 tests/ts/dmesg/input-syslog-printk-caller     | 105 ++++
 tests/ts/dmesg/json-kmsg-printk-caller        |  28 +
 tests/ts/dmesg/json-syslog-printk-caller      |  28 +
 tests/ts/dmesg/kmsg-file-printk-caller        |  28 +
 tests/ts/dmesg/kmsg-input-printk-caller       | Bin 0 -> 2187 bytes
 tests/ts/dmesg/limit-kmsg-printk-caller       |  29 +
 tests/ts/dmesg/newlines-kmsg-printk-caller    | Bin 0 -> 152 bytes
 25 files changed, 1457 insertions(+), 1 deletion(-)
 create mode 100644 tests/expected/dmesg/colors-kmsg-printk-caller
 create mode 100644 tests/expected/dmesg/console-levels-kmsg-printk-caller
 create mode 100644 tests/expected/dmesg/decode-kmsg-printk-caller
 create mode 100644 tests/expected/dmesg/delta-kmsg-printk-caller
 create mode 100644 tests/expected/dmesg/facilities-kmsg-printk-caller
 create mode 100644 tests/expected/dmesg/indentation-kmsg-printk-caller
 create mode 100644 tests/expected/dmesg/json-kmsg-printk-caller
 create mode 100644 tests/expected/dmesg/json-syslog-printk-caller
 create mode 100644 tests/expected/dmesg/kmsg-file-printk-caller
 create mode 100644 tests/expected/dmesg/limit-kmsg-printk-caller
 create mode 100755 tests/ts/dmesg/colors-kmsg-printk-caller
 create mode 100755 tests/ts/dmesg/console-levels-kmsg-printk-caller
 create mode 100755 tests/ts/dmesg/decode-kmsg-printk-caller
 create mode 100755 tests/ts/dmesg/delta-kmsg-printk-caller
 create mode 100755 tests/ts/dmesg/facilities-kmsg-printk-caller
 create mode 100755 tests/ts/dmesg/indentation-kmsg-printk-caller
 create mode 100644 tests/ts/dmesg/input-syslog-printk-caller
 create mode 100755 tests/ts/dmesg/json-kmsg-printk-caller
 create mode 100755 tests/ts/dmesg/json-syslog-printk-caller
 create mode 100755 tests/ts/dmesg/kmsg-file-printk-caller
 create mode 100644 tests/ts/dmesg/kmsg-input-printk-caller
 create mode 100755 tests/ts/dmesg/limit-kmsg-printk-caller
 create mode 100644 tests/ts/dmesg/newlines-kmsg-printk-caller

diff --git a/include/pathnames.h b/include/pathnames.h
index caf0e63d4..81fa405f6 100644
--- a/include/pathnames.h
+++ b/include/pathnames.h
@@ -230,4 +230,7 @@
 /* cgroup path */
 #define _PATH_SYS_CGROUP	"/sys/fs/cgroup"
 
+/* Maximum number of PIDs system supports */
+#define _PATH_PROC_PIDMAX	"/proc/sys/kernel/pid_max"
+
 #endif /* PATHNAMES_H */
diff --git a/sys-utils/dmesg.c b/sys-utils/dmesg.c
index 77728b419..5a04af3e6 100644
--- a/sys-utils/dmesg.c
+++ b/sys-utils/dmesg.c
@@ -13,7 +13,9 @@
  */
 #include <stdio.h>
 #include <getopt.h>
+#include <stdbool.h>
 #include <stdlib.h>
+#include <string.h>
 #include <sys/klog.h>
 #include <sys/syslog.h>
 #include <sys/time.h>
@@ -41,6 +43,7 @@
 #include "mangle.h"
 #include "pager.h"
 #include "jsonwrt.h"
+#include "pathnames.h"
 
 /* Close the log.  Currently a NOP. */
 #define SYSLOG_ACTION_CLOSE          0
@@ -65,6 +68,11 @@
 /* Return size of the log buffer */
 #define SYSLOG_ACTION_SIZE_BUFFER   10
 
+#define PID_CHARS_MAX sizeof(stringify_value(LONG_MAX))
+#define PID_CHARS_DEFAULT sizeof(stringify_value(INT_MAX))
+#define DMESG_CALLER_PREFIX "caller="
+#define DMESG_CALLER_PREFIXSZ (sizeof(DMESG_CALLER_PREFIX)-1)
+
 /*
  * Color scheme
  */
@@ -233,6 +241,7 @@ struct dmesg_control {
 			force_prefix:1;	/* force timestamp and decode prefix
 					   on each line */
 	int		indent;		/* due to timestamps if newline */
+	size_t          caller_id_size;   /* PRINTK_CALLERID max field size */
 };
 
 struct dmesg_record {
@@ -242,6 +251,7 @@ struct dmesg_record {
 	int		level;
 	int		facility;
 	struct timeval  tv;
+	char		caller_id[PID_CHARS_MAX];
 
 	const char	*next;		/* buffer with next unparsed record */
 	size_t		next_size;	/* size of the next buffer */
@@ -254,6 +264,7 @@ struct dmesg_record {
 		(_r)->level = -1; \
 		(_r)->tv.tv_sec = 0; \
 		(_r)->tv.tv_usec = 0; \
+		(_r)->caller_id[0] = 0; \
 	} while (0)
 
 static int process_kmsg(struct dmesg_control *ctl);
@@ -551,6 +562,45 @@ static int get_syslog_buffer_size(void)
 	return n > 0 ? n : 0;
 }
 
+/*
+ * Get the number of characters needed to hold the maximum number
+ * of tasks this system supports. This size of string could hold
+ * a thread id large enough for the highest thread id.
+ * This is needed to determine the number of characters reserved for
+ * the PRINTK_CALLER field if it has been configured in the Linux Kernel.
+ *
+ * The number of digits sets the max value since the value can't exceed
+ * a value of that size. The /proc field defined by _PATH_PROC_PIDMAX
+ * holds the maximum number of PID values that may be ussed by the system,
+ * so 0 to that value minus one.
+ *
+ * For determining the size of the PRINTK_CALLER field, we make the safe
+ * assumption that the number of threads >= number of cpus. This because
+ * the PRINTK_CALLER field can hold either a thread id or a CPU id value.
+ *
+ * If we can't access the pid max kernel proc entry we assign a default
+ * field size of 5 characters as that is what the old syslog interface
+ * uses as the reserved field size. This is justified because 32-bit Linux
+ * systems are limited to PID values between (0-32767).
+ *
+ */
+static size_t max_threads_id_size(void)
+{
+	char taskmax[PID_CHARS_MAX] = {'\0'};
+	ssize_t rdsize;
+	int fd;
+
+	fd = open(_PATH_PROC_PIDMAX, O_RDONLY);
+	if (fd == -1)
+		return PID_CHARS_DEFAULT;
+
+	rdsize = read(fd, taskmax, sizeof(taskmax));
+	if (rdsize == -1)
+		return PID_CHARS_DEFAULT;
+
+	return strnlen(taskmax, sizeof(taskmax));
+}
+
 /*
  * Reads messages from regular file by mmap
  */
@@ -728,6 +778,36 @@ static const char *skip_item(const char *begin, const char *end, const char *sep
 	return begin;
 }
 
+/*
+ * Checks to see if the caller (caller id) field is present in the kmsg record.
+ * This is true if the PRINTK_CALLER config option has been set in the kernel.
+ *
+ * If the caller_id is found in the kmsg buffer then return the id and id type
+ * to the caller in dmesg caller_id. Returns string pointer to next value.
+ *
+ */
+static const char *parse_callerid(const char *p_str, const char *end,
+				  struct dmesg_record *p_drec)
+{
+	const char *p_after;
+	const char *p_next;
+	size_t cid_size;
+	char *p_cid;
+
+	p_cid = strstr(p_str, DMESG_CALLER_PREFIX);
+	if (p_cid != NULL && p_drec != NULL) {
+		p_next = p_cid + DMESG_CALLER_PREFIXSZ;
+		p_after = skip_item(p_next, end, ",;");
+		cid_size = p_after - p_next;
+		if (cid_size < sizeof(p_drec->caller_id))
+			xstrncpy(p_drec->caller_id, p_next, cid_size);
+		else
+			return p_str;
+		return p_after;
+	}
+	return p_str;
+}
+
 /*
  * Parses one record from syslog(2) buffer
  */
@@ -795,6 +875,18 @@ static int get_next_syslog_record(struct dmesg_control *ctl,
 				begin++;
 		}
 
+		if (*begin == '[' && (*(begin + 1) == ' ' ||
+			(*(begin + 1) == 'T' || *(begin + 1) == 'C'))) {
+			const char *start = begin + 1;
+			size_t id_size;
+
+			start = start + strspn(start, " ");
+			begin = skip_item(begin, end, "]");
+			id_size = begin - start;
+			if (id_size < sizeof(rec->caller_id))
+				xstrncpy(rec->caller_id, start, id_size);
+		}
+
 		rec->mesg = begin;
 		rec->mesg_size = end - begin;
 
@@ -1101,6 +1193,19 @@ full_output:
 			color_disable();
 	}
 
+	if (*rec->caller_id) {
+		if (ctl->json) {
+			ul_jsonwrt_value_s(&ctl->jfmt, "caller", rec->caller_id);
+		} else {
+			char cidbuf[PID_CHARS_MAX+3] = {'\0'};
+
+			sprintf(cidbuf, "[%*s] ",
+				(char)ctl->caller_id_size - 1, rec->caller_id);
+			ctl->indent += strnlen(cidbuf, PID_CHARS_MAX+3);
+			fputs(cidbuf, stdout);
+		}
+	}
+
 	/*
 	 * A kernel message may contain several lines of output, separated
 	 * by '\n'.  If the timestamp and decode outputs are forced then each
@@ -1229,6 +1334,8 @@ static int init_kmsg(struct dmesg_control *ctl)
 		return -1;
 	}
 
+	ctl->caller_id_size = max_threads_id_size();
+
 	return 0;
 }
 
@@ -1284,7 +1391,10 @@ static int parse_kmsg_record(struct dmesg_control *ctl,
 		goto mesg;
 
 	/* D) optional fields (ignore) */
-	p = skip_item(p, end, ";");
+	p = skip_item(p, end, ",;");
+
+	/* Include optional PRINTK_CALLER field if it is present */
+	p = parse_callerid(p, end, rec);
 
 mesg:
 	/* E) message text */
@@ -1446,6 +1556,7 @@ int main(int argc, char *argv[])
 		.kmsg = -1,
 		.time_fmt = DMESG_TIMEFTM_TIME,
 		.indent = 0,
+		.caller_id_size = 0,
 	};
 	int colormode = UL_COLORMODE_UNDEF;
 	enum {
@@ -1542,6 +1653,7 @@ int main(int argc, char *argv[])
 		case 'K':
 			ctl.filename = optarg;
 			ctl.method = DMESG_METHOD_KMSG;
+			ctl.caller_id_size = max_threads_id_size();
 			break;
 		case 'f':
 			ctl.fltr_fac = 1;
diff --git a/tests/expected/dmesg/colors-kmsg-printk-caller b/tests/expected/dmesg/colors-kmsg-printk-caller
new file mode 100644
index 000000000..c7bf6e8b7
--- /dev/null
+++ b/tests/expected/dmesg/colors-kmsg-printk-caller
@@ -0,0 +1,22 @@
+kern  :notice: ^[[32m[    0.000000] ^[[0m[     T0] Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000
+kern  :info  : ^[[32m[    0.000000] ^[[0m[     T1] ^[[33mCommand line: ^[[0minitrd=\ucode.img initrd=\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system
+kern  :info  : ^[[32m[    0.000000] ^[[0m[     T2] BIOS-provided physical RAM map:
+kern  :info  : ^[[32m[    0.000000] ^[[0m[     T3] ^[[33mBIOS-e820: ^[[0m[mem 0x0000000000000000-0x000000000009efff] usable
+kern  :info  : ^[[32m[    0.000000] ^[[0m[     T4] ^[[33mBIOS-e820: ^[[0m[mem 0x000000000009f000-0x00000000000bffff] reserved
+kern  :info  : ^[[32m[    0.000000] ^[[0m[     T5] ^[[33mBIOS-e820: ^[[0m[mem 0x0000000000100000-0x0000000009afffff] usable
+kern  :info  : ^[[32m[    0.000000] ^[[0m[     T6] ^[[33mBIOS-e820: ^[[0m[mem 0x0000000009b00000-0x0000000009dfffff] reserved
+kern  :info  : ^[[32m[    0.000000] ^[[0m[     T7] ^[[33mBIOS-e820: ^[[0m[mem 0x0000000009e00000-0x0000000009efffff] usable
+kern  :info  : ^[[32m[    0.000000] ^[[0m[     T8] ^[[33mBIOS-e820: ^[[0m[mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS
+kern  :info  : ^[[32m[    0.000000] ^[[0m[     T9] ^[[33mBIOS-e820: ^[[0m[mem 0x0000000009f3c000-0x000000004235ffff] usable
+kern  :info  : ^[[32m[    0.000000] ^[[0m[    T10] ^[[33mBIOS-e820: ^[[0m[mem 0x0000000042360000-0x000000004455ffff] reserved
+kern  :info  : ^[[32m[    0.367657] ^[[0m[    T11] ^[[33mACPI: ^[[0m\_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+kern  :info  : ^[[32m[    0.368615] ^[[0m[    T12] ^[[33mACPI: ^[[0m\_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+kern  :info  : ^[[32m[    0.376316] ^[[0m[    T13] ^[[33mACPI: ^[[0m\_SB_.PRWL: New power resource
+kern  :info  : ^[[32m[    0.376343] ^[[0m[    T14] ^[[33mACPI: ^[[0m\_SB_.PRWB: New power resource
+kern  :info  : ^[[32m[    0.377373] ^[[0m[    T15] ^[[33mACPI: ^[[0mPCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+kern  :info  : ^[[32m[    0.377378] ^[[0m[    T16] ^[[33macpi PNP0A08:00: ^[[0m_OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+kern  :info  : ^[[32m[    0.377569] ^[[0m[    T17] ^[[33macpi PNP0A08:00: ^[[0m_OSC: platform does not support [SHPCHotplug AER]
+kern  :info  : ^[[32m[    0.377933] ^[[0m[    T18] ^[[33macpi PNP0A08:00: ^[[0m_OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+kern  :info  : ^[[32m[    0.378458] ^[[0m[    T19] PCI host bridge to bus 0000:00
+kern  :info  : ^[[32m[    0.378459] ^[[0m[    T20] ^[[33mpci_bus 0000:00: ^[[0mroot bus resource [io  0x0000-0x0cf7 window]
+kern  :info  : ^[[32m[    0.378461] ^[[0m[    T21] ^[[33mpci_bus 0000:00: ^[[0mroot bus resource [io  0x0d00-0xffff window]
diff --git a/tests/expected/dmesg/console-levels-kmsg-printk-caller b/tests/expected/dmesg/console-levels-kmsg-printk-caller
new file mode 100644
index 000000000..1f6e9f178
--- /dev/null
+++ b/tests/expected/dmesg/console-levels-kmsg-printk-caller
@@ -0,0 +1,45 @@
+[    0.000000] [     T0] Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000
+[    0.000000] [     T1] Command line: initrd=\ucode.img initrd=\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system
+[    0.000000] [     T2] BIOS-provided physical RAM map:
+[    0.000000] [     T3] BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable
+[    0.000000] [     T4] BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved
+[    0.000000] [     T5] BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable
+[    0.000000] [     T6] BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved
+[    0.000000] [     T7] BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable
+[    0.000000] [     T8] BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS
+[    0.000000] [     T9] BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable
+[    0.000000] [    T10] BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved
+[    0.367657] [    T11] ACPI: \_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+[    0.368615] [    T12] ACPI: \_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+[    0.376316] [    T13] ACPI: \_SB_.PRWL: New power resource
+[    0.376343] [    T14] ACPI: \_SB_.PRWB: New power resource
+[    0.377373] [    T15] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+[    0.377378] [    T16] acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+[    0.377569] [    T17] acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]
+[    0.377933] [    T18] acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+[    0.378458] [    T19] PCI host bridge to bus 0000:00
+[    0.378459] [    T20] pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]
+[    0.378461] [    T21] pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]
+[    0.000000] [     T0] Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000
+[    0.000000] [     T1] Command line: initrd=\ucode.img initrd=\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system
+[    0.000000] [     T2] BIOS-provided physical RAM map:
+[    0.000000] [     T3] BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable
+[    0.000000] [     T4] BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved
+[    0.000000] [     T5] BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable
+[    0.000000] [     T6] BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved
+[    0.000000] [     T7] BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable
+[    0.000000] [     T8] BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS
+[    0.000000] [     T9] BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable
+[    0.000000] [    T10] BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved
+[    0.367657] [    T11] ACPI: \_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+[    0.368615] [    T12] ACPI: \_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+[    0.376316] [    T13] ACPI: \_SB_.PRWL: New power resource
+[    0.376343] [    T14] ACPI: \_SB_.PRWB: New power resource
+[    0.377373] [    T15] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+[    0.377378] [    T16] acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+[    0.377569] [    T17] acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]
+[    0.377933] [    T18] acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+[    0.378458] [    T19] PCI host bridge to bus 0000:00
+[    0.378459] [    T20] pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]
+[    0.378461] [    T21] pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]
+test_dmesg: unknown level '+'
diff --git a/tests/expected/dmesg/decode-kmsg-printk-caller b/tests/expected/dmesg/decode-kmsg-printk-caller
new file mode 100644
index 000000000..78c363389
--- /dev/null
+++ b/tests/expected/dmesg/decode-kmsg-printk-caller
@@ -0,0 +1,22 @@
+kern  :notice: [    0.000000] [     T0] Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000
+kern  :info  : [    0.000000] [     T1] Command line: initrd=\ucode.img initrd=\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system
+kern  :info  : [    0.000000] [     T2] BIOS-provided physical RAM map:
+kern  :info  : [    0.000000] [     T3] BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable
+kern  :info  : [    0.000000] [     T4] BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved
+kern  :info  : [    0.000000] [     T5] BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable
+kern  :info  : [    0.000000] [     T6] BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved
+kern  :info  : [    0.000000] [     T7] BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable
+kern  :info  : [    0.000000] [     T8] BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS
+kern  :info  : [    0.000000] [     T9] BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable
+kern  :info  : [    0.000000] [    T10] BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved
+kern  :info  : [    0.367657] [    T11] ACPI: \_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+kern  :info  : [    0.368615] [    T12] ACPI: \_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+kern  :info  : [    0.376316] [    T13] ACPI: \_SB_.PRWL: New power resource
+kern  :info  : [    0.376343] [    T14] ACPI: \_SB_.PRWB: New power resource
+kern  :info  : [    0.377373] [    T15] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+kern  :info  : [    0.377378] [    T16] acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+kern  :info  : [    0.377569] [    T17] acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]
+kern  :info  : [    0.377933] [    T18] acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+kern  :info  : [    0.378458] [    T19] PCI host bridge to bus 0000:00
+kern  :info  : [    0.378459] [    T20] pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]
+kern  :info  : [    0.378461] [    T21] pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]
diff --git a/tests/expected/dmesg/delta-kmsg-printk-caller b/tests/expected/dmesg/delta-kmsg-printk-caller
new file mode 100644
index 000000000..892d2dcea
--- /dev/null
+++ b/tests/expected/dmesg/delta-kmsg-printk-caller
@@ -0,0 +1,22 @@
+[    0.000000 <    0.000000>] [     T0] Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000
+[    0.000000 <    0.000000>] [     T1] Command line: initrd=\ucode.img initrd=\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system
+[    0.000000 <    0.000000>] [     T2] BIOS-provided physical RAM map:
+[    0.000000 <    0.000000>] [     T3] BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable
+[    0.000000 <    0.000000>] [     T4] BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved
+[    0.000000 <    0.000000>] [     T5] BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable
+[    0.000000 <    0.000000>] [     T6] BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved
+[    0.000000 <    0.000000>] [     T7] BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable
+[    0.000000 <    0.000000>] [     T8] BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS
+[    0.000000 <    0.000000>] [     T9] BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable
+[    0.000000 <    0.000000>] [    T10] BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved
+[    0.367657 <    0.000000>] [    T11] ACPI: \_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+[    0.368615 <    0.000000>] [    T12] ACPI: \_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+[    0.376316 <    0.000000>] [    T13] ACPI: \_SB_.PRWL: New power resource
+[    0.376343 <    0.000000>] [    T14] ACPI: \_SB_.PRWB: New power resource
+[    0.377373 <    0.000000>] [    T15] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+[    0.377378 <    0.000000>] [    T16] acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+[    0.377569 <    0.000000>] [    T17] acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]
+[    0.377933 <    0.000000>] [    T18] acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+[    0.378458 <    0.000000>] [    T19] PCI host bridge to bus 0000:00
+[    0.378459 <    0.000000>] [    T20] pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]
+[    0.378461 <    0.000000>] [    T21] pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]
diff --git a/tests/expected/dmesg/facilities-kmsg-printk-caller b/tests/expected/dmesg/facilities-kmsg-printk-caller
new file mode 100644
index 000000000..78c363389
--- /dev/null
+++ b/tests/expected/dmesg/facilities-kmsg-printk-caller
@@ -0,0 +1,22 @@
+kern  :notice: [    0.000000] [     T0] Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000
+kern  :info  : [    0.000000] [     T1] Command line: initrd=\ucode.img initrd=\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system
+kern  :info  : [    0.000000] [     T2] BIOS-provided physical RAM map:
+kern  :info  : [    0.000000] [     T3] BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable
+kern  :info  : [    0.000000] [     T4] BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved
+kern  :info  : [    0.000000] [     T5] BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable
+kern  :info  : [    0.000000] [     T6] BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved
+kern  :info  : [    0.000000] [     T7] BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable
+kern  :info  : [    0.000000] [     T8] BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS
+kern  :info  : [    0.000000] [     T9] BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable
+kern  :info  : [    0.000000] [    T10] BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved
+kern  :info  : [    0.367657] [    T11] ACPI: \_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+kern  :info  : [    0.368615] [    T12] ACPI: \_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+kern  :info  : [    0.376316] [    T13] ACPI: \_SB_.PRWL: New power resource
+kern  :info  : [    0.376343] [    T14] ACPI: \_SB_.PRWB: New power resource
+kern  :info  : [    0.377373] [    T15] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+kern  :info  : [    0.377378] [    T16] acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+kern  :info  : [    0.377569] [    T17] acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]
+kern  :info  : [    0.377933] [    T18] acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+kern  :info  : [    0.378458] [    T19] PCI host bridge to bus 0000:00
+kern  :info  : [    0.378459] [    T20] pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]
+kern  :info  : [    0.378461] [    T21] pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]
diff --git a/tests/expected/dmesg/indentation-kmsg-printk-caller b/tests/expected/dmesg/indentation-kmsg-printk-caller
new file mode 100644
index 000000000..47ad73f27
--- /dev/null
+++ b/tests/expected/dmesg/indentation-kmsg-printk-caller
@@ -0,0 +1,28 @@
+[    0.000000] [     T0] line zero
+[    1.000000] [     T1] new
+[    2.000000] [     T2] two
+[    3.000000] [     T3] three
+kern  :notice: [    0.000000] [     T0] line zero
+user  :crit  : [    1.000000] [     T1] new
+mail  :warn  : [    2.000000] [     T2] two
+daemon:info  : [    3.000000] [     T3] three
+[<    0.000000>] [     T0] line zero
+[<    0.000000>] [     T1] new
+[<    1.000000>] [     T2] two
+[<    1.000000>] [     T3] three
+[     T0] line zero
+[     T1] new
+[     T2] two
+[     T3] three
+[Feb13 23:31] [     T0] line zero
+[  +0.000000] [     T1] new
+[  +1.000000] [     T2] two
+[  +1.000000] [     T3] three
+[Fri Feb 13 23:31:30 2009] [     T0] line zero
+[Fri Feb 13 23:31:31 2009] [     T1] new
+[Fri Feb 13 23:31:32 2009] [     T2] two
+[Fri Feb 13 23:31:33 2009] [     T3] three
+2009-02-13T23:31:30,123456+00:00 [     T0] line zero
+2009-02-13T23:31:31,123456+00:00 [     T1] new
+2009-02-13T23:31:32,123456+00:00 [     T2] two
+2009-02-13T23:31:33,123456+00:00 [     T3] three
diff --git a/tests/expected/dmesg/json-kmsg-printk-caller b/tests/expected/dmesg/json-kmsg-printk-caller
new file mode 100644
index 000000000..785d730a5
--- /dev/null
+++ b/tests/expected/dmesg/json-kmsg-printk-caller
@@ -0,0 +1,115 @@
+{
+   "dmesg": [
+      {
+         "pri": 5,
+         "time":     0.000000,
+         "caller": "T0",
+         "msg": "Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T1",
+         "msg": "Command line: initrd=\\ucode.img initrd=\\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T2",
+         "msg": "BIOS-provided physical RAM map:"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T3",
+         "msg": "BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T4",
+         "msg": "BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T5",
+         "msg": "BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T6",
+         "msg": "BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T7",
+         "msg": "BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T8",
+         "msg": "BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T9",
+         "msg": "BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T10",
+         "msg": "BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved"
+      },{
+         "pri": 6,
+         "time":     0.367657,
+         "caller": "T11",
+         "msg": "ACPI: \\_SB_.PCI0.GP19.NHI1.PWRS: New power resource"
+      },{
+         "pri": 6,
+         "time":     0.368615,
+         "caller": "T12",
+         "msg": "ACPI: \\_SB_.PCI0.GP19.XHC4.PWRS: New power resource"
+      },{
+         "pri": 6,
+         "time":     0.376316,
+         "caller": "T13",
+         "msg": "ACPI: \\_SB_.PRWL: New power resource"
+      },{
+         "pri": 6,
+         "time":     0.376343,
+         "caller": "T14",
+         "msg": "ACPI: \\_SB_.PRWB: New power resource"
+      },{
+         "pri": 6,
+         "time":     0.377373,
+         "caller": "T15",
+         "msg": "ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])"
+      },{
+         "pri": 6,
+         "time":     0.377378,
+         "caller": "T16",
+         "msg": "acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]"
+      },{
+         "pri": 6,
+         "time":     0.377569,
+         "caller": "T17",
+         "msg": "acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]"
+      },{
+         "pri": 6,
+         "time":     0.377933,
+         "caller": "T18",
+         "msg": "acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]"
+      },{
+         "pri": 6,
+         "time":     0.378458,
+         "caller": "T19",
+         "msg": "PCI host bridge to bus 0000:00"
+      },{
+         "pri": 6,
+         "time":     0.378459,
+         "caller": "T20",
+         "msg": "pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]"
+      },{
+         "pri": 6,
+         "time":     0.378461,
+         "caller": "T21",
+         "msg": "pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]"
+      }
+   ]
+}
diff --git a/tests/expected/dmesg/json-syslog-printk-caller b/tests/expected/dmesg/json-syslog-printk-caller
new file mode 100644
index 000000000..40c98aa67
--- /dev/null
+++ b/tests/expected/dmesg/json-syslog-printk-caller
@@ -0,0 +1,530 @@
+{
+   "dmesg": [
+      {
+         "pri": 0,
+         "time":     0.000000,
+         "caller": "T0",
+         "msg": " example[0]"
+      },{
+         "pri": 1,
+         "time":     1.000000,
+         "caller": "T1",
+         "msg": " example[1]"
+      },{
+         "pri": 2,
+         "time":     8.000000,
+         "caller": "T2",
+         "msg": " example[2]"
+      },{
+         "pri": 3,
+         "time":    27.000000,
+         "caller": "T3",
+         "msg": " example[3]"
+      },{
+         "pri": 4,
+         "time":    64.000000,
+         "caller": "T4",
+         "msg": " example[4]"
+      },{
+         "pri": 5,
+         "time":   125.000000,
+         "caller": "T5",
+         "msg": " example[5]"
+      },{
+         "pri": 6,
+         "time":   216.000000,
+         "caller": "T6",
+         "msg": " example[6]"
+      },{
+         "pri": 7,
+         "time":   343.000000,
+         "caller": "T7",
+         "msg": " example[7]"
+      },{
+         "pri": 8,
+         "time":   512.000000,
+         "caller": "T8",
+         "msg": " example[8]"
+      },{
+         "pri": 9,
+         "time":   729.000000,
+         "caller": "T9",
+         "msg": " example[9]"
+      },{
+         "pri": 10,
+         "time":  1000.000000,
+         "caller": "T10",
+         "msg": " example[10]"
+      },{
+         "pri": 11,
+         "time":  1331.000000,
+         "caller": "T11",
+         "msg": " example[11]"
+      },{
+         "pri": 12,
+         "time":  1728.000000,
+         "caller": "T12",
+         "msg": " example[12]"
+      },{
+         "pri": 13,
+         "time":  2197.000000,
+         "caller": "T13",
+         "msg": " example[13]"
+      },{
+         "pri": 14,
+         "time":  2744.000000,
+         "caller": "T14",
+         "msg": " example[14]"
+      },{
+         "pri": 15,
+         "time":  3375.000000,
+         "caller": "T15",
+         "msg": " example[15]"
+      },{
+         "pri": 16,
+         "time":  4096.000000,
+         "caller": "T16",
+         "msg": " example[16]"
+      },{
+         "pri": 17,
+         "time":  4913.000000,
+         "caller": "T17",
+         "msg": " example[17]"
+      },{
+         "pri": 18,
+         "time":  5832.000000,
+         "caller": "T18",
+         "msg": " example[18]"
+      },{
+         "pri": 19,
+         "time":  6859.000000,
+         "caller": "T19",
+         "msg": " example[19]"
+      },{
+         "pri": 20,
+         "time":  8000.000000,
+         "caller": "T20",
+         "msg": " example[20]"
+      },{
+         "pri": 21,
+         "time":  9261.000000,
+         "caller": "T21",
+         "msg": " example[21]"
+      },{
+         "pri": 22,
+         "time": 10648.000000,
+         "caller": "T22",
+         "msg": " example[22]"
+      },{
+         "pri": 23,
+         "time": 12167.000000,
+         "caller": "T23",
+         "msg": " example[23]"
+      },{
+         "pri": 24,
+         "time": 13824.000000,
+         "caller": "T24",
+         "msg": " example[24]"
+      },{
+         "pri": 25,
+         "time": 15625.000000,
+         "caller": "T25",
+         "msg": " example[25]"
+      },{
+         "pri": 26,
+         "time": 17576.000000,
+         "caller": "T26",
+         "msg": " example[26]"
+      },{
+         "pri": 27,
+         "time": 19683.000000,
+         "caller": "T27",
+         "msg": " example[27]"
+      },{
+         "pri": 28,
+         "time": 21952.000000,
+         "caller": "T28",
+         "msg": " example[28]"
+      },{
+         "pri": 29,
+         "time": 24389.000000,
+         "caller": "T29",
+         "msg": " example[29]"
+      },{
+         "pri": 30,
+         "time": 27000.000000,
+         "caller": "T10",
+         "msg": " example[30]"
+      },{
+         "pri": 31,
+         "time": 29791.000000,
+         "caller": "T31",
+         "msg": " example[31]"
+      },{
+         "pri": 32,
+         "time": 32768.000000,
+         "caller": "T32",
+         "msg": " example[32]"
+      },{
+         "pri": 33,
+         "time": 35937.000000,
+         "caller": "T33",
+         "msg": " example[33]"
+      },{
+         "pri": 34,
+         "time": 39304.000000,
+         "caller": "T34",
+         "msg": " example[34]"
+      },{
+         "pri": 35,
+         "time": 42875.000000,
+         "caller": "T35",
+         "msg": " example[35]"
+      },{
+         "pri": 36,
+         "time": 46656.000000,
+         "caller": "T36",
+         "msg": " example[36]"
+      },{
+         "pri": 37,
+         "time": 50653.000000,
+         "caller": "T37",
+         "msg": " example[37]"
+      },{
+         "pri": 38,
+         "time": 54872.000000,
+         "caller": "T38",
+         "msg": " example[38]"
+      },{
+         "pri": 39,
+         "time": 59319.000000,
+         "caller": "T39",
+         "msg": " example[39]"
+      },{
+         "pri": 40,
+         "time": 64000.000000,
+         "caller": "T40",
+         "msg": " example[40]"
+      },{
+         "pri": 41,
+         "time": 68921.000000,
+         "caller": "T41",
+         "msg": " example[41]"
+      },{
+         "pri": 42,
+         "time": 74088.000000,
+         "caller": "T42",
+         "msg": " example[42]"
+      },{
+         "pri": 43,
+         "time": 79507.000000,
+         "caller": "T43",
+         "msg": " example[43]"
+      },{
+         "pri": 44,
+         "time": 85184.000000,
+         "caller": "T44",
+         "msg": " example[44]"
+      },{
+         "pri": 45,
+         "time": 91125.000000,
+         "caller": "T45",
+         "msg": " example[45]"
+      },{
+         "pri": 46,
+         "time": 97336.000000,
+         "caller": "T46",
+         "msg": " example[46]"
+      },{
+         "pri": 47,
+         "time": 103823.000000,
+         "caller": "T47",
+         "msg": " example[47]"
+      },{
+         "pri": 48,
+         "time": 110592.000000,
+         "caller": "T48",
+         "msg": " example[48]"
+      },{
+         "pri": 49,
+         "time": 117649.000000,
+         "caller": "T49",
+         "msg": " example[49]"
+      },{
+         "pri": 50,
+         "time": 125000.000000,
+         "caller": "T50",
+         "msg": " example[50]"
+      },{
+         "pri": 51,
+         "time": 132651.000000,
+         "caller": "T51",
+         "msg": " example[51]"
+      },{
+         "pri": 52,
+         "time": 140608.000000,
+         "caller": "T52",
+         "msg": " example[52]"
+      },{
+         "pri": 53,
+         "time": 148877.000000,
+         "caller": "T53",
+         "msg": " example[53]"
+      },{
+         "pri": 54,
+         "time": 157464.000000,
+         "caller": "T54",
+         "msg": " example[54]"
+      },{
+         "pri": 55,
+         "time": 166375.000000,
+         "caller": "T55",
+         "msg": " example[55]"
+      },{
+         "pri": 56,
+         "time": 175616.000000,
+         "caller": "T56",
+         "msg": " example[56]"
+      },{
+         "pri": 57,
+         "time": 185193.000000,
+         "caller": "T57",
+         "msg": " example[57]"
+      },{
+         "pri": 58,
+         "time": 195112.000000,
+         "caller": "T58",
+         "msg": " example[58]"
+      },{
+         "pri": 59,
+         "time": 205379.000000,
+         "caller": "T59",
+         "msg": " example[59]"
+      },{
+         "pri": 60,
+         "time": 216000.000000,
+         "caller": "T60",
+         "msg": " example[60]"
+      },{
+         "pri": 61,
+         "time": 226981.000000,
+         "caller": "T61",
+         "msg": " example[61]"
+      },{
+         "pri": 62,
+         "time": 238328.000000,
+         "caller": "T62",
+         "msg": " example[62]"
+      },{
+         "pri": 63,
+         "time": 250047.000000,
+         "caller": "T63",
+         "msg": " example[63]"
+      },{
+         "pri": 64,
+         "time": 262144.000000,
+         "caller": "T64",
+         "msg": " example[64]"
+      },{
+         "pri": 65,
+         "time": 274625.000000,
+         "caller": "T65",
+         "msg": " example[65]"
+      },{
+         "pri": 66,
+         "time": 287496.000000,
+         "caller": "T66",
+         "msg": " example[66]"
+      },{
+         "pri": 67,
+         "time": 300763.000000,
+         "caller": "T67",
+         "msg": " example[67]"
+      },{
+         "pri": 68,
+         "time": 314432.000000,
+         "caller": "T68",
+         "msg": " example[68]"
+      },{
+         "pri": 69,
+         "time": 328509.000000,
+         "caller": "T69",
+         "msg": " example[69]"
+      },{
+         "pri": 70,
+         "time": 343000.000000,
+         "caller": "T70",
+         "msg": " example[70]"
+      },{
+         "pri": 71,
+         "time": 357911.000000,
+         "caller": "T71",
+         "msg": " example[71]"
+      },{
+         "pri": 72,
+         "time": 373248.000000,
+         "caller": "T72",
+         "msg": " example[72]"
+      },{
+         "pri": 73,
+         "time": 389017.000000,
+         "caller": "T73",
+         "msg": " example[73]"
+      },{
+         "pri": 74,
+         "time": 405224.000000,
+         "caller": "T74",
+         "msg": " example[74]"
+      },{
+         "pri": 75,
+         "time": 421875.000000,
+         "caller": "T75",
+         "msg": " example[75]"
+      },{
+         "pri": 76,
+         "time": 438976.000000,
+         "caller": "T76",
+         "msg": " example[76]"
+      },{
+         "pri": 77,
+         "time": 456533.000000,
+         "caller": "T77",
+         "msg": " example[77]"
+      },{
+         "pri": 78,
+         "time": 474552.000000,
+         "caller": "T78",
+         "msg": " example[78]"
+      },{
+         "pri": 79,
+         "time": 493039.000000,
+         "caller": "T79",
+         "msg": " example[79]"
+      },{
+         "pri": 80,
+         "time": 512000.000000,
+         "caller": "T80",
+         "msg": " example[80]"
+      },{
+         "pri": 81,
+         "time": 531441.000000,
+         "caller": "T81",
+         "msg": " example[81]"
+      },{
+         "pri": 82,
+         "time": 551368.000000,
+         "caller": "T82",
+         "msg": " example[82]"
+      },{
+         "pri": 83,
+         "time": 571787.000000,
+         "caller": "T83",
+         "msg": " example[83]"
+      },{
+         "pri": 84,
+         "time": 592704.000000,
+         "caller": "T84",
+         "msg": " example[84]"
+      },{
+         "pri": 85,
+         "time": 614125.000000,
+         "caller": "T85",
+         "msg": " example[85]"
+      },{
+         "pri": 86,
+         "time": 636056.000000,
+         "caller": "T86",
+         "msg": " example[86]"
+      },{
+         "pri": 87,
+         "time": 658503.000000,
+         "caller": "T87",
+         "msg": " example[87]"
+      },{
+         "pri": 88,
+         "time": 681472.000000,
+         "caller": "T88",
+         "msg": " example[88]"
+      },{
+         "pri": 89,
+         "time": 704969.000000,
+         "caller": "T89",
+         "msg": " example[89]"
+      },{
+         "pri": 90,
+         "time": 729000.000000,
+         "caller": "T90",
+         "msg": " example[90]"
+      },{
+         "pri": 91,
+         "time": 753571.000000,
+         "caller": "T91",
+         "msg": " example[91]"
+      },{
+         "pri": 92,
+         "time": 778688.000000,
+         "caller": "T92",
+         "msg": " example[92]"
+      },{
+         "pri": 93,
+         "time": 804357.000000,
+         "caller": "T93",
+         "msg": " example[93]"
+      },{
+         "pri": 94,
+         "time": 830584.000000,
+         "caller": "T94",
+         "msg": " example[94]"
+      },{
+         "pri": 95,
+         "time": 857375.000000,
+         "caller": "T95",
+         "msg": " example[95]"
+      },{
+         "pri": 96,
+         "time": 884736.000000,
+         "caller": "T96",
+         "msg": " example[96]"
+      },{
+         "pri": 97,
+         "time": 912673.000000,
+         "caller": "T97",
+         "msg": " example[97]"
+      },{
+         "pri": 98,
+         "time": 941192.000000,
+         "caller": "T98",
+         "msg": " example[98]"
+      },{
+         "pri": 99,
+         "time": 970299.000000,
+         "caller": "T99",
+         "msg": " example[99]"
+      },{
+         "pri": 100,
+         "time": 1000000.000000,
+         "caller": "T100",
+         "msg": " example[100]"
+      },{
+         "pri": 101,
+         "time": 1030301.000000,
+         "caller": "T101",
+         "msg": " example[101]"
+      },{
+         "pri": 102,
+         "time": 1061208.000000,
+         "caller": "T102",
+         "msg": " example[102]"
+      },{
+         "pri": 103,
+         "time": 1092727.000000,
+         "caller": "T103",
+         "msg": " example[103]"
+      },{
+         "pri": 104,
+         "time": 1124864.000000,
+         "caller": "T104",
+         "msg": " example[104]"
+      }
+   ]
+}
diff --git a/tests/expected/dmesg/kmsg-file-printk-caller b/tests/expected/dmesg/kmsg-file-printk-caller
new file mode 100644
index 000000000..785d730a5
--- /dev/null
+++ b/tests/expected/dmesg/kmsg-file-printk-caller
@@ -0,0 +1,115 @@
+{
+   "dmesg": [
+      {
+         "pri": 5,
+         "time":     0.000000,
+         "caller": "T0",
+         "msg": "Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T1",
+         "msg": "Command line: initrd=\\ucode.img initrd=\\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T2",
+         "msg": "BIOS-provided physical RAM map:"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T3",
+         "msg": "BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T4",
+         "msg": "BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T5",
+         "msg": "BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T6",
+         "msg": "BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T7",
+         "msg": "BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T8",
+         "msg": "BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T9",
+         "msg": "BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "caller": "T10",
+         "msg": "BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved"
+      },{
+         "pri": 6,
+         "time":     0.367657,
+         "caller": "T11",
+         "msg": "ACPI: \\_SB_.PCI0.GP19.NHI1.PWRS: New power resource"
+      },{
+         "pri": 6,
+         "time":     0.368615,
+         "caller": "T12",
+         "msg": "ACPI: \\_SB_.PCI0.GP19.XHC4.PWRS: New power resource"
+      },{
+         "pri": 6,
+         "time":     0.376316,
+         "caller": "T13",
+         "msg": "ACPI: \\_SB_.PRWL: New power resource"
+      },{
+         "pri": 6,
+         "time":     0.376343,
+         "caller": "T14",
+         "msg": "ACPI: \\_SB_.PRWB: New power resource"
+      },{
+         "pri": 6,
+         "time":     0.377373,
+         "caller": "T15",
+         "msg": "ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])"
+      },{
+         "pri": 6,
+         "time":     0.377378,
+         "caller": "T16",
+         "msg": "acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]"
+      },{
+         "pri": 6,
+         "time":     0.377569,
+         "caller": "T17",
+         "msg": "acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]"
+      },{
+         "pri": 6,
+         "time":     0.377933,
+         "caller": "T18",
+         "msg": "acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]"
+      },{
+         "pri": 6,
+         "time":     0.378458,
+         "caller": "T19",
+         "msg": "PCI host bridge to bus 0000:00"
+      },{
+         "pri": 6,
+         "time":     0.378459,
+         "caller": "T20",
+         "msg": "pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]"
+      },{
+         "pri": 6,
+         "time":     0.378461,
+         "caller": "T21",
+         "msg": "pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]"
+      }
+   ]
+}
diff --git a/tests/expected/dmesg/limit-kmsg-printk-caller b/tests/expected/dmesg/limit-kmsg-printk-caller
new file mode 100644
index 000000000..2ea07d4c8
--- /dev/null
+++ b/tests/expected/dmesg/limit-kmsg-printk-caller
@@ -0,0 +1,11 @@
+[    0.367657] [    T11] ACPI: \_SB_.PCI0.GP19.NHI1.PWRS: New power resource
+[    0.368615] [    T12] ACPI: \_SB_.PCI0.GP19.XHC4.PWRS: New power resource
+[    0.376316] [    T13] ACPI: \_SB_.PRWL: New power resource
+[    0.376343] [    T14] ACPI: \_SB_.PRWB: New power resource
+[    0.377373] [    T15] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
+[    0.377378] [    T16] acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]
+[    0.377569] [    T17] acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]
+[    0.377933] [    T18] acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]
+[    0.378458] [    T19] PCI host bridge to bus 0000:00
+[    0.378459] [    T20] pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]
+[    0.378461] [    T21] pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]
diff --git a/tests/ts/dmesg/colors-kmsg-printk-caller b/tests/ts/dmesg/colors-kmsg-printk-caller
new file mode 100755
index 000000000..513ca82d4
--- /dev/null
+++ b/tests/ts/dmesg/colors-kmsg-printk-caller
@@ -0,0 +1,29 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="colors-kmsg-prtk-caller"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+ts_inhibit_custom_colorscheme
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG --color=always -K $TS_SELF/kmsg-input-printk-caller -x >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/console-levels-kmsg-printk-caller b/tests/ts/dmesg/console-levels-kmsg-printk-caller
new file mode 100755
index 000000000..00b8b3681
--- /dev/null
+++ b/tests/ts/dmesg/console-levels-kmsg-printk-caller
@@ -0,0 +1,36 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="levels-kmsg-prtk-caller"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+for I in {-1..8}; do
+	$TS_HELPER_DMESG -K $TS_SELF/kmsg-input-printk-caller -l $I >> $TS_OUTPUT 2>/dev/null
+done
+
+$TS_HELPER_DMESG -K $TS_SELF/kmsg-input-printk-caller -l err+ >> $TS_OUTPUT 2>/dev/null
+$TS_HELPER_DMESG -K $TS_SELF/kmsg-input-printk-caller -l emerg+ >> $TS_OUTPUT 2>/dev/null
+$TS_HELPER_DMESG -K $TS_SELF/kmsg-input-printk-caller -l +err >> $TS_OUTPUT 2>/dev/null
+$TS_HELPER_DMESG -K $TS_SELF/kmsg-input-printk-caller -l +debug >> $TS_OUTPUT 2>/dev/null
+$TS_HELPER_DMESG -K $TS_SELF/kmsg-input-printk-caller -l + 2>> $TS_OUTPUT >/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/decode-kmsg-printk-caller b/tests/ts/dmesg/decode-kmsg-printk-caller
new file mode 100755
index 000000000..d05b9fb68
--- /dev/null
+++ b/tests/ts/dmesg/decode-kmsg-printk-caller
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="decode-kmsg-prtk-caller"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG -x -K $TS_SELF/kmsg-input-printk-caller >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/delta-kmsg-printk-caller b/tests/ts/dmesg/delta-kmsg-printk-caller
new file mode 100755
index 000000000..020b82357
--- /dev/null
+++ b/tests/ts/dmesg/delta-kmsg-printk-caller
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="delta-kmsg-prtk-caller"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG -d -K $TS_SELF/kmsg-input-printk-caller >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/facilities-kmsg-printk-caller b/tests/ts/dmesg/facilities-kmsg-printk-caller
new file mode 100755
index 000000000..bec301516
--- /dev/null
+++ b/tests/ts/dmesg/facilities-kmsg-printk-caller
@@ -0,0 +1,30 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="facilities-kmsg-prtk-caller"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+for I in {-1..12}; do
+	$TS_HELPER_DMESG -K $TS_SELF/kmsg-input-printk-caller -f $I -x >> $TS_OUTPUT 2>/dev/null
+done
+
+ts_finalize
diff --git a/tests/ts/dmesg/indentation-kmsg-printk-caller b/tests/ts/dmesg/indentation-kmsg-printk-caller
new file mode 100755
index 000000000..53e549b62
--- /dev/null
+++ b/tests/ts/dmesg/indentation-kmsg-printk-caller
@@ -0,0 +1,40 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="indentation-kmsg-prtk-caller"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG -K $TS_SELF/newlines-kmsg-printk-caller >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG -K $TS_SELF/newlines-kmsg-printk-caller -x >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=delta --kmsg-file $TS_SELF/newlines-kmsg-printk-caller >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=notime --kmsg-file $TS_SELF/newlines-kmsg-printk-caller >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=reltime --kmsg-file $TS_SELF/newlines-kmsg-printk-caller >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=ctime --kmsg-file $TS_SELF/newlines-kmsg-printk-caller >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+$TS_HELPER_DMESG --time-format=iso --kmsg-file $TS_SELF/newlines-kmsg-printk-caller >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+ts_finalize
diff --git a/tests/ts/dmesg/input-syslog-printk-caller b/tests/ts/dmesg/input-syslog-printk-caller
new file mode 100644
index 000000000..5fcff6abe
--- /dev/null
+++ b/tests/ts/dmesg/input-syslog-printk-caller
@@ -0,0 +1,105 @@
+<0>[    0.000000] [    T0] example[0]
+<1>[    1.000000] [    T1] example[1]
+<2>[    8.000000] [    T2] example[2]
+<3>[   27.000000] [    T3] example[3]
+<4>[   64.000000] [    T4] example[4]
+<5>[  125.000000] [    T5] example[5]
+<6>[  216.000000] [    T6] example[6]
+<7>[  343.000000] [    T7] example[7]
+<8>[  512.000000] [    T8] example[8]
+<9>[  729.000000] [    T9] example[9]
+<10>[ 1000.000000] [   T10] example[10]
+<11>[ 1331.000000] [   T11] example[11]
+<12>[ 1728.000000] [   T12] example[12]
+<13>[ 2197.000000] [   T13] example[13]
+<14>[ 2744.000000] [   T14] example[14]
+<15>[ 3375.000000] [   T15] example[15]
+<16>[ 4096.000000] [   T16] example[16]
+<17>[ 4913.000000] [   T17] example[17]
+<18>[ 5832.000000] [   T18] example[18]
+<19>[ 6859.000000] [   T19] example[19]
+<20>[ 8000.000000] [   T20] example[20]
+<21>[ 9261.000000] [   T21] example[21]
+<22>[10648.000000] [   T22] example[22]
+<23>[12167.000000] [   T23] example[23]
+<24>[13824.000000] [   T24] example[24]
+<25>[15625.000000] [   T25] example[25]
+<26>[17576.000000] [   T26] example[26]
+<27>[19683.000000] [   T27] example[27]
+<28>[21952.000000] [   T28] example[28]
+<29>[24389.000000] [   T29] example[29]
+<30>[27000.000000] [   T10] example[30]
+<31>[29791.000000] [   T31] example[31]
+<32>[32768.000000] [   T32] example[32]
+<33>[35937.000000] [   T33] example[33]
+<34>[39304.000000] [   T34] example[34]
+<35>[42875.000000] [   T35] example[35]
+<36>[46656.000000] [   T36] example[36]
+<37>[50653.000000] [   T37] example[37]
+<38>[54872.000000] [   T38] example[38]
+<39>[59319.000000] [   T39] example[39]
+<40>[64000.000000] [   T40] example[40]
+<41>[68921.000000] [   T41] example[41]
+<42>[74088.000000] [   T42] example[42]
+<43>[79507.000000] [   T43] example[43]
+<44>[85184.000000] [   T44] example[44]
+<45>[91125.000000] [   T45] example[45]
+<46>[97336.000000] [   T46] example[46]
+<47>[103823.000000] [   T47] example[47]
+<48>[110592.000000] [   T48] example[48]
+<49>[117649.000000] [   T49] example[49]
+<50>[125000.000000] [   T50] example[50]
+<51>[132651.000000] [   T51] example[51]
+<52>[140608.000000] [   T52] example[52]
+<53>[148877.000000] [   T53] example[53]
+<54>[157464.000000] [   T54] example[54]
+<55>[166375.000000] [   T55] example[55]
+<56>[175616.000000] [   T56] example[56]
+<57>[185193.000000] [   T57] example[57]
+<58>[195112.000000] [   T58] example[58]
+<59>[205379.000000] [   T59] example[59]
+<60>[216000.000000] [   T60] example[60]
+<61>[226981.000000] [   T61] example[61]
+<62>[238328.000000] [   T62] example[62]
+<63>[250047.000000] [   T63] example[63]
+<64>[262144.000000] [   T64] example[64]
+<65>[274625.000000] [   T65] example[65]
+<66>[287496.000000] [   T66] example[66]
+<67>[300763.000000] [   T67] example[67]
+<68>[314432.000000] [   T68] example[68]
+<69>[328509.000000] [   T69] example[69]
+<70>[343000.000000] [   T70] example[70]
+<71>[357911.000000] [   T71] example[71]
+<72>[373248.000000] [   T72] example[72]
+<73>[389017.000000] [   T73] example[73]
+<74>[405224.000000] [   T74] example[74]
+<75>[421875.000000] [   T75] example[75]
+<76>[438976.000000] [   T76] example[76]
+<77>[456533.000000] [   T77] example[77]
+<78>[474552.000000] [   T78] example[78]
+<79>[493039.000000] [   T79] example[79]
+<80>[512000.000000] [   T80] example[80]
+<81>[531441.000000] [   T81] example[81]
+<82>[551368.000000] [   T82] example[82]
+<83>[571787.000000] [   T83] example[83]
+<84>[592704.000000] [   T84] example[84]
+<85>[614125.000000] [   T85] example[85]
+<86>[636056.000000] [   T86] example[86]
+<87>[658503.000000] [   T87] example[87]
+<88>[681472.000000] [   T88] example[88]
+<89>[704969.000000] [   T89] example[89]
+<90>[729000.000000] [   T90] example[90]
+<91>[753571.000000] [   T91] example[91]
+<92>[778688.000000] [   T92] example[92]
+<93>[804357.000000] [   T93] example[93]
+<94>[830584.000000] [   T94] example[94]
+<95>[857375.000000] [   T95] example[95]
+<96>[884736.000000] [   T96] example[96]
+<97>[912673.000000] [   T97] example[97]
+<98>[941192.000000] [   T98] example[98]
+<99>[970299.000000] [   T99] example[99]
+<100>[1000000.000000] [  T100] example[100]
+<101>[1030301.000000] [  T101] example[101]
+<102>[1061208.000000] [  T102] example[102]
+<103>[1092727.000000] [  T103] example[103]
+<104>[1124864.000000] [  T104] example[104]
diff --git a/tests/ts/dmesg/json-kmsg-printk-caller b/tests/ts/dmesg/json-kmsg-printk-caller
new file mode 100755
index 000000000..cb6c5e4a8
--- /dev/null
+++ b/tests/ts/dmesg/json-kmsg-printk-caller
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="json-kmsg-prtk-caller"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG -J -K $TS_SELF/kmsg-input-printk-caller >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/json-syslog-printk-caller b/tests/ts/dmesg/json-syslog-printk-caller
new file mode 100755
index 000000000..10dfaa423
--- /dev/null
+++ b/tests/ts/dmesg/json-syslog-printk-caller
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="json-syslog-prtk-caller"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG -J -F $TS_SELF/input-syslog-printk-caller >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/kmsg-file-printk-caller b/tests/ts/dmesg/kmsg-file-printk-caller
new file mode 100755
index 000000000..a01fc723f
--- /dev/null
+++ b/tests/ts/dmesg/kmsg-file-printk-caller
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="kmsg-file-prtk-caller"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG -J -K $TS_SELF/kmsg-input-printk-caller >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/kmsg-input-printk-caller b/tests/ts/dmesg/kmsg-input-printk-caller
new file mode 100644
index 0000000000000000000000000000000000000000..8d67f11cad7988469dd5e4a7c8589d2b744168bb
GIT binary patch
literal 2187
zcmbW2TW{hx6oB`+zv4*yQZ$g-aqb9dAw>nL(1<WMu@wr5q0uIBlmsaMe(Z!%<LSbv
zlRV_&oX=m5?PI-*_}S}*L6Xp7utfdGINQI%ffi-VGB6ZF(Rx7<zTh5)+e9?}BOdF!
z4&3g-5N;n_w*#0cs)9j9DnS;)U3i#(h9u&x{5s-+Rh*O^P!$a;r~`jv@Mj))i}85o
zE!X$o=fm05g&E7bfHb(LVT}TW9MyKP4WAG{ZvHa5STe?am!)ZtMZlG)1928tMKt*L
zRS)+ei>MN(yY|bvJxI4@ul|L)xi~^toboE7hd88zJAS>(4k<+$&WTf=%8I5=6qjL8
zL{KnRHJ_wGp3~y4X%}XyWTy5<(<i@|7wiy6G=lu)RK`5fuo%vO$2uZ}NFk&Np_Ymq
zSfw-t^eTS4ee|SPHr;Nw&#*6pO+p1wlYrWFpuOc}8Mxs*4lHO%ivx`WQkRhWRV1!e
z+ekYQM9I;RfW|eTy?GCe&cL>#DIv|PNctWrvM4)R641H|6j_w>Xm5!~<TDIiZwm7-
zzR063A?@o(63R$TCHk+9SYEssT|x4A;}=U!)6d9uCN)C3#4rurY}Eyf`{GX=5bJ8~
zkJgIkPLcB9VOyC`rdaX5E_?^(^awdS(n8E1wlBhFN)n9|Ed%RqqI#M5ZQ^RbA?jUX
z8U!0{B6&w#e0{tu#TOq(XrztM{s%F-j4(OEB&LMW&j_9%Snyf_qau!W6jmZ*&u|;D
zG>9`^*ARl$W?%BV9-k?ldhrsgAzE!IqaTEM4Bp&BLu5I;BEtH~cO7{0q1@*=E2<J!
z<JXF2yw12R+r~Q>`rZuOgoXd{t50_+&G=U{e+uLK1x&nez2zyV<oO2t&m;f4zZ}m7
zqMIAIAAgy;<H0BK<h*s-_}RiwH|(~bdC4zNf@;f(6e31T$apT!y0G#mo;zVxp6t2m
zc=16E4G9gK&(ycA3tN{oc$zZCOFYY}f+ajvd?e`4&b`?f#IqaZ!6r`P>I9F=1>Ae?
zN1ZTtvNT;9I=e5X!3!%Z*fi6iV$cjaAI4@s(=@e-Y$sJk{XC4<txuhL=c$8#E-qNb
x49;7GD7oR*gkzjV>?paPL2n~_e!=^1N$^$A^$pxgsfs@$5!EG7)Tlp__yL<dZm0kN

literal 0
HcmV?d00001

diff --git a/tests/ts/dmesg/limit-kmsg-printk-caller b/tests/ts/dmesg/limit-kmsg-printk-caller
new file mode 100755
index 000000000..4d4d9912d
--- /dev/null
+++ b/tests/ts/dmesg/limit-kmsg-printk-caller
@@ -0,0 +1,29 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="limit-kmsg-prtk-caller"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG --since @1234567890.124 --until @1234567991 -K $TS_SELF/kmsg-input-printk-caller \
+	>> $TS_OUTPUT 2> $TS_ERRLOG
+
+ts_finalize
diff --git a/tests/ts/dmesg/newlines-kmsg-printk-caller b/tests/ts/dmesg/newlines-kmsg-printk-caller
new file mode 100644
index 0000000000000000000000000000000000000000..574d2177796677b73f1efcf273005169ed832c60
GIT binary patch
literal 152
zcmXrjF#tkco#e!voYW%Q5CiL+%)C^Es??%<E(Svb9YY;M128~RV`!b1TFwPh$Hia-
tQeuRm#K^j&Jf91MLCT7`7>o^cjC71K)EQfsWE7>QazV)4{GwE-1^{d2D<=Q|

literal 0
HcmV?d00001

-- 
2.43.0


^ permalink raw reply related

* Re: [PATCH] util-linux/sys-utils dmesg add PRINTK_CALLER support
From: Thomas Weißschuh @ 2023-12-12 18:53 UTC (permalink / raw)
  To: Edward Chron; +Cc: util-linux, colona
In-Reply-To: <20231211172337.31108-1-echron@arista.com>

On 2023-12-11 09:23:37-0800, Edward Chron wrote:
> Submission to Project: util-linux
> Open Incident: #2906 at github.com/util-linux/util-linux/issues/2906
> Component: util-linux/sys-utils
> File: dmesg.c
> Code level patch applied against: 2.39.3 - latest code pulled from
>            git.github.com:util-linux/util-linux.git
> Revision: #1 on 2023/12/08 per Review from Karel Zak

[..]

> ---
>  include/pathnames.h |   3 ++
>  sys-utils/dmesg.c   | 100 +++++++++++++++++++++++++++++++++++++++++++-
>  2 files changed, 102 insertions(+), 1 deletion(-)
> 
> diff --git a/include/pathnames.h b/include/pathnames.h
> index caf0e63d4..81fa405f6 100644
> --- a/include/pathnames.h
> +++ b/include/pathnames.h
> @@ -230,4 +230,7 @@
>  /* cgroup path */
>  #define _PATH_SYS_CGROUP	"/sys/fs/cgroup"
>  
> +/* Maximum number of PIDs system supports */
> +#define _PATH_PROC_PIDMAX	"/proc/sys/kernel/pid_max"
> +
>  #endif /* PATHNAMES_H */
> diff --git a/sys-utils/dmesg.c b/sys-utils/dmesg.c
> index 79e1c1690..fc7252539 100644
> --- a/sys-utils/dmesg.c
> +++ b/sys-utils/dmesg.c
> @@ -8,6 +8,7 @@
>   */
>  #include <stdio.h>
>  #include <getopt.h>
> +#include <stdbool.h>
>  #include <stdlib.h>
>  #include <sys/klog.h>
>  #include <sys/syslog.h>
> @@ -36,6 +37,7 @@
>  #include "mangle.h"
>  #include "pager.h"
>  #include "jsonwrt.h"
> +#include "pathnames.h"
>  
>  /* Close the log.  Currently a NOP. */
>  #define SYSLOG_ACTION_CLOSE          0
> @@ -60,6 +62,11 @@
>  /* Return size of the log buffer */
>  #define SYSLOG_ACTION_SIZE_BUFFER   10
>  
> +#define PID_CHARS_MAX sizeof(stringify_value(LONG_MAX))
> +#define PID_CHARS_DEFAULT sizeof(stringify_value(INT_MAX))
> +#define DMESG_CALLER_PREFIX "caller="
> +#define DMESG_CALLER_PREFIXSZ (sizeof(DMESG_CALLER_PREFIX)-1)
> +
>  /*
>   * Color scheme
>   */
> @@ -216,6 +223,7 @@ struct dmesg_control {
>  			force_prefix:1;	/* force timestamp and decode prefix
>  					   on each line */
>  	int		indent;		/* due to timestamps if newline */
> +	size_t          caller_id_size;   /* PRINTK_CALLERID max field size */
>  };
>  
>  struct dmesg_record {
> @@ -225,6 +233,7 @@ struct dmesg_record {
>  	int		level;
>  	int		facility;
>  	struct timeval  tv;
> +	char		caller_id[PID_CHARS_MAX];
>  
>  	const char	*next;		/* buffer with next unparsed record */
>  	size_t		next_size;	/* size of the next buffer */
> @@ -237,6 +246,7 @@ struct dmesg_record {
>  		(_r)->level = -1; \
>  		(_r)->tv.tv_sec = 0; \
>  		(_r)->tv.tv_usec = 0; \
> +		(_r)->caller_id[0] = 0; \
>  	} while (0)
>  
>  static int process_kmsg(struct dmesg_control *ctl);
> @@ -532,6 +542,45 @@ static int get_syslog_buffer_size(void)
>  	return n > 0 ? n : 0;
>  }
>  
> +/*
> + * Get the number of characters needed to hold the maximum number
> + * of tasks this system supports. This size of string could hold
> + * a thread id large enough for the highest thread id.
> + * This is needed to determine the number of characters reserved for
> + * the PRINTK_CALLER field if it has been configured in the Linux Kernel.
> + *
> + * The number of digits sets the max value since the value can't exceed
> + * a value of that size. The /proc field defined by _PATH_PROC_PIDMAX
> + * holds the maximum number of PID values that may be ussed by the system,
> + * so 0 to that value minus one.
> + *
> + * For determining the size of the PRINTK_CALLER field, we make the safe
> + * assumption that the number of threads >= number of cpus. This because
> + * the PRINTK_CALLER field can hold either a thread id or a CPU id value.
> + *
> + * If we can't access the pid max kernel proc entry we assign a default
> + * field size of 5 characters as that is what the old syslog interface
> + * uses as the reserved field size. This is justified because 32-bit Linux
> + * systems are limited to PID values between (0-32767).
> + *
> + */
> +static size_t max_threads_id_size(void)
> +{
> +	char taskmax[PID_CHARS_MAX] = {'\0'};
> +	ssize_t rdsize;
> +	int fd;
> +
> +	fd = open(_PATH_PROC_PIDMAX, O_RDONLY);
> +	if (fd == -1)
> +		return PID_CHARS_DEFAULT;
> +
> +	rdsize = read(fd, taskmax, sizeof(taskmax));
> +	if (rdsize == -1)
> +		return PID_CHARS_DEFAULT;
> +
> +	return strnlen(taskmax, sizeof(taskmax));
> +}
> +
>  /*
>   * Reads messages from regular file by mmap
>   */
> @@ -706,6 +755,36 @@ static const char *skip_item(const char *begin, const char *end, const char *sep
>  	return begin;
>  }
>  
> +/*
> + * Checks to see if the caller (caller id) field is present in the kmsg record.
> + * This is true if the PRINTK_CALLER config option has been set in the kernel.
> + *
> + * If the caller_id is found in the kmsg buffer then return the id and id type
> + * to the caller in dmesg caller_id. Returns string pointer to next value.
> + *
> + */
> +static const char *parse_callerid(const char *p_str, const char *end,
> +				  struct dmesg_record *p_drec)
> +{
> +	const char *p_after;
> +	const char *p_next;
> +	size_t cid_size;
> +	char *p_cid;
> +
> +	p_cid = strstr(p_str, DMESG_CALLER_PREFIX);

Could this be made a bit more robust to only look for the field in the
expected location and not all of the message?

> +	if (p_cid != NULL && p_drec != NULL) {
> +		p_next = p_cid + DMESG_CALLER_PREFIXSZ;
> +		p_after = skip_item(p_next, end, ",;");
> +		cid_size = p_after - p_next;
> +		if (cid_size < sizeof(p_drec->caller_id))
> +			xstrncpy(p_drec->caller_id, p_next, cid_size);
> +		else
> +			return p_str;
> +		return p_after;
> +	}
> +	return p_str;
> +}
> +
>  /*
>   * Parses one record from syslog(2) buffer
>   */
> @@ -1079,6 +1158,19 @@ full_output:
>  			color_disable();
>  	}
>  
> +	if (*rec->caller_id) {
> +		if (ctl->json) {
> +			ul_jsonwrt_value_s(&ctl->jfmt, "caller", rec->caller_id);
> +		} else {
> +			char cidbuf[PID_CHARS_MAX+3] = {'\0'};
> +
> +			sprintf(cidbuf, "[%*s] ",
> +				(char)ctl->caller_id_size - 1, rec->caller_id);
> +			ctl->indent += strnlen(cidbuf, PID_CHARS_MAX+3);

Use sizeof(cidbuf);

> +			fputs(cidbuf, stdout);
> +		}
> +	}
> +
>  	/*
>  	 * A kernel message may contain several lines of output, separated
>  	 * by '\n'.  If the timestamp and decode outputs are forced then each
> @@ -1207,6 +1299,8 @@ static int init_kmsg(struct dmesg_control *ctl)
>  		return -1;
>  	}
>  
> +	ctl->caller_id_size = max_threads_id_size();
> +
>  	return 0;
>  }
>  
> @@ -1262,7 +1356,10 @@ static int parse_kmsg_record(struct dmesg_control *ctl,
>  		goto mesg;
>  
>  	/* D) optional fields (ignore) */
> -	p = skip_item(p, end, ";");
> +	p = skip_item(p, end, ",;");
> +
> +	/* Include optional PRINTK_CALLER field if it is present */
> +	p = parse_callerid(p, end, rec);
>  
>  mesg:
>  	/* E) message text */
> @@ -1390,6 +1487,7 @@ int main(int argc, char *argv[])
>  		.kmsg = -1,
>  		.time_fmt = DMESG_TIMEFTM_TIME,
>  		.indent = 0,
> +		.caller_id_size = 0,
>  	};
>  	int colormode = UL_COLORMODE_UNDEF;
>  	enum {
> -- 
> 2.43.0
> 
> 

^ permalink raw reply

* Re: [PATCH] Add dmesg syslog interface tests for PRINTK_CALLER field
From: Thomas Weißschuh @ 2023-12-12 18:46 UTC (permalink / raw)
  To: Edward Chron; +Cc: util-linux, colona
In-Reply-To: <20231209222019.954-1-echron@arista.com>

Hi,

thanks for the tests!

On 2023-12-09 14:20:19-0800, Edward Chron wrote:
> Submission to Project: util-linux
> Open Incident: #2637 at github.com/util-linux/util-linux/issues/2637
> Component: util-linux/sys-utils
> File: dmesg.c
> Code level patch applied against: https://github.com/t-8ch/util-linux/
>      and we used his local-dmesg-tests from t8ch/dmesg/tests
>      as we needed the numerous improvements and fixes that Thomas has
>      made to the code.
> 

[..]

> Tests include syslog-printk-caller versions of all existing tests:
> 
> -------------------- util-linux regression tests --------------------
> 
>                     For development purpose only.
>                  Don't execute on production system!
> 
>        kernel: 6.6.4-200.fc39.x86_64
> 
>       options: --srcdir=/usr/src/util-linux/pending/util-linux/tests/.. \
>                --builddir=/usr/src/util-linux/pending/util-linux/tests/..
> 
>         dmesg: colors                         ... OK
>         dmesg: colors-syslog-prtk-caller      ... OK
>         dmesg: levels                         ... OK
>         dmesg: levels-syslog-prtk-caller      ... OK
>         dmesg: decode                         ... OK
>         dmesg: decode-syslog-prtk-caller      ... OK
>         dmesg: delta                          ... OK
>         dmesg: delta-syslog-prtk-caller       ... OK
>         dmesg: facilities                     ... OK
>         dmesg: facilities-syslog-prtk-caller  ... OK
>         dmesg: indentation                    ... OK
>         dmesg: indent-syslog-printk-caller    ... OK
>         dmesg: limit                          ... OK
>         dmesg: limit-syslog-prtk-caller       ... OK

Do we need so many new testcases?
Wouldn't two tests be enough to be sure that the new logic works?

One for the syslog parsing logic and one for the /dev/kmsg one?

Thomas

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox