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 5import re 6 7 8def CreateLowOverheadFilter(): 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 ChromeTraceCategoryFilter(filter_string=','.join(categories)) 26 27 28def CreateDefaultOverheadFilter(): 29 """Returns a filter with the best-effort amount of overhead. 30 31 This matches Chrome tracing's default category filter setting, i.e., enable 32 all categories except the disabled-by-default-* ones. 33 34 We should use '*' instead of '' (empty string) here. On the Chrome side, both 35 '*' and '' mean default category filter setting. However, if someone adds 36 additional category filters, the behavior becomes different. 37 38 For example: 39 '*': enable all categories except the disabled-by-default-* ones. 40 '': enable all categories except the disabled-by-default-* ones. 41 42 Now add an additional category filter 'abc' to '*' and '': 43 '*,abc': enable all categories (including 'abc') except the 44 disabled-by-default-* ones. 45 'abc': enable only 'abc', and disable all other ones. 46 """ 47 return ChromeTraceCategoryFilter(filter_string='*') 48 49 50def CreateDebugOverheadFilter(): 51 """Returns a filter with as many traces enabled as is useful.""" 52 return ChromeTraceCategoryFilter( 53 filter_string='*,disabled-by-default-cc.debug') 54 55 56_delay_re = re.compile(r'DELAY[(][A-Za-z0-9._;]+[)]') 57 58 59class ChromeTraceCategoryFilter(object): 60 """A set of included and excluded categories that should be traced. 61 62 The ChromeTraceCategoryFilter allows fine tuning of what data is traced for 63 Chrome. Basic choice of which tracers to use is done by TracingConfig. 64 65 Providing filter_string=None gives the default category filter, which leaves 66 what to trace up to the individual trace systems. 67 """ 68 def __init__(self, filter_string=None): 69 self._included_categories = set() 70 self._excluded_categories = set() 71 self._disabled_by_default_categories = set() 72 self._synthetic_delays = set() 73 self.contains_wildcards = False 74 self.AddFilterString(filter_string) 75 76 def AddFilterString(self, filter_string): 77 if filter_string == None: 78 return 79 80 if '*' in filter_string or '?' in filter_string: 81 self.contains_wildcards = True 82 83 filter_set = set([cf.strip() for cf in filter_string.split(',')]) 84 for category in filter_set: 85 if category == '': 86 continue 87 88 if _delay_re.match(category): 89 self._synthetic_delays.add(category) 90 continue 91 92 if category[0] == '-': 93 assert not category[1:] in self._included_categories 94 self._excluded_categories.add(category[1:]) 95 continue 96 97 if category.startswith('disabled-by-default-'): 98 self._disabled_by_default_categories.add(category) 99 continue 100 101 assert not category in self._excluded_categories 102 self._included_categories.add(category) 103 104 @property 105 def included_categories(self): 106 return self._included_categories 107 108 @property 109 def excluded_categories(self): 110 return self._excluded_categories 111 112 @property 113 def disabled_by_default_categories(self): 114 return self._disabled_by_default_categories 115 116 @property 117 def synthetic_delays(self): 118 return self._synthetic_delays 119 120 @property 121 def filter_string(self): 122 return self._GetFilterString(stable_output=False) 123 124 @property 125 def stable_filter_string(self): 126 return self._GetFilterString(stable_output=True) 127 128 def _GetFilterString(self, stable_output): 129 # Note: This outputs fields in an order that intentionally matches 130 # trace_event_impl's CategoryFilter string order. 131 lists = [] 132 lists.append(self._included_categories) 133 lists.append(self._disabled_by_default_categories) 134 lists.append(['-%s' % x for x in self._excluded_categories]) 135 lists.append(self._synthetic_delays) 136 categories = [] 137 for l in lists: 138 if stable_output: 139 l = list(l) 140 l.sort() 141 categories.extend(l) 142 return ','.join(categories) 143 144 def GetDictForChromeTracing(self): 145 INCLUDED_CATEGORIES_PARAM = 'included_categories' 146 EXCLUDED_CATEGORIES_PARAM = 'excluded_categories' 147 SYNTHETIC_DELAYS_PARAM = 'synthetic_delays' 148 149 result = {} 150 if self._included_categories or self._disabled_by_default_categories: 151 result[INCLUDED_CATEGORIES_PARAM] = list( 152 self._included_categories | self._disabled_by_default_categories) 153 if self._excluded_categories: 154 result[EXCLUDED_CATEGORIES_PARAM] = list(self._excluded_categories) 155 if self._synthetic_delays: 156 result[SYNTHETIC_DELAYS_PARAM] = list(self._synthetic_delays) 157 return result 158 159 def AddDisabledByDefault(self, category): 160 assert category.startswith('disabled-by-default-') 161 self._disabled_by_default_categories.add(category) 162 163 def AddIncludedCategory(self, category_glob): 164 """Explicitly enables anything matching category_glob.""" 165 assert not category_glob.startswith('disabled-by-default-') 166 assert not category_glob in self._excluded_categories 167 self._included_categories.add(category_glob) 168 169 def AddExcludedCategory(self, category_glob): 170 """Explicitly disables anything matching category_glob.""" 171 assert not category_glob.startswith('disabled-by-default-') 172 assert not category_glob in self._included_categories 173 self._excluded_categories.add(category_glob) 174 175 def AddSyntheticDelay(self, delay): 176 assert _delay_re.match(delay) 177 self._synthetic_delays.add(delay) 178 179 def IsSubset(self, other): 180 """ Determine if filter A (self) is a subset of filter B (other). 181 Returns True if A is a subset of B, False if A is not a subset of B, 182 and None if we can't tell for sure. 183 """ 184 # We don't handle filters with wildcards in this test. 185 if self.contains_wildcards or other.contains_wildcards: 186 return None 187 188 # Disabled categories get into a trace if and only if they are contained in 189 # the 'disabled' set. Return False if A's disabled set is not a subset of 190 # B's disabled set. 191 if not self.disabled_by_default_categories <= \ 192 other.disabled_by_default_categories: 193 return False 194 195 # If A defines more or different synthetic delays than B, then A is not a 196 # subset. 197 if not self.synthetic_delays <= other.synthetic_delays: 198 return False 199 200 if self.included_categories and other.included_categories: 201 # A and B have explicit include lists. If A includes something that B 202 # doesn't, return False. 203 if not self.included_categories <= other.included_categories: 204 return False 205 elif self.included_categories: 206 # Only A has an explicit include list. If A includes something that B 207 # excludes, return False. 208 if self.included_categories.intersection(other.excluded_categories): 209 return False 210 elif other.included_categories: 211 # Only B has an explicit include list. We don't know which categories are 212 # contained in the default list, so return None. 213 return None 214 else: 215 # None of the filter have explicit include list. If B excludes categories 216 # that A doesn't exclude, return False. 217 if not other.excluded_categories <= self.excluded_categories: 218 return False 219 220 return True 221