simpletrace: made Analyzer into context-manager

Instead of explicitly calling `begin` and `end`, we can change the class
to use the context-manager paradigm. This is mostly a styling choice,
used in modern Python code. But it also allows for more advanced analyzers
to handle exceptions gracefully in the `__exit__` method (not
demonstrated here).

Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Mads Ynddal <m.ynddal@samsung.com>
Message-id: 20230926103436.25700-9-mads@ynddal.dk
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
Mads Ynddal 2023-09-26 12:34:30 +02:00 committed by Stefan Hajnoczi
parent 1990fb9893
commit 87617b9ae6

View File

@ -122,12 +122,13 @@ def read_trace_records(event_mapping, event_id_to_name, fobj):
yield rec
class Analyzer(object):
class Analyzer:
"""A trace file analyzer which processes trace records.
An analyzer can be passed to run() or process(). The begin() method is
invoked, then each trace record is processed, and finally the end() method
is invoked.
is invoked. When Analyzer is used as a context-manager (using the `with`
statement), begin() and end() are called automatically.
If a method matching a trace event name exists, it is invoked to process
that trace record. Otherwise the catchall() method is invoked.
@ -165,6 +166,15 @@ class Analyzer(object):
"""Called at the end of the trace."""
pass
def __enter__(self):
self.begin()
return self
def __exit__(self, exc_type, exc_val, exc_tb):
if exc_type is None:
self.end()
return False
def process(events, log, analyzer, read_header=True):
"""Invoke an analyzer on each event in a log.
Args:
@ -226,15 +236,14 @@ def process(events, log, analyzer, read_header=True):
# Just arguments, no timestamp or pid
return lambda _, rec: fn(*rec[3:3 + event_argcount])
analyzer.begin()
fn_cache = {}
for rec in read_trace_records(event_mapping, event_id_to_name, log):
event_num = rec[0]
event = event_mapping[event_num]
if event_num not in fn_cache:
fn_cache[event_num] = build_fn(analyzer, event)
fn_cache[event_num](event, rec)
analyzer.end()
with analyzer:
fn_cache = {}
for rec in read_trace_records(event_mapping, event_id_to_name, log):
event_num = rec[0]
event = event_mapping[event_num]
if event_num not in fn_cache:
fn_cache[event_num] = build_fn(analyzer, event)
fn_cache[event_num](event, rec)
if close_log:
log.close()