1# Copyright 2015 The Chromium Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5import json
6
7from telemetry.timeline import tracing_category_filter
8
9ECHO_TO_CONSOLE = 'trace-to-console'
10ENABLE_SYSTRACE = 'enable-systrace'
11RECORD_AS_MUCH_AS_POSSIBLE = 'record-as-much-as-possible'
12RECORD_CONTINUOUSLY = 'record-continuously'
13RECORD_UNTIL_FULL = 'record-until-full'
14
15# Map telemetry's tracing record_mode to the DevTools API string.
16# (The keys happen to be the same as the values.)
17RECORD_MODE_MAP = {
18  RECORD_UNTIL_FULL: 'record-until-full',
19  RECORD_CONTINUOUSLY: 'record-continuously',
20  RECORD_AS_MUCH_AS_POSSIBLE: 'record-as-much-as-possible',
21  ECHO_TO_CONSOLE: 'trace-to-console'
22}
23
24
25class MemoryDumpConfig(object):
26  """Stores the triggers for memory dumps in tracing config."""
27  def __init__(self):
28    self._triggers = []
29
30  def AddTrigger(self, mode, periodic_interval_ms):
31    """Adds a new trigger to config.
32
33    Args:
34      periodic_interval_ms: Dump time period in milliseconds.
35      level_of_detail: Memory dump level of detail string.
36          Valid arguments are "light" and "detailed".
37    """
38    assert mode in ['light', 'detailed']
39    assert periodic_interval_ms > 0
40    self._triggers.append({'mode': mode,
41                           'periodic_interval_ms': periodic_interval_ms})
42
43  def GetDictForChromeTracing(self):
44    """Returns the dump config as dictionary for chrome tracing."""
45    # An empty trigger list would mean no periodic memory dumps.
46    return {'memory_dump_config': {'triggers': self._triggers}}
47
48
49class TracingConfig(object):
50  """Tracing config is the configuration for Chrome tracing.
51
52  This produces the trace config JSON string for Chrome tracing. For the details
53  about the JSON string format, see base/trace_event/trace_config.h.
54
55  Contains tracing options:
56  Tracing options control which core tracing systems should be enabled.
57
58  This simply turns on those systems. If those systems have additional options,
59  e.g. what to trace, then they are typically configured by adding
60  categories to the TracingCategoryFilter.
61
62  Options:
63      enable_chrome_trace: a boolean that specifies whether to enable
64          chrome tracing.
65      enable_platform_display_trace: a boolean that specifies whether to
66          platform display tracing.
67      enable_android_graphics_memtrack: a boolean that specifies whether
68          to enable the memtrack_helper daemon to track graphics memory on
69          Android (see goo.gl/4Y30p9). Doesn't have any effects on other OSs.
70
71      The following ones are specific to chrome tracing. See
72      base/trace_event/trace_config.h for more information.
73          record_mode: can be any mode in RECORD_MODE_MAP. This corresponds to
74                       record modes in chrome.
75          enable_systrace: a boolean that specifies whether to enable systrace.
76
77  """
78
79  def __init__(self):
80    # Trace options.
81    self.enable_chrome_trace = False
82    self.enable_platform_display_trace = False
83    self.enable_android_graphics_memtrack = False
84    self._record_mode = RECORD_AS_MUCH_AS_POSSIBLE
85    self._enable_systrace = False
86    # Tracing category filter.
87    self._tracing_category_filter = (
88        tracing_category_filter.TracingCategoryFilter())
89    self._memory_dump_config = None
90
91  @property
92  def tracing_category_filter(self):
93    return self._tracing_category_filter
94
95  def GetChromeTraceConfigJsonString(self):
96    result = {}
97    result.update(self.GetDictForChromeTracing())
98    result.update(self._tracing_category_filter.GetDictForChromeTracing())
99    if self._memory_dump_config:
100      result.update(self._memory_dump_config.GetDictForChromeTracing())
101    return json.dumps(result, sort_keys=True)
102
103  def SetNoOverheadFilter(self):
104    """Sets a filter with the least overhead possible.
105
106    This contains no sub-traces of thread tasks, so it's only useful for
107    capturing the cpu-time spent on threads (as well as needed benchmark
108    traces).
109
110    FIXME: Remove webkit.console when blink.console lands in chromium and
111    the ref builds are updated. crbug.com/386847
112    """
113    categories = [
114      "toplevel",
115      "benchmark",
116      "webkit.console",
117      "blink.console",
118      "trace_event_overhead"
119    ]
120    self._tracing_category_filter = (
121        tracing_category_filter.TracingCategoryFilter(
122            filter_string=','.join(categories)))
123
124  def SetMinimalOverheadFilter(self):
125    self._tracing_category_filter = (
126        tracing_category_filter.TracingCategoryFilter(filter_string=''))
127
128  def SetDebugOverheadFilter(self):
129    self._tracing_category_filter = (
130        tracing_category_filter.TracingCategoryFilter(
131            filter_string='*,disabled-by-default-cc.debug'))
132
133  def SetTracingCategoryFilter(self, cf):
134    if isinstance(cf, tracing_category_filter.TracingCategoryFilter):
135      self._tracing_category_filter = cf
136    else:
137      raise TypeError(
138          'Must pass SetTracingCategoryFilter a TracingCategoryFilter instance')
139
140  def SetMemoryDumpConfig(self, dump_config):
141    if isinstance(dump_config, MemoryDumpConfig):
142      self._memory_dump_config = dump_config
143    else:
144      raise TypeError(
145          'Must pass SetMemoryDumpConfig a MemoryDumpConfig instance')
146
147  # Trace Options
148  @property
149  def record_mode(self):
150    return self._record_mode
151
152  @record_mode.setter
153  def record_mode(self, value):
154    assert value in RECORD_MODE_MAP
155    self._record_mode = value
156
157  @property
158  def enable_systrace(self):
159    return self._enable_systrace
160
161  @enable_systrace.setter
162  def enable_systrace(self, value):
163    self._enable_systrace = value
164
165  def GetTraceOptionsStringForChromeDevtool(self):
166    """Map Chrome tracing options in Telemetry to the DevTools API string."""
167    result = [RECORD_MODE_MAP[self._record_mode]]
168    if self._enable_systrace:
169      result.append(ENABLE_SYSTRACE)
170    return ','.join(result)
171
172  def GetDictForChromeTracing(self):
173    RECORD_MODE_PARAM = 'record_mode'
174    ENABLE_SYSTRACE_PARAM = 'enable_systrace'
175
176    result = {}
177    result[RECORD_MODE_PARAM] = (
178        RECORD_MODE_MAP[self._record_mode])
179    if self._enable_systrace:
180      result[ENABLE_SYSTRACE_PARAM] = True
181    return result
182