""" 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)