sysviewtrace_proc.py 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. #!/usr/bin/env python
  2. #
  3. # SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD
  4. # SPDX-License-Identifier: Apache-2.0
  5. #
  6. # This is python script to process various types trace data streams in SystemView format.
  7. # Trace data can be provided in multiple trace files (one per CPU). After processing phase
  8. # script prints report for every type of trace data stream which was found.
  9. #
  10. import argparse
  11. import json
  12. import logging
  13. import os.path
  14. import signal
  15. import sys
  16. import traceback
  17. import espytrace.apptrace as apptrace
  18. import espytrace.sysview as sysview
  19. def main():
  20. verbosity_levels = [
  21. logging.CRITICAL,
  22. logging.ERROR,
  23. logging.WARNING,
  24. logging.INFO,
  25. logging.DEBUG
  26. ]
  27. parser = argparse.ArgumentParser(description='ESP32 SEGGER SystemView Trace Parsing Tool')
  28. parser.add_argument('trace_sources', help='Trace data sources. Format: [file://]/path/to/file.', nargs='+', type=str)
  29. parser.add_argument('--elf-file', '-b', help='Path to program ELF file.', type=str, default='')
  30. parser.add_argument('--tmo', '-w', help='Data wait timeout in sec. -1: infinite, 0: no wait', type=int, default=0)
  31. parser.add_argument('--dump-events', '-d', help='Dump all events.', action='store_true')
  32. parser.add_argument('--print-events', '-p', help='Print events of selected types. By default only reports are printed', action='store_true')
  33. parser.add_argument('--include-events', '-i', help='Events types to be included into report.', type=str, choices=['heap', 'log', 'all'], default='all')
  34. parser.add_argument('--toolchain', '-t', help='Toolchain prefix.', type=str, default='xtensa-esp32-elf-')
  35. parser.add_argument('--events-map', '-e', help='Events map file.', type=str, default=os.path.join(os.path.dirname(__file__), 'SYSVIEW_FreeRTOS.txt'))
  36. parser.add_argument('--to-json', '-j', help='Print JSON.', action='store_true', default=False)
  37. parser.add_argument('--verbose', '-v', help='Verbosity level. Default 1', choices=range(0, len(verbosity_levels)), type=int, default=1)
  38. args = parser.parse_args()
  39. def sig_int_handler(signum, frame):
  40. reader.cleanup()
  41. signal.signal(signal.SIGINT, sig_int_handler)
  42. include_events = {'heap': False, 'log': False}
  43. if args.include_events == 'all':
  44. for k in include_events:
  45. include_events[k] = True
  46. elif args.include_events == 'heap':
  47. include_events['heap'] = True
  48. elif args.include_events == 'log':
  49. include_events['log'] = True
  50. logging.basicConfig(level=verbosity_levels[args.verbose], format='[%(levelname)s] %(message)s')
  51. # parse trace files
  52. parsers = []
  53. for i, trace_source in enumerate(args.trace_sources):
  54. try:
  55. parser = sysview.SysViewMultiTraceDataParser(print_events=False, core_id=i)
  56. if include_events['heap']:
  57. parser.add_stream_parser(sysview.SysViewTraceDataParser.STREAMID_HEAP,
  58. sysview.SysViewHeapTraceDataParser(print_events=False, core_id=i))
  59. if include_events['log']:
  60. parser.add_stream_parser(sysview.SysViewTraceDataParser.STREAMID_LOG,
  61. sysview.SysViewLogTraceDataParser(print_events=False, core_id=i))
  62. parsers.append(parser)
  63. except Exception as e:
  64. logging.error('Failed to create data parser (%s)!', e)
  65. traceback.print_exc()
  66. sys.exit(2)
  67. reader = apptrace.reader_create(trace_source, args.tmo)
  68. if not reader:
  69. logging.error('Failed to create trace reader!')
  70. sys.exit(2)
  71. try:
  72. # logging.info("Parse trace from '{}'...".format(trace_source))
  73. logging.info("Parse trace from '%s'...", trace_source)
  74. sysview.parse_trace(reader, parser, args.events_map)
  75. logging.info('Parsing completed.')
  76. except (apptrace.ReaderTimeoutError, apptrace.ReaderShutdownRequest) as e:
  77. logging.info('Stop parsing trace. (%s)', e)
  78. except Exception as e:
  79. logging.error('Failed to parse trace (%s)!', e)
  80. parser.cleanup()
  81. traceback.print_exc()
  82. sys.exit(2)
  83. finally:
  84. reader.cleanup()
  85. # merge and process traces
  86. try:
  87. proc = sysview.SysViewMultiStreamTraceDataProcessor(traces=parsers, print_events=args.dump_events, keep_all_events=True if args.to_json else False)
  88. if include_events['heap']:
  89. proc.add_stream_processor(sysview.SysViewTraceDataParser.STREAMID_HEAP,
  90. sysview.SysViewHeapTraceDataProcessor(args.toolchain, args.elf_file, root_proc=proc, print_heap_events=args.print_events))
  91. if include_events['log']:
  92. proc.add_stream_processor(sysview.SysViewTraceDataParser.STREAMID_LOG,
  93. sysview.SysViewLogTraceDataProcessor(root_proc=proc, print_log_events=args.print_events))
  94. except Exception as e:
  95. logging.error('Failed to create data processor (%s)!', e)
  96. traceback.print_exc()
  97. sys.exit(2)
  98. try:
  99. logging.info("Process events from '%s'...", args.trace_sources)
  100. proc.merge_and_process()
  101. logging.info('Processing completed.')
  102. except Exception as e:
  103. logging.error('Failed to process trace (%s)!', e)
  104. traceback.print_exc()
  105. sys.exit(2)
  106. finally:
  107. if args.to_json:
  108. print(json.dumps(proc, cls=sysview.SysViewTraceDataJsonEncoder, indent=4, separators=(',', ': '), sort_keys=True))
  109. else:
  110. proc.print_report()
  111. proc.cleanup()
  112. if __name__ == '__main__':
  113. main()