-Hi folks, I’m Jake Ouellette. -And I’m Chris Chestnut.
We’re software engineers who work on Firebase Crashlytics.
Today we’re going to talk about some new feature of the Crashlytics dashboard.
If you already use Crashlytics, you know that it was designed to work great
from the start for your iOS and Android apps, but you know your apps better than we do.
So we also want to give you the tools to equip you
to solve the issues that you care most about.
Let me talk about a time I was really frustrated
trying to prioritize issues on the Crashlytics dashboard.
My team would release a new version of our app every month,
but whenever we shipped new features, we’d switch them off
and slowly roll them out to percentage of our customers.
One time, I built a dark mode UI feature and shipped it to 10% of our customers.
Then I went to the Crashlytics dashboard to make sure my role out it was going well.
I’ll never get back that hour of opening up issues and reading through stack traces.
I was looking for something that might be affecting that 10% of customers
but could not figure out if any of these issues were being caused by our new feature.
We launched dark mode to 100% of our users,
and of course, it turned out that there was an issue
that used to have only a few crashes,
which started impacting all of our customers, and it was all my fault.
Today, I’m happy to tell you that you don’t need to go through that pain.
With the new custom key search and filtering feature in Crashlytics,
you’re now able to filter crashes by custom keys
and identify when there are issues that are impacting your business.
Custom keys are key-value pairs that you can define
and attach to crash reports using the Crashlytics SDK.
By setting custom keys in your code,
you can get a better picture of user’s state leading up to a crash,
as well as track other metadata specific to your app.
This filtering feature gives many developers insight
into the areas of their code they most care about.
Now you can use the Crashlytics dashboard
to quickly find issues that include custom keys.
You'll also be able to filter your session data
within those issues to debug how they’re happening.
With our dashboard’s new and improved filtering,
we've made custom keys much more useful.
Let's take a look at how to use them.
Shown here is an example of setting a custom key-value pair with an Android.
This method takes two parameters, a key and a value.
So you could set a string for the key and the value parameter is overloaded
so it can accept any primitive type.
And while this looks slightly different between Android, iOS and Unity,
the general implementation is the same.
So that’s what setting a custom key looks like,
but how should you use them?
What are some best practices?
Well, when diagnosing the cause of an issue,
it can be really helpful to know what was unique
about the users who caused that crash.
So I'm going to give you some examples
of useful custom keys that might help in debugging.
First, if your app does a lot of network requests,
it’s worth knowing if the users experiencing the crash
were connected to the internet using Wi-Fi, cellular, or if they were out of range.
Here’s a code example written in Swift on iOS
for how to populate custom key with that network state.
By the way, any code examples I show you have resources linked alongside this talk.
On Android, you can get the network state from the Telephony Manager.
The TelephonyManager has a lot of useful states.
So for example, if you’re debugging any network issues,
you might care about what wireless carrier the user is using,
which you can get from the SIM operator ID.
And occasionally apps have unexpected bugs and languages
that you might not have fully tested.
For example, when you’re using right-to-left directional text.
So it’s useful to set a custom key that describes the user’s language or their locale
to be able to detect these types of issues.
Here's an example of retrieving that information in iOS using Swift.
On Android, you can get that locale from the current Android context.
The Android resources have a lot of other useful state.
For example, you can get the screen density
to help you understand if you have any display problems.
There are potentially lots of other types of device info
that you could store in custom keys.
So let’s go through a few examples that are really only Android-specific.
You could store the availability of Google Play Services on the device
to tell whether or not your app had the ability to make calls to those APIs.
Also, you could store the install source
to tell whether or not the app was installed on the device from the Google Play Store.
If you have an Android app that might be running on various ARM and x86 architectures,
it would be useful to know the application binary interface, or ABI,
used by the crashing device.
And there could even be situations
where the Linux Kernel version helps you debug an issue.
When you set those keys, rather than setting each of these keys individually,
we added a Builder API to add custom keys in bulk.
Now here’s a really important use of custom keys.
Some app developers roll out their latest features
behind what’s called a feature switch
They enable their feature only for a subset of their users.
If those users start crashing, it might be tough for you to figure out
which of your crashes relate to that new feature.
So when you enable a feature switch,
we recommend setting a custom key that represents the feature state.
Afterwards you’ll be able to search the Crashlytics dashboard
for the crashes that occurred when the feature switch was on.
Now let’s discuss best practices
for knowing more about your app’s state leading up to a crash.
While the lifecycle methods vary between Android, iOS and Unity,
most app frameworks include ways to listen in your application for certain events,
activities and parts of the UI that your users are seeing.
In order to better understand what your users were doing leading up to a crash,
try adding custom keys within the lifecycle methods
of different activities of your app.
You could use key value pairs to identify
when your user is within important user journeys in your app.
By adding a line to our function as we begin a new activity,
we can keep track of when and if our customer has entered the purchase funnel.
When we view our crash in the Crashlytics dashboard, we can filter our issues
to find out what crashes are occurring in this important user flow.
In a similar way, you could maintain a set of custom keys
that keep track of the visible UI elements.
You could use a custom key to track the element,
with focus at the time of the crash.
As an example, let’s add a custom key to onFocusChange called view_focus.
We can set this key to the name of the view we’re in.
This will bring us closer to knowing what the user was doing before the crash occurred.
Something only available in iOS at the moment
is the ability to add additional data to the previous crash
after one of your users restarts their app.
You can call checkAndUpdateUnsentReports with completion
to get a Crashlytics report object.
You can use this object to modify the report from the last run of the app.
Use this functionality to capture any additional data that might be useful,
such as anything cached from the previous section state.
For example, if a crash happened while a user was watching a video,
you could send up the amount of minutes remaining in that video.
Another thing to keep track of is if your app was in the background when it crashed,
or if a user switched back to your app when the crash occurred.
There are a number of different ways to implement this,
but iOS offers a really easy way to do this
by adding code to the applicationWillResignActive
in your app delegate.
If you also add a boolean to your applicationWillEnterForeground function,
you can check to see if your app is coming back from background.
Adding a custom key to these sections could prove useful in the crash report.
Those are just a few of the best practices that we recommend.
As you can see, custom keys are really powerful,
but there are also a few practices we recommend you avoid
to make your experience using custom keys a lot better.
First, avoid sending too many key value pairs in your app.
A crash report is limited to a maximum of 64 key-value pairs.
The reason is, that during your app session,
any key that you add after the first 64 will be excluded from your crash report.
Focus your custom keys around the areas of your code most important to your app.
And instead use the Crashlytics log function to track unstructured data.
Here's what that log function looks like.
Crashlytics logs are meant to store ordered events
occurring within your app leading up to a crash.
We also recommend staying away from setting keys with lots of unique values
if you need to filter by them on the Crashlytics dashboard.
If your data is too granular, there’ll be fewer exact matches
and will be more difficult to filter down to a meaningful key-value pair,
since each key and value will appear less often.
We recommend increasing the grouping.
For example, you could truncate timestamps by minute or hour
if the timestamp is something you want to filter by.
You’ll also want to avoid creating keys that could mislead you.
Any key you set will be set for the remainder of your app session.
Let’s say you have a key for networkType that you set to Wi-Fi,
but you only set it at app launch,
that could make you think that all of your crashes are occurring on Wi-Fi connections.
Instead, make sure to update that key
when you detect that the user’s connection is switched to cellular.
Finally, we want to give you a quick reminder that custom keys are not intended
to store personally identifiable information, or PII.
Respect your user's privacy by not putting PII inside of custom keys.
If you need to identify the user who caused a crash,
the Crashlytics SDK has an API for setting the user identifier
and our dashboard supports searching for crashes by your customers IDs.
Here’s what the API for setting a user ID looks like.
If you need to delete records associated with a user ID, contact Firebase support.
Now that we’ve talked about segmenting your users with custom keys,
let’s show you an example.
Let’s go back to Bingo Blast and prioritize issues for that app.
Let’s say I’m a developer working on a new feature in Bingo Blast.
Coming to the Crashlytics dashboard,
I want to know if any of these issues are affecting my new feature.
Going to the top of the issue list table, I can enter the relevant key and value.
I’m now seeing only the issues where the custom key for this feature was recorded.
Looking at this list, I spot an older issue our team had previously disregarded
since it wasn't happening very frequently.
Because my new feature’s causing the issue to happen more often,
it's definitely worth my team fixing.
Custom keys can give me a clue as to where to start investigating.
Opening up the list of top custom keys for this issue,
I see that most of these crashes occurred with was_backgrounded set to true
and purchase_funnel set to cart_review.
Not only is this crash effecting an important user base for our app,
we’re also impacting our customer’s ability to complete a purchase
when our user switches back to their app while purchase is in progress.
I’m now equipped with the data I need to go to my team and prioritize the issue,
and have a better idea in my code where to start investigating
Today we’ve shown you our new custom key filtering on the Crashlytics dashboard.
We’ve given you some tips for best practices and things to avoid when using custom keys.
The custom keys feature of Firebase Crashlytics
is a really powerful way for developers to better understand their crash data.
Below this video, you'll find a link
to resources and references discussed in this talk.
So that’s it. Check out our new custom key filtering
and use it to find and fix important crashes faster.