Page MenuHomePhabricator

[Bug] WMFDailyStatsLoggingFunnel doesn't send event on the day users opt-in from setting
Closed, ResolvedPublic

Description

The current behavior is:
If a user opt in during onboarding, we will log it in MobileWikiAppDailyStats with appInstallAgeDays = 0
If a user opt in in the setting, we will NOT log it in MobileWikiAppDailyStats with the current appInstallAgeDays, but only when appInstallAgeDays changes

Expected behavior:
When a user opt in in the setting, we log it in MobileWikiAppDailyStats with the current appInstallAgeDays

Steps to reproduce
1, Set a break point in WMFDailyStatsLoggingFunnel
2, Erase all content and settings in simulator
3, Build and Install the app, write down the appInstallID when the app is initialized and make sure daysInstalledNumber=0
4, Turn on "Send usage reports"
5, Launch the app several times later
6, Query the appInstallID in MobileWikiAppDailyStats ~2h later

Actual Result
We did not see any record for this appInstallID

See also T193908

Event Timeline

Tbayer renamed this task from [Bug] MobileWikiAppDailyStats is not tracking every user to [Bug] MobileWikiAppDailyStats is not tracking every opted-in user.Mar 11 2018, 1:40 AM
Tbayer updated the task description. (Show Details)
JMinor triaged this task as Medium priority.Mar 12 2018, 5:43 PM
JMinor raised the priority of this task from Medium to High.
JMinor moved this task from Needs Triage to Bug Backlog on the Wikipedia-iOS-App-Backlog board.

By default, when users install the iOS app, they're opted-out to be track by EL. Even if they opt-in when they first launch the app, we should not see any record in MobileWikiAppDailyStats for any user on > day 0, because the daysInstalledNumber saved in the app hasn't changed (see the code). However, we're still seeing ~700 appInstallId whose appInstallAgeDays = 0.

Confirmed this is a bug, easy to fix.

If you opt in to send usage reports during onboarding (as opposed to doing it in Settings later), we will log it in MobileWikiAppDailyStats (with the appInstallID generated by WMFDailyStatsLoggingFunnel). You can check it by opting in to send usage reporting during onboarding, and setting a breakpoint in https://github.com/wikimedia/wikipedia-ios/blob/e444abd854fc79af9caf2440439c40d70b65cb75/Wikipedia/Code/EventLogger.m#L33. If you look at the event dictionary. appInstallAgeDays will equal 0. It's because in the first call to logAppNumberOfDaysSinceInstall (https://github.com/wikimedia/wikipedia-ios/blob/1d2548e869086a279b90c2302feeb4cbadd31b59/Wikipedia/Code/WMFDailyStatsLoggingFunnel.m#L19) this if https://github.com/wikimedia/wikipedia-ios/blob/1d2548e869086a279b90c2302feeb4cbadd31b59/Wikipedia/Code/WMFDailyStatsLoggingFunnel.m#L33 fails and we lose our chance to compare lastLoggedDaysInstalled with current daysInstalled. So if at that time we know that user opted in, we will log it, even if appInstallAgeDays = 0.

MobileWikiAppDailyStats is 100% sampling and should be tracking every opted-in user every day. However, we have only ~60k distinct iOS appInstallIDs daily in MobileWikiAppDailyStats in March so far, > while there are ~150k distinct iOS appInstallIDs daily in mobile_apps_uniques which is an aggregated table from webrequest.

It looks like we're generating a bunch of different ids for different actions, which perhaps explains the elevated number of ids in mobile_apps_uniques? For example, WMFShareFunnel generates its own id (https://github.com/wikimedia/wikipedia-ios/blob/63ed11842066de7fee35028350ff3ff4d43a296a/Wikipedia/Code/WMFShareFunnel.m#L56). So if a user saves an article and shares an article, on that day we would log an id generated by WMFDailyStatsLoggingFunnel, one generated by ReadingActionFunnel (related to T189356), and one generated by WMFShareFunnel. That would mean one distinct id in MobileWikiAppDailyStats, and 3 distinct ids in mobile_apps_uniques. WMFSuggestedPagesFunnel, WMFSearchFunnel, WMFHamburgerMenuFunnelgenerate their own ids too.

If you opt in to send usage reports during onboarding (as opposed to doing it in Settings later), we will log it in MobileWikiAppDailyStats (with the appInstallID generated by WMFDailyStatsLoggingFunnel).

Thanks @NHarateh_WMF ! I didn't know user can opt in during onboarding :P

So the current behavior is:

  1. if a user opt in during onboarding, we will log it in MobileWikiAppDailyStats with appInstallAgeDays = 0
  2. if a user opt in in the setting, we will NOT log it in MobileWikiAppDailyStats

