diff options
author | gtm.daemon <gtm.daemon@7dc7ac4e-7543-0410-b95c-c1676fc8e2a3> | 2011-10-21 22:30:18 +0000 |
---|---|---|
committer | gtm.daemon <gtm.daemon@7dc7ac4e-7543-0410-b95c-c1676fc8e2a3> | 2011-10-21 22:30:18 +0000 |
commit | 56a2b11be338d2ed249a6cbc956166312df2dbb3 (patch) | |
tree | 818674fb474ad5ac428c4b0d453ab68e6d42c0c5 /Foundation | |
parent | 10a61bef2683db2f1f27cebfdd1d7cd9c8faa657 (diff) |
[Author: aharper]
- Make custom level filters much more flexible (arbitrary level combinations).
- Remove older custom level class to prevent confusion.
- Add a new standard logger that tries to produce a reasonable stdout/stderr
split for commandline tools.
R=dmaclach
APPROVED=dmaclach
Diffstat (limited to 'Foundation')
-rw-r--r-- | Foundation/GTMLogger.h | 33 | ||||
-rw-r--r-- | Foundation/GTMLogger.m | 96 | ||||
-rw-r--r-- | Foundation/GTMLoggerTest.m | 67 |
3 files changed, 156 insertions, 40 deletions
diff --git a/Foundation/GTMLogger.h b/Foundation/GTMLogger.h index 4355292..43ae848 100644 --- a/Foundation/GTMLogger.h +++ b/Foundation/GTMLogger.h @@ -238,6 +238,10 @@ // Same as +standardLogger, but logs to stderr. + (id)standardLoggerWithStderr; +// Same as +standardLogger but levels >= kGTMLoggerLevelError are routed to +// stderr, everything else goes to stdout. ++ (id)standardLoggerWithStdoutAndStderr; + // Returns a new standard GTMLogger instance with a log writer that will // write to the file at |path|, and will use the GTMLogStandardFormatter and // GTMLogLevelFilter classes. If |path| does not exist, it will be created. @@ -454,20 +458,33 @@ typedef enum { @interface GTMLogNoFilter : NSObject <GTMLogFilter> @end // GTMLogNoFilter -// A log filter that filters messages below a specified level. Intended for -// use where finer control than all (GTMLogNoFilter) or heavy filter -// (GTMLogLevelFilter) isn't appropriate. -@interface GTMLogCustomLevelFilter : NSObject <GTMLogFilter> { + +// Base class for custom level filters. Not for direct use, use the minimum +// or maximum level subclasses below. +@interface GTMLogAllowedLevelFilter : NSObject <GTMLogFilter> { @private - GTMLoggerLevel filterLevel_; + NSIndexSet *allowedLevels_; } +@end + +// A log filter that allows you to set a minimum log level. Messages below this +// level will be filtered. +@interface GTMLogMininumLevelFilter : GTMLogAllowedLevelFilter // Designated initializer, logs at levels < |level| will be filtered. -// |level| cannot exceed kGTMLoggerLevelAssert -- (id)initWithFilterLevel:(GTMLoggerLevel)level; +- (id)initWithMinimumLevel:(GTMLoggerLevel)level; -@end // GTMLogLevelFilter +@end + +// A log filter that allows you to set a maximum log level. Messages whose level +// exceeds this level will be filtered. This is really only useful if you have +// a composite GTMLogger that is sending the other messages elsewhere. +@interface GTMLogMaximumLevelFilter : GTMLogAllowedLevelFilter + +// Designated initializer, logs at levels > |level| will be filtered. +- (id)initWithMaximumLevel:(GTMLoggerLevel)level; +@end diff --git a/Foundation/GTMLogger.m b/Foundation/GTMLogger.m index 1769ddb..cb36e3b 100644 --- a/Foundation/GTMLogger.m +++ b/Foundation/GTMLogger.m @@ -89,6 +89,44 @@ static GTMLogger *gSharedLogger = nil; return nil; } ++ (id)standardLoggerWithStdoutAndStderr { + // We're going to take advantage of the GTMLogger to GTMLogWriter adaptor + // and create a composite logger that an outer "standard" logger can use + // as a writer. Our inner loggers should apply no formatting since the main + // logger does that and we want the caller to be able to change formatters + // or add writers without knowing the inner structure of our composite. + + // Don't trust NSFileHandle not to throw + @try { + GTMLogBasicFormatter *formatter = [[[GTMLogBasicFormatter alloc] init] + autorelease]; + GTMLogger *stdoutLogger = + [self loggerWithWriter:[NSFileHandle fileHandleWithStandardOutput] + formatter:formatter + filter:[[[GTMLogMaximumLevelFilter alloc] + initWithMaximumLevel:kGTMLoggerLevelInfo] + autorelease]]; + GTMLogger *stderrLogger = + [self loggerWithWriter:[NSFileHandle fileHandleWithStandardError] + formatter:formatter + filter:[[[GTMLogMininumLevelFilter alloc] + initWithMinimumLevel:kGTMLoggerLevelError] + autorelease]]; + GTMLogger *compositeWriter = + [self loggerWithWriter:[NSArray arrayWithObjects: + stdoutLogger, stderrLogger, nil] + formatter:formatter + filter:[[[GTMLogNoFilter alloc] init] autorelease]]; + GTMLogger *outerLogger = [self standardLogger]; + [outerLogger setWriter:compositeWriter]; + return outerLogger; + } + @catch (id e) { + // Ignored + } + return nil; +} + + (id)standardLoggerWithPath:(NSString *)path { @try { NSFileHandle *fh = [NSFileHandle fileHandleForLoggingAtPath:path mode:0644]; @@ -509,19 +547,20 @@ static BOOL IsVerboseLoggingEnabled(void) { @end // GTMLogNoFilter -@implementation GTMLogCustomLevelFilter - -- (id)init { - // Use error level for default init. - return [self initWithFilterLevel:kGTMLoggerLevelError]; -} +@implementation GTMLogAllowedLevelFilter -- (id)initWithFilterLevel:(GTMLoggerLevel)level { +// Private designated initializer +- (id)initWithAllowedLevels:(NSIndexSet *)levels { self = [super init]; if (self != nil) { - filterLevel_ = level; - // Cap max level - if (filterLevel_ > kGTMLoggerLevelAssert) { + allowedLevels_ = [levels retain]; + // Cap min/max level + if (!allowedLevels_ || + // NSIndexSet is unsigned so only check the high bound, but need to + // check both first and last index because NSIndexSet appears to allow + // wraparound. + ([allowedLevels_ firstIndex] > kGTMLoggerLevelAssert) || + ([allowedLevels_ lastIndex] > kGTMLoggerLevelAssert)) { [self release]; return nil; } @@ -529,8 +568,41 @@ static BOOL IsVerboseLoggingEnabled(void) { return self; } +- (id)init { + // Allow all levels in default init + return [self initWithAllowedLevels:[NSIndexSet indexSetWithIndexesInRange: + NSMakeRange(kGTMLoggerLevelUnknown, + (kGTMLoggerLevelAssert - kGTMLoggerLevelUnknown + 1))]]; +} + +- (void)dealloc { + [allowedLevels_ release]; + [super dealloc]; +} + - (BOOL)filterAllowsMessage:(NSString *)msg level:(GTMLoggerLevel)level { - return (level >= filterLevel_) ? YES : NO; + return [allowedLevels_ containsIndex:level]; } -@end +@end // GTMLogAllowedLevelFilter + + +@implementation GTMLogMininumLevelFilter + +- (id)initWithMinimumLevel:(GTMLoggerLevel)level { + return [super initWithAllowedLevels:[NSIndexSet indexSetWithIndexesInRange: + NSMakeRange(level, + (kGTMLoggerLevelAssert - level + 1))]]; +} + +@end // GTMLogMininumLevelFilter + + +@implementation GTMLogMaximumLevelFilter + +- (id)initWithMaximumLevel:(GTMLoggerLevel)level { + return [super initWithAllowedLevels:[NSIndexSet indexSetWithIndexesInRange: + NSMakeRange(kGTMLoggerLevelUnknown, level + 1)]]; +} + +@end // GTMLogMaximumLevelFilter diff --git a/Foundation/GTMLoggerTest.m b/Foundation/GTMLoggerTest.m index fe76194..c0280e1 100644 --- a/Foundation/GTMLoggerTest.m +++ b/Foundation/GTMLoggerTest.m @@ -469,30 +469,29 @@ STAssertTrue([filter filterAllowsMessage:nil level:kGTMLoggerLevelDebug], nil); } -- (void)testCustomFilter { - // Default level is kGTMLoggerLevelError - id<GTMLogFilter> filter = [[[GTMLogCustomLevelFilter alloc] init] - autorelease]; +- (void)testMinimumFilter { + id<GTMLogFilter> filter = [[[GTMLogMininumLevelFilter alloc] + initWithMinimumLevel:kGTMLoggerLevelInfo] + autorelease]; STAssertNotNil(filter, nil); STAssertFalse([filter filterAllowsMessage:@"hi" level:kGTMLoggerLevelUnknown], nil); STAssertFalse([filter filterAllowsMessage:@"hi" level:kGTMLoggerLevelDebug], nil); - STAssertFalse([filter filterAllowsMessage:@"hi" level:kGTMLoggerLevelInfo], - nil); + STAssertTrue([filter filterAllowsMessage:@"hi" level:kGTMLoggerLevelInfo], + nil); STAssertTrue([filter filterAllowsMessage:@"hi" level:kGTMLoggerLevelError], nil); STAssertTrue([filter filterAllowsMessage:@"hi" level:kGTMLoggerLevelAssert], nil); - // Custom level is possible - filter = [[[GTMLogCustomLevelFilter alloc] - initWithFilterLevel:kGTMLoggerLevelInfo] autorelease]; + filter = [[[GTMLogMininumLevelFilter alloc] + initWithMinimumLevel:kGTMLoggerLevelDebug] autorelease]; STAssertNotNil(filter, nil); STAssertFalse([filter filterAllowsMessage:@"hi" level:kGTMLoggerLevelUnknown], nil); - STAssertFalse([filter filterAllowsMessage:@"hi" level:kGTMLoggerLevelDebug], - nil); + STAssertTrue([filter filterAllowsMessage:@"hi" level:kGTMLoggerLevelDebug], + nil); STAssertTrue([filter filterAllowsMessage:@"hi" level:kGTMLoggerLevelInfo], nil); STAssertTrue([filter filterAllowsMessage:@"hi" level:kGTMLoggerLevelError], @@ -500,23 +499,51 @@ STAssertTrue([filter filterAllowsMessage:@"hi" level:kGTMLoggerLevelAssert], nil); - filter = [[[GTMLogCustomLevelFilter alloc] - initWithFilterLevel:kGTMLoggerLevelDebug] autorelease]; + // Cannot exceed min/max levels filter + filter = [[[GTMLogMininumLevelFilter alloc] + initWithMinimumLevel:kGTMLoggerLevelAssert + 1] autorelease]; + STAssertNil(filter, nil); + filter = [[[GTMLogMininumLevelFilter alloc] + initWithMinimumLevel:kGTMLoggerLevelUnknown - 1] autorelease]; + STAssertNil(filter, nil); +} + +- (void)testMaximumFilter { + id<GTMLogFilter> filter = [[[GTMLogMaximumLevelFilter alloc] + initWithMaximumLevel:kGTMLoggerLevelInfo] + autorelease]; STAssertNotNil(filter, nil); - STAssertFalse([filter filterAllowsMessage:@"hi" level:kGTMLoggerLevelUnknown], + STAssertTrue([filter filterAllowsMessage:@"hi" level:kGTMLoggerLevelUnknown], nil); STAssertTrue([filter filterAllowsMessage:@"hi" level:kGTMLoggerLevelDebug], - nil); + nil); STAssertTrue([filter filterAllowsMessage:@"hi" level:kGTMLoggerLevelInfo], nil); - STAssertTrue([filter filterAllowsMessage:@"hi" level:kGTMLoggerLevelError], + STAssertFalse([filter filterAllowsMessage:@"hi" level:kGTMLoggerLevelError], nil); - STAssertTrue([filter filterAllowsMessage:@"hi" level:kGTMLoggerLevelAssert], + STAssertFalse([filter filterAllowsMessage:@"hi" level:kGTMLoggerLevelAssert], nil); - // Cannot exceed assert level filter - filter = [[[GTMLogCustomLevelFilter alloc] - initWithFilterLevel:kGTMLoggerLevelAssert + 1] autorelease]; + filter = [[[GTMLogMaximumLevelFilter alloc] + initWithMaximumLevel:kGTMLoggerLevelDebug] autorelease]; + STAssertNotNil(filter, nil); + STAssertTrue([filter filterAllowsMessage:@"hi" level:kGTMLoggerLevelUnknown], + nil); + STAssertTrue([filter filterAllowsMessage:@"hi" level:kGTMLoggerLevelDebug], + nil); + STAssertFalse([filter filterAllowsMessage:@"hi" level:kGTMLoggerLevelInfo], + nil); + STAssertFalse([filter filterAllowsMessage:@"hi" level:kGTMLoggerLevelError], + nil); + STAssertFalse([filter filterAllowsMessage:@"hi" level:kGTMLoggerLevelAssert], + nil); + + // Cannot exceed min/max levels filter + filter = [[[GTMLogMaximumLevelFilter alloc] + initWithMaximumLevel:kGTMLoggerLevelAssert + 1] autorelease]; + STAssertNil(filter, nil); + filter = [[[GTMLogMaximumLevelFilter alloc] + initWithMaximumLevel:kGTMLoggerLevelUnknown - 1] autorelease]; STAssertNil(filter, nil); } |