tools/trace.py: add msg filter of event

In the normal develop, will produce many event on the same tracepoint,
like do_sys_open, a executable program will open many files but
developer only has interesting on the specific file. So this filter
will
help developer to get their interesting msg

Signed-off-by: tty5 <tty.fqq@gmail.com>
diff --git a/man/man8/trace.8 b/man/man8/trace.8
index dee0872..0b27dbd 100644
--- a/man/man8/trace.8
+++ b/man/man8/trace.8
@@ -61,6 +61,9 @@
 \-n NAME
 Only print process names containing this name.
 .TP
+\-f MSG_FILTER
+Only print message of event containing this string.
+.TP
 \-B
 Treat argument of STRCMP helper as a binary value
 .TP
diff --git a/tools/trace.py b/tools/trace.py
index d5a5f50..9afd672 100755
--- a/tools/trace.py
+++ b/tools/trace.py
@@ -58,7 +58,7 @@
                 cls.build_id_enabled = args.sym_file_list is not None
 
         def __init__(self, probe, string_size, kernel_stack, user_stack,
-                     cgroup_map_name, name):
+                     cgroup_map_name, name, msg_filter):
                 self.usdt = None
                 self.streq_functions = ""
                 self.raw_probe = probe
@@ -74,6 +74,7 @@
                                          self.probe_name)
                 self.cgroup_map_name = cgroup_map_name
                 self.name = name
+                self.msg_filter = msg_filter
                 # compiler can generate proper codes for function
                 # signatures with "syscall__" prefix
                 if self.is_syscall_kprobe:
@@ -576,6 +577,8 @@
                 values = map(lambda i: getattr(event, "v%d" % i),
                              range(0, len(self.values)))
                 msg = self._format_message(bpf, event.tgid, values)
+                if self.msg_filter and bytes(self.msg_filter) not in msg:
+                    return
                 if Probe.print_time:
                     time = strftime("%H:%M:%S") if Probe.use_localtime else \
                            Probe._time_off_str(event.timestamp_ns)
@@ -653,6 +656,8 @@
         Trace the open syscall and print the filename being opened
 trace 'do_sys_open "%s", arg2' -n main
         Trace the open syscall and only print event that process names containing "main"
+trace 'do_sys_open "%s", arg2' -f config
+        Trace the open syscall and print the filename being opened filtered by "config"
 trace 'sys_read (arg3 > 20000) "read %d bytes", arg3'
         Trace the read syscall and print a message for reads >20000 bytes
 trace 'r::do_sys_open "%llx", retval'
@@ -731,6 +736,8 @@
                   help="cgroup path")
                 parser.add_argument("-n", "--name", type=str,
                                     help="only print process names containing this name")
+                parser.add_argument("-f", "--msg-filter", type=str, dest="msg_filter",
+                                    help="only print the msg of event containing this string")
                 parser.add_argument("-B", "--bin_cmp", action="store_true",
                   help="allow to use STRCMP with binary values")
                 parser.add_argument('-s', "--sym_file_list", type=str, \
@@ -768,7 +775,7 @@
                         self.probes.append(Probe(
                                 probe_spec, self.args.string_size,
                                 self.args.kernel_stack, self.args.user_stack,
-                                self.cgroup_map_name, self.args.name))
+                                self.cgroup_map_name, self.args.name, self.args.msg_filter))
 
         def _generate_program(self):
                 self.program = """
diff --git a/tools/trace_example.txt b/tools/trace_example.txt
index d50ff49..eb63750 100644
--- a/tools/trace_example.txt
+++ b/tools/trace_example.txt
@@ -50,6 +50,25 @@
 each read. The parenthesized expression "(arg3 > 20000)" is a filter that is
 evaluated for each invocation of the probe before printing anything.
 
+Event message filter is useful while you only interesting the specific event.
+Like the program open thousands file and you only want to see the "temp" file
+and print stack.
+
+# trace 'do_sys_open "%s", arg2' -UK -f temp
+PID     TID     COMM            FUNC             -
+9557    9557    a.out           do_sys_open      temp.1
+        do_sys_open+0x1 [kernel]
+        do_syscall_64+0x5b [kernel]
+        entry_SYSCALL_64_after_hwframe+0x44 [kernel]
+        __open_nocancel+0x7 [libc-2.17.so]
+        __libc_start_main+0xf5 [libc-2.17.so]
+9558    9558    a.out           do_sys_open      temp.2
+        do_sys_open+0x1 [kernel]
+        do_syscall_64+0x5b [kernel]
+        entry_SYSCALL_64_after_hwframe+0x44 [kernel]
+        __open_nocancel+0x7 [libc-2.17.so]
+        __libc_start_main+0xf5 [libc-2.17.so]
+
 Process name filter is porting from tools/opensnoop
 
 # trace 'do_sys_open "%s", arg2' -UK -n out
@@ -300,6 +319,8 @@
   -t, --timestamp       print timestamp column (offset from trace start)
   -T, --time            print time column
   -n NAME, --name NAME  only print process names containing this name
+  -f MSG_FILTER, --msg-filter MSG_FILTER
+                        only print message of event containing this string
   -C, --print_cpu       print CPU id
   -B, --bin_cmp         allow to use STRCMP with binary values
   -K, --kernel-stack    output kernel stack trace
@@ -318,6 +339,8 @@
         Trace the open syscall and print the filename being opened
 trace 'do_sys_open "%s", arg2' -n main
         Trace the open syscall and only print event that process names containing "main"
+trace 'do_sys_open "%s", arg2' -f config
+        Trace the open syscall and print the filename being opened filtered by "config"
 trace 'sys_read (arg3 > 20000) "read %d bytes", arg3'
         Trace the read syscall and print a message for reads >20000 bytes
 trace 'r::do_sys_open "%llx", retval'