Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / tools / telemetry / telemetry / core / platform / tracing_category_filter.py
1 # Copyright 2014 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
5 import re
6
7
8 def CreateNoOverheadFilter():
9   """Returns a filter with the least overhead possible.
10
11   This contains no sub-traces of thread tasks, so it's only useful for
12   capturing the cpu-time spent on threads (as well as needed benchmark
13   traces).
14
15   FIXME: Remove webkit.console when blink.console lands in chromium and
16   the ref builds are updated. crbug.com/386847
17   """
18   categories = [
19     "toplevel",
20     "benchmark",
21     "webkit.console",
22     "blink.console",
23     "trace_event_overhead"
24   ]
25   return TracingCategoryFilter(filter_string=','.join(categories))
26
27
28 def CreateMinimalOverheadFilter():
29   """Returns a filter with the best-effort amount of overhead."""
30   return TracingCategoryFilter(filter_string='')
31
32
33 def CreateDebugOverheadFilter():
34   """Returns a filter with as many traces enabled as is useful."""
35   return TracingCategoryFilter(filter_string='*,disabled-by-default-cc.debug')
36
37
38 _delay_re = re.compile(r'DELAY[(][A-Za-z0-9._;]+[)]')
39
40
41 class TracingCategoryFilter(object):
42   """A set of included and excluded categories that should be traced.
43
44   The TraceCategoryFilter allows fine tuning of what data is traced. Basic
45   choice of which tracers to use is done by TracingOptions.
46
47   Providing filter_string=None gives the default category filter, which leaves
48   what to trace up to the individual trace systems.
49   """
50   def __init__(self, filter_string=None):
51     self._included_categories = set()
52     self._excluded_categories = set()
53     self._disabled_by_default_categories = set()
54     self._synthetic_delays = set()
55     self.contains_wildcards = False
56
57     if filter_string == None:
58       return
59
60     if '*' in filter_string or '?' in filter_string:
61       self.contains_wildcards = True
62
63     filter_set = set(filter_string.split(','))
64     for category in filter_set:
65       if category == '':
66         continue
67
68       if _delay_re.match(category):
69         self._synthetic_delays.add(category)
70         continue
71
72       if category[0] == '-':
73         assert not category[1:] in self._included_categories
74         self._excluded_categories.add(category[1:])
75         continue
76
77       if category.startswith('disabled-by-default-'):
78         self._disabled_by_default_categories.add(category)
79         continue
80
81       assert not category in self._excluded_categories
82       self._included_categories.add(category)
83
84   @property
85   def included_categories(self):
86     return self._included_categories
87
88   @property
89   def excluded_categories(self):
90     return self._excluded_categories
91
92   @property
93   def disabled_by_default_categories(self):
94     return self._disabled_by_default_categories
95
96   @property
97   def synthetic_delays(self):
98     return self._synthetic_delays
99
100   @property
101   def filter_string(self):
102     return self._GetFilterString(stable_output=False)
103
104   @property
105   def stable_filter_string(self):
106     return self._GetFilterString(stable_output=True)
107
108   def _GetFilterString(self, stable_output):
109     # Note: This outputs fields in an order that intentionally matches
110     # trace_event_impl's CategoryFilter string order.
111     lists = []
112     lists.append(self._included_categories)
113     lists.append(self._disabled_by_default_categories)
114     lists.append(['-%s' % x for x in self._excluded_categories])
115     lists.append(self._synthetic_delays)
116     categories = []
117     for l in lists:
118       if stable_output:
119         l = list(l)
120         l.sort()
121       categories.extend(l)
122     return ','.join(categories)
123
124   def AddIncludedCategory(self, category_glob):
125     """Explicitly enables anything matching category_glob."""
126     assert not category_glob.startswith('disabled-by-default-')
127     assert not category_glob in self._excluded_categories
128     self._included_categories.add(category_glob)
129
130   def AddExcludedCategory(self, category_glob):
131     """Explicitly disables anything matching category_glob."""
132     assert not category_glob.startswith('disabled-by-default-')
133     assert not category_glob in self._included_categories
134     self._excluded_categories.add(category_glob)
135
136   def AddSyntheticDelay(self, delay):
137     assert _delay_re.match(delay)
138     self._synthetic_delays.add(delay)
139
140   def IsSubset(self, other):
141     """ Determine if filter A (self) is a subset of filter B (other).
142         Returns True if A is a subset of B, False if A is not a subset of B,
143         and None if we can't tell for sure.
144     """
145     # We don't handle filters with wildcards in this test.
146     if self.contains_wildcards or other.contains_wildcards:
147       return None
148
149     # Disabled categories get into a trace if and only if they are contained in
150     # the 'disabled' set. Return False if A's disabled set is not a subset of
151     # B's disabled set.
152     if not self.disabled_by_default_categories <= \
153        other.disabled_by_default_categories:
154       return False
155
156     # If A defines more or different synthetic delays than B, then A is not a
157     # subset.
158     if not self.synthetic_delays <= other.synthetic_delays:
159       return False
160
161     if self.included_categories and other.included_categories:
162       # A and B have explicit include lists. If A includes something that B
163       # doesn't, return False.
164       if not self.included_categories <= other.included_categories:
165         return False
166     elif self.included_categories:
167       # Only A has an explicit include list. If A includes something that B
168       # excludes, return False.
169       if self.included_categories.intersection(other.excluded_categories):
170         return False
171     elif other.included_categories:
172       # Only B has an explicit include list. We don't know which categories are
173       # contained in the default list, so return None.
174       return None
175     else:
176       # None of the filter have explicit include list. If B excludes categories
177       # that A doesn't exclude, return False.
178       if not other.excluded_categories <= self.excluded_categories:
179         return False
180
181     return True