Cronet is deeply integrated with the Perfetto tracing framework. Using Perfetto, you can:
This makes Perfetto a very powerful swiss-army knife for all your Cronet inspection, troubleshooting, debugging, and optimization needs.
Cronet tracing is usable out-of-the-box on every variant of Cronet across every release channel, including production builds running in production apps on production devices, as long as the Cronet version is recent enough. There is no need to rebuild Cronet nor the app.
Open this example trace in Perfetto
There are two ways to gather a Cronet-focused trace:
To capture a trace using this method, follow the Android instructions on how to capture a system trace.
To ensure Cronet events are recorded, make sure that:
To record a trace using Perfetto, refer to the Perfetto Android Quick Start guide.
The following Perfetto trace config provides a good starting point for gathering a Cronet-focused trace:
# Trace for up to 1 minute. Adjust to taste. duration_ms: 60000 data_sources { config { # Most Chromium code below the Cronet app-facing API uses the Perfetto # Track Event framework for tracing. This includes Chromium native call # stacks and NetLogs. name: "track_event" track_event_config { # Uncomment to record unredacted NetLogs, potentially revealing # credentials and other private information. # Note for this to work, you will also need to follow the instructions # in "Gathering unredacted NetLogs" below. # enabled_categories: "disabled-by-default-netlog.sensitive" } } # Only collect track events from Cronet, as opposed to other Chromium products # (e.g. WebView) that may be running at the same time. Uncomment if you want # to collect events from those too. # You can also use this to restrict the events to a single app. For example: # producer_name_filter: "cronet-com.google.android.googlequicksearchbox" producer_name_regex_filter: "cronet-.*" } data_sources { config { name: "linux.ftrace" ftrace_config { # Cronet Java code, including the app-facing higher layers (close to the # Cronet API), uses the Android Trace APIs (ATrace) for tracing. # You may wish to restrict this to the app you are interested in. atrace_apps: "*" # Required to get correct thread names. ftrace_events: "task/task_newtask" ftrace_events: "task/task_rename" # Trace ActivityManager. Useful to get insights into app initialization. atrace_categories: "am" # Trace the standard C library. Particularly useful to get insights into # Cronet native shared library (.so) loading (dlopen) performance. Also # provides insights into pthreads. atrace_categories: "bionic" # Trace the Java VM. Notably provides insights into Java class loading, # Java threads. Note this may also spam you with Java GC events. atrace_categories: "dalvik" # Surfaces IPCs. atrace_categories: "aidl" atrace_categories: "binder_driver" # Trace the Android OS network stack. Provides insights into a variety of # networking components such as WiFi, cellular, app network access policy, # firewall rules, etc. Can go as deep as providing detailed events about # cellular modem operation (RIL), such as data setup and signal strength. atrace_categories: "network" # ------------------------------------------------------------------------ # Note the below settings add a lot of high-frequency events to the trace. # You may want to comment them out if you want smaller, possibly more # readable traces and are not interested in highly detailed system # performance information. # Surfaces which threads are running on which CPU at any given time. # Useful for troubleshooting CPU contention. ftrace_events: "sched/sched_switch" # Surfaces the reason why a thread became schedulable (e.g. a mutex being # unlocked). Useful for troubleshooting lock contention. ftrace_events: "sched/sched_wakeup" ftrace_events: "sched/sched_wakeup_new" ftrace_events: "sched/sched_waking" # Surfaces thread terminations. ftrace_events: "sched/sched_process_exit" ftrace_events: "sched/sched_process_free" # Surfaces system calls. Useful for surfacing mutex waits and individual # socket send/receive calls. ftrace_events: "raw_syscalls/sys_enter" ftrace_events: "raw_syscalls/sys_exit" # ------------------------------------------------------------------------ } } } data_sources { config { name: "android.statsd" # Note: this data source only exists in Android 14+, see # https://r.android.com/2132122. If you get a "no field named ..." error # on the next line, you'll have to remove this data source. statsd_tracing_config { # Log Cronet telemetry atoms; see # org.chromium.net.telemetry.CronetStatsLog. # These can be used to troubleshoot Cronet telemetry, and the atom data # itself can provide insights into Cronet operation. # These will show up under "System" > "Statsd Atoms" in the Perfetto UI. push_atom_id: ATOM_CRONET_ENGINE_CREATED push_atom_id: ATOM_CRONET_TRAFFIC_REPORTED push_atom_id: ATOM_CRONET_ENGINE_BUILDER_INITIALIZED push_atom_id: ATOM_CRONET_INITIALIZED } } } data_sources { config { # Surfaces individual network packets being sent or received at the OS # level. Provides insights below the Cronet socket layer. This will show # up under "System" > "Network" in the Perfetto UI, and as counters under # process tracks. name: "android.network_packets" # Note: this data source only exists in Android 14+, see # https://r.android.com/2310392. If you get a "no field named ..." error # on the next line, you'll have to remove this data source. network_packet_trace_config { poll_ms: 250 } } } data_sources { config { name: "linux.process_stats" process_stats_config { scan_all_processes_on_start: true record_thread_names: true } } } data_sources { config { # Include the logcat in the trace. # Note that, sadly, this only works on userdebug/eng Android system # images, not production devices. See https://crbug.com/126721497. name: "android.log" } } data_sources { config { # Gather the list of packages installed on the device, along with their # versions. This can be found in the "Info and stats" section in the # Perfetto UI. name: "android.packages_list" } } buffers { size_kb: 65536 }
NetLogs are included in the trace by default. However, for privacy and security reasons, Cronet NetLog tracing operates in “heavily redacted” mode, where most of the metadata is stripped out. Notably, this means the resulting trace will not contain IP addresses, hostnames, URLs, HTTP headers, request/response bodies, TLS certificate details, etc.
If this is a problem, it is possible to configure Cronet to trace unredacted, unstripped NetLogs that will include the above information.
Cronet can only be configured to trace unredacted NetLogs if the following conditions are met:
To enable unredacted NetLog tracing, run:
adb shell setprop debug.cronet.trace_netlog everything
Then restart the app. This setting will persist until the next device reboot.
You will also need to explicitly enable the disabled-by-default-netlog.sensitive
track event category in your trace config (see above), otherwise no NetLog events will be logged while the above setting is active.
Due to a Perfetto limitation, events logged using the Perfetto SDK very shortly (single-digit milliseconds) after Cronet library initialization are liable to get dropped.
If you suspect this is preventing you from seeing the events you are looking for, use the following setting to delay Cronet initialization. This will hopefully allow Perfetto enough time to initialize.
adb shell setprop debug.cronet.init_trace_sleep 10ms