in utils/ptreetime/ptreetime.py [0:0]
def _parse_event_log(path):
# Load the file as JSON.
with open(path) as f:
data = json.load(f)
command = data['command']
events_data = data['events']
# Convert the events data into events.
def convert_event(data):
evt_name = data.pop('evt', '').strip()
evt_class = _event_classes.get(evt_name)
if evt_class is None:
raise ValueError("unknown event: %r" % ((evt_name, data),))
try:
return evt_class(**data)
except TypeError:
raise ValueError("invalid event: %r (unable to instantiate %r)" % (
(evt_name, data), evt_class))
events = [convert_event(d)
for d in events_data]
# Order all of the events by timestamp.
events.sort(key = lambda event: event.timestamp)
# Check that the file is complete.
if not events:
raise ValueError("data file has no events: %r" % (path,))
if not isinstance(events[0], PTreeStartEvent):
raise ValueError("data file %r starts with unexpected event %r" % (
path, events[0]))
if not isinstance(events[-1], PTreeStopEvent):
raise ValueError("data file %r ends with unexpected event %r" % (
path, events[-1]))
# Get the target PID.
target = events[0].target
target_start_timestamp = events[0].timestamp
# Drop the start and stop events.
events = events[1:-1]
# Build the process tree list.
def get_record_for_pid(pid):
# Lookup the PID.
record = active_processes.get(pid)
if record is not None:
return record
# The PID was unknown, create a record for it.
active_processes[pid] = record = ProcessInfo(pid)
# Add to the list of all records.
all_records.append(record)
roots.add(record)
return record
all_records = []
roots = set()
target_root = None
active_processes = {}
active_spawn_args = {}
for event in events:
# Handle the exit of the target process specially.
if event.pid == target:
if not isinstance(event, PTreeProcExitEvent):
raise RuntimeError("unexpected event for target %r" % (
event,))
assert isinstance(event, PTreeProcExitEvent)
target_root = get_record_for_pid(event.pid)
roots.remove(target_root)
target_root.start_timestamp = target_start_timestamp
target_root.exit_timestamp = event.timestamp
target_root.name = event.name
del active_processes[event.pid]
continue
# First, lookup or create an entry for the parent process.
parent_process = get_record_for_pid(event.parent)
# Get the record for this PID.
child_process = get_record_for_pid(event.pid)
# If this is a create event, store the timestamp and add it to the
# parent.
if isinstance(event, PTreeProcCreateEvent):
if child_process.parent:
raise RuntimeError("multiple create events for %r" % (
event,))
child_process.parent = parent_process
child_process.start_timestamp = event.timestamp
parent_process.children.append(child_process)
roots.remove(child_process)
child_process.args = active_spawn_args.pop(event.parent, None)
if child_process.args is not None:
child_process.name = os.path.basename(child_process.args[0])
continue
# Otherwise, handle the various "user" events.
if isinstance(event, PTreeUserStartupEvent):
child_process.user_start_timestamp = event.timestamp
child_process.startup_user_time = event.user_time
child_process.startup_system_time = event.system_time
continue
if isinstance(event, PTreeUserExecEvent):
# If the child process already has arguments defined, then the
# process is re-exec'ing itself. Create a new process entry.
if child_process.args is not None:
child_process.exit_timestamp = \
child_process.user_exit_timestamp = event.timestamp
child_process.user_time = event.user_time
child_process.system_time = event.system_time
# FIXME: Get utime and stime available here, and copy.
del active_processes[event.pid]
child_process = get_record_for_pid(event.pid)
child_process.parent = parent_process
child_process.start_timestamp = event.timestamp
child_process.args = event.args
child_process.name = os.path.basename(child_process.args[0])
parent_process.children.append(child_process)
roots.remove(child_process)
else:
child_process.args = event.args
child_process.name = os.path.basename(child_process.args[0])
continue
if isinstance(event, PTreeUserSpawnEvent):
active_spawn_args[event.pid] = event.args
continue
if isinstance(event, PTreeUserExitEvent):
child_process.user_exit_timestamp = event.timestamp
child_process.user_time = event.user_time
child_process.system_time = event.system_time
continue
# Otherwise, this is an exit event, store the event information and
# update the parent and active process list.
if child_process.parent is None:
warning('found stray exit: %r' % (
(event.timestamp, event.pid, event.name),))
child_process.parent = parent_process
parent_process.children.append(child_process)
roots.remove(child_process)
assert isinstance(event, PTreeProcExitEvent)
child_process.exit_timestamp = event.timestamp
child_process.name = event.name
del active_processes[event.pid]
return target_root, roots, active_processes