diff --git a/.chloggen/feat_app-spans.yaml b/.chloggen/feat_app-spans.yaml new file mode 100644 index 0000000000..ba925453c6 --- /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 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. +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/app/app-spans.md b/docs/app/app-spans.md new file mode 100644 index 0000000000..53c34c3e6e --- /dev/null +++ b/docs/app/app-spans.md @@ -0,0 +1,172 @@ + + +# Semantic conventions for app spans + +**Status**: [Development][DocumentStatus] + + + +- [Time to first draw span](#time-to-first-draw-span) +- [Time on screen span](#time-on-screen-span) +- [App start span](#app-start-span) + + + +## Time to first draw span + + + + + + + + +**Status:** ![Development](https://img.shields.io/badge/-development-blue) + +This span represents an application screen first draw operation. + +**Span name**: MUST be `app.screen.time_to_first_draw`. + +**Span kind** MUST 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.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.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.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) | + + + + + + +## 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 + + + + + + + + +**Status:** ![Development](https://img.shields.io/badge/-development-blue) + +This span represents an application start operation. + +**Span name:** MUST be `app.start`. + +**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 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) | 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) | + +**[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. + +--- + +`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 [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. + + + + + + +[DocumentStatus]: https://opentelemetry.io/docs/specs/otel/document-status diff --git a/docs/registry/attributes/app.md b/docs/registry/attributes/app.md index 13b23e6b16..37f85c4c83 100644 --- a/docs/registry/attributes/app.md +++ b/docs/registry/attributes/app.md @@ -18,8 +18,13 @@ 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.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.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) | +| `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. @@ -45,6 +50,38 @@ 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.widget.id`:** A widget is an application component, typically an on-screen visual GUI element. +**[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.widget.name`:** A widget is an application component, typically an on-screen visual GUI element. +**[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.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.widget.id`:** 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. + +--- + +`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.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 [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/registry.yaml b/model/app/registry.yaml index 7c704bf10f..b5ad17a4b7 100644 --- a/model/app/registry.yaml +++ b/model/app/registry.yaml @@ -86,6 +86,80 @@ 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.time_to_first_draw.duration + type: double + stability: development + brief: > + The time, in seconds, from screen initialization to the first frame being rendered. + 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] + - 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.time_on_screen.duration + type: double + stability: development + brief: > + 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: [30.0, 10.21] + - id: app.start.duration + type: double + stability: development + brief: > + 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 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: [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. + examples: ["cold", "warm"] - 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..79e7985e7f --- /dev/null +++ b/model/app/spans.yaml @@ -0,0 +1,64 @@ +groups: + - id: span.app.screen.time_to_first_draw.internal + type: span + span_kind: internal + brief: This span represents an application screen first draw operation. + note: | + **Span name**: MUST be `app.screen.time_to_first_draw`. + + **Span kind** MUST be `INTERNAL`. + + 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 + - 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 + brief: This span represents an application start operation. + note: | + **Span name:** MUST be `app.start`. + + **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 begins UI rendering. + stability: development + attributes: + - ref: app.start.type + requirement_level: required + - ref: app.start.duration + requirement_level: required