Skip to content

Merged sessions-sharedrepo into main #7039

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 21 commits into
base: main
Choose a base branch
from
Open

Merged sessions-sharedrepo into main #7039

wants to merge 21 commits into from

Conversation

mrober
Copy link
Contributor

@mrober mrober commented Jun 17, 2025

Merged sessions-sharedrepo into main

This merge brings in the new sessions shared repo implementation, which facilitates the Perf+AQS integration. This also includes improvements that will benefit Crashlytics e.g. providing sessions for early crashes

All individual commits on the sessions-sharedrepo branch were reviewed and approved in their respective pull requests

mrober and others added 19 commits June 17, 2025 10:21
Use multi-process DataStore instead of Preferences DataStore.

This change allows multiple processes to share the same datastore file
safely. This reduces settings fetch to one per app run, not one per
process.

Also updated the TimeProvider to provide an object with explicit time
units. This will make time less error prone. Removed all instances of
`System.currentTimeMillis()` from tests, making them deterministic.
With the multi-process data store change, all processes will read the
settings cache from the same file safely. This means if a second process
started, it would read the cache the first process persisted.

But if 2 processes were already running, and one fetched and cached new
settings, it wouldn't automatically share it with the other running
process.

This change fixes that by having all processes watch the file.

Also cleaned up settings a bit, and made everything in seconds to avoid
converting units. Cleaned up unit tests. Also removed the need to lazy
load the cache by doing a double check in the getter instead.

