toolkit/crashreporter/google-breakpad/src/common/mac/GTMLogger.h

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial