xref: /openbmc/openbmc-tools/pretty-journal/pretty-journal.py (revision c17b438a587931c3d6f3dd7f6d532f841de67b08)
1#!/usr/bin/env python3
2
3r"""
4BMC FFDC will at times include the journal in json format
5(journalctl -o json-pretty ).  This is a quick and dirty script which
6will convert that json output into the standard journalctl output
7"""
8
9import datetime
10import json
11import re
12from argparse import ArgumentParser
13from datetime import timezone
14
15
16def jpretty_to_python(buf):
17    entries = []
18
19    for entry in re.findall("^{$(.+?)^}$", buf, re.DOTALL | re.MULTILINE):
20        entries += [json.loads("{{{}}}".format(entry))]
21
22    return entries
23
24
25def format_timestamp_utc(us_timestamp, use_utc=False):
26    """Convert microseconds since epoch to formatted timestamp (with microseconds)."""
27    ts = float(us_timestamp) / 1000000
28    tz = timezone.utc if use_utc else None
29    dt = datetime.datetime.fromtimestamp(ts, tz)
30    return dt.strftime("%b %d %H:%M:%S.%f")
31
32
33if __name__ == "__main__":
34    parser = ArgumentParser()
35    parser.add_argument(
36        "journalfile", metavar="FILE", help="the file to parse"
37    )
38    parser.add_argument(
39        "--localtime",
40        action="store_true",
41        help="Display timestamps in local time (default is UTC)",
42    )
43    args = parser.parse_args()
44
45    with open(args.journalfile) as fd:
46        entries = jpretty_to_python(fd.read())
47        entries = sorted(entries, key=lambda k: k["__REALTIME_TIMESTAMP"])
48
49        for e in entries:
50            e["ts"] = format_timestamp_utc(
51                e["__REALTIME_TIMESTAMP"], use_utc=not args.localtime
52            )
53            try:
54                print(
55                    f'{e["ts"]} {e["_HOSTNAME"]} {e["SYSLOG_IDENTIFIER"]}:'
56                    f' {e["MESSAGE"]}'
57                )
58            except Exception:
59                print("Unable to parse msg: " + str(e))
60                continue
61