1
0
mirror of https://github.com/ARM-software/workload-automation.git synced 2025-01-18 20:11:20 +00:00

trace-cmd: Added ability to generate reports on target device

This commit is contained in:
Sebastian Goscik 2015-12-01 11:16:05 +00:00
parent 2510329cdf
commit a697c47c49

View File

@ -22,7 +22,7 @@ import subprocess
from collections import defaultdict
from wlauto import Instrument, Parameter, Executable
from wlauto.exceptions import InstrumentError, ConfigError
from wlauto.exceptions import InstrumentError, ConfigError, DeviceError
from wlauto.core import signal
from wlauto.utils.types import boolean
@ -133,12 +133,7 @@ class TraceCmdInstrument(Instrument):
"""),
Parameter('report', kind=boolean, default=True,
description="""
Specifies whether host-side reporting should be performed once the binary trace has been
pulled form the device.
.. note:: This requires the latest version of trace-cmd to be installed on the host (the
one in your distribution's repos may be too old).
Specifies whether reporting should be performed once the binary trace has been generated.
"""),
Parameter('no_install', kind=boolean, default=False,
description="""
@ -146,6 +141,15 @@ class TraceCmdInstrument(Instrument):
not already a trace-cmd on the device, an error is raised.
"""),
Parameter('report_on_target', kind=boolean, default=False,
description="""
When enabled generation of reports will be done host-side because the generated file is
very large. If trace-cmd is not available on the host device this setting and be disabled
and the report will be generated on the target device.
.. note:: This requires the latest version of trace-cmd to be installed on the host (the
one in your distribution's repos may be too old).
"""),
]
def __init__(self, device, **kwargs):
@ -227,45 +231,35 @@ class TraceCmdInstrument(Instrument):
# The size of trace.dat will depend on how long trace-cmd was running.
# Therefore timout for the pull command must also be adjusted
# accordingly.
pull_timeout = (self.stop_time - self.start_time)
self.device.pull_file(self.output_file, context.output_directory, timeout=pull_timeout)
self._pull_timeout = (self.stop_time - self.start_time) # pylint: disable=attribute-defined-outside-init
self.device.pull_file(self.output_file, context.output_directory, timeout=self._pull_timeout)
context.add_iteration_artifact('bintrace', OUTPUT_TRACE_FILE, kind='data',
description='trace-cmd generated ftrace dump.')
local_trace_file = os.path.join(context.output_directory, OUTPUT_TRACE_FILE)
local_txt_trace_file = os.path.join(context.output_directory, OUTPUT_TEXT_FILE)
if self.report:
# To get the output of trace.dat, trace-cmd must be installed
# This is done host-side because the generated file is very large
if not os.path.isfile(local_trace_file):
self.logger.warning('Not generating trace.txt, as {} does not exist.'.format(OUTPUT_TRACE_FILE))
try:
command = 'trace-cmd report {} > {}'.format(local_trace_file, local_txt_trace_file)
self.logger.debug(command)
process = subprocess.Popen(command, stderr=subprocess.PIPE, shell=True)
_, error = process.communicate()
if process.returncode:
raise InstrumentError('trace-cmd returned non-zero exit code {}'.format(process.returncode))
if error:
# logged at debug level, as trace-cmd always outputs some
# errors that seem benign.
self.logger.debug(error)
if os.path.isfile(local_txt_trace_file):
context.add_iteration_artifact('txttrace', OUTPUT_TEXT_FILE, kind='export',
description='trace-cmd generated ftrace dump.')
self.logger.debug('Verifying traces.')
with open(local_txt_trace_file) as fh:
for line in fh:
if 'EVENTS DROPPED' in line:
self.logger.warning('Dropped events detected.')
break
else:
self.logger.debug('Trace verified.')
else:
self.logger.warning('Could not generate trace.txt.')
except OSError:
raise InstrumentError('Could not find trace-cmd. Please make sure it is installed and is in PATH.')
# By default this is done host-side because the generated file is
# very large
if self.report_on_target:
self._generate_report_on_target(context)
else:
self._generate_report_on_host(context)
if os.path.isfile(local_txt_trace_file):
context.add_iteration_artifact('txttrace', OUTPUT_TEXT_FILE, kind='export',
description='trace-cmd generated ftrace dump.')
self.logger.debug('Verifying traces.')
with open(local_txt_trace_file) as fh:
for line in fh:
if 'EVENTS DROPPED' in line:
self.logger.warning('Dropped events detected.')
break
else:
self.logger.debug('Trace verified.')
else:
self.logger.warning('Could not generate trace.txt.')
def teardown(self, context):
self.device.delete_file(os.path.join(self.device.working_directory, OUTPUT_TRACE_FILE))
@ -315,8 +309,37 @@ class TraceCmdInstrument(Instrument):
self.logger.warning('Failed to set trace buffer size to {}, value set was {}'.format(target_buffer_size, buffer_size))
break
def _generate_report_on_target(self, context):
try:
trace_file = self.output_file
txt_trace_file = os.path.join(self.device.working_directory, OUTPUT_TEXT_FILE)
command = 'trace-cmd report {} > {}'.format(trace_file, txt_trace_file)
self.device.execute(command)
self.device.pull_file(txt_trace_file, context.output_directory, timeout=self._pull_timeout)
except DeviceError:
raise InstrumentError('Could not generate TXT report on target.')
def _generate_report_on_host(self, context):
local_trace_file = os.path.join(context.output_directory, OUTPUT_TRACE_FILE)
local_txt_trace_file = os.path.join(context.output_directory, OUTPUT_TEXT_FILE)
command = 'trace-cmd report {} > {}'.format(local_trace_file, local_txt_trace_file)
self.logger.debug(command)
if not os.path.isfile(local_trace_file):
self.logger.warning('Not generating trace.txt, as {} does not exist.'.format(OUTPUT_TRACE_FILE))
else:
try:
process = subprocess.Popen(command, stderr=subprocess.PIPE, shell=True)
_, error = process.communicate()
if process.returncode:
raise InstrumentError('trace-cmd returned non-zero exit code {}'.format(process.returncode))
if error:
# logged at debug level, as trace-cmd always outputs some
# errors that seem benign.
self.logger.debug(error)
except OSError:
raise InstrumentError('Could not find trace-cmd. Please make sure it is installed and is in PATH.')
def _build_trace_events(events):
event_string = ' '.join(['-e {}'.format(e) for e in events])
return event_string