1*9712c20fSFrederick Mayle // 2*9712c20fSFrederick Mayle // GTMLogger.h 3*9712c20fSFrederick Mayle // 4*9712c20fSFrederick Mayle // Copyright 2007-2008 Google LLC 5*9712c20fSFrederick Mayle // 6*9712c20fSFrederick Mayle // Licensed under the Apache License, Version 2.0 (the "License"); you may not 7*9712c20fSFrederick Mayle // use this file except in compliance with the License. You may obtain a copy 8*9712c20fSFrederick Mayle // of the License at 9*9712c20fSFrederick Mayle // 10*9712c20fSFrederick Mayle // http://www.apache.org/licenses/LICENSE-2.0 11*9712c20fSFrederick Mayle // 12*9712c20fSFrederick Mayle // Unless required by applicable law or agreed to in writing, software 13*9712c20fSFrederick Mayle // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 14*9712c20fSFrederick Mayle // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 15*9712c20fSFrederick Mayle // License for the specific language governing permissions and limitations under 16*9712c20fSFrederick Mayle // the License. 17*9712c20fSFrederick Mayle // 18*9712c20fSFrederick Mayle 19*9712c20fSFrederick Mayle // Key Abstractions 20*9712c20fSFrederick Mayle // ---------------- 21*9712c20fSFrederick Mayle // 22*9712c20fSFrederick Mayle // This file declares multiple classes and protocols that are used by the 23*9712c20fSFrederick Mayle // GTMLogger logging system. The 4 main abstractions used in this file are the 24*9712c20fSFrederick Mayle // following: 25*9712c20fSFrederick Mayle // 26*9712c20fSFrederick Mayle // * logger (GTMLogger) - The main logging class that users interact with. It 27*9712c20fSFrederick Mayle // has methods for logging at different levels and uses a log writer, a log 28*9712c20fSFrederick Mayle // formatter, and a log filter to get the job done. 29*9712c20fSFrederick Mayle // 30*9712c20fSFrederick Mayle // * log writer (GTMLogWriter) - Writes a given string to some log file, where 31*9712c20fSFrederick Mayle // a "log file" can be a physical file on disk, a POST over HTTP to some URL, 32*9712c20fSFrederick Mayle // or even some in-memory structure (e.g., a ring buffer). 33*9712c20fSFrederick Mayle // 34*9712c20fSFrederick Mayle // * log formatter (GTMLogFormatter) - Given a format string and arguments as 35*9712c20fSFrederick Mayle // a va_list, returns a single formatted NSString. A "formatted string" could 36*9712c20fSFrederick Mayle // be a string with the date prepended, a string with values in a CSV format, 37*9712c20fSFrederick Mayle // or even a string of XML. 38*9712c20fSFrederick Mayle // 39*9712c20fSFrederick Mayle // * log filter (GTMLogFilter) - Given a formatted log message as an NSString 40*9712c20fSFrederick Mayle // and the level at which the message is to be logged, this class will decide 41*9712c20fSFrederick Mayle // whether the given message should be logged or not. This is a flexible way 42*9712c20fSFrederick Mayle // to filter out messages logged at a certain level, messages that contain 43*9712c20fSFrederick Mayle // certain text, or filter nothing out at all. This gives the caller the 44*9712c20fSFrederick Mayle // flexibility to dynamically enable debug logging in Release builds. 45*9712c20fSFrederick Mayle // 46*9712c20fSFrederick Mayle // This file also declares some classes to handle the common log writer, log 47*9712c20fSFrederick Mayle // formatter, and log filter cases. Callers can also create their own writers, 48*9712c20fSFrederick Mayle // formatters, and filters and they can even build them on top of the ones 49*9712c20fSFrederick Mayle // declared here. Keep in mind that your custom writer/formatter/filter may be 50*9712c20fSFrederick Mayle // called from multiple threads, so it must be thread-safe. 51*9712c20fSFrederick Mayle 52*9712c20fSFrederick Mayle #import <Foundation/Foundation.h> 53*9712c20fSFrederick Mayle #import "GTMDefines.h" 54*9712c20fSFrederick Mayle 55*9712c20fSFrederick Mayle // Predeclaration of used protocols that are declared later in this file. 56*9712c20fSFrederick Mayle @protocol GTMLogWriter, GTMLogFormatter, GTMLogFilter; 57*9712c20fSFrederick Mayle 58*9712c20fSFrederick Mayle // GTMLogger 59*9712c20fSFrederick Mayle // 60*9712c20fSFrederick Mayle // GTMLogger is the primary user-facing class for an object-oriented logging 61*9712c20fSFrederick Mayle // system. It is built on the concept of log formatters (GTMLogFormatter), log 62*9712c20fSFrederick Mayle // writers (GTMLogWriter), and log filters (GTMLogFilter). When a message is 63*9712c20fSFrederick Mayle // sent to a GTMLogger to log a message, the message is formatted using the log 64*9712c20fSFrederick Mayle // formatter, then the log filter is consulted to see if the message should be 65*9712c20fSFrederick Mayle // logged, and if so, the message is sent to the log writer to be written out. 66*9712c20fSFrederick Mayle // 67*9712c20fSFrederick Mayle // GTMLogger is intended to be a flexible and thread-safe logging solution. Its 68*9712c20fSFrederick Mayle // flexibility comes from the fact that GTMLogger instances can be customized 69*9712c20fSFrederick Mayle // with user defined formatters, filters, and writers. And these writers, 70*9712c20fSFrederick Mayle // filters, and formatters can be combined, stacked, and customized in arbitrary 71*9712c20fSFrederick Mayle // ways to suit the needs at hand. For example, multiple writers can be used at 72*9712c20fSFrederick Mayle // the same time, and a GTMLogger instance can even be used as another 73*9712c20fSFrederick Mayle // GTMLogger's writer. This allows for arbitrarily deep logging trees. 74*9712c20fSFrederick Mayle // 75*9712c20fSFrederick Mayle // A standard GTMLogger uses a writer that sends messages to standard out, a 76*9712c20fSFrederick Mayle // formatter that smacks a timestamp and a few other bits of interesting 77*9712c20fSFrederick Mayle // information on the message, and a filter that filters out debug messages from 78*9712c20fSFrederick Mayle // release builds. Using the standard log settings, a log message will look like 79*9712c20fSFrederick Mayle // the following: 80*9712c20fSFrederick Mayle // 81*9712c20fSFrederick Mayle // 2007-12-30 10:29:24.177 myapp[4588/0xa07d0f60] [lvl=1] foo=<Foo: 0x123> 82*9712c20fSFrederick Mayle // 83*9712c20fSFrederick Mayle // The output contains the date and time of the log message, the name of the 84*9712c20fSFrederick Mayle // process followed by its process ID/thread ID, the log level at which the 85*9712c20fSFrederick Mayle // message was logged (in the previous example the level was 1: 86*9712c20fSFrederick Mayle // kGTMLoggerLevelDebug), and finally, the user-specified log message itself (in 87*9712c20fSFrederick Mayle // this case, the log message was @"foo=%@", foo). 88*9712c20fSFrederick Mayle // 89*9712c20fSFrederick Mayle // Multiple instances of GTMLogger can be created, each configured their own 90*9712c20fSFrederick Mayle // way. Though GTMLogger is not a singleton (in the GoF sense), it does provide 91*9712c20fSFrederick Mayle // access to a shared (i.e., globally accessible) GTMLogger instance. This makes 92*9712c20fSFrederick Mayle // it convenient for all code in a process to use the same GTMLogger instance. 93*9712c20fSFrederick Mayle // The shared GTMLogger instance can also be configured in an arbitrary, and 94*9712c20fSFrederick Mayle // these configuration changes will affect all code that logs through the shared 95*9712c20fSFrederick Mayle // instance. 96*9712c20fSFrederick Mayle 97*9712c20fSFrederick Mayle // 98*9712c20fSFrederick Mayle // Log Levels 99*9712c20fSFrederick Mayle // ---------- 100*9712c20fSFrederick Mayle // GTMLogger has 3 different log levels: Debug, Info, and Error. GTMLogger 101*9712c20fSFrederick Mayle // doesn't take any special action based on the log level; it simply forwards 102*9712c20fSFrederick Mayle // this information on to formatters, filters, and writers, each of which may 103*9712c20fSFrederick Mayle // optionally take action based on the level. Since log level filtering is 104*9712c20fSFrederick Mayle // performed at runtime, log messages are typically not filtered out at compile 105*9712c20fSFrederick Mayle // time. The exception to this rule is that calls to the GTMLoggerDebug() macro 106*9712c20fSFrederick Mayle // *ARE* filtered out of non-DEBUG builds. This is to be backwards compatible 107*9712c20fSFrederick Mayle // with behavior that many developers are currently used to. Note that this 108*9712c20fSFrederick Mayle // means that GTMLoggerDebug(@"hi") will be compiled out of Release builds, but 109*9712c20fSFrederick Mayle // [[GTMLogger sharedLogger] logDebug:@"hi"] will NOT be compiled out. 110*9712c20fSFrederick Mayle // 111*9712c20fSFrederick Mayle // Standard loggers are created with the GTMLogLevelFilter log filter, which 112*9712c20fSFrederick Mayle // filters out certain log messages based on log level, and some other settings. 113*9712c20fSFrederick Mayle // 114*9712c20fSFrederick Mayle // In addition to the -logDebug:, -logInfo:, and -logError: methods defined on 115*9712c20fSFrederick Mayle // GTMLogger itself, there are also C macros that make usage of the shared 116*9712c20fSFrederick Mayle // GTMLogger instance very convenient. These macros are: 117*9712c20fSFrederick Mayle // 118*9712c20fSFrederick Mayle // GTMLoggerDebug(...) 119*9712c20fSFrederick Mayle // GTMLoggerInfo(...) 120*9712c20fSFrederick Mayle // GTMLoggerError(...) 121*9712c20fSFrederick Mayle // 122*9712c20fSFrederick Mayle // Again, a notable feature of these macros is that GTMLogDebug() calls *will be 123*9712c20fSFrederick Mayle // compiled out of non-DEBUG builds*. 124*9712c20fSFrederick Mayle // 125*9712c20fSFrederick Mayle // Standard Loggers 126*9712c20fSFrederick Mayle // ---------------- 127*9712c20fSFrederick Mayle // GTMLogger has the concept of "standard loggers". A standard logger is simply 128*9712c20fSFrederick Mayle // a logger that is pre-configured with some standard/common writer, formatter, 129*9712c20fSFrederick Mayle // and filter combination. Standard loggers are created using the creation 130*9712c20fSFrederick Mayle // methods beginning with "standard". The alternative to a standard logger is a 131*9712c20fSFrederick Mayle // regular logger, which will send messages to stdout, with no special 132*9712c20fSFrederick Mayle // formatting, and no filtering. 133*9712c20fSFrederick Mayle // 134*9712c20fSFrederick Mayle // How do I use GTMLogger? 135*9712c20fSFrederick Mayle // ---------------------- 136*9712c20fSFrederick Mayle // The typical way you will want to use GTMLogger is to simply use the 137*9712c20fSFrederick Mayle // GTMLogger*() macros for logging from code. That way we can easily make 138*9712c20fSFrederick Mayle // changes to the GTMLogger class and simply update the macros accordingly. Only 139*9712c20fSFrederick Mayle // your application startup code (perhaps, somewhere in main()) should use the 140*9712c20fSFrederick Mayle // GTMLogger class directly in order to configure the shared logger, which all 141*9712c20fSFrederick Mayle // of the code using the macros will be using. Again, this is just the typical 142*9712c20fSFrederick Mayle // situation. 143*9712c20fSFrederick Mayle // 144*9712c20fSFrederick Mayle // To be complete, there are cases where you may want to use GTMLogger directly, 145*9712c20fSFrederick Mayle // or even create separate GTMLogger instances for some reason. That's fine, 146*9712c20fSFrederick Mayle // too. 147*9712c20fSFrederick Mayle // 148*9712c20fSFrederick Mayle // Examples 149*9712c20fSFrederick Mayle // -------- 150*9712c20fSFrederick Mayle // The following show some common GTMLogger use cases. 151*9712c20fSFrederick Mayle // 152*9712c20fSFrederick Mayle // 1. You want to log something as simply as possible. Also, this call will only 153*9712c20fSFrederick Mayle // appear in debug builds. In non-DEBUG builds it will be completely removed. 154*9712c20fSFrederick Mayle // 155*9712c20fSFrederick Mayle // GTMLoggerDebug(@"foo = %@", foo); 156*9712c20fSFrederick Mayle // 157*9712c20fSFrederick Mayle // 2. The previous example is similar to the following. The major difference is 158*9712c20fSFrederick Mayle // that the previous call (example 1) will be compiled out of Release builds 159*9712c20fSFrederick Mayle // but this statement will not be compiled out. 160*9712c20fSFrederick Mayle // 161*9712c20fSFrederick Mayle // [[GTMLogger sharedLogger] logDebug:@"foo = %@", foo]; 162*9712c20fSFrederick Mayle // 163*9712c20fSFrederick Mayle // 3. Send all logging output from the shared logger to a file. We do this by 164*9712c20fSFrederick Mayle // creating an NSFileHandle for writing associated with a file, and setting 165*9712c20fSFrederick Mayle // that file handle as the logger's writer. 166*9712c20fSFrederick Mayle // 167*9712c20fSFrederick Mayle // NSFileHandle *f = [NSFileHandle fileHandleForWritingAtPath:@"/tmp/f.log" 168*9712c20fSFrederick Mayle // create:YES]; 169*9712c20fSFrederick Mayle // [[GTMLogger sharedLogger] setWriter:f]; 170*9712c20fSFrederick Mayle // GTMLoggerError(@"hi"); // This will be sent to /tmp/f.log 171*9712c20fSFrederick Mayle // 172*9712c20fSFrederick Mayle // 4. Create a new GTMLogger that will log to a file. This example differs from 173*9712c20fSFrederick Mayle // the previous one because here we create a new GTMLogger that is different 174*9712c20fSFrederick Mayle // from the shared logger. 175*9712c20fSFrederick Mayle // 176*9712c20fSFrederick Mayle // GTMLogger *logger = [GTMLogger standardLoggerWithPath:@"/tmp/temp.log"]; 177*9712c20fSFrederick Mayle // [logger logInfo:@"hi temp log file"]; 178*9712c20fSFrederick Mayle // 179*9712c20fSFrederick Mayle // 5. Create a logger that writes to stdout and does NOT do any formatting to 180*9712c20fSFrederick Mayle // the log message. This might be useful, for example, when writing a help 181*9712c20fSFrederick Mayle // screen for a command-line tool to standard output. 182*9712c20fSFrederick Mayle // 183*9712c20fSFrederick Mayle // GTMLogger *logger = [GTMLogger logger]; 184*9712c20fSFrederick Mayle // [logger logInfo:@"%@ version 0.1 usage", progName]; 185*9712c20fSFrederick Mayle // 186*9712c20fSFrederick Mayle // 6. Send log output to stdout AND to a log file. The trick here is that 187*9712c20fSFrederick Mayle // NSArrays function as composite log writers, which means when an array is 188*9712c20fSFrederick Mayle // set as the log writer, it forwards all logging messages to all of its 189*9712c20fSFrederick Mayle // contained GTMLogWriters. 190*9712c20fSFrederick Mayle // 191*9712c20fSFrederick Mayle // // Create array of GTMLogWriters 192*9712c20fSFrederick Mayle // NSArray *writers = [NSArray arrayWithObjects: 193*9712c20fSFrederick Mayle // [NSFileHandle fileHandleForWritingAtPath:@"/tmp/f.log" create:YES], 194*9712c20fSFrederick Mayle // [NSFileHandle fileHandleWithStandardOutput], nil]; 195*9712c20fSFrederick Mayle // 196*9712c20fSFrederick Mayle // GTMLogger *logger = [GTMLogger standardLogger]; 197*9712c20fSFrederick Mayle // [logger setWriter:writers]; 198*9712c20fSFrederick Mayle // [logger logInfo:@"hi"]; // Output goes to stdout and /tmp/f.log 199*9712c20fSFrederick Mayle // 200*9712c20fSFrederick Mayle // For futher details on log writers, formatters, and filters, see the 201*9712c20fSFrederick Mayle // documentation below. 202*9712c20fSFrederick Mayle // 203*9712c20fSFrederick Mayle // NOTE: GTMLogger is application level logging. By default it does nothing 204*9712c20fSFrederick Mayle // with _GTMDevLog/_GTMDevAssert (see GTMDefines.h). An application can choose 205*9712c20fSFrederick Mayle // to bridge _GTMDevLog/_GTMDevAssert to GTMLogger by providing macro 206*9712c20fSFrederick Mayle // definitions in its prefix header (see GTMDefines.h for how one would do 207*9712c20fSFrederick Mayle // that). 208*9712c20fSFrederick Mayle // 209*9712c20fSFrederick Mayle @interface GTMLogger : NSObject { 210*9712c20fSFrederick Mayle @private 211*9712c20fSFrederick Mayle id<GTMLogWriter> writer_; 212*9712c20fSFrederick Mayle id<GTMLogFormatter> formatter_; 213*9712c20fSFrederick Mayle id<GTMLogFilter> filter_; 214*9712c20fSFrederick Mayle } 215*9712c20fSFrederick Mayle 216*9712c20fSFrederick Mayle // 217*9712c20fSFrederick Mayle // Accessors for the shared logger instance 218*9712c20fSFrederick Mayle // 219*9712c20fSFrederick Mayle 220*9712c20fSFrederick Mayle // Returns a shared/global standard GTMLogger instance. Callers should typically 221*9712c20fSFrederick Mayle // use this method to get a GTMLogger instance, unless they explicitly want 222*9712c20fSFrederick Mayle // their own instance to configure for their own needs. This is the only method 223*9712c20fSFrederick Mayle // that returns a shared instance; all the rest return new GTMLogger instances. 224*9712c20fSFrederick Mayle + (id)sharedLogger; 225*9712c20fSFrederick Mayle 226*9712c20fSFrederick Mayle // Sets the shared logger instance to |logger|. Future calls to +sharedLogger 227*9712c20fSFrederick Mayle // will return |logger| instead. 228*9712c20fSFrederick Mayle + (void)setSharedLogger:(GTMLogger *)logger; 229*9712c20fSFrederick Mayle 230*9712c20fSFrederick Mayle // 231*9712c20fSFrederick Mayle // Creation methods 232*9712c20fSFrederick Mayle // 233*9712c20fSFrederick Mayle 234*9712c20fSFrederick Mayle // Returns a new autoreleased GTMLogger instance that will log to stdout, using 235*9712c20fSFrederick Mayle // the GTMLogStandardFormatter, and the GTMLogLevelFilter filter. 236*9712c20fSFrederick Mayle + (id)standardLogger; 237*9712c20fSFrederick Mayle 238*9712c20fSFrederick Mayle // Same as +standardLogger, but logs to stderr. 239*9712c20fSFrederick Mayle + (id)standardLoggerWithStderr; 240*9712c20fSFrederick Mayle 241*9712c20fSFrederick Mayle // Same as +standardLogger but levels >= kGTMLoggerLevelError are routed to 242*9712c20fSFrederick Mayle // stderr, everything else goes to stdout. 243*9712c20fSFrederick Mayle + (id)standardLoggerWithStdoutAndStderr; 244*9712c20fSFrederick Mayle 245*9712c20fSFrederick Mayle // Returns a new standard GTMLogger instance with a log writer that will 246*9712c20fSFrederick Mayle // write to the file at |path|, and will use the GTMLogStandardFormatter and 247*9712c20fSFrederick Mayle // GTMLogLevelFilter classes. If |path| does not exist, it will be created. 248*9712c20fSFrederick Mayle + (id)standardLoggerWithPath:(NSString *)path; 249*9712c20fSFrederick Mayle 250*9712c20fSFrederick Mayle // Returns an autoreleased GTMLogger instance that will use the specified 251*9712c20fSFrederick Mayle // |writer|, |formatter|, and |filter|. 252*9712c20fSFrederick Mayle + (id)loggerWithWriter:(id<GTMLogWriter>)writer 253*9712c20fSFrederick Mayle formatter:(id<GTMLogFormatter>)formatter 254*9712c20fSFrederick Mayle filter:(id<GTMLogFilter>)filter; 255*9712c20fSFrederick Mayle 256*9712c20fSFrederick Mayle // Returns an autoreleased GTMLogger instance that logs to stdout, with the 257*9712c20fSFrederick Mayle // basic formatter, and no filter. The returned logger differs from the logger 258*9712c20fSFrederick Mayle // returned by +standardLogger because this one does not do any filtering and 259*9712c20fSFrederick Mayle // does not do any special log formatting; this is the difference between a 260*9712c20fSFrederick Mayle // "regular" logger and a "standard" logger. 261*9712c20fSFrederick Mayle + (id)logger; 262*9712c20fSFrederick Mayle 263*9712c20fSFrederick Mayle // Designated initializer. This method returns a GTMLogger initialized with the 264*9712c20fSFrederick Mayle // specified |writer|, |formatter|, and |filter|. See the setter methods below 265*9712c20fSFrederick Mayle // for what values will be used if nil is passed for a parameter. 266*9712c20fSFrederick Mayle - (id)initWithWriter:(id<GTMLogWriter>)writer 267*9712c20fSFrederick Mayle formatter:(id<GTMLogFormatter>)formatter 268*9712c20fSFrederick Mayle filter:(id<GTMLogFilter>)filter; 269*9712c20fSFrederick Mayle 270*9712c20fSFrederick Mayle // 271*9712c20fSFrederick Mayle // Logging methods 272*9712c20fSFrederick Mayle // 273*9712c20fSFrederick Mayle 274*9712c20fSFrederick Mayle // Logs a message at the debug level (kGTMLoggerLevelDebug). 275*9712c20fSFrederick Mayle - (void)logDebug:(NSString *)fmt, ... NS_FORMAT_FUNCTION(1, 2); 276*9712c20fSFrederick Mayle // Logs a message at the info level (kGTMLoggerLevelInfo). 277*9712c20fSFrederick Mayle - (void)logInfo:(NSString *)fmt, ... NS_FORMAT_FUNCTION(1, 2); 278*9712c20fSFrederick Mayle // Logs a message at the error level (kGTMLoggerLevelError). 279*9712c20fSFrederick Mayle - (void)logError:(NSString *)fmt, ... NS_FORMAT_FUNCTION(1, 2); 280*9712c20fSFrederick Mayle // Logs a message at the assert level (kGTMLoggerLevelAssert). 281*9712c20fSFrederick Mayle - (void)logAssert:(NSString *)fmt, ... NS_FORMAT_FUNCTION(1, 2); 282*9712c20fSFrederick Mayle 283*9712c20fSFrederick Mayle 284*9712c20fSFrederick Mayle // 285*9712c20fSFrederick Mayle // Accessors 286*9712c20fSFrederick Mayle // 287*9712c20fSFrederick Mayle 288*9712c20fSFrederick Mayle // Accessor methods for the log writer. If the log writer is set to nil, 289*9712c20fSFrederick Mayle // [NSFileHandle fileHandleWithStandardOutput] is used. 290*9712c20fSFrederick Mayle - (id<GTMLogWriter>)writer; 291*9712c20fSFrederick Mayle - (void)setWriter:(id<GTMLogWriter>)writer; 292*9712c20fSFrederick Mayle 293*9712c20fSFrederick Mayle // Accessor methods for the log formatter. If the log formatter is set to nil, 294*9712c20fSFrederick Mayle // GTMLogBasicFormatter is used. This formatter will format log messages in a 295*9712c20fSFrederick Mayle // plain printf style. 296*9712c20fSFrederick Mayle - (id<GTMLogFormatter>)formatter; 297*9712c20fSFrederick Mayle - (void)setFormatter:(id<GTMLogFormatter>)formatter; 298*9712c20fSFrederick Mayle 299*9712c20fSFrederick Mayle // Accessor methods for the log filter. If the log filter is set to nil, 300*9712c20fSFrederick Mayle // GTMLogNoFilter is used, which allows all log messages through. 301*9712c20fSFrederick Mayle - (id<GTMLogFilter>)filter; 302*9712c20fSFrederick Mayle - (void)setFilter:(id<GTMLogFilter>)filter; 303*9712c20fSFrederick Mayle 304*9712c20fSFrederick Mayle @end // GTMLogger 305*9712c20fSFrederick Mayle 306*9712c20fSFrederick Mayle 307*9712c20fSFrederick Mayle // Helper functions that are used by the convenience GTMLogger*() macros that 308*9712c20fSFrederick Mayle // enable the logging of function names. 309*9712c20fSFrederick Mayle @interface GTMLogger (GTMLoggerMacroHelpers) 310*9712c20fSFrederick Mayle - (void)logFuncDebug:(const char *)func msg:(NSString *)fmt, ... 311*9712c20fSFrederick Mayle NS_FORMAT_FUNCTION(2, 3); 312*9712c20fSFrederick Mayle - (void)logFuncInfo:(const char *)func msg:(NSString *)fmt, ... 313*9712c20fSFrederick Mayle NS_FORMAT_FUNCTION(2, 3); 314*9712c20fSFrederick Mayle - (void)logFuncError:(const char *)func msg:(NSString *)fmt, ... 315*9712c20fSFrederick Mayle NS_FORMAT_FUNCTION(2, 3); 316*9712c20fSFrederick Mayle - (void)logFuncAssert:(const char *)func msg:(NSString *)fmt, ... 317*9712c20fSFrederick Mayle NS_FORMAT_FUNCTION(2, 3); 318*9712c20fSFrederick Mayle @end // GTMLoggerMacroHelpers 319*9712c20fSFrederick Mayle 320*9712c20fSFrederick Mayle 321*9712c20fSFrederick Mayle // The convenience macros are only defined if they haven't already been defined. 322*9712c20fSFrederick Mayle #ifndef GTMLoggerInfo 323*9712c20fSFrederick Mayle 324*9712c20fSFrederick Mayle // Convenience macros that log to the shared GTMLogger instance. These macros 325*9712c20fSFrederick Mayle // are how users should typically log to GTMLogger. Notice that GTMLoggerDebug() 326*9712c20fSFrederick Mayle // calls will be compiled out of non-Debug builds. 327*9712c20fSFrederick Mayle #define GTMLoggerDebug(...) \ 328*9712c20fSFrederick Mayle [[GTMLogger sharedLogger] logFuncDebug:__func__ msg:__VA_ARGS__] 329*9712c20fSFrederick Mayle #define GTMLoggerInfo(...) \ 330*9712c20fSFrederick Mayle [[GTMLogger sharedLogger] logFuncInfo:__func__ msg:__VA_ARGS__] 331*9712c20fSFrederick Mayle #define GTMLoggerError(...) \ 332*9712c20fSFrederick Mayle [[GTMLogger sharedLogger] logFuncError:__func__ msg:__VA_ARGS__] 333*9712c20fSFrederick Mayle #define GTMLoggerAssert(...) \ 334*9712c20fSFrederick Mayle [[GTMLogger sharedLogger] logFuncAssert:__func__ msg:__VA_ARGS__] 335*9712c20fSFrederick Mayle 336*9712c20fSFrederick Mayle // If we're not in a debug build, remove the GTMLoggerDebug statements. This 337*9712c20fSFrederick Mayle // makes calls to GTMLoggerDebug "compile out" of Release builds 338*9712c20fSFrederick Mayle #ifndef DEBUG 339*9712c20fSFrederick Mayle #undef GTMLoggerDebug 340*9712c20fSFrederick Mayle #define GTMLoggerDebug(...) do {} while(0) 341*9712c20fSFrederick Mayle #endif 342*9712c20fSFrederick Mayle 343*9712c20fSFrederick Mayle #endif // !defined(GTMLoggerInfo) 344*9712c20fSFrederick Mayle 345*9712c20fSFrederick Mayle // Log levels. 346*9712c20fSFrederick Mayle typedef enum { 347*9712c20fSFrederick Mayle kGTMLoggerLevelUnknown, 348*9712c20fSFrederick Mayle kGTMLoggerLevelDebug, 349*9712c20fSFrederick Mayle kGTMLoggerLevelInfo, 350*9712c20fSFrederick Mayle kGTMLoggerLevelError, 351*9712c20fSFrederick Mayle kGTMLoggerLevelAssert, 352*9712c20fSFrederick Mayle } GTMLoggerLevel; 353*9712c20fSFrederick Mayle 354*9712c20fSFrederick Mayle 355*9712c20fSFrederick Mayle // 356*9712c20fSFrederick Mayle // Log Writers 357*9712c20fSFrederick Mayle // 358*9712c20fSFrederick Mayle 359*9712c20fSFrederick Mayle // Protocol to be implemented by a GTMLogWriter instance. 360*9712c20fSFrederick Mayle @protocol GTMLogWriter <NSObject> 361*9712c20fSFrederick Mayle // Writes the given log message to where the log writer is configured to write. 362*9712c20fSFrederick Mayle - (void)logMessage:(NSString *)msg level:(GTMLoggerLevel)level; 363*9712c20fSFrederick Mayle @end // GTMLogWriter 364*9712c20fSFrederick Mayle 365*9712c20fSFrederick Mayle 366*9712c20fSFrederick Mayle // Simple category on NSFileHandle that makes NSFileHandles valid log writers. 367*9712c20fSFrederick Mayle // This is convenient because something like, say, +fileHandleWithStandardError 368*9712c20fSFrederick Mayle // now becomes a valid log writer. Log messages are written to the file handle 369*9712c20fSFrederick Mayle // with a newline appended. 370*9712c20fSFrederick Mayle @interface NSFileHandle (GTMFileHandleLogWriter) <GTMLogWriter> 371*9712c20fSFrederick Mayle // Opens the file at |path| in append mode, and creates the file with |mode| 372*9712c20fSFrederick Mayle // if it didn't previously exist. 373*9712c20fSFrederick Mayle + (id)fileHandleForLoggingAtPath:(NSString *)path mode:(mode_t)mode; 374*9712c20fSFrederick Mayle @end // NSFileHandle 375*9712c20fSFrederick Mayle 376*9712c20fSFrederick Mayle 377*9712c20fSFrederick Mayle // This category makes NSArray a GTMLogWriter that can be composed of other 378*9712c20fSFrederick Mayle // GTMLogWriters. This is the classic Composite GoF design pattern. When the 379*9712c20fSFrederick Mayle // GTMLogWriter -logMessage:level: message is sent to the array, the array 380*9712c20fSFrederick Mayle // forwards the message to all of its elements that implement the GTMLogWriter 381*9712c20fSFrederick Mayle // protocol. 382*9712c20fSFrederick Mayle // 383*9712c20fSFrederick Mayle // This is useful in situations where you would like to send log output to 384*9712c20fSFrederick Mayle // multiple log writers at the same time. Simply create an NSArray of the log 385*9712c20fSFrederick Mayle // writers you wish to use, then set the array as the "writer" for your 386*9712c20fSFrederick Mayle // GTMLogger instance. 387*9712c20fSFrederick Mayle @interface NSArray (GTMArrayCompositeLogWriter) <GTMLogWriter> 388*9712c20fSFrederick Mayle @end // GTMArrayCompositeLogWriter 389*9712c20fSFrederick Mayle 390*9712c20fSFrederick Mayle 391*9712c20fSFrederick Mayle // This category adapts the GTMLogger interface so that it can be used as a log 392*9712c20fSFrederick Mayle // writer; it's an "adapter" in the GoF Adapter pattern sense. 393*9712c20fSFrederick Mayle // 394*9712c20fSFrederick Mayle // This is useful when you want to configure a logger to log to a specific 395*9712c20fSFrederick Mayle // writer with a specific formatter and/or filter. But you want to also compose 396*9712c20fSFrederick Mayle // that with a different log writer that may have its own formatter and/or 397*9712c20fSFrederick Mayle // filter. 398*9712c20fSFrederick Mayle @interface GTMLogger (GTMLoggerLogWriter) <GTMLogWriter> 399*9712c20fSFrederick Mayle @end // GTMLoggerLogWriter 400*9712c20fSFrederick Mayle 401*9712c20fSFrederick Mayle 402*9712c20fSFrederick Mayle // 403*9712c20fSFrederick Mayle // Log Formatters 404*9712c20fSFrederick Mayle // 405*9712c20fSFrederick Mayle 406*9712c20fSFrederick Mayle // Protocol to be implemented by a GTMLogFormatter instance. 407*9712c20fSFrederick Mayle @protocol GTMLogFormatter <NSObject> 408*9712c20fSFrederick Mayle // Returns a formatted string using the format specified in |fmt| and the va 409*9712c20fSFrederick Mayle // args specified in |args|. 410*9712c20fSFrederick Mayle - (NSString *)stringForFunc:(NSString *)func 411*9712c20fSFrederick Mayle withFormat:(NSString *)fmt 412*9712c20fSFrederick Mayle valist:(va_list)args 413*9712c20fSFrederick Mayle level:(GTMLoggerLevel)level NS_FORMAT_FUNCTION(2, 0); 414*9712c20fSFrederick Mayle @end // GTMLogFormatter 415*9712c20fSFrederick Mayle 416*9712c20fSFrederick Mayle 417*9712c20fSFrederick Mayle // A basic log formatter that formats a string the same way that NSLog (or 418*9712c20fSFrederick Mayle // printf) would. It does not do anything fancy, nor does it add any data of its 419*9712c20fSFrederick Mayle // own. 420*9712c20fSFrederick Mayle @interface GTMLogBasicFormatter : NSObject <GTMLogFormatter> 421*9712c20fSFrederick Mayle 422*9712c20fSFrederick Mayle // Helper method for prettying C99 __func__ and GCC __PRETTY_FUNCTION__ 423*9712c20fSFrederick Mayle - (NSString *)prettyNameForFunc:(NSString *)func; 424*9712c20fSFrederick Mayle 425*9712c20fSFrederick Mayle @end // GTMLogBasicFormatter 426*9712c20fSFrederick Mayle 427*9712c20fSFrederick Mayle 428*9712c20fSFrederick Mayle // A log formatter that formats the log string like the basic formatter, but 429*9712c20fSFrederick Mayle // also prepends a timestamp and some basic process info to the message, as 430*9712c20fSFrederick Mayle // shown in the following sample output. 431*9712c20fSFrederick Mayle // 2007-12-30 10:29:24.177 myapp[4588/0xa07d0f60] [lvl=1] log mesage here 432*9712c20fSFrederick Mayle @interface GTMLogStandardFormatter : GTMLogBasicFormatter { 433*9712c20fSFrederick Mayle @private 434*9712c20fSFrederick Mayle NSDateFormatter *dateFormatter_; // yyyy-MM-dd HH:mm:ss.SSS 435*9712c20fSFrederick Mayle NSString *pname_; 436*9712c20fSFrederick Mayle pid_t pid_; 437*9712c20fSFrederick Mayle } 438*9712c20fSFrederick Mayle @end // GTMLogStandardFormatter 439*9712c20fSFrederick Mayle 440*9712c20fSFrederick Mayle 441*9712c20fSFrederick Mayle // 442*9712c20fSFrederick Mayle // Log Filters 443*9712c20fSFrederick Mayle // 444*9712c20fSFrederick Mayle 445*9712c20fSFrederick Mayle // Protocol to be imlemented by a GTMLogFilter instance. 446*9712c20fSFrederick Mayle @protocol GTMLogFilter <NSObject> 447*9712c20fSFrederick Mayle // Returns YES if |msg| at |level| should be filtered out; NO otherwise. 448*9712c20fSFrederick Mayle - (BOOL)filterAllowsMessage:(NSString *)msg level:(GTMLoggerLevel)level; 449*9712c20fSFrederick Mayle @end // GTMLogFilter 450*9712c20fSFrederick Mayle 451*9712c20fSFrederick Mayle 452*9712c20fSFrederick Mayle // A log filter that filters messages at the kGTMLoggerLevelDebug level out of 453*9712c20fSFrederick Mayle // non-debug builds. Messages at the kGTMLoggerLevelInfo level are also filtered 454*9712c20fSFrederick Mayle // out of non-debug builds unless GTMVerboseLogging is set in the environment or 455*9712c20fSFrederick Mayle // the processes's defaults. Messages at the kGTMLoggerLevelError level are 456*9712c20fSFrederick Mayle // never filtered. 457*9712c20fSFrederick Mayle @interface GTMLogLevelFilter : NSObject <GTMLogFilter> 458*9712c20fSFrederick Mayle @end // GTMLogLevelFilter 459*9712c20fSFrederick Mayle 460*9712c20fSFrederick Mayle // A simple log filter that does NOT filter anything out; 461*9712c20fSFrederick Mayle // -filterAllowsMessage:level will always return YES. This can be a convenient 462*9712c20fSFrederick Mayle // way to enable debug-level logging in release builds (if you so desire). 463*9712c20fSFrederick Mayle @interface GTMLogNoFilter : NSObject <GTMLogFilter> 464*9712c20fSFrederick Mayle @end // GTMLogNoFilter 465*9712c20fSFrederick Mayle 466*9712c20fSFrederick Mayle 467*9712c20fSFrederick Mayle // Base class for custom level filters. Not for direct use, use the minimum 468*9712c20fSFrederick Mayle // or maximum level subclasses below. 469*9712c20fSFrederick Mayle @interface GTMLogAllowedLevelFilter : NSObject <GTMLogFilter> { 470*9712c20fSFrederick Mayle @private 471*9712c20fSFrederick Mayle NSIndexSet *allowedLevels_; 472*9712c20fSFrederick Mayle } 473*9712c20fSFrederick Mayle @end 474*9712c20fSFrederick Mayle 475*9712c20fSFrederick Mayle // A log filter that allows you to set a minimum log level. Messages below this 476*9712c20fSFrederick Mayle // level will be filtered. 477*9712c20fSFrederick Mayle @interface GTMLogMininumLevelFilter : GTMLogAllowedLevelFilter 478*9712c20fSFrederick Mayle 479*9712c20fSFrederick Mayle // Designated initializer, logs at levels < |level| will be filtered. 480*9712c20fSFrederick Mayle - (id)initWithMinimumLevel:(GTMLoggerLevel)level; 481*9712c20fSFrederick Mayle 482*9712c20fSFrederick Mayle @end 483*9712c20fSFrederick Mayle 484*9712c20fSFrederick Mayle // A log filter that allows you to set a maximum log level. Messages whose level 485*9712c20fSFrederick Mayle // exceeds this level will be filtered. This is really only useful if you have 486*9712c20fSFrederick Mayle // a composite GTMLogger that is sending the other messages elsewhere. 487*9712c20fSFrederick Mayle @interface GTMLogMaximumLevelFilter : GTMLogAllowedLevelFilter 488*9712c20fSFrederick Mayle 489*9712c20fSFrederick Mayle // Designated initializer, logs at levels > |level| will be filtered. 490*9712c20fSFrederick Mayle - (id)initWithMaximumLevel:(GTMLoggerLevel)level; 491*9712c20fSFrederick Mayle 492*9712c20fSFrederick Mayle @end 493*9712c20fSFrederick Mayle 494*9712c20fSFrederick Mayle 495*9712c20fSFrederick Mayle // For subclasses only 496*9712c20fSFrederick Mayle @interface GTMLogger (PrivateMethods) 497*9712c20fSFrederick Mayle 498*9712c20fSFrederick Mayle - (void)logInternalFunc:(const char *)func 499*9712c20fSFrederick Mayle format:(NSString *)fmt 500*9712c20fSFrederick Mayle valist:(va_list)args 501*9712c20fSFrederick Mayle level:(GTMLoggerLevel)level NS_FORMAT_FUNCTION(2, 0); 502*9712c20fSFrederick Mayle 503*9712c20fSFrederick Mayle @end 504*9712c20fSFrederick Mayle 505