Home | History | Annotate | Download | only in trace_event_impl
      1 # Copyright 2016 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 import math
      5 import json
      6 
      7 
      8 class ParsedTraceEvents(object):
      9   def __init__(self, events = None, trace_filename = None):
     10     """
     11     Utility class for filtering and manipulating trace data.
     12 
     13     events -- An iterable object containing trace events
     14     trace_filename -- A file object that contains a complete trace.
     15 
     16     """
     17     if trace_filename and events:
     18       raise Exception("Provide either a trace file or event list")
     19     if not trace_filename and events == None:
     20       raise Exception("Provide either a trace file or event list")
     21 
     22     if trace_filename:
     23       f = open(trace_filename, 'r')
     24       t = f.read()
     25       f.close()
     26 
     27       # If the event data begins with a [, then we know it should end with a ].
     28       # The reason we check for this is because some tracing implementations
     29       # cannot guarantee that a ']' gets written to the trace file. So, we are
     30       # forgiving and if this is obviously the case, we fix it up before
     31       # throwing the string at JSON.parse.
     32       if t[0] == '[':
     33         n = len(t);
     34         if t[n - 1] != ']' and t[n - 1] != '\n':
     35           t = t + ']'
     36         elif t[n - 2] != ']' and t[n - 1] == '\n':
     37           t = t + ']'
     38         elif t[n - 3] != ']' and t[n - 2] == '\r' and t[n - 1] == '\n':
     39           t = t + ']'
     40 
     41       try:
     42         events = json.loads(t)
     43       except ValueError:
     44         raise Exception("Corrupt trace, did not parse. Value: %s" % t)
     45 
     46       if 'traceEvents' in events:
     47         events = events['traceEvents']
     48 
     49     if not hasattr(events, '__iter__'):
     50       raise Exception, 'events must be iteraable.'
     51     self.events = events
     52     self.pids = None
     53     self.tids = None
     54 
     55   def __len__(self):
     56     return len(self.events)
     57 
     58   def __getitem__(self, i):
     59     return self.events[i]
     60 
     61   def __setitem__(self, i, v):
     62     self.events[i] = v
     63 
     64   def __repr__(self):
     65     return "[%s]" % ",\n ".join([repr(e) for e in self.events])
     66 
     67   def findProcessIds(self):
     68     if self.pids:
     69       return self.pids
     70     pids = set()
     71     for e in self.events:
     72       if "pid" in e and e["pid"]:
     73         pids.add(e["pid"])
     74     self.pids = list(pids)
     75     return self.pids
     76 
     77   def findThreadIds(self):
     78     if self.tids:
     79       return self.tids
     80     tids = set()
     81     for e in self.events:
     82       if "tid" in e and e["tid"]:
     83         tids.add(e["tid"])
     84     self.tids = list(tids)
     85     return self.tids
     86 
     87   def findEventsOnProcess(self, pid):
     88     return ParsedTraceEvents([e for e in self.events if e["pid"] == pid])
     89 
     90   def findEventsOnThread(self, tid):
     91     return ParsedTraceEvents(
     92         [e for e in self.events if e["ph"] != "M" and e["tid"] == tid])
     93 
     94   def findByPhase(self, ph):
     95     return ParsedTraceEvents([e for e in self.events if e["ph"] == ph])
     96 
     97   def findByName(self, n):
     98     return ParsedTraceEvents([e for e in self.events if e["name"] == n])
     99