emaloney / CleanroomLogger

CleanroomLogger provides an extensible Swift-based logging API that is simple, lightweight and performant
MIT License
1.32k stars 153 forks source link

Custom LogRecorder is not invoked #13

Closed bourquep closed 9 years ago

bourquep commented 9 years ago

I have built a custom LogRecorder to send logs with Crashlytics reports. Here's my recorder:

class CrashlyticsLogRecorder: LogRecorderBase
{
    init()
    {
        super.init(name: "CrashlyticsLogRecorder", formatters: [])
    }

    override func recordFormattedMessage(
        message: String,
        forLogEntry entry: LogEntry,
        currentQueue: dispatch_queue_t,
        synchronousMode: Bool)
    {
        CLSLogv(message, CVaListPointer(_fromUnsafeMutablePointer: nil))
    }
}

And here's my Log.enable() call, in AppDelegate.init():

override init()
{
    let logConfiguration = DefaultLogConfiguration(
        minimumSeverity: .Debug,
        filters: [],
        formatters: [DefaultLogFormatter()],
        additionalRecorders: [CrashlyticsLogRecorder()],
        synchronousMode: false)

    Log.enable(logConfiguration)

    super.init()
}

All my Log.message() calls are visible in the Xcode console, but a breakpoint in CrashlyticsLogRecorder.recordFormattedMessage() is never hit and the logs are never sent with Crashlytics reports.

emaloney commented 9 years ago

I believe the problem may be that you're not passing any formatters up to the superclass in your init(). If my suspicion is correct, all you should need to do is remove the text ", formatters: []" from your call to super.init() to inherit the default value for that parameter provided by the LogRecorderBase superclass.

Each LogRecorder can provide its own set of LogFormatters via the formatters property. Only those formatters returned by a given LogRecorder instance will be consulted when attempting to format a message that would be passed to that LogRecorder. This allows you to use different formatters with different recorders.

In the case of the LogRecorderBase class, you can specify the formatters either by passing at least one instance to the superclass from your init(), or by overriding the formatters property to return your own value(s).

The reason your recordFormattedMessage(_:forLogEntry:currentQueue:synchronousMode:) is not getting called, then, is because it will only be called if at least one formatter instance returns a non-nil value for a call to formatLogEntry().

Please confirm if this suggestion resolves your issue.

bourquep commented 9 years ago

Thanks, it does resolve the issue.