diff mbox series

logread : add option to exclude lines matching regex

Message ID CAODUAvttSKHBYu-wtLKSt+0Zy_zf-EAzDuQXNB-NFPvSy74R2Q@mail.gmail.com
State New
Headers show
Series logread : add option to exclude lines matching regex | expand

Commit Message

Dan Brown Jan. 23, 2023, 7:06 p.m. UTC
From: Dan Brown <danbrown@gmail.com>

logread: add option to exclude lines matching regex

This adds another filtering option (-E) to exclude lines that match a
regex, similar to the existing include option (-e):
-e <pattern>       include messages matching a regexp
-E <pattern>       exclude messages matching a regexp

The two options -e and -E are independent, and lines must pass both
tests to appear in program output.
* 'logread -E dhcp' will display all lines that do not contain the string "dhcp"
* 'logread -e dhcp -E 192.168' will display all lines that contain
"dhcp" and do not contain "192.168"

signed off by: Dan Brown, danbrown@gmail.com
---
Further update: Sorry for yet another (third) version of this. I
discovered that the regex match checked only the contents of the
message part of the log, but I want to match the entire formatted
logline with program, priority, etc. This new version does that. This
probably deserves some discussion because it changes the behavior of
the existing '-e' option, and may not be what some people want to
match on. Are there use cases that depend on matching only the message
part of the log line?

Update: this newer (second) version fixes a bug where the -e and -E options
would be mutually exclusive instead of independent. Sorry.

The motivation for adding this option to logread is to remove frequent
and uninteresting loglines from being displayed in Luci. One way to
achieve this is to install an alternate logging system (syslog-ng or
rsyslog) and set up rules for filtering there. Instead of that, I
would prefer to use the simpler and standard logd/ubox method with
this small enhancement.

This patch applies to the ubox project
(https://git.openwrt.org/?p=project/ubox.git;a=summary)

 static int log_timestamp;
@@ -157,9 +158,6 @@ static int log_notify(struct blob_attr *
             return 0;

     m = blobmsg_get_string(tb[LOG_MSG]);
-    if (regexp_pattern &&
-        regexec(&regexp_preg, m, 0, NULL, 0) == REG_NOMATCH)
-        return 0;
     t = blobmsg_get_u64(tb[LOG_TIME]) / 1000;
     if (log_timestamp) {
         t_ms = blobmsg_get_u64(tb[LOG_TIME]) % 1000;
@@ -188,6 +186,12 @@ static int log_notify(struct blob_attr *
         if (blobmsg_get_u32(tb[LOG_SOURCE]) == SOURCE_KLOG)
             strncat(buf, "kernel: ", sizeof(buf) - strlen(buf) - 1);
         strncat(buf, m, sizeof(buf) - strlen(buf) - 1);
+        if (regexp_pattern_include &&
+            regexec(&regexp_preg_include, buf, 0, NULL, 0) == REG_NOMATCH)
+            return 0;
+        if (regexp_pattern_exclude &&
+            regexec(&regexp_preg_exclude, buf, 0, NULL, 0) != REG_NOMATCH)
+            return 0;
         if (log_udp)
             err = write(sender.fd, buf, strlen(buf));
         else {
@@ -211,6 +215,12 @@ static int log_notify(struct blob_attr *
             getcodetext(LOG_FAC(p) << 3, facilitynames),
             getcodetext(LOG_PRI(p), prioritynames),
             (blobmsg_get_u32(tb[LOG_SOURCE])) ? ("") : (" kernel:"), m);
+        if (regexp_pattern_include &&
+            regexec(&regexp_preg_include, buf, 0, NULL, 0) == REG_NOMATCH)
+            return 0;
+        if (regexp_pattern_exclude &&
+            regexec(&regexp_preg_exclude, buf, 0, NULL, 0) != REG_NOMATCH)
+            return 0;
         ret = write(sender.fd, buf, strlen(buf));
     }

@@ -226,7 +236,8 @@ static int usage(const char *prog)
         "Options:\n"
         "    -s <path>        Path to ubus socket\n"
         "    -l    <count>        Got only the last 'count' messages\n"
-        "    -e    <pattern>    Filter messages with a regexp\n"
+        "    -e    <pattern>    include log lines that match a regexp\n"
+        "    -E    <pattern>    exclude log lines that match a regexp\n"
         "    -r    <server> <port>    Stream message to a server\n"
         "    -F    <file>        Log file\n"
         "    -S    <bytes>        Log size\n"
@@ -313,7 +324,7 @@ int main(int argc, char **argv)

     signal(SIGPIPE, SIG_IGN);

-    while ((ch = getopt(argc, argv, "u0fcs:l:z:Z:r:F:p:S:P:h:e:t")) != -1) {
+    while ((ch = getopt(argc, argv, "u0fcs:l:z:Z:r:F:p:S:P:h:e:E:t")) != -1) {
         switch (ch) {
         case 'u':
             log_udp = 1;
@@ -361,8 +372,13 @@ int main(int argc, char **argv)
             hostname = optarg;
             break;
         case 'e':
-            if (!regcomp(&regexp_preg, optarg, REG_NOSUB)) {
-                regexp_pattern = optarg;
+            if (!regcomp(&regexp_preg_include, optarg, REG_NOSUB)) {
+                regexp_pattern_include = optarg;
+            }
+            break;
+        case 'E':
+            if (!regcomp(&regexp_preg_exclude, optarg, REG_NOSUB)) {
+                regexp_pattern_exclude = optarg;
             }
             break;
         case 't':
diff mbox series

Patch

--- log/logread.c.orig    2023-01-23 13:16:59.502476137 +0100
+++ log/logread.c    2023-01-23 20:05:48.478603378 +0100
@@ -60,8 +60,9 @@  static const struct blobmsg_policy log_p

 static struct uloop_timeout retry;
 static struct uloop_fd sender;
-static regex_t regexp_preg;
-static const char *log_file, *log_ip, *log_port, *log_prefix,
*pid_file, *hostname, *regexp_pattern;
+static regex_t regexp_preg_include, regexp_preg_exclude;
+static const char *log_file, *log_ip, *log_port, *log_prefix, *pid_file;
+static const char *hostname, *regexp_pattern_include, *regexp_pattern_exclude;
 static int log_type = LOG_STDOUT;
 static int log_size, log_udp, log_follow, log_trailer_null = 0;