这是我的用例:
我正在使用CocoaLumberjack在我的应用中记录数据。我有六种不同的严重程度。一些数据是微不足道的(严重性为6),有些则不是(严重性为1)。我有两个“记录器”,所有数据都记录到控制台,所有数据也被发送到API进行存储。 API接受JSON格式的日志消息。我已经有了将日志发送到API的代码(自定义DDFileLoggerManager
)。到目前为止,我一直在使用自定义DDLogFormatter
将我的日志消息转换为JSON对象,然后由DDFileLogger写入磁盘。到目前为止,此自定义格式仅由文件记录器使用,因此控制台消息仍然可读。 (我不一定想将数千个JSON对象传递给控制台。)到目前为止,整个系统一直运行良好。
问题在于:
对于转到API服务器的日志数据的版本,我有时也需要提交数据统计信息作为日志消息的一部分。我需要能够将键值对附加到日志消息。我的JSON对象最终将如下所示:
{
'time': '2015-03-01T13:54:03-05:00',
'message': 'User logged in',
'severity': 6,
'data': {
'username':'testuser',
'deviceType': 'iPad Air 2'
}
}
最后,问题
如何让CocoaLumberjack允许我在记录时存储任意键值数据,然后在进行自定义格式化时检索它?
到目前为止,我提出的唯一解决方案是创建一个自定义函数,用于满足我的所有日志记录需求。此函数将采用数据参数(NSDictionary
)并预先执行所有JSONification:
+ (void) logWithSeverity: (uint) severity
data:(NSDictionary *) data
andFormat:(NSString *)formatString, ...
{
va_list args;
va_start(args, formatString);
NSString *message = [[NSString alloc] initWithFormat:formatString
arguments:args];
va_end(args);
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
NSLocale *enUSPOSIXLocale =
[NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"];
[dateFormatter setLocale:enUSPOSIXLocale];
[dateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ssZZZZZ"];
if (data == nil) {
data = @{};
}
// Since we are going to be using the pipe character as a data demarcation,
// we want to remove any that might naturally be occuring in the string
NSDictionary *jsonDictionary = @{
@"time": [dateFormatter stringFromDate:[NSDate date]],
@"message": message,
@"severity": [NSNumber numberWithUnsignedInt:severity],
@"data": data
};
NSError* error;
NSData *jsonData = [NSJSONSerialization
dataWithJSONObject:jsonDictionary options:0 error:&error];
if(error) {
NSLog(@"ERROR: We were unable to serialize JSON .");
return;
}
NSString *jsonString = [[NSString alloc] initWithData:jsonData
encoding:NSUTF8StringEncoding];
DDLogVerbose(jsonString);
}
我会第一个承认这是一个糟糕的解决方案:
有没有人能为我提供更优雅的解决方案?在一个完美的世界中,会有一个这样的函数:DDLogVerboseWithData(*someObject, @"User logged in.");
然后该数据将被存储为一部分DDLogMessage,可通过自定义格式化程序访问。
答案 0 :(得分:0)
在CocoaLumberjack Github Issues Tracker收到来自@river的非常有用的反馈后,我了解到我可以使用DDLogMessage的tag
参数来存储我的数据。这就是我最终得到的结果:
/***
*
* Contains custom logging definitions that allow us to do our control server logging
*
****/
#import "DDLog.h"
#undef LOG_FLAG_ERROR
#undef LOG_FLAG_WARN
#undef LOG_FLAG_INFO
#undef LOG_FLAG_DEBUG
#undef LOG_FLAG_VERBOSE
#undef LOG_LEVEL_ERROR
#undef LOG_LEVEL_WARN
#undef LOG_LEVEL_INFO
#undef LOG_LEVEL_DEBUG
#undef LOG_LEVEL_VERBOSE
#undef LOG_ERROR
#undef LOG_WARN
#undef LOG_INFO
#undef LOG_DEBUG
#undef LOG_VERBOSE
#undef DDLogError
#undef DDLogWarn
#undef DDLogInfo
#undef DDLogDebug
#undef DDLogVerbose
#undef DDLogCError
#undef DDLogCWarn
#undef DDLogCInfo
#undef DDLogCDebug
#undef DDLogCVerbose
// Now define everything how we want it
#define LOG_FLAG_SEV_1 (1 << 0) // 0...000001
#define LOG_FLAG_SEV_2 (1 << 1) // 0...000010
#define LOG_FLAG_SEV_3 (1 << 2) // 0...000100
#define LOG_FLAG_SEV_4 (1 << 3) // 0...001000
#define LOG_FLAG_SEV_5 (1 << 4) // 0...010000
#define LOG_FLAG_SEV_6 (1 << 5) // 0...100000
#define LOG_LEVEL_SEV_1 (LOG_FLAG_SEV_1) // 0...000001
#define LOG_LEVEL_SEV_2 (LOG_FLAG_SEV_2 | LOG_LEVEL_SEV_1 ) // 0...000011
#define LOG_LEVEL_SEV_3 (LOG_FLAG_SEV_3 | LOG_LEVEL_SEV_2 ) // 0...000111
#define LOG_LEVEL_SEV_4 (LOG_FLAG_SEV_4 | LOG_LEVEL_SEV_3 ) // 0...001111
#define LOG_LEVEL_SEV_5 (LOG_FLAG_SEV_5 | LOG_LEVEL_SEV_4 ) // 0...011111
#define LOG_LEVEL_SEV_6 (LOG_FLAG_SEV_6 | LOG_LEVEL_SEV_5 ) // 0...111111
#define LOG_SEV_1 (ddLogLevel & LOG_FLAG_SEV_1 )
#define LOG_SEV_2 (ddLogLevel & LOG_FLAG_SEV_2 )
#define LOG_SEV_3 (ddLogLevel & LOG_FLAG_SEV_3 )
#define LOG_SEV_4 (ddLogLevel & LOG_FLAG_SEV_4 )
#define LOG_SEV_5 (ddLogLevel & LOG_FLAG_SEV_5 )
#define LOG_SEV_6 (ddLogLevel & LOG_FLAG_SEV_6 )
#define DDLogSeverity1(frmt, ...) SYNC_LOG_OBJC_MAYBE(ddLogLevel, LOG_FLAG_SEV_1, 0, frmt, ##__VA_ARGS__)
#define DDLogSeverity2(frmt, ...) SYNC_LOG_OBJC_MAYBE(ddLogLevel, LOG_FLAG_SEV_2, 0, frmt, ##__VA_ARGS__)
#define DDLogSeverity3(frmt, ...) ASYNC_LOG_OBJC_MAYBE(ddLogLevel, LOG_FLAG_SEV_3, 0, frmt, ##__VA_ARGS__)
#define DDLogSeverity4(frmt, ...) ASYNC_LOG_OBJC_MAYBE(ddLogLevel, LOG_FLAG_SEV_4, 0, frmt, ##__VA_ARGS__)
#define DDLogSeverity5(frmt, ...) ASYNC_LOG_OBJC_MAYBE(ddLogLevel, LOG_FLAG_SEV_5, 0, frmt, ##__VA_ARGS__)
#define DDLogSeverity6(frmt, ...) ASYNC_LOG_OBJC_MAYBE(ddLogLevel, LOG_FLAG_SEV_6, 0, frmt, ##__VA_ARGS__)
#define DDLogCSeverity1(frmt, ...) SYNC_LOG_C_MAYBE(ddLogLevel, LOG_FLAG_SEV_1, 0, frmt, ##__VA_ARGS__)
#define DDLogCSeverity2(frmt, ...) SYNC_LOG_C_MAYBE(ddLogLevel, LOG_FLAG_SEV_2, 0, frmt, ##__VA_ARGS__)
#define DDLogCSeverity3(frmt, ...) ASYNC_LOG_C_MAYBE(ddLogLevel, LOG_FLAG_SEV_3, 0, frmt, ##__VA_ARGS__)
#define DDLogCSeverity4(frmt, ...) ASYNC_LOG_C_MAYBE(ddLogLevel, LOG_FLAG_SEV_4, 0, frmt, ##__VA_ARGS__)
#define DDLogCSeverity5(frmt, ...) ASYNC_LOG_C_MAYBE(ddLogLevel, LOG_FLAG_SEV_5, 0, frmt, ##__VA_ARGS__)
#define DDLogCSeverity6(frmt, ...) ASYNC_LOG_C_MAYBE(ddLogLevel, LOG_FLAG_SEV_6, 0, frmt, ##__VA_ARGS__)
#define DDLogSeverity1WithData(theData, frmt, ...) LOG_MACRO(LOG_ASYNC_ENABLED, LOG_LEVEL_DEF, LOG_FLAG_SEV_1, 0, theData, __PRETTY_FUNCTION__, frmt, ##__VA_ARGS__)
#define DDLogSeverity2WithData(theData, frmt, ...) LOG_MACRO(LOG_ASYNC_ENABLED, LOG_LEVEL_DEF, LOG_FLAG_SEV_2, 0, theData, __PRETTY_FUNCTION__, frmt, ##__VA_ARGS__)
#define DDLogSeverity3WithData(theData, frmt, ...) LOG_MACRO(LOG_ASYNC_ENABLED, LOG_LEVEL_DEF, LOG_FLAG_SEV_3, 0, theData, __PRETTY_FUNCTION__, frmt, ##__VA_ARGS__)
#define DDLogSeverity4WithData(theData, frmt, ...) LOG_MACRO(LOG_ASYNC_ENABLED, LOG_LEVEL_DEF, LOG_FLAG_SEV_4, 0, theData, __PRETTY_FUNCTION__, frmt, ##__VA_ARGS__)
#define DDLogSeverity5WithData(theData, frmt, ...) LOG_MACRO(LOG_ASYNC_ENABLED, LOG_LEVEL_DEF, LOG_FLAG_SEV_5, 0, theData, __PRETTY_FUNCTION__, frmt, ##__VA_ARGS__)
#define DDLogSeverity6WithData(theData, frmt, ...) LOG_MACRO(LOG_ASYNC_ENABLED, LOG_LEVEL_DEF, LOG_FLAG_SEV_6, 0, theData, __PRETTY_FUNCTION__, frmt, ##__VA_ARGS__)
/**
* Controls the verbosity of the entire app's logging.
*/
static const int ddLogLevel = LOG_LEVEL_SEV_6;