firebase-ios-sdk icon indicating copy to clipboard operation
firebase-ios-sdk copied to clipboard

[FR]: Ignore dependency-injected logging interfaces in non-fatal crash reports

Open jacobsapps opened this issue 11 months ago • 3 comments

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.

Non-fatal has unhelpful file name and library

We need to drill down into the error's stack trace to find the culprit.

Drill-down into non-fatal

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

jacobsapps avatar Mar 04 '24 12:03 jacobsapps

I couldn't figure out how to label this issue, so I've labeled it for a human to triage. Hang tight.

google-oss-bot avatar Mar 04 '24 12:03 google-oss-bot

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

SwiftNativeDeveloper avatar Mar 04 '24 22:03 SwiftNativeDeveloper

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!).

jacobsapps avatar Mar 05 '24 11:03 jacobsapps