diff options
Diffstat (limited to 'src/common/mac/GTMLogger.h')
-rw-r--r-- | src/common/mac/GTMLogger.h | 128 |
1 files changed, 87 insertions, 41 deletions
diff --git a/src/common/mac/GTMLogger.h b/src/common/mac/GTMLogger.h index 7d52f01e..c4fd1402 100644 --- a/src/common/mac/GTMLogger.h +++ b/src/common/mac/GTMLogger.h @@ -6,9 +6,9 @@ // Licensed under the Apache License, Version 2.0 (the "License"); you may not // use this file except in compliance with the License. You may obtain a copy // of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the @@ -18,15 +18,15 @@ // Key Abstractions // ---------------- -// -// This file declares multiple classes and protocols that are used by the +// +// This file declares multiple classes and protocols that are used by the // GTMLogger logging system. The 4 main abstractions used in this file are the // following: // // * logger (GTMLogger) - The main logging class that users interact with. It // has methods for logging at different levels and uses a log writer, a log // formatter, and a log filter to get the job done. -// +// // * log writer (GTMLogWriter) - Writes a given string to some log file, where // a "log file" can be a physical file on disk, a POST over HTTP to some URL, // or even some in-memory structure (e.g., a ring buffer). @@ -44,7 +44,7 @@ // flexibility to dynamically enable debug logging in Release builds. // // This file also declares some classes to handle the common log writer, log -// formatter, and log filter cases. Callers can also create their own writers, +// formatter, and log filter cases. Callers can also create their own writers, // formatters, and filters and they can even build them on top of the ones // declared here. Keep in mind that your custom writer/formatter/filter may be // called from multiple threads, so it must be thread-safe. @@ -55,12 +55,6 @@ // Predeclaration of used protocols that are declared later in this file. @protocol GTMLogWriter, GTMLogFormatter, GTMLogFilter; -#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 -#define CHECK_FORMAT_NSSTRING(a, b) __attribute__((format(__NSString__, a, b))) -#else -#define CHECK_FORMAT_NSSTRING(a, b) -#endif - // GTMLogger // // GTMLogger is the primary user-facing class for an object-oriented logging @@ -69,7 +63,7 @@ // sent to a GTMLogger to log a message, the message is formatted using the log // formatter, then the log filter is consulted to see if the message should be // logged, and if so, the message is sent to the log writer to be written out. -// +// // GTMLogger is intended to be a flexible and thread-safe logging solution. Its // flexibility comes from the fact that GTMLogger instances can be customized // with user defined formatters, filters, and writers. And these writers, @@ -77,7 +71,7 @@ // ways to suit the needs at hand. For example, multiple writers can be used at // the same time, and a GTMLogger instance can even be used as another // GTMLogger's writer. This allows for arbitrarily deep logging trees. -// +// // A standard GTMLogger uses a writer that sends messages to standard out, a // formatter that smacks a timestamp and a few other bits of interesting // information on the message, and a filter that filters out debug messages from @@ -85,13 +79,13 @@ // the following: // // 2007-12-30 10:29:24.177 myapp[4588/0xa07d0f60] [lvl=1] foo=<Foo: 0x123> -// +// // The output contains the date and time of the log message, the name of the // process followed by its process ID/thread ID, the log level at which the // message was logged (in the previous example the level was 1: // kGTMLoggerLevelDebug), and finally, the user-specified log message itself (in // this case, the log message was @"foo=%@", foo). -// +// // Multiple instances of GTMLogger can be created, each configured their own // way. Though GTMLogger is not a singleton (in the GoF sense), it does provide // access to a shared (i.e., globally accessible) GTMLogger instance. This makes @@ -113,10 +107,10 @@ // with behavior that many developers are currently used to. Note that this // means that GTMLoggerDebug(@"hi") will be compiled out of Release builds, but // [[GTMLogger sharedLogger] logDebug:@"hi"] will NOT be compiled out. -// +// // Standard loggers are created with the GTMLogLevelFilter log filter, which // filters out certain log messages based on log level, and some other settings. -// +// // In addition to the -logDebug:, -logInfo:, and -logError: methods defined on // GTMLogger itself, there are also C macros that make usage of the shared // GTMLogger instance very convenient. These macros are: @@ -146,7 +140,7 @@ // GTMLogger class directly in order to configure the shared logger, which all // of the code using the macros will be using. Again, this is just the typical // situation. -// +// // To be complete, there are cases where you may want to use GTMLogger directly, // or even create separate GTMLogger instances for some reason. That's fine, // too. @@ -160,14 +154,14 @@ // // GTMLoggerDebug(@"foo = %@", foo); // -// 2. The previous example is similar to the following. The major difference is +// 2. The previous example is similar to the following. The major difference is // that the previous call (example 1) will be compiled out of Release builds // but this statement will not be compiled out. // // [[GTMLogger sharedLogger] logDebug:@"foo = %@", foo]; // // 3. Send all logging output from the shared logger to a file. We do this by -// creating an NSFileHandle for writing associated with a file, and setting +// creating an NSFileHandle for writing associated with a file, and setting // that file handle as the logger's writer. // // NSFileHandle *f = [NSFileHandle fileHandleForWritingAtPath:@"/tmp/f.log" @@ -185,12 +179,12 @@ // 5. Create a logger that writes to stdout and does NOT do any formatting to // the log message. This might be useful, for example, when writing a help // screen for a command-line tool to standard output. -// +// // GTMLogger *logger = [GTMLogger logger]; // [logger logInfo:@"%@ version 0.1 usage", progName]; // -// 6. Send log output to stdout AND to a log file. The trick here is that -// NSArrays function as composite log writers, which means when an array is +// 6. Send log output to stdout AND to a log file. The trick here is that +// NSArrays function as composite log writers, which means when an array is // set as the log writer, it forwards all logging messages to all of its // contained GTMLogWriters. // @@ -198,7 +192,7 @@ // NSArray *writers = [NSArray arrayWithObjects: // [NSFileHandle fileHandleForWritingAtPath:@"/tmp/f.log" create:YES], // [NSFileHandle fileHandleWithStandardOutput], nil]; -// +// // GTMLogger *logger = [GTMLogger standardLogger]; // [logger setWriter:writers]; // [logger logInfo:@"hi"]; // Output goes to stdout and /tmp/f.log @@ -244,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. @@ -274,20 +272,20 @@ // // Logs a message at the debug level (kGTMLoggerLevelDebug). -- (void)logDebug:(NSString *)fmt, ... CHECK_FORMAT_NSSTRING(1, 2); +- (void)logDebug:(NSString *)fmt, ... NS_FORMAT_FUNCTION(1, 2); // Logs a message at the info level (kGTMLoggerLevelInfo). -- (void)logInfo:(NSString *)fmt, ... CHECK_FORMAT_NSSTRING(1, 2); +- (void)logInfo:(NSString *)fmt, ... NS_FORMAT_FUNCTION(1, 2); // Logs a message at the error level (kGTMLoggerLevelError). -- (void)logError:(NSString *)fmt, ... CHECK_FORMAT_NSSTRING(1, 2); +- (void)logError:(NSString *)fmt, ... NS_FORMAT_FUNCTION(1, 2); // Logs a message at the assert level (kGTMLoggerLevelAssert). -- (void)logAssert:(NSString *)fmt, ... CHECK_FORMAT_NSSTRING(1, 2); +- (void)logAssert:(NSString *)fmt, ... NS_FORMAT_FUNCTION(1, 2); // // Accessors // -// Accessor methods for the log writer. If the log writer is set to nil, +// Accessor methods for the log writer. If the log writer is set to nil, // [NSFileHandle fileHandleWithStandardOutput] is used. - (id<GTMLogWriter>)writer; - (void)setWriter:(id<GTMLogWriter>)writer; @@ -306,20 +304,23 @@ @end // GTMLogger -// Helper functions that are used by the convenience GTMLogger*() macros that +// Helper functions that are used by the convenience GTMLogger*() macros that // enable the logging of function names. @interface GTMLogger (GTMLoggerMacroHelpers) - (void)logFuncDebug:(const char *)func msg:(NSString *)fmt, ... - CHECK_FORMAT_NSSTRING(2, 3); + NS_FORMAT_FUNCTION(2, 3); - (void)logFuncInfo:(const char *)func msg:(NSString *)fmt, ... - CHECK_FORMAT_NSSTRING(2, 3); + NS_FORMAT_FUNCTION(2, 3); - (void)logFuncError:(const char *)func msg:(NSString *)fmt, ... - CHECK_FORMAT_NSSTRING(2, 3); + NS_FORMAT_FUNCTION(2, 3); - (void)logFuncAssert:(const char *)func msg:(NSString *)fmt, ... - CHECK_FORMAT_NSSTRING(2, 3); + NS_FORMAT_FUNCTION(2, 3); @end // GTMLoggerMacroHelpers +// The convenience macros are only defined if they haven't already been defined. +#ifndef GTMLoggerInfo + // Convenience macros that log to the shared GTMLogger instance. These macros // are how users should typically log to GTMLogger. Notice that GTMLoggerDebug() // calls will be compiled out of non-Debug builds. @@ -339,6 +340,8 @@ #define GTMLoggerDebug(...) do {} while(0) #endif +#endif // !defined(GTMLoggerInfo) + // Log levels. typedef enum { kGTMLoggerLevelUnknown, @@ -365,7 +368,7 @@ typedef enum { // now becomes a valid log writer. Log messages are written to the file handle // with a newline appended. @interface NSFileHandle (GTMFileHandleLogWriter) <GTMLogWriter> -// Opens the file at |path| in append mode, and creates the file with |mode| +// Opens the file at |path| in append mode, and creates the file with |mode| // if it didn't previously exist. + (id)fileHandleForLoggingAtPath:(NSString *)path mode:(mode_t)mode; @end // NSFileHandle @@ -379,7 +382,7 @@ typedef enum { // // This is useful in situations where you would like to send log output to // multiple log writers at the same time. Simply create an NSArray of the log -// writers you wish to use, then set the array as the "writer" for your +// writers you wish to use, then set the array as the "writer" for your // GTMLogger instance. @interface NSArray (GTMArrayCompositeLogWriter) <GTMLogWriter> @end // GTMArrayCompositeLogWriter @@ -390,7 +393,7 @@ typedef enum { // // This is useful when you want to configure a logger to log to a specific // writer with a specific formatter and/or filter. But you want to also compose -// that with a different log writer that may have its own formatter and/or +// that with a different log writer that may have its own formatter and/or // filter. @interface GTMLogger (GTMLoggerLogWriter) <GTMLogWriter> @end // GTMLoggerLogWriter @@ -407,14 +410,18 @@ typedef enum { - (NSString *)stringForFunc:(NSString *)func withFormat:(NSString *)fmt valist:(va_list)args - level:(GTMLoggerLevel)level; + level:(GTMLoggerLevel)level NS_FORMAT_FUNCTION(2, 0); @end // GTMLogFormatter -// A basic log formatter that formats a string the same way that NSLog (or +// A basic log formatter that formats a string the same way that NSLog (or // printf) would. It does not do anything fancy, nor does it add any data of its // own. @interface GTMLogBasicFormatter : NSObject <GTMLogFormatter> + +// Helper method for prettying C99 __func__ and GCC __PRETTY_FUNCTION__ +- (NSString *)prettyNameForFunc:(NSString *)func; + @end // GTMLogBasicFormatter @@ -450,9 +457,48 @@ typedef enum { @interface GTMLogLevelFilter : NSObject <GTMLogFilter> @end // GTMLogLevelFilter - // A simple log filter that does NOT filter anything out; // -filterAllowsMessage:level will always return YES. This can be a convenient // way to enable debug-level logging in release builds (if you so desire). @interface GTMLogNoFilter : NSObject <GTMLogFilter> @end // GTMLogNoFilter + + +// Base class for custom level filters. Not for direct use, use the minimum +// or maximum level subclasses below. +@interface GTMLogAllowedLevelFilter : NSObject <GTMLogFilter> { + @private + 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. +- (id)initWithMinimumLevel:(GTMLoggerLevel)level; + +@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 + + +// For subclasses only +@interface GTMLogger (PrivateMethods) + +- (void)logInternalFunc:(const char *)func + format:(NSString *)fmt + valist:(va_list)args + level:(GTMLoggerLevel)level NS_FORMAT_FUNCTION(2, 0); + +@end + |