summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2021-06-02 16:56:31 +0200
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2021-06-04 12:09:58 +0200
commit19c79550b489740b3473d7c76ff6aadf739160e2 (patch)
tree1ce55a95c4ecceeaa1063487bf74b5798a38b967 /tools
parent771bdb6aaeb2873011edb72c8f861c41414563d9 (diff)
downloadsystemd-19c79550b489740b3473d7c76ff6aadf739160e2.tar.gz
tools/analyze-dump-sort: a helper to compare two 'systemd-analyze dump' outputs
Lines in the dumps are ordered by some pseudo-random hashmap entry order, which makes it hard to diff two outputs. This sort the entries alphabetically, and also sorts items within the entries, and supresses timestamps and other fields which always vary. We could sort the output inside of systemd itself, but it'd make things more complex, and we probably don't need output to be sorted in most cases. It also wouldn't be enough, because timestamps and such would still need to be ignored to do a nice diff. So I think doing the sorting and suppression in a python helper is a better approach.
Diffstat (limited to 'tools')
-rwxr-xr-xtools/analyze-dump-sort.py78
1 files changed, 78 insertions, 0 deletions
diff --git a/tools/analyze-dump-sort.py b/tools/analyze-dump-sort.py
new file mode 100755
index 0000000000..015027ad4b
--- /dev/null
+++ b/tools/analyze-dump-sort.py
@@ -0,0 +1,78 @@
+#!/usr/bin/python
+# SPDX-License-Identifier: LGPL-2.1-or-later
+
+"""
+A helper to compare 'systemd-analyze dump' outputs.
+
+systemd-analyze dump >/var/tmp/dump1
+(reboot)
+tools/analyze-dump-sort.py /var/tmp/dump1 → this does a diff from dump1 to current
+
+systemd-analyze dump >/var/tmp/dump2
+tools/analyze-dump-sort.py /var/tmp/{dump1,dump2} → this does a diff from dump1 to dump2
+"""
+
+import argparse
+import tempfile
+import subprocess
+
+def sort_dump(sourcefile, destfile=None):
+ if destfile is None:
+ destfile = tempfile.NamedTemporaryFile('wt')
+
+ units = {}
+ unit = []
+
+ same = []
+
+ for line in sourcefile:
+ line = line.rstrip()
+
+ header = line.split(':')[0]
+ if 'Timestamp' in header or 'Invocation ID' in header or 'PID' in header:
+ line = header + ': …'
+
+ if line.startswith('->'):
+ if unit:
+ units[unit[0]] = unit
+ unit = [line]
+ elif line.startswith('\t'):
+ assert unit
+
+ if same and same[0].startswith(header):
+ same.append(line)
+ else:
+ unit.extend(sorted(same, key=str.lower))
+ same = [line]
+ else:
+ print(line, file=destfile)
+
+ if unit:
+ units[unit[0]] = unit
+
+ for unit in sorted(units.values()):
+ print('\n'.join(unit), file=destfile)
+
+ destfile.flush()
+ return destfile
+
+def parse_args():
+ p = argparse.ArgumentParser(description=__doc__)
+ p.add_argument('one')
+ p.add_argument('two', nargs='?')
+ p.add_argument('--user', action='store_true')
+ return p.parse_args()
+
+if __name__ == '__main__':
+ opts = parse_args()
+
+ one = sort_dump(open(opts.one))
+ if opts.two:
+ two = sort_dump(open(opts.two))
+ else:
+ user = ['--user'] if opts.user else []
+ two = subprocess.run(['systemd-analyze', 'dump', *user],
+ capture_output=True, text=True, check=True)
+ two = sort_dump(two.stdout.splitlines())
+ with subprocess.Popen(['diff', '-U10', one.name, two.name], stdout=subprocess.PIPE) as diff:
+ subprocess.Popen(['less'], stdin=diff.stdout)