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

reformatting xcodeformatter output. #38

Closed navisingh closed 8 years ago

navisingh commented 8 years ago

What is the cleanest way you suggest to reformat the xcodeformatter output to something like this: I 09:07:39.015 -KeychainService.savedModelForKey:369 | Successfully retrieved a model from keychain where the first column is I/E/U/W/D, the date is in 24h local time, ...

The sample I had posted earlier no longer works due to all the 2.0 changes.

Navi

emaloney commented 8 years ago

The simplest thing would be to use the FieldBasedLogFormatter to construct your own custom LogFormatter:

let formatter = FieldBasedLogFormatter(fields: [
    .Severity(.Custom(textRepresentation: .Uppercase, truncateAtWidth: 1, padToWidth: 0, rightAlign: false)),
    .Literal(" "),
    .Timestamp(.Custom("hh:mm:ss.SSS")),
    .Literal(" "),
    .CallSite,
    .Literal(" "),
    .StackFrame,
    .Delimiter(.SpacedPipe),
    .Payload
])

The code above would get you close to the output you desire, eg.:

D 12:51:53.482 CommonAppDelegate.m:677 -[CommonAppDelegate networkActivityFinished:] | Network activity finished - initiating database cleanup.

However, the .CallSite and .StackFrame fields don't give you the exact output of your old stringRepresentationForCallingFile() function.

If you absolutely must have that exact format, the next-simplest way to do that is to create a LogFormatter that will format just that portion of a log entry. For example:

public struct CustomCallerLogFormatter: LogFormatter
{
    public init() {}

    public func formatLogEntry(entry: LogEntry)
        -> String?
    {
        let filename = NSURL(fileURLWithPath: entry.callingFilePath).URLByDeletingPathExtension?.lastPathComponent ?? "(unknown)"

        return "\(filename).\(entry.callingStackFrame):\(entry.callingFileLine)"
    }
}

Then, for the remaining output, you can use some of the built-in LogFormatter implementations and then combine everything using a ConcatenatingLogFormatter:

let formatter = ConcatenatingLogFormatter(formatters: [
    SeverityLogFormatter(style: .Custom(textRepresentation: .Uppercase, truncateAtWidth: 1, padToWidth: 0, rightAlign: false)),
    LiteralLogFormatter(" "),
    TimestampLogFormatter(style: .Custom("hh:mm:ss.SSS")),
    LiteralLogFormatter(" "),
    CustomCallerLogFormatter(),
    DelimiterLogFormatter(style: .SpacedPipe),
    PayloadLogFormatter()
])

Hope this helps, E.

emaloney commented 8 years ago

Navi,

I just wanted to update you on some recent API changes that make it a little easier to use a custom LogFormatter. You can now use the FieldBasedLogFormatter directly in conjunction with the CustomCallerLogFormatter shown in the example above. This means you can avoid using the slightly-more-complex ConcatenatingLogFormatter.

For example:

let formatter = FieldBasedLogFormatter(fields: [
    .Severity(.Custom(textRepresentation: .Uppercase, truncateAtWidth: 1, padToWidth: 0, rightAlign: false)),
    .Delimiter(.Space),
    .Timestamp(.Custom("hh:mm:ss.SSS")),
    .Delimiter(.Space),
    .Custom(CustomCallerLogFormatter()),
    .Delimiter(.SpacedPipe),
    .Payload
])

You'll notice that there's a new .Space delimiter now, so you can use more type-safe delimiters, in this case .Delimiter(.Space) instead of .Literal(" ").

emaloney commented 8 years ago

Closing ticket now that question is answered.