Once again I’ve been instructed to add analytics into an app. Anyone that has ever instrumented analytics knows that it is a royal pain as analytics requires various pieces of information in all kinds of places in apps. While there are ways to mitigate the number of places that code has to be modified, someone still needs to verify that the required events are fired and the necessary parameters are included.
Like many analytics systems, Firebase batches events and sends them off to the server every so often making it hard to see in real time what events are being fired. In order to facilitate analytics verification, Firebase has a method to enable near real time events. Unfortunately this requires access to the source as the parameter Google says to add is a runtime parameter (-FIRDebugEnabled
). I was also told to look at an article about debugging, but clearly the author never actually tried the method described on iOS as it references the runtime parameter which is NOT available in TestFlight builds.
Just to make sure I wasn’t crazy that there was no documented way to enable debugging in a TestFlight build, I asked a friend to review the documentation. He confirmed what I thought, but pointed out the following:
This behavior persists until you explicitly disable Debug mode by specifying the following command line argument:
-FIRDebugDisabled
Immediately after he pointed this out, I got an idea that the runtime flag stored a parameter in the UserDefaults for the app. I ran my app in the simulator using the enabled runtime flag (and another flag) and then used ControlRoom to inspect the plist containing my user defaults. I then ran it again with the disabled flag and compared the results. I found the following 2 entries when the debugging was enabled:
<key>/google/firebase/debug_mode</key>
<true/>
<key>/google/measurement/debug_mode</key>
<true/>
In order to test my theory that these 2 preferences would turn on Firebase debugging, I added a hidden preference to the app to toggle it and ran the app.
UserDefaults.standard.set(true, forKey: "/google/firebase/debug_mode")
UserDefaults.standard.set(true, forKey: "/google/measurement/debug_mode")
Once I toggled the preference, I looked at the Firebase console and didn’t notice anything. Based on the fact that the Google used runtime parameters, I thought that maybe the values were only checked at startup. So I killed the app and re-ran it. Low and behold, data started showing up in the Firebase console! I fixed up my hidden debugging setting to call exit(0)
after toggling the preference, built the app and tested on a device not connected to the debugger. It worked perfectly!
I suspect that Google wanted to keep this a runtime parameter so that it wasn’t accidentally turned on in the wild and cause extra load on the servers. However, it really makes it hard to debug the analytics without access to the source code.
Just after writing this article, I searched the web again for a way to do this and found a Stack Overflow answer that sets the runtime flags when the app is started. The answers are interesting, but should also have a mechanism to turn off the debugging! To be more complete, the answers should be more like:
#if DEBUG || STAGING
if UserDefaults.standard.bool(forKey: "firebaseDebug") == true {
var args = ProcessInfo.processInfo.arguments
args.append("-FIRAnalyticsDebugEnabled")
args.append("-FIRDebugEnabled")
ProcessInfo.processInfo.setValue(args, forKey: "arguments")
} else {
var args = ProcessInfo.processInfo.arguments
args.append("-FIRAnalyticsDebugDisabled")
args.append("-FIRDebugDisabled")
ProcessInfo.processInfo.setValue(args, forKey: "arguments")
}
#endif
Then in some hidden debug screen, add a flag to turn on firebaseDebug UserDefault.