There is more potential to clean up, but let's do it later.
Fix Robolectric tests showing warning about datastore_shared_counter by
falling back to the normal DataStore instance. This is a known issue,
see [b/352047731](http://b/352047731).
This removes all the bound service implementation, and starts the shared
sessions repository implementation. The shared repository is responsible
for sharing session data between processes in a simple way.

This does not detect cold starts yet. The `SharedSessionRepository`
class might be getting too much, we will consider splitting it up as
implementation goes further.
send session event based on data collection and setting config
Fix where we generate and send session details to firelog. Before this,
we might send false positives to firelog, or even update the session
details with a stale copy. Now the session generate and send to firelog
happen inside the datastore transform with the data in datastore.
Implement fake datastore for unit tests. This fake can act like a simple
in memory datastore, but it can also throw provided exceptions on
specific actions. It can throw on update, throw on collect, throw on
init. This will help write unit tests for when datastore fails.
Using try catch block to make datastore fall back to a pre multi-process
supported version. Generate a new session locally then notify to
subscribers
Make background time nullable
For each new session generated, reset background time
Update unit tests
Implement new cold app start detection heuristic.

This is just the reading part, and all the scaffolding. Next step will
be to start writing the process data map.

Tested by unit tests and manual testing with the sessions test app
Implement ProcessDataManager in the way we designed in
https://docs.google.com/document/d/1yEd8dCIzwNwLhRRwkDtzWFx9vxV5d-eQU-P47wDL40k/edit?usp=sharing

Tested manually in the sessions test app, and with unit tests
Implement cold start detection logic as described in
https://docs.google.com/document/d/1yEd8dCIzwNwLhRRwkDtzWFx9vxV5d-eQU-P47wDL40k/edit?usp=sharing

Also renamed process related functions to be more consistent to make the
code less error prone. This is also described in the doc

Tested by unit tests and with the sessions test app
Tested manually using sessions test app. This is a trivial change
Fix the profile case with clear app data. Now the app data will clear in
the setup block, instead of the measure block. This also reads the
output to make sure app data has cleared before proceeding to the
measure block.
Use the same tag for all logs in sessions. This will make it easier to
dogfood, and is consistent with Perf and Crashlytics

If any context is lost by losing the tag named after the class, we can
update those log lines as we run into them. A future change we can do is
refactor to use the firebase common logger
Add more trace buttons to sessions test app to match the detailed test
cases easier
Copy link
Contributor

Firebase AI Mock Responses Check ⚠️

A newer major version of the mock responses for Firebase AI unit tests is available. update_responses.sh should be updated to clone the latest version of the responses: v14.1

Copy link
Contributor

github-actions bot commented Jun 17, 2025

📝 PRs merging into main branch

Our main branch should always be in a releasable state. If you are working on a larger change, or if you don't want this change to see the light of the day just yet, consider using a feature branch first, and only merge into the main branch when the code complete and ready to be released.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Summary of Changes

Hello @mrober, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request integrates a new shared session repository implementation, which is a major architectural overhaul for the Firebase Sessions SDK. The primary goal is to facilitate Perf+AQS integration and enhance Crashlytics session reporting, particularly for early crashes, by enabling multi-process session awareness and improving cold app start detection. This involves a significant shift in how session data and settings are stored and managed across application processes.

Highlights

  • Multi-Process Session Management: I've introduced a new SharedSessionRepository and migrated session data persistence to a custom DataStore implementation, leveraging kotlinx.serialization. This enables robust session management across all application processes, replacing the previous SessionLifecycleService and Preferences DataStore approach.
  • Improved Cold Start Detection: I've added a ProcessDataManager component to manage process-specific data and enhance the heuristic for detecting cold app starts. This is crucial for more accurate session reporting, especially for early crashes.
  • Architectural Refinement: The session lifecycle management has been significantly refactored. The SDK now uses direct ActivityLifecycleCallbacks that interact with the SharedSessionRepository, streamlining the overall architecture and removing the need for a dedicated service.
  • Settings Management Upgrade: Session settings persistence has been upgraded from Preferences DataStore to a custom DataStore that stores SessionConfigs objects. This change improves data integrity, flexibility, and aligns with the new serialization strategy.
  • Test Infrastructure Enhancement: I've added new fake implementations (FakeDataStore, FakeProcessDataManager, FakeSettingsCache) and updated existing tests to fully support the new multi-process and DataStore-based architecture, ensuring comprehensive test coverage for the refactored components.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in issue comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist is currently in preview and may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments to provide feedback.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This PR merges the sessions-sharedrepo branch, enabling multi-process support for Firebase Sessions. The core architectural changes involve adopting MultiProcessDataStoreFactory with Kotlinx Serialization, introducing SharedSessionRepository for centralized session logic, and enhancing cold start detection with ProcessDataManager. The lifecycle management has also been refactored. The changes appear robust, with a couple of points noted for consideration regarding exception logging and potential blocking calls during initialization.

}
}
} catch (ex: Exception) {
Log.d(TAG, "App appForegrounded, failed to update data. Message: ${ex.message}")

Choose a reason for hiding this comment

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

medium

Consider logging exceptions at a higher severity level (e.g., Log.w or Log.e) for better visibility of unexpected failures. Including the full stack trace (ex) would also aid debugging. Additionally, there's a minor typo: "App appForegrounded" should likely be "App foregrounded".

Copy link
Contributor

github-actions bot commented Jun 17, 2025

Test Results

 1 058 files  ± 0   1 058 suites  ±0   36m 2s ⏱️ +10s
 5 978 tests  -  7   5 956 ✅  -  7  22 💤 ±0  0 ❌ ±0 
12 019 runs   - 14  11 975 ✅  - 14  44 💤 ±0  0 ❌ ±0 

Results for commit 21215eb. ± Comparison against base commit f08e0c7.

This pull request removes 28 and adds 21 tests. Note that renamed tests count towards both.
com.google.firebase.sessions.ApplicationInfoTest ‑ applicationInfo_missiongVersionCode_populatesInfoCorrectly
com.google.firebase.sessions.ProcessDetailsProviderTest ‑ getCurrentProcessDetails
com.google.firebase.sessions.SessionGeneratorTest ‑ currentSession_beforeGenerate_throwsUninitialized
com.google.firebase.sessions.SessionGeneratorTest ‑ hasGenerateSession_afterGenerate_returnsTrue
com.google.firebase.sessions.SessionGeneratorTest ‑ hasGenerateSession_beforeGenerate_returnsFalse
com.google.firebase.sessions.SessionLifecycleClientTest ‑ bindToService_registersCallbacks
com.google.firebase.sessions.SessionLifecycleClientTest ‑ doesNotSendLifecycleEventsWithoutEnabledSubscribers
com.google.firebase.sessions.SessionLifecycleClientTest ‑ doesNotSendLifecycleEventsWithoutSubscribers
com.google.firebase.sessions.SessionLifecycleClientTest ‑ handleSessionUpdate_noSubscribers
com.google.firebase.sessions.SessionLifecycleClientTest ‑ handleSessionUpdate_sendsToAllSubscribersAsLongAsOneIsEnabled
…
com.google.firebase.sessions.ApplicationInfoTest ‑ applicationInfo_missingVersionCode_populatesInfoCorrectly
com.google.firebase.sessions.FakeDataStoreTest ‑ consistentAfterManyUpdates
com.google.firebase.sessions.FakeDataStoreTest ‑ emitsProvidedValues
com.google.firebase.sessions.FakeDataStoreTest ‑ throwsFirstProvidedExceptionOnCollect
com.google.firebase.sessions.FakeDataStoreTest ‑ throwsFirstProvidedExceptionOnFirst
com.google.firebase.sessions.FakeDataStoreTest ‑ throwsProvidedExceptionOnEmit
com.google.firebase.sessions.FakeDataStoreTest ‑ throwsProvidedExceptionOnUpdateData
com.google.firebase.sessions.ProcessDataManagerTest ‑ isColdStart_emptyProcessDataMap
com.google.firebase.sessions.ProcessDataManagerTest ‑ isColdStart_myProcess
com.google.firebase.sessions.ProcessDataManagerTest ‑ isColdStart_myProcessStale_otherProcessCurrent
…

♻️ This comment has been updated with latest results.

@google-oss-bot
Copy link
Contributor

google-oss-bot commented Jun 17, 2025

Size Report 1

Affected Products

  • firebase-crashlytics

    TypeBase (f08e0c7)Merge (0386ca7)Diff
    apk (aggressive)785 kB683 kB-102 kB (-13.0%)
    apk (release)6.65 MB6.12 MB-529 kB (-8.0%)
  • firebase-crashlytics-ktx

    TypeBase (f08e0c7)Merge (0386ca7)Diff
    apk (aggressive)785 kB683 kB-102 kB (-13.0%)
    apk (release)6.65 MB6.12 MB-529 kB (-8.0%)
  • firebase-crashlytics-ndk

    TypeBase (f08e0c7)Merge (0386ca7)Diff
    apk (aggressive / arm64-v8a)2.15 MB2.04 MB-102 kB (-4.8%)
    apk (aggressive / armeabi-v7a)1.61 MB1.51 MB-102 kB (-6.4%)
    apk (aggressive / x86)2.09 MB1.99 MB-102 kB (-4.9%)
    apk (aggressive / x86_64)2.12 MB2.01 MB-102 kB (-4.8%)
    apk (release / arm64-v8a)8.00 MB7.47 MB-528 kB (-6.6%)
    apk (release / armeabi-v7a)7.47 MB6.94 MB-528 kB (-7.1%)
    apk (release / x86)7.95 MB7.42 MB-528 kB (-6.6%)
    apk (release / x86_64)7.97 MB7.44 MB-528 kB (-6.6%)
  • firebase-sessions

    TypeBase (f08e0c7)Merge (0386ca7)Diff
    aar203 kB216 kB+13.5 kB (+6.7%)
    apk (aggressive)645 kB539 kB-106 kB (-16.4%)
    apk (release)6.31 MB5.79 MB-529 kB (-8.4%)

Test Logs

  1. https://storage.googleapis.com/firebase-sdk-metric-reports/jiG88hfevX.html

@google-oss-bot
Copy link
Contributor

google-oss-bot commented Jun 17, 2025

Coverage Report 1

Affected Products

  • firebase-database

    Overall coverage changed from 50.18% (f08e0c7) to 50.15% (872cada) by -0.03%.

    FilenameBase (f08e0c7)Merge (872cada)Diff
    DefaultPersistenceManager.java75.73%74.76%-0.97%
    ViewProcessor.java92.10%91.79%-0.30%
    WriteTree.java77.22%76.67%-0.56%
  • firebase-sessions

    Overall coverage changed from 66.56% (f08e0c7) to 81.63% (872cada) by +15.07%.

    29 individual files with coverage change

    FilenameBase (f08e0c7)Merge (872cada)Diff
    DaggerFirebaseSessionsComponent.java0.00%94.23%+94.23%
    FirebaseSessions.kt0.00%53.57%+53.57%
    FirebaseSessionsComponent.kt0.00%65.79%+65.79%
    FirebaseSessionsComponent_MainModule_Companion_SessionDataStoreFactory.java?0.00%?
    FirebaseSessionsComponent_MainModule_Companion_TimeProviderFactory.java0.00%100.00%+100.00%
    FirebaseSessionsComponent_MainModule_Companion_UuidGeneratorFactory.java0.00%100.00%+100.00%
    FirebaseSessionsDependencies.kt85.71%92.00%+6.29%
    FirebaseSessionsRegistrar.kt0.00%90.91%+90.91%
    ProcessDataManager.kt?71.43%?
    ProcessDataManagerImpl_Factory.java?0.00%?
    ProcessDetailsProvider.kt76.67%76.00%-0.67%
    RemoteSettings.kt87.32%88.41%+1.08%
    RemoteSettingsFetcher.kt0.00%10.00%+10.00%
    SessionConfigs.kt?95.45%?
    SessionData.kt?58.82%?
    SessionDataSerializer_Factory.java?0.00%?
    SessionDetails.kt?85.71%?
    SessionFirelogPublisher.kt84.21%83.33%-0.88%
    SessionGenerator.kt90.91%100.00%+9.09%
    SessionsActivityLifecycleCallbacks.kt55.56%18.75%-36.81%
    SessionsActivityLifecycleCallbacks_Factory.java?0.00%?
    SessionsSettings.kt96.88%93.75%-3.13%
    SessionSubscriber.kt100.00%75.00%-25.00%
    SettingsCache.kt93.55%80.56%-12.99%
    SettingsCacheImpl_Factory.java?0.00%?
    SharedSessionRepository.kt?79.84%?
    SharedSessionRepositoryImpl_Factory.java?0.00%?
    TimeProvider.kt0.00%75.00%+75.00%
    UuidGenerator.kt0.00%100.00%+100.00%

  • firebase-storage

    Overall coverage changed from 83.96% (f08e0c7) to 84.00% (872cada) by +0.04%.

    FilenameBase (f08e0c7)Merge (872cada)Diff
    NetworkRequest.java87.29%87.85%+0.55%
  • firebase-firestore

    FilenameBase (f08e0c7)Merge (872cada)Diff
    DeleteMutation.java95.24%90.48%-4.76%
    SetMutation.java94.44%97.22%+2.78%

Test Logs

  1. https://storage.googleapis.com/firebase-sdk-metric-reports/0hvPfGTZ1F.html

@google-oss-bot
Copy link
Contributor

google-oss-bot commented Jun 17, 2025

Startup Time Report 1

The report is too large (122,633 chars) to be displayed on GitHub. Please check this report on GCS.

  1. https://storage.googleapis.com/firebase-sdk-metric-reports/tUax1aZ1Ay/index.html

Copy link
Contributor

@themiswang themiswang left a comment

Choose a reason for hiding this comment

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

Reviewed cold start detection offline

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants