1
1
mirror of https://github.com/systemd/systemd-stable.git synced 2024-12-21 09:33:57 +03:00

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.
This commit is contained in:
Zbigniew Jędrzejewski-Szmek 2021-06-02 16:56:31 +02:00
parent 771bdb6aae
commit 19c79550b4

78
tools/analyze-dump-sort.py Executable file
View File

@ -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)