Blob Blame Raw
From a38cb7ff39accd9ea600e2409866eb12fb3b8871 Mon Sep 17 00:00:00 2001
From: Stefan Hajnoczi <stefanha@redhat.com>
Date: Tue, 7 Oct 2014 14:06:55 +0200
Subject: [PATCH 37/43] trace: add tracetool simpletrace_stap format

Message-id: <1412690820-31016-7-git-send-email-stefanha@redhat.com>
Patchwork-id: 61611
O-Subject: [RHEL7.1 qemu-kvm PATCH 06/11] trace: add tracetool simpletrace_stap format
Bugzilla: 1088112
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>

This new tracetool "format" generates a SystemTap .stp file that outputs
simpletrace binary trace data.

In contrast to simpletrace or ftrace, SystemTap does not define its own
trace format.  All output from SystemTap is generated by .stp files.
This patch lets us generate a .stp file that outputs in the simpletrace
binary format.

This makes it possible to reuse simpletrace.py to analyze traces
recorded using SystemTap.  The simpletrace binary format is especially
useful for long-running traces like flight-recorder mode where string
formatting can be expensive.

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit 3f8b112d6b9ab65e165096582c78154dda1adc69)
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>

Downstream tracetool does not have the code reorganization from the
multi-backend tracing changes.  Therefore the stap generation has to
happen in scripts/tracetool/backend/dtrace.py while the
scripts/tracetool/format/simpletrace_stap.py file just emits the file
header.

Remember to import tracetool.backend.simple is_string() in dtrace.py.

Also note that scripts/tracetool/__init__.py filters out disabled events
so we don't need to skip them explicitly.

Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
---
 scripts/tracetool/backend/dtrace.py          | 47 ++++++++++++++++++++++++++++
 scripts/tracetool/format/simpletrace_stap.py | 21 +++++++++++++
 2 files changed, 68 insertions(+)
 create mode 100644 scripts/tracetool/format/simpletrace_stap.py

diff --git a/scripts/tracetool/backend/dtrace.py b/scripts/tracetool/backend/dtrace.py
index 614316f..2d8cd2d 100644
--- a/scripts/tracetool/backend/dtrace.py
+++ b/scripts/tracetool/backend/dtrace.py
@@ -14,6 +14,7 @@ __email__      = "stefanha@linux.vnet.ibm.com"
 
 
 from tracetool import out
+from tracetool.backend.simple import is_string
 
 
 PUBLIC = True
@@ -112,3 +113,49 @@ def stap(events):
         out('}')
 
     out()
+
+
+def simpletrace_stap(events):
+    for event_id, e in enumerate(events):
+        out('probe %(probeprefix)s.simpletrace.%(name)s = %(probeprefix)s.%(name)s ?',
+            '{',
+            probeprefix=_probeprefix(),
+            name=e.name)
+
+        # Calculate record size
+        sizes = ['24'] # sizeof(TraceRecord)
+        for type_, name in e.args:
+            name = stap_escape(name)
+            if is_string(type_):
+                out('    try {',
+                    '        arg%(name)s_str = %(name)s ? user_string_n(%(name)s, 512) : "<null>"',
+                    '    } catch {}',
+                    '    arg%(name)s_len = strlen(arg%(name)s_str)',
+                    name=name)
+                sizes.append('4 + arg%s_len' % name)
+            else:
+                sizes.append('8')
+        sizestr = ' + '.join(sizes)
+
+        # Generate format string and value pairs for record header and arguments
+        fields = [('8b', str(event_id)),
+                  ('8b', 'gettimeofday_ns()'),
+                  ('4b', sizestr),
+                  ('4b', 'pid()')]
+        for type_, name in e.args:
+            name = stap_escape(name)
+            if is_string(type_):
+                fields.extend([('4b', 'arg%s_len' % name),
+                               ('.*s', 'arg%s_len, arg%s_str' % (name, name))])
+            else:
+                fields.append(('8b', name))
+
+        # Emit the entire record in a single SystemTap printf()
+        fmt_str = '%'.join(fmt for fmt, _ in fields)
+        arg_str = ', '.join(arg for _, arg in fields)
+        out('    printf("%%%(fmt_str)s", %(arg_str)s)',
+            fmt_str=fmt_str, arg_str=arg_str)
+
+        out('}')
+
+    out()
diff --git a/scripts/tracetool/format/simpletrace_stap.py b/scripts/tracetool/format/simpletrace_stap.py
new file mode 100644
index 0000000..b8daa03
--- /dev/null
+++ b/scripts/tracetool/format/simpletrace_stap.py
@@ -0,0 +1,21 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+"""
+Generate .stp file that outputs simpletrace binary traces (DTrace with SystemTAP only).
+"""
+
+__author__     = "Stefan Hajnoczi <redhat.com>"
+__copyright__  = "Copyright (C) 2014, Red Hat, Inc."
+__license__    = "GPL version 2 or (at your option) any later version"
+
+__maintainer__ = "Stefan Hajnoczi"
+__email__      = "stefanha@redhat.com"
+
+
+from tracetool import out
+
+
+def begin(events):
+    out('/* This file is autogenerated by tracetool, do not edit. */',
+        '')
-- 
1.8.3.1