In LogKit, Log Entries go from LXLogEntry to string by using each target Endpoint’s formatters. Every Endpoint has its own formatters, so different Endpoints can output Entries in different formats. For example, an application using both a Console Endpoint and a File Endpoint could choose concise formatters for the console, and more detailed formatters for the file.

An Endpoint requires two formatters to convert each Log Entry to a string. The Endpoint’s dateFormatter describes how an Entry’s dateTime property will be converted. Its entryFormatter describes how the Entry itself will be converted. Using the Endpoint’s formatters, each LXLogEntry is converted to a string before the Endpoint writes it to its final destination.

Although the formatters of each Endpoint may be customized, all Endpoints include sensible defaults that will suit most developer’s needs. If desired, however, a developer can create and use their own.

Date Formatters

Date formatting is handled by the NSDateFormatter class.

Default Date Formatter

Unless otherwise specified by a specific Endpoint’s documentation, when the dateFormatter initialization parameter is omitted, the Endpoint will be initialized with the default date formatter. This formatter uses the following format:

yyyy-MM-dd HH:mm:ss.SSS

2015-06-19 06:20:51.895

Custom Date Formatters

Endpoint date formatting behavior can be modified by providing a custom NSDateFormatter instance. Please refer to Apple’s NSDateFormatter documentation for details on NSDateFormatter objects.

Example: The following creates a date formatter that outputs only the hour and minute of a Log Entry’s dateTime in the user’s local time zone:

let myDateFormatter: NSDateFormatter = {
    let formatter = NSDateFormatter()
    formatter.dateFormat = "HH:mm"
    formatter.timeZone = NSTimeZone.localTimeZone()
    return formatter
}()

A note about precision:

Although LogKit captures timestamps with microsecond precision, NSDateFormatter always rounds to the nearest millisecond. If your application requires microsecond precision, you should customize your Endpoint’s entryFormatter to display each Entry’s timestamp property, which retains microsecond precision.

Using a Date Formatter

To use a date formatter, simply provide it to the Endpoint you are initializing using the dateFormatter parameter. Some examples:

// Using a custom date formatter:
LXLogConsoleEndpoint(
    dateFormatter: {
        let formatter = NSDateFormatter()
        formatter.dateFormat = "HH:mm"
        formatter.timeZone = NSTimeZone.localTimeZone()
        return formatter
    }()
)

// Omit the dateFormatter parameter to use an Endpoint's default date formatter:
LXLogConsoleEndpoint()

Entry Formatters

Log Entry formatting is handled by the LXLogEntryFormatter closure.

Default Entry Formatter

Unless otherwise specified by a specific Endpoint’s documentation, when the entryFormatter initialization parameter is omitted, the Endpoint will be initialized with the default Entry formatter. This formatter uses the following format:

dateTime [LEVEL] functionName <fileName:lineNumber> message

2015-06-16 03:58:04.609 [DEBUG] applicationDidFinishLaunching <AppDelegate.swift:27> Hello Internet!

Custom Entry Formatters

LogKit makes creating custom Entry formatters easy. The LXLogEntryFormatter closure is defined as:

typealias LXLogEntryFormatter = (entry: LXLogEntry) -> String

Creating an Entry formatter is as simple as providing a closure that accepts a Log Entry and returns a string. The closure is free to use as many or as few of a Log Entry’s properties as the developer wishes.

Example: The following creates a concise Entry formatter that outputs only a Log Entry’s dateTime and message:

let shortFormatter: LXLogEntryFormatter = { entry in return "\(entry.dateTime) \(entry.message)" }

Example: The following creates a detailed Entry formatter that outputs an Entry’s timestamp, logLevel, and detailed information regarding location of the function that generated the message, as well as the message itself:

let logFormatter: LXLogEntryFormatter = { entry in
    return "\(entry.timestamp) [\(entry.logLevel.uppercaseString)] \(entry.functionName) <\(entry.fileName):\(entry.lineNumber).\(entry.columnNumber)> \(entry.message)"
}

Using an Entry Formatter

To use an Entry formatter, simply provide it to the Endpoint you are initializing using the entryFormatter parameter. Some examples:

// Using a custom Entry formatter:
LXLogConsoleEndpoint(entryFormatter: { entry in return "\(entry.dateTime) \(entry.message)" })

// Omit the entryFormatter parameter to use an Endpoint's default Entry formatter:
LXLogConsoleEndpoint()

Customizing Entry Properties

Each Log Entry instance contains a userInfo dictionary property. This dictionary’s contents are set by the application developer during each Logger method call. For example:

log.debug("Hello Internet!", ["year": "2015"])

Including data in userData can be useful in a few ways.

  • The developer can supply additional properties to be included in an Entry formatter’s string output.
let myFormatter: LXLogEntryFormatter = { entry in
    let year = entry.userInfo["year"] as? String ?? "unknown"
    return "\(entry.message) The year is \(year)."
}

// Hello Internet! The year is 2015.
  • The developer can supply parameters intended to control an Entry formatter’s string output.
let myFormatter: LXLogEntryFormatter = { entry in
    if let year = entry.userInfo["year"] as? String where year == "2015" {
        return "\(entry.message)"
    } else {
        return "" // No bugs to log in 2016 and beyond!
    }
}

Note: Some Endpoints (such as the included HTTP JSON Endpoint) may automatically attempt to include any userInfo provided as a part of their entryFormatter output string.