CocoaLumberjack FileLogger logging to multiple files

5k views Asked by At

I am using this CocoaLumberjack framework to log all my messages in Objective-C design. Now I want to log all errors to one file and all other messages to another file. I know I could use formatter to filter this information. I created two DDFileLogger instances in AppDelegate but these two loggers keep writing into the same file. I wonder if there is a way that I could specify the logging destination so that two loggers write to two different files.

2

There are 2 answers

1
Bogdan On

You can achieve something very close by using a new feature (different log level for every logger). See https://github.com/robbiehanson/CocoaLumberjack/wiki/PerLoggerLogLevels. Creating 2 file loggers (one having error level and the other having verbose) would is not exactly as you described, since the error logs will go into both files. Is this good enough?

2
KabukiAdam On

The key to getting this working is to set up each DDFileLogger with its own DDLogFileManager, with separate log directory paths for each. DDLogFileManager uses the log directory path to determine which file to log to, so if you have two of them pointing to the same directory, they will log to the same log file. So the key is to use separate directories for each log.

For two different log types: "One" and "Two":

// Set the base log directory
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *baseDir = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;
NSString *logsDirectory = [baseDir stringByAppendingPathComponent:@"Logs"];

// set up file logger One to log to subdirectory "One"
DDLogFileManagerDefault *fileManagerOne = [[DDLogFileManagerDefault alloc] initWithLogsDirectory:[logsDirectory stringByAppendingPathComponent:@"One"]];
DDFileLogger *loggerOne = [[DDFileLogger alloc] fileManagerOne];

// Use the filter formatter to make sure only "One" logs go to the "One" log files
ContextWhitelistFilterLogFormatter *formatterOne = [[ContextWhitelistFilterLogFormatter alloc] init];
[formatterOne addToWhitelist:LOG_CONTEXT_ONE];
[loggerOne formatterOne];

[DDLog loggerOne];

    // set up file logger Two to log to subdirectory "Two"
DDLogFileManagerDefault *fileManagerTwo = [[DDLogFileManagerDefault alloc] initWithLogsDirectory:[logsDirectory stringByAppendingPathComponent:@"Two"]];
DDFileLogger *loggerTwo = [[DDFileLogger alloc] fileManagerTwo];

// Use the filter formatter to make sure only "Two" logs go to the "Two" log files
ContextWhitelistFilterLogFormatter *formatterTwo = [[ContextWhitelistFilterLogFormatter alloc] init];
[formatterTwo addToWhitelist:LOG_CONTEXT_TWO];
[loggerTwo formatterTwo];

[DDLog loggerTwo];

then of course you still need to define macros to do your logging:

#define LOG_CONTEXT_ONE    1
#define LOG_CONTEXT_TWO    2

#define LogOne(frmt, ...) SYNC_LOG_OBJC_MACRO(0, 0, LOG_CONTEXT_ONE, frmt, ##__VA_ARGS__)
#define LogTwo(frmt, ...) SYNC_LOG_OBJC_MACRO(0, 0, LOG_CONTEXT_TWO, frmt, ##__VA_ARGS__)

This is what worked for me.