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