Skip to content

Instantly share code, notes, and snippets.

@leeprobert
Created July 3, 2013 11:34
Show Gist options
  • Save leeprobert/5917199 to your computer and use it in GitHub Desktop.
Save leeprobert/5917199 to your computer and use it in GitHub Desktop.
AGNLogging - class for logging based on different priorities. Will log to a file and to the console. Requires the Lumberjack Framework : https://github.com/robbiehanson/CocoaLumberjack
//
// AGNLogging.h
// Agnitio iPlanner
//
// Created by Matt Gough on 14/02/2013.
// Copyright (c) 2013 Agnitio. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "AGNLoggingDefines.h"
@class AGNConfigurableLogFormatterConfiguration;
// Do not access the following directly - go via [AGNLogging ddLogLevel] and [AGNLogging ddSetLogLevel]
extern int PRIVATE_agnGenericLogLevel;
extern AGNConfigurableLogFormatterConfiguration* PRIVATE_agnLogLocationConfig;
#define AGNLowLevelLogIf(test, async, lvl, flg, ctx, frmt, ...) \
do { \
if ((lvl & flg) && (test)) \
LOG_MACRO(async, lvl, flg, ctx, nil, __PRETTY_FUNCTION__, frmt, ##__VA_ARGS__); \
} while (0)
#define AGNLowLevelLogLIf(test, async, lvl, flg, ctx, frmt, ...) \
do { \
if ((lvl & flg) && (test)) \
LOG_MACRO(async, lvl, flg, ctx, PRIVATE_agnLogLocationConfig, __PRETTY_FUNCTION__, frmt, ##__VA_ARGS__); \
} while (0)
#define AGNLogAlwaysIf(test,format, ...) AGNLowLevelLogIf((test),LOG_ASYNC_ALWAYS, (PRIVATE_agnGenericLogLevel | LOG_FLAG_ALWAYS), LOG_FLAG_ALWAYS, 0, (format), ##__VA_ARGS__)
#define AGNLogAlways(format, ...) AGNLogAlwaysIf(1, format,##__VA_ARGS__)
#define AGNLogLAlwaysIf(test,format, ...) AGNLowLevelLogLIf((test),LOG_ASYNC_ALWAYS, (PRIVATE_agnGenericLogLevel | LOG_FLAG_ALWAYS), LOG_FLAG_ALWAYS, 0, (format), ##__VA_ARGS__)
#define AGNLogLAlways(format, ...) AGNLogLAlwaysIf(1, format,##__VA_ARGS__)
#define AGNLogErrorIf(test,format, ...) AGNLowLevelLogIf((test),LOG_ASYNC_ERROR, PRIVATE_agnGenericLogLevel, LOG_FLAG_ERROR, 0, (format), ##__VA_ARGS__)
#define AGNLogError(format, ...) AGNLogErrorIf(1, format,##__VA_ARGS__)
#define AGNLogLErrorIf(test,format, ...) AGNLowLevelLogLIf((test),LOG_ASYNC_ERROR, PRIVATE_agnGenericLogLevel, LOG_FLAG_ERROR, 0, (format), ##__VA_ARGS__)
#define AGNLogLError(format, ...) AGNLogLErrorIf(1, format,##__VA_ARGS__)
#define AGNLogWarningIf(test,format, ...) AGNLowLevelLogIf((test),LOG_ASYNC_WARN, PRIVATE_agnGenericLogLevel, LOG_FLAG_WARN, 0, (format), ##__VA_ARGS__)
#define AGNLogWarning(format, ...) AGNLogWarningIf(1, format,##__VA_ARGS__)
#define AGNLogLWarningIf(test,format, ...) AGNLowLevelLogLIf((test),LOG_ASYNC_WARN, PRIVATE_agnGenericLogLevel, LOG_FLAG_WARN, 0, (format), ##__VA_ARGS__)
#define AGNLogLWarning(format, ...) AGNLogLWarningIf(1, format,##__VA_ARGS__)
#define AGNLogNoticeIf(test,format, ...) AGNLowLevelLogIf((test),LOG_ASYNC_NOTICE, PRIVATE_agnGenericLogLevel, LOG_FLAG_NOTICE, 0, (format), ##__VA_ARGS__)
#define AGNLogNotice(format, ...) AGNLogNoticeIf(1, format,##__VA_ARGS__)
#define AGNLogLNoticeIf(test,format, ...) AGNLowLevelLogLIf((test),LOG_ASYNC_NOTICE, PRIVATE_agnGenericLogLevel, LOG_FLAG_NOTICE, 0, (format), ##__VA_ARGS__)
#define AGNLogLNotice(format, ...) AGNLogLNoticeIf(1, format,##__VA_ARGS__)
#define AGNLogInfoIf(test,format, ...) AGNLowLevelLogIf((test),LOG_ASYNC_INFO, PRIVATE_agnGenericLogLevel, LOG_FLAG_INFO, 0, (format), ##__VA_ARGS__)
#define AGNLogInfo(format, ...) AGNLogInfoIf(1, format,##__VA_ARGS__)
#define AGNLogLInfoIf(test,format, ...) AGNLowLevelLogLIf((test),LOG_ASYNC_INFO, PRIVATE_agnGenericLogLevel, LOG_FLAG_INFO, 0, (format), ##__VA_ARGS__)
#define AGNLogLInfo(format, ...) AGNLogLInfoIf(1, format,##__VA_ARGS__)
#define AGNLogVerboseIf(test,format, ...) AGNLowLevelLogIf((test),LOG_ASYNC_VERBOSE, PRIVATE_agnGenericLogLevel, LOG_FLAG_VERBOSE, 0, (format), ##__VA_ARGS__)
#define AGNLogVerbose(format, ...) AGNLogVerboseIf(1, format,##__VA_ARGS__)
#define AGNLogLVerboseIf(test,format, ...) AGNLowLevelLogLIf((test),LOG_ASYNC_VERBOSE, PRIVATE_agnGenericLogLevel, LOG_FLAG_VERBOSE, 0, (format), ##__VA_ARGS__)
#define AGNLogLVerbose(format, ...) AGNLogLVerboseIf(1, format,##__VA_ARGS__)
#define AGNLogDebugIf(test,format, ...) AGNLowLevelLogIf((test),LOG_ASYNC_DEBUG, LOG_DEBUGGING, LOG_FLAG_DEBUG, 0, (format), ##__VA_ARGS__)
#define AGNLogDebug(format, ...) AGNLogDebugIf(1, format,##__VA_ARGS__)
#define AGNLogLDebugIf(test,format, ...) AGNLowLevelLogLIf((test),LOG_ASYNC_DEBUG, LOG_DEBUGGING, LOG_FLAG_DEBUG, 0, (format), ##__VA_ARGS__)
#define AGNLogLDebug(format, ...) AGNLogLDebugIf(1, format,##__VA_ARGS__)
// Redefine NSLog
#ifndef NSLog
# define NSLog AGNLogAlways
#endif
@interface AGNLogging : NSObject <DDRegisteredDynamicLogging>
+ (NSMutableString*)newMutableStringForLogDate:(NSDate*)logDate;
+ (NSString*)appName;
+ (NSString*)processIdString;
// Use these methods to set the log level instead of accessing PRIVATE_agnGenericLogLevel directly
+ (int)ddLogLevel;
+ (void)ddSetLogLevel:(int)logLevel;
@end
/*
AGNNSLogLogFormatter is a log formatter that prepends the same info to the log message as NSLog does.
E.g:
"Hello World" -> "2013-03-27 12:05:58:759 Agnitio_iPlanner[57774:c07] Hello World"
*/
@interface AGNNSLogLogFormatter : NSObject <DDLogFormatter>
@end
@protocol AGNLogFormatterAppender
@required
- (void)appendToString:(NSMutableString*)accumulatedString forLogMessage:(DDLogMessage*)logMessage asPrefix:(BOOL)isPrefix;
@end
@interface AGNStringLogFormatterAppender : NSObject <AGNLogFormatterAppender>
+ (id)sharedInstanceForASCIICharacter:(unsigned char)c; // [1..127]
+ (id)sharedInstanceForSpace;
+ (id)sharedInstanceForNewline;
- (id)initWithString:(NSString*)stringToAppend;
@end
@interface AGNDateLogFormatterAppender : NSObject <AGNLogFormatterAppender>
+ (id)sharedInstance;
@end
@interface AGNLocationLogFormatterAppender : NSObject <AGNLogFormatterAppender>
+ (id)sharedInstance;
@end
@interface AGNMachThreadLogFormatterAppender : NSObject <AGNLogFormatterAppender>
+ (id)sharedInstance;
@end
@interface AGNClumpedThreadLogFormatter : NSObject <AGNLogFormatterAppender>
+ (id)sharedInstance;
@end
@interface AGNQueueLabelLogFormatterAppender : NSObject <AGNLogFormatterAppender>
+ (id)sharedInstance;
@end
@interface AGNAppNameLogFormatterAppender : NSObject <AGNLogFormatterAppender>
+ (id)sharedInstance;
@end
@interface AGNProcessIdLogFormatterAppender : NSObject <AGNLogFormatterAppender>
+ (id)sharedInstance;
@end
@interface AGNFlagLogFormatterAppender : NSObject <AGNLogFormatterAppender>
+ (id)sharedInstance;
@end
@interface AGNConfigurableLogFormatterConfiguration : NSObject
+ (NSArray*)NSLogEquivalentPrefixers;
- (id)initWithPrefixers:(NSArray*)prefixers // Array of AGNLogFormatterAppender
messageFormatter:(id<DDLogFormatter>)logFormatter
suffixers:(NSArray*)suffixers; // Array of AGNLogFormatterAppender
@end
@interface AGNConfigurableLogFormatter : NSObject <DDLogFormatter>
- (id)initWithCommonPrefixers:(NSArray*)prefixers
suffixers:(NSArray*)suffixers;
@end
/**
AGNClipboardLogger send the logs to the clipboard
*/
@interface AGNClipboardLogger : DDAbstractLogger <DDLogger>
+ (AGNClipboardLogger*)sharedInstance;
@end
@interface NSMutableString (AGNLogging)
- (void)indentWithString:(NSString*)string;
@end
//
// AGNLogging.m
// Agnitio iPlanner
//
// Created by Matt Gough on 14/02/2013.
// Copyright (c) 2013 Agnitio. All rights reserved.
//
#if ! __has_feature(objc_arc)
#warning This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC).
#endif
#import "AGNLogging.h"
#import <pthread.h>
int PRIVATE_agnGenericLogLevel = LOG_LEVEL_ALWAYS;
AGNConfigurableLogFormatterConfiguration* PRIVATE_agnLogLocationConfig = nil;
@implementation NSMutableString (AGNLogging)
- (void)indentWithString:(NSString*)string
{
if (![string length])
return;
if (string == self)
string = [string copy];
BOOL startsWithNewline = [self length] && [self characterAtIndex:0] == '\n';
NSString* newlineString = [[NSString alloc] initWithFormat:@"\n%@", string];
[self replaceOccurrencesOfString:@"\n" withString:newlineString options:0 range:NSMakeRange(0, [self length])];
if (!startsWithNewline)
[self insertString:string atIndex:0];
}
@end
@implementation AGNLogging
static const NSUInteger sCalendarUnits = NSYearCalendarUnit
| NSMonthCalendarUnit
| NSDayCalendarUnit
| NSHourCalendarUnit
| NSMinuteCalendarUnit
| NSSecondCalendarUnit
;
NSCalendar* sLogCalendar;
NSString* sAppName;
NSString* sProcessIDString;
mach_port_t sMainThreadId;
char* sMainQueueLabel;
static char *str_copy(const char *str)
{
if (str == NULL) return NULL;
size_t length = strlen(str);
char * result = malloc(length + 1);
strncpy(result, str, length);
result[length] = 0;
return result;
}
+ (void)initialize
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sMainThreadId = pthread_mach_thread_np(pthread_self());
sMainQueueLabel = str_copy(dispatch_queue_get_label(dispatch_get_main_queue()));
sLogCalendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSProcessInfo* processInfo = [NSProcessInfo processInfo];
sAppName = [processInfo processName];
sProcessIDString = [[NSString alloc] initWithFormat:@"%i", [processInfo processIdentifier]];
PRIVATE_agnLogLocationConfig = [[AGNConfigurableLogFormatterConfiguration alloc] initWithPrefixers:@[[AGNLocationLogFormatterAppender sharedInstance], [AGNStringLogFormatterAppender sharedInstanceForSpace]]
messageFormatter:nil
suffixers:nil];
});
}
+ (NSMutableString*)newMutableStringForLogDate:(NSDate*)logDate
{
// Calculate timestamp.
// The technique below is faster than using NSDateFormatter.
NSDateComponents *components = [sLogCalendar components:sCalendarUnits fromDate:logDate];
NSTimeInterval epoch = [logDate timeIntervalSinceReferenceDate];
int milliseconds = (int)((epoch - floor(epoch)) * 1000);
NSMutableString* result = [[NSMutableString alloc] initWithFormat:@"%04ld-%02ld-%02ld %02ld:%02ld:%02ld:%03d", // yyyy-MM-dd HH:mm:ss:SSS - Same as NSLog uses
(long)components.year,
(long)components.month,
(long)components.day,
(long)components.hour,
(long)components.minute,
(long)components.second,
milliseconds
];
return result;
}
+ (NSString*)appName
{
return sAppName;
}
+ (NSString*)processIdString
{
return sProcessIDString;
}
+ (int)ddLogLevel
{
return PRIVATE_agnGenericLogLevel;
}
+ (void)ddSetLogLevel:(int)logLevel
{
PRIVATE_agnGenericLogLevel = logLevel;
}
@end
@implementation AGNNSLogLogFormatter
- (NSString *)formatLogMessage:(DDLogMessage *)logMessage
{
NSMutableString* result = [AGNLogging newMutableStringForLogDate:logMessage->timestamp];
[result appendFormat:@" %@[%@:%x] %@", [AGNLogging appName], [AGNLogging processIdString], logMessage->machThreadID, logMessage->logMsg];
return result;
}
@end
@implementation AGNStringLogFormatterAppender {
NSString* _string;
}
+ (id)sharedInstanceForASCIICharacter:(unsigned char)c
{
static id sSharedInstances[127];
NSParameterAssert(c <= 127);
@synchronized(self)
{
id result = sSharedInstances[c];
if (!result)
{
NSString* s = [[NSString alloc] initWithBytes:&c length:1 encoding:NSASCIIStringEncoding];
result = [[[self class] alloc] initWithString:s];
sSharedInstances[c] = result;
}
return result;
}
}
+ (id)sharedInstanceForSpace
{
return [self sharedInstanceForASCIICharacter:' '];
}
+ (id)sharedInstanceForNewline
{
return [self sharedInstanceForASCIICharacter:'\n'];
}
- (id)initWithString:(NSString*)stringToAppend
{
self = [super init];
if (self)
{
_string = [stringToAppend copy];
}
return self;
}
- (void)appendToString:(NSMutableString*)accumulatedString forLogMessage:(DDLogMessage*)logMessage asPrefix:(BOOL)isPrefix
{
if (_string)
[accumulatedString appendString:_string];
}
@end
#define SIMPLE_SHARED_INSTANCE \
+ (id)sharedInstance {\
static id sSharedInstance;\
static dispatch_once_t onceToken;\
dispatch_once(&onceToken, ^{\
sSharedInstance = [[[self class] alloc] init];\
});\
return sSharedInstance;\
}
@implementation AGNDateLogFormatterAppender
SIMPLE_SHARED_INSTANCE
- (void)appendToString:(NSMutableString*)accumulatedString forLogMessage:(DDLogMessage*)logMessage asPrefix:(BOOL)isPrefix
{
NSString* dateString = [AGNLogging newMutableStringForLogDate:logMessage->timestamp];
[accumulatedString appendString:dateString];
}
@end
@implementation AGNLocationLogFormatterAppender
SIMPLE_SHARED_INSTANCE
- (void)appendToString:(NSMutableString*)accumulatedString forLogMessage:(DDLogMessage*)logMessage asPrefix:(BOOL)isPrefix
{
[accumulatedString appendFormat:@"%s:%i", logMessage->function, logMessage->lineNumber];
}
@end
@implementation AGNFlagLogFormatterAppender
SIMPLE_SHARED_INSTANCE
- (void)appendToString:(NSMutableString*)accumulatedString forLogMessage:(DDLogMessage*)logMessage asPrefix:(BOOL)isPrefix
{
int flag = logMessage->logFlag & logMessage->logLevel;
NSString* s;
switch (flag)
{
case LOG_FLAG_ALWAYS:
s = @"[A]";
break;
case LOG_FLAG_ERROR:
s = @"[E]";
break;
case LOG_FLAG_WARN:
s = @"[W]";
break;
case LOG_FLAG_NOTICE:
s = @"[N]";
break;
case LOG_FLAG_INFO:
s = @"[I]";
break;
case LOG_FLAG_VERBOSE:
s = @"[V]";
break;
case LOG_FLAG_DEBUG:
s = @"[D]";
break;
default:
s = @"[?]";
break;
}
[accumulatedString appendString:s];
}
@end
@implementation AGNMachThreadLogFormatterAppender
SIMPLE_SHARED_INSTANCE
- (void)appendToString:(NSMutableString*)accumulatedString forLogMessage:(DDLogMessage*)logMessage asPrefix:(BOOL)isPrefix
{
[accumulatedString appendFormat:@"%x", logMessage->machThreadID];
}
@end
@implementation AGNQueueLabelLogFormatterAppender
SIMPLE_SHARED_INSTANCE
- (void)appendToString:(NSMutableString*)accumulatedString forLogMessage:(DDLogMessage*)logMessage asPrefix:(BOOL)isPrefix
{
[accumulatedString appendFormat:@"%s", logMessage->queueLabel ?: "<NULL>"];
}
@end
@implementation AGNClumpedThreadLogFormatter
SIMPLE_SHARED_INSTANCE
- (void)appendToString:(NSMutableString*)accumulatedString forLogMessage:(DDLogMessage*)logMessage asPrefix:(BOOL)isPrefix
{
if (sMainThreadId == logMessage->machThreadID)
[accumulatedString appendString:@"[::"];
else
[accumulatedString appendFormat:@"[%x:%@:", logMessage->machThreadID, logMessage->threadName];
if (logMessage->queueLabel && (strcmp(logMessage->queueLabel, sMainQueueLabel) == 0))
[accumulatedString appendString:@"]"];
else
[accumulatedString appendFormat:@"%s]", logMessage->queueLabel ?: "0"];
}
@end
@implementation AGNAppNameLogFormatterAppender
SIMPLE_SHARED_INSTANCE
- (void)appendToString:(NSMutableString*)accumulatedString forLogMessage:(DDLogMessage*)logMessage asPrefix:(BOOL)isPrefix
{
[accumulatedString appendString:[AGNLogging appName]];
}
@end
@implementation AGNProcessIdLogFormatterAppender
SIMPLE_SHARED_INSTANCE
- (void)appendToString:(NSMutableString*)accumulatedString forLogMessage:(DDLogMessage*)logMessage asPrefix:(BOOL)isPrefix
{
[accumulatedString appendString:[AGNLogging processIdString]];
}
@end
@implementation AGNConfigurableLogFormatterConfiguration {
@public
NSArray* _prefixers;
NSArray* _suffixers;
id<DDLogFormatter> _formatter;
}
- (id)initWithPrefixers:(NSArray*)prefixers
messageFormatter:(id<DDLogFormatter>)logFormatter
suffixers:(NSArray*)suffixers
{
self = [super init];
if (self)
{
_prefixers = [prefixers copy];
_suffixers = [suffixers copy];
_formatter = logFormatter;
}
return self;
}
+ (NSArray*)NSLogEquivalentPrefixers
{
static NSArray* sPrefixers;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
id space = [AGNStringLogFormatterAppender sharedInstanceForSpace];
sPrefixers = @[
[AGNDateLogFormatterAppender sharedInstance],
space,
[AGNAppNameLogFormatterAppender sharedInstance],
[AGNStringLogFormatterAppender sharedInstanceForASCIICharacter:'['],
[AGNProcessIdLogFormatterAppender sharedInstance],
[AGNStringLogFormatterAppender sharedInstanceForASCIICharacter:':'],
[AGNMachThreadLogFormatterAppender sharedInstance],
[AGNStringLogFormatterAppender sharedInstanceForASCIICharacter:']'],
space
];
});
return sPrefixers;
}
@end
@implementation AGNConfigurableLogFormatter
{
NSArray* _commonPrefixers;
NSArray* _commonSuffixers;
}
- (id)initWithCommonPrefixers:(NSArray*)prefixers
suffixers:(NSArray*)suffixers
{
self = [super init];
if (self)
{
_commonPrefixers = [prefixers copy];
_commonSuffixers = [suffixers copy];
}
return self;
}
- (NSString*)formatLogMessage:(DDLogMessage *)logMessage
{
NSMutableString* result = [NSMutableString string];
for (id<AGNLogFormatterAppender> prefix in _commonPrefixers)
{
[prefix appendToString:result forLogMessage:logMessage asPrefix:YES];
}
AGNConfigurableLogFormatterConfiguration* config = logMessage->tag;
if (config)
{
#if DEBUG
NSAssert([config isKindOfClass:[AGNConfigurableLogFormatterConfiguration class]], @"Unexpected config:%@", config);
#endif
for (id<AGNLogFormatterAppender> prefix in config->_prefixers)
{
[prefix appendToString:result forLogMessage:logMessage asPrefix:YES];
}
}
id<DDLogFormatter> formatter = config ? config->_formatter : nil;
[result appendString:formatter ? [formatter
formatLogMessage:logMessage] : logMessage->logMsg];
if (config)
{
for (id<AGNLogFormatterAppender> suffix in config->_suffixers)
{
[suffix appendToString:result forLogMessage:logMessage asPrefix:NO];
}
}
for (id<AGNLogFormatterAppender> suffix in _commonSuffixers)
{
[suffix appendToString:result forLogMessage:logMessage asPrefix:NO];
}
return result;
}
@end
@implementation AGNClipboardLogger
static AGNClipboardLogger* sharedInstance;
+ (AGNClipboardLogger*)sharedInstance
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[AGNClipboardLogger alloc] init];
});
return sharedInstance;
}
- (void)logMessage:(DDLogMessage *)logMessage
{
static NSMutableString* sPasteboardString;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sPasteboardString = [NSMutableString new];
});
NSString* formattedLog = formatter ? [formatter formatLogMessage:logMessage] : logMessage->logMsg;
@synchronized (sPasteboardString) {
[sPasteboardString appendString:formattedLog];
[sPasteboardString appendString:@"\n"];
NSUInteger length = [sPasteboardString length];
if (length > 100000)
{
[sPasteboardString replaceCharactersInRange:NSMakeRange(0, length - 100000) withString:@"!!truncated!!\n"];
}
[UIPasteboard generalPasteboard].string = sPasteboardString;
}
}
@end
//
// AGNLoggingDefines.h
// Agnitio iPlanner
//
// Created by Matt Gough on 27/03/2013.
// Copyright (c) 2013 Agnitio. All rights reserved.
//
#ifndef Agnitio_iPlanner_AGNLoggingDefines_h
#define Agnitio_iPlanner_AGNLoggingDefines_h
#import "DDLog.h"
// Set off async logging ourselves so we can toggle it without modifying DDLog.h
#undef LOG_ASYNC_ENABLED
#define LOG_ASYNC_ENABLED YES
// Define our own logging levels
// First undefine the default stuff we don't want to use.
#undef LOG_FLAG_ERROR
#undef LOG_FLAG_WARN
#undef LOG_FLAG_INFO
#undef LOG_FLAG_VERBOSE
#undef LOG_LEVEL_ERROR
#undef LOG_LEVEL_WARN
#undef LOG_LEVEL_INFO
#undef LOG_LEVEL_VERBOSE
#undef LOG_ERROR
#undef LOG_WARN
#undef LOG_INFO
#undef LOG_VERBOSE
// Remove the DD versions of the log calls - Only allow AGNLogger
#undef DDLogError
#undef DDLogWarn
#undef DDLogInfo
#undef DDLogVerbose
#undef DDLogCError
#undef DDLogCWarn
#undef DDLogCInfo
#undef DDLogCVerbose
// Now define everything how we want it
#define LOG_FLAG_ALWAYS (1 << 0) // 0...000001
#define LOG_FLAG_ERROR (1 << 1) // 0...000010
#define LOG_FLAG_WARN (1 << 2) // 0...000100
#define LOG_FLAG_NOTICE (1 << 3) // 0...001000
#define LOG_FLAG_INFO (1 << 4) // 0...010000
#define LOG_FLAG_VERBOSE (1 << 5) // 0...100000
#define LOG_FLAG_DEBUG (1 << 31)
#define LOG_LEVEL_ALWAYS (LOG_FLAG_ALWAYS) // 0...000001
#define LOG_LEVEL_ERROR (LOG_FLAG_ERROR | LOG_FLAG_ALWAYS) // 0...000011
#define LOG_LEVEL_WARN (LOG_FLAG_WARN | LOG_LEVEL_ERROR) // 0...000111
#define LOG_LEVEL_NOTICE (LOG_FLAG_NOTICE | LOG_LEVEL_WARN ) // 0...001111
#define LOG_LEVEL_INFO (LOG_FLAG_INFO | LOG_LEVEL_NOTICE) // 0...011111
#define LOG_LEVEL_VERBOSE (LOG_FLAG_VERBOSE| LOG_LEVEL_INFO) // 0...111111
#define LOG_ALWAYS (PRIVATE_agnGenericLogLevel & LOG_FLAG_ALWAYS)
#define LOG_ERROR (PRIVATE_agnGenericLogLevel & LOG_FLAG_ERROR)
#define LOG_WARN (PRIVATE_agnGenericLogLevel & LOG_FLAG_WARN)
#define LOG_NOTICE (PRIVATE_agnGenericLogLevel & LOG_FLAG_NOTICE)
#define LOG_INFO (PRIVATE_agnGenericLogLevel & LOG_FLAG_INFO)
#define LOG_VERBOSE (PRIVATE_agnGenericLogLevel & LOG_FLAG_VERBOSE)
#if DEBUG
# define LOG_DEBUGGING (LOG_FLAG_DEBUG)
#else
# define LOG_DEBUGGING (0)
#endif
#define LOG_ASYNC_ALWAYS (YES && LOG_ASYNC_ENABLED)
#define LOG_ASYNC_NOTICE (YES && LOG_ASYNC_ENABLED)
#define LOG_ASYNC_DEBUG ( NO && LOG_ASYNC_ENABLED)
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment