[ovs-dev] [PATCH] utilities: New helper ovs-backtrace-parse.

Ethan Jackson ethan at nicira.com
Mon Oct 15 22:22:41 UTC 2012


The new ovs-backtrace-parse utility makes the output of ovs-appctl
backtrace more human readable by removing duplicate traces and
converting addresses to function names.

Signed-off-by: Ethan Jackson <ethan at nicira.com>
---
 utilities/.gitignore             |   1 +
 utilities/automake.mk            |   2 +
 utilities/ovs-backtrace-parse.in | 100 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 103 insertions(+)
 create mode 100755 utilities/ovs-backtrace-parse.in

diff --git a/utilities/.gitignore b/utilities/.gitignore
index 4f96a4f..9813842 100644
--- a/utilities/.gitignore
+++ b/utilities/.gitignore
@@ -3,6 +3,7 @@
 /nlmon
 /ovs-appctl
 /ovs-appctl.8
+/ovs-backtrace-parse
 /ovs-benchmark
 /ovs-benchmark.1
 /ovs-cfg-mod
diff --git a/utilities/automake.mk b/utilities/automake.mk
index 890f867..4dc9545 100644
--- a/utilities/automake.mk
+++ b/utilities/automake.mk
@@ -7,6 +7,7 @@ bin_PROGRAMS += \
 bin_SCRIPTS += utilities/ovs-pki utilities/ovs-parse-leaks
 if HAVE_PYTHON
 bin_SCRIPTS += \
+	utilities/ovs-backtrace-parse \
 	utilities/ovs-l3ping \
 	utilities/ovs-pcap \
 	utilities/ovs-tcpundump \
@@ -20,6 +21,7 @@ scripts_SCRIPTS += \
 scripts_DATA += utilities/ovs-lib
 
 EXTRA_DIST += \
+	utilities/ovs-backtrace-parse.in \
 	utilities/ovs-check-dead-ifs.in \
 	utilities/ovs-ctl.in \
 	utilities/ovs-l3ping.in \
diff --git a/utilities/ovs-backtrace-parse.in b/utilities/ovs-backtrace-parse.in
new file mode 100755
index 0000000..3656f6f
--- /dev/null
+++ b/utilities/ovs-backtrace-parse.in
@@ -0,0 +1,100 @@
+#! @PYTHON@
+#
+# Copyright (c) 2012 Nicira, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at:
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import argparse
+import os
+import re
+import subprocess
+import sys
+
+import ovs.dirs
+
+has_addr2line = True
+addr2line_cache = {}
+
+
+def addr2line(ovs_vswitchd, addr):
+    global has_addr2line
+    global addr2line_cache
+
+    if not has_addr2line:
+        return ""
+
+    if addr in addr2line_cache:
+        return addr2line_cache[addr]
+
+    cmd = ["addr2line", "-f", "-s", "-e", ovs_vswitchd, addr]
+    try:
+        proc = subprocess.Popen(cmd, stdout=subprocess.PIPE,
+                                stderr=subprocess.PIPE)
+        lines = proc.stdout.readlines()
+        failed = proc.returncode
+    except OSError:
+        failed = True
+
+    if failed:
+        has_addr2line = False
+        return ""
+
+    lines = [l.strip() for l in lines]
+    return " ".join(lines)
+
+
+def main():
+    description = """\
+Parses the output of ovs-appctl backtrace producing a more human readable
+result.  Expected usage is for ovs-appctl backtrace to be piped in.
+
+    ovs-appctl backtrace | %(prog)s"""
+
+    formatter_class = argparse.RawDescriptionHelpFormatter
+    parser = argparse.ArgumentParser(description=description,
+                                     formatter_class=formatter_class)
+    parser.add_argument('--version', action='version', version='@VERSION@')
+    parser.add_argument('-e', '--exe', nargs=1, type=str,
+                        help="path to ovs-vswitchd")
+    args = parser.parse_args()
+
+    if args.exe is not None:
+        ovs_vswitchd = args.exe[0]
+    else:
+        ovs_vswitchd = "@sbindir@/ovs-vswitchd"
+
+    trace_list = sys.stdin.read().strip().split("\n\n")
+
+    #Remove the first line from each trace.
+    trace_list = [trace[(trace.index("\n") + 1):] for trace in trace_list]
+
+    trace_map = {}
+    for trace in trace_list:
+        trace_map[trace] = trace_map.get(trace, 0) + 1
+
+    sorted_traces = sorted(trace_map.items(), key=(lambda x: x[1]),
+                           reverse=True)
+    for trace, count in sorted_traces:
+        lines = trace.split("\n")
+        longest = max([len(l) for l in lines])
+
+        print "Backtrace Count: %d" % count
+        for line in trace.split("\n"):
+            match = re.search(r'\[(0x.*)]', line)
+            print "%s %s" % (line.ljust(longest), addr2line(ovs_vswitchd,
+                                                            match.group(1)))
+        print
+
+
+if __name__ == "__main__":
+    main()
-- 
1.7.12




More information about the dev mailing list