- Start Date: 2022-12-16
- RFC Type: feature
- RFC PR: #46
- RFC Status: draft
We want to provide a new span to the automatic UI transactions.
The TTFD (time-to-full-display) span is a way for the user to notify the SDK that the UI has been fully loaded.
That is, after all data is retrieved, either by database calls or rest APIs, and set into the UI.
We would create a new span to the UI automatic transactions to measure it, for all screens of the application.
This RFC is mostly about how we should design the new API.
This is useful especially for mobile developers, but could also be useful for web.
There is no reliable way to automatically detect when UI is fully drawn, as the "fully drawn" concept depends on the developer.
We have to add a new API to the SDK to allow the user to notify that the UI was fully drawn.
Also, we need the user to specify the span to finish through a parameter, as it cannot be done automatically.
E.g. Activity A starts -> Activity B starts -> Activity A finishes loading data and the API is called.
At this point without the activity it was called on, we wouldn't know which span to finish, because the activity B would be at the top of the stack.
We decided to go with the simplest API possible, from the end user perspective.
We are going to add a single new API Sentry.reportFullDisplayed()
, which will find the last active screen load transaction and finish the time-to-full-display
span.
The active screen load transaction needs to wait for a to-be-defined timeout if the user calls this API.
We still have to evaluate all the edge cases.
Since we are going to wait for the user to call the manual API, we are going to make it opt-in, otherwise unaware users would have their transactions take much longer without immediate causes.
Furthermore, we will evaluate if the SDKs should automatically finish the time-to-full-display
span, as it would greatly push adoption, but with a lot of possible false positives.
This consideration will be evaluated after getting feedbacks (or complains) from the users and after checking the feature adoption.
We are keeping the considered options as a reference.
Options removed:
- 1. SentryAndroid.reportFullyDrawn(Activity)
- 3. Sentry.monitorFullDisplay() with UUID
- 5. reportFullDisplay() on ISpan
- 6. reportFullDisplay on ISpan with Option
- 7. Hook into Android's
FullyDrawnReporter
These options were considered for Android, but the same apply to other SDKs, too.
Add a Sentry.monitorFullDisplay()
API. We would start the span automatically when an Activity is being created.
This API would return the span or a custom object to allow the user to finish it autonomously.
- We don't depend on Activity, making it usable on other platforms, too.
- We can flag the span when the API is called, so that if the user doesn't call the API, we know we can cancel it.
- Returning the span would allow the user to perform "dangerous" operations. We could solve this by returning a stripped interface to allow only the
finish()
method, or an entirely custom object. - If the user doesn't call the API, we would have a span that runs forever. We would have to add a timeout to automatically cancel the span.
- We can't reliably map
Sentry.monitorFullDisplay()
to the correct APM transaction, unless we force the user to call it in a specific callback, likeActivity.onActivityCreated()
.
Add monitorFullDisplay()
and reportFullDisplay()
to ISpan. The user gets access to the APM UI transaction by calling Sentry.getSpan
, calls span.monitorFullDisplay()
and span.reportFullDisplay()
.
- We don't depend on Activity, making it usable on other platforms, too.
- Correlate fully drawn to correct APM transaction.
- User can add more spans via the same API Sentry.span.
- Knowing when to wait for fully drawn.
- Extra APIs to call.
- Keeping a reference of transaction.
Add a SentryAndroid.reportFullyDrawn(Activity)
static method. We would start the span automatically when an Activity is being created and we would finish it when the API is called.
- The name of the api should be closer to
reportTimeToFullDisplay()
, losing the only pro.
- This resembles the system API
Activity.reportFullyDrawn()
, making it obvious how to use.
- We need the activity this API is called for, and passing an Activity instance to an API is not ideal.
- We need to add an API to
SentryAndroid
, instead of theSentry
class used everywhere else, due to Activity dependency. - This is not ideal for single activity apps, as it wouldn't work for fragments.
- If the user doesn't call the API, we would have a span that runs forever. We would have to add a timeout to automatically cancel the span.
Add a Sentry.monitorFullDisplay()
and a Sentry.reportFullDisplay(UUID)
API. We would start the span automatically when the SDK creates an auto-generated transaction.
This API would return a UUID used by the other API to stop the span.
- Returning a span could be more useful to the end user, making option 2 better then this.
- We don't depend on Activity, making it usable on other platforms, too.
- We can flag the span when the API is called, so that if the user doesn't call the API, we know we can cancel it.
- We don't return any "dangerous" object to the user.
- We would add and force the user to use 2 APIs.
- If the user doesn't call the second API, we would have a span that runs forever. We would have to add a timeout to automatically cancel the span.
- We can't reliably map
Sentry.monitorFullDisplay()
to the correct APM transaction, unless we force the user to call it in a specific callback, likeActivity.onActivityCreated()
.
Add reportFullDisplay()
toISpan. The user gets access to the APM UI transaction by calling Sentry.getSpan
, and calls span.reportFullDisplay()
.
- Add an API to all ISpan objects could be confusing.
- Not knowing when to wait for fully drawn, making option 4 better then this.
- We don't depend on Activity, making it usable on other platforms, too.
- Correlate fully drawn to correct APM transaction.
- User can add more spans via the same API Sentry.span.
- Extra APIs to call.
- Keeping a reference of a transaction.
- Not knowing when to wait for fully drawn.
Same as Option 5. but with an option wether to wait for calling reportFullDisplay
or not.
The SDK would wait for a configurable timeout for the user to call reportFullDisplay
. If the user doesn't call the API the SDK adds a ui.load.full_display
span with deadline_exceeded
, and finishes the auto-generated transaction.
If the user calls reportFullDisplay
and the option wether to wait for calling reportFullDisplay
or not is disabled, the SDK does nothing.
- A timeout should always be present, to avoid transactions running indefinitely due to user's error.
- Same reasons of option 5.
- Same Pros as option 5
- Knowing when to wait for fully drawn when option enabled.
We would use use a callback from that.
- Not knowing when to wait for fully drawn.
- Would work only on Android, and not even for single activity apps.
- Completely automatic and transparent to the user.
- We would know the activity that was drawn, so we'd know the span to finish.
- Only available from
androidx.activity
library version 1.7, currently in alpha. - This is not ideal for single activity apps, as it wouldn't work for fragments.
- Not knowing when to wait for fully drawn.
- Only works on Android.
- How long should the timeout be? The Facebook app developers consider a "bad start" a ttfd of 2.5 seconds or more, or an unsuccessful start.
This is only for the first screen, as the other screens are usually faster.
https://android-developers.googleblog.com/2021/11/improving-app-startup-facebook-app.html