aboutsummaryrefslogtreecommitdiff
path: root/Foundation
diff options
context:
space:
mode:
authorGravatar gtm.daemon <gtm.daemon@7dc7ac4e-7543-0410-b95c-c1676fc8e2a3>2011-10-21 22:30:18 +0000
committerGravatar gtm.daemon <gtm.daemon@7dc7ac4e-7543-0410-b95c-c1676fc8e2a3>2011-10-21 22:30:18 +0000
commit56a2b11be338d2ed249a6cbc956166312df2dbb3 (patch)
tree818674fb474ad5ac428c4b0d453ab68e6d42c0c5 /Foundation
parent10a61bef2683db2f1f27cebfdd1d7cd9c8faa657 (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.h33
-rw-r--r--Foundation/GTMLogger.m96
-rw-r--r--Foundation/GTMLoggerTest.m67
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);
}