After your fix, the behavior will become:
Whether a user opt in during onboarding or in setting, we will log it in MobileWikiAppDailyStats with appInstallAgeDays = 0

Is that right?

It looks like we're generating a bunch of different ids for different actions, which perhaps explains the elevated number of ids in mobile_apps_uniques? For example, WMFShareFunnel generates its own id (https://github.com/wikimedia/wikipedia-ios/blob/63ed11842066de7fee35028350ff3ff4d43a296a/Wikipedia/Code/WMFShareFunnel.m#L56). So if a user saves an article and shares an article, on that day we would log an id generated by WMFDailyStatsLoggingFunnel, one generated by ReadingActionFunnel (related to T189356), and one generated by WMFShareFunnel. That would mean one distinct id in MobileWikiAppDailyStats, and 3 distinct ids in mobile_apps_uniques. WMFSuggestedPagesFunnel, WMFSearchFunnel, WMFHamburgerMenuFunnelgenerate their own ids too.

Does that mean that the ID logged by this line (seems to be generating the header for all api calls to me. mobile_apps_uniques get the ID from the header.) varies by different types of api calls? Isn't it the same ID as ReadingActionFunnel?

@chelsyx

So the current behavior is:
if a user opt in during onboarding, we will log it in MobileWikiAppDailyStats with appInstallAgeDays = 0
if a user opt in in the setting, we will NOT log it in MobileWikiAppDailyStats

Correct! If a user opts in via settings, we will log it when appInstallAgeDays changes, but not when appInstallAgeDays = 0.

After your fix, the behavior will become:
Whether a user opt in during onboarding or in setting, we will log it in MobileWikiAppDailyStats with appInstallAgeDays = 0

If that's the desired behavior, then yes :D I can also implement it so that we don't ever log it in MobileWikiAppDailyStats if appInstallAgeDays = 0, regardless of how the user opted in. Whichever you prefer

Does that mean that the ID logged by this line (seems to be generating the header for all api calls to me. mobile_apps_uniques get the ID from the header.) varies by different types of api calls? Isn't it the > same ID as ReadingActionFunnel?

Yes, it varies, even though looking at that header I too would assume that all those requests are sent with the ID generated by ReadingActionFunnel. Here are the repro steps to see that there's a bunch of different ids being sent

  1. Set a breakpoint here https://github.com/wikimedia/wikipedia-ios/blob/e444abd854fc79af9caf2440439c40d70b65cb75/Wikipedia/Code/EventLogger.m#L39
  2. Clean install, opt in to send reports during onboarding :D

