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