Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(338)

Unified Diff: systrace/systrace/tracing_agents/ftrace_agent.py

Issue 1776013005: [DO NOT COMMIT] Refactor systrace to support new clock sync design (Closed) Base URL: git@github.com:catapult-project/catapult@master
Patch Set: fix categories issue Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: systrace/systrace/tracing_agents/ftrace_agent.py
diff --git a/systrace/systrace/agents/ftrace_agent.py b/systrace/systrace/tracing_agents/ftrace_agent.py
similarity index 48%
rename from systrace/systrace/agents/ftrace_agent.py
rename to systrace/systrace/tracing_agents/ftrace_agent.py
index 758fc617e5e10dea6140501b7a7d678e6dbf49ce..281a88db31ad7dec298609366327331bcbea7b87 100644
--- a/systrace/systrace/agents/ftrace_agent.py
+++ b/systrace/systrace/tracing_agents/ftrace_agent.py
@@ -4,10 +4,15 @@
import os
import sys
-import time
-from systrace import systrace_agent
+from collections import namedtuple
+from devil.utils import timeout_retry
+from systrace.tracing_agents import TracingAgent
+from systrace.tracing_agents import TraceResults
+ftrace_postproc = namedtuple('ftrace_postproc', ['fix_threads',
+ 'fix_tgids',
+ 'fix_circular'])
class FtraceAgentIo(object):
@@ -25,6 +30,13 @@ class FtraceAgentIo(object):
def haveWritePermissions(path):
return os.access(path, os.W_OK)
+ @staticmethod
+ def checkAndWriteFile(path, data):
+ if FtraceAgentIo.haveWritePermissions(path):
+ FtraceAgentIo.writeFile(path, data)
+ else:
+ raise IOError('Cannot write to %s; did you forget sudo/root?' % path)
+
FT_DIR = "/sys/kernel/debug/tracing/"
FT_CLOCK = FT_DIR + "trace_clock"
FT_BUFFER_SIZE = FT_DIR + "buffer_size_kb"
@@ -84,118 +96,145 @@ all_categories = {
}
-def try_create_agent(options, categories):
+def list_categories(_):
+ agent = FtraceAgent(FtraceAgentIo)
+ agent._print_avail_categories()
+
+
+def try_create_agent(options, _):
if options.target != 'linux':
return False
- return FtraceAgent(options, categories, FtraceAgentIo)
+ return FtraceAgent(FtraceAgentIo)
-class FtraceAgent(systrace_agent.SystraceAgent):
+def _get_trace_buffer_size(options):
+ buffer_size = 4096
+ if ((options.trace_buf_size is not None)
+ and (options.trace_buf_size > 0)):
+ buffer_size = options.trace_buf_size
+ return buffer_size
- def __init__(self, options, categories, fio=FtraceAgentIo):
+
+class FtraceAgent(TracingAgent):
+
+ def __init__(self, fio=FtraceAgentIo):
"""Initialize a systrace agent.
Args:
options: The command-line options.
categories: The trace categories to capture.
"""
- super(FtraceAgent, self).__init__(options, categories)
- if not self._categories:
- self._categories = ["sched"]
+ super(FtraceAgent, self).__init__()
self._fio = fio
- self._categories = [x for x in self._categories
- if self._is_category_available(x)]
- self._expect_trace = False
-
- def _get_trace_buffer_size(self):
- buffer_size = 4096
- if ((self._options.trace_buf_size is not None)
- and (self._options.trace_buf_size > 0)):
- buffer_size = self._options.trace_buf_size
- return buffer_size
-
- def _get_trace_time(self):
- wait_time = 5
- if ((self._options.trace_time is not None)
- and (self._options.trace_time > 0)):
- wait_time = self._options.trace_time
- return wait_time
-
- def start(self):
+ self._postproc = None
+ self._categories = None
+
+ def __str__(self):
+ return 'FtraceAgent'
+
+ def _fix_categories(self, categories):
+ """Fix a list of categories.
+
+ Applies the default category (sched) if there are no categories
+ in the list and removes unavailable categories from the list.
+
+ Args:
+ categories: List of categories.
+ """
+ if not categories:
+ categories = ["sched"]
+ return [x for x in categories
+ if self._is_category_available(x)]
+
+ def _StartAgentTracingImpl(self, options, categories):
"""Start tracing.
+
+ Args:
+ options: Tracing options.
+ categories: Categories of trace events to capture.
"""
- if self._options.list_categories or len(self._categories) == 0:
- self._expect_trace = False
- else:
- self._expect_trace = True
+ categories = self._fix_categories(categories)
+ self._fio.checkAndWriteFile(FT_BUFFER_SIZE,
+ str(_get_trace_buffer_size(options)))
- self._fio.writeFile(FT_BUFFER_SIZE, str(self._get_trace_buffer_size()))
+ self._fio.checkAndWriteFile(FT_CLOCK, 'global')
+ self._fio.checkAndWriteFile(FT_TRACER, 'nop')
+ self._fio.checkAndWriteFile(FT_OVERWRITE, "0")
- self._fio.writeFile(FT_CLOCK, 'global')
- self._fio.writeFile(FT_TRACER, 'nop')
- self._fio.writeFile(FT_OVERWRITE, "0")
+ # TODO: riandrews to push necessary patches for TGID option to upstream
+ # linux kernel
+ # self._fio.checkAndWriteFile(FT_PRINT_TGID, '1')
- # TODO: riandrews to push necessary patches for TGID option to upstream
- # linux kernel
- # self._fio.writeFile(FT_PRINT_TGID, '1')
+ for category in categories:
+ self._category_enable(category)
- for category in self._categories:
- self._category_enable(category)
+ self._categories = categories # need to store list of categories to disable
+ self._postproc = ftrace_postproc(options.fix_threads,
+ options.fix_tgids,
+ options.fix_circular)
- self._fio.writeFile(FT_TRACE, '')
+ self._fio.checkAndWriteFile(FT_TRACE, '')
- print "starting tracing."
- sys.stdout.flush()
+ sys.stdout.flush()
- self._fio.writeFile(FT_TRACE_ON, '1')
+ self._fio.checkAndWriteFile(FT_TRACE_ON, '1')
+ return True
+
+ def StartAgentTracing(self, options, categories, timeout=10):
+ return timeout_retry.Run(self._StartAgentTracingImpl,
+ timeout, 1,
+ args=[options, categories])
- def collect_result(self):
+ def _StopAgentTracingImpl(self):
"""Collect the result of tracing.
- This function will block while collecting the result. For sync mode, it
- reads the data, e.g., from stdout, until it finishes. For async mode, it
- blocks until the agent is stopped and the data is ready.
- """
- if self._options.list_categories or len(self._categories) == 0:
- self._print_avail_categories()
- else:
- try:
- time.sleep(self._get_trace_time())
- except KeyboardInterrupt:
- pass
- self._fio.writeFile(FT_TRACE_ON, '0')
- for category in self._categories:
- self._category_disable(category)
- if self._options.fix_threads:
- print "WARN: thread name fixing is not yet supported."
- if self._options.fix_tgids:
- print "WARN: tgid fixing is not yet supported."
- if self._options.fix_circular:
- print "WARN: circular buffer fixups are not yet supported."
-
- def expect_trace(self):
- """Check if the agent is returning a trace or not.
-
- This will be determined in collect_result().
- Returns:
- Whether the agent is expecting a trace or not.
+ This function will block while collecting the result.
"""
- return self._expect_trace
+ self._fio.checkAndWriteFile(FT_TRACE_ON, '0')
+ for category in self._categories:
+ self._category_disable(category)
+ if self._postproc.fix_threads:
+ print "WARN: thread name fixing is not yet supported."
+ if self._postproc.fix_tgids:
+ print "WARN: tgid fixing is not yet supported."
+ if self._postproc.fix_circular:
+ print "WARN: circular buffer fixups are not yet supported."
+ return True
+
+ def StopAgentTracing(self, timeout=10):
+ return timeout_retry.Run(self._StopAgentTracingImpl,
+ timeout, 1)
- def get_trace_data(self):
+ def _GetResultsImpl(self):
"""Get the trace data.
Returns:
The trace data.
"""
d = self._fio.readFile(FT_TRACE)
- self._fio.writeFile(FT_BUFFER_SIZE, "1")
- return d
+ self._fio.checkAndWriteFile(FT_BUFFER_SIZE, "1")
+ return TraceResults('systemTraceEvents', d)
- def get_class_name(self):
- return 'trace-data'
+ def GetResults(self, timeout=30):
+ return timeout_retry.Run(self._GetResultsImpl,
+ timeout, 1)
+
+ def SupportsExplicitClockSync(self):
+ return False
+
+ def RecordClockSyncMarker(self, sync_id, callback):
+ raise NotImplementedError
def _is_category_available(self, category):
+ """Determines if a category is available for tracing.
+
+ For a category to be available, we must have write permissions
+ to the file path needed to record the types of events in
+ that category.
+
+ Args:
+ category: Category to check.
+ """
if category not in all_categories:
return False
events_dir = FT_DIR + "events/"
@@ -207,6 +246,7 @@ class FtraceAgent(systrace_agent.SystraceAgent):
return True
def _avail_categories(self):
+ """Get list of available categories."""
ret = []
for event in all_categories:
if self._is_category_available(event):
@@ -214,6 +254,7 @@ class FtraceAgent(systrace_agent.SystraceAgent):
return ret
def _print_avail_categories(self):
+ """Print the list of available categories."""
avail = self._avail_categories()
if len(avail):
print "tracing options:"
@@ -224,6 +265,11 @@ class FtraceAgent(systrace_agent.SystraceAgent):
print "No tracing categories available - perhaps you need root?"
def _category_enable_paths(self, category):
+ """Gets the list of file paths that correspond to events in category.
+
+ Args:
+ category: Category to check.
+ """
events_dir = FT_DIR + "events/"
req_events = all_categories[category]["req"]
for event in req_events:
@@ -237,9 +283,11 @@ class FtraceAgent(systrace_agent.SystraceAgent):
yield event_full_path
def _category_enable(self, category):
+ """Enables tracing for a category."""
for path in self._category_enable_paths(category):
- self._fio.writeFile(path, "1")
+ self._fio.checkAndWriteFile(path, "1")
def _category_disable(self, category):
+ """Disables tracing for a category."""
for path in self._category_enable_paths(category):
- self._fio.writeFile(path, "0")
+ self._fio.checkAndWriteFile(path, "0")
« no previous file with comments | « systrace/systrace/tracing_agents/atrace_agent_unittest.py ('k') | systrace/systrace/tracing_agents/ftrace_agent_unittest.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698