这是我的用例:
我正在使用 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
) 并预先完成所有 JSON 化:
+ (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);
}
我将是第一个承认这是一个糟糕的解决方案的人:
- 自从实现它以来,我不得不关闭到控制台的输出,因为现在记录的所有内容都是一个大而笨重的 JSON 对象,其中包含我不想输出到控制台的各种数据。
- 由于我的严重性级别现在在 JSON 对象内部,因此我不再使用 CocoaLumberjack logLevel 概念。我的记录器将始终设置为“详细”。因此,我完全摆脱了使用日志库的最大好处之一。
有没有人对我有更优雅的解决方案?在一个完美的世界中,会有这样一个函数:DDLogVerboseWithData(*someObject, @"User logged in.");
然后该数据将作为 DDLogMessage 的一部分存储,并且可以通过自定义格式化程序访问。