13ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
23ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//  GTMLogger.h
33ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
43ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//  Copyright 2007-2008 Google Inc.
53ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
63ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//  Licensed under the Apache License, Version 2.0 (the "License"); you may not
73ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//  use this file except in compliance with the License.  You may obtain a copy
83ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//  of the License at
92b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org//
103ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//  http://www.apache.org/licenses/LICENSE-2.0
112b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org//
123ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//  Unless required by applicable law or agreed to in writing, software
133ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
143ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
153ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//  License for the specific language governing permissions and limitations under
163ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//  the License.
173ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
183ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
193ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// Key Abstractions
203ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// ----------------
212b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org//
222b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org// This file declares multiple classes and protocols that are used by the
233ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// GTMLogger logging system. The 4 main abstractions used in this file are the
243ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// following:
253ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
263ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//   * logger (GTMLogger) - The main logging class that users interact with. It
273ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//   has methods for logging at different levels and uses a log writer, a log
283ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//   formatter, and a log filter to get the job done.
292b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org//
303ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//   * log writer (GTMLogWriter) - Writes a given string to some log file, where
313ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//   a "log file" can be a physical file on disk, a POST over HTTP to some URL,
323ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//   or even some in-memory structure (e.g., a ring buffer).
333ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
343ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//   * log formatter (GTMLogFormatter) - Given a format string and arguments as
353ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//   a va_list, returns a single formatted NSString. A "formatted string" could
363ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//   be a string with the date prepended, a string with values in a CSV format,
373ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//   or even a string of XML.
383ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
393ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//   * log filter (GTMLogFilter) - Given a formatted log message as an NSString
403ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//   and the level at which the message is to be logged, this class will decide
413ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//   whether the given message should be logged or not. This is a flexible way
423ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//   to filter out messages logged at a certain level, messages that contain
433ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//   certain text, or filter nothing out at all. This gives the caller the
443ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//   flexibility to dynamically enable debug logging in Release builds.
453ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
463ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// This file also declares some classes to handle the common log writer, log
472b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org// formatter, and log filter cases. Callers can also create their own writers,
483ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// formatters, and filters and they can even build them on top of the ones
493ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// declared here. Keep in mind that your custom writer/formatter/filter may be
503ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// called from multiple threads, so it must be thread-safe.
513ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
523ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid#import <Foundation/Foundation.h>
53a3d4c973369987e14cc0c05964e288ea0eac11dcnealsid#import "GTMDefines.h"
543ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
553ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// Predeclaration of used protocols that are declared later in this file.
563ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid@protocol GTMLogWriter, GTMLogFormatter, GTMLogFilter;
573ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
583ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// GTMLogger
593ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
603ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// GTMLogger is the primary user-facing class for an object-oriented logging
613ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// system. It is built on the concept of log formatters (GTMLogFormatter), log
623ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// writers (GTMLogWriter), and log filters (GTMLogFilter). When a message is
633ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// sent to a GTMLogger to log a message, the message is formatted using the log
643ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// formatter, then the log filter is consulted to see if the message should be
653ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// logged, and if so, the message is sent to the log writer to be written out.
662b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org//
673ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// GTMLogger is intended to be a flexible and thread-safe logging solution. Its
683ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// flexibility comes from the fact that GTMLogger instances can be customized
693ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// with user defined formatters, filters, and writers. And these writers,
703ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// filters, and formatters can be combined, stacked, and customized in arbitrary
713ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// ways to suit the needs at hand. For example, multiple writers can be used at
723ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// the same time, and a GTMLogger instance can even be used as another
733ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// GTMLogger's writer. This allows for arbitrarily deep logging trees.
742b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org//
753ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// A standard GTMLogger uses a writer that sends messages to standard out, a
763ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// formatter that smacks a timestamp and a few other bits of interesting
773ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// information on the message, and a filter that filters out debug messages from
783ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// release builds. Using the standard log settings, a log message will look like
793ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// the following:
803ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
813ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//   2007-12-30 10:29:24.177 myapp[4588/0xa07d0f60] [lvl=1] foo=<Foo: 0x123>
822b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org//
833ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// The output contains the date and time of the log message, the name of the
843ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// process followed by its process ID/thread ID, the log level at which the
853ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// message was logged (in the previous example the level was 1:
863ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// kGTMLoggerLevelDebug), and finally, the user-specified log message itself (in
873ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// this case, the log message was @"foo=%@", foo).
882b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org//
893ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// Multiple instances of GTMLogger can be created, each configured their own
903ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// way.  Though GTMLogger is not a singleton (in the GoF sense), it does provide
913ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// access to a shared (i.e., globally accessible) GTMLogger instance. This makes
923ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// it convenient for all code in a process to use the same GTMLogger instance.
933ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// The shared GTMLogger instance can also be configured in an arbitrary, and
943ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// these configuration changes will affect all code that logs through the shared
953ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// instance.
963ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
973ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
983ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// Log Levels
993ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// ----------
1003ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// GTMLogger has 3 different log levels: Debug, Info, and Error. GTMLogger
1013ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// doesn't take any special action based on the log level; it simply forwards
1023ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// this information on to formatters, filters, and writers, each of which may
1033ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// optionally take action based on the level. Since log level filtering is
1043ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// performed at runtime, log messages are typically not filtered out at compile
1053ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// time.  The exception to this rule is that calls to the GTMLoggerDebug() macro
1063ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// *ARE* filtered out of non-DEBUG builds. This is to be backwards compatible
1073ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// with behavior that many developers are currently used to. Note that this
1083ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// means that GTMLoggerDebug(@"hi") will be compiled out of Release builds, but
1093ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// [[GTMLogger sharedLogger] logDebug:@"hi"] will NOT be compiled out.
1102b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org//
1113ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// Standard loggers are created with the GTMLogLevelFilter log filter, which
1123ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// filters out certain log messages based on log level, and some other settings.
1132b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org//
1143ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// In addition to the -logDebug:, -logInfo:, and -logError: methods defined on
1153ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// GTMLogger itself, there are also C macros that make usage of the shared
1163ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// GTMLogger instance very convenient. These macros are:
1173ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
1183ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//   GTMLoggerDebug(...)
1193ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//   GTMLoggerInfo(...)
1203ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//   GTMLoggerError(...)
1213ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
1223ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// Again, a notable feature of these macros is that GTMLogDebug() calls *will be
1233ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// compiled out of non-DEBUG builds*.
1243ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
1253ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// Standard Loggers
1263ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// ----------------
1273ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// GTMLogger has the concept of "standard loggers". A standard logger is simply
1283ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// a logger that is pre-configured with some standard/common writer, formatter,
1293ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// and filter combination. Standard loggers are created using the creation
1303ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// methods beginning with "standard". The alternative to a standard logger is a
1313ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// regular logger, which will send messages to stdout, with no special
1323ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// formatting, and no filtering.
1333ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
1343ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// How do I use GTMLogger?
1353ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// ----------------------
1363ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// The typical way you will want to use GTMLogger is to simply use the
1373ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// GTMLogger*() macros for logging from code. That way we can easily make
1383ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// changes to the GTMLogger class and simply update the macros accordingly. Only
1393ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// your application startup code (perhaps, somewhere in main()) should use the
1403ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// GTMLogger class directly in order to configure the shared logger, which all
1413ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// of the code using the macros will be using. Again, this is just the typical
1423ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// situation.
1432b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org//
1443ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// To be complete, there are cases where you may want to use GTMLogger directly,
1453ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// or even create separate GTMLogger instances for some reason. That's fine,
1463ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// too.
1473ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
1483ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// Examples
1493ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// --------
1503ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// The following show some common GTMLogger use cases.
1513ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
1523ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// 1. You want to log something as simply as possible. Also, this call will only
1533ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//    appear in debug builds. In non-DEBUG builds it will be completely removed.
1543ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
1553ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//      GTMLoggerDebug(@"foo = %@", foo);
1563ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
1572b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org// 2. The previous example is similar to the following. The major difference is
1583ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//    that the previous call (example 1) will be compiled out of Release builds
1593ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//    but this statement will not be compiled out.
1603ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
1613ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//      [[GTMLogger sharedLogger] logDebug:@"foo = %@", foo];
1623ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
1633ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// 3. Send all logging output from the shared logger to a file. We do this by
1642b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org//    creating an NSFileHandle for writing associated with a file, and setting
1653ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//    that file handle as the logger's writer.
1663ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
1673ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//      NSFileHandle *f = [NSFileHandle fileHandleForWritingAtPath:@"/tmp/f.log"
1683ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//                                                          create:YES];
1693ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//      [[GTMLogger sharedLogger] setWriter:f];
1703ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//      GTMLoggerError(@"hi");  // This will be sent to /tmp/f.log
1713ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
1723ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// 4. Create a new GTMLogger that will log to a file. This example differs from
1733ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//    the previous one because here we create a new GTMLogger that is different
1743ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//    from the shared logger.
1753ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
1763ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//      GTMLogger *logger = [GTMLogger standardLoggerWithPath:@"/tmp/temp.log"];
1773ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//      [logger logInfo:@"hi temp log file"];
1783ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
1793ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// 5. Create a logger that writes to stdout and does NOT do any formatting to
1803ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//    the log message. This might be useful, for example, when writing a help
1813ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//    screen for a command-line tool to standard output.
1822b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org//
1833ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//      GTMLogger *logger = [GTMLogger logger];
1843ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//      [logger logInfo:@"%@ version 0.1 usage", progName];
1853ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
1862b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org// 6. Send log output to stdout AND to a log file. The trick here is that
1872b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org//    NSArrays function as composite log writers, which means when an array is
1883ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//    set as the log writer, it forwards all logging messages to all of its
1893ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//    contained GTMLogWriters.
1903ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
1913ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//      // Create array of GTMLogWriters
1923ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//      NSArray *writers = [NSArray arrayWithObjects:
1933ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//          [NSFileHandle fileHandleForWritingAtPath:@"/tmp/f.log" create:YES],
1943ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//          [NSFileHandle fileHandleWithStandardOutput], nil];
1952b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org//
1963ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//      GTMLogger *logger = [GTMLogger standardLogger];
1973ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//      [logger setWriter:writers];
1983ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//      [logger logInfo:@"hi"];  // Output goes to stdout and /tmp/f.log
1993ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
2003ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// For futher details on log writers, formatters, and filters, see the
2013ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// documentation below.
2023ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
2033ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// NOTE: GTMLogger is application level logging.  By default it does nothing
2043ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// with _GTMDevLog/_GTMDevAssert (see GTMDefines.h).  An application can choose
2053ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// to bridge _GTMDevLog/_GTMDevAssert to GTMLogger by providing macro
2063ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// definitions in its prefix header (see GTMDefines.h for how one would do
2073ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// that).
2083ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
2093ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid@interface GTMLogger : NSObject {
2103ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid @private
2113ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  id<GTMLogWriter> writer_;
2123ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  id<GTMLogFormatter> formatter_;
2133ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  id<GTMLogFilter> filter_;
2143ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid}
2153ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
2163ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
2173ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// Accessors for the shared logger instance
2183ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
2193ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
2203ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// Returns a shared/global standard GTMLogger instance. Callers should typically
2213ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// use this method to get a GTMLogger instance, unless they explicitly want
2223ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// their own instance to configure for their own needs. This is the only method
2233ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// that returns a shared instance; all the rest return new GTMLogger instances.
2243ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid+ (id)sharedLogger;
2253ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
2263ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// Sets the shared logger instance to |logger|. Future calls to +sharedLogger
2273ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// will return |logger| instead.
2283ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid+ (void)setSharedLogger:(GTMLogger *)logger;
2293ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
2303ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
2313ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// Creation methods
2323ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
2333ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
2343ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// Returns a new autoreleased GTMLogger instance that will log to stdout, using
2353ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// the GTMLogStandardFormatter, and the GTMLogLevelFilter filter.
2363ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid+ (id)standardLogger;
2373ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
2383ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// Same as +standardLogger, but logs to stderr.
2393ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid+ (id)standardLoggerWithStderr;
2403ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
2412b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org// Same as +standardLogger but levels >= kGTMLoggerLevelError are routed to
2422b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org// stderr, everything else goes to stdout.
2432b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org+ (id)standardLoggerWithStdoutAndStderr;
2442b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org
2453ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// Returns a new standard GTMLogger instance with a log writer that will
2463ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// write to the file at |path|, and will use the GTMLogStandardFormatter and
2473ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// GTMLogLevelFilter classes. If |path| does not exist, it will be created.
2483ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid+ (id)standardLoggerWithPath:(NSString *)path;
2493ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
2503ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// Returns an autoreleased GTMLogger instance that will use the specified
2513ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// |writer|, |formatter|, and |filter|.
2523ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid+ (id)loggerWithWriter:(id<GTMLogWriter>)writer
2533ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid             formatter:(id<GTMLogFormatter>)formatter
2543ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid                filter:(id<GTMLogFilter>)filter;
2553ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
2563ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// Returns an autoreleased GTMLogger instance that logs to stdout, with the
2573ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// basic formatter, and no filter. The returned logger differs from the logger
2583ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// returned by +standardLogger because this one does not do any filtering and
2593ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// does not do any special log formatting; this is the difference between a
2603ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// "regular" logger and a "standard" logger.
2613ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid+ (id)logger;
2623ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
2633ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// Designated initializer. This method returns a GTMLogger initialized with the
2643ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// specified |writer|, |formatter|, and |filter|. See the setter methods below
2653ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// for what values will be used if nil is passed for a parameter.
2663ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid- (id)initWithWriter:(id<GTMLogWriter>)writer
2673ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid           formatter:(id<GTMLogFormatter>)formatter
2683ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid              filter:(id<GTMLogFilter>)filter;
2693ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
2703ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
2713ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// Logging  methods
2723ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
2733ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
2743ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// Logs a message at the debug level (kGTMLoggerLevelDebug).
2752b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org- (void)logDebug:(NSString *)fmt, ... NS_FORMAT_FUNCTION(1, 2);
2763ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// Logs a message at the info level (kGTMLoggerLevelInfo).
2772b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org- (void)logInfo:(NSString *)fmt, ... NS_FORMAT_FUNCTION(1, 2);
2783ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// Logs a message at the error level (kGTMLoggerLevelError).
2792b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org- (void)logError:(NSString *)fmt, ... NS_FORMAT_FUNCTION(1, 2);
2803ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// Logs a message at the assert level (kGTMLoggerLevelAssert).
2812b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org- (void)logAssert:(NSString *)fmt, ... NS_FORMAT_FUNCTION(1, 2);
2823ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
2833ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
2843ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
2853ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// Accessors
2863ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
2873ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
2882b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org// Accessor methods for the log writer. If the log writer is set to nil,
2893ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// [NSFileHandle fileHandleWithStandardOutput] is used.
2903ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid- (id<GTMLogWriter>)writer;
2913ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid- (void)setWriter:(id<GTMLogWriter>)writer;
2923ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
2933ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// Accessor methods for the log formatter. If the log formatter is set to nil,
2943ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// GTMLogBasicFormatter is used. This formatter will format log messages in a
2953ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// plain printf style.
2963ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid- (id<GTMLogFormatter>)formatter;
2973ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid- (void)setFormatter:(id<GTMLogFormatter>)formatter;
2983ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
2993ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// Accessor methods for the log filter. If the log filter is set to nil,
3003ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// GTMLogNoFilter is used, which allows all log messages through.
3013ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid- (id<GTMLogFilter>)filter;
3023ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid- (void)setFilter:(id<GTMLogFilter>)filter;
3033ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
3043ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid@end  // GTMLogger
3053ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
3063ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
3072b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org// Helper functions that are used by the convenience GTMLogger*() macros that
3083ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// enable the logging of function names.
3093ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid@interface GTMLogger (GTMLoggerMacroHelpers)
3103ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid- (void)logFuncDebug:(const char *)func msg:(NSString *)fmt, ...
3112b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org  NS_FORMAT_FUNCTION(2, 3);
3123ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid- (void)logFuncInfo:(const char *)func msg:(NSString *)fmt, ...
3132b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org  NS_FORMAT_FUNCTION(2, 3);
3143ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid- (void)logFuncError:(const char *)func msg:(NSString *)fmt, ...
3152b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org  NS_FORMAT_FUNCTION(2, 3);
3163ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid- (void)logFuncAssert:(const char *)func msg:(NSString *)fmt, ...
3172b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org  NS_FORMAT_FUNCTION(2, 3);
3183ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid@end  // GTMLoggerMacroHelpers
3193ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
3203ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
3212b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org// The convenience macros are only defined if they haven't already been defined.
3222b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org#ifndef GTMLoggerInfo
3232b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org
3243ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// Convenience macros that log to the shared GTMLogger instance. These macros
3253ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// are how users should typically log to GTMLogger. Notice that GTMLoggerDebug()
3263ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// calls will be compiled out of non-Debug builds.
3273ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid#define GTMLoggerDebug(...)  \
3283ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  [[GTMLogger sharedLogger] logFuncDebug:__func__ msg:__VA_ARGS__]
3293ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid#define GTMLoggerInfo(...)   \
3303ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  [[GTMLogger sharedLogger] logFuncInfo:__func__ msg:__VA_ARGS__]
3313ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid#define GTMLoggerError(...)  \
3323ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  [[GTMLogger sharedLogger] logFuncError:__func__ msg:__VA_ARGS__]
3333ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid#define GTMLoggerAssert(...) \
3343ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  [[GTMLogger sharedLogger] logFuncAssert:__func__ msg:__VA_ARGS__]
3353ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
3363ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// If we're not in a debug build, remove the GTMLoggerDebug statements. This
3373ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// makes calls to GTMLoggerDebug "compile out" of Release builds
3383ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid#ifndef DEBUG
3393ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid#undef GTMLoggerDebug
3403ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid#define GTMLoggerDebug(...) do {} while(0)
3413ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid#endif
3423ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
3432b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org#endif  // !defined(GTMLoggerInfo)
3442b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org
3453ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// Log levels.
3463ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsidtypedef enum {
3473ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  kGTMLoggerLevelUnknown,
3483ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  kGTMLoggerLevelDebug,
3493ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  kGTMLoggerLevelInfo,
3503ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  kGTMLoggerLevelError,
3513ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  kGTMLoggerLevelAssert,
3523ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid} GTMLoggerLevel;
3533ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
3543ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
3553ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
3563ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//   Log Writers
3573ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
3583ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
3593ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// Protocol to be implemented by a GTMLogWriter instance.
3603ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid@protocol GTMLogWriter <NSObject>
3613ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// Writes the given log message to where the log writer is configured to write.
3623ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid- (void)logMessage:(NSString *)msg level:(GTMLoggerLevel)level;
3633ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid@end  // GTMLogWriter
3643ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
3653ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
3663ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// Simple category on NSFileHandle that makes NSFileHandles valid log writers.
3673ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// This is convenient because something like, say, +fileHandleWithStandardError
3683ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// now becomes a valid log writer. Log messages are written to the file handle
3693ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// with a newline appended.
3703ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid@interface NSFileHandle (GTMFileHandleLogWriter) <GTMLogWriter>
3712b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org// Opens the file at |path| in append mode, and creates the file with |mode|
3723ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// if it didn't previously exist.
3733ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid+ (id)fileHandleForLoggingAtPath:(NSString *)path mode:(mode_t)mode;
3743ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid@end  // NSFileHandle
3753ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
3763ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
3773ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// This category makes NSArray a GTMLogWriter that can be composed of other
3783ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// GTMLogWriters. This is the classic Composite GoF design pattern. When the
3793ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// GTMLogWriter -logMessage:level: message is sent to the array, the array
3803ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// forwards the message to all of its elements that implement the GTMLogWriter
3813ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// protocol.
3823ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
3833ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// This is useful in situations where you would like to send log output to
3843ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// multiple log writers at the same time. Simply create an NSArray of the log
3852b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org// writers you wish to use, then set the array as the "writer" for your
3863ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// GTMLogger instance.
3873ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid@interface NSArray (GTMArrayCompositeLogWriter) <GTMLogWriter>
3883ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid@end  // GTMArrayCompositeLogWriter
3893ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
3903ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
3913ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// This category adapts the GTMLogger interface so that it can be used as a log
3923ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// writer; it's an "adapter" in the GoF Adapter pattern sense.
3933ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
3943ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// This is useful when you want to configure a logger to log to a specific
3953ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// writer with a specific formatter and/or filter. But you want to also compose
3962b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org// that with a different log writer that may have its own formatter and/or
3973ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// filter.
3983ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid@interface GTMLogger (GTMLoggerLogWriter) <GTMLogWriter>
3993ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid@end  // GTMLoggerLogWriter
4003ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
4013ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
4023ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
4033ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//   Log Formatters
4043ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
4053ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
4063ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// Protocol to be implemented by a GTMLogFormatter instance.
4073ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid@protocol GTMLogFormatter <NSObject>
4083ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// Returns a formatted string using the format specified in |fmt| and the va
4093ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// args specified in |args|.
4103ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid- (NSString *)stringForFunc:(NSString *)func
4113ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid                 withFormat:(NSString *)fmt
4123ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid                     valist:(va_list)args
4132b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org                      level:(GTMLoggerLevel)level NS_FORMAT_FUNCTION(2, 0);
4143ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid@end  // GTMLogFormatter
4153ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
4163ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
4172b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org// A basic log formatter that formats a string the same way that NSLog (or
4183ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// printf) would. It does not do anything fancy, nor does it add any data of its
4193ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// own.
4203ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid@interface GTMLogBasicFormatter : NSObject <GTMLogFormatter>
4212b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org
4222b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org// Helper method for prettying C99 __func__ and GCC __PRETTY_FUNCTION__
4232b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org- (NSString *)prettyNameForFunc:(NSString *)func;
4242b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org
4253ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid@end  // GTMLogBasicFormatter
4263ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
4273ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
4283ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// A log formatter that formats the log string like the basic formatter, but
4293ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// also prepends a timestamp and some basic process info to the message, as
4303ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// shown in the following sample output.
4313ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//   2007-12-30 10:29:24.177 myapp[4588/0xa07d0f60] [lvl=1] log mesage here
4323ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid@interface GTMLogStandardFormatter : GTMLogBasicFormatter {
4333ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid @private
4343ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  NSDateFormatter *dateFormatter_;  // yyyy-MM-dd HH:mm:ss.SSS
4353ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  NSString *pname_;
4363ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  pid_t pid_;
4373ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid}
4383ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid@end  // GTMLogStandardFormatter
4393ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
4403ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
4413ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
4423ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//   Log Filters
4433ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
4443ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
4453ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// Protocol to be imlemented by a GTMLogFilter instance.
4463ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid@protocol GTMLogFilter <NSObject>
4473ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// Returns YES if |msg| at |level| should be filtered out; NO otherwise.
4483ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid- (BOOL)filterAllowsMessage:(NSString *)msg level:(GTMLoggerLevel)level;
4493ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid@end  // GTMLogFilter
4503ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
4513ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
4523ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// A log filter that filters messages at the kGTMLoggerLevelDebug level out of
4533ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// non-debug builds. Messages at the kGTMLoggerLevelInfo level are also filtered
4543ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// out of non-debug builds unless GTMVerboseLogging is set in the environment or
4553ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// the processes's defaults. Messages at the kGTMLoggerLevelError level are
4563ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// never filtered.
4573ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid@interface GTMLogLevelFilter : NSObject <GTMLogFilter>
4583ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid@end  // GTMLogLevelFilter
4593ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
4603ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// A simple log filter that does NOT filter anything out;
4613ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// -filterAllowsMessage:level will always return YES. This can be a convenient
4623ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// way to enable debug-level logging in release builds (if you so desire).
4633ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid@interface GTMLogNoFilter : NSObject <GTMLogFilter>
4643ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid@end  // GTMLogNoFilter
4652b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org
4662b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org
4672b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org// Base class for custom level filters. Not for direct use, use the minimum
4682b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org// or maximum level subclasses below.
4692b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org@interface GTMLogAllowedLevelFilter : NSObject <GTMLogFilter> {
4702b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org @private
4712b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org  NSIndexSet *allowedLevels_;
4722b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org}
4732b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org@end
4742b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org
4752b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org// A log filter that allows you to set a minimum log level. Messages below this
4762b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org// level will be filtered.
4772b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org@interface GTMLogMininumLevelFilter : GTMLogAllowedLevelFilter
4782b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org
4792b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org// Designated initializer, logs at levels < |level| will be filtered.
4802b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org- (id)initWithMinimumLevel:(GTMLoggerLevel)level;
4812b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org
4822b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org@end
4832b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org
4842b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org// A log filter that allows you to set a maximum log level. Messages whose level
4852b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org// exceeds this level will be filtered. This is really only useful if you have
4862b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org// a composite GTMLogger that is sending the other messages elsewhere.
4872b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org@interface GTMLogMaximumLevelFilter : GTMLogAllowedLevelFilter
4882b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org
4892b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org// Designated initializer, logs at levels > |level| will be filtered.
4902b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org- (id)initWithMaximumLevel:(GTMLoggerLevel)level;
4912b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org
4922b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org@end
4932b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org
4942b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org
4952b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org// For subclasses only
4962b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org@interface GTMLogger (PrivateMethods)
4972b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org
4982b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org- (void)logInternalFunc:(const char *)func
4992b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org                 format:(NSString *)fmt
5002b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org                 valist:(va_list)args
5012b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org                  level:(GTMLoggerLevel)level NS_FORMAT_FUNCTION(2, 0);
5022b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org
5032b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org@end
5042b18e3c814d6e233ef2205026b9bc521044822abqsr@chromium.org
505