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