sysviewtrace_proc.py 6.1 KB

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