Subversion Repositories Mobile Apps.GyroMouse

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. #import <Foundation/Foundation.h>
  2.  
  3. /**
  4.  * Welcome to Cocoa Lumberjack!
  5.  *
  6.  * The project page has a wealth of documentation if you have any questions.
  7.  * https://github.com/CocoaLumberjack/CocoaLumberjack
  8.  *
  9.  * If you're new to the project you may wish to read the "Getting Started" wiki.
  10.  * https://github.com/CocoaLumberjack/CocoaLumberjack/wiki/GettingStarted
  11.  *
  12.  * Otherwise, here is a quick refresher.
  13.  * There are three steps to using the macros:
  14.  *
  15.  * Step 1:
  16.  * Import the header in your implementation file:
  17.  *
  18.  * #import "DDLog.h"
  19.  *
  20.  * Step 2:
  21.  * Define your logging level in your implementation file:
  22.  *
  23.  * // Log levels: off, error, warn, info, verbose
  24.  * static const int ddLogLevel = LOG_LEVEL_VERBOSE;
  25.  *
  26.  * Step 2 [3rd party frameworks]:
  27.  *
  28.  * Define your LOG_LEVEL_DEF to a different variable/function than ddLogLevel:
  29.  *
  30.  * // #undef LOG_LEVEL_DEF // Undefine first only if needed
  31.  * #define LOG_LEVEL_DEF myLibLogLevel
  32.  *
  33.  * Define your logging level in your implementation file:
  34.  *
  35.  * // Log levels: off, error, warn, info, verbose
  36.  * static const int myLibLogLevel = LOG_LEVEL_VERBOSE;
  37.  *
  38.  * Step 3:
  39.  * Replace your NSLog statements with DDLog statements according to the severity of the message.
  40.  *
  41.  * NSLog(@"Fatal error, no dohickey found!"); -> DDLogError(@"Fatal error, no dohickey found!");
  42.  *
  43.  * DDLog works exactly the same as NSLog.
  44.  * This means you can pass it multiple variables just like NSLog.
  45. **/
  46.  
  47. #ifndef LOG_LEVEL_DEF
  48.     #define LOG_LEVEL_DEF ddLogLevel
  49. #endif
  50.  
  51. @class DDLogMessage;
  52.  
  53. @protocol DDLogger;
  54. @protocol DDLogFormatter;
  55.  
  56. /**
  57.  * This is the single macro that all other macros below compile into.
  58.  * This big multiline macro makes all the other macros easier to read.
  59. **/
  60.  
  61. #define LOG_MACRO(isAsynchronous, lvl, flg, ctx, atag, fnct, frmt, ...) \
  62.   [DDLog log:isAsynchronous                                             \
  63.        level:lvl                                                        \
  64.         flag:flg                                                        \
  65.      context:ctx                                                        \
  66.         file:__FILE__                                                   \
  67.     function:fnct                                                       \
  68.         line:__LINE__                                                   \
  69.          tag:atag                                                       \
  70.       format:(frmt), ##__VA_ARGS__]
  71.  
  72. /**
  73.  * Define the Objective-C and C versions of the macro.
  74.  * These automatically inject the proper function name for either an objective-c method or c function.
  75.  *
  76.  * We also define shorthand versions for asynchronous and synchronous logging.
  77. **/
  78.  
  79. #define LOG_OBJC_MACRO(async, lvl, flg, ctx, frmt, ...) \
  80.              LOG_MACRO(async, lvl, flg, ctx, nil, sel_getName(_cmd), frmt, ##__VA_ARGS__)
  81.  
  82. #define LOG_C_MACRO(async, lvl, flg, ctx, frmt, ...) \
  83.           LOG_MACRO(async, lvl, flg, ctx, nil, __FUNCTION__, frmt, ##__VA_ARGS__)
  84.  
  85. #define  SYNC_LOG_OBJC_MACRO(lvl, flg, ctx, frmt, ...) \
  86.               LOG_OBJC_MACRO( NO, lvl, flg, ctx, frmt, ##__VA_ARGS__)
  87.  
  88. #define ASYNC_LOG_OBJC_MACRO(lvl, flg, ctx, frmt, ...) \
  89.               LOG_OBJC_MACRO(YES, lvl, flg, ctx, frmt, ##__VA_ARGS__)
  90.  
  91. #define  SYNC_LOG_C_MACRO(lvl, flg, ctx, frmt, ...) \
  92.               LOG_C_MACRO( NO, lvl, flg, ctx, frmt, ##__VA_ARGS__)
  93.  
  94. #define ASYNC_LOG_C_MACRO(lvl, flg, ctx, frmt, ...) \
  95.               LOG_C_MACRO(YES, lvl, flg, ctx, frmt, ##__VA_ARGS__)
  96.  
  97. /**
  98.  * Define version of the macro that only execute if the logLevel is above the threshold.
  99.  * The compiled versions essentially look like this:
  100.  *
  101.  * if (logFlagForThisLogMsg & ddLogLevel) { execute log message }
  102.  *
  103.  * When LOG_LEVEL_DEF is defined as ddLogLevel.
  104.  *
  105.  * As shown further below, Lumberjack actually uses a bitmask as opposed to primitive log levels.
  106.  * This allows for a great amount of flexibility and some pretty advanced fine grained logging techniques.
  107.  *
  108.  * Note that when compiler optimizations are enabled (as they are for your release builds),
  109.  * the log messages above your logging threshold will automatically be compiled out.
  110.  *
  111.  * (If the compiler sees ddLogLevel declared as a constant, the compiler simply checks to see if the 'if' statement
  112.  *  would execute, and if not it strips it from the binary.)
  113.  *
  114.  * We also define shorthand versions for asynchronous and synchronous logging.
  115. **/
  116.  
  117. #define LOG_MAYBE(async, lvl, flg, ctx, fnct, frmt, ...) \
  118.   do { if(lvl & flg) LOG_MACRO(async, lvl, flg, ctx, nil, fnct, frmt, ##__VA_ARGS__); } while(0)
  119.  
  120. #define LOG_OBJC_MAYBE(async, lvl, flg, ctx, frmt, ...) \
  121.              LOG_MAYBE(async, lvl, flg, ctx, sel_getName(_cmd), frmt, ##__VA_ARGS__)
  122.  
  123. #define LOG_C_MAYBE(async, lvl, flg, ctx, frmt, ...) \
  124.           LOG_MAYBE(async, lvl, flg, ctx, __FUNCTION__, frmt, ##__VA_ARGS__)
  125.  
  126. #define  SYNC_LOG_OBJC_MAYBE(lvl, flg, ctx, frmt, ...) \
  127.               LOG_OBJC_MAYBE( NO, lvl, flg, ctx, frmt, ##__VA_ARGS__)
  128.  
  129. #define ASYNC_LOG_OBJC_MAYBE(lvl, flg, ctx, frmt, ...) \
  130.               LOG_OBJC_MAYBE(YES, lvl, flg, ctx, frmt, ##__VA_ARGS__)
  131.  
  132. #define  SYNC_LOG_C_MAYBE(lvl, flg, ctx, frmt, ...) \
  133.               LOG_C_MAYBE( NO, lvl, flg, ctx, frmt, ##__VA_ARGS__)
  134.  
  135. #define ASYNC_LOG_C_MAYBE(lvl, flg, ctx, frmt, ...) \
  136.               LOG_C_MAYBE(YES, lvl, flg, ctx, frmt, ##__VA_ARGS__)
  137.  
  138. /**
  139.  * Define versions of the macros that also accept tags.
  140.  *
  141.  * The DDLogMessage object includes a 'tag' ivar that may be used for a variety of purposes.
  142.  * It may be used to pass custom information to loggers or formatters.
  143.  * Or it may be used by 3rd party extensions to the framework.
  144.  *
  145.  * Thes macros just make it a little easier to extend logging functionality.
  146. **/
  147.  
  148. #define LOG_OBJC_TAG_MACRO(async, lvl, flg, ctx, tag, frmt, ...) \
  149.                  LOG_MACRO(async, lvl, flg, ctx, tag, sel_getName(_cmd), frmt, ##__VA_ARGS__)
  150.  
  151. #define LOG_C_TAG_MACRO(async, lvl, flg, ctx, tag, frmt, ...) \
  152.               LOG_MACRO(async, lvl, flg, ctx, tag, __FUNCTION__, frmt, ##__VA_ARGS__)
  153.  
  154. #define LOG_TAG_MAYBE(async, lvl, flg, ctx, tag, fnct, frmt, ...) \
  155.   do { if(lvl & flg) LOG_MACRO(async, lvl, flg, ctx, tag, fnct, frmt, ##__VA_ARGS__); } while(0)
  156.  
  157. #define LOG_OBJC_TAG_MAYBE(async, lvl, flg, ctx, tag, frmt, ...) \
  158.              LOG_TAG_MAYBE(async, lvl, flg, ctx, tag, sel_getName(_cmd), frmt, ##__VA_ARGS__)
  159.  
  160. #define LOG_C_TAG_MAYBE(async, lvl, flg, ctx, tag, frmt, ...) \
  161.           LOG_TAG_MAYBE(async, lvl, flg, ctx, tag, __FUNCTION__, frmt, ##__VA_ARGS__)
  162.  
  163. /**
  164.  * Define the standard options.
  165.  *
  166.  * We default to only 4 levels because it makes it easier for beginners
  167.  * to make the transition to a logging framework.
  168.  *
  169.  * More advanced users may choose to completely customize the levels (and level names) to suite their needs.
  170.  * For more information on this see the "Custom Log Levels" page:
  171.  * https://github.com/CocoaLumberjack/CocoaLumberjack/wiki/CustomLogLevels
  172.  *
  173.  * Advanced users may also notice that we're using a bitmask.
  174.  * This is to allow for custom fine grained logging:
  175.  * https://github.com/CocoaLumberjack/CocoaLumberjack/wiki/FineGrainedLogging
  176.  *
  177.  * -- Flags --
  178.  *
  179.  * Typically you will use the LOG_LEVELS (see below), but the flags may be used directly in certain situations.
  180.  * For example, say you have a lot of warning log messages, and you wanted to disable them.
  181.  * However, you still needed to see your error and info log messages.
  182.  * You could accomplish that with the following:
  183.  *
  184.  * static const int ddLogLevel = LOG_FLAG_ERROR | LOG_FLAG_INFO;
  185.  *
  186.  * When LOG_LEVEL_DEF is defined as ddLogLevel.
  187.  *
  188.  * Flags may also be consulted when writing custom log formatters,
  189.  * as the DDLogMessage class captures the individual flag that caused the log message to fire.
  190.  *
  191.  * -- Levels --
  192.  *
  193.  * Log levels are simply the proper bitmask of the flags.
  194.  *
  195.  * -- Booleans --
  196.  *
  197.  * The booleans may be used when your logging code involves more than one line.
  198.  * For example:
  199.  *
  200.  * if (LOG_VERBOSE) {
  201.  *     for (id sprocket in sprockets)
  202.  *         DDLogVerbose(@"sprocket: %@", [sprocket description])
  203.  * }
  204.  *
  205.  * -- Async --
  206.  *
  207.  * Defines the default asynchronous options.
  208.  * The default philosophy for asynchronous logging is very simple:
  209.  *
  210.  * Log messages with errors should be executed synchronously.
  211.  *     After all, an error just occurred. The application could be unstable.
  212.  *
  213.  * All other log messages, such as debug output, are executed asynchronously.
  214.  *     After all, if it wasn't an error, then it was just informational output,
  215.  *     or something the application was easily able to recover from.
  216.  *
  217.  * -- Changes --
  218.  *
  219.  * You are strongly discouraged from modifying this file.
  220.  * If you do, you make it more difficult on yourself to merge future bug fixes and improvements from the project.
  221.  * Instead, create your own MyLogging.h or ApplicationNameLogging.h or CompanyLogging.h
  222.  *
  223.  * For an example of customizing your logging experience, see the "Custom Log Levels" page:
  224.  * https://github.com/CocoaLumberjack/CocoaLumberjack/wiki/CustomLogLevels
  225. **/
  226.  
  227. #define LOG_FLAG_ERROR    (1 << 0)  // 0...00001
  228. #define LOG_FLAG_WARN     (1 << 1)  // 0...00010
  229. #define LOG_FLAG_INFO     (1 << 2)  // 0...00100
  230. #define LOG_FLAG_DEBUG    (1 << 3)  // 0...01000
  231. #define LOG_FLAG_VERBOSE  (1 << 4)  // 0...10000
  232.  
  233. #define LOG_LEVEL_OFF     0
  234. #define LOG_LEVEL_ERROR   (LOG_FLAG_ERROR)                                                                          // 0...00001
  235. #define LOG_LEVEL_WARN    (LOG_FLAG_ERROR | LOG_FLAG_WARN)                                                          // 0...00011
  236. #define LOG_LEVEL_INFO    (LOG_FLAG_ERROR | LOG_FLAG_WARN | LOG_FLAG_INFO)                                          // 0...00111
  237. #define LOG_LEVEL_DEBUG   (LOG_FLAG_ERROR | LOG_FLAG_WARN | LOG_FLAG_INFO | LOG_FLAG_DEBUG)                         // 0...01111
  238. #define LOG_LEVEL_VERBOSE (LOG_FLAG_ERROR | LOG_FLAG_WARN | LOG_FLAG_INFO | LOG_FLAG_DEBUG | LOG_FLAG_VERBOSE)      // 0...11111
  239.  
  240. #define LOG_ERROR    (LOG_LEVEL_DEF & LOG_FLAG_ERROR)
  241. #define LOG_WARN     (LOG_LEVEL_DEF & LOG_FLAG_WARN)
  242. #define LOG_INFO     (LOG_LEVEL_DEF & LOG_FLAG_INFO)
  243. #define LOG_DEBUG    (LOG_LEVEL_DEF & LOG_FLAG_DEBUG)
  244. #define LOG_VERBOSE  (LOG_LEVEL_DEF & LOG_FLAG_VERBOSE)
  245.  
  246. #define LOG_ASYNC_ENABLED YES
  247.  
  248. #define LOG_ASYNC_ERROR    ( NO && LOG_ASYNC_ENABLED)
  249. #define LOG_ASYNC_WARN     (YES && LOG_ASYNC_ENABLED)
  250. #define LOG_ASYNC_INFO     (YES && LOG_ASYNC_ENABLED)
  251. #define LOG_ASYNC_DEBUG    (YES && LOG_ASYNC_ENABLED)
  252. #define LOG_ASYNC_VERBOSE  (YES && LOG_ASYNC_ENABLED)
  253.  
  254. #define DDLogError(frmt, ...)   LOG_OBJC_MAYBE(LOG_ASYNC_ERROR,   LOG_LEVEL_DEF, LOG_FLAG_ERROR,   0, frmt, ##__VA_ARGS__)
  255. #define DDLogWarn(frmt, ...)    LOG_OBJC_MAYBE(LOG_ASYNC_WARN,    LOG_LEVEL_DEF, LOG_FLAG_WARN,    0, frmt, ##__VA_ARGS__)
  256. #define DDLogInfo(frmt, ...)    LOG_OBJC_MAYBE(LOG_ASYNC_INFO,    LOG_LEVEL_DEF, LOG_FLAG_INFO,    0, frmt, ##__VA_ARGS__)
  257. #define DDLogDebug(frmt, ...)   LOG_OBJC_MAYBE(LOG_ASYNC_DEBUG,   LOG_LEVEL_DEF, LOG_FLAG_DEBUG,   0, frmt, ##__VA_ARGS__)
  258. #define DDLogVerbose(frmt, ...) LOG_OBJC_MAYBE(LOG_ASYNC_VERBOSE, LOG_LEVEL_DEF, LOG_FLAG_VERBOSE, 0, frmt, ##__VA_ARGS__)
  259.  
  260. #define DDLogCError(frmt, ...)   LOG_C_MAYBE(LOG_ASYNC_ERROR,   LOG_LEVEL_DEF, LOG_FLAG_ERROR,   0, frmt, ##__VA_ARGS__)
  261. #define DDLogCWarn(frmt, ...)    LOG_C_MAYBE(LOG_ASYNC_WARN,    LOG_LEVEL_DEF, LOG_FLAG_WARN,    0, frmt, ##__VA_ARGS__)
  262. #define DDLogCInfo(frmt, ...)    LOG_C_MAYBE(LOG_ASYNC_INFO,    LOG_LEVEL_DEF, LOG_FLAG_INFO,    0, frmt, ##__VA_ARGS__)
  263. #define DDLogCDebug(frmt, ...)   LOG_C_MAYBE(LOG_ASYNC_DEBUG,   LOG_LEVEL_DEF, LOG_FLAG_DEBUG,   0, frmt, ##__VA_ARGS__)
  264. #define DDLogCVerbose(frmt, ...) LOG_C_MAYBE(LOG_ASYNC_VERBOSE, LOG_LEVEL_DEF, LOG_FLAG_VERBOSE, 0, frmt, ##__VA_ARGS__)
  265.  
  266. /**
  267.  * The THIS_FILE macro gives you an NSString of the file name.
  268.  * For simplicity and clarity, the file name does not include the full path or file extension.
  269.  *
  270.  * For example: DDLogWarn(@"%@: Unable to find thingy", THIS_FILE) -> @"MyViewController: Unable to find thingy"
  271. **/
  272.  
  273. NSString *DDExtractFileNameWithoutExtension(const char *filePath, BOOL copy);
  274.  
  275. #define THIS_FILE (DDExtractFileNameWithoutExtension(__FILE__, NO))
  276.  
  277. /**
  278.  * The THIS_METHOD macro gives you the name of the current objective-c method.
  279.  *
  280.  * For example: DDLogWarn(@"%@ - Requires non-nil strings", THIS_METHOD) -> @"setMake:model: requires non-nil strings"
  281.  *
  282.  * Note: This does NOT work in straight C functions (non objective-c).
  283.  * Instead you should use the predefined __FUNCTION__ macro.
  284. **/
  285.  
  286. #define THIS_METHOD NSStringFromSelector(_cmd)
  287.  
  288.  
  289. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  290. #pragma mark -
  291. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  292.  
  293. @interface DDLog : NSObject
  294.  
  295. /**
  296.  * Provides access to the underlying logging queue.
  297.  * This may be helpful to Logger classes for things like thread synchronization.
  298. **/
  299.  
  300. + (dispatch_queue_t)loggingQueue;
  301.  
  302. /**
  303.  * Logging Primitive.
  304.  *
  305.  * This method is used by the macros above.
  306.  * It is suggested you stick with the macros as they're easier to use.
  307. **/
  308.  
  309. + (void)log:(BOOL)synchronous
  310.       level:(int)level
  311.        flag:(int)flag
  312.     context:(int)context
  313.        file:(const char *)file
  314.    function:(const char *)function
  315.        line:(int)line
  316.         tag:(id)tag
  317.      format:(NSString *)format, ... __attribute__ ((format (__NSString__, 9, 10)));
  318.  
  319. /**
  320.  * Logging Primitive.
  321.  *
  322.  * This method can be used if you have a prepared va_list.
  323. **/
  324.  
  325. + (void)log:(BOOL)asynchronous
  326.       level:(int)level
  327.        flag:(int)flag
  328.     context:(int)context
  329.        file:(const char *)file
  330.    function:(const char *)function
  331.        line:(int)line
  332.         tag:(id)tag
  333.      format:(NSString *)format
  334.        args:(va_list)argList;
  335.  
  336.  
  337. /**
  338.  * Since logging can be asynchronous, there may be times when you want to flush the logs.
  339.  * The framework invokes this automatically when the application quits.
  340. **/
  341.  
  342. + (void)flushLog;
  343.  
  344. /**
  345.  * Loggers
  346.  *
  347.  * If you want your log statements to go somewhere,
  348.  * you should create and add a logger.
  349. **/
  350.  
  351. + (void)addLogger:(id <DDLogger>)logger;    // adds the logger using maximum log level (LOG_LEVEL_VERBOSE)
  352.  
  353. /**
  354.  * Please use as logLevels the LOG_LEVEL_* macros
  355.  *
  356. **/
  357. + (void)addLogger:(id <DDLogger>)logger withLogLevel:(int)logLevel;
  358.  
  359. + (void)removeLogger:(id <DDLogger>)logger;
  360. + (void)removeAllLoggers;
  361.  
  362. /**
  363.  * Registered Dynamic Logging
  364.  *
  365.  * These methods allow you to obtain a list of classes that are using registered dynamic logging,
  366.  * and also provides methods to get and set their log level during run time.
  367. **/
  368.  
  369. + (NSArray *)registeredClasses;
  370. + (NSArray *)registeredClassNames;
  371.  
  372. + (int)logLevelForClass:(Class)aClass;
  373. + (int)logLevelForClassWithName:(NSString *)aClassName;
  374.  
  375. + (void)setLogLevel:(int)logLevel forClass:(Class)aClass;
  376. + (void)setLogLevel:(int)logLevel forClassWithName:(NSString *)aClassName;
  377.  
  378. @end
  379.  
  380. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  381. #pragma mark -
  382. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  383.  
  384. @protocol DDLogger <NSObject>
  385. @required
  386.  
  387. - (void)logMessage:(DDLogMessage *)logMessage;
  388.  
  389. /**
  390.  * Formatters may optionally be added to any logger.
  391.  *
  392.  * If no formatter is set, the logger simply logs the message as it is given in logMessage,
  393.  * or it may use its own built in formatting style.
  394. **/
  395. - (id <DDLogFormatter>)logFormatter;
  396. - (void)setLogFormatter:(id <DDLogFormatter>)formatter;
  397.  
  398. @optional
  399.  
  400. /**
  401.  * Since logging is asynchronous, adding and removing loggers is also asynchronous.
  402.  * In other words, the loggers are added and removed at appropriate times with regards to log messages.
  403.  *
  404.  * - Loggers will not receive log messages that were executed prior to when they were added.
  405.  * - Loggers will not receive log messages that were executed after they were removed.
  406.  *
  407.  * These methods are executed in the logging thread/queue.
  408.  * This is the same thread/queue that will execute every logMessage: invocation.
  409.  * Loggers may use these methods for thread synchronization or other setup/teardown tasks.
  410. **/
  411. - (void)didAddLogger;
  412. - (void)willRemoveLogger;
  413.  
  414. /**
  415.  * Some loggers may buffer IO for optimization purposes.
  416.  * For example, a database logger may only save occasionaly as the disk IO is slow.
  417.  * In such loggers, this method should be implemented to flush any pending IO.
  418.  *
  419.  * This allows invocations of DDLog's flushLog method to be propogated to loggers that need it.
  420.  *
  421.  * Note that DDLog's flushLog method is invoked automatically when the application quits,
  422.  * and it may be also invoked manually by the developer prior to application crashes, or other such reasons.
  423. **/
  424. - (void)flush;
  425.  
  426. /**
  427.  * Each logger is executed concurrently with respect to the other loggers.
  428.  * Thus, a dedicated dispatch queue is used for each logger.
  429.  * Logger implementations may optionally choose to provide their own dispatch queue.
  430. **/
  431. - (dispatch_queue_t)loggerQueue;
  432.  
  433. /**
  434.  * If the logger implementation does not choose to provide its own queue,
  435.  * one will automatically be created for it.
  436.  * The created queue will receive its name from this method.
  437.  * This may be helpful for debugging or profiling reasons.
  438. **/
  439. - (NSString *)loggerName;
  440.  
  441. @end
  442.  
  443. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  444. #pragma mark -
  445. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  446.  
  447. @protocol DDLogFormatter <NSObject>
  448. @required
  449.  
  450. /**
  451.  * Formatters may optionally be added to any logger.
  452.  * This allows for increased flexibility in the logging environment.
  453.  * For example, log messages for log files may be formatted differently than log messages for the console.
  454.  *
  455.  * For more information about formatters, see the "Custom Formatters" page:
  456.  * https://github.com/CocoaLumberjack/CocoaLumberjack/wiki/CustomFormatters
  457.  *
  458.  * The formatter may also optionally filter the log message by returning nil,
  459.  * in which case the logger will not log the message.
  460. **/
  461. - (NSString *)formatLogMessage:(DDLogMessage *)logMessage;
  462.  
  463. @optional
  464.  
  465. /**
  466.  * A single formatter instance can be added to multiple loggers.
  467.  * These methods provides hooks to notify the formatter of when it's added/removed.
  468.  *
  469.  * This is primarily for thread-safety.
  470.  * If a formatter is explicitly not thread-safe, it may wish to throw an exception if added to multiple loggers.
  471.  * Or if a formatter has potentially thread-unsafe code (e.g. NSDateFormatter),
  472.  * it could possibly use these hooks to switch to thread-safe versions of the code.
  473. **/
  474. - (void)didAddToLogger:(id <DDLogger>)logger;
  475. - (void)willRemoveFromLogger:(id <DDLogger>)logger;
  476.  
  477. @end
  478.  
  479. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  480. #pragma mark -
  481. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  482.  
  483. @protocol DDRegisteredDynamicLogging
  484.  
  485. /**
  486.  * Implement these methods to allow a file's log level to be managed from a central location.
  487.  *
  488.  * This is useful if you'd like to be able to change log levels for various parts
  489.  * of your code from within the running application.
  490.  *
  491.  * Imagine pulling up the settings for your application,
  492.  * and being able to configure the logging level on a per file basis.
  493.  *
  494.  * The implementation can be very straight-forward:
  495.  *
  496.  * + (int)ddLogLevel
  497.  * {
  498.  *     return ddLogLevel;
  499.  * }
  500.  *  
  501.  * + (void)ddSetLogLevel:(int)logLevel
  502.  * {
  503.  *     ddLogLevel = logLevel;
  504.  * }
  505. **/
  506.  
  507. + (int)ddLogLevel;
  508. + (void)ddSetLogLevel:(int)logLevel;
  509.  
  510. @end
  511.  
  512. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  513. #pragma mark -
  514. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  515.  
  516. /**
  517.  * The DDLogMessage class encapsulates information about the log message.
  518.  * If you write custom loggers or formatters, you will be dealing with objects of this class.
  519. **/
  520.  
  521. enum {
  522.     DDLogMessageCopyFile     = 1 << 0,
  523.     DDLogMessageCopyFunction = 1 << 1
  524. };
  525. typedef int DDLogMessageOptions;
  526.  
  527. @interface DDLogMessage : NSObject <NSCopying>
  528. {
  529.  
  530. // The public variables below can be accessed directly (for speed).
  531. // For example: logMessage->logLevel
  532.    
  533. @public
  534.     int logLevel;
  535.     int logFlag;
  536.     int logContext;
  537.     NSString *logMsg;
  538.     NSDate *timestamp;
  539.     char *file;
  540.     char *function;
  541.     int lineNumber;
  542.     mach_port_t machThreadID;
  543.     char *queueLabel;
  544.     NSString *threadName;
  545.    
  546.     // For 3rd party extensions to the framework, where flags and contexts aren't enough.
  547.     id tag;
  548.    
  549.     // For 3rd party extensions that manually create DDLogMessage instances.
  550.     DDLogMessageOptions options;
  551. }
  552.  
  553. /**
  554.  * Standard init method for a log message object.
  555.  * Used by the logging primitives. (And the macros use the logging primitives.)
  556.  *
  557.  * If you find need to manually create logMessage objects, there is one thing you should be aware of:
  558.  *
  559.  * If no flags are passed, the method expects the file and function parameters to be string literals.
  560.  * That is, it expects the given strings to exist for the duration of the object's lifetime,
  561.  * and it expects the given strings to be immutable.
  562.  * In other words, it does not copy these strings, it simply points to them.
  563.  * This is due to the fact that __FILE__ and __FUNCTION__ are usually used to specify these parameters,
  564.  * so it makes sense to optimize and skip the unnecessary allocations.
  565.  * However, if you need them to be copied you may use the options parameter to specify this.
  566.  * Options is a bitmask which supports DDLogMessageCopyFile and DDLogMessageCopyFunction.
  567. **/
  568. - (instancetype)initWithLogMsg:(NSString *)logMsg
  569.                          level:(int)logLevel
  570.                           flag:(int)logFlag
  571.                        context:(int)logContext
  572.                           file:(const char *)file
  573.                       function:(const char *)function
  574.                           line:(int)line
  575.                            tag:(id)tag
  576.                        options:(DDLogMessageOptions)optionsMask;
  577.  
  578. /**
  579.  * Returns the threadID as it appears in NSLog.
  580.  * That is, it is a hexadecimal value which is calculated from the machThreadID.
  581. **/
  582. - (NSString *)threadID;
  583.  
  584. /**
  585.  * Convenience property to get just the file name, as the file variable is generally the full file path.
  586.  * This method does not include the file extension, which is generally unwanted for logging purposes.
  587. **/
  588. - (NSString *)fileName;
  589.  
  590. /**
  591.  * Returns the function variable in NSString form.
  592. **/
  593. - (NSString *)methodName;
  594.  
  595. @end
  596.  
  597. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  598. #pragma mark -
  599. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  600.  
  601. /**
  602.  * The DDLogger protocol specifies that an optional formatter can be added to a logger.
  603.  * Most (but not all) loggers will want to support formatters.
  604.  *
  605.  * However, writting getters and setters in a thread safe manner,
  606.  * while still maintaining maximum speed for the logging process, is a difficult task.
  607.  *
  608.  * To do it right, the implementation of the getter/setter has strict requiremenets:
  609.  * - Must NOT require the logMessage method to acquire a lock.
  610.  * - Must NOT require the logMessage method to access an atomic property (also a lock of sorts).
  611.  *
  612.  * To simplify things, an abstract logger is provided that implements the getter and setter.
  613.  *
  614.  * Logger implementations may simply extend this class,
  615.  * and they can ACCESS THE FORMATTER VARIABLE DIRECTLY from within their logMessage method!
  616. **/
  617.  
  618. @interface DDAbstractLogger : NSObject <DDLogger>
  619. {
  620.     id <DDLogFormatter> formatter;
  621.    
  622.     dispatch_queue_t loggerQueue;
  623. }
  624.  
  625. - (id <DDLogFormatter>)logFormatter;
  626. - (void)setLogFormatter:(id <DDLogFormatter>)formatter;
  627.  
  628. // For thread-safety assertions
  629. - (BOOL)isOnGlobalLoggingQueue;
  630. - (BOOL)isOnInternalLoggerQueue;
  631.  
  632. @end
  633.