TODD BURNER: We all know crashes happen in our apps,
but it's hard to know which ones happen often, what causes them,
or what to fix first.
We find out about crashes in reviews, social media,
and sometimes even panicked emails.
Usually, these are really hard to investigate.
And when you don't know how many people the issue impacts,
it's hard to decide what to tackle first.
You might have noticed that we added Crashlytics
to the Firebase Dashboard.
It's our primary crash reporting solution for Firebase.
Firebase Crashlytics helps you track, prioritize,
and fix stability issues that erode your app quality.
Most importantly, it does all this in real time.
It synthesizes an avalanche of crashes
into a manageable list of issues,
provides contextual information, and highlights the severity
and prevalence of crashes so you can pinpoint the root
cause faster.
With Firebase Crashlytics, you spend less time
triaging and troubleshooting issues and more time
doing what you love--
building new app features.
So let's explore Crashlytics in this episode of "Firecasts."
[MUSIC PLAYING]
It's happened to all of us--
you release a new version of your app,
and suddenly you hear that the new feature you launched
is causing crashes.
It's important to get as much information about these crashes
as fast as possible.
To start analyzing stack traces and getting alerts
about your crashes in real time when they happen,
let's set up Firebase Crashlytics.
I'm going to use our Firebase Codelab app Friendly Chat,
but you can go ahead and follow along in your favorite app.
The process should be nearly the same.
So I've already got my app set up
to use Firebase by creating a project in the Firebase
Console, downloading the GoogleService plist file,
and adding it to my Xcode project.
Finally, I'll install Firebase through CocoaPods.
Don't know what I'm talking about?
Check out this video first.
OK, let's install Crashlytics.
There are two things you need to do
to add Crashlytics to your app after getting Firebase set up.
Add the dependencies-- in this case, CocoaPods--
and set up a Run Script Build Phase.
So let's open our pod file in Xcode
and add Fabric and Crashlytics pods.
After that, I'm going to run pod install
to update the dependencies.
Let's go back to Xcode.
Take a moment and check out the debug information
format in our Build Settings.
To get a readable stack trace, we
need to use DWARF with dSYM for all build types.
This is usually set up by default,
but it's also worth checking.
This will make sure our builds generate dSYM files to allow
us to get clear stack traces with line numbers and method
names.
Next, we'll add the Run Script Build Phase.
I select the project file in the Navigator,
then open up the Build Phases tab.
I'll hit Plus here and select New Run Script Build Phase
to run a script on each build.
The script we just added uploads your dSYM allocation files
to Firebase so we can just show detailed stack traces.
Without these dSYM files, we'd see raw stack traces
with non-readable logs, like these.
The reason why is to protect your source code
and to optimize your app at runtime.
Xcode compiles your code into machine code
before it runs on a device.
Crashlytics will turn that machine code from a raw crash
report back into a readable stack trace.
To make sure we have the files to do
that, just make sure the Crashlytics Run Script Build
Phase is set up.
So now we're set up, but how do we test it?
I'm going to hop into the FCViewController.swift
and add a crash button that calls a didPressCrash method.
And in that method, we'll just call assert false.
We could also use the Crashlytics Helper
method over here.
Before we test the crash, let's turn
on debug mode so that we can get some logs on the console.
To do that, in our didFinishLaunchingWithOptions
method, add fabric.sharedSDK.debug
equals true.
OK.
Let's test the crash.
But we need to make sure that we detach from Xcode,
as its debugger will prevent us from being
able to report the crash.
First, I press Play to build and run my app.
Then I'll press Stop within Xcode.
And now I'll run it again from within the simulator
without having the Xcode debugger attached.
This time, my app properly crashes.
Now I can run it a second time to upload the crash reports
to the Crashlytics servers.
For this second time, I can either run it directly
from the simulator or build and run from Xcode.
Either way works.
Although if you run it from Xcode,
you can see this crashes uploaded successfully line.
Now in the Firebase console, I'll click on Crashlytics,
and our crash now shows.
At the top, I get a summary of my crash for user rate
and the number of crashes and users I've seen.
I can also filter by version and set custom time ranges to dig
deeper in the trends in my app.
At the bottom, I can see a list of issues
with their type, crash or nonfatal, what
versions they've occurred in, and the raw number of crashes
and number of users affected.
If I click into this issue, I can
see which versions have been most impacted, what devices,
and which OS versions were most impacted.
At the bottom of the page is the most recent session
stack trace for this crash.
You can click to see each individual crash's stack trace
from individual sessions.
If my dSYMs have been uploaded correctly,
my crash reports will look something
like this, where I can see the method names in my stack trace.
Notice the Keys and Log section.
More on that now.
OK.
So we've got basic crash reporting working.
But sometimes more information helps
us get to the bottom of what's happening.
Maybe there's a weird string in a text field
that's causing a crash, or maybe a crash only
happens at a certain level of my game.
There are two ways I can do this.
Firebase Crashlytics will automatically
add analytics events to its crash report
logs when you experience a crash.
Here you can see the different screen [? reviews ?]
and the log-in event.
This is a good way of seeing what
your user has done within the app before it started crashing.
This is really helpful, because sometimes your users
use your app in ways you just don't expect.
Crashlytics also lets you add logs and key value
pairs to add even more information to your crash
reports.
In Swift, you can use CLSLogv or CLSNSLogv
to help pinpoint issues.
There are two things to keep in mind when using these methods.
You can store up to 64 KB of logs
before the crash happens, which means
you can store server responses or anything else you want.
Custom keys help you get the specific state of your app
leading up to the crash.
You can associate any arbitrary key value pair
within your crash report and see them in the Firebase console.
Check out our docs for more.
The last feature of Crashlytics to cover today
is nonfatal exceptions.
In addition to automatically reporting your app's crashes,
Crashlytics lets you log nonfatal exceptions.
On iOS, you do that by recording an NSError object.
Crashlytics reports this and groups it much like crashes.
An NSError object has three main arguments--
domain, code, and userInfo.
Unlike fatal crashes, which are grouped
via stack trace analysis, logged errors
are grouped by NSError domain and code.
Crashlytics offers faster processing
of crashes, broader crash coverage,
and more sophisticated analysis, with real-time alerts,
than our previous crash reporting solution.
It also offers the ability to create custom logs and keys
to collect information and context on the events that
led up to the crash.
The team's continuing to work on big new features
to help make Crashlytics even more powerful.
And we can't wait for you to try them out.
And that's Crashlytics for iOS.
We've been looking forward to having it be part of Firebase.
If you want to find out more, check out
our documentation or the Friendly Chat iOS codelab.
Thanks for watching.
[MUSIC PLAYING]