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 5from telemetry.timeline import async_slice as async_slice_module 6from telemetry.timeline import flow_event as flow_event_module 7from telemetry.timeline import slice as slice_module 8 9 10class TimelineEventContainer(object): 11 """Represents a container for events. 12 13 """ 14 def __init__(self, name, parent): 15 self.parent = parent 16 self.name = name 17 18 @staticmethod 19 def IsAsyncSlice(t): 20 return t == async_slice_module.AsyncSlice 21 22 # Basic functions that subclasses of TimelineEventContainer should implement 23 # in order to expose their events. New methods should be added to this part of 24 # the code only when absolutely certain they're needed. 25 26 def IterChildContainers(self): 27 raise NotImplementedError() 28 29 def IterEventsInThisContainer(self, event_type_predicate, event_predicate): 30 """Iterates all the TimelineEvents in this container. 31 32 Only events with a type matching event_type_predicate AND matching event 33 event_predicate will be yielded. 34 35 event_type_predicate is given an actual type object, e.g.: 36 event_type_predicate(slice_module.Slice) 37 38 event_predicate is given actual events: 39 event_predicate(thread.slices[7]) 40 41 DO NOT ASSUME that the event_type_predicate will be called for every event 42 found. The relative calling order of the two is left up to the implementer 43 of the method. 44 45 """ 46 del event_type_predicate, event_predicate # unused 47 return 48 yield # pylint: disable=unreachable 49 50 51 def IterAllEvents(self, 52 recursive=True, 53 event_type_predicate=lambda t: True, 54 event_predicate=lambda e: True): 55 """Iterates all events in this container, pre-filtered by two predicates. 56 57 Only events with a type matching event_type_predicate AND matching event 58 event_predicate will be yielded. 59 60 event_type_predicate is given an actual type object, e.g.: 61 event_type_predicate(slice_module.Slice) 62 63 event_predicate is given actual events: 64 event_predicate(thread.slices[7]) 65 """ 66 if not recursive: 67 for e in self.IterEventsInThisContainer( 68 event_type_predicate, event_predicate): 69 yield e 70 return 71 72 # TODO(nduca): Write this as a proper iterator instead of one that creates a 73 # list and then iterates it. 74 containers = [] 75 def GetContainersRecursive(container): 76 containers.append(container) 77 for container in container.IterChildContainers(): 78 GetContainersRecursive(container) 79 GetContainersRecursive(self) 80 81 # Actually create the iterator. 82 for c in containers: 83 for e in c.IterEventsInThisContainer(event_type_predicate, 84 event_predicate): 85 yield e 86 87 # Helper functions for finding common kinds of events. Must always take an 88 # optinal recurisve parameter and be implemented in terms fo IterAllEvents. 89 def IterAllEventsOfName(self, name, recursive=True): 90 return self.IterAllEvents( 91 recursive=recursive, 92 event_type_predicate=lambda t: True, 93 event_predicate=lambda e: e.name == name) 94 95 def IterAllSlices(self, recursive=True): 96 return self.IterAllEvents( 97 recursive=recursive, 98 event_type_predicate=lambda t: t == slice_module.Slice) 99 100 def IterAllSlicesInRange(self, start, end, recursive=True): 101 return self.IterAllEvents( 102 recursive=recursive, 103 event_type_predicate=lambda t: t == slice_module.Slice, 104 event_predicate=lambda s: s.start >= start and s.end <= end) 105 106 def IterAllSlicesOfName(self, name, recursive=True): 107 return self.IterAllEvents( 108 recursive=recursive, 109 event_type_predicate=lambda t: t == slice_module.Slice, 110 event_predicate=lambda e: e.name == name) 111 112 def IterAllToplevelSlicesOfName(self, name, recursive=True): 113 return self.IterAllEvents( 114 recursive=recursive, 115 event_type_predicate=lambda t: t == slice_module.Slice, 116 event_predicate=lambda e: e.name == name and e.parent_slice == None) 117 118 def IterAllAsyncSlicesOfName(self, name, recursive=True): 119 return self.IterAllEvents( 120 recursive=recursive, 121 event_type_predicate=self.IsAsyncSlice, 122 event_predicate=lambda e: e.name == name) 123 124 def IterAllAsyncSlicesStartsWithName(self, name, recursive=True): 125 return self.IterAllEvents( 126 recursive=recursive, 127 event_type_predicate=self.IsAsyncSlice, 128 event_predicate=lambda e: e.name.startswith(name)) 129 130 def IterAllFlowEvents(self, recursive=True): 131 return self.IterAllEvents( 132 recursive=recursive, 133 event_type_predicate=lambda t: t == flow_event_module.FlowEvent) 134 135 # List versions. These should always be simple expressions that list() on 136 # an underlying iter method. 137 def GetAllEvents(self, recursive=True): 138 return list(self.IterAllEvents(recursive=recursive)) 139 140 def GetAllEventsOfName(self, name, recursive=True): 141 return list(self.IterAllEventsOfName(name, recursive)) 142 143 def GetAllToplevelSlicesOfName(self, name, recursive=True): 144 return list(self.IterAllToplevelSlicesOfName(name, recursive)) 145