dd-sdk-flutter
dd-sdk-flutter copied to clipboard
Calling DatadogSdk.instance.setUserInfo doesn't update ongoing RUM sessions
Describe the bug
For context, we have a flutter application with a standard JWT auth setup. We have configured to call DatadogSdk.instance.setUserInfo whenever we get the first access token for our session in order to distinguish anonymous vs user RUM sessions. This can either be:
- when a new user first logs in
- when an existing user opens the app, and we verify the validity of their token in local storage
When doing analysis of our onboarding flow dropoff, we noticed that our user IDs are not attached to the first session of newly created accounts. Here is a screenshot:
So you can see that the upper half of that session is for an anonymous user who hasn't craeted an account yet. After the tap on log_in button we have a token so the app would've called DatadogSdk.instance.setUserInfo. However the session does not have any user attached to its attributes
Here is what a session with a user looks like:
I am not sure what the expected behaviour here is? I would assume either the session gets split in two, or the user gets attributed to the anonymous events as well. But currently we are losing all data altogether, which makes it harder to measure onboarding flow drop off for those first user sessions, does that make sense?
If this is expected behaviour, is there a way to work around it? Perhaps some method in the SDK that restarts the session when the user has been identified?
Reproduction steps
Start a session as an anonymous user, and subsequently authenticate. Observe that the user attributes are not applied to the session
SDK logs
No response
Expected behavior
No response
Affected SDK versions
2.4.0, 2.5.0
Latest working SDK version
Did you confirm if the latest SDK version fixes the bug?
Yes
Flutter Version
3.19.6
Setup Type
Flutter Application
Device Information
seems to be device-agnostic. We've seen this happening on Android & iOS devices alike
Other relevant information
No response
Hi @mbtodorov,
Do the events (view events, action events, etc) after your call to setUserInfo have the appropriate user information, but this information isn't being applied to the entire session?
I do think this is intended behavior, but I will look into whether there's a workaround or query you can do that will get you the information you need.
Do the events (view events, action events, etc) after your call to setUserInfo have the appropriate user information
Thats a good question, forgot to post a screenshot of that. The events themselves also dont have any user info attached.
I do think this is intended behavior, but I will look into whether there's a workaround or query you can do that will get you the information you need.
This will be much appreciated, thank you. I tried finding a way to force terminate the session and start a new one but couldnt find any method in the SDK.
Thats a good question, forgot to post a screenshot of that. The events themselves also dont have any user info attached.
I don't think that is correct. I will look into it.
I tried finding a way to force terminate the session and start a new one but couldnt find any method in the SDK.
There is a method you can use to stop a Datadog Session on the rum member:
DatadogSdk.instance.rum?.stopSession();
This will stop the current session. The next user action (view change or call to addAction) will start a new session.
@fuzzybinary thanks for the quick workaround. I am not sure how i missed that method.. I have just tested it and it works as a workaround - we can split the session in two, one part anonymous and one part authenticated. I am happy to close this issue with this.
However, let me know if you would perhaps like to keep it open, while you verify that not having the attributes attached even in the individual events is expected behaviour
I don't think that is correct. I will look into it.
Let's keep it open, as we agree the User information should be applied to all events after the call to setUserInfo even if they aren't applied to the session itself.
Can you contact Datadog support to open an issue and point them to this Github issue? That will let us get a bit more information.
Thanks!
@mbtodorov I was originally able to reproduce this but I checked again with the latest SDK and wasn't able to reproduce. Would you be able to check with 2.6.0 and see if this still happens?
I just checked with the latest datadog SDK version and I can still reproduce it. Its worth noting that it is somewhat flaky in reproduction - for instance, i was only able to reproduce it 1 out of 3 times. From a rough analysis we did, we think its happening to about 60% of freshly created account sessions in production, but we cant tell for sure
Thanks @mbtodorov, that's good information to have. It sounds like this is a weird concurrency issue. I'll continue to look into it.
Hi there,
Is there an update on this? We're seeing very similar symptoms, meaning we call setUserInfo very early during app boot up, but still see a ton of actions in the dashboard without a user ID attached to them.
Is calling stopSession during boot up, right before calling setUserInfo a sensible workaround? Will it work?
Hi @juan-tado ,
Sorry, this fell off my radar a bit, as I've been having trouble reproducing. I'll pick it up again this week and figure out what's going wrong.
Are you also only seeing this on iOS?
@fuzzybinary yeah both Android and iOS.
Happy to share our DD application ID privately if it helps.
yeah both Android and iOS.
Really? This is new information. I could only ever reproduce on iOS and then only intermittently.
No need to share your application ID. If you open a support ticket with Datadog and point them to this ticket they should escalate to me fairly quickly, but I'm not sure I'll be able to get much out of your data as I think it's a reporting issue.
So, I'm still trying to reproduce this issue consistently, but one thing we've noticed is that setting the user info does not trigger an immediate update to RUM, though any subsequent actions will. So if no actions are sent post calling setUserInfo, that would result in a userless session.
I'm not sure if that's the root of your issue, but one simple way to test is to add a custom action immediately after setUserInfo. So for example:
DatadogSdk.instance.setUserInfo(id: 'user');
DatadogSdk.instance.rum?.addAction(RumActionType.custom, 'UserLogin');
If that seems to solve your issue, then I can look into a potential fix for that specifically.
We seem to have found a different workaround which we've just put into production, so we'll know more in a few days.
Basically:
var datadogConfiguration = DatadogConfiguration();
...
await DatadogSdk.runApp(datadogConfiguration, TrackingConsent.pending, () async {
DatadogSdk.instance.setUserInfo(id: "xxxxxx");
...
}
So far it looks like all the events are now correctly coming with their user ID.
Where was the setUserInfo call prior to this?
@fuzzybinary outside, after datadogConfiguration, right before await DatadogSdk.runApp.
Ah, this is because runApp initializes Datadog. The call for setUserInfo is a no-op prior to Datadog being initialized.
I seeeeeee. Well, you might want to mention that in the documentation about setUserInfo, throw or at least leave a log in the console.
It might feel obvious, but in our case we recently migrated from an old unofficial DD library to the official one and this just seemed to work. We only realized doing some unrelated analysis.
Anyway, mystery solved.
For me I was passing an Object into one of extraInfo's key's value, but it really wanted a string. It took me a long time to finally see in the logs the little log output showing ArgumentError. This broke the functionality to set user info in DD. 🤦
setUserInfo says it can take a Map<String, Object?>, but you're better off passing Map<String, String?>. I guess if you're passing an Object, then nested therein the terminal values should respond to toString() is my guess. 🤷
My user's preferredLanguage returned an enum LanguageCode, so to fix it I had to call a method on it that returns a string.
DatadogSdk.instance.setUserInfo(
id: 'someUserId',
extraInfo: {
'preferred_language': user.preferredLanguage, // this doesn't raise an exception; it just reports the error in logs
},
);
---
flutter: [Datadog 🐶⚠️ ] ArgumentError when calling setUserInfo: parameter null. It looks like preferred_language is of type LanguageCode, which is not supported.