| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389 |
- # SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
- # SPDX-License-Identifier: Apache-2.0
- import copy
- import json
- import re
- import struct
- import espytrace.apptrace as apptrace
- SYSVIEW_EVTID_NOP = 0 # Dummy packet.
- SYSVIEW_EVTID_OVERFLOW = 1
- SYSVIEW_EVTID_ISR_ENTER = 2
- SYSVIEW_EVTID_ISR_EXIT = 3
- SYSVIEW_EVTID_TASK_START_EXEC = 4
- SYSVIEW_EVTID_TASK_STOP_EXEC = 5
- SYSVIEW_EVTID_TASK_START_READY = 6
- SYSVIEW_EVTID_TASK_STOP_READY = 7
- SYSVIEW_EVTID_TASK_CREATE = 8
- SYSVIEW_EVTID_TASK_INFO = 9
- SYSVIEW_EVTID_TRACE_START = 10
- SYSVIEW_EVTID_TRACE_STOP = 11
- SYSVIEW_EVTID_SYSTIME_CYCLES = 12
- SYSVIEW_EVTID_SYSTIME_US = 13
- SYSVIEW_EVTID_SYSDESC = 14
- SYSVIEW_EVTID_MARK_START = 15
- SYSVIEW_EVTID_MARK_STOP = 16
- SYSVIEW_EVTID_IDLE = 17
- SYSVIEW_EVTID_ISR_TO_SCHEDULER = 18
- SYSVIEW_EVTID_TIMER_ENTER = 19
- SYSVIEW_EVTID_TIMER_EXIT = 20
- SYSVIEW_EVTID_STACK_INFO = 21
- SYSVIEW_EVTID_MODULEDESC = 22
- SYSVIEW_EVTID_INIT = 24
- SYSVIEW_EVENT_ID_PREDEF_LEN_MAX = SYSVIEW_EVTID_INIT
- SYSVIEW_EVTID_NAME_RESOURCE = 25
- SYSVIEW_EVTID_PRINT_FORMATTED = 26
- SYSVIEW_EVTID_NUMMODULES = 27
- SYSVIEW_EVENT_ID_PREDEF_MAX = SYSVIEW_EVTID_NUMMODULES
- SYSVIEW_EVENT_ID_MAX = 200
- SYSVIEW_MODULE_EVENT_OFFSET = 512
- SYSVIEW_SYNC_LEN = 10
- _sysview_events_map = {
- 'SYS_NOP': SYSVIEW_EVTID_NOP,
- 'SYS_OVERFLOW': SYSVIEW_EVTID_OVERFLOW,
- 'SYS_ISR_ENTER': SYSVIEW_EVTID_ISR_ENTER,
- 'SYS_ISR_EXIT': SYSVIEW_EVTID_ISR_EXIT,
- 'SYS_TASK_START_EXEC': SYSVIEW_EVTID_TASK_START_EXEC,
- 'SYS_TASK_STOP_EXEC': SYSVIEW_EVTID_TASK_STOP_EXEC,
- 'SYS_TASK_START_READY': SYSVIEW_EVTID_TASK_START_READY,
- 'SYS_TASK_STOP_READY': SYSVIEW_EVTID_TASK_STOP_READY,
- 'SYS_TASK_CREATE': SYSVIEW_EVTID_TASK_CREATE,
- 'SYS_TASK_INFO': SYSVIEW_EVTID_TASK_INFO,
- 'SYS_TRACE_START': SYSVIEW_EVTID_TRACE_START,
- 'SYS_TRACE_STOP': SYSVIEW_EVTID_TRACE_STOP,
- 'SYS_SYSTIME_CYCLES': SYSVIEW_EVTID_SYSTIME_CYCLES,
- 'SYS_SYSTIME_US': SYSVIEW_EVTID_SYSTIME_US,
- 'SYS_SYSDESC': SYSVIEW_EVTID_SYSDESC,
- 'SYS_USER_START': SYSVIEW_EVTID_MARK_START,
- 'SYS_USER_STOP': SYSVIEW_EVTID_MARK_STOP,
- 'SYS_IDLE': SYSVIEW_EVTID_IDLE,
- 'SYS_ISR_TO_SCHEDULER': SYSVIEW_EVTID_ISR_TO_SCHEDULER,
- 'SYS_TIMER_ENTER': SYSVIEW_EVTID_TIMER_ENTER,
- 'SYS_TIMER_EXIT': SYSVIEW_EVTID_TIMER_EXIT,
- 'SYS_STACK_INFO': SYSVIEW_EVTID_STACK_INFO,
- 'SYS_MODULEDESC': SYSVIEW_EVTID_INIT,
- 'SYS_INIT': SYSVIEW_EVTID_INIT,
- 'SYS_NAME_RESOURCE': SYSVIEW_EVTID_NAME_RESOURCE,
- 'SYS_PRINT_FORMATTED': SYSVIEW_EVTID_PRINT_FORMATTED,
- 'SYS_NUMMODULES': SYSVIEW_EVTID_NUMMODULES
- }
- _os_events_map = {}
- def parse_trace(reader, parser, os_evt_map_file=''):
- """
- Parses trace.
- Parameters
- ----------
- reader : apptrace.Reader
- Trace reader object.
- parser : SysViewTraceDataParser
- Top level parser object.
- os_evt_map_file : string
- Path to file containg events format description.
- """
- global _os_events_map
- # parse OS events formats file
- _os_events_map = _read_events_map(os_evt_map_file)
- parser.esp_ext = ('; ESP_Extension\n' in _read_file_header(reader))
- _read_init_seq(reader)
- while True:
- event = parser.read_event(reader, _os_events_map)
- parser.on_new_event(event)
- def _read_events_map(os_evt_map_file):
- """
- Reads SystemView events format description from file.
- Parameters
- ----------
- os_evt_map_file : string
- Path to file containg events format description.
- Returns
- -------
- dict
- a dict with event IDs as keys and values as tuples containg event name and a list of parameters.
- """
- os_evt_map = {}
- with open(os_evt_map_file) as f:
- for line in f:
- comps = line.split()
- if len(comps) < 2:
- continue
- params = []
- if len(comps) > 2:
- for p in comps[2:]:
- sp = p.split('=')
- if sp[1].startswith('%'):
- sp[1] = sp[1][1:]
- if sp[1] == 'u':
- params.append(SysViewEventParamSimple(sp[0], _decode_u32))
- elif sp[1] == 's':
- params.append(SysViewEventParamSimple(sp[0], _decode_str))
- elif sp[1] == 't' or sp[1] == 'T' or sp[1] == 'I' or sp[1] == 'p':
- # TODO: handle shrinked task/queue ID and addresses
- params.append(SysViewEventParamSimple(sp[0], _decode_u32))
- os_evt_map[int(comps[0])] = (comps[1], params)
- return os_evt_map
- def _read_file_header(reader):
- """
- Reads SystemView trace file header.
- Parameters
- ----------
- reader : apptrace.Reader
- Trace reader object.
- Returns
- -------
- list
- a list of header lines.
- """
- empty_count = 0
- lines = []
- while empty_count < 2:
- lines.append(reader.readline(linesep='\n'))
- if lines[-1] == ';\n':
- empty_count += 1
- return lines
- def _read_init_seq(reader):
- """
- Reads SystemView trace initial synchronisation sequence of bytes.
- Parameters
- ----------
- reader : apptrace.Reader
- Trace reader object.
- Raises
- -------
- SysViewTraceParseError
- If sync sequence is broken.
- """
- SYNC_SEQ_FMT = '<%dB' % SYSVIEW_SYNC_LEN
- sync_bytes = struct.unpack(SYNC_SEQ_FMT, reader.read(struct.calcsize(SYNC_SEQ_FMT)))
- for b in sync_bytes:
- if b != 0:
- raise SysViewTraceParseError('Invalid sync sequense!')
- def _decode_u32(reader):
- """
- Reads and decodes unsigned 32-bit integer.
- Parameters
- ----------
- reader : apptrace.Reader
- Trace reader object.
- Returns
- -------
- tuple
- a tuple containg number of read bytes and decoded value.
- """
- sz = 0
- val = 0
- while True:
- b, = struct.unpack('<B', reader.read(1))
- if b & 0x80:
- val |= (b & 0x7F) << (7 * sz)
- else:
- val |= b << (7 * sz)
- break
- sz += 1
- return (sz + 1,val)
- def _decode_id(reader):
- """
- Reads and decodes ID (task ID, queue handle, semaphore handle etc.).
- Parameters
- ----------
- reader : apptrace.Reader
- Trace reader object.
- Returns
- -------
- tuple
- a tuple containg number of read bytes and decoded value.
- """
- return _decode_u32(reader)
- def _decode_u64(reader):
- """
- Reads and decodes unsigned 64-bit integer.
- Parameters
- ----------
- reader : apptrace.Reader
- Trace reader object.
- Returns
- -------
- tuple
- a tuple containg number of read bytes and decoded value.
- """
- sz,val = _decode_u32(reader)
- sz2,high = _decode_u32(reader)
- sz += sz2
- return sz,(val | (high << 32))
- def _decode_str(reader):
- """
- Reads and decodes string.
- Parameters
- ----------
- reader : apptrace.Reader
- Trace reader object.
- Returns
- -------
- tuple
- a tuple containg number of read bytes and decoded value.
- """
- sz = 0
- val = ''
- sz, = struct.unpack('<B', reader.read(1))
- if sz == 0xFF:
- buf = struct.unpack('<2B', reader.read(2))
- sz = (buf[1] << 8) | buf[0]
- val, = struct.unpack('<%ds' % sz, reader.read(sz))
- val = val.decode('utf-8')
- if sz < 0xFF:
- return (sz + 1,val) # one extra byte for length
- return (sz + 3,val) # 3 extra bytes for length
- def _decode_plen(reader):
- """
- Reads and decodes event's payload length.
- Parameters
- ----------
- reader : apptrace.Reader
- Trace reader object.
- Returns
- -------
- int
- decoded value.
- """
- plen = 0
- b0, = struct.unpack('<B', reader.read(1))
- if b0 & 0x80:
- b1, = struct.unpack('<B', reader.read(1))
- plen = b1 # higher part
- plen = (plen << 7) | (b0 & ~0x80) # lower 7 bits
- else:
- plen = b0
- return plen
- class SysViewTraceParseError(apptrace.ParseError):
- """
- SystemView parse error exception.
- """
- pass
- class SysViewEvent(apptrace.TraceEvent):
- """
- Generic SystemView event class. This is a base class for all events.
- """
- def __init__(self, evt_id, core_id, reader, events_fmt_map=None):
- """
- Constructor. Reads and optionally decodes event.
- Parameters
- ----------
- evt_id : int
- Event ID.
- reader : apptrace.Reader
- Trace reader object.
- core_id : int
- Core ID event has been generated on.
- events_fmt_map : dict
- see return value of _read_events_map()
- """
- apptrace.TraceEvent.__init__(self, 'SysViewEvent', core_id, evt_id)
- self.plen = 0
- if self.id >= SYSVIEW_EVENT_ID_PREDEF_LEN_MAX:
- self.plen = _decode_plen(reader)
- if events_fmt_map:
- self._read_payload(reader, events_fmt_map)
- else:
- reader.forward(self.plen)
- _,self.ts = _decode_u32(reader)
- def _read_payload(self, reader, events_fmt_map):
- """
- Reads event's payload and populates its parameters dictionary.
- Parameters
- ----------
- reader : apptrace.Reader
- Trace reader object.
- events_fmt_map : dict
- see return value of _read_events_map()
- Raises
- -------
- SysViewTraceParseError
- if event has unknown or invalid format.
- """
- if self.id not in events_fmt_map:
- raise SysViewTraceParseError('Unknown event ID %d!' % self.id)
- self.name = events_fmt_map[self.id][0]
- evt_params_templates = events_fmt_map[self.id][1]
- params_len = 0
- for i in range(len(evt_params_templates)):
- event_param = copy.deepcopy(evt_params_templates[i])
- try:
- cur_pos = reader.get_pos()
- sz,param_val = event_param.decode(reader, self.plen - params_len)
- except Exception as e:
- raise SysViewTraceParseError('Failed to decode event {}({:d}) {:d} param @ 0x{:x}! {}'.format(self.name, self.id, self.plen, cur_pos, e))
- event_param.idx = i
- event_param.value = param_val
- self.params[event_param.name] = event_param
- params_len += sz
- if self.id >= SYSVIEW_EVENT_ID_PREDEF_LEN_MAX and self.plen != params_len:
- raise SysViewTraceParseError('Invalid event {}({:d}) payload len {:d}! Must be {:d}.'.format(self.name, self.id, self.plen, params_len))
- def __str__(self):
- params = ''
- for param in sorted(self.params.values(), key=lambda x: x.idx):
- params += '{}, '.format(param)
- if len(params):
- params = params[:-2] # remove trailing ', '
- return '{:.9f} - core[{:d}].{}({:d}), plen {:d}: [{}]'.format(self.ts, self.core_id, self.name, self.id, self.plen, params)
- class SysViewEventParam:
- """
- Abstract base SystemView event's parameter class. This is a base class for all event's parameters.
- """
- def __init__(self, name, decode_func):
- """
- Constructor.
- Parameters
- ----------
- name : string
- Event parameter name.
- decode_func : callable object
- Parameter decoding function.
- """
- self.name = name
- self.decode_func = decode_func
- self.value = None
- # positional index, used for sorting parameters before printing to make them looking as they appear in the event
- self.idx = 0
- def decode(self, reader, max_sz):
- """
- Reads and decodes events parameter.
- Parameters
- ----------
- reader : apptrace.Reader
- Trace reader object.
- max_sz : int
- Maximum number of bytes to read.
- Returns
- -------
- tuple
- a tuple containg number of read bytes and decoded value.
- """
- pass
- def __str__(self):
- return '{}: {}'.format(self.name, self.value)
- def to_jsonable(self):
- return {self.name: self.value}
- class SysViewEventParamSimple(SysViewEventParam):
- """
- Simple SystemView event's parameter class.
- """
- def decode(self, reader, max_sz):
- """
- see SysViewEventParam.decode()
- """
- return self.decode_func(reader)
- class SysViewEventParamArray(SysViewEventParamSimple):
- """
- Array SystemView event's parameter class.
- """
- def __init__(self, name, decode_func, size=-1):
- """
- Constructor.
- Parameters
- ----------
- name : string
- see SysViewEventParam.__init__()
- decode_func : callable object
- see SysViewEventParam.__init__()
- size : int
- Array's size. If -1 decode() will try to read all bytes from reader.
- """
- SysViewEventParamSimple.__init__(self, name, decode_func)
- self.arr_size = size
- def decode(self, reader, max_sz):
- """
- see SysViewEventParam.decode()
- """
- tottal_sz = 0
- vals = []
- i = 0
- while tottal_sz < max_sz:
- sz,val = self.decode_func(reader)
- vals.append(val)
- tottal_sz += sz
- i += 1
- if self.arr_size != -1 and i == self.arr_size:
- break
- return tottal_sz,vals
- class SysViewPredefinedEvent(SysViewEvent):
- """
- Pre-defined SystemView events class.
- """
- _predef_events_fmt = {
- SYSVIEW_EVTID_NOP: ('svNop', []),
- SYSVIEW_EVTID_OVERFLOW: ('svOverflow', [SysViewEventParamSimple('drop_cnt', _decode_u32)]),
- SYSVIEW_EVTID_ISR_ENTER: ('svIsrEnter', [SysViewEventParamSimple('irq_num', _decode_u32)]),
- SYSVIEW_EVTID_ISR_EXIT: ('svIsrExit', []),
- SYSVIEW_EVTID_TASK_START_EXEC: ('svTaskStartExec', [SysViewEventParamSimple('tid', _decode_id)]),
- SYSVIEW_EVTID_TASK_STOP_EXEC: ('svTaskStopExec', []),
- SYSVIEW_EVTID_TASK_START_READY: ('svTaskStartReady', [SysViewEventParamSimple('tid', _decode_id)]),
- SYSVIEW_EVTID_TASK_STOP_READY: ('svTaskStopReady', [SysViewEventParamSimple('tid', _decode_id),
- SysViewEventParamSimple('cause', _decode_u32)]),
- SYSVIEW_EVTID_TASK_CREATE: ('svTaskCreate', [SysViewEventParamSimple('tid', _decode_id)]),
- SYSVIEW_EVTID_TASK_INFO: ('svTaskInfo', [SysViewEventParamSimple('tid', _decode_id),
- SysViewEventParamSimple('prio', _decode_u32),
- SysViewEventParamSimple('name', _decode_str)]),
- SYSVIEW_EVTID_TRACE_START: ('svTraceStart', []),
- SYSVIEW_EVTID_TRACE_STOP: ('svTraceStop', []),
- SYSVIEW_EVTID_SYSTIME_CYCLES: ('svSysTimeCycles', [SysViewEventParamSimple('cycles', _decode_u32)]),
- SYSVIEW_EVTID_SYSTIME_US: ('svSysTimeUs', [SysViewEventParamSimple('time', _decode_u64)]),
- SYSVIEW_EVTID_SYSDESC: ('svSysDesc', [SysViewEventParamSimple('desc', _decode_str)]),
- SYSVIEW_EVTID_MARK_START: ('svUserStart', [SysViewEventParamSimple('user_id', _decode_u32)]),
- SYSVIEW_EVTID_MARK_STOP: ('svUserStop', [SysViewEventParamSimple('user_id', _decode_u32)]),
- SYSVIEW_EVTID_IDLE: ('svIdle', []),
- SYSVIEW_EVTID_ISR_TO_SCHEDULER: ('svExitIsrToScheduler', []),
- SYSVIEW_EVTID_TIMER_ENTER: ('svTimerEnter', [SysViewEventParamSimple('tim_id', _decode_u32)]),
- SYSVIEW_EVTID_TIMER_EXIT: ('svTimerExit', []),
- SYSVIEW_EVTID_STACK_INFO: ('svStackInfo', [SysViewEventParamSimple('tid', _decode_id),
- SysViewEventParamSimple('base', _decode_u32),
- SysViewEventParamSimple('sz', _decode_u32),
- SysViewEventParamSimple('unused', _decode_u32)]),
- SYSVIEW_EVTID_MODULEDESC: ('svModuleDesc', [SysViewEventParamSimple('mod_id', _decode_u32),
- SysViewEventParamSimple('evt_off', _decode_u32),
- SysViewEventParamSimple('desc', _decode_str)]),
- SYSVIEW_EVTID_INIT: ('svInit', [SysViewEventParamSimple('sys_freq', _decode_u32),
- SysViewEventParamSimple('cpu_freq', _decode_u32),
- SysViewEventParamSimple('ram_base', _decode_u32),
- SysViewEventParamSimple('id_shift', _decode_u32)]),
- SYSVIEW_EVTID_NAME_RESOURCE: ('svNameResource', [SysViewEventParamSimple('res_id', _decode_u32),
- SysViewEventParamSimple('name', _decode_str)]),
- SYSVIEW_EVTID_PRINT_FORMATTED: ('svPrint', [SysViewEventParamSimple('msg', _decode_str),
- SysViewEventParamSimple('lvl', _decode_u32),
- SysViewEventParamSimple('unused', _decode_u32)]),
- SYSVIEW_EVTID_NUMMODULES: ('svNumModules', [SysViewEventParamSimple('mod_cnt', _decode_u32)]),
- }
- def __init__(self, evt_id, core_id, reader):
- """
- see SysViewEvent.__init__()
- """
- SysViewEvent.__init__(self, evt_id, core_id, reader, self._predef_events_fmt)
- # self.name = 'SysViewPredefinedEvent'
- class SysViewOSEvent(SysViewEvent):
- """
- OS related SystemView events class.
- """
- def __init__(self, evt_id, core_id, reader, events_fmt_map):
- """
- see SysViewEvent.__init__()
- """
- SysViewEvent.__init__(self, evt_id, core_id, reader, events_fmt_map)
- # self.name = 'SysViewOSEvent'
- class SysViewHeapEvent(SysViewEvent):
- """
- Heap related SystemView events class.
- Attributes
- ----------
- events_fmt : dict
- see return value of _read_events_map()
- """
- events_fmt = {
- 0: ('esp_sysview_heap_trace_alloc', [SysViewEventParamSimple('addr', _decode_u32),
- SysViewEventParamSimple('size', _decode_u32),
- SysViewEventParamArray('callers', _decode_u32)]),
- 1: ('esp_sysview_heap_trace_free', [SysViewEventParamSimple('addr', _decode_u32),
- SysViewEventParamArray('callers', _decode_u32)]),
- }
- def __init__(self, evt_id, core_id, events_off, reader):
- """
- Constructor. Reads and optionally decodes event.
- Parameters
- ----------
- evt_id : int
- see SysViewEvent.__init__()
- events_off : int
- Offset for heap events IDs. Greater or equal to SYSVIEW_MODULE_EVENT_OFFSET.
- reader : apptrace.Reader
- see SysViewEvent.__init__()
- core_id : int
- see SysViewEvent.__init__()
- """
- cur_events_map = {}
- for id in self.events_fmt:
- cur_events_map[events_off + id] = self.events_fmt[id]
- SysViewEvent.__init__(self, evt_id, core_id, reader, cur_events_map)
- # self.name = 'SysViewHeapEvent'
- class SysViewTraceDataParser(apptrace.TraceDataProcessor):
- """
- Base SystemView trace data parser class.
- Attributes
- ----------
- STREAMID_SYS : int
- system events stream ID. Reserved for internal uses.
- STREAMID_LOG : int
- log events stream ID.
- STREAMID_HEAP : int
- heap events stream ID.
- """
- STREAMID_SYS = -1
- STREAMID_LOG = 0
- STREAMID_HEAP = 1
- def __init__(self, print_events=False, core_id=0):
- """
- Constructor.
- Parameters
- ----------
- print_events : bool
- see apptrace.TraceDataProcessor.__init__()
- core_id : int
- id of the core this parser object relates to.
- """
- apptrace.TraceDataProcessor.__init__(self, print_events=print_events, keep_all_events=True)
- self.sys_info = None
- self._last_ts = 0
- self.irqs_info = {}
- self.tasks_info = {}
- self.core_id = core_id
- self.esp_ext = False
- def _parse_irq_desc(self, desc):
- """
- Parses IRQ description.
- Parameters
- ----------
- desc : string
- IRQ description string.
- Returns
- -------
- tuple
- a tuple with IRQ number and name or None on error.
- """
- m = re.match('I#([0-9]+)=(.+)', desc)
- if m:
- return m.group(2),m.group(1)
- return None
- def _update_ts(self, ts):
- """
- Calculates real event timestamp.
- Parameters
- ----------
- ts : int
- Event timestamp offset.
- Returns
- -------
- float
- real event timestamp.
- """
- self._last_ts += ts
- return float(self._last_ts) / self.sys_info.params['sys_freq'].value
- def read_extension_event(self, evt_id, core_id, reader):
- """
- Reads extension event.
- Default implementation which just reads out event.
- Parameters
- ----------
- evt_id : int
- Event ID.
- reader : apptrace.Reader
- Trace reader object.
- Returns
- -------
- SysViewEvent
- if this is top level parser returns object for generic event,
- otherwise returns None indicating to the calling top level parser
- that extension event are not supported.
- """
- if self.root_proc == self:
- # by default just read out and skip unknown event
- return SysViewEvent(evt_id, core_id, reader)
- return None # let decide to root parser
- @staticmethod
- def _decode_core_id(high_b):
- if high_b & (1 << 6):
- core_id = 1
- high_b &= ~(1 << 6)
- else:
- core_id = 0
- return high_b,core_id
- def read_event(self, reader, os_evt_map):
- """
- Reads pre-defined or OS-related event.
- Parameters
- ----------
- reader : apptrace.Reader
- Trace reader object.
- os_evt_map : dict
- see return value of _read_events_map()
- Returns
- -------
- SysViewEvent
- pre-defined, OS-related or extension event object.
- """
- evt_hdr, = struct.unpack('<B', reader.read(1))
- # read ID and core num
- evt_id = 0
- if evt_hdr & 0x80:
- # evt_id (2 bytes)
- b, = struct.unpack('<B', reader.read(1))
- # higher part
- if self.esp_ext:
- evt_id,core_id = self._decode_core_id(b)
- else:
- evt_id = b
- core_id = self.core_id
- evt_id = (evt_id << 7) | (evt_hdr & ~0x80) # lower 7 bits
- else:
- # evt_id (1 byte)
- if self.esp_ext:
- evt_id,core_id = self._decode_core_id(evt_hdr)
- else:
- evt_id = evt_hdr
- core_id = self.core_id
- if evt_id <= SYSVIEW_EVENT_ID_PREDEF_MAX:
- return SysViewPredefinedEvent(evt_id, core_id, reader)
- elif evt_id < SYSVIEW_MODULE_EVENT_OFFSET:
- return SysViewOSEvent(evt_id, core_id, reader, os_evt_map)
- else:
- return self.read_extension_event(evt_id, core_id, reader)
- def event_supported(self, event):
- return False
- def on_new_event(self, event):
- """
- Does essential processing of event. Must be called for every read event.
- Assigns real timestamp to event. Updates global system info: system description,
- mapping of tasks IDs to names and IRQ names to numbers.
- Parameters
- ----------
- event : SysViewEvent
- Event object.
- """
- if event.id == SYSVIEW_EVTID_TRACE_START:
- event.ts = 0
- self._last_ts = 0
- elif self.sys_info:
- event.ts = self._update_ts(event.ts)
- if event.id == SYSVIEW_EVTID_INIT:
- self.sys_info = event
- event.ts = self._update_ts(event.ts)
- elif event.id == SYSVIEW_EVTID_TASK_INFO:
- self.tasks_info[event.params['tid'].value] = event.params['name'].value
- elif event.id == SYSVIEW_EVTID_SYSDESC:
- irq = self._parse_irq_desc(event.params['desc'].value)
- if irq:
- irq_num = int(irq[1])
- self.irqs_info[irq_num] = irq[0]
- # count event and save it to the list
- apptrace.TraceDataProcessor.on_new_event(self, event)
- class SysViewTraceDataExtEventParser(SysViewTraceDataParser):
- def __init__(self, events_num, print_events=False, core_id=0):
- """
- Constructor.
- Parameters
- ----------
- print_events : bool
- see apptrace.TraceDataProcessor.__init__()
- core_id : int
- id of the core this parser object relates to.
- """
- SysViewTraceDataParser.__init__(self, core_id=core_id, print_events=print_events)
- self.events_off = 0
- self.events_num = events_num
- def event_supported(self, event):
- return False if (self.events_off < SYSVIEW_MODULE_EVENT_OFFSET or event.id < self.events_off or
- event.id >= (self.events_off + self.events_num)) else True
- class SysViewMultiTraceDataParser(SysViewTraceDataParser):
- """
- SystemView trace data parser supporting multiple event streams.
- """
- def __init__(self, print_events=False, core_id=0):
- """
- see SysViewTraceDataParser.__init__()
- """
- SysViewTraceDataParser.__init__(self, print_events, core_id)
- self.stream_parsers = {}
- def add_stream_parser(self, stream_id, parser):
- """
- Assigns parser for events stream.
- Parameters
- ----------
- stream_id : int
- stream ID. See SysViewTraceDataParser.STREAMID_xxx.
- Parsers for SysViewTraceDataParser.STREAMID_SYS are ignored.
- Top level parser is the default for SysViewTraceDataParser.STREAMID_SYS.
- parser : SysViewTraceDataParser
- parser object.
- """
- if stream_id == SysViewTraceDataParser.STREAMID_SYS:
- return
- parser.root_proc = self
- self.stream_parsers[stream_id] = parser
- def read_extension_event(self, evt_id, core_id, reader):
- """
- Reads extension event.
- Iterates over registered stream parsers trying to find one which supports that type of event.
- Parameters
- ----------
- evt_id : int
- see SysViewTraceDataParser.read_extension_event()
- reader : apptrace.Reader
- see SysViewTraceDataParser.read_extension_event()
- Returns
- -------
- SysViewEvent
- object for extension event, if extension event is not supported return SysViewEvent instance.
- """
- for stream_id in self.stream_parsers:
- evt = self.stream_parsers[stream_id].read_extension_event(evt_id, core_id, reader)
- if evt:
- return evt
- return SysViewTraceDataParser.read_extension_event(self, evt_id, core_id, reader)
- def on_new_event(self, event):
- """
- Iterates over registered stream parsers allowing them to do
- essential processing of event. Must be called for every read event.
- Parameters
- ----------
- event : SysViewEvent
- Event object.
- """
- SysViewTraceDataParser.on_new_event(self, event)
- for stream_id in self.stream_parsers:
- self.stream_parsers[stream_id].on_new_event(event)
- class SysViewEventContext():
- """
- SystemView event context.
- """
- def __init__(self, handle, irq, name=''):
- """
- Constructor.
- Parameters
- ----------
- handle : int
- handle of the context: task ID or IRQ number.
- irq : bool
- flag indicating whether this is IRQ or task context.
- name : string
- name of the context: task or IRQ name. Empty if context is unknown.
- """
- self.handle = handle
- self.irq = irq
- self.name = name
- class SysViewTraceDataProcessor(apptrace.TraceDataProcessor):
- """
- Base SystemView trace data processor class.
- """
- def __init__(self, traces, root_proc=None, print_events=False, keep_all_events=False):
- """
- Constructor.
- Parameters
- ----------
- traces : list
- list of parsers to process data from.
- print_events : bool
- see apptrace.TraceDataProcessor.__init__()
- keep_all_events : bool
- see apptrace.TraceDataProcessor.__init__()
- """
- apptrace.TraceDataProcessor.__init__(self, print_events, keep_all_events)
- self.event_ids = {}
- self.name = ''
- self.root_proc = root_proc if root_proc else self
- self.traces = {}
- self.ctx_stack = {}
- self.prev_ctx = {}
- self.no_ctx_events = []
- for t in traces:
- self.traces[t.core_id] = t
- # current context item is a tuple of task ID or IRQ num and 'in_irq' flag
- # empty list means IDLE context or self.start_ctx
- self.ctx_stack[t.core_id] = []
- # context is undefined, we do not know have we started the tracing in task/IDLE or IRQ context
- # in general there are three scenarious when we can start tracing: when core is in task, IDLE task or IRQ context
- self.prev_ctx[t.core_id] = None
- def _get_curr_context(self, core_id):
- """
- Returns current context.
- Parameters
- ----------
- core_id : int
- core ID for requested context.
- Returns
- -------
- SysViewEventContext
- context object
- None
- if there current is undefined
- """
- if len(self.root_proc.ctx_stack[core_id]):
- return self.root_proc.ctx_stack[core_id][-1]
- if self._get_prev_context(core_id):
- return SysViewEventContext(None, False, 'IDLE%d' % core_id)
- return None
- def _get_prev_context(self, core_id):
- """
- Returns current context.
- Parameters
- ----------
- core_id : int
- core ID for requested context.
- Returns
- -------
- SysViewEventContext
- context object
- """
- return self.root_proc.prev_ctx[core_id]
- def get_trace_stream(self, core_id, stream_id):
- """
- Retrieves parser for specified stream and core.
- Parameters
- ----------
- core_id : int
- Parser's core ID.
- stream_id : int
- Parser's stream ID.
- Returns
- -------
- SysViewTraceDataParser
- parser object for specified stream and core
- """
- if self.root_proc == self:
- return self.traces[core_id]
- return self.root_proc.get_trace_stream(core_id, stream_id)
- def event_supported(self, e):
- """
- Should be overriden in child class.
- """
- return False
- def handle_event(self, e):
- """
- Should be overriden in child class.
- """
- pass
- def print_report(self):
- """
- see apptrace.TraceDataProcessor.print_report()
- """
- apptrace.TraceDataProcessor.print_report(self)
- def _process_event(self, event):
- """
- Processes event.
- Keeps track of execution context on every core.
- Parameters
- ----------
- event : SysViewEvent
- Event object.
- Raises
- ----------
- SysViewTraceParseError
- if there is no parser for event's core or
- if SYSVIEW_EVTID_ISR_ENTER is received for unknown IRQ or
- if SYSVIEW_EVTID_TASK_START_EXEC or SYSVIEW_EVTID_TASK_STOP_READY is received for unknown task.
- """
- if event.core_id not in self.traces:
- if 0 in self.traces and self.traces[0].esp_ext:
- # for Espressif extension there is one trace for all cores
- trace = self.traces[0]
- if event.core_id not in self.ctx_stack:
- self.ctx_stack[event.core_id] = []
- if event.core_id not in self.prev_ctx:
- self.prev_ctx[event.core_id] = None
- else:
- raise SysViewTraceParseError('Event for unknown core %d' % event.core_id)
- else:
- trace = self.traces[event.core_id]
- if event.id == SYSVIEW_EVTID_ISR_ENTER:
- if event.params['irq_num'].value not in trace.irqs_info:
- raise SysViewTraceParseError('Enter unknown ISR %d' % event.params['irq_num'].value)
- if len(self.ctx_stack[event.core_id]):
- self.prev_ctx[event.core_id] = self.ctx_stack[event.core_id][-1]
- else:
- # the 1st context switching event after trace start is SYSVIEW_EVTID_ISR_ENTER, so we have been in IDLE context
- self.prev_ctx[event.core_id] = SysViewEventContext(None, False, 'IDLE%d' % event.core_id)
- # put new ISR context on top of the stack (the last in the list)
- self.ctx_stack[event.core_id].append(SysViewEventContext(event.params['irq_num'].value, True, trace.irqs_info[event.params['irq_num'].value]))
- elif event.id == SYSVIEW_EVTID_ISR_EXIT or event.id == SYSVIEW_EVTID_ISR_TO_SCHEDULER:
- if len(self.ctx_stack[event.core_id]):
- # return to the previous context (the last in the list)
- self.prev_ctx[event.core_id] = self.ctx_stack[event.core_id].pop()
- else:
- # the 1st context switching event after trace start is SYSVIEW_EVTID_ISR_EXIT, so we have been in ISR context,
- # but we do not know which one because SYSVIEW_EVTID_ISR_EXIT do not include the IRQ number
- self.prev_ctx[event.core_id] = SysViewEventContext(None, True, 'IRQ_oncore%d' % event.core_id)
- elif event.id == SYSVIEW_EVTID_TASK_START_EXEC:
- if event.params['tid'].value not in trace.tasks_info:
- raise SysViewTraceParseError('Start exec unknown task 0x%x' % event.params['tid'].value)
- if len(self.ctx_stack[event.core_id]):
- # return to the previous context (the last in the list)
- self.prev_ctx[event.core_id] = self.ctx_stack[event.core_id][-1]
- else:
- # the 1st context switching event after trace start is SYSVIEW_EVTID_TASK_START_EXEC, so we have been in IDLE context
- self.prev_ctx[event.core_id] = SysViewEventContext(None, False, 'IDLE%d' % event.core_id)
- # only one task at a time in context stack (can be interrupted by a bunch of ISRs)
- self.ctx_stack[event.core_id] = [SysViewEventContext(event.params['tid'].value, False, trace.tasks_info[event.params['tid'].value])]
- elif event.id == SYSVIEW_EVTID_TASK_STOP_EXEC:
- # delete task from context stack
- for ctx in self.ctx_stack[event.core_id]:
- if not ctx.irq:
- if len(self.ctx_stack[event.core_id]) == 1:
- # if this is the only ctx in context stack
- self.prev_ctx[event.core_id] = ctx
- del ctx
- break
- elif event.id == SYSVIEW_EVTID_TASK_STOP_READY:
- if event.params['tid'].value not in trace.tasks_info:
- raise SysViewTraceParseError('Stop ready unknown task 0x%x' % event.params['tid'].value)
- if len(self.ctx_stack[event.core_id]):
- if (not self.ctx_stack[event.core_id][-1].irq and event.params['tid'].value == self.ctx_stack[event.core_id][-1].handle):
- # return to the previous context (the last in the list)
- self.prev_ctx[event.core_id] = self.ctx_stack[event.core_id].pop()
- else:
- # the 1st context switching event after trace start is SYSVIEW_EVTID_TASK_STOP_READY, so we have been in task context
- self.prev_ctx[event.core_id] = SysViewEventContext(event.params['tid'].value, False, trace.tasks_info[event.params['tid'].value])
- def on_new_event(self, event):
- """
- Processes heap events.
- """
- if self.root_proc == self:
- SysViewTraceDataProcessor._process_event(self, event)
- curr_ctx = self._get_curr_context(event.core_id)
- if not curr_ctx:
- # postpone events handling till their context is known
- self.no_ctx_events.append(event)
- return
- event.in_irq = curr_ctx.irq
- event.ctx_name = curr_ctx.name
- # here we know the previous context: we switched from it or implied upon the 1st context switching event
- prev_ctx = self._get_prev_context(event.core_id)
- if len(self.no_ctx_events):
- for cached_evt in self.no_ctx_events:
- cached_evt.ctx_name = prev_ctx.name
- cached_evt.in_irq = prev_ctx.irq
- # count and save the event
- apptrace.TraceDataProcessor.on_new_event(self, cached_evt)
- if self.event_supported(event):
- self.handle_event(event)
- del self.no_ctx_events[:]
- # count and save the event
- apptrace.TraceDataProcessor.on_new_event(self, event)
- if self.event_supported(event):
- self.handle_event(event)
- def merge_and_process(self):
- """
- Merges events from all registered parsers, sorts them by timestamp and processes them.
- """
- all_events = []
- for t in self.traces.values():
- all_events.extend(t.events)
- all_events.sort(key=lambda x: x.ts)
- for event in all_events:
- self.on_new_event(event)
- class SysViewMultiStreamTraceDataProcessor(SysViewTraceDataProcessor):
- """
- SystemView trace data processor supporting multiple event streams.
- """
- def __init__(self, traces, print_events=False, keep_all_events=False):
- """
- see SysViewTraceDataProcessor.__init__()
- """
- SysViewTraceDataProcessor.__init__(self, traces, print_events=print_events, keep_all_events=keep_all_events)
- self.stream_procs = {}
- def add_stream_processor(self, stream_id, proc):
- """
- Assigns processor for events stream.
- Parameters
- ----------
- stream_id : int
- stream ID. See SysViewTraceDataParser.STREAMID_xxx.
- Parsers for SysViewTraceDataParser.STREAMID_SYS are ignored.
- Top level parser is the default for SysViewTraceDataParser.STREAMID_SYS.
- proc : SysViewTraceDataProcessor
- processor object.
- """
- if stream_id == SysViewTraceDataParser.STREAMID_SYS:
- return
- proc.root_proc = self # common processing data is kept by this processor
- self.stream_procs[stream_id] = proc
- def get_trace_stream(self, core_id, stream_id):
- """
- Retrieves parser for specified stream and core.
- Parameters
- ----------
- core_id : int
- Parser's core ID.
- stream_id : int
- Parser's stream ID.
- Returns
- -------
- SysViewTraceDataParser
- parser object for specified stream and core
- """
- if core_id not in self.traces and 0 in self.traces and self.traces[0].esp_ext:
- # for Espressif extension there is one trace for all cores
- trace = self.traces[0]
- else:
- trace = self.traces[core_id]
- if stream_id == SysViewTraceDataParser.STREAMID_SYS:
- return trace
- if isinstance(trace, SysViewMultiTraceDataParser):
- return trace.stream_parsers[stream_id]
- return trace
- def print_report(self):
- """
- Iterates over registered stream processors and prints their reports.
- """
- SysViewTraceDataProcessor.print_report(self)
- # need to sort stream procs by keys to print reports in the same order regardless of Python version
- stream_ids = list(self.stream_procs.keys())
- stream_ids.sort()
- for stream_id in stream_ids:
- self.stream_procs[stream_id].print_report()
- def cleanup(self):
- """
- Iterates over registered stream processors and cleans them up.
- """
- for stream_id in self.stream_procs:
- self.stream_procs[stream_id].cleanup()
- SysViewTraceDataProcessor.cleanup(self)
- def on_new_event(self, event):
- """
- Iterates over registered stream processors allowing them to do
- the processing of event.
- Parameters
- ----------
- event : SysViewEvent
- Event object.
- """
- SysViewTraceDataProcessor.on_new_event(self, event)
- for stream_id in self.stream_procs:
- self.stream_procs[stream_id].on_new_event(event)
- class SysViewTraceDataJsonEncoder(json.JSONEncoder):
- JSON_TRACE_VER = '1.0'
- def default(self, obj):
- global _sysview_events_map
- global _os_events_map
- if isinstance(obj, SysViewMultiStreamTraceDataProcessor):
- json_event_ids = {'system': _sysview_events_map, 'os': {}}
- for eid in _os_events_map:
- ename = _os_events_map[eid][0]
- json_event_ids['os'][ename] = eid
- for stream in obj.stream_procs.values():
- json_event_ids[stream.name] = stream.event_ids
- json_events = []
- for e in obj.events:
- for stream in obj.stream_procs.values():
- if stream.event_supported(e):
- json_events.append(e)
- break
- # include also OS and pre-defined events
- if isinstance(e, SysViewPredefinedEvent) or isinstance(e, SysViewOSEvent):
- json_events.append(e)
- return {'version': self.JSON_TRACE_VER, 'streams': json_event_ids, 'events': json_events}
- if isinstance(obj, SysViewHeapEvent):
- blk_size = 0
- if 'size' in obj.params:
- blk_size = obj.params['size'].value
- blk_addr = '0x{:x}'.format(obj.params['addr'].value)
- callers = []
- for addr in obj.params['callers'].value:
- callers.append('0x{:x}'.format(addr))
- return {'ctx_name': obj.ctx_name, 'in_irq': obj.in_irq, 'id': obj.id, 'core_id': obj.core_id,
- 'ts': obj.ts, 'addr': blk_addr, 'size': blk_size, 'callers': callers}
- if isinstance(obj, SysViewPredefinedEvent) and obj.id == SYSVIEW_EVTID_PRINT_FORMATTED:
- return {'ctx_name': obj.ctx_name, 'in_irq': obj.in_irq, 'id': obj.id, 'core_id': obj.core_id,
- 'ts': obj.ts, 'msg': obj.params['msg'].value, 'lvl': obj.params['lvl'].value}
- if isinstance(obj, SysViewEvent):
- jobj = obj.to_jsonable()
- # remove unused fields
- if 'name' in jobj:
- del jobj['name']
- if 'plen' in jobj:
- del jobj['plen']
- return jobj
- # Let the base class default method raise the TypeError
- return json.JSONEncoder.default(self, obj)
- class SysViewHeapTraceDataParser(SysViewTraceDataExtEventParser):
- """
- SystemView trace data parser supporting heap events.
- """
- def __init__(self, print_events=False, core_id=0):
- """
- SystemView trace data parser supporting multiple event streams.
- see SysViewTraceDataExtEventParser.__init__()
- """
- SysViewTraceDataExtEventParser.__init__(self, events_num=len(SysViewHeapEvent.events_fmt.keys()), core_id=core_id, print_events=print_events)
- def read_extension_event(self, evt_id, core_id, reader):
- """
- Reads heap event.
- see SysViewTraceDataParser.read_extension_event()
- """
- if (self.events_off >= SYSVIEW_MODULE_EVENT_OFFSET and evt_id >= self.events_off and
- evt_id < self.events_off + self.events_num):
- return SysViewHeapEvent(evt_id, core_id, self.events_off, reader)
- return SysViewTraceDataParser.read_extension_event(self, evt_id, core_id, reader)
- def on_new_event(self, event):
- """
- Keeps track of heap module descriptions.
- """
- if self.root_proc == self:
- SysViewTraceDataParser.on_new_event(self, event)
- if event.id == SYSVIEW_EVTID_MODULEDESC and event.params['desc'].value == 'ESP32 SystemView Heap Tracing Module':
- self.events_off = event.params['evt_off'].value
- class SysViewHeapTraceDataProcessor(SysViewTraceDataProcessor, apptrace.BaseHeapTraceDataProcessorImpl):
- """
- SystemView trace data processor supporting heap events.
- """
- def __init__(self, toolchain_pref, elf_path, root_proc=None, traces=[], print_events=False, print_heap_events=False):
- """
- Constructor.
- see SysViewTraceDataProcessor.__init__()
- see apptrace.BaseHeapTraceDataProcessorImpl.__init__()
- """
- SysViewTraceDataProcessor.__init__(self, traces, root_proc=root_proc, print_events=print_events)
- apptrace.BaseHeapTraceDataProcessorImpl.__init__(self, print_heap_events)
- self.toolchain = toolchain_pref
- self.elf_path = elf_path
- # self.no_ctx_events = []
- self.name = 'heap'
- stream = self.root_proc.get_trace_stream(0, SysViewTraceDataParser.STREAMID_HEAP)
- self.event_ids = {'alloc': stream.events_off, 'free': stream.events_off + 1}
- def event_supported(self, event):
- heap_stream = self.root_proc.get_trace_stream(event.core_id, SysViewTraceDataParser.STREAMID_HEAP)
- return heap_stream.event_supported(event)
- def handle_event(self, event):
- heap_stream = self.root_proc.get_trace_stream(event.core_id, SysViewTraceDataParser.STREAMID_HEAP)
- if (event.id - heap_stream.events_off) == 0:
- heap_event = apptrace.HeapTraceEvent(event, True, toolchain=self.toolchain,
- elf_path=self.elf_path)
- else:
- heap_event = apptrace.HeapTraceEvent(event, False, toolchain=self.toolchain,
- elf_path=self.elf_path)
- apptrace.BaseHeapTraceDataProcessorImpl.on_new_event(self, heap_event)
- def print_report(self):
- """
- see apptrace.TraceDataProcessor.print_report()
- """
- if self.root_proc == self:
- SysViewTraceDataProcessor.print_report(self)
- apptrace.BaseHeapTraceDataProcessorImpl.print_report(self)
- class SysViewLogTraceEvent(apptrace.LogTraceEvent):
- """
- SystemView log event.
- """
- def __init__(self, ts, msg):
- """
- Constructor.
- Parameters
- ----------
- msg : string
- Log message string.
- """
- self.msg = msg
- self.ts = ts
- def get_message(self, unused):
- """
- Retrieves log message.
- Returns
- -------
- string
- formatted log message
- """
- return '[{:.9f}] LOG: {}'.format(self.ts, self.msg)
- class SysViewLogTraceDataParser(SysViewTraceDataParser):
- """
- SystemView trace data parser supporting log events.
- """
- def event_supported(self, event):
- return event.id == SYSVIEW_EVTID_PRINT_FORMATTED
- def on_new_event(self, event):
- """
- see SysViewTraceDataParser.on_new_event()
- """
- if self.root_proc == self:
- SysViewTraceDataParser.on_new_event(self, event)
- class SysViewLogTraceDataProcessor(SysViewTraceDataProcessor, apptrace.BaseLogTraceDataProcessorImpl):
- """
- SystemView trace data processor supporting heap events.
- """
- def __init__(self, traces=[], root_proc=None, print_events=False, print_log_events=False):
- """
- Constructor.
- see SysViewTraceDataProcessor.__init__()
- see apptrace.BaseLogTraceDataProcessorImpl.__init__()
- """
- SysViewTraceDataProcessor.__init__(self, traces, root_proc=root_proc, print_events=print_events)
- apptrace.BaseLogTraceDataProcessorImpl.__init__(self, print_log_events)
- self.name = 'log'
- self.event_ids = {'print': SYSVIEW_EVTID_PRINT_FORMATTED}
- def event_supported(self, event):
- return event.id == SYSVIEW_EVTID_PRINT_FORMATTED
- def on_new_event(self, event):
- """
- Processes log events.
- """
- if self.root_proc == self:
- SysViewTraceDataProcessor.on_new_event(self, event)
- if event.id == SYSVIEW_EVTID_PRINT_FORMATTED:
- log_evt = SysViewLogTraceEvent(event.ts, event.params['msg'].value)
- apptrace.BaseLogTraceDataProcessorImpl.on_new_event(self, log_evt)
- def print_report(self):
- """
- see apptrace.TraceDataProcessor.print_report()
- """
- if self.root_proc == self:
- SysViewTraceDataProcessor.print_report(self)
- apptrace.BaseLogTraceDataProcessorImpl.print_report(self)
|