Skip to content

RUM-11990: Defer requestProfiling to next app launch#2950

Merged
ambushwork merged 1 commit into
feature/perfetto-profilingfrom
yl/profiling/defer-profiling
Oct 23, 2025
Merged

RUM-11990: Defer requestProfiling to next app launch#2950
ambushwork merged 1 commit into
feature/perfetto-profilingfrom
yl/profiling/defer-profiling

Conversation

@ambushwork

@ambushwork ambushwork commented Oct 17, 2025

Copy link
Copy Markdown
Member

What does this PR do?

This PR enables the profiling request as early as possible during the app launch:

  • Add DdProfilingContentProvider to start the profiling request.
  • Add ProfilingStorage to read/save/clean the profiling flag to defer the profiling request to the next app launch.

Motivation

RUM-11990

Additional Notes

Profiling Sampling rate is not covered by this PR.

Review checklist (to be filled by reviewers)

  • Feature or bugfix MUST have appropriate tests (unit, integration, e2e)
  • Make sure you discussed the feature or bugfix with the maintaining team in an Issue
  • Make sure each commit and the PR mention the Issue number (cf the CONTRIBUTING doc)

@ambushwork
ambushwork force-pushed the yl/profiling/defer-profiling branch 6 times, most recently from 6fe7292 to 1846513 Compare October 20, 2025 13:33
@datadog-datadog-prod-us1

datadog-datadog-prod-us1 Bot commented Oct 20, 2025

Copy link
Copy Markdown

🎯 Code Coverage
Patch Coverage: 56.72%
Total Coverage: 70.94% (+0.01%)

View detailed report

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: c4f87a2 | Docs | Was this helpful? Give us feedback!

@ambushwork
ambushwork force-pushed the yl/profiling/defer-profiling branch from 1846513 to d595d0e Compare October 21, 2025 07:31
@ambushwork
ambushwork marked this pull request as ready for review October 21, 2025 08:04
@ambushwork
ambushwork requested review from a team as code owners October 21, 2025 08:04
@codecov-commenter

codecov-commenter commented Oct 21, 2025

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 48.27586% with 30 lines in your changes missing coverage. Please review.
✅ Project coverage is 70.90%. Comparing base (4895fe1) to head (c4f87a2).
⚠️ Report is 920 commits behind head on feature/perfetto-profiling.

Files with missing lines Patch % Lines
...og/android/profiling/DdProfilingContentProvider.kt 0.00% 16 Missing ⚠️
...in/java/com/datadog/android/profiling/Profiling.kt 0.00% 8 Missing ⚠️
...atadog/android/internal/data/PreferencesStorage.kt 0.00% 3 Missing ⚠️
...id/profiling/internal/perfetto/PerfettoProfiler.kt 50.00% 0 Missing and 3 partials ⚠️
Additional details and impacted files
@@                      Coverage Diff                       @@
##           feature/perfetto-profiling    #2950      +/-   ##
==============================================================
+ Coverage                       70.89%   70.90%   +0.01%     
==============================================================
  Files                             839      842       +3     
  Lines                           30579    30616      +37     
  Branches                         5192     5204      +12     
==============================================================
+ Hits                            21676    21706      +30     
- Misses                           7428     7430       +2     
- Partials                         1475     1480       +5     
Files with missing lines Coverage Δ
.../android/internal/data/SharedPreferencesStorage.kt 100.00% <100.00%> (ø)
...dog/android/profiling/internal/ProfilingFeature.kt 86.67% <100.00%> (-1.57%) ⬇️
...dog/android/profiling/internal/ProfilingStorage.kt 100.00% <100.00%> (ø)
...atadog/android/internal/data/PreferencesStorage.kt 0.00% <0.00%> (ø)
...id/profiling/internal/perfetto/PerfettoProfiler.kt 90.74% <50.00%> (-5.49%) ⬇️
...in/java/com/datadog/android/profiling/Profiling.kt 0.00% <0.00%> (ø)
...og/android/profiling/DdProfilingContentProvider.kt 0.00% <0.00%> (ø)

... and 43 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Comment thread features/dd-sdk-android-profiling/src/main/AndroidManifest.xml Outdated
@ambushwork
ambushwork force-pushed the yl/profiling/defer-profiling branch from d595d0e to da6a14c Compare October 21, 2025 12:11
}

