#!/usr/bin/env python3 from __future__ import annotations import argparse from collections import Counter import shlex import sys def parse(line: str) -> dict[str, str]: parts = shlex.split(line.strip()) if not parts or parts[0] != "event": return {} out: dict[str, str] = {} for part in parts[1:]: if "=" in part: key, value = part.split("=", 1) out[key] = value return out def emit_event(event: dict[str, str]) -> None: print( "seq={seq} vcpu={vcpu} kind={kind} ec={ec} name={name} " "dir={dir} action={action} reason={reason}".format( seq=event.get("seq", "-"), vcpu=event.get("vcpu", "-"), kind=event.get("kind", "-"), ec=event.get("ec", "-"), name=event.get("name", "-"), dir=event.get("dir", "-"), action=event.get("action", "-"), reason=event.get("reason", "-"), ) ) def print_counter(title: str, counter: Counter[str]) -> None: print(title) for key, count in counter.most_common(): print(f" {key}: {count}") def main() -> int: parser = argparse.ArgumentParser() parser.add_argument("--summary", action="store_true", help="print aggregate trace counters") parser.add_argument("--events", action="store_true", help="print normalized events with --summary") args = parser.parse_args() events: list[dict[str, str]] = [] for line in sys.stdin: event = parse(line) if not event: continue events.append(event) if not args.summary or args.events: emit_event(event) if args.summary: print(f"events: {len(events)}") print_counter("by-kind", Counter(e.get("kind", "-") for e in events)) print_counter("by-ec", Counter(e.get("ec", "-") for e in events)) print_counter("by-sysreg", Counter(e.get("name", "-") for e in events if e.get("kind") == "trap")) print_counter("by-action", Counter(e.get("action", "-") for e in events)) print_counter("by-reason", Counter(e.get("reason", "-") for e in events)) return 0 if __name__ == "__main__": raise SystemExit(main())