printk: add console_msg_format command line option
authorSergey Senozhatsky <sergey.senozhatsky.work@gmail.com>
Thu, 21 Dec 2017 05:41:49 +0000 (14:41 +0900)
committerPetr Mladek <pmladek@suse.com>
Thu, 4 Jan 2018 13:51:27 +0000 (14:51 +0100)
0day and kernelCI automatically parse kernel log - basically some sort
of grepping using the pre-defined text patterns - in order to detect
and report regressions/errors. There are several sources they get the
kernel logs from:

a) dmesg or /proc/ksmg

   This is the preferred way. Because `dmesg --raw' (see later Note)
   and /proc/kmsg output contains facility and log level, which greatly
   simplifies grepping for EMERG/ALERT/CRIT/ERR messages.

b) serial consoles

   This option is harder to maintain, because serial console messages
   don't contain facility and log level.

This patch introduces a `console_msg_format=' command line option,
to switch between different message formatting on serial consoles.
For the time being we have just two options - default and syslog.
The "default" option just keeps the existing format. While the
"syslog" option makes serial console messages to appear in syslog
format [syslog() syscall], matching the `dmesg -S --raw' and
`cat /proc/kmsg' output formats:

- facility and log level
- time stamp (depends on printk_time/PRINTK_TIME)
- message

<%u>[time stamp] text\n

NOTE: while Kevin and Fengguang talk about "dmesg --raw", it's actually
"dmesg -S --raw" that always prints messages in syslog format [per
Petr Mladek]. Running "dmesg --raw" may produce output in non-syslog
format sometimes. console_msg_format=syslog enables syslog format,
thus in documentation we mention "dmesg -S --raw", not "dmesg --raw".

Per Kevin Hilman:

: Right now we can get this info from a "dmesg --raw" after bootup,
: but it would be really nice in certain automation frameworks to
: have a kernel command-line option to enable printing of loglevels
: in default boot log.
:
: This is especially useful when ingesting kernel logs into advanced
: search/analytics frameworks (I'm playing with and ELK stack: Elastic
: Search, Logstash, Kibana).
:
: The other important reason for having this on the command line is that
: for testing linux-next (and other bleeding edge developer branches),
: it's common that we never make it to userspace, so can't even run
: "dmesg --raw" (or equivalent.)  So we really want this on the primary
: boot (serial) console.

Per Fengguang Wu, 0day scripts should quickly benefit from that
feature, because they will be able to switch to a more reliable
parsing, based on messages' facility and log levels [1]:

`#{grep} -a -E -e '^<[0123]>' -e '^kern  :(err   |crit  |alert |emerg )'

instead of doing text pattern matching

`#{grep} -a -F -f /lkp/printk-error-messages #{kmsg_file} |
      grep -a -v -E -f #{LKP_SRC}/etc/oops-pattern |
      grep -a -v -F -f #{LKP_SRC}/etc/kmsg-blacklist`

[1] https://github.com/fengguang/lkp-tests/blob/master/lib/dmesg.rb

Link: http://lkml.kernel.org/r/20171221054149.4398-1-sergey.senozhatsky@gmail.com
To: Steven Rostedt <rostedt@goodmis.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Fengguang Wu <fengguang.wu@intel.com>
Cc: Kevin Hilman <khilman@baylibre.com>
Cc: Mark Brown <broonie@kernel.org>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: LKML <linux-kernel@vger.kernel.org>
Signed-off-by: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
Reviewed-by: Fengguang Wu <fengguang.wu@intel.com>
Reviewed-by: Kevin Hilman <khilman@baylibre.com>
Tested-by: Kevin Hilman <khilman@baylibre.com>
Signed-off-by: Petr Mladek <pmladek@suse.com>
Documentation/admin-guide/kernel-parameters.txt
kernel/printk/printk.c

index 62436bd..af61499 100644 (file)
                        console=brl,ttyS0
                For now, only VisioBraille is supported.
 
+       console_msg_format=
+                       [KNL] Change console messages format
+               default
+                       By default we print messages on consoles in
+                       "[time stamp] text\n" format (time stamp may not be
+                       printed, depending on CONFIG_PRINTK_TIME or
+                       `printk_time' param).
+               syslog
+                       Switch to syslog format: "<%u>[time stamp] text\n"
+                       IOW, each message will have a facility and loglevel
+                       prefix. The format is similar to one used by syslog()
+                       syscall, or to executing "dmesg -S --raw" or to reading
+                       from /proc/kmsg.
+
        consoleblank=   [KNL] The console blank (screen saver) timeout in
                        seconds. A value of 0 disables the blank timer.
                        Defaults to 0.
index 5d81206..568729e 100644 (file)
@@ -277,6 +277,13 @@ EXPORT_SYMBOL(console_set_on_cmdline);
 /* Flag: console code may call schedule() */
 static int console_may_schedule;
 
+enum con_msg_format_flags {
+       MSG_FORMAT_DEFAULT      = 0,
+       MSG_FORMAT_SYSLOG       = (1 << 0),
+};
+
+static int console_msg_format = MSG_FORMAT_DEFAULT;
+
 /*
  * The printk log buffer consists of a chain of concatenated variable
  * length records. Every record starts with a record header, containing
@@ -1913,6 +1920,17 @@ static int __add_preferred_console(char *name, int idx, char *options,
        c->index = idx;
        return 0;
 }
+
+static int __init console_msg_format_setup(char *str)
+{
+       if (!strcmp(str, "syslog"))
+               console_msg_format = MSG_FORMAT_SYSLOG;
+       if (!strcmp(str, "default"))
+               console_msg_format = MSG_FORMAT_DEFAULT;
+       return 1;
+}
+__setup("console_msg_format=", console_msg_format_setup);
+
 /*
  * Set up a console.  Called via do_early_param() in init/main.c
  * for each "console=" parameter in the boot command line.
@@ -2215,7 +2233,10 @@ skip:
                        goto skip;
                }
 
-               len += msg_print_text(msg, false, text + len, sizeof(text) - len);
+               len += msg_print_text(msg,
+                               console_msg_format & MSG_FORMAT_SYSLOG,
+                               text + len,
+                               sizeof(text) - len);
                if (nr_ext_console_drivers) {
                        ext_len = msg_print_ext_header(ext_text,
                                                sizeof(ext_text),