"""
Trace kernel events with Linux Tracing Toolkit (lttng).
You need to install the lttng patched kernel in order to use the profiler.
Examples:
job.profilers.add('lttng', tracepoints = None): enable all trace points.
job.profilers.add('lttng', tracepoints = []): disable all trace points.
job.profilers.add('lttng', tracepoints = ['kernel_arch_syscall_entry',
'kernel_arch_syscall_exit'])
will only trace syscall events.
Take a look at /proc/ltt for the list of the tracing events currently
supported by lttng and their output formats.
To view the collected traces, copy results/your-test/profiler/lttng
to a machine that has Linux Tracing Toolkit Viewer (lttv) installed:
test$ scp -r results/your-test/profiler/lttng user@localmachine:/home/tmp/
Then you can examine the traces either in text mode or in GUI:
localmachine$ lttv -m textDump -t /home/tmp/lttng
or
localmachine$ lttv-gui -t /home/tmp/lttng &
"""
import os, shutil, time
from autotest_lib.client.bin import utils, profiler
from autotest_lib.client.common_lib import error
class lttng(profiler.profiler):
version = 1
# http://ltt.polymtl.ca/lttng/ltt-control-0.51-12082008.tar.gz
def setup(self, tarball='ltt-control-0.51-12082008.tar.gz', **dargs):
self.tarball = utils.unmap_url(self.bindir, tarball, self.tmpdir)
utils.extract_tarball_to_dir(self.tarball, self.srcdir)
os.chdir(self.srcdir)
utils.configure()
utils.make()
# tracepoints: list of trace points to enable
# outputsize: size limit for lttng output file. -1: no limit.
def initialize(self, outputsize=1048576, tracepoints=None, **dargs):
self.job.require_gcc()
self.tracepoints = tracepoints
self.ltt_bindir = os.path.join(self.srcdir, 'lttctl')
self.lttctl = os.path.join(self.ltt_bindir, 'lttctl')
self.lttd = os.path.join(self.srcdir, 'lttd', 'lttd')
self.armall = os.path.join(self.ltt_bindir, 'ltt-armall')
self.disarmall = os.path.join(self.ltt_bindir, 'ltt-disarmall')
self.mountpoint = '/mnt/debugfs'
self.outputsize = outputsize
os.putenv('LTT_DAEMON', self.lttd)
if not os.path.exists(self.mountpoint):
os.mkdir(self.mountpoint)
utils.system('mount -t debugfs debugfs ' + self.mountpoint,
ignore_status=True)
utils.system('modprobe ltt-control')
utils.system('modprobe ltt-statedump')
# clean up from any tracing we left running
utils.system(self.lttctl + ' -n test -R', ignore_status=True)
utils.system(self.disarmall, ignore_status=True)
if tracepoints is None:
utils.system(self.armall, ignore_status=True)
else:
for tracepoint in self.tracepoints:
if tracepoint in ('list_process_state',
'user_generic_thread_brand', 'fs_exec',
'kernel_process_fork', 'kernel_process_free',
'kernel_process_exit',
'kernel_arch_kthread_create',
'list_statedump_end', 'list_vm_map'):
channel = 'processes'
elif tracepoint in ('list_interrupt',
'statedump_idt_table',
'statedump_sys_call_table'):
channel = 'interrupts'
elif tracepoint in ('list_network_ipv4_interface',
'list_network_ip_interface'):
channel = 'network'
elif tracepoint in ('kernel_module_load', 'kernel_module_free'):
channel = 'modules'
else:
channel = ''
print 'Connecting ' + tracepoint
utils.write_one_line('/proc/ltt', 'connect ' + tracepoint
+ ' default dynamic ' + channel)
def start(self, test):
self.output = os.path.join(test.profdir, 'lttng')
utils.system('%s -n test -d -l %s/ltt -t %s' %
(self.lttctl, self.mountpoint, self.output))
def stop(self, test):
utils.system(self.lttctl + ' -n test -R')
time.sleep(10)
if self.outputsize != -1:
# truncate lttng output file to the specified limit
for filename in os.listdir(self.output):
file_path = os.path.join(self.output, filename)
if os.path.isdir(file_path):
continue
size = os.stat(file_path)[6] # grab file size
if size > self.outputsize:
f = open(file_path, 'r+')
f.truncate(self.outputsize)
f.close()
tarball = os.path.join(test.profdir, 'lttng.tar.bz2')
utils.system("tar -cvjf %s -C %s %s" % (tarball, test.profdir, 'lttng'))
utils.system('rm -rf ' + self.output)