companion object {
internal const val DATADOG_PREFERENCES_FILE_NAME = "dd_prefs"

@aleksandr-gringauz aleksandr-gringauz Oct 21, 2025

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a heads up.

There is this comment in the RFC about the case when we have multiple instances of the SDK in the app.

Currently they will use the same shared preferences which is probably not good. We might need to parametrize this with sdkInstanceName string.

Not a blocking comment for this PR. Maybe you'll come up with better ideas.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 on this: what we are missing is multiple SDK cores support.

To start recording we need that any of the cores requested it (at least with current configuration where sampling rate is hardcoded), so this is probably fine for the flag to be shared, but we need to:

  • make sure that after recording is done it is sent to the proper core which requested it.
  • make sure that we don't run several profiles in parallel.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, I think the multiple SDK core issue is not mainly on SharedPreference flag, but on the ProfilingFeature implementation about writing and uploading events as you said. For the dogfooding it's not an issue, I create a ticket to handle it in as a separate task

@0xnm 0xnm left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think what we are missing is multiple SDK cores support, we need to refine this flow.

* An implementation of [PreferencesStorage] that uses Android's [SharedPreferences] as storage
* backend.
*/
class SharedPreferencesStorage(context: Context) : PreferencesStorage {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

public class is exposing internal interface, there should be warning about this. We need to make interface public as well then.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated

* An implementation of [PreferencesStorage] that uses Android's [SharedPreferences] as storage
* backend.
*/
class SharedPreferencesStorage(context: Context) : PreferencesStorage {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor: let's make it clear what we expect application context here

Suggested change
class SharedPreferencesStorage(context: Context) : PreferencesStorage {
class SharedPreferencesStorage(appContext: Context) : PreferencesStorage {

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated

}

companion object {
internal const val DATADOG_PREFERENCES_FILE_NAME = "dd_prefs"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 on this: what we are missing is multiple SDK cores support.

To start recording we need that any of the cores requested it (at least with current configuration where sampling rate is hardcoded), so this is probably fine for the flag to be shared, but we need to:

  • make sure that after recording is done it is sent to the proper core which requested it.
  • make sure that we don't run several profiles in parallel.

@ambushwork
ambushwork force-pushed the yl/profiling/defer-profiling branch 3 times, most recently from e8d21b1 to 7dbecec Compare October 22, 2025 08:13
@ambushwork
ambushwork force-pushed the yl/profiling/defer-profiling branch 2 times, most recently from 9774f31 to 5509e32 Compare October 22, 2025 11:51
0xnm
0xnm previously approved these changes Oct 22, 2025
Comment thread dd-sdk-android-internal/api/apiSurface Outdated
* An implementation of [PreferencesStorage] that uses Android's [SharedPreferences] as storage
* backend.
*/
class SharedPreferencesStorage(appContext: Context) : PreferencesStorage {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

one downside is that we will trigger Strict Mode violation, because we need to read from disk on I/O thread, but I guess we don't have any other choice.

/**
* Put a string value in the storage.
*/
fun getString(key: String): String?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we are not supplying any default value here as we do with getInt and getBoolean methods?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

Comment thread features/dd-sdk-android-profiling/src/main/AndroidManifest.xml
private const val KEY_PROFILING_ENABLED = "dd_profiling_enabled"

internal fun setProfilingFlag(appContext: Context) {
SharedPreferencesStorage(appContext).putBoolean(KEY_PROFILING_ENABLED, true)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor: each instance creation will involve doing appContext.getSharedPreferences call, which is probably doing I/O, so ideally we could create an instance only once if it is a concern

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update ProfilingStage to singleton with unit test

@ambushwork
ambushwork dismissed stale reviews from 0xnm and aleksandr-gringauz via c4f87a2 October 22, 2025 14:46
@ambushwork
ambushwork force-pushed the yl/profiling/defer-profiling branch from 5509e32 to c4f87a2 Compare October 22, 2025 14:46
Comment on lines +50 to +53
// Reset the singleton
val storageField = ProfilingStorage::class.java.getDeclaredField("sharedPreferencesStorage")
storageField.isAccessible = true
storageField.set(ProfilingStorage, null)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor: probably it is better to do it in the AfterEach (or maybe even in both BeforeEach and AfterEach), because we will leave the object with state set and this object may be used in another test class.

val isEnabled = ProfilingStorage.isProfilingEnabled(mockContext)

// Then
Assertions.assertThat(isEnabled).isTrue()

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: can be a static import

latch.await(5, TimeUnit.SECONDS)

// Then
verify(mockContext, times(1)).getSharedPreferences(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
verify(mockContext, times(1)).getSharedPreferences(
verify(mockContext).getSharedPreferences(

@ambushwork
ambushwork merged commit 46d5192 into feature/perfetto-profiling Oct 23, 2025
25 of 26 checks passed
@ambushwork
ambushwork deleted the yl/profiling/defer-profiling branch October 23, 2025 08:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants