# Copyright 2021 The Chromium Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. """This script provides the necessary flags to symbolize proto traces. """ import logging import optparse import os import sys sys.path.insert( 0, os.path.join(os.path.dirname(__file__), os.pardir, os.pardir, 'third_party', 'catapult', 'systrace')) from systrace import util TRACING_LOGGER_NAME = 'chromium:tools/tracing' def GeneralOptions(parser): """Build option group for general options. Args: parser: OptionParser object for parsing the command-line. Returns: Option group that contains general options. """ general_options = optparse.OptionGroup(parser, 'General Options') general_options.add_option('-o', '--output', help=('Save trace output to file. ' 'Defaults to trace_file + ' '"_symbolized_trace."'), dest='output_file') general_options.add_option('-v', '--verbose', help='Increase output verbosity.', action='count', dest='verbosity', default=0) general_options.add_option('--view', help='Open resulting trace file in a ' 'browser.', action='store_true', dest='view') return general_options def ProfileOptions(parser): """Build option group for profiling chrome. Args: parser: OptionParser object for parsing the command-line. Returns: Option group that contains profiling chrome options. """ profile_options = optparse.OptionGroup(parser, 'Profile Chrome Options') browsers = sorted(util.get_supported_browsers().keys()) profile_options.add_option('-b', '--browser', help='Select among installed browsers. ' 'One of ' + ', '.join(browsers) + '. "stable" is used by ' 'default.', type='choice', choices=browsers, default='stable') profile_options.add_option('-t', '--time', help=('Stops tracing after N seconds. ' 'Default is 5 seconds'), default=5, metavar='N', type='int', dest='trace_time') profile_options.add_option('-e', '--serial', help='adb device serial number.', type='string', default=util.get_default_serial(), dest='device_serial_number') profile_options.add_option('-f', '--trace_format', help='Format of saved trace: proto, json, html.' ' Default is proto.', default='proto', dest='trace_format') profile_options.add_option('-p', '--platform', help='Device platform. Only Android is supported.', default='android', dest='platform') profile_options.add_option('--buf-size', help='Use a trace buffer size ' ' of N KB.', type='int', metavar='N', dest='trace_buf_size') profile_options.add_option( '--enable_profiler', help='Comma-separated string of ' 'profiling options to use. Supports options for memory or ' 'cpu or both. Ex: --enable_profiler=memory ' 'or --enable_profiler=memory,cpu. ', dest='enable_profiler') profile_options.add_option('--chrome_categories', help='Chrome tracing ' 'categories to record.', type='string') profile_options.add_option( '--skip_symbolize', help='Skips symbolization after recording trace profile, if specified.', action='store_true', dest='skip_symbolize') profile_options.add_option('--compress', help='Compress the resulting trace ' 'with gzip. ', action='store_true') # This is kept for backwards compatibility. Help is suppressed because this # should be specified through the newer |trace_format| flag. profile_options.add_option('--json', help=optparse.SUPPRESS_HELP, dest='write_json') return profile_options def SymbolizeOptions(parser): """Build option group for proto trace symbolization. Args: parser: OptionParser object for parsing the command-line. Returns: Option group that contains symbolization options. """ symbolization_options = optparse.OptionGroup(parser, 'Symbolization Options') symbolization_options.add_option( '--breakpad_output_dir', help='Optional path to empty directory to store fetched trace symbols ' 'and extracted breakpad symbol files for official builds. Useful ' 'for symbolizing multiple traces from the same Chrome build. Use ' '--local_breakpad_dir when you already have breakpad files fetched. ' 'Automatically uses temporary directory if flag not specified.', dest='breakpad_output_dir') symbolization_options.add_option( '--local_breakpad_dir', help='Optional path to local directory containing breakpad symbol files ' 'used to symbolize the given trace. Breakpad files should be named ' 'with module id in upper case hexadecimal and ".breakpad" ' 'suffix. Ex: 12EFA32BE.breakpad', dest='local_breakpad_dir') symbolization_options.add_option( '--local_build_dir', help='Optional path to a local build directory containing symbol files.', dest='local_build_dir') symbolization_options.add_option( '--dump_syms', help=('Path to a dump_syms binary. Required when symbolizing an official ' 'build. Optional on local builds as we can use --local_build_dir ' 'to locate a binary. If built locally with ' 'autoninja -C out/Release dump_syms then the binary path is ' 'out/Release/dump_syms'), dest='dump_syms_path') symbolization_options.add_option( '--symbolizer', help=('Path to the trace_to_text binary for symbolization. Defaults to ' '"third_party/perfetto/tools/traceconv". traceconv is the same as ' 'trace_to_text, except that tracevonv finds a prebuilt ' 'trace_to_text binary to use.'), default='third_party/perfetto/tools/traceconv', dest='symbolizer_path') symbolization_options.add_option( '--trace_processor', help=('Optional path to trace processor binary. ' 'Automatically downloads binary if flag not specified.'), dest='trace_processor_path') symbolization_options.add_option( '--cloud_storage_bucket', help=('Optional cloud storage bucket to where symbol files reside. ' 'Defaults to "chrome-unsigned".'), default='chrome-unsigned', dest='cloud_storage_bucket') return symbolization_options def SetupProfilingCategories(options): """Sets --chrome_categories flag. Uses the --enable_profile flag to modify the --chrome_categories flag for specific profiling options. Args: options: The command-line options given. """ if options.enable_profiler is None: if not options.chrome_categories: GetTracingLogger().warning( 'No trace category or profiler is enabled using --enable_profiler ' 'and/or --chrome_categories, enabling all default categories.') if not options.skip_symbolize: GetTracingLogger().warning( 'No profiler is enabled, symbolization might fail without any ' 'frames. Use --skip_symbolize to disable symbolization.') else: GetTracingLogger().info( 'No profiler is enabled, the trace will only have trace events.') return if options.chrome_categories is None: options.chrome_categories = '' profile_options = options.enable_profiler.split(',') # Add to the --chrome_categories flag. if 'cpu' in profile_options: if options.chrome_categories: options.chrome_categories += ',' options.chrome_categories += 'disabled-by-default-cpu_profiler' if 'memory' in profile_options: if options.chrome_categories: options.chrome_categories += ',disabled-by-default-memory-infra' else: # If heap profiling is enabled and no categories are provided, it is # usually not helpful to include other information in traces. '-*' # disables other default categories so that only memory data is recorded. options.chrome_categories += 'disabled-by-default-memory-infra,-*' def GetTracingLogger(): """Returns the logger for tools/tracing.""" return logging.getLogger(TRACING_LOGGER_NAME) def SetupLogging(verbosity): """Setup logging levels. Sets default level to warning. Args: verbosity: None or integer type that specifies the logging level. (options.verbosity) """ logger = GetTracingLogger() if verbosity == 1: logging.basicConfig(level=logging.INFO) logger.setLevel(level=logging.INFO) elif verbosity >= 2: logging.basicConfig(level=logging.DEBUG) logger.setLevel(level=logging.DEBUG) else: logging.basicConfig(level=logging.WARNING) logger.setLevel(level=logging.WARNING)