1/* 2 * Copyright (C) 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17syntax = "proto2"; 18 19package android.os.statsd.cronet; 20 21import "frameworks/proto_logging/stats/atoms.proto"; 22import "frameworks/proto_logging/stats/atom_field_options.proto"; 23 24option java_package = "com.android.os.cronet"; 25option java_multiple_files = true; 26 27extend Atom { 28 optional CronetEngineCreated cronet_engine_created = 703 29 [(module) = "cronet"]; 30 optional CronetTrafficReported cronet_traffic_reported = 704 31 [(module) = "cronet"]; 32 optional CronetEngineBuilderInitialized cronet_engine_builder_initialized = 762 [(module) = "cronet"]; 33 optional CronetHttpFlagsInitialized cronet_http_flags_initialized = 763 [(module) = "cronet"]; 34 optional CronetInitialized cronet_initialized = 764 [(module) = "cronet"]; 35} 36 37// Logged every time CronetEngine.Builder#build() returns. 38message CronetEngineCreated { 39 // A weak-ID-like reference to the instance of the Cronet engine being 40 // created. The field can be used to join subsequent request metrics with the 41 // engine details. 42 // 43 // The reference is NOT meant to be globally (or even on-device) unique, but 44 // on device collisions should be unlikely. 45 // Defaults to max positive int64 value which is equivalent to "not set". 46 optional int64 engine_instance_ref = 1 [default = 9223372036854775807]; 47 // Deprecated, moved to CronetEngineBuilderInitialized 48 optional int32 major_version = 2 [deprecated = true]; 49 // Deprecated, moved to CronetEngineBuilderInitialized 50 optional int32 minor_version = 3 [deprecated = true]; 51 // Deprecated, moved to CronetEngineBuilderInitialized 52 optional int32 build_version = 4 [deprecated = true]; 53 // Deprecated, moved to CronetEngineBuilderInitialized 54 optional int32 patch_version = 5 [deprecated = true]; 55 56 // Deprecated, moved to CronetInitialized 57 optional CronetSource source = 6 [deprecated = true]; 58 // Options that can be set on the Cronet builder. Only fields which are 59 // actively set by the Cronet user are populated. When using the protos 60 // default values should be considered as "null" - default semnantics can 61 // change based on the Cronet version. 62 // 63 // Fields that can contain free text (even if just theoretically) should be 64 // curated and/or replaced with fields that provide useful signal while not 65 // being sensitive. For instance, instead of logging values of quic hint hosts 66 // verbatim, prefer to log if a request was affected by a hint. 67 // 68 // For field names, follow the nomenclature below: 69 // - fields set directly on the builder should have no prefix 70 // (e.g., enableBrotli() translates to enable_brotli) 71 // - fields which are set in a sub-object or sub-structure should be prefixed 72 // with the path leading to that field. For example, 73 // builder.setExperimentalOptions("quic: { foo: { bar: 2 } }"); 74 // translates to experimental_options_quic_foo_bar 75 // 76 // 77 // In both cases, keep the existing names that are used in Cronet if at all 78 // possible. 79 80 // --- CronetEngine.Builder controls --- 81 optional bool enable_brotli = 7; 82 optional bool enable_http2 = 8; 83 optional CronetHttpCacheMode http_cache_mode = 9; 84 optional bool enable_public_key_pinning_bypass_for_local_trust_anchors = 10; 85 optional bool enable_quic = 11; 86 87 // --- ExperimentalCronetEngine.Builder controls --- 88 optional bool enable_network_quality_estimator = 12; 89 optional int32 thread_priority = 13; 90 91 // --- JSON experimental options --- 92 // The JSON config offers a lot of options but most of the atoms will have 93 // a majority of the fields below unset. We considered lumping the boolean 94 // flags into a single int32 field bud decided not to do so because 95 // a) having the standalone booleans makes the data set easier to understand 96 // and use 97 // b) we need to distinguish between three states (unset / true / false) 98 // which makes the compaction less efficient 99 // c) we expect the booleans to not be set in majority of the cases, 100 // in such a case, no space is saved. 101 102 // QUIC 103 // Lexicographically sorted, comma separated, curated list of QUIC connection 104 // options. 105 optional string experimental_options_quic_connection_options = 14; 106 optional OptionalBoolean 107 experimental_options_quic_store_server_configs_in_properties = 15; 108 // Unset value is -1 109 optional int32 110 experimental_options_quic_max_server_configs_stored_in_properties = 16 111 [default = -1]; 112 // Unset value is -1 113 optional int32 experimental_options_quic_idle_connection_timeout_seconds = 17 114 [default = -1]; 115 optional OptionalBoolean 116 experimental_options_quic_goaway_sessions_on_ip_change = 18; 117 optional OptionalBoolean 118 experimental_options_quic_close_sessions_on_ip_change = 19; 119 optional OptionalBoolean 120 experimental_options_quic_migrate_sessions_on_network_change_v2 = 20; 121 optional OptionalBoolean experimental_options_quic_migrate_sessions_early_v2 = 122 21; 123 optional OptionalBoolean 124 experimental_options_quic_quic_disable_bidirectional_streams = 22; 125 // Unset value is -1 126 optional int32 127 experimental_options_quic_max_time_before_crypto_handshake_seconds = 23 128 [default = -1]; 129 // Unset value is -1 130 optional int32 131 experimental_options_quic_max_idle_time_before_crypto_handshake_seconds = 132 24 [default = -1]; 133 optional OptionalBoolean 134 experimental_options_quic_enable_socket_recv_optimization = 25; 135 136 // DNS 137 optional OptionalBoolean experimental_options_asyncdns_enable = 26; 138 optional OptionalBoolean experimental_options_staledns_enable = 27; 139 // Unset value is -1 140 optional int32 experimental_options_staledns_delay_ms = 28 [default = -1]; 141 // Unset value is -1 142 optional int32 experimental_options_staledns_max_expired_time_ms = 29 143 [default = -1]; 144 // Unset value is -1 145 optional int32 experimental_options_staledns_max_stale_uses = 30 146 [default = -1]; 147 optional OptionalBoolean experimental_options_staledns_allow_other_network = 148 31; 149 optional OptionalBoolean experimental_options_staledns_persist_to_disk = 32; 150 // Unset value is -1 151 optional int32 experimental_options_staledns_persist_delay_ms = 33 152 [default = -1]; 153 optional OptionalBoolean 154 experimental_options_staledns_use_stale_on_name_not_resolved = 34; 155 // Host resolver rules omitted 156 optional OptionalBoolean experimental_options_disable_ipv6_on_wifi = 35; 157 158 // Deprecated, moved to CronetEngineBuilderInitialized. 159 enum CronetSource { 160 option deprecated = true; 161 // Safe default, don't use explicitly. 162 CRONET_SOURCE_UNSPECIFIED = 0; 163 // The library is bundled with the application. 164 CRONET_SOURCE_STATICALLY_LINKED = 1; 165 // The library is loaded from GMS Core 166 CRONET_SOURCE_GMSCORE_DYNAMITE = 2; 167 // The application is using the fallback implementation 168 CRONET_SOURCE_FALLBACK = 3; 169 } 170 171 // A pointer to CronetInitialized.cronet_initialization_ref for the Cronet initialization 172 // sequence that this engine relied on. 173 // Note that CronetInitialized may be logged after CronetEngineCreated because initialization 174 // continues in the background after the CronetEngine is instantiated. 175 // One consequence is that this reference can be broken if a 176 // crash occurs after the engine is created but before initialization is complete. 177 optional int64 cronet_initialization_ref = 36; 178 179 // See 180 // https://developer.android.com/guide/topics/connectivity/cronet/reference/org/chromium/net/CronetEngine.Builder.html#constants 181 // for detailed semantics. 182 enum CronetHttpCacheMode { 183 // Safe default, don't use explicitly. 184 HTTP_CACHE_MODE_UNSPECIFIED = 0; 185 186 HTTP_CACHE_DISABLED = 1; 187 HTTP_CACHE_DISK = 2; 188 HTTP_CACHE_DISK_NO_HTTP = 3; 189 HTTP_CACHE_IN_MEMORY = 4; 190 } 191} 192 193// Logged when a request has reached terminal state after the final user callback has returned 194// and before the requestFinishedListeners has fired. 195message CronetTrafficReported { 196 // The Cronet engine that sent the trafic. See 197 // CronetEngineCreated.engine_instance_ref for more details. 198 // Defaults to max negative int64 value which is equivalent to "not set". 199 // The default value is deliberately different from 200 // CronetEngineCreated.engine_instance_ref to avoid unintentional joining. 201 optional int64 engine_instance_ref = 1 [default = -9223372036854775808]; 202 203 // Bucketized sizes for request and response headers and body. 204 optional CronetRequestHeadersSizeBucket request_headers_size = 2; 205 optional CronetRequestBodySizeBucket request_body_size = 3; 206 optional CronetResponseHeadersSizeBucket response_headers_size = 4; 207 optional CronetResponseBodySizeBucket response_body_size = 5; 208 209 // The status code of the response. 210 optional int32 http_status_code = 6; 211 // The Fingerprint2011 hash of the protocol that was negotiated for this 212 // request (as returned by UrlResponseInfo.getNegotiatedProtocol()). The 213 // possible values for the string are limited so the hash is sufficient 214 // to identify known values while preventing accidental presence of 215 // freeform text. 216 // See go/cronet-negotiated-protocols for possible values. 217 optional int64 negotiated_protocol_hash = 7; 218 219 // The time it took from starting the request to receiving the full set of 220 // response headers, in milliseconds. 221 optional int32 headers_latency_millis = 8; 222 223 // The time that elapsed from the point UrlRequest#start() was called to the point 224 // we are ready to call the final user callback (e.g. onSucceeded). 225 // Note: this includes time spent waiting for the user to issue an I/O request. 226 // In other words this includes the effect of the user 227 // throttling Cronet (a.k.a. flow control, a.k.a. backpressure). 228 // See also total_idle_time_millis 229 optional int32 overall_latency_millis = 9; 230 231 // Whether a connection migration was attempted for this request. 232 optional bool connection_migration_attempted = 10; 233 // Whether a connection migration was attempted and successful for this 234 // request. 235 optional bool connection_migration_successful = 11; 236 237 // Number of previous CronetTrafficReported records that were dropped due to rate limiting. 238 optional int32 samples_rate_limited = 12; 239 240 // Terminal state of the reported request. 241 optional CronetRequestTerminalState terminal_state = 13; 242 243 enum CronetRequestTerminalState { 244 STATE_UNKNOWN = 0; 245 STATE_SUCCEEDED = 1; 246 STATE_ERROR = 2; 247 STATE_CANCELLED = 3; 248 } 249 250 // count of exceptions thrown during the execution of a user callback. 251 optional int32 user_callback_exception_count = 14; 252 253 // Same as `overall_latency_millis`, but only including time spent with no 254 // outstanding I/O request from the user. For example, the time that elapses between Cronet 255 // becoming ready to call the onReadCompleted callback and the user making the 256 // next UrlRequest#read() call is idle time: during that time 257 // there is no outstanding read request. 258 // If this value is large relative to overall_latency_millis, it may mean the request was 259 // throttled by the user, i.e. they applied backpressure/flow control, intentionally or not. 260 // Note that in this context, "idle" should be interpreted from the 261 // perspective of the Cronet user. Internally, Cronet might not actually be "idle" 262 // as it may still attempt to keep its internal buffers filled. 263 // An example of Cronet idly waiting for the user would look like the following 264 /* 265 Cronet User 266 | 267 | 268 |----- OnResponseStarted ------| 269 | 270 Cronet | 271 Idle | 272 Time | 273 | 274Cronet |------------------------------| User calls request.read() 275Doing | 276Work | 277 | 278OnReadCompleted | 279 | 280 |----- onReadCompleted -------| 281 | Cronet Idle Time includes the time taken to call 282 | Executor#execute() on the user's executor. 283 | 284 Cronet | If the user is blocking the network 285 Idle | thread in Executor#execute(), then technically that 286 Time | counts as backpressure / flow control. 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 |------------------------------| 298 */ 299 // This field contains the sum of Cronet Idle time waiting for user calls. 300 optional int64 total_idle_time_millis = 15; 301 302 // The time it takes for the user's Executor#execute() method to return 303 // Note: contrary to most other metrics in this atom, this also includes 304 // the final user callback (e.g. onSucceeded). 305 // Note: in the case of the native implementation, Executor#execute() is called on 306 // the network thread, which is a shared resource. High values for this metric are 307 // usually a red flag because they mean the network thread is unable to service any 308 // other UrlRequests during this time (including those from other engines). 309 optional int64 total_user_executor_execute_latency_millis = 16; 310 311 // The total amount of times `UrlRequest#read()` was called. 312 optional int32 read_count = 17; 313 314 // The total amount of times `UploadDataProvider#read` has been fired. 315 optional int32 on_upload_read_count = 18; 316 317 // Indicates if the request is a bidirectional stream or not. 318 optional OptionalBoolean is_bidi_stream = 19; 319 320 321 enum CronetRequestHeadersSizeBucket { 322 REQUEST_HEADERS_SIZE_BUCKET_UNSPECIFIED = 0; 323 // It's impossible to send requests without any headers in Cronet 324 REQUEST_HEADERS_SIZE_BUCKET_UNDER_ONE_KIB = 1; 325 REQUEST_HEADERS_SIZE_BUCKET_ONE_TO_TEN_KIB = 2; 326 REQUEST_HEADERS_SIZE_BUCKET_TEN_TO_TWENTY_FIVE_KIB = 3; 327 REQUEST_HEADERS_SIZE_BUCKET_TWENTY_FIVE_TO_FIFTY_KIB = 4; 328 REQUEST_HEADERS_SIZE_BUCKET_FIFTY_TO_HUNDRED_KIB = 5; 329 REQUEST_HEADERS_SIZE_BUCKET_OVER_HUNDRED_KIB = 6; 330 } 331 332 enum CronetRequestBodySizeBucket { 333 REQUEST_BODY_SIZE_BUCKET_UNSPECIFIED = 0; 334 REQUEST_BODY_SIZE_BUCKET_ZERO = 1; 335 REQUEST_BODY_SIZE_BUCKET_UNDER_TEN_KIB = 2; 336 REQUEST_BODY_SIZE_BUCKET_TEN_TO_FIFTY_KIB = 3; 337 REQUEST_BODY_SIZE_BUCKET_FIFTY_TO_TWO_HUNDRED_KIB = 4; 338 REQUEST_BODY_SIZE_BUCKET_TWO_HUNDRED_TO_FIVE_HUNDRED_KIB = 5; 339 REQUEST_BODY_SIZE_BUCKET_FIVE_HUNDRED_KIB_TO_ONE_MIB = 6; 340 REQUEST_BODY_SIZE_BUCKET_ONE_TO_FIVE_MIB = 7; 341 REQUEST_BODY_SIZE_BUCKET_OVER_FIVE_MIB = 8; 342 } 343 344 enum CronetResponseHeadersSizeBucket { 345 RESPONSE_HEADERS_SIZE_BUCKET_UNSPECIFIED = 0; 346 RESPONSE_HEADERS_SIZE_BUCKET_UNDER_ONE_KIB = 1; 347 RESPONSE_HEADERS_SIZE_BUCKET_ONE_TO_TEN_KIB = 2; 348 RESPONSE_HEADERS_SIZE_BUCKET_TEN_TO_TWENTY_FIVE_KIB = 3; 349 RESPONSE_HEADERS_SIZE_BUCKET_TWENTY_FIVE_TO_FIFTY_KIB = 4; 350 RESPONSE_HEADERS_SIZE_BUCKET_FIFTY_TO_HUNDRED_KIB = 5; 351 RESPONSE_HEADERS_SIZE_BUCKET_OVER_HUNDRED_KIB = 6; 352 } 353 354 enum CronetResponseBodySizeBucket { 355 RESPONSE_BODY_SIZE_BUCKET_UNSPECIFIED = 0; 356 RESPONSE_BODY_SIZE_BUCKET_ZERO = 1; 357 RESPONSE_BODY_SIZE_BUCKET_UNDER_TEN_KIB = 2; 358 RESPONSE_BODY_SIZE_BUCKET_TEN_TO_FIFTY_KIB = 3; 359 RESPONSE_BODY_SIZE_BUCKET_FIFTY_TO_TWO_HUNDRED_KIB = 4; 360 RESPONSE_BODY_SIZE_BUCKET_TWO_HUNDRED_TO_FIVE_HUNDRED_KIB = 5; 361 RESPONSE_BODY_SIZE_BUCKET_FIVE_HUNDRED_KIB_TO_ONE_MIB = 6; 362 RESPONSE_BODY_SIZE_BUCKET_ONE_TO_FIVE_MIB = 7; 363 RESPONSE_BODY_SIZE_BUCKET_OVER_FIVE_MIB = 8; 364 } 365} 366 367// Logged when the HTTP flags have been read. 368message CronetHttpFlagsInitialized { 369 // A weak-ID-like reference to the http flags loading operation. 370 // The field can be used to join with CronetEngineBuilderInitialized atom. 371 optional int64 cronet_http_flags_ref = 1; 372 // how long it took to load (or attempt to load) http flags. 373 // This field is set to -1 if flag loading was not attempted 374 // (e.g. because the app opted out of Cronet flag support). 375 // Note: There is no support for unset values, hence -1 is used. 376 optional int32 http_flags_latency_millis = 2 [default = -1]; 377 // Determine whether flag loading was successful or not. 378 optional OptionalBoolean flags_successful = 3; 379 380 // The first 8 bytes of the MD5 hashes, interpreted as signed little-endian integers, 381 // of the HTTP flag names that the Cronet instance logging the atoms is 382 // actually running with. 383 repeated int64 http_flags_names = 4 [packed = true]; 384 385 // The effective values of the flags, in the same order as 386 // http_flags_names. 387 // For boolean flags, this is 0 or 1. 388 // For integer flags, this is the value of the flag itself. 389 // For float values, this is the floating point value multiplied by 1 billion, 390 // rounded, and clamped to the int64 range. (This should result in distinct 391 // values for most commonly used floating point inputs.) 392 // For string or bytes flags, this is a hash of the value 393 // calculated in the same way as http_flags_names above. 394 repeated int64 http_flags_values = 5 [packed = true]; 395} 396 397/* 398 --------------------- ----------------- 399 | | createBuilder() | | ================⦀ 400 | Provider | -------------------------------> | Builder | ⦀ 401 | | | | ⦀ 402 |-------------------| engine_builder_created_lat |---------------- ⦀ 403 | ⦀ 404 Build() | engine_created_latency ⦀ 405 | ⦀ 406 V ⦀ 407 ------------------ ------------------- ⦀ 408 | | | | ⦀ 409 | REQ CAN START | <------------- | Engine | ⦀ 410 |WITHOUT BLOCKING| | | ⦀ 411 |----------------| |-----------------| ⦀ 412 ⦀ ⦀ 413 ==================================================================⦀ 414 engine_async_latency (This takes a variable amount of time depending on async jobs) 415 416 engine_builder_created_latency: The wall time elapsed since createBuilder() has been called 417 until a builder has been returned. 418 419 engine_created_latency: The wall time elapsed since Build() has been called until a CronetEngine 420 has been returned. 421 422 engine_async_latency: The wall time elapsed since Build() 423 has been called until the returned CronetEngine 424 is usable (All Asynchronous setup calls have finished executing). 425*/ 426 427// Logged once for each CronetSource when createBuilder() has returned. 428// This atom should normally be logged from Cronet API code (as opposed to impl code). 429// If the app is bundling a Cronet API version that is too old to know about this atom, 430// the impl takes responsibility for logging this atom and attempts to do so soon as 431// the impl is loaded. Some fields may be missing in this case. 432message CronetEngineBuilderInitialized { 433 // A weak-ID-like reference to the instance of the Cronet initialization. 434 // The field can be used to join subsequent engine creation and request 435 // metrics with the initialization details. 436 optional int64 cronet_initialization_ref = 1; 437 438 // How long it took to produce the first `CronetEngine.Builder` instance for the source specified. 439 // This field can be set by Api layer or Impl Layer, If this field was set by the Impl layer then 440 // the value of the field will be equal to -1. 441 optional int32 engine_builder_created_latency_millis = 2 [default = -1]; 442 443 // Source of the Cronet being loaded 444 optional Source source = 3; 445 446 enum Source { 447 // Safe default, don't use explicitly. 448 CRONET_SOURCE_UNSPECIFIED = 0; 449 // Native-based Cronet implementation, bundled within the client app. 450 CRONET_SOURCE_EMBEDDED_NATIVE = 1; 451 // Java-based Cronet implementation, bundled within the client app. 452 CRONET_SOURCE_EMBEDDED_JAVA = 2; 453 // Native-based Cronet implementation, loaded from GMS Core (Google Play Services). 454 CRONET_SOURCE_GMSCORE_NATIVE = 3; 455 // Native-based Cronet implementation, loaded from the bootclasspath 456 // through the android.net.http.HttpEngine API. 457 CRONET_SOURCE_HTTPENGINE_NATIVE = 4; 458 } 459 460 461 // Whether the Provider successfully created a builder or not. 462 // This field can be set by Api layer or Impl Layer, If this field was set by the Impl layer then 463 // the value of the field will be equal to `UNSET`. 464 optional OptionalBoolean creation_successful = 4; 465 466 // A weak-ID-like reference to the http flags loading operation. 467 // The field can be used to join with CronetHttpFlagsInitialized atoms. 468 // Note: at the time of writing, loading of flags happens after the builder creation 469 // has returned. This means the corresponding CronetHttpFlagsLoaded is logged 470 // after or might not be logged at all (if there was a crash or 471 // the resulting builder was never used). 472 optional int64 cronet_http_flags_ref = 5; 473 474 // This field carries the value stored in the file below 475 // https://source.chromium.org/chromium/chromium/src/+/main:components/cronet/android/api/src/org/chromium/net/ApiVersion.template 476 optional int32 cronet_api_level = 6; 477 478 // This field carries the value stored in the file below 479 // https://source.chromium.org/chromium/chromium/src/+/main:components/cronet/android/java/src/org/chromium/net/impl/ImplVersion.template 480 optional int32 cronet_impl_api_level = 7; 481 482 // The following fields corresponds to the version of Chromium for which the implementation 483 // was compiled against as seen https://source.chromium.org/chromium/chromium/src/+/main:chrome/VERSION;l=1;bpv=0;bpt=0 484 optional int32 major_version = 8; 485 optional int32 minor_version = 9; 486 optional int32 build_version = 10; 487 optional int32 patch_version = 11; 488 // The Android UID of the process that Cronet was initialized in. 489 optional int32 uid = 12 [(is_uid) = true]; 490} 491 492// Logged once for each CronetSource when the first CronetEngine is ready to be used. 493// Note that CronetInitialized may be logged after CronetEngineCreated because initialization 494// may continue in the background after the CronetEngine is instantiated. 495// One consequence is that cronet_initialization_ref can be broken if a 496// crash occurs after the engine is created but before initialization is complete. 497message CronetInitialized { 498 // A weak-ID-like reference to the instance of the Cronet initialization. 499 // The field can be used to join subsequent engine creation and request 500 // metrics with the native details. 501 optional int64 cronet_initialization_ref = 1; 502 503 // The wall clock time spent in the execution of the first call to `CronetEngine.Builder#build` 504 optional int32 engine_creation_latency_millis = 2 [default = -1]; 505 506 // How much wall clock time was spent from the moment the first `CronetEngine.Builder#build()` 507 // was made and the point where Cronet is ready to send requests. Notably, 508 // this includes the time it took for any asynchronous background initialization code to complete 509 optional int32 engine_async_latency_millis = 3 [default = -1]; 510} 511 512// Distinguishes between three states (unset / true / false) 513enum OptionalBoolean { 514 UNSET = 0; 515 TRUE = 1; 516 FALSE = 2; 517}