Simulator Screen Shot - iPhone X - 2018-05-03 at 12.11.50.png (2×1 px, 179 KB)

  1. When breakpoint is triggered for the first time, po event and note the ID (that's the one generated by WMFDailyStatsLoggingFunnel)
  2. Continue execution
  3. Save one of the articles in the feed
  4. When breakpoint is triggered, po event and note the ID (that's the one generated by ReadingActionFunnel)
  5. Continue execution
  6. Open that article and tap share on the article toolbar
  7. When breakpoint is triggered, po event and note the ID (that's a different ID generated by WMFShareFunnel)

It looks like WMFSuggestedPagesFunnel, WMFSearchFunnel and WMFHamburgerMenuFunnelgenerate aren't even used anywhere so it's safe to disregard those.

After your fix, the behavior will become:
Whether a user opt in during onboarding or in setting, we will log it in MobileWikiAppDailyStats with appInstallAgeDays = 0

If that's the desired behavior, then yes :D

Thanks @NHarateh_WMF ! Yes! This is what I want! :D

Yes, it varies, even though looking at that header I too would assume that all those requests are sent with the ID generated by ReadingActionFunnel. Here are the repro steps to see that there's a bunch of different ids being sent

I'm sorry if I confused you :(
Your repro steps show that we are sending different IDs for different events logged by different funnels.

However, the problem of this ticket is also about the X-Analytics header sent along with the API calls. For example, when I tap to read an article "Mount Potalaka" on the app, our server will receive a request like:
en.wikipedia.org/w/api.php?action=mobileview&format=json&noheadings=true&page=Mount%20Potalaka&pilicense=any&prop=sections%7Ctext%7Clastmodified%7Clastmodifiedby%7Clanguagecount%7Cid%7Cprotection%7Ceditable%7Cdisplaytitle%7Cthumb%7Cdescription%7Cimage%7Crevision%7Cnamespace&sectionprop=toclevel%7Cline%7Canchor%7Clevel%7Cnumber%7Cfromtitle%7Cindex&sections=all&thumbwidth=640
Similar request will be sent during App initialization. Along with this API call, the X-Analytics header which contains an wmfuuid will be sent, like:
ns=0;page_id=25807626;loggedIn=1;WMF-Last-Access=05-Mar-2018;WMF-Last-Access-Global=05-Mar-2018;https=1;wmfuuid=3A5FC461-5F94-4B85-9857-64A552DF7D98
The wmfuuid is the appInstallID generated by [L15 in AFHTTPRequestSerializer+WMFRequestHeaders.m](https://github.com/wikimedia/wikipedia-ios/blob/1d2548e869086a279b90c2302feeb4cbadd31b59/Wikipedia/Code/AFHTTPRequestSerializer%2BWMFRequestHeaders.m#L15) which is the same as ReadingActionFunnel, and we want it to be the same as the one we send to WMFDailyStatsLoggingFunnel and all other funnels.

Steps to reproduce:

We count the number of unique wmfuuid to get the number of unique devices for [mobile_apps_uniques](https://wikitech.wikimedia.org/wiki/Analytics/Data_Lake/Traffic/mobile_apps_uniques). Regardless of the different IDs from different funnels, my main concern is that there is a large discrepancy in their counts. That is to say, if a user use the app at least once on a given day, we should have records in both MobileWikiAppDailyStats (with an ID) and request sent to our server to fetch the feed (with another ID), because both the event and the request are sent during app initialization. However, when we count the number of unique IDs in MobileWikiAppDailyStats, there are ~60k per day; when we count the number of unique IDs in our web request, there are ~150k per day.

Sorry again for the confusion. I should have put the "Related issue" part of this ticket into another ticket because they are two different problems. Please ping me if it is still not clear and we can have a quick video chat :)

To be clear, the issues related to appInstallID are:

1, [Reason Identified] Multiple IDs generated by different funnels
(Mostly related to T189356, but there are also some discussion in T189359#4178912)
WMFDailyStatsLoggingFunnel, ReadingActionFunnel and WMFShareFunnel (not sure if there are others) generate different appInstallID. Among them, WMFShareFunnel and WMFDailyStatsLoggingFunnel only send the ID to their corresponding eventlogging schemas, while ReadingActionFunnel send ID to BOTH eventlogging schema AND X-Analytics header along with api calls to retrieve feed, articles, etc. We want to use the same appInstallID across all schemas and X-Analytics header.

2, [Reason Identified] WMFDailyStatsLoggingFunnel doesn't send event on the day users opt-in from setting
(T189359#4163741 and below)
The current behavior is:
If a user opt in during onboarding, we will log it in MobileWikiAppDailyStats with appInstallAgeDays = 0
If a user opt in in the setting, we will NOT log it in MobileWikiAppDailyStats with the current appInstallAgeDays, but only when appInstallAgeDays changes
Expected behavior:
When a user opt in in the setting, we log it in MobileWikiAppDailyStats with the current appInstallAgeDays

3, [Reason Unidentified] The number of unique IDs are very different in MobileWikiAppDailyStats and mobile_apps_uniques
On any given day, if a user use the app at least once, the app will send an event to MobileWikiAppDailyStats with ID generated by WMFDailyStatsLoggingFunnel, also the app will send at least one api call with ID in X-Analytics header generated by ReadingActionFunnel (through [L15 in AFHTTPRequestSerializer+WMFRequestHeaders.m](https://github.com/wikimedia/wikipedia-ios/blob/1d2548e869086a279b90c2302feeb4cbadd31b59/Wikipedia/Code/AFHTTPRequestSerializer%2BWMFRequestHeaders.m#L15)). Although these two IDs are different, we should have similar (if not the same) counts of unique IDs in these two places. However, we have only ~60k distinct iOS appInstallIDs daily in MobileWikiAppDailyStats, while there are ~150k distinct iOS appInstallIDs daily in mobile_apps_uniques (it is an aggregated table from webrequest, which logs all api calls from the app).

Again, @NHarateh_WMF sorry for my poor management of the bug tickets! I will change to task description to make it more clear.

@chelsyx not a problem at all! Your explanations are very detailed and your reproduction steps are on point! Thanks for taking the time to include even more details, I really appreciate that + have a better understanding of what's happening now. Do you know if there is a beta equivalent of the mobile_apps_uniques table?

chelsyx renamed this task from [Bug] MobileWikiAppDailyStats is not tracking every opted-in user to [Bug] WMFDailyStatsLoggingFunnel doesn't send event on the day users opt-in from setting.May 5 2018, 12:42 AM
chelsyx updated the task description. (Show Details)

Do you know if there is a beta equivalent of the mobile_apps_uniques table?

As we chat off-ticket, there is no beta to test. But we can check in kafka and webrequest.
Also, I create a new ticket for this issue: T193917: The number of unique IDs are very different in MobileWikiAppDailyStats and mobile_apps_uniques

I'm gonna leave this open until product data can be verified by @chelsyx after release.

chelsyx claimed this task.