Skip to content
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

OfflineStorage_Room::GetAndReserveRecords crash in Android #1227

Open
FreddyJD opened this issue Dec 16, 2023 · 6 comments
Open

OfflineStorage_Room::GetAndReserveRecords crash in Android #1227

FreddyJD opened this issue Dec 16, 2023 · 6 comments
Labels
bug Something isn't working

Comments

@FreddyJD
Copy link

Describe your environment. Latest 1DS C++ SDK v3.7.62.1

Steps to reproduce.
No repro just a crash report from AppCenter from our Android app.

What is the expected behavior?
N/A

What is the actual behavior?
N/A

Additional context.
This is the crash in appcenter

libmaesdk.so
Microsoft::Applications::Events::OfflineStorage_Room::GetAndReserveRecords(std::__ndk1::function<bool (Microsoft::Applications::Events::StorageRecord&&)> const&, unsigned int, Microsoft::Applications::Events::EventLatency, unsigned int)
libmaesdk.so
Microsoft::Applications::Events::StorageObserver::handleRetrieveEvents(std::__ndk1::shared_ptr<Microsoft::Applications::Events::EventsUploadContext> const&)
libmaesdk.so
Microsoft::Applications::Events::TransmissionPolicyManager::uploadAsync(Microsoft::Applications::Events::EventLatency)
libmaesdk.so
Microsoft::Applications::Events::PlatformAbstraction::WorkerThread::threadFunc(void*)
libmaesdk.so
void* std::__ndk1::__thread_proxy<std::__ndk1::tuple<std::__ndk1::unique_ptr<std::__ndk1::__thread_struct, std::__ndk1::default_delete<std::__ndk1::__thread_struct> >, void (*)(void*), void*> >(void*)

We are not sending events right now just initializing:

override fun initialize(context: Context) {
        loadLibraries()
        setupHttpClient(context)
        setupOfflineRoom(context)
        initializeLogger()
    }

    private fun loadLibraries() {
        System.loadLibrary(TelemetryConstants.MAE_SDK_LIB_NAME)
    }

    private fun setupHttpClient(context: Context) {
        HttpClient(context.applicationContext)
    }

    private fun setupOfflineRoom(context: Context) {
        OfflineRoom.connectContext(context.applicationContext)
    }
@FreddyJD FreddyJD added the bug Something isn't working label Dec 16, 2023
@anod
Copy link
Member

anod commented Dec 17, 2023

Do you use main thread to initalize Room?

@FreddyJD
Copy link
Author

FreddyJD commented Dec 18, 2023

Hi @anod It seems so, yes. Is this issue causing crashes for the users? It only affects a small portion of our user base, and we've followed the setup in the repository.

After reviewing the documentation, it appears that Room, HTTP, and the library need to be initialized before we can initialize the loggers.

image

@anod
Copy link
Member

anod commented Dec 18, 2023

Yes, initialization looks correct,
looking on stack, the crash is happening during uploading an event when it tires to load records from Room DB

Is it possible to add line number to stack trace nd error message?
Do you know if the crash is happening during a specific lifecycle: openning app or closing?

@FreddyJD
Copy link
Author

FreddyJD commented Dec 19, 2023

@anod App Center reports the only function names where the crash occurs (from native crashes atleast). It appears to be random. Also we are not sending events right now; we are just initializing. So, the issue could be occurring after a background notification, while using the app, or after some time has passed (reporting session times are random)

Question to clarify, is this function called only during the creation of the Room database? Seems that is happening with an Observable that the library sets*

@FreddyJD
Copy link
Author

To add more context, we are creating 3 loggers currently.

private fun getLogConfiguration(apiKey: String, teamName: String): ILogConfiguration {
        val config = LogManager.getLogConfigurationCopy().apply {
            set(LogConfigurationKey.CFG_STR_PRIMARY_TOKEN, apiKey)
            set(LogConfigurationKey.CFG_STR_FACTORY_NAME, teamName)
            set(LogConfigurationKey.CFG_STR_FACTORY_HOST, teamName)
        }
        return config
    }

    private fun initializeLogger() {
        if (loggerAuthApp == null) {
            val logConfigAuthApp = getLogConfiguration(TelemetryClientType.AUTHAPP.apiKey, "authapp")
            loggerAuthApp = LogManagerProvider.createLogManager(logConfigAuthApp)
                .getLogger(TelemetryClientType.AUTHAPP.apiKey, "authapp", "")
        }
        if (loggerPIM == null) {
            val logConfigPIM = getLogConfiguration(TelemetryClientType.PIM.apiKey, "pim")
            loggerPIM = LogManagerProvider.createLogManager(logConfigPIM)
                .getLogger(TelemetryClientType.PIM.apiKey, "pim", "")
        }
        if (loggerDID == null) {
            val logConfigDID = getLogConfiguration(TelemetryClientType.DID.apiKey, "did")
            loggerDID = LogManagerProvider.createLogManager(logConfigDID)
                .getLogger(TelemetryClientType.DID.apiKey, "did", "")
        }
    }

@anod
Copy link
Member

anod commented Dec 21, 2023

The trace posted is trying to uploadAsync something, looking in the source, the flow looks following: scheduleUpload >> uploadAsync >> initiateUpload >> retrieveEvents >> handleRetrieveEvents >> GetAndReserveRecords.

May be some stats info is being collected, not familiar with it, you can try to disable stats via configuration and see if it helps

The code crashes when accessing Room DB via GetAndReserveRecords,
I would also suggest to verify that:

  • Code that initializes Room, Http client and loggers runs once.
  • Code that initializes loggers creates 3 separate database files.

we use the following code, to create multiple loggers:

            val config = LogManager.logConfigurationFactory().apply {
                set(LogConfigurationKey.CFG_STR_PRIMARY_TOKEN, token)
                set(LogConfigurationKey.CFG_STR_COLLECTOR_URL, collectorUrl)
                set(LogConfigurationKey.CFG_STR_FACTORY_NAME, name + UUID.randomUUID())
            }

            val logManager = LogManagerProvider.createLogManager(config)
            return logManager.getLogger(token, "", "")

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants