summaryrefslogtreecommitdiffstats
path: root/tools/analyze-dump-sort.py
blob: cc9a9fcd379d6420d06842017eb3a77e15eeeea5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#!/usr/bin/python
# SPDX-License-Identifier: LGPL-2.1-or-later
# pylint: disable=consider-using-with

"""
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 subprocess
import tempfile


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)