Created
July 3, 2013 11:34
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// 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 | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// 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 | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// 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