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

Snowplow.createTracker takes 10 seconds? #620

Closed
peterdk opened this issue Jun 23, 2023 · 18 comments
Closed

Snowplow.createTracker takes 10 seconds? #620

peterdk opened this issue Jun 23, 2023 · 18 comments
Labels
type:defect Bugs or weaknesses. The issue has to contain steps to reproduce.

Comments

@peterdk
Copy link

peterdk commented Jun 23, 2023

Describe the bug
When initiating Snowplow it takes 10 seconds to complete that call.....

To Reproduce
val network = NetworkConfiguration(endpoint = "url", HttpMethod.POST)
val config = TrackerConfiguration(context.packageName).screenViewAutotracking(true)
Snowplow.createTracker(
context = context,
namespace = "namespace",
network = network,
config,
)

Expected behavior
200ms setup time or something reasonable.

Device information (please complete the following information):

  • Device: Pixel 6a
  • OS: Android 14
  • Version com.snowplowanalytics:snowplow-android-tracker:5.2.0

Additional context
Not useable this way

@peterdk peterdk added the type:defect Bugs or weaknesses. The issue has to contain steps to reproduce. label Jun 23, 2023
@peterdk
Copy link
Author

peterdk commented Jun 23, 2023

Also on Android 9, Samsung Note

@matus-tomlein
Copy link
Contributor

Hi @peterdk, that is very unexpected, could you please help me replicate this?

I have created a blank new Android app and pasted in the code that you provided above, see here.
However, when I try to test, the createTracker call is instant:

D/Snowplow: Fri Jun 23 12:58:45 GMT+02:00 2023 Snowplow tracker starting
I/TetheringManager: registerTetheringEventCallback:com.example.testlagapp
D/Snowplow: Fri Jun 23 12:58:45 GMT+02:00 2023 Snowplow tracker created

Could you please tell me what is different about your setup or help me extend the app to replicate the problem?

@peterdk
Copy link
Author

peterdk commented Jun 23, 2023

Yeah, I just moved the code to onCreate, like in the docs, and there it runs indeed very fast.
We use Koin with a lot of dependencies, so I'll look into this next week to see if I can find out what is causing this hang. Can it be that we call createTracker on a background thread and that gives issues?

@matus-tomlein
Copy link
Contributor

I don't think running on a background thread should be the problem - I have just tried it and the call was instant as well.

@peterdk
Copy link
Author

peterdk commented Jun 23, 2023

I debugged, and we indeed load our analytics module and thus also Snowplow, on a background coroutine dispatcher/thread.
I can reproduce the slow start if I make the main thread during that process busy:

CoroutineScope(Dispatchers.Default  + SupervisorJob()).launch{ createTracker()}
Thread.sleep(5000)

What I see is that with this sleep of the main thread, the createTracker only returns after the main thread is done. Without it it returns indeed in a few 100ms. So I guess SnowPlow needs the main thread somewhere in its initialisation code and has to wait until that thread is available, before being able to return the tracker.

Ofcourse we don't sleep on the main thread, but it is busy for a long time.

@peterdk
Copy link
Author

peterdk commented Jun 23, 2023

Probably can be reproduced without coroutines, since we don't use anything here that is coroutine related.

@matus-tomlein
Copy link
Contributor

Interesting! I can't think of anything in the tracker that would require running on the main thread, but will look into this!

@peterdk
Copy link
Author

peterdk commented Jun 23, 2023

Yes, with:

 Thread {
            SnowPlowTracker.setup(this)
       }.start()
Thread.sleep(5000)

I have the same result. (Method is just calling the proper Snowplow setup in it)

@matus-tomlein
Copy link
Contributor

I think I am still missing something here, because when I tried to do this in the example app, see here, the createTracker call is still instant based on the log:

D/Snowplow: Fri Jun 23 13:45:04 GMT+02:00 2023 Snowplow tracker starting
I/TetheringManager: registerTetheringEventCallback:com.example.testlagapp
D/Snowplow: Fri Jun 23 13:45:04 GMT+02:00 2023 Snowplow tracker created

@peterdk
Copy link
Author

peterdk commented Jun 23, 2023

I'll try to look in a working example there.

@peterdk
Copy link
Author

peterdk commented Jun 23, 2023

I can't reproduce it indeed in the test project. Also not when I move it tot an Application class. I'll look into it next week to see if I can reproduce it, otherwise we'll work around it.

@peterdk
Copy link
Author

peterdk commented Jun 23, 2023

So I profiled the boot of our app, and the Snowplow thread I use to setup the tracker waits due to the Google Advertising ID:
hang

@dpgmedia-gbero
Copy link

We're experiencing the same issue here. Hard to say why yet, but can you point us to where is the offloading from the main thread done in order to retrieve the getAndroidIdfa

@peterdk do you have any pointer on how did you solve this ?

@matus-tomlein
Copy link
Contributor

Hi @dpgmedia-gbero, there are two ways that the getAndroidIdfa may be called:

  1. During tracker initialization – in case you initialize the tracker on a background thread (as @peterdk has done above), the IDFA will be retrieved on the same thread. However, if you initialize the tracker on the UI thread, retrieving the IDFA will fail in this way as Android does not allow it.
  2. Later when individual events are processed on a background thread (the new thread is dispatched here).

Since version 6 of the trackers, there is now an option to override how the tracker retrieves the IDFA and provide a custom retriever function – see the docs here. Maybe it would be worth overriding this to see if it solves the problem?

@dpgmedia-gbero
Copy link

dpgmedia-gbero commented Feb 23, 2024

Hi @matus-tomlein thanks for your reply.

I could reproduce the issue in your setup by adding gms ads dependency, see here

Screenshot 2024-02-23 at 11 33 05

@dpgmedia-gbero
Copy link

The 10-second duration is actually caused by :

java.io.IOException: java.util.concurrent.TimeoutException: Timed out waiting for the service connection in the catch of getAndroidIdfa()

@peterdk
Copy link
Author

peterdk commented Feb 23, 2024

I did not yet find a proper solution for this as well. I can initialize in onCreate(), but that makes my co-devs not very happy, since we just want to do this in Koin.

I tried the 6.0.1 version, and then fetch the Idfa myself earlier in the init method, but that also caused the same blocking.

Hopefully the repro from gbero can lead to a working fix. For now we temporarily disable idfa by returning null from PlatformContextReceiver androidIdfa method.

@matus-tomlein
Copy link
Contributor

Thanks @dpgmedia-gbero, that is super useful to be able to reproduce! We will look into this and aim for a patch release with a fix.

The solution might actually be pretty simple – add this kind of condition to check that we are not on the main thread in the getAndroidIdfa function.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type:defect Bugs or weaknesses. The issue has to contain steps to reproduce.
Projects
None yet
Development

No branches or pull requests

3 participants