firebase-ios-sdk
firebase-ios-sdk copied to clipboard
[FR]: Ignore dependency-injected logging interfaces in non-fatal crash reports
Description
I'm using Crashlytics in my apps for crash reporting and general logging tool.
Naturally, to avoid writing import Firebase
into every part of my app, I wrap the logging functionality in a Logger
interface, and inject Firebase at the top level. This is a standard pattern adopted every time I've seen the Firebase SDK used in a complex app.
public protocol Logger {
func log(error: Error)
}
final class LoggerImpl: Logger {
func log(error: Error) {
Crashlytics.crashlytics().record(error: error)
}
}
Frustratingly, this means every non-fatal we log implicates the top-level app module, and the LoggerImpl file.
We need to drill down into the error's stack trace to find the culprit.
Is there any way to override behaviour on Crashlytics so this extremely common dependency-injection pattern can work better?
Looking through the Crashlytics API itself, the only method which seems plausible is recordError(error: userInfo:)
, however I was unable to find any documentation or work out any combination of keys and values which overrode the basic library/file in the UI.
Thank you.
API Proposal
Firebase uses NSThread callStackReturnAddresses
internally to find the stack trace. Therefore, it's a bad idea to try to override this information.
What might be better is, implementing the same approach in the Crashlytics dashboard UI where the first item in a stack trace is greyed out.
FIRCLSUserLogging.m - Line 393
FIRCLSUserLoggingRecordError + 393
Allowing an option for a user to grey out and ignore the first app-sourced line in the stack trace would mean anyone using this DI pattern could get more useful crash reports.
Firebase Product(s)
Crashlytics
I couldn't figure out how to label this issue, so I've labeled it for a human to triage. Hang tight.
While it isn't perfect, I use #file and #line and then put in custom user info keys in the error object.
It would be nice if the record error function itself took #file (alt #fileID, #filePath, #function) and #line and recorded that as metadata. Then you can easily adapt your interface with a default value.
Check out SwiftLog for examples: https://github.com/apple/swift-log
Thanks @SwiftNativeDeveloper, that's a neat approach!
I also ended up extending it to also log the module identifier, though it was a little cumbersome making a custom extension w/ default module argument in each individual module (since Bundle.module is internal!).