From c40ccc2f687057040b642f8649566b610bbdd97c Mon Sep 17 00:00:00 2001 From: Grace Lim Date: Mon, 29 Sep 2025 20:35:53 -0700 Subject: [PATCH 01/17] feat: Add spans for app launch, screen load/visible/time to first appear --- .chloggen/feat_app-spans.yaml | 22 ++++++ docs/registry/attributes/app.md | 69 +++++++++++++++--- model/app/registry.yaml | 120 ++++++++++++++++++++++++++++++++ model/app/spans.yaml | 98 ++++++++++++++++++++++++++ 4 files changed, 301 insertions(+), 8 deletions(-) create mode 100644 .chloggen/feat_app-spans.yaml create mode 100644 model/app/spans.yaml diff --git a/.chloggen/feat_app-spans.yaml b/.chloggen/feat_app-spans.yaml new file mode 100644 index 0000000000..e463b0f58e --- /dev/null +++ b/.chloggen/feat_app-spans.yaml @@ -0,0 +1,22 @@ +# Use this changelog template to create an entry for release notes. +# +# If your change doesn't affect end users you should instead start +# your pull request title with [chore] or use the "Skip Changelog" label. + +# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix' +change_type: enhancement + +# The name of the area of concern in the attributes-registry, (e.g. http, cloud, db) +component: app + +# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). +note: Add spans for app launch, app screen load, app time to first appear + +# Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists. +# The values here must be integers. +issues: [2830] + +# (Optional) One or more lines of additional information to render under the primary note. +# These lines will be padded with 2 spaces and then inserted directly into the document. +# Use pipe (|) for multiline entries. +subtext: diff --git a/docs/registry/attributes/app.md b/docs/registry/attributes/app.md index 13b23e6b16..f4621dada6 100644 --- a/docs/registry/attributes/app.md +++ b/docs/registry/attributes/app.md @@ -14,12 +14,21 @@ Describes attributes related to client-side applications (e.g. web apps or mobil | `app.jank.frame_count` | int | A number of frame renders that experienced jank. [2] | `9`; `42` | ![Development](https://img.shields.io/badge/-development-blue) | | `app.jank.period` | double | The time period, in seconds, for which this jank is being reported. | `1.0`; `5.0`; `10.24` | ![Development](https://img.shields.io/badge/-development-blue) | | `app.jank.threshold` | double | The minimum rendering threshold for this jank, in seconds. | `0.016`; `0.7`; `1.024` | ![Development](https://img.shields.io/badge/-development-blue) | +| `app.launch.duration` | int | The total time, in milliseconds, taken for the application to launch, from user initiation to being ready for interaction. [3] | `1000` | ![Development](https://img.shields.io/badge/-development-blue) | +| `app.launch.type` | string | The type of application launch, indicating the state of the app when the launch was initiated. [4] | `cold`; `warm`; `hot`; `pre_warm` | ![Development](https://img.shields.io/badge/-development-blue) | | `app.screen.coordinate.x` | int | The x (horizontal) coordinate of a screen coordinate, in screen pixels. | `0`; `131` | ![Development](https://img.shields.io/badge/-development-blue) | | `app.screen.coordinate.y` | int | The y (vertical) component of a screen coordinate, in screen pixels. | `12`; `99` | ![Development](https://img.shields.io/badge/-development-blue) | -| `app.screen.id` | string | An identifier that uniquely differentiates this screen from other screens in the same application. [3] | `f9bc787d-ff05-48ad-90e1-fca1d46130b3`; `com.example.app.MainActivity`; `com.example.shop.ProductDetailFragment`; `MyApp.ProfileView`; `MyApp.ProfileViewController` | ![Development](https://img.shields.io/badge/-development-blue) | -| `app.screen.name` | string | The name of an application screen. [4] | `MainActivity`; `ProductDetailFragment`; `ProfileView`; `ProfileViewController` | ![Development](https://img.shields.io/badge/-development-blue) | -| `app.widget.id` | string | An identifier that uniquely differentiates this widget from other widgets in the same application. [5] | `f9bc787d-ff05-48ad-90e1-fca1d46130b3`; `submit_order_1829` | ![Development](https://img.shields.io/badge/-development-blue) | -| `app.widget.name` | string | The name of an application widget. [6] | `submit`; `attack`; `Clear Cart` | ![Development](https://img.shields.io/badge/-development-blue) | +| `app.screen.depth` | int | The depth of this screen in the application’s screen hierarchy, where 0 represents the root screen. [5] | `0`; `2`; `5` | ![Development](https://img.shields.io/badge/-development-blue) | +| `app.screen.first_appear.duration` | int | The time, in milliseconds, from screen initialization to the first visual render of the screen. [6] | `1000` | ![Development](https://img.shields.io/badge/-development-blue) | +| `app.screen.id` | string | An identifier that uniquely differentiates this screen from other screens in the same application. [7] | `f9bc787d-ff05-48ad-90e1-fca1d46130b3`; `com.example.app.MainActivity`; `com.example.shop.ProductDetailFragment`; `MyApp.ProfileView`; `MyApp.ProfileViewController` | ![Development](https://img.shields.io/badge/-development-blue) | +| `app.screen.load.duration` | int | The total time, in milliseconds, from navigation trigger (e.g., button tap) to when the screen is able to handle user interactions. [8] | `1000` | ![Development](https://img.shields.io/badge/-development-blue) | +| `app.screen.main_thread_busy_time` | int | The time, in milliseconds, during which the main thread is occupied or blocked from processing user input, such as during rendering, animations, or network requests. This indicates the time the app is "busy" and unable to respond to user interactions. | | ![Development](https://img.shields.io/badge/-development-blue) | +| `app.screen.name` | string | The name of an application screen. [9] | `MainActivity`; `ProductDetailFragment`; `ProfileView`; `ProfileViewController` | ![Development](https://img.shields.io/badge/-development-blue) | +| `app.screen.nodes` | int | The total number of visual or interactive elements (widgets, views, components, etc.) within an application screen. [10] | `5`; `23`; `147` | ![Development](https://img.shields.io/badge/-development-blue) | +| `app.screen.type` | string | The type of UI management component or framework used to render and manage the screen's presentation and interactions. [11] | `swiftui`; `uikit`; `activity`; `fragment` | ![Development](https://img.shields.io/badge/-development-blue) | +| `app.screen.visible.duration` | int | The total time, in milliseconds, that the screen remained visible to the user. [12] | `1200`; `5500`; `700` | ![Development](https://img.shields.io/badge/-development-blue) | +| `app.widget.id` | string | An identifier that uniquely differentiates this widget from other widgets in the same application. [13] | `f9bc787d-ff05-48ad-90e1-fca1d46130b3`; `submit_order_1829` | ![Development](https://img.shields.io/badge/-development-blue) | +| `app.widget.name` | string | The name of an application widget. [14] | `submit`; `attack`; `Clear Cart` | ![Development](https://img.shields.io/badge/-development-blue) | **[1] `app.installation.id`:** Its value SHOULD persist across launches of the same application installation, including through application upgrades. It SHOULD change if the application is uninstalled or if all applications of the vendor are uninstalled. @@ -41,10 +50,54 @@ More information about Android identifier best practices can be found in the [An **[2] `app.jank.frame_count`:** Depending on platform limitations, the value provided MAY be approximation. -**[3] `app.screen.id`:** A screen represents only the part of the device display drawn by the app. It typically contains multiple widgets or UI components and is larger in scope than individual widgets. Multiple screens can coexist on the same display simultaneously (e.g., split view on tablets). +**[3] `app.launch.duration`:** This is the time, in milliseconds, between the user's initiation of the app launch (e.g., tapping the app icon or opening a link) and the point when the app is fully ready for interaction, such as the main screen becoming visible or the app’s main functionality being accessible. -**[4] `app.screen.name`:** A screen represents only the part of the device display drawn by the app. It typically contains multiple widgets or UI components and is larger in scope than individual widgets. Multiple screens can coexist on the same display simultaneously (e.g., split view on tablets). +**[4] `app.launch.type`:** Launch types include: -**[5] `app.widget.id`:** A widget is an application component, typically an on-screen visual GUI element. +- **Cold**: The app is launched from a terminated state, meaning no prior instance of the app is running. +- **Warm**: The app is launched from the background, meaning an instance of the app is still in memory, but not active. +- **Hot**: The app is already running and brought to the foreground, meaning no re-initialization is needed. +- **Pre-Warm**: The app launch uses a pre-warmed process, meaning part of the app's initialization has already been done in anticipation of the launch. -**[6] `app.widget.name`:** A widget is an application component, typically an on-screen visual GUI element. +**[5] `app.screen.depth`:** Depth represents the screen's position in the screen hierarchy tree. The root screen of the app is considered to have a depth of 0. Screens that are nested within other screens (such as in tab navigation, modals, or multi-screen flows) will have increasing depth values (1, 2, etc.). For example, a modal screen that is presented over the root screen would have a depth of 1, while a screen inside a modal might have a depth of 2. + +**[6] `app.screen.first_appear.duration`:** This measures the time, in milliseconds, until the first pixels of the screen are drawn and the screen becomes visible to the user. It does not necessarily mean the screen is fully interactive or that dynamic content (like images, API responses, or animations) is fully loaded. + +**[7] `app.screen.id`:** A screen represents only the part of the device display drawn by the app. It typically contains multiple widgets or UI components and is larger in scope than individual widgets. Multiple screens can coexist on the same display simultaneously (e.g., split view on tablets). + +**[8] `app.screen.load.duration`:** This includes time, in milliseconds, spent rendering the screen, waiting for dynamic content (if necessary), and ensuring the app is ready to process user input. The screen is considered "ready" once the UI is able to respond to user interactions such as taps, swipes, or gestures. + +**[9] `app.screen.name`:** A screen represents only the part of the device display drawn by the app. It typically contains multiple widgets or UI components and is larger in scope than individual widgets. Multiple screens can coexist on the same display simultaneously (e.g., split view on tablets). + +**[10] `app.screen.nodes`:** A "node" is any individual visual or interactive component contained within a screen. This includes UI elements like buttons, labels, text fields, images, containers, and static content such as images or text. + +**[11] `app.screen.type`:** This attribute indicates which framework or structure is used to manage and display the screen’s content. For iOS, it may refer to either SwiftUI (declarative) or UIKit (imperative) for managing views. On Android, it can refer to either an Activity or a Fragment. + +**[12] `app.screen.visible.duration`:** This attribute measures the duration during which the screen is visible and actively being displayed to the user. It begins when the screen becomes visible (e.g., `viewDidAppear` on iOS or `onResume` on Android) and ends when it is no longer visible (e.g., `viewWillDisappear` on iOS or `onPause` on Android). +It does **not** include the time when the screen is in the background, nor does it account for time the screen may be obscured by other views or overlays (e.g., modals, popups, or other screens in split-view). + +**[13] `app.widget.id`:** A widget is an application component, typically an on-screen visual GUI element. + +**[14] `app.widget.name`:** A widget is an application component, typically an on-screen visual GUI element. + +--- + +`app.launch.type` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used. + +| Value | Description | Stability | +|---|---|---| +| `cold` | App launch from terminated state | ![Development](https://img.shields.io/badge/-development-blue) | +| `hot` | App launch from memory (already running) | ![Development](https://img.shields.io/badge/-development-blue) | +| `pre_warm` | App launch using pre-warmed process | ![Development](https://img.shields.io/badge/-development-blue) | +| `warm` | App launch from background state] | ![Development](https://img.shields.io/badge/-development-blue) | + +--- + +`app.screen.type` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used. + +| Value | Description | Stability | +|---|---|---| +| `activity` | Android Activity (Android) | ![Development](https://img.shields.io/badge/-development-blue) | +| `fragment` | Android Fragment (Android) | ![Development](https://img.shields.io/badge/-development-blue) | +| `swiftui` | SwiftUI View (iOS) | ![Development](https://img.shields.io/badge/-development-blue) | +| `uikit` | UIKit ViewController (iOS) | ![Development](https://img.shields.io/badge/-development-blue) | diff --git a/model/app/registry.yaml b/model/app/registry.yaml index 7c704bf10f..0f45fc6301 100644 --- a/model/app/registry.yaml +++ b/model/app/registry.yaml @@ -48,6 +48,45 @@ groups: type: double brief: The time period, in seconds, for which this jank is being reported. examples: [ 1.0, 5.0, 10.24 ] + - id: app.launch.duration + type: int + stability: development + brief: > + The total time, in milliseconds, taken for the application to launch, from user initiation to being ready for interaction. + note: > + This is the time, in milliseconds, between the user's initiation of the app launch (e.g., tapping the app icon or opening a link) and the point when the app is fully ready for interaction, + such as the main screen becoming visible or the app’s main functionality being accessible. + examples: [1000] + - id: app.launch.type + type: + members: + - id: cold + value: "cold" + brief: App launch from terminated state + stability: development + - id: warm + value: "warm" + brief: App launch from background state] + stability: development + - id: hot + value: "hot" + brief: App launch from memory (already running) + stability: development + - id: pre_warm + value: "pre_warm" + brief: App launch using pre-warmed process + stability: development + stability: development + brief: > + The type of application launch, indicating the state of the app when the launch was initiated. + note: | + Launch types include: + + - **Cold**: The app is launched from a terminated state, meaning no prior instance of the app is running. + - **Warm**: The app is launched from the background, meaning an instance of the app is still in memory, but not active. + - **Hot**: The app is already running and brought to the foreground, meaning no re-initialization is needed. + - **Pre-Warm**: The app launch uses a pre-warmed process, meaning part of the app's initialization has already been done in anticipation of the launch. + examples: ["cold", "warm", "hot", "pre_warm"] - id: app.screen.coordinate.x type: int brief: The x (horizontal) coordinate of a screen coordinate, in screen pixels. @@ -86,6 +125,87 @@ groups: is larger in scope than individual widgets. Multiple screens can coexist on the same display simultaneously (e.g., split view on tablets). examples: ["MainActivity", "ProductDetailFragment", "ProfileView", "ProfileViewController"] + - id: app.screen.depth + type: int + stability: development + brief: > + The depth of this screen in the application’s screen hierarchy, where 0 represents the root screen. + note: > + Depth represents the screen's position in the screen hierarchy tree. + The root screen of the app is considered to have a depth of 0. Screens that are nested within other screens (such as in tab navigation, modals, or multi-screen flows) will have increasing depth values (1, 2, etc.). + For example, a modal screen that is presented over the root screen would have a depth of 1, while a screen inside a modal might have a depth of 2. + examples: [0, 2, 5] + - id: app.screen.first_appear.duration + type: int + stability: development + brief: > + The time, in milliseconds, from screen initialization to the first visual render of the screen. + note: > + This measures the time, in milliseconds, until the first pixels of the screen are drawn and the screen becomes visible to the user. + It does not necessarily mean the screen is fully interactive or that dynamic content (like images, API responses, or animations) is fully loaded. + examples: [1000] + - id: app.screen.load.duration + type: int + stability: development + brief: > + The total time, in milliseconds, from navigation trigger (e.g., button tap) to when the screen is able to handle user interactions. + note: > + This includes time, in milliseconds, spent rendering the screen, waiting for dynamic content (if necessary), and ensuring the app is ready to process user input. + The screen is considered "ready" once the UI is able to respond to user interactions such as taps, swipes, or gestures. + examples: [1000] + - id: app.screen.main_thread_busy_time + type: int + stability: development + brief: > + The time, in milliseconds, during which the main thread is occupied or blocked from processing user input, + such as during rendering, animations, or network requests. This indicates the time the app is "busy" and unable to respond to user interactions. + - id: app.screen.nodes + type: int + stability: development + brief: > + The total number of visual or interactive elements (widgets, views, components, etc.) within an application screen. + note: > + A "node" is any individual visual or interactive component contained within a screen. This includes UI elements like buttons, labels, text fields, images, containers, and static content such as images or text. + examples: [5, 23, 147] + - id: app.screen.type + type: + members: + - id: swiftui + value: "swiftui" + brief: SwiftUI View (iOS) + stability: development + - id: uikit + value: "uikit" + brief: UIKit ViewController (iOS) + stability: development + - id: activity + value: "activity" + brief: Android Activity (Android) + stability: development + - id: fragment + value: "fragment" + brief: Android Fragment (Android) + stability: development + stability: development + brief: > + The type of UI management component or framework used to render and manage the screen's presentation and interactions. + note: > + This attribute indicates which framework or structure is used to manage and display the screen’s content. For iOS, it may refer to either SwiftUI (declarative) or UIKit (imperative) for managing views. + On Android, it can refer to either an Activity or a Fragment. + examples: ["swiftui", "uikit", "activity", "fragment"] + - id: app.screen.visible.duration + type: int + stability: development + brief: > + The total time, in milliseconds, that the screen remained visible to the user. + note: > + This attribute measures the duration during which the screen is visible and actively being displayed to the user. + It begins when the screen becomes visible (e.g., `viewDidAppear` on iOS or `onResume` on Android) and ends when it is no longer visible + (e.g., `viewWillDisappear` on iOS or `onPause` on Android). + + It does **not** include the time when the screen is in the background, nor does it account for time the screen may be obscured by other views + or overlays (e.g., modals, popups, or other screens in split-view). + examples: [1200, 5500, 700] - id: app.widget.id type: string stability: development diff --git a/model/app/spans.yaml b/model/app/spans.yaml new file mode 100644 index 0000000000..d1037bc176 --- /dev/null +++ b/model/app/spans.yaml @@ -0,0 +1,98 @@ +groups: + - id: span.app.launch.client + type: span + span_kind: client + brief: This span represents an application launch operation. + note: | + **Span name:** MUST be `AppLaunch`. + + **Span kind** MUST be `CLIENT`. + + This span captures the time from user initiation (e.g., tapping the app icon or opening a link) + to the moment the app is ready for interaction. + stability: development + attributes: + - ref: app.launch.type + requirement_level: required + - ref: app.launch.duration + requirement_level: required + - id: span.app.screen.first_appear.client + type: span + span_kind: client + brief: This span describes the time until the first visual render of an application UI screen. + note: | + **Span name**: MUST be one of the following based on the measurement: + - `TimeToFirstDraw`: Time from screen initialization to the first pixel drawn. + - `TimeToFirstAppear`: Time from screen initialization to first appearance. + + **Span kind** MUST be `CLIENT`. + + This span captures the first visual render of the screen, even if it + might not be fully interactive or loaded yet. + stability: development + attributes: + - ref: app.screen.name + requirement_level: required + - ref: app.screen.first_appear.duration + requirement_level: required + - ref: app.screen.type + requirement_level: opt_in + - ref: app.screen.nodes + requirement_level: opt_in + - ref: app.screen.depth + requirement_level: opt_in + - id: span.app.screen.load.client + type: span + span_kind: client + brief: This span describes an application screen load operation, from navigation trigger to when the main thread becomes ready for user input. + note: | + **Span name:** MUST be `ScreenLoad`. + + **Span kind** MUST be `CLIENT`. + + This span captures the time from user initiation of navigation (e.g., tapping a button) to the point when the main thread is + ready to handle user input (e.g., taps, scrolls, gestures). + **Main thread readiness** refers to when the UI thread is no longer blocked by rendering, animations, or background tasks, + and is free to accept user input. + + It is important to note that while the main thread may be ready, some dynamic content, animations, or UI components may + still be loading, making the screen "appear" interactive even if it's not fully ready. + stability: development + attributes: + - ref: app.screen.name + requirement_level: required + - ref: app.screen.type + requirement_level: opt_in + - ref: app.screen.load.duration + requirement_level: required + - ref: app.screen.nodes + requirement_level: opt_in + - ref: app.screen.depth + requirement_level: opt_in + - ref: app.screen.main_thread_busy_time + requirement_level: opt_in + - id: span.app.screen.visible.client + type: span + span_kind: client + brief: > + This span captures the duration that a screen was visible to the user, indicating the time between when the screen becomes + visible and when it stops being visible. + note: | + **Span name:** MUST be `ScreenVisible`. + + **Span kind** MUST be `CLIENT`. + + This span captures the amount of time a screen remained visible to the user across platforms. For example: + - **iOS**: From `viewDidAppear` to `viewWillDisappear`, indicating when the screen is first shown and when it's about to disappear. + - **Android**: From `onResume` to `onPause`, indicating when the screen comes to the foreground and when it goes to the background. + + This span measures the screen’s visibility, meaning it includes only the time the screen is actively being shown to the user. + It does not include times when the app is in the background or when other screens/modal views are covering it. + stability: development + attributes: + - ref: app.screen.name + requirement_level: required + - ref: app.screen.type + requirement_level: opt_in + - ref: app.screen.visible.duration + requirement_level: required \ No newline at end of file From ca52bcb4ff2e70e908e369b846deb6e431c233d0 Mon Sep 17 00:00:00 2001 From: Grace Lim Date: Mon, 29 Sep 2025 21:07:35 -0700 Subject: [PATCH 02/17] fix: Define as app start instead of app launch --- docs/registry/attributes/app.md | 72 +++++++++++++------------- model/app/registry.yaml | 91 +++++++++++++++++---------------- model/app/spans.yaml | 34 ++++++------ 3 files changed, 99 insertions(+), 98 deletions(-) diff --git a/docs/registry/attributes/app.md b/docs/registry/attributes/app.md index f4621dada6..edf13b157d 100644 --- a/docs/registry/attributes/app.md +++ b/docs/registry/attributes/app.md @@ -14,19 +14,19 @@ Describes attributes related to client-side applications (e.g. web apps or mobil | `app.jank.frame_count` | int | A number of frame renders that experienced jank. [2] | `9`; `42` | ![Development](https://img.shields.io/badge/-development-blue) | | `app.jank.period` | double | The time period, in seconds, for which this jank is being reported. | `1.0`; `5.0`; `10.24` | ![Development](https://img.shields.io/badge/-development-blue) | | `app.jank.threshold` | double | The minimum rendering threshold for this jank, in seconds. | `0.016`; `0.7`; `1.024` | ![Development](https://img.shields.io/badge/-development-blue) | -| `app.launch.duration` | int | The total time, in milliseconds, taken for the application to launch, from user initiation to being ready for interaction. [3] | `1000` | ![Development](https://img.shields.io/badge/-development-blue) | -| `app.launch.type` | string | The type of application launch, indicating the state of the app when the launch was initiated. [4] | `cold`; `warm`; `hot`; `pre_warm` | ![Development](https://img.shields.io/badge/-development-blue) | | `app.screen.coordinate.x` | int | The x (horizontal) coordinate of a screen coordinate, in screen pixels. | `0`; `131` | ![Development](https://img.shields.io/badge/-development-blue) | | `app.screen.coordinate.y` | int | The y (vertical) component of a screen coordinate, in screen pixels. | `12`; `99` | ![Development](https://img.shields.io/badge/-development-blue) | -| `app.screen.depth` | int | The depth of this screen in the application’s screen hierarchy, where 0 represents the root screen. [5] | `0`; `2`; `5` | ![Development](https://img.shields.io/badge/-development-blue) | -| `app.screen.first_appear.duration` | int | The time, in milliseconds, from screen initialization to the first visual render of the screen. [6] | `1000` | ![Development](https://img.shields.io/badge/-development-blue) | -| `app.screen.id` | string | An identifier that uniquely differentiates this screen from other screens in the same application. [7] | `f9bc787d-ff05-48ad-90e1-fca1d46130b3`; `com.example.app.MainActivity`; `com.example.shop.ProductDetailFragment`; `MyApp.ProfileView`; `MyApp.ProfileViewController` | ![Development](https://img.shields.io/badge/-development-blue) | -| `app.screen.load.duration` | int | The total time, in milliseconds, from navigation trigger (e.g., button tap) to when the screen is able to handle user interactions. [8] | `1000` | ![Development](https://img.shields.io/badge/-development-blue) | -| `app.screen.main_thread_busy_time` | int | The time, in milliseconds, during which the main thread is occupied or blocked from processing user input, such as during rendering, animations, or network requests. This indicates the time the app is "busy" and unable to respond to user interactions. | | ![Development](https://img.shields.io/badge/-development-blue) | -| `app.screen.name` | string | The name of an application screen. [9] | `MainActivity`; `ProductDetailFragment`; `ProfileView`; `ProfileViewController` | ![Development](https://img.shields.io/badge/-development-blue) | -| `app.screen.nodes` | int | The total number of visual or interactive elements (widgets, views, components, etc.) within an application screen. [10] | `5`; `23`; `147` | ![Development](https://img.shields.io/badge/-development-blue) | -| `app.screen.type` | string | The type of UI management component or framework used to render and manage the screen's presentation and interactions. [11] | `swiftui`; `uikit`; `activity`; `fragment` | ![Development](https://img.shields.io/badge/-development-blue) | -| `app.screen.visible.duration` | int | The total time, in milliseconds, that the screen remained visible to the user. [12] | `1200`; `5500`; `700` | ![Development](https://img.shields.io/badge/-development-blue) | +| `app.screen.depth` | int | The depth of this screen in the application’s screen hierarchy, where 0 represents the root screen. [3] | `0`; `2`; `5` | ![Development](https://img.shields.io/badge/-development-blue) | +| `app.screen.first_appear.duration` | int | The time, in nanoseconds, from screen initialization to the first visual render of the screen. [4] | `1000` | ![Development](https://img.shields.io/badge/-development-blue) | +| `app.screen.id` | string | An identifier that uniquely differentiates this screen from other screens in the same application. [5] | `f9bc787d-ff05-48ad-90e1-fca1d46130b3`; `com.example.app.MainActivity`; `com.example.shop.ProductDetailFragment`; `MyApp.ProfileView`; `MyApp.ProfileViewController` | ![Development](https://img.shields.io/badge/-development-blue) | +| `app.screen.load.duration` | int | The total time, in nanoseconds, from navigation trigger (e.g., button tap) to when the screen is able to handle user interactions. [6] | `1000` | ![Development](https://img.shields.io/badge/-development-blue) | +| `app.screen.main_thread_busy_time` | int | The time, in nanoseconds, during which the main thread is occupied or blocked from processing user input, such as during rendering, animations, or network requests. This indicates the time the app is "busy" and unable to respond to user interactions. | | ![Development](https://img.shields.io/badge/-development-blue) | +| `app.screen.name` | string | The name of an application screen. [7] | `MainActivity`; `ProductDetailFragment`; `ProfileView`; `ProfileViewController` | ![Development](https://img.shields.io/badge/-development-blue) | +| `app.screen.nodes` | int | The total number of visual or interactive elements (widgets, views, components, etc.) within an application screen. [8] | `5`; `23`; `147` | ![Development](https://img.shields.io/badge/-development-blue) | +| `app.screen.type` | string | The type of UI management component or framework used to render and manage the screen's presentation and interactions. [9] | `swiftui`; `uikit`; `activity`; `fragment` | ![Development](https://img.shields.io/badge/-development-blue) | +| `app.screen.visible.duration` | int | The total time, in nanoseconds, that the screen remained visible to the user. [10] | `1200`; `5500`; `700` | ![Development](https://img.shields.io/badge/-development-blue) | +| `app.start.duration` | int | The total time, in nanoseconds, taken for the application to start, from user initiation to being ready for interaction. [11] | `1000` | ![Development](https://img.shields.io/badge/-development-blue) | +| `app.start.type` | string | The type of application start, indicating the state of the app when it was initiated. [12] | `cold`; `warm`; `hot`; `pre_warm` | ![Development](https://img.shields.io/badge/-development-blue) | | `app.widget.id` | string | An identifier that uniquely differentiates this widget from other widgets in the same application. [13] | `f9bc787d-ff05-48ad-90e1-fca1d46130b3`; `submit_order_1829` | ![Development](https://img.shields.io/badge/-development-blue) | | `app.widget.name` | string | The name of an application widget. [14] | `submit`; `attack`; `Clear Cart` | ![Development](https://img.shields.io/badge/-development-blue) | @@ -50,31 +50,31 @@ More information about Android identifier best practices can be found in the [An **[2] `app.jank.frame_count`:** Depending on platform limitations, the value provided MAY be approximation. -**[3] `app.launch.duration`:** This is the time, in milliseconds, between the user's initiation of the app launch (e.g., tapping the app icon or opening a link) and the point when the app is fully ready for interaction, such as the main screen becoming visible or the app’s main functionality being accessible. +**[3] `app.screen.depth`:** Depth represents the screen's position in the screen hierarchy tree. The root screen of the app is considered to have a depth of 0. Screens that are nested within other screens (such as in tab navigation, modals, or multi-screen flows) will have increasing depth values (1, 2, etc.). For example, a modal screen that is presented over the root screen would have a depth of 1, while a screen inside a modal might have a depth of 2. -**[4] `app.launch.type`:** Launch types include: +**[4] `app.screen.first_appear.duration`:** This measures the time, in nanoseconds, until the first pixels of the screen are drawn and the screen becomes visible to the user. It does not necessarily mean the screen is fully interactive or that dynamic content (like images, API responses, or animations) is fully loaded. -- **Cold**: The app is launched from a terminated state, meaning no prior instance of the app is running. -- **Warm**: The app is launched from the background, meaning an instance of the app is still in memory, but not active. -- **Hot**: The app is already running and brought to the foreground, meaning no re-initialization is needed. -- **Pre-Warm**: The app launch uses a pre-warmed process, meaning part of the app's initialization has already been done in anticipation of the launch. +**[5] `app.screen.id`:** A screen represents only the part of the device display drawn by the app. It typically contains multiple widgets or UI components and is larger in scope than individual widgets. Multiple screens can coexist on the same display simultaneously (e.g., split view on tablets). -**[5] `app.screen.depth`:** Depth represents the screen's position in the screen hierarchy tree. The root screen of the app is considered to have a depth of 0. Screens that are nested within other screens (such as in tab navigation, modals, or multi-screen flows) will have increasing depth values (1, 2, etc.). For example, a modal screen that is presented over the root screen would have a depth of 1, while a screen inside a modal might have a depth of 2. +**[6] `app.screen.load.duration`:** This includes time, in nanoseconds, spent rendering the screen, waiting for dynamic content (if necessary), and ensuring the app is ready to process user input. The screen is considered "ready" once the UI is able to respond to user interactions such as taps, swipes, or gestures. -**[6] `app.screen.first_appear.duration`:** This measures the time, in milliseconds, until the first pixels of the screen are drawn and the screen becomes visible to the user. It does not necessarily mean the screen is fully interactive or that dynamic content (like images, API responses, or animations) is fully loaded. +**[7] `app.screen.name`:** A screen represents only the part of the device display drawn by the app. It typically contains multiple widgets or UI components and is larger in scope than individual widgets. Multiple screens can coexist on the same display simultaneously (e.g., split view on tablets). -**[7] `app.screen.id`:** A screen represents only the part of the device display drawn by the app. It typically contains multiple widgets or UI components and is larger in scope than individual widgets. Multiple screens can coexist on the same display simultaneously (e.g., split view on tablets). +**[8] `app.screen.nodes`:** A "node" is any individual visual or interactive component contained within a screen. This includes UI elements like buttons, labels, text fields, images, containers, and static content such as images or text. -**[8] `app.screen.load.duration`:** This includes time, in milliseconds, spent rendering the screen, waiting for dynamic content (if necessary), and ensuring the app is ready to process user input. The screen is considered "ready" once the UI is able to respond to user interactions such as taps, swipes, or gestures. +**[9] `app.screen.type`:** This attribute indicates which framework or structure is used to manage and display the screen’s content. For iOS, it may refer to either SwiftUI (declarative) or UIKit (imperative) for managing views. On Android, it can refer to either an Activity or a Fragment. -**[9] `app.screen.name`:** A screen represents only the part of the device display drawn by the app. It typically contains multiple widgets or UI components and is larger in scope than individual widgets. Multiple screens can coexist on the same display simultaneously (e.g., split view on tablets). +**[10] `app.screen.visible.duration`:** This attribute measures the duration during which the screen is visible and actively being displayed to the user. It begins when the screen becomes visible (e.g., `viewDidAppear` on iOS or `onResume` on Android) and ends when it is no longer visible (e.g., `viewWillDisappear` on iOS or `onPause` on Android). +It does **not** include the time when the screen is in the background, nor does it account for time the screen may be obscured by other views or overlays (e.g., modals, popups, or other screens in split-view). -**[10] `app.screen.nodes`:** A "node" is any individual visual or interactive component contained within a screen. This includes UI elements like buttons, labels, text fields, images, containers, and static content such as images or text. +**[11] `app.start.duration`:** This is the time, in nanoseconds, between the user's initiation of the app start (e.g., tapping the app icon or opening a link) and the point when the app is fully ready for interaction, such as the main screen becoming visible or the app’s main functionality being accessible. -**[11] `app.screen.type`:** This attribute indicates which framework or structure is used to manage and display the screen’s content. For iOS, it may refer to either SwiftUI (declarative) or UIKit (imperative) for managing views. On Android, it can refer to either an Activity or a Fragment. +**[12] `app.start.type`:** Start types include: -**[12] `app.screen.visible.duration`:** This attribute measures the duration during which the screen is visible and actively being displayed to the user. It begins when the screen becomes visible (e.g., `viewDidAppear` on iOS or `onResume` on Android) and ends when it is no longer visible (e.g., `viewWillDisappear` on iOS or `onPause` on Android). -It does **not** include the time when the screen is in the background, nor does it account for time the screen may be obscured by other views or overlays (e.g., modals, popups, or other screens in split-view). +- **Cold**: The app is started from a terminated state, meaning no prior instance of the app is running. +- **Warm**: The app is started from the background, meaning an instance of the app is still in memory, but not active. +- **Hot**: The app is already running and brought to the foreground, meaning no re-initialization is needed. +- **Pre-Warm**: The app started uses a pre-warmed process, meaning part of the app's initialization has already been done in anticipation of the start. **[13] `app.widget.id`:** A widget is an application component, typically an on-screen visual GUI element. @@ -82,22 +82,22 @@ It does **not** include the time when the screen is in the background, nor does --- -`app.launch.type` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used. +`app.screen.type` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used. | Value | Description | Stability | |---|---|---| -| `cold` | App launch from terminated state | ![Development](https://img.shields.io/badge/-development-blue) | -| `hot` | App launch from memory (already running) | ![Development](https://img.shields.io/badge/-development-blue) | -| `pre_warm` | App launch using pre-warmed process | ![Development](https://img.shields.io/badge/-development-blue) | -| `warm` | App launch from background state] | ![Development](https://img.shields.io/badge/-development-blue) | +| `activity` | Android Activity (Android) | ![Development](https://img.shields.io/badge/-development-blue) | +| `fragment` | Android Fragment (Android) | ![Development](https://img.shields.io/badge/-development-blue) | +| `swiftui` | SwiftUI View (iOS) | ![Development](https://img.shields.io/badge/-development-blue) | +| `uikit` | UIKit ViewController (iOS) | ![Development](https://img.shields.io/badge/-development-blue) | --- -`app.screen.type` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used. +`app.start.type` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used. | Value | Description | Stability | |---|---|---| -| `activity` | Android Activity (Android) | ![Development](https://img.shields.io/badge/-development-blue) | -| `fragment` | Android Fragment (Android) | ![Development](https://img.shields.io/badge/-development-blue) | -| `swiftui` | SwiftUI View (iOS) | ![Development](https://img.shields.io/badge/-development-blue) | -| `uikit` | UIKit ViewController (iOS) | ![Development](https://img.shields.io/badge/-development-blue) | +| `cold` | App start from terminated state | ![Development](https://img.shields.io/badge/-development-blue) | +| `hot` | App start from memory (already running) | ![Development](https://img.shields.io/badge/-development-blue) | +| `pre_warm` | App start using pre-warmed process | ![Development](https://img.shields.io/badge/-development-blue) | +| `warm` | App start from background state] | ![Development](https://img.shields.io/badge/-development-blue) | diff --git a/model/app/registry.yaml b/model/app/registry.yaml index 0f45fc6301..62a3867ae4 100644 --- a/model/app/registry.yaml +++ b/model/app/registry.yaml @@ -48,45 +48,6 @@ groups: type: double brief: The time period, in seconds, for which this jank is being reported. examples: [ 1.0, 5.0, 10.24 ] - - id: app.launch.duration - type: int - stability: development - brief: > - The total time, in milliseconds, taken for the application to launch, from user initiation to being ready for interaction. - note: > - This is the time, in milliseconds, between the user's initiation of the app launch (e.g., tapping the app icon or opening a link) and the point when the app is fully ready for interaction, - such as the main screen becoming visible or the app’s main functionality being accessible. - examples: [1000] - - id: app.launch.type - type: - members: - - id: cold - value: "cold" - brief: App launch from terminated state - stability: development - - id: warm - value: "warm" - brief: App launch from background state] - stability: development - - id: hot - value: "hot" - brief: App launch from memory (already running) - stability: development - - id: pre_warm - value: "pre_warm" - brief: App launch using pre-warmed process - stability: development - stability: development - brief: > - The type of application launch, indicating the state of the app when the launch was initiated. - note: | - Launch types include: - - - **Cold**: The app is launched from a terminated state, meaning no prior instance of the app is running. - - **Warm**: The app is launched from the background, meaning an instance of the app is still in memory, but not active. - - **Hot**: The app is already running and brought to the foreground, meaning no re-initialization is needed. - - **Pre-Warm**: The app launch uses a pre-warmed process, meaning part of the app's initialization has already been done in anticipation of the launch. - examples: ["cold", "warm", "hot", "pre_warm"] - id: app.screen.coordinate.x type: int brief: The x (horizontal) coordinate of a screen coordinate, in screen pixels. @@ -139,25 +100,25 @@ groups: type: int stability: development brief: > - The time, in milliseconds, from screen initialization to the first visual render of the screen. + The time, in nanoseconds, from screen initialization to the first visual render of the screen. note: > - This measures the time, in milliseconds, until the first pixels of the screen are drawn and the screen becomes visible to the user. + This measures the time, in nanoseconds, until the first pixels of the screen are drawn and the screen becomes visible to the user. It does not necessarily mean the screen is fully interactive or that dynamic content (like images, API responses, or animations) is fully loaded. examples: [1000] - id: app.screen.load.duration type: int stability: development brief: > - The total time, in milliseconds, from navigation trigger (e.g., button tap) to when the screen is able to handle user interactions. + The total time, in nanoseconds, from navigation trigger (e.g., button tap) to when the screen is able to handle user interactions. note: > - This includes time, in milliseconds, spent rendering the screen, waiting for dynamic content (if necessary), and ensuring the app is ready to process user input. + This includes time, in nanoseconds, spent rendering the screen, waiting for dynamic content (if necessary), and ensuring the app is ready to process user input. The screen is considered "ready" once the UI is able to respond to user interactions such as taps, swipes, or gestures. examples: [1000] - id: app.screen.main_thread_busy_time type: int stability: development brief: > - The time, in milliseconds, during which the main thread is occupied or blocked from processing user input, + The time, in nanoseconds, during which the main thread is occupied or blocked from processing user input, such as during rendering, animations, or network requests. This indicates the time the app is "busy" and unable to respond to user interactions. - id: app.screen.nodes type: int @@ -197,7 +158,7 @@ groups: type: int stability: development brief: > - The total time, in milliseconds, that the screen remained visible to the user. + The total time, in nanoseconds, that the screen remained visible to the user. note: > This attribute measures the duration during which the screen is visible and actively being displayed to the user. It begins when the screen becomes visible (e.g., `viewDidAppear` on iOS or `onResume` on Android) and ends when it is no longer visible @@ -206,6 +167,45 @@ groups: It does **not** include the time when the screen is in the background, nor does it account for time the screen may be obscured by other views or overlays (e.g., modals, popups, or other screens in split-view). examples: [1200, 5500, 700] + - id: app.start.duration + type: int + stability: development + brief: > + The total time, in nanoseconds, taken for the application to start, from user initiation to being ready for interaction. + note: > + This is the time, in nanoseconds, between the user's initiation of the app start (e.g., tapping the app icon or opening a link) and the point when the app is fully ready for interaction, + such as the main screen becoming visible or the app’s main functionality being accessible. + examples: [1000] + - id: app.start.type + type: + members: + - id: cold + value: "cold" + brief: App start from terminated state + stability: development + - id: warm + value: "warm" + brief: App start from background state] + stability: development + - id: hot + value: "hot" + brief: App start from memory (already running) + stability: development + - id: pre_warm + value: "pre_warm" + brief: App start using pre-warmed process + stability: development + stability: development + brief: > + The type of application start, indicating the state of the app when it was initiated. + note: | + Start types include: + + - **Cold**: The app is started from a terminated state, meaning no prior instance of the app is running. + - **Warm**: The app is started from the background, meaning an instance of the app is still in memory, but not active. + - **Hot**: The app is already running and brought to the foreground, meaning no re-initialization is needed. + - **Pre-Warm**: The app started uses a pre-warmed process, meaning part of the app's initialization has already been done in anticipation of the start. + examples: ["cold", "warm", "hot", "pre_warm"] - id: app.widget.id type: string stability: development @@ -231,3 +231,4 @@ groups: stability: development brief: 'Unique identifier for a particular build or compilation of the application.' examples: ['6cff0a7e-cefc-4668-96f5-1273d8b334d0', '9f2b833506aa6973a92fde9733e6271f', 'my-app-1.0.0-code-123'] + diff --git a/model/app/spans.yaml b/model/app/spans.yaml index d1037bc176..f2b2d9d408 100644 --- a/model/app/spans.yaml +++ b/model/app/spans.yaml @@ -1,21 +1,4 @@ groups: - - id: span.app.launch.client - type: span - span_kind: client - brief: This span represents an application launch operation. - note: | - **Span name:** MUST be `AppLaunch`. - - **Span kind** MUST be `CLIENT`. - - This span captures the time from user initiation (e.g., tapping the app icon or opening a link) - to the moment the app is ready for interaction. - stability: development - attributes: - - ref: app.launch.type - requirement_level: required - - ref: app.launch.duration - requirement_level: required - id: span.app.screen.first_appear.client type: span span_kind: client @@ -95,4 +78,21 @@ groups: - ref: app.screen.type requirement_level: opt_in - ref: app.screen.visible.duration + requirement_level: required + - id: span.app.start.client + type: span + span_kind: client + brief: This span represents an application start operation. + note: | + **Span name:** MUST be `AppStart`. + + **Span kind** MUST be `CLIENT`. + + This span captures the time from user initiation (e.g., tapping the app icon or opening a link) + to the moment the app is ready for interaction. + stability: development + attributes: + - ref: app.start.type + requirement_level: required + - ref: app.start.duration requirement_level: required \ No newline at end of file From bf828ad10871f4a1e9c786462de81c4156dcc35e Mon Sep 17 00:00:00 2001 From: Grace Lim Date: Mon, 29 Sep 2025 21:17:56 -0700 Subject: [PATCH 03/17] fix: Resolve lint errors --- docs/registry/attributes/app.md | 13 +++++----- model/app/registry.yaml | 44 ++++++++++++++++++++------------- model/app/spans.yaml | 23 +++++++++-------- 3 files changed, 44 insertions(+), 36 deletions(-) diff --git a/docs/registry/attributes/app.md b/docs/registry/attributes/app.md index edf13b157d..e83ead4f86 100644 --- a/docs/registry/attributes/app.md +++ b/docs/registry/attributes/app.md @@ -20,7 +20,7 @@ Describes attributes related to client-side applications (e.g. web apps or mobil | `app.screen.first_appear.duration` | int | The time, in nanoseconds, from screen initialization to the first visual render of the screen. [4] | `1000` | ![Development](https://img.shields.io/badge/-development-blue) | | `app.screen.id` | string | An identifier that uniquely differentiates this screen from other screens in the same application. [5] | `f9bc787d-ff05-48ad-90e1-fca1d46130b3`; `com.example.app.MainActivity`; `com.example.shop.ProductDetailFragment`; `MyApp.ProfileView`; `MyApp.ProfileViewController` | ![Development](https://img.shields.io/badge/-development-blue) | | `app.screen.load.duration` | int | The total time, in nanoseconds, from navigation trigger (e.g., button tap) to when the screen is able to handle user interactions. [6] | `1000` | ![Development](https://img.shields.io/badge/-development-blue) | -| `app.screen.main_thread_busy_time` | int | The time, in nanoseconds, during which the main thread is occupied or blocked from processing user input, such as during rendering, animations, or network requests. This indicates the time the app is "busy" and unable to respond to user interactions. | | ![Development](https://img.shields.io/badge/-development-blue) | +| `app.screen.main_thread_busy_time` | int | The time, in nanoseconds, during which the main thread is occupied or blocked from processing user input, such as during rendering, animations, or network requests. This indicates the time the app is "busy" and unable to respond to user interactions. | | ![Development](https://img.shields.io/badge/-development-blue) | | `app.screen.name` | string | The name of an application screen. [7] | `MainActivity`; `ProductDetailFragment`; `ProfileView`; `ProfileViewController` | ![Development](https://img.shields.io/badge/-development-blue) | | `app.screen.nodes` | int | The total number of visual or interactive elements (widgets, views, components, etc.) within an application screen. [8] | `5`; `23`; `147` | ![Development](https://img.shields.io/badge/-development-blue) | | `app.screen.type` | string | The type of UI management component or framework used to render and manage the screen's presentation and interactions. [9] | `swiftui`; `uikit`; `activity`; `fragment` | ![Development](https://img.shields.io/badge/-development-blue) | @@ -50,9 +50,9 @@ More information about Android identifier best practices can be found in the [An **[2] `app.jank.frame_count`:** Depending on platform limitations, the value provided MAY be approximation. -**[3] `app.screen.depth`:** Depth represents the screen's position in the screen hierarchy tree. The root screen of the app is considered to have a depth of 0. Screens that are nested within other screens (such as in tab navigation, modals, or multi-screen flows) will have increasing depth values (1, 2, etc.). For example, a modal screen that is presented over the root screen would have a depth of 1, while a screen inside a modal might have a depth of 2. +**[3] `app.screen.depth`:** Depth represents the screen's position in the screen hierarchy tree. The root screen of the app is considered to have a depth of 0. Screens that are nested within other screens (such as in tab navigation, modals, or multi-screen flows) will have increasing depth values (1, 2, etc.). For example, a modal screen that is presented over the root screen would have a depth of 1, while a screen inside a modal might have a depth of 2. -**[4] `app.screen.first_appear.duration`:** This measures the time, in nanoseconds, until the first pixels of the screen are drawn and the screen becomes visible to the user. It does not necessarily mean the screen is fully interactive or that dynamic content (like images, API responses, or animations) is fully loaded. +**[4] `app.screen.first_appear.duration`:** This measures the time, in nanoseconds, until the first pixels of the screen are drawn and the screen becomes visible to the user. It does not necessarily mean the screen is fully interactive or that dynamic content (like images, API responses, or animations) is fully loaded. **[5] `app.screen.id`:** A screen represents only the part of the device display drawn by the app. It typically contains multiple widgets or UI components and is larger in scope than individual widgets. Multiple screens can coexist on the same display simultaneously (e.g., split view on tablets). @@ -62,12 +62,11 @@ More information about Android identifier best practices can be found in the [An **[8] `app.screen.nodes`:** A "node" is any individual visual or interactive component contained within a screen. This includes UI elements like buttons, labels, text fields, images, containers, and static content such as images or text. -**[9] `app.screen.type`:** This attribute indicates which framework or structure is used to manage and display the screen’s content. For iOS, it may refer to either SwiftUI (declarative) or UIKit (imperative) for managing views. On Android, it can refer to either an Activity or a Fragment. +**[9] `app.screen.type`:** This attribute indicates which framework or structure is used to manage and display the screen’s content. For iOS, it may refer to either SwiftUI (declarative) or UIKit (imperative) for managing views. On Android, it can refer to either an Activity or a Fragment. -**[10] `app.screen.visible.duration`:** This attribute measures the duration during which the screen is visible and actively being displayed to the user. It begins when the screen becomes visible (e.g., `viewDidAppear` on iOS or `onResume` on Android) and ends when it is no longer visible (e.g., `viewWillDisappear` on iOS or `onPause` on Android). -It does **not** include the time when the screen is in the background, nor does it account for time the screen may be obscured by other views or overlays (e.g., modals, popups, or other screens in split-view). +**[10] `app.screen.visible.duration`:** This attribute measures the duration during which the screen is visible and actively being displayed to the user. It begins when the screen becomes visible (e.g., `viewDidAppear` on iOS or `onResume` on Android) and ends when it is no longer visible (e.g., `viewWillDisappear` on iOS or `onPause` on Android). It does **not** include the time when the screen is in the background, nor does it account for time the screen may be obscured by other views or overlays (e.g., modals, popups, or other screens in split-view). -**[11] `app.start.duration`:** This is the time, in nanoseconds, between the user's initiation of the app start (e.g., tapping the app icon or opening a link) and the point when the app is fully ready for interaction, such as the main screen becoming visible or the app’s main functionality being accessible. +**[11] `app.start.duration`:** This is the time, in nanoseconds, between the user's initiation of the app start (e.g., tapping the app icon or opening a link) and the point when the app is fully ready for interaction, such as the main screen becoming visible or the app’s main functionality being accessible. **[12] `app.start.type`:** Start types include: diff --git a/model/app/registry.yaml b/model/app/registry.yaml index 62a3867ae4..c378e75496 100644 --- a/model/app/registry.yaml +++ b/model/app/registry.yaml @@ -92,9 +92,12 @@ groups: brief: > The depth of this screen in the application’s screen hierarchy, where 0 represents the root screen. note: > - Depth represents the screen's position in the screen hierarchy tree. - The root screen of the app is considered to have a depth of 0. Screens that are nested within other screens (such as in tab navigation, modals, or multi-screen flows) will have increasing depth values (1, 2, etc.). - For example, a modal screen that is presented over the root screen would have a depth of 1, while a screen inside a modal might have a depth of 2. + Depth represents the screen's position in the screen hierarchy tree. + The root screen of the app is considered to have a depth of 0. Screens + that are nested within other screens (such as in tab navigation, modals, + or multi-screen flows) will have increasing depth values (1, 2, etc.). + For example, a modal screen that is presented over the root screen would + have a depth of 1, while a screen inside a modal might have a depth of 2. examples: [0, 2, 5] - id: app.screen.first_appear.duration type: int @@ -102,31 +105,38 @@ groups: brief: > The time, in nanoseconds, from screen initialization to the first visual render of the screen. note: > - This measures the time, in nanoseconds, until the first pixels of the screen are drawn and the screen becomes visible to the user. - It does not necessarily mean the screen is fully interactive or that dynamic content (like images, API responses, or animations) is fully loaded. + This measures the time, in nanoseconds, until the first pixels of the screen + are drawn and the screen becomes visible to the user. + It does not necessarily mean the screen is fully interactive or that dynamic content + (like images, API responses, or animations) is fully loaded. examples: [1000] - id: app.screen.load.duration type: int stability: development brief: > - The total time, in nanoseconds, from navigation trigger (e.g., button tap) to when the screen is able to handle user interactions. + The total time, in nanoseconds, from navigation trigger (e.g., button tap) + to when the screen is able to handle user interactions. note: > - This includes time, in nanoseconds, spent rendering the screen, waiting for dynamic content (if necessary), and ensuring the app is ready to process user input. - The screen is considered "ready" once the UI is able to respond to user interactions such as taps, swipes, or gestures. + This includes time, in nanoseconds, spent rendering the screen, waiting for dynamic content + (if necessary), and ensuring the app is ready to process user input. + The screen is considered "ready" once the UI is able to respond to user interactions + such as taps, swipes, or gestures. examples: [1000] - id: app.screen.main_thread_busy_time type: int stability: development brief: > - The time, in nanoseconds, during which the main thread is occupied or blocked from processing user input, - such as during rendering, animations, or network requests. This indicates the time the app is "busy" and unable to respond to user interactions. + The time, in nanoseconds, during which the main thread is occupied or + blocked from processing user input, such as during rendering, animations, + or network requests. This indicates the time the app is "busy" and unable to respond to user interactions. - id: app.screen.nodes type: int stability: development brief: > The total number of visual or interactive elements (widgets, views, components, etc.) within an application screen. note: > - A "node" is any individual visual or interactive component contained within a screen. This includes UI elements like buttons, labels, text fields, images, containers, and static content such as images or text. + A "node" is any individual visual or interactive component contained within a screen. + This includes UI elements like buttons, labels, text fields, images, containers, and static content such as images or text. examples: [5, 23, 147] - id: app.screen.type type: @@ -149,9 +159,11 @@ groups: stability: development stability: development brief: > - The type of UI management component or framework used to render and manage the screen's presentation and interactions. + The type of UI management component or framework used to render and manage the screen's + presentation and interactions. note: > - This attribute indicates which framework or structure is used to manage and display the screen’s content. For iOS, it may refer to either SwiftUI (declarative) or UIKit (imperative) for managing views. + This attribute indicates which framework or structure is used to manage and display the + screen’s content. For iOS, it may refer to either SwiftUI (declarative) or UIKit (imperative) for managing views. On Android, it can refer to either an Activity or a Fragment. examples: ["swiftui", "uikit", "activity", "fragment"] - id: app.screen.visible.duration @@ -159,11 +171,10 @@ groups: stability: development brief: > The total time, in nanoseconds, that the screen remained visible to the user. - note: > + note: > This attribute measures the duration during which the screen is visible and actively being displayed to the user. It begins when the screen becomes visible (e.g., `viewDidAppear` on iOS or `onResume` on Android) and ends when it is no longer visible (e.g., `viewWillDisappear` on iOS or `onPause` on Android). - It does **not** include the time when the screen is in the background, nor does it account for time the screen may be obscured by other views or overlays (e.g., modals, popups, or other screens in split-view). examples: [1200, 5500, 700] @@ -173,7 +184,7 @@ groups: brief: > The total time, in nanoseconds, taken for the application to start, from user initiation to being ready for interaction. note: > - This is the time, in nanoseconds, between the user's initiation of the app start (e.g., tapping the app icon or opening a link) and the point when the app is fully ready for interaction, + This is the time, in nanoseconds, between the user's initiation of the app start (e.g., tapping the app icon or opening a link) and the point when the app is fully ready for interaction, such as the main screen becoming visible or the app’s main functionality being accessible. examples: [1000] - id: app.start.type @@ -231,4 +242,3 @@ groups: stability: development brief: 'Unique identifier for a particular build or compilation of the application.' examples: ['6cff0a7e-cefc-4668-96f5-1273d8b334d0', '9f2b833506aa6973a92fde9733e6271f', 'my-app-1.0.0-code-123'] - diff --git a/model/app/spans.yaml b/model/app/spans.yaml index f2b2d9d408..060c1be58b 100644 --- a/model/app/spans.yaml +++ b/model/app/spans.yaml @@ -10,7 +10,7 @@ groups: **Span kind** MUST be `CLIENT`. - This span captures the first visual render of the screen, even if it + This span captures the first visual render of the screen, even if it might not be fully interactive or loaded yet. stability: development attributes: @@ -33,12 +33,11 @@ groups: **Span kind** MUST be `CLIENT`. - This span captures the time from user initiation of navigation (e.g., tapping a button) to the point when the main thread is - ready to handle user input (e.g., taps, scrolls, gestures). - **Main thread readiness** refers to when the UI thread is no longer blocked by rendering, animations, or background tasks, - and is free to accept user input. - - It is important to note that while the main thread may be ready, some dynamic content, animations, or UI components may + This span captures the time from user initiation of navigation (e.g., tapping a button) to the point when the main thread is + ready to handle user input (e.g., taps, scrolls, gestures). + **Main thread readiness** refers to when the UI thread is no longer blocked by rendering, animations, or background tasks, + and is free to accept user input. + It is important to note that while the main thread may be ready, some dynamic content, animations, or UI components may still be loading, making the screen "appear" interactive even if it's not fully ready. stability: development attributes: @@ -58,7 +57,7 @@ groups: type: span span_kind: client brief: > - This span captures the duration that a screen was visible to the user, indicating the time between when the screen becomes + This span captures the duration that a screen was visible to the user, indicating the time between when the screen becomes visible and when it stops being visible. note: | **Span name:** MUST be `ScreenVisible`. @@ -69,7 +68,7 @@ groups: - **iOS**: From `viewDidAppear` to `viewWillDisappear`, indicating when the screen is first shown and when it's about to disappear. - **Android**: From `onResume` to `onPause`, indicating when the screen comes to the foreground and when it goes to the background. - This span measures the screen’s visibility, meaning it includes only the time the screen is actively being shown to the user. + This span measures the screen’s visibility, meaning it includes only the time the screen is actively being shown to the user. It does not include times when the app is in the background or when other screens/modal views are covering it. stability: development attributes: @@ -88,11 +87,11 @@ groups: **Span kind** MUST be `CLIENT`. - This span captures the time from user initiation (e.g., tapping the app icon or opening a link) - to the moment the app is ready for interaction. + This span captures the time from user initiation (e.g., tapping the app icon or opening a link) + to the moment the app is ready for interaction. stability: development attributes: - ref: app.start.type requirement_level: required - ref: app.start.duration - requirement_level: required \ No newline at end of file + requirement_level: required From a366135d1b2af3adb93ec45a46e46172a36e3b99 Mon Sep 17 00:00:00 2001 From: Grace Lim Date: Wed, 8 Oct 2025 13:04:03 -0700 Subject: [PATCH 04/17] Update TTFA to TTFD, propose new definition for screen loads --- model/app/events.yaml | 20 ++++++++++++ model/app/registry.yaml | 64 +++++++------------------------------- model/app/spans.yaml | 69 +++++++---------------------------------- 3 files changed, 43 insertions(+), 110 deletions(-) diff --git a/model/app/events.yaml b/model/app/events.yaml index edbd7d5f04..c9a0c335f1 100644 --- a/model/app/events.yaml +++ b/model/app/events.yaml @@ -62,3 +62,23 @@ groups: requirement_level: recommended - ref: app.jank.period requirement_level: recommended + - id: event.app.screen.visible + stability: development + type: event + name: app.screen.visible + brief: > + This event captures the duration that a screen was visible to the user, indicating the time between when the screen becomes + visible and when it stops being visible. + note: > + This event measures the screen's visibility, in nanoseconds, meaning it includes only the time the screen is actively being shown to the user. + It does not include times when the app is in the background or when other screens/modal views are covering it. For example: + - **iOS**: From `viewDidAppear` to `viewWillDisappear`, indicating when the screen is first shown and when it's about to disappear. + - **Android**: From `onResume` to `onPause`, indicating when the screen comes to the foreground and when it goes to the background. + + attributes: + - ref: app.screen.name + requirement_level: required + - ref: app.screen.type + requirement_level: opt_in + - ref: app.screen.visible.duration + requirement_level: required diff --git a/model/app/registry.yaml b/model/app/registry.yaml index c378e75496..8e9e0ff0cb 100644 --- a/model/app/registry.yaml +++ b/model/app/registry.yaml @@ -86,58 +86,26 @@ groups: is larger in scope than individual widgets. Multiple screens can coexist on the same display simultaneously (e.g., split view on tablets). examples: ["MainActivity", "ProductDetailFragment", "ProfileView", "ProfileViewController"] - - id: app.screen.depth + - id: app.screen.first_draw.duration type: int stability: development brief: > - The depth of this screen in the application’s screen hierarchy, where 0 represents the root screen. + The time, in nanoseconds, from screen initialization to the first frame being rendered. note: > - Depth represents the screen's position in the screen hierarchy tree. - The root screen of the app is considered to have a depth of 0. Screens - that are nested within other screens (such as in tab navigation, modals, - or multi-screen flows) will have increasing depth values (1, 2, etc.). - For example, a modal screen that is presented over the root screen would - have a depth of 1, while a screen inside a modal might have a depth of 2. - examples: [0, 2, 5] - - id: app.screen.first_appear.duration - type: int - stability: development - brief: > - The time, in nanoseconds, from screen initialization to the first visual render of the screen. - note: > - This measures the time, in nanoseconds, until the first pixels of the screen - are drawn and the screen becomes visible to the user. - It does not necessarily mean the screen is fully interactive or that dynamic content - (like images, API responses, or animations) is fully loaded. + This measures the time, in nanoseconds, until the first frame of the screen + is rendered and becomes visible to the user. examples: [1000] - id: app.screen.load.duration type: int stability: development brief: > - The total time, in nanoseconds, from navigation trigger (e.g., button tap) - to when the screen is able to handle user interactions. + The time taken, in nanoseconds, for a screen to load and become stable, measured from when + the screen begins appearing until the first stable frame has been rendered. note: > - This includes time, in nanoseconds, spent rendering the screen, waiting for dynamic content - (if necessary), and ensuring the app is ready to process user input. - The screen is considered "ready" once the UI is able to respond to user interactions - such as taps, swipes, or gestures. + This attribute represents the total duration, in nanoseconds, of a screen load as experienced by the user. + The screen load is considered complete when the first stable frame of the screen has been rendered. + A frame is considered stable when no major layout or frame changes occur for a brief stability interval (e.g. 150 ms). examples: [1000] - - id: app.screen.main_thread_busy_time - type: int - stability: development - brief: > - The time, in nanoseconds, during which the main thread is occupied or - blocked from processing user input, such as during rendering, animations, - or network requests. This indicates the time the app is "busy" and unable to respond to user interactions. - - id: app.screen.nodes - type: int - stability: development - brief: > - The total number of visual or interactive elements (widgets, views, components, etc.) within an application screen. - note: > - A "node" is any individual visual or interactive component contained within a screen. - This includes UI elements like buttons, labels, text fields, images, containers, and static content such as images or text. - examples: [5, 23, 147] - id: app.screen.type type: members: @@ -196,15 +164,7 @@ groups: stability: development - id: warm value: "warm" - brief: App start from background state] - stability: development - - id: hot - value: "hot" - brief: App start from memory (already running) - stability: development - - id: pre_warm - value: "pre_warm" - brief: App start using pre-warmed process + brief: App start from background state stability: development stability: development brief: > @@ -214,9 +174,7 @@ groups: - **Cold**: The app is started from a terminated state, meaning no prior instance of the app is running. - **Warm**: The app is started from the background, meaning an instance of the app is still in memory, but not active. - - **Hot**: The app is already running and brought to the foreground, meaning no re-initialization is needed. - - **Pre-Warm**: The app started uses a pre-warmed process, meaning part of the app's initialization has already been done in anticipation of the start. - examples: ["cold", "warm", "hot", "pre_warm"] + examples: ["cold", "warm"] - id: app.widget.id type: string stability: development diff --git a/model/app/spans.yaml b/model/app/spans.yaml index 060c1be58b..a8edf77b63 100644 --- a/model/app/spans.yaml +++ b/model/app/spans.yaml @@ -1,44 +1,30 @@ groups: - - id: span.app.screen.first_appear.client + - id: span.app.screen.first_draw.client type: span - span_kind: client - brief: This span describes the time until the first visual render of an application UI screen. + span_kind: internal + brief: This span describes the time until the first draw of an application UI screen. note: | - **Span name**: MUST be one of the following based on the measurement: - - `TimeToFirstDraw`: Time from screen initialization to the first pixel drawn. - - `TimeToFirstAppear`: Time from screen initialization to first appearance. - - **Span kind** MUST be `CLIENT`. + **Span name**: MUST be `app.screen.first_draw`. - This span captures the first visual render of the screen, even if it - might not be fully interactive or loaded yet. + This span captures the time from screen initialization to the first frame drawn. stability: development attributes: - ref: app.screen.name requirement_level: required - - ref: app.screen.first_appear.duration + - ref: app.screen.first_draw.duration requirement_level: required - ref: app.screen.type requirement_level: opt_in - - ref: app.screen.nodes - requirement_level: opt_in - - ref: app.screen.depth - requirement_level: opt_in - id: span.app.screen.load.client type: span - span_kind: client - brief: This span describes an application screen load operation, from navigation trigger to when the main thread becomes ready for user input. + span_kind: internal + brief: This span describes an application screen load operation, from navigation trigger to when the first stable frame has been rendered. note: | - **Span name:** MUST be `ScreenLoad`. + **Span name:** MUST be `app.screen.load`. - **Span kind** MUST be `CLIENT`. - - This span captures the time from user initiation of navigation (e.g., tapping a button) to the point when the main thread is - ready to handle user input (e.g., taps, scrolls, gestures). - **Main thread readiness** refers to when the UI thread is no longer blocked by rendering, animations, or background tasks, - and is free to accept user input. - It is important to note that while the main thread may be ready, some dynamic content, animations, or UI components may - still be loading, making the screen "appear" interactive even if it's not fully ready. + This span captures the time from user initiation of navigation (e.g., tapping a button) to the point when the first stable frame + of the screen has been rendered. A frame is considered stable when no major layout or frame changes occur for a brief stability + interval (e.g. 100–200 ms). stability: development attributes: - ref: app.screen.name @@ -47,37 +33,6 @@ groups: requirement_level: opt_in - ref: app.screen.load.duration requirement_level: required - - ref: app.screen.nodes - requirement_level: opt_in - - ref: app.screen.depth - requirement_level: opt_in - - ref: app.screen.main_thread_busy_time - requirement_level: opt_in - - id: span.app.screen.visible.client - type: span - span_kind: client - brief: > - This span captures the duration that a screen was visible to the user, indicating the time between when the screen becomes - visible and when it stops being visible. - note: | - **Span name:** MUST be `ScreenVisible`. - - **Span kind** MUST be `CLIENT`. - - This span captures the amount of time a screen remained visible to the user across platforms. For example: - - **iOS**: From `viewDidAppear` to `viewWillDisappear`, indicating when the screen is first shown and when it's about to disappear. - - **Android**: From `onResume` to `onPause`, indicating when the screen comes to the foreground and when it goes to the background. - - This span measures the screen’s visibility, meaning it includes only the time the screen is actively being shown to the user. - It does not include times when the app is in the background or when other screens/modal views are covering it. - stability: development - attributes: - - ref: app.screen.name - requirement_level: required - - ref: app.screen.type - requirement_level: opt_in - - ref: app.screen.visible.duration - requirement_level: required - id: span.app.start.client type: span span_kind: client From a0c435c10fbe0cb98f3be395822e101bffb5c9da Mon Sep 17 00:00:00 2001 From: Grace Lim Date: Wed, 8 Oct 2025 15:24:55 -0700 Subject: [PATCH 05/17] chore: Generate doc updates for latest changes --- docs/registry/attributes/app.md | 53 +++++++++++++-------------------- model/app/spans.yaml | 4 +-- 2 files changed, 23 insertions(+), 34 deletions(-) diff --git a/docs/registry/attributes/app.md b/docs/registry/attributes/app.md index e83ead4f86..c8a18568c9 100644 --- a/docs/registry/attributes/app.md +++ b/docs/registry/attributes/app.md @@ -16,19 +16,16 @@ Describes attributes related to client-side applications (e.g. web apps or mobil | `app.jank.threshold` | double | The minimum rendering threshold for this jank, in seconds. | `0.016`; `0.7`; `1.024` | ![Development](https://img.shields.io/badge/-development-blue) | | `app.screen.coordinate.x` | int | The x (horizontal) coordinate of a screen coordinate, in screen pixels. | `0`; `131` | ![Development](https://img.shields.io/badge/-development-blue) | | `app.screen.coordinate.y` | int | The y (vertical) component of a screen coordinate, in screen pixels. | `12`; `99` | ![Development](https://img.shields.io/badge/-development-blue) | -| `app.screen.depth` | int | The depth of this screen in the application’s screen hierarchy, where 0 represents the root screen. [3] | `0`; `2`; `5` | ![Development](https://img.shields.io/badge/-development-blue) | -| `app.screen.first_appear.duration` | int | The time, in nanoseconds, from screen initialization to the first visual render of the screen. [4] | `1000` | ![Development](https://img.shields.io/badge/-development-blue) | -| `app.screen.id` | string | An identifier that uniquely differentiates this screen from other screens in the same application. [5] | `f9bc787d-ff05-48ad-90e1-fca1d46130b3`; `com.example.app.MainActivity`; `com.example.shop.ProductDetailFragment`; `MyApp.ProfileView`; `MyApp.ProfileViewController` | ![Development](https://img.shields.io/badge/-development-blue) | -| `app.screen.load.duration` | int | The total time, in nanoseconds, from navigation trigger (e.g., button tap) to when the screen is able to handle user interactions. [6] | `1000` | ![Development](https://img.shields.io/badge/-development-blue) | -| `app.screen.main_thread_busy_time` | int | The time, in nanoseconds, during which the main thread is occupied or blocked from processing user input, such as during rendering, animations, or network requests. This indicates the time the app is "busy" and unable to respond to user interactions. | | ![Development](https://img.shields.io/badge/-development-blue) | -| `app.screen.name` | string | The name of an application screen. [7] | `MainActivity`; `ProductDetailFragment`; `ProfileView`; `ProfileViewController` | ![Development](https://img.shields.io/badge/-development-blue) | -| `app.screen.nodes` | int | The total number of visual or interactive elements (widgets, views, components, etc.) within an application screen. [8] | `5`; `23`; `147` | ![Development](https://img.shields.io/badge/-development-blue) | -| `app.screen.type` | string | The type of UI management component or framework used to render and manage the screen's presentation and interactions. [9] | `swiftui`; `uikit`; `activity`; `fragment` | ![Development](https://img.shields.io/badge/-development-blue) | -| `app.screen.visible.duration` | int | The total time, in nanoseconds, that the screen remained visible to the user. [10] | `1200`; `5500`; `700` | ![Development](https://img.shields.io/badge/-development-blue) | -| `app.start.duration` | int | The total time, in nanoseconds, taken for the application to start, from user initiation to being ready for interaction. [11] | `1000` | ![Development](https://img.shields.io/badge/-development-blue) | -| `app.start.type` | string | The type of application start, indicating the state of the app when it was initiated. [12] | `cold`; `warm`; `hot`; `pre_warm` | ![Development](https://img.shields.io/badge/-development-blue) | -| `app.widget.id` | string | An identifier that uniquely differentiates this widget from other widgets in the same application. [13] | `f9bc787d-ff05-48ad-90e1-fca1d46130b3`; `submit_order_1829` | ![Development](https://img.shields.io/badge/-development-blue) | -| `app.widget.name` | string | The name of an application widget. [14] | `submit`; `attack`; `Clear Cart` | ![Development](https://img.shields.io/badge/-development-blue) | +| `app.screen.first_draw.duration` | int | The time, in nanoseconds, from screen initialization to the first frame being rendered. [3] | `1000` | ![Development](https://img.shields.io/badge/-development-blue) | +| `app.screen.id` | string | An identifier that uniquely differentiates this screen from other screens in the same application. [4] | `f9bc787d-ff05-48ad-90e1-fca1d46130b3`; `com.example.app.MainActivity`; `com.example.shop.ProductDetailFragment`; `MyApp.ProfileView`; `MyApp.ProfileViewController` | ![Development](https://img.shields.io/badge/-development-blue) | +| `app.screen.load.duration` | int | The time taken, in nanoseconds, for a screen to load and become stable, measured from when the screen begins appearing until the first stable frame has been rendered. [5] | `1000` | ![Development](https://img.shields.io/badge/-development-blue) | +| `app.screen.name` | string | The name of an application screen. [6] | `MainActivity`; `ProductDetailFragment`; `ProfileView`; `ProfileViewController` | ![Development](https://img.shields.io/badge/-development-blue) | +| `app.screen.type` | string | The type of UI management component or framework used to render and manage the screen's presentation and interactions. [7] | `swiftui`; `uikit`; `activity`; `fragment` | ![Development](https://img.shields.io/badge/-development-blue) | +| `app.screen.visible.duration` | int | The total time, in nanoseconds, that the screen remained visible to the user. [8] | `1200`; `5500`; `700` | ![Development](https://img.shields.io/badge/-development-blue) | +| `app.start.duration` | int | The total time, in nanoseconds, taken for the application to start, from user initiation to being ready for interaction. [9] | `1000` | ![Development](https://img.shields.io/badge/-development-blue) | +| `app.start.type` | string | The type of application start, indicating the state of the app when it was initiated. [10] | `cold`; `warm` | ![Development](https://img.shields.io/badge/-development-blue) | +| `app.widget.id` | string | An identifier that uniquely differentiates this widget from other widgets in the same application. [11] | `f9bc787d-ff05-48ad-90e1-fca1d46130b3`; `submit_order_1829` | ![Development](https://img.shields.io/badge/-development-blue) | +| `app.widget.name` | string | The name of an application widget. [12] | `submit`; `attack`; `Clear Cart` | ![Development](https://img.shields.io/badge/-development-blue) | **[1] `app.installation.id`:** Its value SHOULD persist across launches of the same application installation, including through application upgrades. It SHOULD change if the application is uninstalled or if all applications of the vendor are uninstalled. @@ -50,34 +47,28 @@ More information about Android identifier best practices can be found in the [An **[2] `app.jank.frame_count`:** Depending on platform limitations, the value provided MAY be approximation. -**[3] `app.screen.depth`:** Depth represents the screen's position in the screen hierarchy tree. The root screen of the app is considered to have a depth of 0. Screens that are nested within other screens (such as in tab navigation, modals, or multi-screen flows) will have increasing depth values (1, 2, etc.). For example, a modal screen that is presented over the root screen would have a depth of 1, while a screen inside a modal might have a depth of 2. +**[3] `app.screen.first_draw.duration`:** This measures the time, in nanoseconds, until the first frame of the screen is rendered and becomes visible to the user. -**[4] `app.screen.first_appear.duration`:** This measures the time, in nanoseconds, until the first pixels of the screen are drawn and the screen becomes visible to the user. It does not necessarily mean the screen is fully interactive or that dynamic content (like images, API responses, or animations) is fully loaded. +**[4] `app.screen.id`:** A screen represents only the part of the device display drawn by the app. It typically contains multiple widgets or UI components and is larger in scope than individual widgets. Multiple screens can coexist on the same display simultaneously (e.g., split view on tablets). -**[5] `app.screen.id`:** A screen represents only the part of the device display drawn by the app. It typically contains multiple widgets or UI components and is larger in scope than individual widgets. Multiple screens can coexist on the same display simultaneously (e.g., split view on tablets). +**[5] `app.screen.load.duration`:** This attribute represents the total duration, in nanoseconds, of a screen load as experienced by the user. The screen load is considered complete when the first stable frame of the screen has been rendered. A frame is considered stable when no major layout or frame changes occur for a brief stability interval (e.g. 150 ms). -**[6] `app.screen.load.duration`:** This includes time, in nanoseconds, spent rendering the screen, waiting for dynamic content (if necessary), and ensuring the app is ready to process user input. The screen is considered "ready" once the UI is able to respond to user interactions such as taps, swipes, or gestures. +**[6] `app.screen.name`:** A screen represents only the part of the device display drawn by the app. It typically contains multiple widgets or UI components and is larger in scope than individual widgets. Multiple screens can coexist on the same display simultaneously (e.g., split view on tablets). -**[7] `app.screen.name`:** A screen represents only the part of the device display drawn by the app. It typically contains multiple widgets or UI components and is larger in scope than individual widgets. Multiple screens can coexist on the same display simultaneously (e.g., split view on tablets). +**[7] `app.screen.type`:** This attribute indicates which framework or structure is used to manage and display the screen’s content. For iOS, it may refer to either SwiftUI (declarative) or UIKit (imperative) for managing views. On Android, it can refer to either an Activity or a Fragment. -**[8] `app.screen.nodes`:** A "node" is any individual visual or interactive component contained within a screen. This includes UI elements like buttons, labels, text fields, images, containers, and static content such as images or text. +**[8] `app.screen.visible.duration`:** This attribute measures the duration during which the screen is visible and actively being displayed to the user. It begins when the screen becomes visible (e.g., `viewDidAppear` on iOS or `onResume` on Android) and ends when it is no longer visible (e.g., `viewWillDisappear` on iOS or `onPause` on Android). It does **not** include the time when the screen is in the background, nor does it account for time the screen may be obscured by other views or overlays (e.g., modals, popups, or other screens in split-view). -**[9] `app.screen.type`:** This attribute indicates which framework or structure is used to manage and display the screen’s content. For iOS, it may refer to either SwiftUI (declarative) or UIKit (imperative) for managing views. On Android, it can refer to either an Activity or a Fragment. +**[9] `app.start.duration`:** This is the time, in nanoseconds, between the user's initiation of the app start (e.g., tapping the app icon or opening a link) and the point when the app is fully ready for interaction, such as the main screen becoming visible or the app’s main functionality being accessible. -**[10] `app.screen.visible.duration`:** This attribute measures the duration during which the screen is visible and actively being displayed to the user. It begins when the screen becomes visible (e.g., `viewDidAppear` on iOS or `onResume` on Android) and ends when it is no longer visible (e.g., `viewWillDisappear` on iOS or `onPause` on Android). It does **not** include the time when the screen is in the background, nor does it account for time the screen may be obscured by other views or overlays (e.g., modals, popups, or other screens in split-view). - -**[11] `app.start.duration`:** This is the time, in nanoseconds, between the user's initiation of the app start (e.g., tapping the app icon or opening a link) and the point when the app is fully ready for interaction, such as the main screen becoming visible or the app’s main functionality being accessible. - -**[12] `app.start.type`:** Start types include: +**[10] `app.start.type`:** Start types include: - **Cold**: The app is started from a terminated state, meaning no prior instance of the app is running. - **Warm**: The app is started from the background, meaning an instance of the app is still in memory, but not active. -- **Hot**: The app is already running and brought to the foreground, meaning no re-initialization is needed. -- **Pre-Warm**: The app started uses a pre-warmed process, meaning part of the app's initialization has already been done in anticipation of the start. -**[13] `app.widget.id`:** A widget is an application component, typically an on-screen visual GUI element. +**[11] `app.widget.id`:** A widget is an application component, typically an on-screen visual GUI element. -**[14] `app.widget.name`:** A widget is an application component, typically an on-screen visual GUI element. +**[12] `app.widget.name`:** A widget is an application component, typically an on-screen visual GUI element. --- @@ -97,6 +88,4 @@ More information about Android identifier best practices can be found in the [An | Value | Description | Stability | |---|---|---| | `cold` | App start from terminated state | ![Development](https://img.shields.io/badge/-development-blue) | -| `hot` | App start from memory (already running) | ![Development](https://img.shields.io/badge/-development-blue) | -| `pre_warm` | App start using pre-warmed process | ![Development](https://img.shields.io/badge/-development-blue) | -| `warm` | App start from background state] | ![Development](https://img.shields.io/badge/-development-blue) | +| `warm` | App start from background state | ![Development](https://img.shields.io/badge/-development-blue) | diff --git a/model/app/spans.yaml b/model/app/spans.yaml index a8edf77b63..a4f6399dad 100644 --- a/model/app/spans.yaml +++ b/model/app/spans.yaml @@ -1,5 +1,5 @@ groups: - - id: span.app.screen.first_draw.client + - id: span.app.screen.first_draw.internal type: span span_kind: internal brief: This span describes the time until the first draw of an application UI screen. @@ -15,7 +15,7 @@ groups: requirement_level: required - ref: app.screen.type requirement_level: opt_in - - id: span.app.screen.load.client + - id: span.app.screen.load.internal type: span span_kind: internal brief: This span describes an application screen load operation, from navigation trigger to when the first stable frame has been rendered. From 9588637ee708f75e57fa3221501b7db76d1cbd73 Mon Sep 17 00:00:00 2001 From: Grace Lim Date: Wed, 8 Oct 2025 16:02:25 -0700 Subject: [PATCH 06/17] chore: Add doc files for new group ids --- docs/app/app-events.md | 46 ++++++++++++ docs/app/app-spans.md | 165 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 211 insertions(+) create mode 100644 docs/app/app-spans.md diff --git a/docs/app/app-events.md b/docs/app/app-events.md index 6cfe4c4431..702d7ef411 100644 --- a/docs/app/app-events.md +++ b/docs/app/app-events.md @@ -16,6 +16,7 @@ This document defines events related to client-side applications - [Event: `app.widget.click`](#event-appwidgetclick) - [Jank Event](#jank-event) - [Event: `app.jank`](#event-appjank) +- [Event: `app.screen.visible`](#event-appscreenvisible) - [Attributes](#attributes) @@ -130,6 +131,51 @@ Jank happens when the UI is rendered slowly enough for the user to experience so +## Event: `app.screen.visible` + + + + + + + + +**Status:** ![Development](https://img.shields.io/badge/-development-blue) + +The event name MUST be `app.screen.visible`. + +This event captures the duration that a screen was visible to the user, indicating the time between when the screen becomes visible and when it stops being visible. + +This event measures the screen's visibility, in nanoseconds, meaning it includes only the time the screen is actively being shown to the user. It does not include times when the app is in the background or when other screens/modal views are covering it. For example: - **iOS**: From `viewDidAppear` to `viewWillDisappear`, indicating when the screen is first shown and when it's about to disappear. - **Android**: From `onResume` to `onPause`, indicating when the screen comes to the foreground and when it goes to the background. + +| Attribute | Type | Description | Examples | [Requirement Level](https://opentelemetry.io/docs/specs/semconv/general/attribute-requirement-level/) | Stability | +|---|---|---|---|---|---| +| [`app.screen.name`](/docs/registry/attributes/app.md) | string | The name of an application screen. [1] | `MainActivity`; `ProductDetailFragment`; `ProfileView`; `ProfileViewController` | `Required` | ![Development](https://img.shields.io/badge/-development-blue) | +| [`app.screen.visible.duration`](/docs/registry/attributes/app.md) | int | The total time, in nanoseconds, that the screen remained visible to the user. [2] | `1200`; `5500`; `700` | `Required` | ![Development](https://img.shields.io/badge/-development-blue) | +| [`app.screen.type`](/docs/registry/attributes/app.md) | string | The type of UI management component or framework used to render and manage the screen's presentation and interactions. [3] | `swiftui`; `uikit`; `activity`; `fragment` | `Opt-In` | ![Development](https://img.shields.io/badge/-development-blue) | + +**[1] `app.screen.name`:** A screen represents only the part of the device display drawn by the app. It typically contains multiple widgets or UI components and is larger in scope than individual widgets. Multiple screens can coexist on the same display simultaneously (e.g., split view on tablets). + +**[2] `app.screen.visible.duration`:** This attribute measures the duration during which the screen is visible and actively being displayed to the user. It begins when the screen becomes visible (e.g., `viewDidAppear` on iOS or `onResume` on Android) and ends when it is no longer visible (e.g., `viewWillDisappear` on iOS or `onPause` on Android). It does **not** include the time when the screen is in the background, nor does it account for time the screen may be obscured by other views or overlays (e.g., modals, popups, or other screens in split-view). + +**[3] `app.screen.type`:** This attribute indicates which framework or structure is used to manage and display the screen’s content. For iOS, it may refer to either SwiftUI (declarative) or UIKit (imperative) for managing views. On Android, it can refer to either an Activity or a Fragment. + +--- + +`app.screen.type` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used. + +| Value | Description | Stability | +|---|---|---| +| `activity` | Android Activity (Android) | ![Development](https://img.shields.io/badge/-development-blue) | +| `fragment` | Android Fragment (Android) | ![Development](https://img.shields.io/badge/-development-blue) | +| `swiftui` | SwiftUI View (iOS) | ![Development](https://img.shields.io/badge/-development-blue) | +| `uikit` | UIKit ViewController (iOS) | ![Development](https://img.shields.io/badge/-development-blue) | + + + + + + ## Attributes See the [app attributes](/docs/registry/attributes/app.md) registry for all diff --git a/docs/app/app-spans.md b/docs/app/app-spans.md new file mode 100644 index 0000000000..1b70f35b32 --- /dev/null +++ b/docs/app/app-spans.md @@ -0,0 +1,165 @@ + + +# Semantic conventions for app spans + +**Status**: [Development][DocumentStatus] + + + +- [Time to first draw spans](#time-to-first-draw-spans) +- [Screen load spans](#screen-load-spans) +- [App start spans](#app-start-spans) + + + +## Time to first draw spans + + + + + + + + +**Status:** ![Development](https://img.shields.io/badge/-development-blue) + +This span describes the time until the first draw of an application UI screen. + +**Span name**: MUST be `app.screen.first_draw`. + +This span captures the time from screen initialization to the first frame drawn. + +**Span kind** SHOULD be `INTERNAL`. + +**Span status** SHOULD follow the [Recording Errors](/docs/general/recording-errors.md) document. + +| Attribute | Type | Description | Examples | [Requirement Level](https://opentelemetry.io/docs/specs/semconv/general/attribute-requirement-level/) | Stability | +|---|---|---|---|---|---| +| [`app.screen.first_draw.duration`](/docs/registry/attributes/app.md) | int | The time, in nanoseconds, from screen initialization to the first frame being rendered. [1] | `1000` | `Required` | ![Development](https://img.shields.io/badge/-development-blue) | +| [`app.screen.name`](/docs/registry/attributes/app.md) | string | The name of an application screen. [2] | `MainActivity`; `ProductDetailFragment`; `ProfileView`; `ProfileViewController` | `Required` | ![Development](https://img.shields.io/badge/-development-blue) | +| [`app.screen.type`](/docs/registry/attributes/app.md) | string | The type of UI management component or framework used to render and manage the screen's presentation and interactions. [3] | `swiftui`; `uikit`; `activity`; `fragment` | `Opt-In` | ![Development](https://img.shields.io/badge/-development-blue) | + +**[1] `app.screen.first_draw.duration`:** This measures the time, in nanoseconds, until the first frame of the screen is rendered and becomes visible to the user. + +**[2] `app.screen.name`:** A screen represents only the part of the device display drawn by the app. It typically contains multiple widgets or UI components and is larger in scope than individual widgets. Multiple screens can coexist on the same display simultaneously (e.g., split view on tablets). + +**[3] `app.screen.type`:** This attribute indicates which framework or structure is used to manage and display the screen’s content. For iOS, it may refer to either SwiftUI (declarative) or UIKit (imperative) for managing views. On Android, it can refer to either an Activity or a Fragment. + +--- + +`app.screen.type` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used. + +| Value | Description | Stability | +|---|---|---| +| `activity` | Android Activity (Android) | ![Development](https://img.shields.io/badge/-development-blue) | +| `fragment` | Android Fragment (Android) | ![Development](https://img.shields.io/badge/-development-blue) | +| `swiftui` | SwiftUI View (iOS) | ![Development](https://img.shields.io/badge/-development-blue) | +| `uikit` | UIKit ViewController (iOS) | ![Development](https://img.shields.io/badge/-development-blue) | + + + + + + +## Screen load spans + + + + + + + + +**Status:** ![Development](https://img.shields.io/badge/-development-blue) + +This span describes an application screen load operation, from navigation trigger to when the first stable frame has been rendered. + +**Span name:** MUST be `app.screen.load`. + +This span captures the time from user initiation of navigation (e.g., tapping a button) to the point when the first stable frame +of the screen has been rendered. A frame is considered stable when no major layout or frame changes occur for a brief stability +interval (e.g. 100–200 ms). + +**Span kind** SHOULD be `INTERNAL`. + +**Span status** SHOULD follow the [Recording Errors](/docs/general/recording-errors.md) document. + +| Attribute | Type | Description | Examples | [Requirement Level](https://opentelemetry.io/docs/specs/semconv/general/attribute-requirement-level/) | Stability | +|---|---|---|---|---|---| +| [`app.screen.load.duration`](/docs/registry/attributes/app.md) | int | The time taken, in nanoseconds, for a screen to load and become stable, measured from when the screen begins appearing until the first stable frame has been rendered. [1] | `1000` | `Required` | ![Development](https://img.shields.io/badge/-development-blue) | +| [`app.screen.name`](/docs/registry/attributes/app.md) | string | The name of an application screen. [2] | `MainActivity`; `ProductDetailFragment`; `ProfileView`; `ProfileViewController` | `Required` | ![Development](https://img.shields.io/badge/-development-blue) | +| [`app.screen.type`](/docs/registry/attributes/app.md) | string | The type of UI management component or framework used to render and manage the screen's presentation and interactions. [3] | `swiftui`; `uikit`; `activity`; `fragment` | `Opt-In` | ![Development](https://img.shields.io/badge/-development-blue) | + +**[1] `app.screen.load.duration`:** This attribute represents the total duration, in nanoseconds, of a screen load as experienced by the user. The screen load is considered complete when the first stable frame of the screen has been rendered. A frame is considered stable when no major layout or frame changes occur for a brief stability interval (e.g. 150 ms). + +**[2] `app.screen.name`:** A screen represents only the part of the device display drawn by the app. It typically contains multiple widgets or UI components and is larger in scope than individual widgets. Multiple screens can coexist on the same display simultaneously (e.g., split view on tablets). + +**[3] `app.screen.type`:** This attribute indicates which framework or structure is used to manage and display the screen’s content. For iOS, it may refer to either SwiftUI (declarative) or UIKit (imperative) for managing views. On Android, it can refer to either an Activity or a Fragment. + +--- + +`app.screen.type` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used. + +| Value | Description | Stability | +|---|---|---| +| `activity` | Android Activity (Android) | ![Development](https://img.shields.io/badge/-development-blue) | +| `fragment` | Android Fragment (Android) | ![Development](https://img.shields.io/badge/-development-blue) | +| `swiftui` | SwiftUI View (iOS) | ![Development](https://img.shields.io/badge/-development-blue) | +| `uikit` | UIKit ViewController (iOS) | ![Development](https://img.shields.io/badge/-development-blue) | + + + + + + +## App start spans + + + + + + + + +**Status:** ![Development](https://img.shields.io/badge/-development-blue) + +This span represents an application start operation. + +**Span name:** MUST be `AppStart`. + +**Span kind** MUST be `CLIENT`. + +This span captures the time from user initiation (e.g., tapping the app icon or opening a link) +to the moment the app is ready for interaction. + +**Span status** SHOULD follow the [Recording Errors](/docs/general/recording-errors.md) document. + +| Attribute | Type | Description | Examples | [Requirement Level](https://opentelemetry.io/docs/specs/semconv/general/attribute-requirement-level/) | Stability | +|---|---|---|---|---|---| +| [`app.start.duration`](/docs/registry/attributes/app.md) | int | The total time, in nanoseconds, taken for the application to start, from user initiation to being ready for interaction. [1] | `1000` | `Required` | ![Development](https://img.shields.io/badge/-development-blue) | +| [`app.start.type`](/docs/registry/attributes/app.md) | string | The type of application start, indicating the state of the app when it was initiated. [2] | `cold`; `warm` | `Required` | ![Development](https://img.shields.io/badge/-development-blue) | + +**[1] `app.start.duration`:** This is the time, in nanoseconds, between the user's initiation of the app start (e.g., tapping the app icon or opening a link) and the point when the app is fully ready for interaction, such as the main screen becoming visible or the app’s main functionality being accessible. + +**[2] `app.start.type`:** Start types include: + +- **Cold**: The app is started from a terminated state, meaning no prior instance of the app is running. +- **Warm**: The app is started from the background, meaning an instance of the app is still in memory, but not active. + +--- + +`app.start.type` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used. + +| Value | Description | Stability | +|---|---|---| +| `cold` | App start from terminated state | ![Development](https://img.shields.io/badge/-development-blue) | +| `warm` | App start from background state | ![Development](https://img.shields.io/badge/-development-blue) | + + + + + + +[DocumentStatus]: https://opentelemetry.io/docs/specs/otel/document-status From 10189ab5d8243b711b75e6975e1030e032251fd8 Mon Sep 17 00:00:00 2001 From: Grace Lim Date: Wed, 8 Oct 2025 16:03:28 -0700 Subject: [PATCH 07/17] fix: Update changlog note with latest --- .chloggen/feat_app-spans.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.chloggen/feat_app-spans.yaml b/.chloggen/feat_app-spans.yaml index e463b0f58e..84668298f8 100644 --- a/.chloggen/feat_app-spans.yaml +++ b/.chloggen/feat_app-spans.yaml @@ -10,7 +10,7 @@ change_type: enhancement component: app # A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). -note: Add spans for app launch, app screen load, app time to first appear +note: Add spans for app start, app screen load, app time to first draw # Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists. # The values here must be integers. From f17367e542822e5295bf88f3ba54b6f990e40fc1 Mon Sep 17 00:00:00 2001 From: Grace Lim Date: Wed, 8 Oct 2025 16:15:45 -0700 Subject: [PATCH 08/17] fix: Remove trailing space to resolve lint failure --- model/app/events.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/model/app/events.yaml b/model/app/events.yaml index c9a0c335f1..2ccc5a11de 100644 --- a/model/app/events.yaml +++ b/model/app/events.yaml @@ -74,7 +74,6 @@ groups: It does not include times when the app is in the background or when other screens/modal views are covering it. For example: - **iOS**: From `viewDidAppear` to `viewWillDisappear`, indicating when the screen is first shown and when it's about to disappear. - **Android**: From `onResume` to `onPause`, indicating when the screen comes to the foreground and when it goes to the background. - attributes: - ref: app.screen.name requirement_level: required From 2ca333801d7dbe175711d4b33b6dc39e44445189 Mon Sep 17 00:00:00 2001 From: Grace Lim Date: Wed, 8 Oct 2025 16:27:46 -0700 Subject: [PATCH 09/17] fix: Update docs to sections to indicate singular span --- docs/app/app-spans.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/app/app-spans.md b/docs/app/app-spans.md index 1b70f35b32..17f2dd13e4 100644 --- a/docs/app/app-spans.md +++ b/docs/app/app-spans.md @@ -8,13 +8,13 @@ linkTitle: App spans -- [Time to first draw spans](#time-to-first-draw-spans) -- [Screen load spans](#screen-load-spans) -- [App start spans](#app-start-spans) +- [Time to first draw span](#time-to-first-draw-span) +- [Screen load span](#screen-load-span) +- [App start span](#app-start-span) -## Time to first draw spans +## Time to first draw span @@ -63,7 +63,7 @@ This span captures the time from screen initialization to the first frame drawn. -## Screen load spans +## Screen load span @@ -114,7 +114,7 @@ interval (e.g. 100–200 ms). -## App start spans +## App start span From 395004f7198b87e3861c667ee464c641e311645f Mon Sep 17 00:00:00 2001 From: Grace Lim Date: Wed, 8 Oct 2025 16:32:14 -0700 Subject: [PATCH 10/17] fix: Update brief stability interval example to 150 ms in span def --- docs/app/app-spans.md | 4 ++-- model/app/spans.yaml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/app/app-spans.md b/docs/app/app-spans.md index 17f2dd13e4..6fbc9d506c 100644 --- a/docs/app/app-spans.md +++ b/docs/app/app-spans.md @@ -78,9 +78,9 @@ This span describes an application screen load operation, from navigation trigge **Span name:** MUST be `app.screen.load`. -This span captures the time from user initiation of navigation (e.g., tapping a button) to the point when the first stable frame +This span captures the time from user initiation of naigation (e.g., tapping a button) to the point when the first stable frame of the screen has been rendered. A frame is considered stable when no major layout or frame changes occur for a brief stability -interval (e.g. 100–200 ms). +interval (e.g. 150 ms). **Span kind** SHOULD be `INTERNAL`. diff --git a/model/app/spans.yaml b/model/app/spans.yaml index a4f6399dad..3bf7f8d5a7 100644 --- a/model/app/spans.yaml +++ b/model/app/spans.yaml @@ -22,9 +22,9 @@ groups: note: | **Span name:** MUST be `app.screen.load`. - This span captures the time from user initiation of navigation (e.g., tapping a button) to the point when the first stable frame + This span captures the time from user initiation of naigation (e.g., tapping a button) to the point when the first stable frame of the screen has been rendered. A frame is considered stable when no major layout or frame changes occur for a brief stability - interval (e.g. 100–200 ms). + interval (e.g. 150 ms). stability: development attributes: - ref: app.screen.name From f54572da9e402102566af48ca97d764e716eb586 Mon Sep 17 00:00:00 2001 From: Grace Lim Date: Thu, 16 Oct 2025 18:15:23 -0700 Subject: [PATCH 11/17] fix: Remove screen load span, other fixes to align with standard sevConv units --- docs/app/app-events.md | 25 ++++---- docs/app/app-spans.md | 103 +++++++++----------------------- docs/registry/attributes/app.md | 46 +++++++------- model/app/events.yaml | 12 ++-- model/app/registry.yaml | 47 +++++---------- model/app/spans.yaml | 43 +++++-------- 6 files changed, 100 insertions(+), 176 deletions(-) diff --git a/docs/app/app-events.md b/docs/app/app-events.md index 702d7ef411..e14deca995 100644 --- a/docs/app/app-events.md +++ b/docs/app/app-events.md @@ -16,7 +16,7 @@ This document defines events related to client-side applications - [Event: `app.widget.click`](#event-appwidgetclick) - [Jank Event](#jank-event) - [Event: `app.jank`](#event-appjank) -- [Event: `app.screen.visible`](#event-appscreenvisible) +- [Event: `app.screen.time_on_screen`](#event-appscreentime_on_screen) - [Attributes](#attributes) @@ -131,9 +131,9 @@ Jank happens when the UI is rendered slowly enough for the user to experience so -## Event: `app.screen.visible` +## Event: `app.screen.time_on_screen` - + @@ -142,23 +142,26 @@ Jank happens when the UI is rendered slowly enough for the user to experience so **Status:** ![Development](https://img.shields.io/badge/-development-blue) -The event name MUST be `app.screen.visible`. +The event name MUST be `app.screen.time_on_screen`. This event captures the duration that a screen was visible to the user, indicating the time between when the screen becomes visible and when it stops being visible. -This event measures the screen's visibility, in nanoseconds, meaning it includes only the time the screen is actively being shown to the user. It does not include times when the app is in the background or when other screens/modal views are covering it. For example: - **iOS**: From `viewDidAppear` to `viewWillDisappear`, indicating when the screen is first shown and when it's about to disappear. - **Android**: From `onResume` to `onPause`, indicating when the screen comes to the foreground and when it goes to the background. +This event measures the screen's visibility, in seconds, meaning it includes only the time the screen is actively being shown to the user. It does not include times when the app is in the background or when other screens/modal views are covering it. For example: - **iOS**: From `viewDidAppear` to `viewWillDisappear`, indicating when the screen is first shown and when it's about to disappear. - **Android**: From `onResume` to `onPause`, indicating when the screen comes to the foreground and when it goes to the background. | Attribute | Type | Description | Examples | [Requirement Level](https://opentelemetry.io/docs/specs/semconv/general/attribute-requirement-level/) | Stability | |---|---|---|---|---|---| -| [`app.screen.name`](/docs/registry/attributes/app.md) | string | The name of an application screen. [1] | `MainActivity`; `ProductDetailFragment`; `ProfileView`; `ProfileViewController` | `Required` | ![Development](https://img.shields.io/badge/-development-blue) | -| [`app.screen.visible.duration`](/docs/registry/attributes/app.md) | int | The total time, in nanoseconds, that the screen remained visible to the user. [2] | `1200`; `5500`; `700` | `Required` | ![Development](https://img.shields.io/badge/-development-blue) | -| [`app.screen.type`](/docs/registry/attributes/app.md) | string | The type of UI management component or framework used to render and manage the screen's presentation and interactions. [3] | `swiftui`; `uikit`; `activity`; `fragment` | `Opt-In` | ![Development](https://img.shields.io/badge/-development-blue) | +| [`app.screen.time_on_screen.duration`](/docs/registry/attributes/app.md) | double | The total time, in seconds, that the screen remained visible to the user. [1] | `30.0`; `10.21` | `Required` | ![Development](https://img.shields.io/badge/-development-blue) | +| [`app.screen.id`](/docs/registry/attributes/app.md) | string | An identifier that uniquely differentiates this screen from other screens in the same application. [2] | `f9bc787d-ff05-48ad-90e1-fca1d46130b3`; `com.example.app.MainActivity`; `com.example.shop.ProductDetailFragment`; `MyApp.ProfileView`; `MyApp.ProfileViewController` | `Recommended` | ![Development](https://img.shields.io/badge/-development-blue) | +| [`app.screen.name`](/docs/registry/attributes/app.md) | string | The name of an application screen. [3] | `MainActivity`; `ProductDetailFragment`; `ProfileView`; `ProfileViewController` | `Opt-In` | ![Development](https://img.shields.io/badge/-development-blue) | +| [`app.screen.type`](/docs/registry/attributes/app.md) | string | The type of UI management component or framework used to render and manage the screen's presentation and interactions. [4] | `swiftui`; `uikit`; `activity`; `fragment` | `Opt-In` | ![Development](https://img.shields.io/badge/-development-blue) | -**[1] `app.screen.name`:** A screen represents only the part of the device display drawn by the app. It typically contains multiple widgets or UI components and is larger in scope than individual widgets. Multiple screens can coexist on the same display simultaneously (e.g., split view on tablets). +**[1] `app.screen.time_on_screen.duration`:** This attribute measures the duration during which the screen is visible and actively being displayed to the user. It begins when the screen becomes visible (e.g., `viewDidAppear` on iOS or `onResume` on Android) and ends when it is no longer visible (e.g., `viewWillDisappear` on iOS or `onPause` on Android). It does **not** include the time when the screen is in the background, nor does it account for time the screen may be obscured by other views or overlays (e.g., modals, popups, or other screens in split-view). -**[2] `app.screen.visible.duration`:** This attribute measures the duration during which the screen is visible and actively being displayed to the user. It begins when the screen becomes visible (e.g., `viewDidAppear` on iOS or `onResume` on Android) and ends when it is no longer visible (e.g., `viewWillDisappear` on iOS or `onPause` on Android). It does **not** include the time when the screen is in the background, nor does it account for time the screen may be obscured by other views or overlays (e.g., modals, popups, or other screens in split-view). +**[2] `app.screen.id`:** A screen represents only the part of the device display drawn by the app. It typically contains multiple widgets or UI components and is larger in scope than individual widgets. Multiple screens can coexist on the same display simultaneously (e.g., split view on tablets). + +**[3] `app.screen.name`:** A screen represents only the part of the device display drawn by the app. It typically contains multiple widgets or UI components and is larger in scope than individual widgets. Multiple screens can coexist on the same display simultaneously (e.g., split view on tablets). -**[3] `app.screen.type`:** This attribute indicates which framework or structure is used to manage and display the screen’s content. For iOS, it may refer to either SwiftUI (declarative) or UIKit (imperative) for managing views. On Android, it can refer to either an Activity or a Fragment. +**[4] `app.screen.type`:** This attribute indicates which framework or structure is used to manage and display the screen’s content. For iOS, it may refer to either SwiftUI (declarative) or UIKit (imperative) for managing views. On Android, it can refer to either an Activity or a Fragment. --- diff --git a/docs/app/app-spans.md b/docs/app/app-spans.md index 6fbc9d506c..5db17db368 100644 --- a/docs/app/app-spans.md +++ b/docs/app/app-spans.md @@ -9,14 +9,13 @@ linkTitle: App spans - [Time to first draw span](#time-to-first-draw-span) -- [Screen load span](#screen-load-span) - [App start span](#app-start-span) ## Time to first draw span - + @@ -25,78 +24,31 @@ linkTitle: App spans **Status:** ![Development](https://img.shields.io/badge/-development-blue) -This span describes the time until the first draw of an application UI screen. +This span represents an application screen first draw operation. -**Span name**: MUST be `app.screen.first_draw`. +**Span name**: MUST be `app.screen.time_to_first_draw`. -This span captures the time from screen initialization to the first frame drawn. +**Span kind** MUST be `INTERNAL`. -**Span kind** SHOULD be `INTERNAL`. +This span captures the time from screen initialization to the first frame +of an application UI screen being drawn. **Span status** SHOULD follow the [Recording Errors](/docs/general/recording-errors.md) document. | Attribute | Type | Description | Examples | [Requirement Level](https://opentelemetry.io/docs/specs/semconv/general/attribute-requirement-level/) | Stability | |---|---|---|---|---|---| -| [`app.screen.first_draw.duration`](/docs/registry/attributes/app.md) | int | The time, in nanoseconds, from screen initialization to the first frame being rendered. [1] | `1000` | `Required` | ![Development](https://img.shields.io/badge/-development-blue) | -| [`app.screen.name`](/docs/registry/attributes/app.md) | string | The name of an application screen. [2] | `MainActivity`; `ProductDetailFragment`; `ProfileView`; `ProfileViewController` | `Required` | ![Development](https://img.shields.io/badge/-development-blue) | -| [`app.screen.type`](/docs/registry/attributes/app.md) | string | The type of UI management component or framework used to render and manage the screen's presentation and interactions. [3] | `swiftui`; `uikit`; `activity`; `fragment` | `Opt-In` | ![Development](https://img.shields.io/badge/-development-blue) | +| [`app.screen.time_to_first_draw.duration`](/docs/registry/attributes/app.md) | double | The time, in seconds, from screen initialization to the first frame being rendered. [1] | `0.95`; `2.0` | `Required` | ![Development](https://img.shields.io/badge/-development-blue) | +| [`app.screen.id`](/docs/registry/attributes/app.md) | string | An identifier that uniquely differentiates this screen from other screens in the same application. [2] | `f9bc787d-ff05-48ad-90e1-fca1d46130b3`; `com.example.app.MainActivity`; `com.example.shop.ProductDetailFragment`; `MyApp.ProfileView`; `MyApp.ProfileViewController` | `Recommended` | ![Development](https://img.shields.io/badge/-development-blue) | +| [`app.screen.name`](/docs/registry/attributes/app.md) | string | The name of an application screen. [3] | `MainActivity`; `ProductDetailFragment`; `ProfileView`; `ProfileViewController` | `Opt-In` | ![Development](https://img.shields.io/badge/-development-blue) | +| [`app.screen.type`](/docs/registry/attributes/app.md) | string | The type of UI management component or framework used to render and manage the screen's presentation and interactions. [4] | `swiftui`; `uikit`; `activity`; `fragment` | `Opt-In` | ![Development](https://img.shields.io/badge/-development-blue) | -**[1] `app.screen.first_draw.duration`:** This measures the time, in nanoseconds, until the first frame of the screen is rendered and becomes visible to the user. +**[1] `app.screen.time_to_first_draw.duration`:** This measures the time, in seconds, until the first frame of the screen is rendered and becomes visible to the user. -**[2] `app.screen.name`:** A screen represents only the part of the device display drawn by the app. It typically contains multiple widgets or UI components and is larger in scope than individual widgets. Multiple screens can coexist on the same display simultaneously (e.g., split view on tablets). +**[2] `app.screen.id`:** A screen represents only the part of the device display drawn by the app. It typically contains multiple widgets or UI components and is larger in scope than individual widgets. Multiple screens can coexist on the same display simultaneously (e.g., split view on tablets). -**[3] `app.screen.type`:** This attribute indicates which framework or structure is used to manage and display the screen’s content. For iOS, it may refer to either SwiftUI (declarative) or UIKit (imperative) for managing views. On Android, it can refer to either an Activity or a Fragment. +**[3] `app.screen.name`:** A screen represents only the part of the device display drawn by the app. It typically contains multiple widgets or UI components and is larger in scope than individual widgets. Multiple screens can coexist on the same display simultaneously (e.g., split view on tablets). ---- - -`app.screen.type` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used. - -| Value | Description | Stability | -|---|---|---| -| `activity` | Android Activity (Android) | ![Development](https://img.shields.io/badge/-development-blue) | -| `fragment` | Android Fragment (Android) | ![Development](https://img.shields.io/badge/-development-blue) | -| `swiftui` | SwiftUI View (iOS) | ![Development](https://img.shields.io/badge/-development-blue) | -| `uikit` | UIKit ViewController (iOS) | ![Development](https://img.shields.io/badge/-development-blue) | - - - - - - -## Screen load span - - - - - - - - -**Status:** ![Development](https://img.shields.io/badge/-development-blue) - -This span describes an application screen load operation, from navigation trigger to when the first stable frame has been rendered. - -**Span name:** MUST be `app.screen.load`. - -This span captures the time from user initiation of naigation (e.g., tapping a button) to the point when the first stable frame -of the screen has been rendered. A frame is considered stable when no major layout or frame changes occur for a brief stability -interval (e.g. 150 ms). - -**Span kind** SHOULD be `INTERNAL`. - -**Span status** SHOULD follow the [Recording Errors](/docs/general/recording-errors.md) document. - -| Attribute | Type | Description | Examples | [Requirement Level](https://opentelemetry.io/docs/specs/semconv/general/attribute-requirement-level/) | Stability | -|---|---|---|---|---|---| -| [`app.screen.load.duration`](/docs/registry/attributes/app.md) | int | The time taken, in nanoseconds, for a screen to load and become stable, measured from when the screen begins appearing until the first stable frame has been rendered. [1] | `1000` | `Required` | ![Development](https://img.shields.io/badge/-development-blue) | -| [`app.screen.name`](/docs/registry/attributes/app.md) | string | The name of an application screen. [2] | `MainActivity`; `ProductDetailFragment`; `ProfileView`; `ProfileViewController` | `Required` | ![Development](https://img.shields.io/badge/-development-blue) | -| [`app.screen.type`](/docs/registry/attributes/app.md) | string | The type of UI management component or framework used to render and manage the screen's presentation and interactions. [3] | `swiftui`; `uikit`; `activity`; `fragment` | `Opt-In` | ![Development](https://img.shields.io/badge/-development-blue) | - -**[1] `app.screen.load.duration`:** This attribute represents the total duration, in nanoseconds, of a screen load as experienced by the user. The screen load is considered complete when the first stable frame of the screen has been rendered. A frame is considered stable when no major layout or frame changes occur for a brief stability interval (e.g. 150 ms). - -**[2] `app.screen.name`:** A screen represents only the part of the device display drawn by the app. It typically contains multiple widgets or UI components and is larger in scope than individual widgets. Multiple screens can coexist on the same display simultaneously (e.g., split view on tablets). - -**[3] `app.screen.type`:** This attribute indicates which framework or structure is used to manage and display the screen’s content. For iOS, it may refer to either SwiftUI (declarative) or UIKit (imperative) for managing views. On Android, it can refer to either an Activity or a Fragment. +**[4] `app.screen.type`:** This attribute indicates which framework or structure is used to manage and display the screen’s content. For iOS, it may refer to either SwiftUI (declarative) or UIKit (imperative) for managing views. On Android, it can refer to either an Activity or a Fragment. --- @@ -116,7 +68,7 @@ interval (e.g. 150 ms). ## App start span - + @@ -127,26 +79,21 @@ interval (e.g. 150 ms). This span represents an application start operation. -**Span name:** MUST be `AppStart`. +**Span name:** MUST be `app.start`. -**Span kind** MUST be `CLIENT`. +**Span kind** MUST be `INTERNAL`. This span captures the time from user initiation (e.g., tapping the app icon or opening a link) -to the moment the app is ready for interaction. +to the moment the app begins UI rendering. **Span status** SHOULD follow the [Recording Errors](/docs/general/recording-errors.md) document. | Attribute | Type | Description | Examples | [Requirement Level](https://opentelemetry.io/docs/specs/semconv/general/attribute-requirement-level/) | Stability | |---|---|---|---|---|---| -| [`app.start.duration`](/docs/registry/attributes/app.md) | int | The total time, in nanoseconds, taken for the application to start, from user initiation to being ready for interaction. [1] | `1000` | `Required` | ![Development](https://img.shields.io/badge/-development-blue) | -| [`app.start.type`](/docs/registry/attributes/app.md) | string | The type of application start, indicating the state of the app when it was initiated. [2] | `cold`; `warm` | `Required` | ![Development](https://img.shields.io/badge/-development-blue) | - -**[1] `app.start.duration`:** This is the time, in nanoseconds, between the user's initiation of the app start (e.g., tapping the app icon or opening a link) and the point when the app is fully ready for interaction, such as the main screen becoming visible or the app’s main functionality being accessible. - -**[2] `app.start.type`:** Start types include: +| [`app.start.duration`](/docs/registry/attributes/app.md) | double | The total time, in seconds, taken for the application to start, from user initiation to being ready for interaction. [1] | `0.95`; `2.0` | `Required` | ![Development](https://img.shields.io/badge/-development-blue) | +| [`app.start.type`](/docs/registry/attributes/app.md) | string | The type of application start, indicating the state of the app when it was initiated. | `cold`; `warm` | `Required` | ![Development](https://img.shields.io/badge/-development-blue) | -- **Cold**: The app is started from a terminated state, meaning no prior instance of the app is running. -- **Warm**: The app is started from the background, meaning an instance of the app is still in memory, but not active. +**[1] `app.start.duration`:** This is the time, in seconds, between the user's initiation of the app start (e.g., tapping the app icon or opening a link) and the point when the app is fully ready for interaction, such as the main screen becoming visible or the app’s main functionality being accessible. --- @@ -154,8 +101,12 @@ to the moment the app is ready for interaction. | Value | Description | Stability | |---|---|---| -| `cold` | App start from terminated state | ![Development](https://img.shields.io/badge/-development-blue) | -| `warm` | App start from background state | ![Development](https://img.shields.io/badge/-development-blue) | +| `cold` | App start from terminated state [2] | ![Development](https://img.shields.io/badge/-development-blue) | +| `warm` | App start from background state [3] | ![Development](https://img.shields.io/badge/-development-blue) | + +**[2]:** The app is started from a terminated state, meaning no prior instance of the app is running. + +**[3]:** The app is started from the background, meaning an instance of the app is still in memory, but not active. diff --git a/docs/registry/attributes/app.md b/docs/registry/attributes/app.md index c8a18568c9..37f85c4c83 100644 --- a/docs/registry/attributes/app.md +++ b/docs/registry/attributes/app.md @@ -16,16 +16,15 @@ Describes attributes related to client-side applications (e.g. web apps or mobil | `app.jank.threshold` | double | The minimum rendering threshold for this jank, in seconds. | `0.016`; `0.7`; `1.024` | ![Development](https://img.shields.io/badge/-development-blue) | | `app.screen.coordinate.x` | int | The x (horizontal) coordinate of a screen coordinate, in screen pixels. | `0`; `131` | ![Development](https://img.shields.io/badge/-development-blue) | | `app.screen.coordinate.y` | int | The y (vertical) component of a screen coordinate, in screen pixels. | `12`; `99` | ![Development](https://img.shields.io/badge/-development-blue) | -| `app.screen.first_draw.duration` | int | The time, in nanoseconds, from screen initialization to the first frame being rendered. [3] | `1000` | ![Development](https://img.shields.io/badge/-development-blue) | -| `app.screen.id` | string | An identifier that uniquely differentiates this screen from other screens in the same application. [4] | `f9bc787d-ff05-48ad-90e1-fca1d46130b3`; `com.example.app.MainActivity`; `com.example.shop.ProductDetailFragment`; `MyApp.ProfileView`; `MyApp.ProfileViewController` | ![Development](https://img.shields.io/badge/-development-blue) | -| `app.screen.load.duration` | int | The time taken, in nanoseconds, for a screen to load and become stable, measured from when the screen begins appearing until the first stable frame has been rendered. [5] | `1000` | ![Development](https://img.shields.io/badge/-development-blue) | -| `app.screen.name` | string | The name of an application screen. [6] | `MainActivity`; `ProductDetailFragment`; `ProfileView`; `ProfileViewController` | ![Development](https://img.shields.io/badge/-development-blue) | +| `app.screen.id` | string | An identifier that uniquely differentiates this screen from other screens in the same application. [3] | `f9bc787d-ff05-48ad-90e1-fca1d46130b3`; `com.example.app.MainActivity`; `com.example.shop.ProductDetailFragment`; `MyApp.ProfileView`; `MyApp.ProfileViewController` | ![Development](https://img.shields.io/badge/-development-blue) | +| `app.screen.name` | string | The name of an application screen. [4] | `MainActivity`; `ProductDetailFragment`; `ProfileView`; `ProfileViewController` | ![Development](https://img.shields.io/badge/-development-blue) | +| `app.screen.time_on_screen.duration` | double | The total time, in seconds, that the screen remained visible to the user. [5] | `30.0`; `10.21` | ![Development](https://img.shields.io/badge/-development-blue) | +| `app.screen.time_to_first_draw.duration` | double | The time, in seconds, from screen initialization to the first frame being rendered. [6] | `0.95`; `2.0` | ![Development](https://img.shields.io/badge/-development-blue) | | `app.screen.type` | string | The type of UI management component or framework used to render and manage the screen's presentation and interactions. [7] | `swiftui`; `uikit`; `activity`; `fragment` | ![Development](https://img.shields.io/badge/-development-blue) | -| `app.screen.visible.duration` | int | The total time, in nanoseconds, that the screen remained visible to the user. [8] | `1200`; `5500`; `700` | ![Development](https://img.shields.io/badge/-development-blue) | -| `app.start.duration` | int | The total time, in nanoseconds, taken for the application to start, from user initiation to being ready for interaction. [9] | `1000` | ![Development](https://img.shields.io/badge/-development-blue) | -| `app.start.type` | string | The type of application start, indicating the state of the app when it was initiated. [10] | `cold`; `warm` | ![Development](https://img.shields.io/badge/-development-blue) | -| `app.widget.id` | string | An identifier that uniquely differentiates this widget from other widgets in the same application. [11] | `f9bc787d-ff05-48ad-90e1-fca1d46130b3`; `submit_order_1829` | ![Development](https://img.shields.io/badge/-development-blue) | -| `app.widget.name` | string | The name of an application widget. [12] | `submit`; `attack`; `Clear Cart` | ![Development](https://img.shields.io/badge/-development-blue) | +| `app.start.duration` | double | The total time, in seconds, taken for the application to start, from user initiation to being ready for interaction. [8] | `0.95`; `2.0` | ![Development](https://img.shields.io/badge/-development-blue) | +| `app.start.type` | string | The type of application start, indicating the state of the app when it was initiated. | `cold`; `warm` | ![Development](https://img.shields.io/badge/-development-blue) | +| `app.widget.id` | string | An identifier that uniquely differentiates this widget from other widgets in the same application. [9] | `f9bc787d-ff05-48ad-90e1-fca1d46130b3`; `submit_order_1829` | ![Development](https://img.shields.io/badge/-development-blue) | +| `app.widget.name` | string | The name of an application widget. [10] | `submit`; `attack`; `Clear Cart` | ![Development](https://img.shields.io/badge/-development-blue) | **[1] `app.installation.id`:** Its value SHOULD persist across launches of the same application installation, including through application upgrades. It SHOULD change if the application is uninstalled or if all applications of the vendor are uninstalled. @@ -47,28 +46,21 @@ More information about Android identifier best practices can be found in the [An **[2] `app.jank.frame_count`:** Depending on platform limitations, the value provided MAY be approximation. -**[3] `app.screen.first_draw.duration`:** This measures the time, in nanoseconds, until the first frame of the screen is rendered and becomes visible to the user. +**[3] `app.screen.id`:** A screen represents only the part of the device display drawn by the app. It typically contains multiple widgets or UI components and is larger in scope than individual widgets. Multiple screens can coexist on the same display simultaneously (e.g., split view on tablets). -**[4] `app.screen.id`:** A screen represents only the part of the device display drawn by the app. It typically contains multiple widgets or UI components and is larger in scope than individual widgets. Multiple screens can coexist on the same display simultaneously (e.g., split view on tablets). +**[4] `app.screen.name`:** A screen represents only the part of the device display drawn by the app. It typically contains multiple widgets or UI components and is larger in scope than individual widgets. Multiple screens can coexist on the same display simultaneously (e.g., split view on tablets). -**[5] `app.screen.load.duration`:** This attribute represents the total duration, in nanoseconds, of a screen load as experienced by the user. The screen load is considered complete when the first stable frame of the screen has been rendered. A frame is considered stable when no major layout or frame changes occur for a brief stability interval (e.g. 150 ms). +**[5] `app.screen.time_on_screen.duration`:** This attribute measures the duration during which the screen is visible and actively being displayed to the user. It begins when the screen becomes visible (e.g., `viewDidAppear` on iOS or `onResume` on Android) and ends when it is no longer visible (e.g., `viewWillDisappear` on iOS or `onPause` on Android). It does **not** include the time when the screen is in the background, nor does it account for time the screen may be obscured by other views or overlays (e.g., modals, popups, or other screens in split-view). -**[6] `app.screen.name`:** A screen represents only the part of the device display drawn by the app. It typically contains multiple widgets or UI components and is larger in scope than individual widgets. Multiple screens can coexist on the same display simultaneously (e.g., split view on tablets). +**[6] `app.screen.time_to_first_draw.duration`:** This measures the time, in seconds, until the first frame of the screen is rendered and becomes visible to the user. **[7] `app.screen.type`:** This attribute indicates which framework or structure is used to manage and display the screen’s content. For iOS, it may refer to either SwiftUI (declarative) or UIKit (imperative) for managing views. On Android, it can refer to either an Activity or a Fragment. -**[8] `app.screen.visible.duration`:** This attribute measures the duration during which the screen is visible and actively being displayed to the user. It begins when the screen becomes visible (e.g., `viewDidAppear` on iOS or `onResume` on Android) and ends when it is no longer visible (e.g., `viewWillDisappear` on iOS or `onPause` on Android). It does **not** include the time when the screen is in the background, nor does it account for time the screen may be obscured by other views or overlays (e.g., modals, popups, or other screens in split-view). +**[8] `app.start.duration`:** This is the time, in seconds, between the user's initiation of the app start (e.g., tapping the app icon or opening a link) and the point when the app is fully ready for interaction, such as the main screen becoming visible or the app’s main functionality being accessible. -**[9] `app.start.duration`:** This is the time, in nanoseconds, between the user's initiation of the app start (e.g., tapping the app icon or opening a link) and the point when the app is fully ready for interaction, such as the main screen becoming visible or the app’s main functionality being accessible. +**[9] `app.widget.id`:** A widget is an application component, typically an on-screen visual GUI element. -**[10] `app.start.type`:** Start types include: - -- **Cold**: The app is started from a terminated state, meaning no prior instance of the app is running. -- **Warm**: The app is started from the background, meaning an instance of the app is still in memory, but not active. - -**[11] `app.widget.id`:** A widget is an application component, typically an on-screen visual GUI element. - -**[12] `app.widget.name`:** A widget is an application component, typically an on-screen visual GUI element. +**[10] `app.widget.name`:** A widget is an application component, typically an on-screen visual GUI element. --- @@ -87,5 +79,9 @@ More information about Android identifier best practices can be found in the [An | Value | Description | Stability | |---|---|---| -| `cold` | App start from terminated state | ![Development](https://img.shields.io/badge/-development-blue) | -| `warm` | App start from background state | ![Development](https://img.shields.io/badge/-development-blue) | +| `cold` | App start from terminated state [11] | ![Development](https://img.shields.io/badge/-development-blue) | +| `warm` | App start from background state [12] | ![Development](https://img.shields.io/badge/-development-blue) | + +**[11]:** The app is started from a terminated state, meaning no prior instance of the app is running. + +**[12]:** The app is started from the background, meaning an instance of the app is still in memory, but not active. diff --git a/model/app/events.yaml b/model/app/events.yaml index 2ccc5a11de..30ae1f3f84 100644 --- a/model/app/events.yaml +++ b/model/app/events.yaml @@ -62,22 +62,24 @@ groups: requirement_level: recommended - ref: app.jank.period requirement_level: recommended - - id: event.app.screen.visible + - id: event.app.screen.time_on_screen stability: development type: event - name: app.screen.visible + name: app.screen.time_on_screen brief: > This event captures the duration that a screen was visible to the user, indicating the time between when the screen becomes visible and when it stops being visible. note: > - This event measures the screen's visibility, in nanoseconds, meaning it includes only the time the screen is actively being shown to the user. + This event measures the screen's visibility, in seconds, meaning it includes only the time the screen is actively being shown to the user. It does not include times when the app is in the background or when other screens/modal views are covering it. For example: - **iOS**: From `viewDidAppear` to `viewWillDisappear`, indicating when the screen is first shown and when it's about to disappear. - **Android**: From `onResume` to `onPause`, indicating when the screen comes to the foreground and when it goes to the background. attributes: + - ref: app.screen.id + requirement_level: recommended - ref: app.screen.name - requirement_level: required + requirement_level: opt_in - ref: app.screen.type requirement_level: opt_in - - ref: app.screen.visible.duration + - ref: app.screen.time_on_screen.duration requirement_level: required diff --git a/model/app/registry.yaml b/model/app/registry.yaml index 8e9e0ff0cb..1abd5b880e 100644 --- a/model/app/registry.yaml +++ b/model/app/registry.yaml @@ -86,26 +86,15 @@ groups: is larger in scope than individual widgets. Multiple screens can coexist on the same display simultaneously (e.g., split view on tablets). examples: ["MainActivity", "ProductDetailFragment", "ProfileView", "ProfileViewController"] - - id: app.screen.first_draw.duration - type: int + - id: app.screen.time_to_first_draw.duration + type: double stability: development brief: > - The time, in nanoseconds, from screen initialization to the first frame being rendered. + The time, in seconds, from screen initialization to the first frame being rendered. note: > - This measures the time, in nanoseconds, until the first frame of the screen + This measures the time, in seconds, until the first frame of the screen is rendered and becomes visible to the user. - examples: [1000] - - id: app.screen.load.duration - type: int - stability: development - brief: > - The time taken, in nanoseconds, for a screen to load and become stable, measured from when - the screen begins appearing until the first stable frame has been rendered. - note: > - This attribute represents the total duration, in nanoseconds, of a screen load as experienced by the user. - The screen load is considered complete when the first stable frame of the screen has been rendered. - A frame is considered stable when no major layout or frame changes occur for a brief stability interval (e.g. 150 ms). - examples: [1000] + examples: [0.95, 2.0] - id: app.screen.type type: members: @@ -134,46 +123,42 @@ groups: screen’s content. For iOS, it may refer to either SwiftUI (declarative) or UIKit (imperative) for managing views. On Android, it can refer to either an Activity or a Fragment. examples: ["swiftui", "uikit", "activity", "fragment"] - - id: app.screen.visible.duration - type: int + - id: app.screen.time_on_screen.duration + type: double stability: development brief: > - The total time, in nanoseconds, that the screen remained visible to the user. + The total time, in seconds, that the screen remained visible to the user. note: > This attribute measures the duration during which the screen is visible and actively being displayed to the user. It begins when the screen becomes visible (e.g., `viewDidAppear` on iOS or `onResume` on Android) and ends when it is no longer visible (e.g., `viewWillDisappear` on iOS or `onPause` on Android). It does **not** include the time when the screen is in the background, nor does it account for time the screen may be obscured by other views or overlays (e.g., modals, popups, or other screens in split-view). - examples: [1200, 5500, 700] + examples: [30.0, 10.21] - id: app.start.duration - type: int + type: double stability: development brief: > - The total time, in nanoseconds, taken for the application to start, from user initiation to being ready for interaction. + The total time, in seconds, taken for the application to start, from user initiation to being ready for interaction. note: > - This is the time, in nanoseconds, between the user's initiation of the app start (e.g., tapping the app icon or opening a link) and the point when the app is fully ready for interaction, + This is the time, in seconds, between the user's initiation of the app start (e.g., tapping the app icon or opening a link) and the point when the app is fully ready for interaction, such as the main screen becoming visible or the app’s main functionality being accessible. - examples: [1000] + examples: [0.95, 2.0] - id: app.start.type type: members: - id: cold value: "cold" brief: App start from terminated state + note: The app is started from a terminated state, meaning no prior instance of the app is running. stability: development - id: warm value: "warm" brief: App start from background state + note: The app is started from the background, meaning an instance of the app is still in memory, but not active. stability: development stability: development - brief: > - The type of application start, indicating the state of the app when it was initiated. - note: | - Start types include: - - - **Cold**: The app is started from a terminated state, meaning no prior instance of the app is running. - - **Warm**: The app is started from the background, meaning an instance of the app is still in memory, but not active. + brief: The type of application start, indicating the state of the app when it was initiated. examples: ["cold", "warm"] - id: app.widget.id type: string diff --git a/model/app/spans.yaml b/model/app/spans.yaml index 3bf7f8d5a7..4f02a640a2 100644 --- a/model/app/spans.yaml +++ b/model/app/spans.yaml @@ -1,49 +1,36 @@ groups: - - id: span.app.screen.first_draw.internal + - id: span.app.screen.time_to_first_draw.internal type: span span_kind: internal - brief: This span describes the time until the first draw of an application UI screen. + brief: This span represents an application screen first draw operation. note: | - **Span name**: MUST be `app.screen.first_draw`. + **Span name**: MUST be `app.screen.time_to_first_draw`. - This span captures the time from screen initialization to the first frame drawn. - stability: development - attributes: - - ref: app.screen.name - requirement_level: required - - ref: app.screen.first_draw.duration - requirement_level: required - - ref: app.screen.type - requirement_level: opt_in - - id: span.app.screen.load.internal - type: span - span_kind: internal - brief: This span describes an application screen load operation, from navigation trigger to when the first stable frame has been rendered. - note: | - **Span name:** MUST be `app.screen.load`. + **Span kind** MUST be `INTERNAL`. - This span captures the time from user initiation of naigation (e.g., tapping a button) to the point when the first stable frame - of the screen has been rendered. A frame is considered stable when no major layout or frame changes occur for a brief stability - interval (e.g. 150 ms). + This span captures the time from screen initialization to the first frame + of an application UI screen being drawn. stability: development attributes: + - ref: app.screen.id + requirement_level: recommended - ref: app.screen.name + requirement_level: opt_in + - ref: app.screen.time_to_first_draw.duration requirement_level: required - ref: app.screen.type requirement_level: opt_in - - ref: app.screen.load.duration - requirement_level: required - - id: span.app.start.client + - id: span.app.start.internal type: span - span_kind: client + span_kind: internal brief: This span represents an application start operation. note: | - **Span name:** MUST be `AppStart`. + **Span name:** MUST be `app.start`. - **Span kind** MUST be `CLIENT`. + **Span kind** MUST be `INTERNAL`. This span captures the time from user initiation (e.g., tapping the app icon or opening a link) - to the moment the app is ready for interaction. + to the moment the app begins UI rendering. stability: development attributes: - ref: app.start.type From 9d526895ef6c8d570413e5752f6312028c4ba5a2 Mon Sep 17 00:00:00 2001 From: Grace Lim Date: Thu, 16 Oct 2025 18:17:57 -0700 Subject: [PATCH 12/17] fix: Remove trailing space to fix lint error --- model/app/registry.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/model/app/registry.yaml b/model/app/registry.yaml index 1abd5b880e..b5ad17a4b7 100644 --- a/model/app/registry.yaml +++ b/model/app/registry.yaml @@ -94,7 +94,7 @@ groups: note: > This measures the time, in seconds, until the first frame of the screen is rendered and becomes visible to the user. - examples: [0.95, 2.0] + examples: [0.95, 2.0] - id: app.screen.type type: members: From a9b8f7871644021613c9700c9fcb0be2c7ae2697 Mon Sep 17 00:00:00 2001 From: Grace Lim Date: Thu, 16 Oct 2025 18:29:22 -0700 Subject: [PATCH 13/17] fix : Revert back to app.screen.visible --- docs/app/app-events.md | 12 ++++++------ docs/registry/attributes/app.md | 12 ++++++------ model/app/events.yaml | 6 +++--- model/app/registry.yaml | 2 +- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/docs/app/app-events.md b/docs/app/app-events.md index e14deca995..ad1dd204f8 100644 --- a/docs/app/app-events.md +++ b/docs/app/app-events.md @@ -16,7 +16,7 @@ This document defines events related to client-side applications - [Event: `app.widget.click`](#event-appwidgetclick) - [Jank Event](#jank-event) - [Event: `app.jank`](#event-appjank) -- [Event: `app.screen.time_on_screen`](#event-appscreentime_on_screen) +- [Event: `app.screen.visible`](#event-appscreenvisible) - [Attributes](#attributes) @@ -131,9 +131,9 @@ Jank happens when the UI is rendered slowly enough for the user to experience so -## Event: `app.screen.time_on_screen` +## Event: `app.screen.visible` - + @@ -142,7 +142,7 @@ Jank happens when the UI is rendered slowly enough for the user to experience so **Status:** ![Development](https://img.shields.io/badge/-development-blue) -The event name MUST be `app.screen.time_on_screen`. +The event name MUST be `app.screen.visible`. This event captures the duration that a screen was visible to the user, indicating the time between when the screen becomes visible and when it stops being visible. @@ -150,12 +150,12 @@ This event measures the screen's visibility, in seconds, meaning it includes onl | Attribute | Type | Description | Examples | [Requirement Level](https://opentelemetry.io/docs/specs/semconv/general/attribute-requirement-level/) | Stability | |---|---|---|---|---|---| -| [`app.screen.time_on_screen.duration`](/docs/registry/attributes/app.md) | double | The total time, in seconds, that the screen remained visible to the user. [1] | `30.0`; `10.21` | `Required` | ![Development](https://img.shields.io/badge/-development-blue) | +| [`app.screen.visible.duration`](/docs/registry/attributes/app.md) | double | The total time, in seconds, that the screen remained visible to the user. [1] | `30.0`; `10.21` | `Required` | ![Development](https://img.shields.io/badge/-development-blue) | | [`app.screen.id`](/docs/registry/attributes/app.md) | string | An identifier that uniquely differentiates this screen from other screens in the same application. [2] | `f9bc787d-ff05-48ad-90e1-fca1d46130b3`; `com.example.app.MainActivity`; `com.example.shop.ProductDetailFragment`; `MyApp.ProfileView`; `MyApp.ProfileViewController` | `Recommended` | ![Development](https://img.shields.io/badge/-development-blue) | | [`app.screen.name`](/docs/registry/attributes/app.md) | string | The name of an application screen. [3] | `MainActivity`; `ProductDetailFragment`; `ProfileView`; `ProfileViewController` | `Opt-In` | ![Development](https://img.shields.io/badge/-development-blue) | | [`app.screen.type`](/docs/registry/attributes/app.md) | string | The type of UI management component or framework used to render and manage the screen's presentation and interactions. [4] | `swiftui`; `uikit`; `activity`; `fragment` | `Opt-In` | ![Development](https://img.shields.io/badge/-development-blue) | -**[1] `app.screen.time_on_screen.duration`:** This attribute measures the duration during which the screen is visible and actively being displayed to the user. It begins when the screen becomes visible (e.g., `viewDidAppear` on iOS or `onResume` on Android) and ends when it is no longer visible (e.g., `viewWillDisappear` on iOS or `onPause` on Android). It does **not** include the time when the screen is in the background, nor does it account for time the screen may be obscured by other views or overlays (e.g., modals, popups, or other screens in split-view). +**[1] `app.screen.visible.duration`:** This attribute measures the duration during which the screen is visible and actively being displayed to the user. It begins when the screen becomes visible (e.g., `viewDidAppear` on iOS or `onResume` on Android) and ends when it is no longer visible (e.g., `viewWillDisappear` on iOS or `onPause` on Android). It does **not** include the time when the screen is in the background, nor does it account for time the screen may be obscured by other views or overlays (e.g., modals, popups, or other screens in split-view). **[2] `app.screen.id`:** A screen represents only the part of the device display drawn by the app. It typically contains multiple widgets or UI components and is larger in scope than individual widgets. Multiple screens can coexist on the same display simultaneously (e.g., split view on tablets). diff --git a/docs/registry/attributes/app.md b/docs/registry/attributes/app.md index 37f85c4c83..f9179bf772 100644 --- a/docs/registry/attributes/app.md +++ b/docs/registry/attributes/app.md @@ -18,9 +18,9 @@ Describes attributes related to client-side applications (e.g. web apps or mobil | `app.screen.coordinate.y` | int | The y (vertical) component of a screen coordinate, in screen pixels. | `12`; `99` | ![Development](https://img.shields.io/badge/-development-blue) | | `app.screen.id` | string | An identifier that uniquely differentiates this screen from other screens in the same application. [3] | `f9bc787d-ff05-48ad-90e1-fca1d46130b3`; `com.example.app.MainActivity`; `com.example.shop.ProductDetailFragment`; `MyApp.ProfileView`; `MyApp.ProfileViewController` | ![Development](https://img.shields.io/badge/-development-blue) | | `app.screen.name` | string | The name of an application screen. [4] | `MainActivity`; `ProductDetailFragment`; `ProfileView`; `ProfileViewController` | ![Development](https://img.shields.io/badge/-development-blue) | -| `app.screen.time_on_screen.duration` | double | The total time, in seconds, that the screen remained visible to the user. [5] | `30.0`; `10.21` | ![Development](https://img.shields.io/badge/-development-blue) | -| `app.screen.time_to_first_draw.duration` | double | The time, in seconds, from screen initialization to the first frame being rendered. [6] | `0.95`; `2.0` | ![Development](https://img.shields.io/badge/-development-blue) | -| `app.screen.type` | string | The type of UI management component or framework used to render and manage the screen's presentation and interactions. [7] | `swiftui`; `uikit`; `activity`; `fragment` | ![Development](https://img.shields.io/badge/-development-blue) | +| `app.screen.time_to_first_draw.duration` | double | The time, in seconds, from screen initialization to the first frame being rendered. [5] | `0.95`; `2.0` | ![Development](https://img.shields.io/badge/-development-blue) | +| `app.screen.type` | string | The type of UI management component or framework used to render and manage the screen's presentation and interactions. [6] | `swiftui`; `uikit`; `activity`; `fragment` | ![Development](https://img.shields.io/badge/-development-blue) | +| `app.screen.visible.duration` | double | The total time, in seconds, that the screen remained visible to the user. [7] | `30.0`; `10.21` | ![Development](https://img.shields.io/badge/-development-blue) | | `app.start.duration` | double | The total time, in seconds, taken for the application to start, from user initiation to being ready for interaction. [8] | `0.95`; `2.0` | ![Development](https://img.shields.io/badge/-development-blue) | | `app.start.type` | string | The type of application start, indicating the state of the app when it was initiated. | `cold`; `warm` | ![Development](https://img.shields.io/badge/-development-blue) | | `app.widget.id` | string | An identifier that uniquely differentiates this widget from other widgets in the same application. [9] | `f9bc787d-ff05-48ad-90e1-fca1d46130b3`; `submit_order_1829` | ![Development](https://img.shields.io/badge/-development-blue) | @@ -50,11 +50,11 @@ More information about Android identifier best practices can be found in the [An **[4] `app.screen.name`:** A screen represents only the part of the device display drawn by the app. It typically contains multiple widgets or UI components and is larger in scope than individual widgets. Multiple screens can coexist on the same display simultaneously (e.g., split view on tablets). -**[5] `app.screen.time_on_screen.duration`:** This attribute measures the duration during which the screen is visible and actively being displayed to the user. It begins when the screen becomes visible (e.g., `viewDidAppear` on iOS or `onResume` on Android) and ends when it is no longer visible (e.g., `viewWillDisappear` on iOS or `onPause` on Android). It does **not** include the time when the screen is in the background, nor does it account for time the screen may be obscured by other views or overlays (e.g., modals, popups, or other screens in split-view). +**[5] `app.screen.time_to_first_draw.duration`:** This measures the time, in seconds, until the first frame of the screen is rendered and becomes visible to the user. -**[6] `app.screen.time_to_first_draw.duration`:** This measures the time, in seconds, until the first frame of the screen is rendered and becomes visible to the user. +**[6] `app.screen.type`:** This attribute indicates which framework or structure is used to manage and display the screen’s content. For iOS, it may refer to either SwiftUI (declarative) or UIKit (imperative) for managing views. On Android, it can refer to either an Activity or a Fragment. -**[7] `app.screen.type`:** This attribute indicates which framework or structure is used to manage and display the screen’s content. For iOS, it may refer to either SwiftUI (declarative) or UIKit (imperative) for managing views. On Android, it can refer to either an Activity or a Fragment. +**[7] `app.screen.visible.duration`:** This attribute measures the duration during which the screen is visible and actively being displayed to the user. It begins when the screen becomes visible (e.g., `viewDidAppear` on iOS or `onResume` on Android) and ends when it is no longer visible (e.g., `viewWillDisappear` on iOS or `onPause` on Android). It does **not** include the time when the screen is in the background, nor does it account for time the screen may be obscured by other views or overlays (e.g., modals, popups, or other screens in split-view). **[8] `app.start.duration`:** This is the time, in seconds, between the user's initiation of the app start (e.g., tapping the app icon or opening a link) and the point when the app is fully ready for interaction, such as the main screen becoming visible or the app’s main functionality being accessible. diff --git a/model/app/events.yaml b/model/app/events.yaml index 30ae1f3f84..4de497e15b 100644 --- a/model/app/events.yaml +++ b/model/app/events.yaml @@ -62,10 +62,10 @@ groups: requirement_level: recommended - ref: app.jank.period requirement_level: recommended - - id: event.app.screen.time_on_screen + - id: event.app.screen.visible stability: development type: event - name: app.screen.time_on_screen + name: app.screen.visible brief: > This event captures the duration that a screen was visible to the user, indicating the time between when the screen becomes visible and when it stops being visible. @@ -81,5 +81,5 @@ groups: requirement_level: opt_in - ref: app.screen.type requirement_level: opt_in - - ref: app.screen.time_on_screen.duration + - ref: app.screen.visible.duration requirement_level: required diff --git a/model/app/registry.yaml b/model/app/registry.yaml index b5ad17a4b7..34250af9b9 100644 --- a/model/app/registry.yaml +++ b/model/app/registry.yaml @@ -123,7 +123,7 @@ groups: screen’s content. For iOS, it may refer to either SwiftUI (declarative) or UIKit (imperative) for managing views. On Android, it can refer to either an Activity or a Fragment. examples: ["swiftui", "uikit", "activity", "fragment"] - - id: app.screen.time_on_screen.duration + - id: app.screen.visible.duration type: double stability: development brief: > From 2214ca74fcc2cb51f2bc7f7f151464d52f2a5a94 Mon Sep 17 00:00:00 2001 From: Grace Lim Date: Thu, 16 Oct 2025 18:31:05 -0700 Subject: [PATCH 14/17] fix: Update changelog with latest changes --- .chloggen/feat_app-spans.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.chloggen/feat_app-spans.yaml b/.chloggen/feat_app-spans.yaml index 84668298f8..1efa4a06c2 100644 --- a/.chloggen/feat_app-spans.yaml +++ b/.chloggen/feat_app-spans.yaml @@ -10,7 +10,7 @@ change_type: enhancement component: app # A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). -note: Add spans for app start, app screen load, app time to first draw +note: Add spans for app start and app screen time to first draw. Add event for app screen visible # Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists. # The values here must be integers. From ea946a0d827870154bd6e3424a54ff0156b9a93e Mon Sep 17 00:00:00 2001 From: Grace Lim Date: Thu, 16 Oct 2025 18:48:18 -0700 Subject: [PATCH 15/17] fix: Make time on screen into span instead of event --- docs/app/app-events.md | 49 ----------------------------- docs/app/app-spans.md | 56 +++++++++++++++++++++++++++++++++ docs/registry/attributes/app.md | 12 +++---- model/app/events.yaml | 23 +------------- model/app/registry.yaml | 2 +- model/app/spans.yaml | 25 +++++++++++++++ 6 files changed, 89 insertions(+), 78 deletions(-) diff --git a/docs/app/app-events.md b/docs/app/app-events.md index ad1dd204f8..6cfe4c4431 100644 --- a/docs/app/app-events.md +++ b/docs/app/app-events.md @@ -16,7 +16,6 @@ This document defines events related to client-side applications - [Event: `app.widget.click`](#event-appwidgetclick) - [Jank Event](#jank-event) - [Event: `app.jank`](#event-appjank) -- [Event: `app.screen.visible`](#event-appscreenvisible) - [Attributes](#attributes) @@ -131,54 +130,6 @@ Jank happens when the UI is rendered slowly enough for the user to experience so -## Event: `app.screen.visible` - - - - - - - - -**Status:** ![Development](https://img.shields.io/badge/-development-blue) - -The event name MUST be `app.screen.visible`. - -This event captures the duration that a screen was visible to the user, indicating the time between when the screen becomes visible and when it stops being visible. - -This event measures the screen's visibility, in seconds, meaning it includes only the time the screen is actively being shown to the user. It does not include times when the app is in the background or when other screens/modal views are covering it. For example: - **iOS**: From `viewDidAppear` to `viewWillDisappear`, indicating when the screen is first shown and when it's about to disappear. - **Android**: From `onResume` to `onPause`, indicating when the screen comes to the foreground and when it goes to the background. - -| Attribute | Type | Description | Examples | [Requirement Level](https://opentelemetry.io/docs/specs/semconv/general/attribute-requirement-level/) | Stability | -|---|---|---|---|---|---| -| [`app.screen.visible.duration`](/docs/registry/attributes/app.md) | double | The total time, in seconds, that the screen remained visible to the user. [1] | `30.0`; `10.21` | `Required` | ![Development](https://img.shields.io/badge/-development-blue) | -| [`app.screen.id`](/docs/registry/attributes/app.md) | string | An identifier that uniquely differentiates this screen from other screens in the same application. [2] | `f9bc787d-ff05-48ad-90e1-fca1d46130b3`; `com.example.app.MainActivity`; `com.example.shop.ProductDetailFragment`; `MyApp.ProfileView`; `MyApp.ProfileViewController` | `Recommended` | ![Development](https://img.shields.io/badge/-development-blue) | -| [`app.screen.name`](/docs/registry/attributes/app.md) | string | The name of an application screen. [3] | `MainActivity`; `ProductDetailFragment`; `ProfileView`; `ProfileViewController` | `Opt-In` | ![Development](https://img.shields.io/badge/-development-blue) | -| [`app.screen.type`](/docs/registry/attributes/app.md) | string | The type of UI management component or framework used to render and manage the screen's presentation and interactions. [4] | `swiftui`; `uikit`; `activity`; `fragment` | `Opt-In` | ![Development](https://img.shields.io/badge/-development-blue) | - -**[1] `app.screen.visible.duration`:** This attribute measures the duration during which the screen is visible and actively being displayed to the user. It begins when the screen becomes visible (e.g., `viewDidAppear` on iOS or `onResume` on Android) and ends when it is no longer visible (e.g., `viewWillDisappear` on iOS or `onPause` on Android). It does **not** include the time when the screen is in the background, nor does it account for time the screen may be obscured by other views or overlays (e.g., modals, popups, or other screens in split-view). - -**[2] `app.screen.id`:** A screen represents only the part of the device display drawn by the app. It typically contains multiple widgets or UI components and is larger in scope than individual widgets. Multiple screens can coexist on the same display simultaneously (e.g., split view on tablets). - -**[3] `app.screen.name`:** A screen represents only the part of the device display drawn by the app. It typically contains multiple widgets or UI components and is larger in scope than individual widgets. Multiple screens can coexist on the same display simultaneously (e.g., split view on tablets). - -**[4] `app.screen.type`:** This attribute indicates which framework or structure is used to manage and display the screen’s content. For iOS, it may refer to either SwiftUI (declarative) or UIKit (imperative) for managing views. On Android, it can refer to either an Activity or a Fragment. - ---- - -`app.screen.type` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used. - -| Value | Description | Stability | -|---|---|---| -| `activity` | Android Activity (Android) | ![Development](https://img.shields.io/badge/-development-blue) | -| `fragment` | Android Fragment (Android) | ![Development](https://img.shields.io/badge/-development-blue) | -| `swiftui` | SwiftUI View (iOS) | ![Development](https://img.shields.io/badge/-development-blue) | -| `uikit` | UIKit ViewController (iOS) | ![Development](https://img.shields.io/badge/-development-blue) | - - - - - - ## Attributes See the [app attributes](/docs/registry/attributes/app.md) registry for all diff --git a/docs/app/app-spans.md b/docs/app/app-spans.md index 5db17db368..53c34c3e6e 100644 --- a/docs/app/app-spans.md +++ b/docs/app/app-spans.md @@ -9,6 +9,7 @@ linkTitle: App spans - [Time to first draw span](#time-to-first-draw-span) +- [Time on screen span](#time-on-screen-span) - [App start span](#app-start-span) @@ -66,6 +67,61 @@ of an application UI screen being drawn. +## Time on screen span + + + + + + + + +**Status:** ![Development](https://img.shields.io/badge/-development-blue) + +This span_kind captures the duration that a screen was visible to the user, indicating the time between when the screen becomes visible and when it stops being visible. + +**Span name:** MUST be `app.screen.time_on_screen`. + +**Span kind** MUST be `INTERNAL`. + +This span captures the screen's visibility, in seconds, meaning it includes only the time the screen is actively being shown to the user. +It does not include times when the app is in the background or when other screens/modal views are covering it. For example: +- **iOS**: From `viewDidAppear` to `viewWillDisappear`, indicating when the screen is first shown and when it's about to disappear. +- **Android**: From `onResume` to `onPause`, indicating when the screen comes to the foreground and when it goes to the background. + +**Span status** SHOULD follow the [Recording Errors](/docs/general/recording-errors.md) document. + +| Attribute | Type | Description | Examples | [Requirement Level](https://opentelemetry.io/docs/specs/semconv/general/attribute-requirement-level/) | Stability | +|---|---|---|---|---|---| +| [`app.screen.time_on_screen.duration`](/docs/registry/attributes/app.md) | double | The total time, in seconds, that the screen remained visible to the user. [1] | `30.0`; `10.21` | `Required` | ![Development](https://img.shields.io/badge/-development-blue) | +| [`app.screen.id`](/docs/registry/attributes/app.md) | string | An identifier that uniquely differentiates this screen from other screens in the same application. [2] | `f9bc787d-ff05-48ad-90e1-fca1d46130b3`; `com.example.app.MainActivity`; `com.example.shop.ProductDetailFragment`; `MyApp.ProfileView`; `MyApp.ProfileViewController` | `Recommended` | ![Development](https://img.shields.io/badge/-development-blue) | +| [`app.screen.name`](/docs/registry/attributes/app.md) | string | The name of an application screen. [3] | `MainActivity`; `ProductDetailFragment`; `ProfileView`; `ProfileViewController` | `Opt-In` | ![Development](https://img.shields.io/badge/-development-blue) | +| [`app.screen.type`](/docs/registry/attributes/app.md) | string | The type of UI management component or framework used to render and manage the screen's presentation and interactions. [4] | `swiftui`; `uikit`; `activity`; `fragment` | `Opt-In` | ![Development](https://img.shields.io/badge/-development-blue) | + +**[1] `app.screen.time_on_screen.duration`:** This attribute measures the duration during which the screen is visible and actively being displayed to the user. It begins when the screen becomes visible (e.g., `viewDidAppear` on iOS or `onResume` on Android) and ends when it is no longer visible (e.g., `viewWillDisappear` on iOS or `onPause` on Android). It does **not** include the time when the screen is in the background, nor does it account for time the screen may be obscured by other views or overlays (e.g., modals, popups, or other screens in split-view). + +**[2] `app.screen.id`:** A screen represents only the part of the device display drawn by the app. It typically contains multiple widgets or UI components and is larger in scope than individual widgets. Multiple screens can coexist on the same display simultaneously (e.g., split view on tablets). + +**[3] `app.screen.name`:** A screen represents only the part of the device display drawn by the app. It typically contains multiple widgets or UI components and is larger in scope than individual widgets. Multiple screens can coexist on the same display simultaneously (e.g., split view on tablets). + +**[4] `app.screen.type`:** This attribute indicates which framework or structure is used to manage and display the screen’s content. For iOS, it may refer to either SwiftUI (declarative) or UIKit (imperative) for managing views. On Android, it can refer to either an Activity or a Fragment. + +--- + +`app.screen.type` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used. + +| Value | Description | Stability | +|---|---|---| +| `activity` | Android Activity (Android) | ![Development](https://img.shields.io/badge/-development-blue) | +| `fragment` | Android Fragment (Android) | ![Development](https://img.shields.io/badge/-development-blue) | +| `swiftui` | SwiftUI View (iOS) | ![Development](https://img.shields.io/badge/-development-blue) | +| `uikit` | UIKit ViewController (iOS) | ![Development](https://img.shields.io/badge/-development-blue) | + + + + + + ## App start span diff --git a/docs/registry/attributes/app.md b/docs/registry/attributes/app.md index f9179bf772..37f85c4c83 100644 --- a/docs/registry/attributes/app.md +++ b/docs/registry/attributes/app.md @@ -18,9 +18,9 @@ Describes attributes related to client-side applications (e.g. web apps or mobil | `app.screen.coordinate.y` | int | The y (vertical) component of a screen coordinate, in screen pixels. | `12`; `99` | ![Development](https://img.shields.io/badge/-development-blue) | | `app.screen.id` | string | An identifier that uniquely differentiates this screen from other screens in the same application. [3] | `f9bc787d-ff05-48ad-90e1-fca1d46130b3`; `com.example.app.MainActivity`; `com.example.shop.ProductDetailFragment`; `MyApp.ProfileView`; `MyApp.ProfileViewController` | ![Development](https://img.shields.io/badge/-development-blue) | | `app.screen.name` | string | The name of an application screen. [4] | `MainActivity`; `ProductDetailFragment`; `ProfileView`; `ProfileViewController` | ![Development](https://img.shields.io/badge/-development-blue) | -| `app.screen.time_to_first_draw.duration` | double | The time, in seconds, from screen initialization to the first frame being rendered. [5] | `0.95`; `2.0` | ![Development](https://img.shields.io/badge/-development-blue) | -| `app.screen.type` | string | The type of UI management component or framework used to render and manage the screen's presentation and interactions. [6] | `swiftui`; `uikit`; `activity`; `fragment` | ![Development](https://img.shields.io/badge/-development-blue) | -| `app.screen.visible.duration` | double | The total time, in seconds, that the screen remained visible to the user. [7] | `30.0`; `10.21` | ![Development](https://img.shields.io/badge/-development-blue) | +| `app.screen.time_on_screen.duration` | double | The total time, in seconds, that the screen remained visible to the user. [5] | `30.0`; `10.21` | ![Development](https://img.shields.io/badge/-development-blue) | +| `app.screen.time_to_first_draw.duration` | double | The time, in seconds, from screen initialization to the first frame being rendered. [6] | `0.95`; `2.0` | ![Development](https://img.shields.io/badge/-development-blue) | +| `app.screen.type` | string | The type of UI management component or framework used to render and manage the screen's presentation and interactions. [7] | `swiftui`; `uikit`; `activity`; `fragment` | ![Development](https://img.shields.io/badge/-development-blue) | | `app.start.duration` | double | The total time, in seconds, taken for the application to start, from user initiation to being ready for interaction. [8] | `0.95`; `2.0` | ![Development](https://img.shields.io/badge/-development-blue) | | `app.start.type` | string | The type of application start, indicating the state of the app when it was initiated. | `cold`; `warm` | ![Development](https://img.shields.io/badge/-development-blue) | | `app.widget.id` | string | An identifier that uniquely differentiates this widget from other widgets in the same application. [9] | `f9bc787d-ff05-48ad-90e1-fca1d46130b3`; `submit_order_1829` | ![Development](https://img.shields.io/badge/-development-blue) | @@ -50,11 +50,11 @@ More information about Android identifier best practices can be found in the [An **[4] `app.screen.name`:** A screen represents only the part of the device display drawn by the app. It typically contains multiple widgets or UI components and is larger in scope than individual widgets. Multiple screens can coexist on the same display simultaneously (e.g., split view on tablets). -**[5] `app.screen.time_to_first_draw.duration`:** This measures the time, in seconds, until the first frame of the screen is rendered and becomes visible to the user. +**[5] `app.screen.time_on_screen.duration`:** This attribute measures the duration during which the screen is visible and actively being displayed to the user. It begins when the screen becomes visible (e.g., `viewDidAppear` on iOS or `onResume` on Android) and ends when it is no longer visible (e.g., `viewWillDisappear` on iOS or `onPause` on Android). It does **not** include the time when the screen is in the background, nor does it account for time the screen may be obscured by other views or overlays (e.g., modals, popups, or other screens in split-view). -**[6] `app.screen.type`:** This attribute indicates which framework or structure is used to manage and display the screen’s content. For iOS, it may refer to either SwiftUI (declarative) or UIKit (imperative) for managing views. On Android, it can refer to either an Activity or a Fragment. +**[6] `app.screen.time_to_first_draw.duration`:** This measures the time, in seconds, until the first frame of the screen is rendered and becomes visible to the user. -**[7] `app.screen.visible.duration`:** This attribute measures the duration during which the screen is visible and actively being displayed to the user. It begins when the screen becomes visible (e.g., `viewDidAppear` on iOS or `onResume` on Android) and ends when it is no longer visible (e.g., `viewWillDisappear` on iOS or `onPause` on Android). It does **not** include the time when the screen is in the background, nor does it account for time the screen may be obscured by other views or overlays (e.g., modals, popups, or other screens in split-view). +**[7] `app.screen.type`:** This attribute indicates which framework or structure is used to manage and display the screen’s content. For iOS, it may refer to either SwiftUI (declarative) or UIKit (imperative) for managing views. On Android, it can refer to either an Activity or a Fragment. **[8] `app.start.duration`:** This is the time, in seconds, between the user's initiation of the app start (e.g., tapping the app icon or opening a link) and the point when the app is fully ready for interaction, such as the main screen becoming visible or the app’s main functionality being accessible. diff --git a/model/app/events.yaml b/model/app/events.yaml index 4de497e15b..08858abd0c 100644 --- a/model/app/events.yaml +++ b/model/app/events.yaml @@ -61,25 +61,4 @@ groups: - ref: app.jank.threshold requirement_level: recommended - ref: app.jank.period - requirement_level: recommended - - id: event.app.screen.visible - stability: development - type: event - name: app.screen.visible - brief: > - This event captures the duration that a screen was visible to the user, indicating the time between when the screen becomes - visible and when it stops being visible. - note: > - This event measures the screen's visibility, in seconds, meaning it includes only the time the screen is actively being shown to the user. - It does not include times when the app is in the background or when other screens/modal views are covering it. For example: - - **iOS**: From `viewDidAppear` to `viewWillDisappear`, indicating when the screen is first shown and when it's about to disappear. - - **Android**: From `onResume` to `onPause`, indicating when the screen comes to the foreground and when it goes to the background. - attributes: - - ref: app.screen.id - requirement_level: recommended - - ref: app.screen.name - requirement_level: opt_in - - ref: app.screen.type - requirement_level: opt_in - - ref: app.screen.visible.duration - requirement_level: required + requirement_level: recommended \ No newline at end of file diff --git a/model/app/registry.yaml b/model/app/registry.yaml index 34250af9b9..b5ad17a4b7 100644 --- a/model/app/registry.yaml +++ b/model/app/registry.yaml @@ -123,7 +123,7 @@ groups: screen’s content. For iOS, it may refer to either SwiftUI (declarative) or UIKit (imperative) for managing views. On Android, it can refer to either an Activity or a Fragment. examples: ["swiftui", "uikit", "activity", "fragment"] - - id: app.screen.visible.duration + - id: app.screen.time_on_screen.duration type: double stability: development brief: > diff --git a/model/app/spans.yaml b/model/app/spans.yaml index 4f02a640a2..79e7985e7f 100644 --- a/model/app/spans.yaml +++ b/model/app/spans.yaml @@ -20,6 +20,31 @@ groups: requirement_level: required - ref: app.screen.type requirement_level: opt_in + - id: span.app.screen.time_on_screen.internal + type: span + span_kind: internal + brief: > + This span_kind captures the duration that a screen was visible to the user, indicating the time between when the screen becomes + visible and when it stops being visible. + note: | + **Span name:** MUST be `app.screen.time_on_screen`. + + **Span kind** MUST be `INTERNAL`. + + This span captures the screen's visibility, in seconds, meaning it includes only the time the screen is actively being shown to the user. + It does not include times when the app is in the background or when other screens/modal views are covering it. For example: + - **iOS**: From `viewDidAppear` to `viewWillDisappear`, indicating when the screen is first shown and when it's about to disappear. + - **Android**: From `onResume` to `onPause`, indicating when the screen comes to the foreground and when it goes to the background. + stability: development + attributes: + - ref: app.screen.id + requirement_level: recommended + - ref: app.screen.name + requirement_level: opt_in + - ref: app.screen.type + requirement_level: opt_in + - ref: app.screen.time_on_screen.duration + requirement_level: required - id: span.app.start.internal type: span span_kind: internal From 6438bc1cad714930cac30be8f3e6250577d5a424 Mon Sep 17 00:00:00 2001 From: Grace Lim Date: Thu, 16 Oct 2025 18:49:56 -0700 Subject: [PATCH 16/17] fix: Add newline to fix yaml lint error --- model/app/events.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/model/app/events.yaml b/model/app/events.yaml index 08858abd0c..edbd7d5f04 100644 --- a/model/app/events.yaml +++ b/model/app/events.yaml @@ -61,4 +61,4 @@ groups: - ref: app.jank.threshold requirement_level: recommended - ref: app.jank.period - requirement_level: recommended \ No newline at end of file + requirement_level: recommended From c8f9774bce7dde07fe0c891d689d4cd2fca316ea Mon Sep 17 00:00:00 2001 From: Grace Lim Date: Thu, 16 Oct 2025 18:51:01 -0700 Subject: [PATCH 17/17] fix :Update chlog file --- .chloggen/feat_app-spans.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.chloggen/feat_app-spans.yaml b/.chloggen/feat_app-spans.yaml index 1efa4a06c2..ba925453c6 100644 --- a/.chloggen/feat_app-spans.yaml +++ b/.chloggen/feat_app-spans.yaml @@ -10,7 +10,7 @@ change_type: enhancement component: app # A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). -note: Add spans for app start and app screen time to first draw. Add event for app screen visible +note: Add spans for app start, time to first draw, time on screen # Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists. # The values here must be integers.