|
Packit Service |
a04d08 |
# Copyright (C) 2016 Canonical Ltd.
|
|
Packit Service |
a04d08 |
#
|
|
Packit Service |
a04d08 |
# Author: Ryan Harper <ryan.harper@canonical.com>
|
|
Packit Service |
a04d08 |
#
|
|
Packit Service |
a04d08 |
# This file is part of cloud-init. See LICENSE file for license information.
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
import base64
|
|
Packit Service |
a04d08 |
import datetime
|
|
Packit Service |
a04d08 |
import json
|
|
Packit Service |
a04d08 |
import os
|
|
Packit Service |
a04d08 |
import time
|
|
Packit Service |
a04d08 |
import sys
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
9bfd13 |
from cloudinit import subp
|
|
Packit Service |
a04d08 |
from cloudinit import util
|
|
Packit Service |
a04d08 |
from cloudinit.distros import uses_systemd
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
9bfd13 |
# Example events:
|
|
Packit Service |
9bfd13 |
# {
|
|
Packit Service |
9bfd13 |
# "description": "executing late commands",
|
|
Packit Service |
9bfd13 |
# "event_type": "start",
|
|
Packit Service |
9bfd13 |
# "level": "INFO",
|
|
Packit Service |
9bfd13 |
# "name": "cmd-install/stage-late"
|
|
Packit Service |
9bfd13 |
# "origin": "cloudinit",
|
|
Packit Service |
9bfd13 |
# "timestamp": 1461164249.1590767,
|
|
Packit Service |
9bfd13 |
# }
|
|
Packit Service |
9bfd13 |
# {
|
|
Packit Service |
9bfd13 |
# "description": "executing late commands",
|
|
Packit Service |
9bfd13 |
# "event_type": "finish",
|
|
Packit Service |
9bfd13 |
# "level": "INFO",
|
|
Packit Service |
9bfd13 |
# "name": "cmd-install/stage-late",
|
|
Packit Service |
9bfd13 |
# "origin": "cloudinit",
|
|
Packit Service |
9bfd13 |
# "result": "SUCCESS",
|
|
Packit Service |
9bfd13 |
# "timestamp": 1461164249.1590767
|
|
Packit Service |
9bfd13 |
# }
|
|
Packit Service |
9bfd13 |
|
|
Packit Service |
a04d08 |
format_key = {
|
|
Packit Service |
a04d08 |
'%d': 'delta',
|
|
Packit Service |
a04d08 |
'%D': 'description',
|
|
Packit Service |
a04d08 |
'%E': 'elapsed',
|
|
Packit Service |
a04d08 |
'%e': 'event_type',
|
|
Packit Service |
a04d08 |
'%I': 'indent',
|
|
Packit Service |
a04d08 |
'%l': 'level',
|
|
Packit Service |
a04d08 |
'%n': 'name',
|
|
Packit Service |
a04d08 |
'%o': 'origin',
|
|
Packit Service |
a04d08 |
'%r': 'result',
|
|
Packit Service |
a04d08 |
'%t': 'timestamp',
|
|
Packit Service |
a04d08 |
'%T': 'total_time',
|
|
Packit Service |
a04d08 |
}
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
formatting_help = " ".join(["{0}: {1}".format(k.replace('%', '%%'), v)
|
|
Packit Service |
a04d08 |
for k, v in format_key.items()])
|
|
Packit Service |
a04d08 |
SUCCESS_CODE = 'successful'
|
|
Packit Service |
a04d08 |
FAIL_CODE = 'failure'
|
|
Packit Service |
a04d08 |
CONTAINER_CODE = 'container'
|
|
Packit Service |
a04d08 |
TIMESTAMP_UNKNOWN = (FAIL_CODE, -1, -1, -1)
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def format_record(msg, event):
|
|
Packit Service |
a04d08 |
for i, j in format_key.items():
|
|
Packit Service |
a04d08 |
if i in msg:
|
|
Packit Service |
a04d08 |
# ensure consistent formatting of time values
|
|
Packit Service |
a04d08 |
if j in ['delta', 'elapsed', 'timestamp']:
|
|
Packit Service |
a04d08 |
msg = msg.replace(i, "{%s:08.5f}" % j)
|
|
Packit Service |
a04d08 |
else:
|
|
Packit Service |
a04d08 |
msg = msg.replace(i, "{%s}" % j)
|
|
Packit Service |
a04d08 |
return msg.format(**event)
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def dump_event_files(event):
|
|
Packit Service |
a04d08 |
content = dict((k, v) for k, v in event.items() if k not in ['content'])
|
|
Packit Service |
a04d08 |
files = content['files']
|
|
Packit Service |
a04d08 |
saved = []
|
|
Packit Service |
a04d08 |
for f in files:
|
|
Packit Service |
a04d08 |
fname = f['path']
|
|
Packit Service |
a04d08 |
fn_local = os.path.basename(fname)
|
|
Packit Service |
a04d08 |
fcontent = base64.b64decode(f['content']).decode('ascii')
|
|
Packit Service |
a04d08 |
util.write_file(fn_local, fcontent)
|
|
Packit Service |
a04d08 |
saved.append(fn_local)
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
return saved
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def event_name(event):
|
|
Packit Service |
a04d08 |
if event:
|
|
Packit Service |
a04d08 |
return event.get('name')
|
|
Packit Service |
a04d08 |
return None
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def event_type(event):
|
|
Packit Service |
a04d08 |
if event:
|
|
Packit Service |
a04d08 |
return event.get('event_type')
|
|
Packit Service |
a04d08 |
return None
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def event_parent(event):
|
|
Packit Service |
a04d08 |
if event:
|
|
Packit Service |
a04d08 |
return event_name(event).split("/")[0]
|
|
Packit Service |
a04d08 |
return None
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def event_timestamp(event):
|
|
Packit Service |
a04d08 |
return float(event.get('timestamp'))
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def event_datetime(event):
|
|
Packit Service |
a04d08 |
return datetime.datetime.utcfromtimestamp(event_timestamp(event))
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def delta_seconds(t1, t2):
|
|
Packit Service |
a04d08 |
return (t2 - t1).total_seconds()
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def event_duration(start, finish):
|
|
Packit Service |
a04d08 |
return delta_seconds(event_datetime(start), event_datetime(finish))
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def event_record(start_time, start, finish):
|
|
Packit Service |
a04d08 |
record = finish.copy()
|
|
Packit Service |
a04d08 |
record.update({
|
|
Packit Service |
a04d08 |
'delta': event_duration(start, finish),
|
|
Packit Service |
a04d08 |
'elapsed': delta_seconds(start_time, event_datetime(start)),
|
|
Packit Service |
a04d08 |
'indent': '|' + ' ' * (event_name(start).count('/') - 1) + '`->',
|
|
Packit Service |
a04d08 |
})
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
return record
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def total_time_record(total_time):
|
|
Packit Service |
a04d08 |
return 'Total Time: %3.5f seconds\n' % total_time
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
class SystemctlReader(object):
|
|
Packit Service |
a04d08 |
'''
|
|
Packit Service |
a04d08 |
Class for dealing with all systemctl subp calls in a consistent manner.
|
|
Packit Service |
a04d08 |
'''
|
|
Packit Service |
a04d08 |
def __init__(self, property, parameter=None):
|
|
Packit Service |
a04d08 |
self.epoch = None
|
|
Packit Service |
a04d08 |
self.args = ['/bin/systemctl', 'show']
|
|
Packit Service |
a04d08 |
if parameter:
|
|
Packit Service |
a04d08 |
self.args.append(parameter)
|
|
Packit Service |
a04d08 |
self.args.extend(['-p', property])
|
|
Packit Service |
a04d08 |
# Don't want the init of our object to break. Instead of throwing
|
|
Packit Service |
a04d08 |
# an exception, set an error code that gets checked when data is
|
|
Packit Service |
a04d08 |
# requested from the object
|
|
Packit Service |
a04d08 |
self.failure = self.subp()
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def subp(self):
|
|
Packit Service |
a04d08 |
'''
|
|
Packit Service |
a04d08 |
Make a subp call based on set args and handle errors by setting
|
|
Packit Service |
a04d08 |
failure code
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
:return: whether the subp call failed or not
|
|
Packit Service |
a04d08 |
'''
|
|
Packit Service |
a04d08 |
try:
|
|
Packit Service |
9bfd13 |
value, err = subp.subp(self.args, capture=True)
|
|
Packit Service |
a04d08 |
if err:
|
|
Packit Service |
a04d08 |
return err
|
|
Packit Service |
a04d08 |
self.epoch = value
|
|
Packit Service |
a04d08 |
return None
|
|
Packit Service |
a04d08 |
except Exception as systemctl_fail:
|
|
Packit Service |
a04d08 |
return systemctl_fail
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def parse_epoch_as_float(self):
|
|
Packit Service |
a04d08 |
'''
|
|
Packit Service |
a04d08 |
If subp call succeeded, return the timestamp from subp as a float.
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
:return: timestamp as a float
|
|
Packit Service |
a04d08 |
'''
|
|
Packit Service |
a04d08 |
# subp has 2 ways to fail: it either fails and throws an exception,
|
|
Packit Service |
a04d08 |
# or returns an error code. Raise an exception here in order to make
|
|
Packit Service |
a04d08 |
# sure both scenarios throw exceptions
|
|
Packit Service |
a04d08 |
if self.failure:
|
|
Packit Service |
a04d08 |
raise RuntimeError('Subprocess call to systemctl has failed, '
|
|
Packit Service |
a04d08 |
'returning error code ({})'
|
|
Packit Service |
a04d08 |
.format(self.failure))
|
|
Packit Service |
a04d08 |
# Output from systemctl show has the format Property=Value.
|
|
Packit Service |
a04d08 |
# For example, UserspaceMonotonic=1929304
|
|
Packit Service |
a04d08 |
timestamp = self.epoch.split('=')[1]
|
|
Packit Service |
a04d08 |
# Timestamps reported by systemctl are in microseconds, converting
|
|
Packit Service |
a04d08 |
return float(timestamp) / 1000000
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def dist_check_timestamp():
|
|
Packit Service |
a04d08 |
'''
|
|
Packit Service |
a04d08 |
Determine which init system a particular linux distro is using.
|
|
Packit Service |
a04d08 |
Each init system (systemd, upstart, etc) has a different way of
|
|
Packit Service |
a04d08 |
providing timestamps.
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
:return: timestamps of kernelboot, kernelendboot, and cloud-initstart
|
|
Packit Service |
a04d08 |
or TIMESTAMP_UNKNOWN if the timestamps cannot be retrieved.
|
|
Packit Service |
a04d08 |
'''
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
if uses_systemd():
|
|
Packit Service |
a04d08 |
return gather_timestamps_using_systemd()
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
# Use dmesg to get timestamps if the distro does not have systemd
|
|
Packit Service |
a04d08 |
if util.is_FreeBSD() or 'gentoo' in \
|
|
Packit Service |
a04d08 |
util.system_info()['system'].lower():
|
|
Packit Service |
a04d08 |
return gather_timestamps_using_dmesg()
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
# this distro doesn't fit anything that is supported by cloud-init. just
|
|
Packit Service |
a04d08 |
# return error codes
|
|
Packit Service |
a04d08 |
return TIMESTAMP_UNKNOWN
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def gather_timestamps_using_dmesg():
|
|
Packit Service |
a04d08 |
'''
|
|
Packit Service |
a04d08 |
Gather timestamps that corresponds to kernel begin initialization,
|
|
Packit Service |
a04d08 |
kernel finish initialization using dmesg as opposed to systemctl
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
:return: the two timestamps plus a dummy timestamp to keep consistency
|
|
Packit Service |
a04d08 |
with gather_timestamps_using_systemd
|
|
Packit Service |
a04d08 |
'''
|
|
Packit Service |
a04d08 |
try:
|
|
Packit Service |
9bfd13 |
data, _ = subp.subp(['dmesg'], capture=True)
|
|
Packit Service |
a04d08 |
split_entries = data[0].splitlines()
|
|
Packit Service |
a04d08 |
for i in split_entries:
|
|
Packit Service |
a04d08 |
if i.decode('UTF-8').find('user') != -1:
|
|
Packit Service |
a04d08 |
splitup = i.decode('UTF-8').split()
|
|
Packit Service |
a04d08 |
stripped = splitup[1].strip(']')
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
# kernel timestamp from dmesg is equal to 0,
|
|
Packit Service |
a04d08 |
# with the userspace timestamp relative to it.
|
|
Packit Service |
a04d08 |
user_space_timestamp = float(stripped)
|
|
Packit Service |
a04d08 |
kernel_start = float(time.time()) - float(util.uptime())
|
|
Packit Service |
a04d08 |
kernel_end = kernel_start + user_space_timestamp
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
# systemd wont start cloud-init in this case,
|
|
Packit Service |
a04d08 |
# so we cannot get that timestamp
|
|
Packit Service |
a04d08 |
return SUCCESS_CODE, kernel_start, kernel_end, \
|
|
Packit Service |
a04d08 |
kernel_end
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
except Exception:
|
|
Packit Service |
a04d08 |
pass
|
|
Packit Service |
a04d08 |
return TIMESTAMP_UNKNOWN
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def gather_timestamps_using_systemd():
|
|
Packit Service |
a04d08 |
'''
|
|
Packit Service |
a04d08 |
Gather timestamps that corresponds to kernel begin initialization,
|
|
Packit Service |
a04d08 |
kernel finish initialization. and cloud-init systemd unit activation
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
:return: the three timestamps
|
|
Packit Service |
a04d08 |
'''
|
|
Packit Service |
a04d08 |
kernel_start = float(time.time()) - float(util.uptime())
|
|
Packit Service |
a04d08 |
try:
|
|
Packit Service |
a04d08 |
delta_k_end = SystemctlReader('UserspaceTimestampMonotonic')\
|
|
Packit Service |
a04d08 |
.parse_epoch_as_float()
|
|
Packit Service |
a04d08 |
delta_ci_s = SystemctlReader('InactiveExitTimestampMonotonic',
|
|
Packit Service |
a04d08 |
'cloud-init-local').parse_epoch_as_float()
|
|
Packit Service |
a04d08 |
base_time = kernel_start
|
|
Packit Service |
a04d08 |
status = SUCCESS_CODE
|
|
Packit Service |
a04d08 |
# lxc based containers do not set their monotonic zero point to be when
|
|
Packit Service |
a04d08 |
# the container starts, instead keep using host boot as zero point
|
|
Packit Service |
a04d08 |
# time.CLOCK_MONOTONIC_RAW is only available in python 3.3
|
|
Packit Service |
a04d08 |
if util.is_container():
|
|
Packit Service |
a04d08 |
# clock.monotonic also uses host boot as zero point
|
|
Packit Service |
a04d08 |
if sys.version_info >= (3, 3):
|
|
Packit Service |
a04d08 |
base_time = float(time.time()) - float(time.monotonic())
|
|
Packit Service |
a04d08 |
# TODO: lxcfs automatically truncates /proc/uptime to seconds
|
|
Packit Service |
a04d08 |
# in containers when https://github.com/lxc/lxcfs/issues/292
|
|
Packit Service |
a04d08 |
# is fixed, util.uptime() should be used instead of stat on
|
|
Packit Service |
a04d08 |
try:
|
|
Packit Service |
a04d08 |
file_stat = os.stat('/proc/1/cmdline')
|
|
Packit Service |
a04d08 |
kernel_start = file_stat.st_atime
|
|
Packit Service |
a04d08 |
except OSError as err:
|
|
Packit Service |
a04d08 |
raise RuntimeError('Could not determine container boot '
|
|
Packit Service |
a04d08 |
'time from /proc/1/cmdline. ({})'
|
|
Packit Service |
9bfd13 |
.format(err)) from err
|
|
Packit Service |
a04d08 |
status = CONTAINER_CODE
|
|
Packit Service |
a04d08 |
else:
|
|
Packit Service |
a04d08 |
status = FAIL_CODE
|
|
Packit Service |
a04d08 |
kernel_end = base_time + delta_k_end
|
|
Packit Service |
a04d08 |
cloudinit_sysd = base_time + delta_ci_s
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
except Exception as e:
|
|
Packit Service |
a04d08 |
# Except ALL exceptions as Systemctl reader can throw many different
|
|
Packit Service |
a04d08 |
# errors, but any failure in systemctl means that timestamps cannot be
|
|
Packit Service |
a04d08 |
# obtained
|
|
Packit Service |
a04d08 |
print(e)
|
|
Packit Service |
a04d08 |
return TIMESTAMP_UNKNOWN
|
|
Packit Service |
a04d08 |
return status, kernel_start, kernel_end, cloudinit_sysd
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def generate_records(events, blame_sort=False,
|
|
Packit Service |
a04d08 |
print_format="(%n) %d seconds in %I%D",
|
|
Packit Service |
a04d08 |
dump_files=False, log_datafiles=False):
|
|
Packit Service |
a04d08 |
'''
|
|
Packit Service |
a04d08 |
Take in raw events and create parent-child dependencies between events
|
|
Packit Service |
a04d08 |
in order to order events in chronological order.
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
:param events: JSONs from dump that represents events taken from logs
|
|
Packit Service |
a04d08 |
:param blame_sort: whether to sort by timestamp or by time taken.
|
|
Packit Service |
a04d08 |
:param print_format: formatting to represent event, time stamp,
|
|
Packit Service |
a04d08 |
and time taken by the event in one line
|
|
Packit Service |
a04d08 |
:param dump_files: whether to dump files into JSONs
|
|
Packit Service |
a04d08 |
:param log_datafiles: whether or not to log events generated
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
:return: boot records ordered chronologically
|
|
Packit Service |
a04d08 |
'''
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
sorted_events = sorted(events, key=lambda x: x['timestamp'])
|
|
Packit Service |
a04d08 |
records = []
|
|
Packit Service |
a04d08 |
start_time = None
|
|
Packit Service |
a04d08 |
total_time = 0.0
|
|
Packit Service |
a04d08 |
stage_start_time = {}
|
|
Packit Service |
a04d08 |
stages_seen = []
|
|
Packit Service |
a04d08 |
boot_records = []
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
unprocessed = []
|
|
Packit Service |
a04d08 |
for e in range(0, len(sorted_events)):
|
|
Packit Service |
a04d08 |
event = events[e]
|
|
Packit Service |
a04d08 |
try:
|
|
Packit Service |
a04d08 |
next_evt = events[e + 1]
|
|
Packit Service |
a04d08 |
except IndexError:
|
|
Packit Service |
a04d08 |
next_evt = None
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
if event_type(event) == 'start':
|
|
Packit Service |
a04d08 |
if event.get('name') in stages_seen:
|
|
Packit Service |
a04d08 |
records.append(total_time_record(total_time))
|
|
Packit Service |
a04d08 |
boot_records.append(records)
|
|
Packit Service |
a04d08 |
records = []
|
|
Packit Service |
a04d08 |
start_time = None
|
|
Packit Service |
a04d08 |
total_time = 0.0
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
if start_time is None:
|
|
Packit Service |
a04d08 |
stages_seen = []
|
|
Packit Service |
a04d08 |
start_time = event_datetime(event)
|
|
Packit Service |
a04d08 |
stage_start_time[event_parent(event)] = start_time
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
# see if we have a pair
|
|
Packit Service |
a04d08 |
if event_name(event) == event_name(next_evt):
|
|
Packit Service |
a04d08 |
if event_type(next_evt) == 'finish':
|
|
Packit Service |
a04d08 |
records.append(format_record(print_format,
|
|
Packit Service |
a04d08 |
event_record(start_time,
|
|
Packit Service |
a04d08 |
event,
|
|
Packit Service |
a04d08 |
next_evt)))
|
|
Packit Service |
a04d08 |
else:
|
|
Packit Service |
a04d08 |
# This is a parent event
|
|
Packit Service |
a04d08 |
records.append("Starting stage: %s" % event.get('name'))
|
|
Packit Service |
a04d08 |
unprocessed.append(event)
|
|
Packit Service |
a04d08 |
stages_seen.append(event.get('name'))
|
|
Packit Service |
a04d08 |
continue
|
|
Packit Service |
a04d08 |
else:
|
|
Packit Service |
a04d08 |
prev_evt = unprocessed.pop()
|
|
Packit Service |
a04d08 |
if event_name(event) == event_name(prev_evt):
|
|
Packit Service |
a04d08 |
record = event_record(start_time, prev_evt, event)
|
|
Packit Service |
a04d08 |
records.append(format_record("Finished stage: "
|
|
Packit Service |
a04d08 |
"(%n) %d seconds",
|
|
Packit Service |
a04d08 |
record) + "\n")
|
|
Packit Service |
a04d08 |
total_time += record.get('delta')
|
|
Packit Service |
a04d08 |
else:
|
|
Packit Service |
a04d08 |
# not a match, put it back
|
|
Packit Service |
a04d08 |
unprocessed.append(prev_evt)
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
records.append(total_time_record(total_time))
|
|
Packit Service |
a04d08 |
boot_records.append(records)
|
|
Packit Service |
a04d08 |
return boot_records
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def show_events(events, print_format):
|
|
Packit Service |
a04d08 |
'''
|
|
Packit Service |
a04d08 |
A passthrough method that makes it easier to call generate_records()
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
:param events: JSONs from dump that represents events taken from logs
|
|
Packit Service |
a04d08 |
:param print_format: formatting to represent event, time stamp,
|
|
Packit Service |
a04d08 |
and time taken by the event in one line
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
:return: boot records ordered chronologically
|
|
Packit Service |
a04d08 |
'''
|
|
Packit Service |
a04d08 |
return generate_records(events, print_format=print_format)
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def load_events_infile(infile):
|
|
Packit Service |
a04d08 |
'''
|
|
Packit Service |
a04d08 |
Takes in a log file, read it, and convert to json.
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
:param infile: The Log file to be read
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
:return: json version of logfile, raw file
|
|
Packit Service |
a04d08 |
'''
|
|
Packit Service |
a04d08 |
data = infile.read()
|
|
Packit Service |
a04d08 |
try:
|
|
Packit Service |
a04d08 |
return json.loads(data), data
|
|
Packit Service |
a04d08 |
except ValueError:
|
|
Packit Service |
a04d08 |
return None, data
|