Przeglądaj źródła

Updated documentation files
- some links were not working as they were not updated after moving the docs from wiki to actual files in the repo
- updated doc according to 2.0 code changes
- highlighted some code pieces so the articles are easier to read

Bogdan Poplauschi 11 lat temu
rodzic
commit
a06650da84

+ 1 - 1
Documentation/ARC.md

@@ -1,4 +1,4 @@
-[Automatic Reference Counting](http://clang.llvm.org/docs/AutomaticReferenceCounting.html) (ARC) is an amazing new technology. It makes life easier for developers and speeds up your code at the same time. However, since it's such a radical change, it requires some new tools (Xcode 4.4+, Apple LLVM 3.0+ compiler) and some code changes (remove retain/release/autorelease, etc). This leaves library developers in a tough position: To ARC, or not to ARC? If the library is converted to ARC, those who haven't converted their apps will complain. If the library isn't converted to ARC, those who have converted their apps will complain! What to do?
+[Automatic Reference Counting](http://clang.llvm.org/docs/AutomaticReferenceCounting.html) (ARC) is an amazing new technology. It makes life easier for developers and speeds up your code at the same time. However, since it's such a radical change, it requires some new tools (Xcode 4.4+, Apple LLVM 3.0+ compiler) and some code changes (remove `retain`/`release`/`autorelease`, etc). This leaves library developers in a tough position: To ARC, or not to ARC? If the library is converted to ARC, those who haven't converted their apps will complain. If the library isn't converted to ARC, those who have converted their apps will complain! What to do?
 
 One possibility is to maintain 2 branches: arc & non-arc. These would have to be kept in sync for every new commit and every push. Obviously this is a large burden. And library developers, especially those who actively develop and improve their libraries, don't consider this a solution. So ultimately, a decision must be made.
 

+ 11 - 15
Documentation/Architecture.md

@@ -4,33 +4,29 @@ Architecture of the lumberjack framework.
 
 If you're familiar with other logging frameworks (such as the popular [log4j](http://logging.apache.org/log4j/1.2/index.html)) then you'll quickly recognize the concepts. If logging is new to you, that's OK because lumberjack was designed to be simple to use.
 
-If you haven't already done so, you may want to read the [[getting started | GettingStarted]] page.
+If you haven't already done so, you may want to read the [getting started](GettingStarted.md) page.
 
 ### Overview
 
-At the heart of the framework is the DDLog file. This file provides the various DDLog macros that will replace your NSLog statements. For example:<br/>
-`
-DDLogWarn(@"Specified file does not exist");
-`
+At the heart of the framework is the `DDLog` file. This file provides the various `DDLog` macros that will replace your `NSLog` statements. For example:<br/>
+``` DDLogWarn(@"Specified file does not exist"); ```
 
 During compilation these macros get expanded to something akin to:<br/>
-`
-if(LOG_WARN) /* Execute log statement */
-`
+``` if(LOG_WARN) /* Execute log statement */ ```
 
-What this means is that the compiler has the ability to automatically prune log statements that will never get executed. (For more information see the [[getting started | GettingStarted]] page. You may also choose to use [[dynamic log levels | DynamicLogLevels]].)
+What this means is that the compiler has the ability to automatically prune log statements that will never get executed. (For more information see the [getting started](GettingStarted.md) page. You may also choose to use [dynamic log levels](DynamicLogLevels.md).)
 
-When a log statement is executed, DDLog forwards the log message to every logger.
+When a log statement is executed, `DDLog` forwards the log message to every logger.
 
 ### Loggers
 
-A logger is a class that does something with a log message. The lumberjack framework comes with several different loggers. (You can also [[create your own | CustomLoggers]].) Loggers such as DDASLLogger and DDTTYLogger can be used to duplicate the functionality of NSLog. And DDFileLogger can be used to write log messages to a log file.
+A logger is a class that does something with a log message. The lumberjack framework comes with several different loggers. (You can also [create your own](CustomLoggers.md).) Loggers such as `DDASLLogger` and `DDTTYLogger` can be used to duplicate the functionality of `NSLog`. And `DDFileLogger` can be used to write log messages to a log file.
 
 You can have multiple simultaneous loggers. So you could, for example, log to the console and a file at the same time. You can add and remove loggers at any time.
 
-When your application first starts, the lumberjack framework has no loggers. So you'll want to add at least one logger if you want your log statements to go anywhere. (For information on how to add a logger, see the [[getting started | GettingStarted]] page.)
+When your application first starts, the lumberjack framework has no loggers. So you'll want to add at least one logger if you want your log statements to go anywhere. (For information on how to add a logger, see the [getting started](GettingStarted.md) page.)
 
-Loggers may have certain settings that you can configure. For example, the DDFileLogger has options for controlling how often to roll log files.
+Loggers may have certain settings that you can configure. For example, the `DDFileLogger` has options for controlling how often to roll log files.
 
 All loggers will also support an optional formatter.
 
@@ -38,10 +34,10 @@ All loggers will also support an optional formatter.
 
 Formatters allow you to format a log message before the logger logs it. For example, there is no need to add a timestamp to normal console log messages because the console automatically does that. However, if you are logging to a file, you would likely want to prepend a timestamp to the log message.
 
-So you could add a formatter to DDFileLogger to automatically prepend a timestamp to every log message.
+So you could add a formatter to `DDFileLogger` to automatically prepend a timestamp to every log message.
 
 Formatters can also be used to filter log messages.
 
 And remember that formatters are applied individually to loggers. So you can format and/or filter on a per-logger basis.
 
-[[Learn how to write your own custom formatters. | CustomFormatters]]
+[Learn how to write your own custom formatters](CustomFormatters.md)

+ 25 - 20
Documentation/CustomContext.md

@@ -6,11 +6,11 @@ Logging contexts allow you to define a particular context for a log message. Thi
 
 Contexts can be used in a wide variety of ways. Here are a few examples.
 
-Example 1:
+#### Example 1:
 
 Some applications are rather modular, and can easily be broken into several logical components. If each separate component of the application uses a different logging context, then it would be easy for the logging framework to detect which log messages are coming from which components. What you do with such information is entirely up to you. Perhaps you want to format them differently. Or perhaps you want to use a filter, such that only log messages from your widget component get saved to disk. The sky is the limit.
 
-Example 2:
+#### Example 2:
 
 You are developing a framework for other developers to use in their application. Being a forward-thinking engineer, you wish to include exemplary logging. This will allow others to quickly learn how your framework operates (less questions), as well as easily diagnose and debug any problems they might encounter (more free patches). So you use Lumberjack, and ensure that your log messages have a custom context. This will allow application developers to easily manage the log statements coming from your framework.
 
@@ -19,27 +19,32 @@ You are developing a framework for other developers to use in their application.
 Every log message that goes through the Lumberjack framework is turned into a DDLogMessage object. This object contains all kinds of juicy information:
 
 ```objective-c
-@interface DDLogMessage : NSObject
+@interface DDLogMessage : NSObject <NSCopying>
 {
-    int logLevel;
-    int logFlag;
-    int logContext;
-    NSString *logMsg;
-    NSDate *timestamp;
-    const char *file;
-    const char *function;
-    int lineNumber;
-    mach_port_t machThreadID;
-#if GCD_MAYBE_AVAILABLE
-    char *queueLabel;
-#endif
-    // ...
+    // Direct accessors to be used only for performance
+    ...
 }
+
+@property (readonly, nonatomic) NSString *message;
+@property (readonly, nonatomic) DDLogLevel level;
+@property (readonly, nonatomic) DDLogFlag flag;
+@property (readonly, nonatomic) NSInteger context;
+@property (readonly, nonatomic) NSString *file;
+@property (readonly, nonatomic) NSString *fileName;
+@property (readonly, nonatomic) NSString *function;
+@property (readonly, nonatomic) NSUInteger line;
+@property (readonly, nonatomic) id tag;
+@property (readonly, nonatomic) DDLogMessageOptions options;
+@property (readonly, nonatomic) NSDate *timestamp;
+@property (readonly, nonatomic) NSString *threadID; // ID as it appears in NSLog calculated from the machThreadID
+@property (readonly, nonatomic) NSString *threadName;
+@property (readonly, nonatomic) NSString *queueLabel;
+
 ```
 
-You can use all this information to customize the format of your log messages. For more information, see the [[Custom Formatters | CustomFormatters]] page.
+You can use all this information to customize the format of your log messages. For more information, see the [Custom Formatters](CustomFormatters.md) page.
 
-You'll also notice there is a "logContext" variable. Now, by default, the log context of every message is zero. However, this can easily be customized.
+You'll also notice there is a `context` method/ivar. Now, by default, the log context of every message is zero. However, this can easily be customized.
 
 Example 2 above mentioned using Lumberjack in third party frameworks. A great example of this is the [CocoaHTTPServer](https://github.com/robbiehanson/CocoaHTTPServer) project. This open-source library provides an embeddable and customizable HTTP server for Mac and iOS applications. Since the project is sizable, it includes extensive logging which enables its functionality to be very transparent for those using the project. Debugging a complex problem becomes a lot easier when you can crank up the log level and see exactly how HTTP requests are coming into the system and being processed.
 
@@ -51,11 +56,11 @@ The HTTP server project then defines its own log messages, using a custom contex
 #define HTTPLogError(frmt, ...)     SYNC_LOG_OBJC_MAYBE(httpLogLevel, LOG_FLAG_ERROR,   HTTP_LOG_CONTEXT, frmt, ##__VA_ARGS__)
 #define HTTPLogWarn(frmt, ...)     ASYNC_LOG_OBJC_MAYBE(httpLogLevel, LOG_FLAG_WARN,    HTTP_LOG_CONTEXT, frmt, ##__VA_ARGS__)
 #define HTTPLogInfo(frmt, ...)     ASYNC_LOG_OBJC_MAYBE(httpLogLevel, LOG_FLAG_INFO,    HTTP_LOG_CONTEXT, frmt, ##__VA_ARGS__)
-#define HTTPLogDebug(frmt, ...)     ASYNC_LOG_OBJC_MAYBE(httpLogLevel, LOG_FLAG_DEBUG,  HTTP_LOG_CONTEXT, frmt, ##__VA_ARGS__)
+#define HTTPLogDebug(frmt, ...)    ASYNC_LOG_OBJC_MAYBE(httpLogLevel, LOG_FLAG_DEBUG,   HTTP_LOG_CONTEXT, frmt, ##__VA_ARGS__)
 #define HTTPLogVerbose(frmt, ...)  ASYNC_LOG_OBJC_MAYBE(httpLogLevel, LOG_FLAG_VERBOSE, HTTP_LOG_CONTEXT, frmt, ##__VA_ARGS__)
 ```
 
-*You may notice how easy it is to define your own custom log functions. For more information see the [[Custom Log Levels | CustomLogLevels]] page. If you want to get really advanced, see the [[Fine Grained Logging | FineGrainedLogging]] page.*
+*You may notice how easy it is to define your own custom log functions. For more information see the [Custom Log Levels](CustomLogLevels.md) page. If you want to get really advanced, see the [Fine Grained Logging](FineGrainedLogging.md) page.*
 
 Now HTTP log messages are clearly identifiable in the code:
 

+ 71 - 79
Documentation/CustomFormatters.md

@@ -10,7 +10,7 @@ And remember that **formatters are applied individually to loggers**. So you can
 
 # Details
 
-It is incredibly simple to create your own custom formatter. The protocol for DDLogFormatter is defined in DDLog.h, and there is only a single required method:
+It is incredibly simple to create your own custom formatter. The protocol for `DDLogFormatter` is defined in `DDLog.h`, and there is only a single required method:
 ```objective-c
 @protocol DDLogFormatter <NSObject>
 @required
@@ -19,26 +19,32 @@ It is incredibly simple to create your own custom formatter. The protocol for DD
  * Formatters may optionally be added to any logger.
  * This allows for increased flexibility in the logging environment.
  * For example, log messages for log files may be formatted differently than log messages for the console.
- * 
- * The formatter may also optionally filter the log message by returning nil.
-**/
+ *
+ * For more information about formatters, see the "Custom Formatters" page:
+ * Documentation/CustomFormatters.md
+ *
+ * The formatter may also optionally filter the log message by returning nil,
+ * in which case the logger will not log the message.
+ **/
 - (NSString *)formatLogMessage:(DDLogMessage *)logMessage;
 
+@optional
 // ...
 @end
 ```
 
-It's pretty straight-forward. The single method takes, as a parameter, an instance of DDLogMessage which contains all the information related to the log message including:
+It's pretty straight-forward. The single method takes, as a parameter, an instance of `DDLogMessage` which contains all the information related to the log message including:
 
--   LogMsg - original log message
--   File - name of the file the log message came from
--   Function - method the log message came from
--   LineNumber - line number in file where the log message came from
--   Timestamp - when the log message was executed
--   LogLevel - log level of message (bitmask of flags, e.g. 0111)
--   LogFlag - log flag of message (individual flag that allowed log message to fire, e.g. 0010)
--   ThreadID - which thread issued the log message
--   QueueLabel - name of gcd queue (if applicable)
+-  `message` - original log message
+-  `file` - full path to the file the log message came from
+-  `filename` - name of the file the log message came from (without extension)
+-  `function` - method the log message came from
+-  `line` - line number in file where the log message came from
+-  `timestamp` - when the log message was executed
+-  `level` - log level of message (bitmask of flags, e.g. 0111)
+-  `flag` - log flag of message (individual flag that allowed log message to fire, e.g. 0010)
+-  `threadID` - which thread issued the log message
+-  `queueLabel` - name of gcd queue (if applicable)
 
 Let's write a simple formatter that automatically simply prepends the log level before every log message.  
 
@@ -68,19 +74,17 @@ MyCustomFormatter.m
 
 @implementation MyCustomFormatter
 
-- (NSString *)formatLogMessage:(DDLogMessage *)logMessage
-{
+- (NSString *)formatLogMessage:(DDLogMessage *)logMessage {
     NSString *logLevel;
-    switch (logMessage->logFlag)
-    {
-        case LOG_FLAG_ERROR : logLevel = @"E"; break;
-        case LOG_FLAG_WARN  : logLevel = @"W"; break;
-        case LOG_FLAG_INFO  : logLevel = @"I"; break;
-        case LOG_FLAG_DEBUG : logLevel = @"D"; break;
+    switch (logMessage.flag) {
+        case DDLogFlagError : logLevel = @"E"; break;
+        case DDLogFlagWarn  : logLevel = @"W"; break;
+        case DDLogFlagInfo  : logLevel = @"I"; break;
+        case DDLogFlagDebug : logLevel = @"D"; break;
         default             : logLevel = @"V"; break;
     }
     
-    return [NSString stringWithFormat:@"%@ | %@\n", logLevel, logMessage->logMsg];
+    return [NSString stringWithFormat:@"%@ | %@\n", logLevel, logMessage.message];
 }
 
 @end
@@ -88,7 +92,7 @@ MyCustomFormatter.m
 
 # Thread-safety (simple)
 
-Let's update our example formatter to also include the timestamp. To do this we'll use NSDateFormatter. But... NSDateFormatter is NOT thread-safe. Does this pose any problems for us?
+Let's update our example formatter to also include the timestamp. To do this we'll use `NSDateFormatter`. But... `NSDateFormatter` is NOT thread-safe. Does this pose any problems for us?
 
 Log formatters are applied individually to loggers. If you instantiate a log formatter instance, **and apply it to a single logger**, then you don't have to worry about thread-safety. All log messages are sent to the logger (and thus to its log formatter) via the serial dispatch queue of the logger. Thus, in this scenario, the formatLogMessage method is guaranteed to run on only a single thread at a time.
 
@@ -102,9 +106,13 @@ It is very often the case that developers write custom formatters specifically f
  * Formatters may optionally be added to any logger.
  * This allows for increased flexibility in the logging environment.
  * For example, log messages for log files may be formatted differently than log messages for the console.
- * 
- * The formatter may also optionally filter the log message by returning nil.
-**/
+ *
+ * For more information about formatters, see the "Custom Formatters" page:
+ * Documentation/CustomFormatters.md
+ *
+ * The formatter may also optionally filter the log message by returning nil,
+ * in which case the logger will not log the message.
+ **/
 - (NSString *)formatLogMessage:(DDLogMessage *)logMessage;
 
 @optional
@@ -117,9 +125,10 @@ It is very often the case that developers write custom formatters specifically f
  * If a formatter is explicitly not thread-safe, it may wish to throw an exception if added to multiple loggers.
  * Or if a formatter has potentially thread-unsafe code (e.g. NSDateFormatter),
  * it could possibly use these hooks to switch to thread-safe versions of the code.
-**/
+ **/
 - (void)didAddToLogger:(id <DDLogger>)logger;
 - (void)willRemoveFromLogger:(id <DDLogger>)logger;
+
 @end
 ```
 
@@ -140,8 +149,7 @@ MyCustomFormatter.h
 #import <Foundation/Foundation.h>
 #import "DDLog.h"
 
-@interface MyCustomFormatter : NSObject <DDLogFormatter>
-{
+@interface MyCustomFormatter : NSObject <DDLogFormatter> {
     int loggerCount;
     NSDateFormatter *threadUnsafeDateFormatter;
 }
@@ -154,41 +162,36 @@ MyCustomFormatter.m
 
 @implementation MyCustomFormatter
 
-- (id)init
-{
-    if((self = [super init]))
-    {
+- (id)init {
+    if((self = [super init])) {
         threadUnsafeDateFormatter = [[NSDateFormatter alloc] init];
         [threadUnsafeDateFormatter setDateFormat:@"yyyy/MM/dd HH:mm:ss:SSS"];
     }
     return self;
 }
 
-- (NSString *)formatLogMessage:(DDLogMessage *)logMessage
-{
+- (NSString *)formatLogMessage:(DDLogMessage *)logMessage {
     NSString *logLevel;
-    switch (logMessage->logFlag)
-    {
-        case LOG_FLAG_ERROR : logLevel = @"E"; break;
-        case LOG_FLAG_WARN  : logLevel = @"W"; break;
-        case LOG_FLAG_INFO  : logLevel = @"I"; break;
-        case LOG_FLAG_DEBUG : logLevel = @"D"; break;
+    switch (logMessage.flag) {
+        case DDLogFlagError : logLevel = @"E"; break;
+        case DDLogFlagWarn  : logLevel = @"W"; break;
+        case DDLogFlagInfo  : logLevel = @"I"; break;
+        case DDLogFlagDebug : logLevel = @"D"; break;
         default             : logLevel = @"V"; break;
     }
-    
-    NSString *dateAndTime = [threadUnsafeDateFormatter stringFromDate:(logMessage->timestamp)];
-    NSString *logMsg = logMessage->logMsg;
+
+    NSString *dateAndTime = [threadUnsafeDateFormatter stringFromDate:(logMessage.timestamp)];
+    NSString *logMsg = logMessage.message;
     
     return [NSString stringWithFormat:@"%@ %@ | %@\n", logLevel, dateAndTime, logMsg];
 }
 
-- (void)didAddToLogger:(id <DDLogger>)logger
-{
+- (void)didAddToLogger:(id <DDLogger>)logger {
     loggerCount++;
     NSAssert(loggerCount <= 1, @"This logger isn't thread-safe");
 }
-- (void)willRemoveFromLogger:(id <DDLogger>)logger
-{
+
+- (void)willRemoveFromLogger:(id <DDLogger>)logger {
     loggerCount--;
 }
 
@@ -205,8 +208,7 @@ However, it's typically not that difficult to support multi-threading. The most
 NSMutableDictionary *threadDictionary = [[NSThread currentThread] threadDictionary];
 NSDateFormatter *dateFormatter = [threadDictionary objectForKey:key];
 
-if (dateFormatter == nil)
-{
+if (dateFormatter == nil) {
     dateFormatter = [[NSDateFormatter alloc] init];
     [dateFormatter setDateFormat:dateFormatString];
     
@@ -221,8 +223,7 @@ MyCustomFormatter.h
 #import <Foundation/Foundation.h>
 #import "DDLog.h"
 
-@interface MyCustomFormatter : NSObject <DDLogFormatter>
-{
+@interface MyCustomFormatter : NSObject <DDLogFormatter> {
     int atomicLoggerCount;
     NSDateFormatter *threadUnsafeDateFormatter;
 }
@@ -236,24 +237,19 @@ MyCustomFormatter.m
 
 @implementation MyCustomFormatter
 
-- (NSString *)stringFromDate:(NSDate *)date
-{
+- (NSString *)stringFromDate:(NSDate *)date {
     int32_t loggerCount = OSAtomicAdd32(0, &atomicLoggerCount);
     
-    if (loggerCount <= 1)
-    {
+    if (loggerCount <= 1) {
         // Single-threaded mode.
         
-        if (threadUnsafeDateFormatter == nil)
-        {
+        if (threadUnsafeDateFormatter == nil) {
             threadUnsafeDateFormatter = [[NSDateFormatter alloc] init];
             [threadUnsafeDateFormatter setDateFormat:dateFormatString];
         }
         
         return [threadUnsafeDateFormatter stringFromDate:date];
-    }
-    else
-    {
+    } else {
         // Multi-threaded mode.
         // NSDateFormatter is NOT thread-safe.
         
@@ -262,8 +258,7 @@ MyCustomFormatter.m
         NSMutableDictionary *threadDictionary = [[NSThread currentThread] threadDictionary];
         NSDateFormatter *dateFormatter = [threadDictionary objectForKey:key];
         
-        if (dateFormatter == nil)
-        {
+        if (dateFormatter == nil) {
             dateFormatter = [[NSDateFormatter alloc] init];
             [dateFormatter setDateFormat:dateFormatString];
             
@@ -274,30 +269,27 @@ MyCustomFormatter.m
     }
 }
 
-- (NSString *)formatLogMessage:(DDLogMessage *)logMessage
-{
+- (NSString *)formatLogMessage:(DDLogMessage *)logMessage {
     NSString *logLevel;
-    switch (logMessage->logFlag)
-    {
-        case LOG_FLAG_ERROR : logLevel = @"E"; break;
-        case LOG_FLAG_WARN  : logLevel = @"W"; break;
-        case LOG_FLAG_INFO  : logLevel = @"I"; break;
-        case LOG_FLAG_DEBUG : logLevel = @"D"; break;
+    switch (logMessage.flag) {
+        case DDLogFlagError : logLevel = @"E"; break;
+        case DDLogFlagWarn  : logLevel = @"W"; break;
+        case DDLogFlagInfo  : logLevel = @"I"; break;
+        case DDLogFlagDebug : logLevel = @"D"; break;
         default             : logLevel = @"V"; break;
     }
-    
-    NSString *dateAndTime = [self stringFromDate:(logMessage->timestamp)];
-    NSString *logMsg = logMessage->logMsg;
+
+    NSString *dateAndTime = [self stringFromDate:(logMessage.timestamp)];
+    NSString *logMsg = logMessage.message;
     
     return [NSString stringWithFormat:@"%@ %@ | %@\n", logLevel, dateAndTime, logMsg];
 }
 
-- (void)didAddToLogger:(id <DDLogger>)logger
-{
+- (void)didAddToLogger:(id <DDLogger>)logger {
     OSAtomicIncrement32(&atomicLoggerCount);
 }
-- (void)willRemoveFromLogger:(id <DDLogger>)logger
-{
+
+- (void)willRemoveFromLogger:(id <DDLogger>)logger {
     OSAtomicDecrement32(&atomicLoggerCount);
 }
 

+ 7 - 7
Documentation/CustomLogLevels.md

@@ -4,11 +4,11 @@ How to add or customise log levels
 
 By default, Lumberjack comes with 5 pre-defined log levels:
 
--   Error
--   Warn
--   Info
--   Debug
--   Verbose
+- Error
+- Warn
+- Info
+- Debug
+- Verbose
 
 The small number of levels helps those who are new to logging frameworks. (When there are 16 different log levels, it can be become difficult to choose...)
 
@@ -18,7 +18,7 @@ You're in luck because **you can customise the log levels however you want**! In
 
 ### Details
 
-The log levels are all defined in DDLog.h. All you have to do is create your own header (e.g. MYLog.h). Your project files will then import MYLog.h instead of DDLog.h.
+The log levels are all defined in `DDLog.h`. All you have to do is create your own header (e.g. `MYLog.h`). Your project files will then import `MYLog.h` instead of `DDLog.h`.
 
 Within MYLog.h you simply undefine the pre-defined stuff, and then set everything up however you want.
 
@@ -26,7 +26,7 @@ There is a sample Xcode project that comes with Lumberjack that does exactly thi
 
 > **Warning**  
 Some internal methods, such as `addLogger:`, ignore custom log levels/flags.  
-To avoid unexpected behaviors use more specific methods such as `addLogger:withLogLevel:`.
+To avoid unexpected behaviors use more specific methods such as `addLogger:withLevel:`.
 
 MYLog.h:
 ```objective-c

+ 64 - 61
Documentation/CustomLoggers.md

@@ -2,46 +2,71 @@ How to write your own custom loggers.
 
 ### Introduction
 
-Loggers allow you to direct log messages wherever you want. For general information about loggers, see the [[architecture | Architecture]] page. The best part is that it's relatively easy to write your own custom loggers.
+Loggers allow you to direct log messages wherever you want. For general information about loggers, see the [architecture](Architecture.md) page. The best part is that it's relatively easy to write your own custom loggers.
 
-The DDLog header file defines the DDLogger protocol. It consists of only 3 mandatory methods:
+The `DDLog` header file defines the `DDLogger` protocol. It consists of only 3 mandatory methods:
 
 ```objective-c
 @protocol DDLogger <NSObject>
-@required
 
 - (void)logMessage:(DDLogMessage *)logMessage;
 
 /**
  * Formatters may optionally be added to any logger.
- * If no formatter is set, the logger simply logs the message as it is given in logMessage.
- * Or it may use its own built in formatting style.
-**/
-- (id <DDLogFormatter>)logFormatter;
-- (void)setLogFormatter:(id <DDLogFormatter>)formatter;
+ *
+ * If no formatter is set, the logger simply logs the message as it is given in logMessage,
+ * or it may use its own built in formatting style.
+ **/
+@property (nonatomic, strong) id <DDLogFormatter> logFormatter;
 
 @optional
 
 /**
  * Since logging is asynchronous, adding and removing loggers is also asynchronous.
  * In other words, the loggers are added and removed at appropriate times with regards to log messages.
- * 
+ *
  * - Loggers will not receive log messages that were executed prior to when they were added.
  * - Loggers will not receive log messages that were executed after they were removed.
- * 
- * These methods are executed in the logging thread.
- * This is the same thread that will execute every logMessage: invocation.
- * Loggers may use these methods for proper thread synchronization or any other setup.
-**/
-
+ *
+ * These methods are executed in the logging thread/queue.
+ * This is the same thread/queue that will execute every logMessage: invocation.
+ * Loggers may use these methods for thread synchronization or other setup/teardown tasks.
+ **/
 - (void)didAddLogger;
 - (void)willRemoveLogger;
 
+/**
+ * Some loggers may buffer IO for optimization purposes.
+ * For example, a database logger may only save occasionaly as the disk IO is slow.
+ * In such loggers, this method should be implemented to flush any pending IO.
+ *
+ * This allows invocations of DDLog's flushLog method to be propogated to loggers that need it.
+ *
+ * Note that DDLog's flushLog method is invoked automatically when the application quits,
+ * and it may be also invoked manually by the developer prior to application crashes, or other such reasons.
+ **/
+- (void)flush;
+
+/**
+ * Each logger is executed concurrently with respect to the other loggers.
+ * Thus, a dedicated dispatch queue is used for each logger.
+ * Logger implementations may optionally choose to provide their own dispatch queue.
+ **/
+@property (nonatomic, DISPATCH_QUEUE_REFERENCE_TYPE, readonly) dispatch_queue_t loggerQueue;
+
+/**
+ * If the logger implementation does not choose to provide its own queue,
+ * one will automatically be created for it.
+ * The created queue will receive its name from this method.
+ * This may be helpful for debugging or profiling reasons.
+ **/
+@property (nonatomic, readonly) NSString *loggerName;
+
 @end
 ```
 <br/>
 <br/>
-Furthermore, **there is a base logger implementation one can extend** (DDAbstractLogger) that will automatically implement 2 of the 3 mandatory methods (logFormatter & setLogFormatter). So implementing a logger can be pretty straight-forward.
+Furthermore, **there is a base logger implementation one can extend** (`DDAbstractLogger`) that will automatically implement 2 of the 3 mandatory methods (`logFormatter` & `setLogFormatter:`). So implementing a logger can be pretty straight-forward.
 
 ### Skeleton Implementation
 
@@ -64,15 +89,13 @@ MyCustomLogger.m
 
 @implementation MyCustomLogger
 
-- (void)logMessage:(DDLogMessage *)logMessage
-{
-    NSString *logMsg = logMessage->logMsg;
+- (void)logMessage:(DDLogMessage *)logMessage {
+    NSString *logMsg = logMessage.message;
 
-    if (self->formatter)
-        logMsg = [self->formatter formatLogMessage:logMessage];
+    if (self->logFormatter)
+        logMsg = [self->logFormatter formatLogMessage:logMessage];
 
-    if (logMsg)
-    {
+    if (logMsg) {
         // Write logMsg to wherever...
     }
 }
@@ -91,47 +114,27 @@ However, you are obviously free to do whatever you want. If it doesn't make sens
 The DDLogMessage object encapsulates the information about a log message. It is also defined in DDLog.h:
 
 ```objective-c
-@interface DDLogMessage : NSObject
+@interface DDLogMessage : NSObject <NSCopying>
 {
-
-// The public variables below can be accessed directly (for speed).
-// For example: logMessage->logLevel
-	
-@public
-    int logLevel;
-    int logFlag;
-    int logContext;
-    NSString *logMsg;
-    NSDate *timestamp;
-    const char *file;
-    const char *function;
-    int lineNumber;
-    mach_port_t machThreadID;
-#if GCD_MAYBE_AVAILABLE
-    char *queueLabel;
-#endif
-
-    // ...
+    // Direct accessors to be used only for performance
+    ...
 }
 
-/**
- * Returns the threadID as it appears in NSLog.
- * That is, it is a hexadecimal value which is calculated from the machThreadID.
-**/
-- (NSString *)threadID;
-
-/**
- * Convenience method to get just the file name, as the file variable is generally the full file path.
- * This method does not include the file extension, which is generally unwanted for logging purposes.
-**/
-- (NSString *)fileName;
+@property (readonly, nonatomic) NSString *message;
+@property (readonly, nonatomic) DDLogLevel level;
+@property (readonly, nonatomic) DDLogFlag flag;
+@property (readonly, nonatomic) NSInteger context;
+@property (readonly, nonatomic) NSString *file;
+@property (readonly, nonatomic) NSString *fileName;
+@property (readonly, nonatomic) NSString *function;
+@property (readonly, nonatomic) NSUInteger line;
+@property (readonly, nonatomic) id tag;
+@property (readonly, nonatomic) DDLogMessageOptions options;
+@property (readonly, nonatomic) NSDate *timestamp;
+@property (readonly, nonatomic) NSString *threadID; // ID as it appears in NSLog calculated from the machThreadID
+@property (readonly, nonatomic) NSString *threadName;
+@property (readonly, nonatomic) NSString *queueLabel;
 
-/**
- * Returns the function variable in NSString form.
-**/
-- (NSString *)methodName;
-
-@end
 ```
 
 ### Threading
@@ -146,6 +149,6 @@ Almost all of the multi-threading issues are solved for you. The following 3 met
 
 Using these 3 methods you can setup resources, perform logging, and teardown resources without worrying about multi-threaded complications.
 
-Furthermore, the DDAbstractLogger provides thread-safe implementations of setLogFormatter and (get)logFormatter. And it does so in such a way that allows you to access the logFormatter variable directly from within your logMessage method! (Performance win!)
+Furthermore, the `DDAbstractLogger` provides thread-safe implementations of `setLogFormatter:` and `logFormatter`. And it does so in such a way that allows you to access the logFormatter variable directly from within your logMessage method! (Performance win!)
 
 However, if your custom logger has custom configuration variables, you may need to make them atomic and/or thread-safe.

+ 17 - 21
Documentation/DynamicLogLevels.md

@@ -4,33 +4,31 @@ Dynamically changing log levels during run-time
 
 When you define your log level, you generally define it in a manner similar to this:
 ```objective-c
-static const int ddLogLevel = LOG_LEVEL_WARN;
+static const DDLogLevel ddLogLevel = DDLogLevelWarn;
 ```
 
 What this means is that your log level is declared as a constant. It cannot be changed.\
 
-This has the advantage that the compiler can automatically prune DDLog statements above the log level threshold during compilation.  However, it also has the disadvantage that you cannot change your log level during run-time.
+This has the advantage that the compiler can automatically prune `DDLog` statements above the log level threshold during compilation.  However, it also has the disadvantage that you cannot change your log level during run-time.
 
 To allow a dynamic log level, all we need to do is remove the "const" part:
 ```objective-c
-static int ddLogLevel = LOG_LEVEL_WARN;
+static DDLogLevel ddLogLevel = DDLogLevelWarn;
 ```
 
 This means that we can change the log level when/how we want. For example, maybe we're debugging some specific part of our application.
 ```objective-c
-- (void)startTask
-{
-    ddLogLevel = LOG_LEVEL_VERBOSE;
+- (void)startTask {
+    ddLogLevel = DDLogLevelVerbose;
     [self startTaskInBackground];
 }
 
-- (void)taskDidFinish
-{
-    ddLogLevel = LOG_LEVEL_WARN;
+- (void)taskDidFinish {
+    ddLogLevel = DDLogLevelWarn;
 }
 ```
 
-You will incur a tiny little performance penalty for using dynamic log levels. (A single integer comparison... gasp!) However, due to the architecture and speed of the lumberjack framework, most DDLog statements will **still be faster than NSLog**. (For more information, see the [[performance | Performance]] page.)
+You will incur a tiny little performance penalty for using dynamic log levels. (A single integer comparison... gasp!) However, due to the architecture and speed of the lumberjack framework, most DDLog statements will **still be faster than NSLog**. (For more information, see the [performance](Performance.md) page.)
 
 ### Crazy Awesomeness
 
@@ -38,7 +36,7 @@ Dynamic logging, as used in the example above, can be helpful for debugging.\
 
 **But what if we wanted to take it to the next level?**
 
-Imagine if you could alter log levels via the NSUserDefaults system...\
+Imagine if you could alter log levels via the `NSUserDefaults` system...\
 
 A user is complaining about the application not acting properly (in the preference pane somewhere). So you simply tell them to issue a
 ```objective-c
@@ -47,13 +45,13 @@ defaults write com.yourapp.prefsLogLevel 4
 
 And in your preference pane code, you have something like this:
 ```objective-c
-static int ddLogLevel = LOG_LEVEL_WARN;
+static DDLogLevel ddLogLevel = DDLogLevelWarn;
 
-+ (void)initialize
-{
++ (void)initialize {
     NSNumber *logLevel = [[NSUserDefaults standardUserDefaults] objectForKey:@"prefsLogLevel"];
-    if (logLevel)
-        ddLogLevel = [logLevel intValue];
+    if (logLevel) {
+        ddLogLevel = (DDLogLevel)[logLevel intValue];
+    }
 }
 ```
 
@@ -77,17 +75,15 @@ The lumberjack framework has something called "registered dynamic logging". Here
 #import "Sprocket.h"
 #import "DDLog.h"
 
-static int ddLogLevel = LOG_LEVEL_WARN;
+static DDLogLevel ddLogLevel = DDLogLevelWarn;
 
 @implementation Sprocket
 
-+ (int)ddLogLevel
-{
++ (DDLogLevel)ddLogLevel {
     return ddLogLevel;
 }
 
-+ (void)ddSetLogLevel:(int)logLevel
-{
++ (void)ddSetLogLevel:(DDLogLevel)logLevel {
     ddLogLevel = logLevel;
 }
 

+ 4 - 4
Documentation/FineGrainedLogging.md

@@ -4,11 +4,11 @@ When you need something more advanced than simple log levels.
 
 Most of us are familiar with log levels. They are simple to understand, and they're used in almost every logging framework. However, there are times when something more advanced is desired. Something more fine grained.
 
-Example \#1:
+#### Example \#1:
 
 You have a large source code file that you are debugging. The code is logically separated into 7 different sub-components. One of these sub-components is having issues. So you'd like to enable some extra logging, but you don't want to see all the log statements from the other 6 sub-components. That would be too much junk to filter through. Wouldn't it be nice if your logging framework was tailored to fit the logical separations in your code?
 
-Example \#2:
+#### Example \#2:
 
 You're adding a new feature to your application. The implementation of this feature spans across several different files. Something isn't quite working right and you'd like to enable some extra logging, but you only want to see log statements related to this new feature. The problem is, there are a bunch of other log statements in these files. You don't want to remove them. You just want a little bit extra fine-grained control.
 
@@ -16,7 +16,7 @@ Not a problem. Lumberjack can help!
 
 ### Details
 
-If you look closely at the definitions in the DDLog header file, you'll notice something interesting:
+If you look closely at the definitions in the `DDLogLegacyMacros` header file, you'll notice something interesting:
 ```objective-c
 #define LOG_FLAG_ERROR    (1 << 0)  // 0...00001
 #define LOG_FLAG_WARN     (1 << 1)  // 0...00010
@@ -97,4 +97,4 @@ For example, let's say you wanted to have 30 fine-grained log options. No proble
 
 All we had to do was use a new variable - ddLogLevel2.
 
-You should also note that you aren't restricted to the 4 pre-defined log levels. You can define them however you want. Learn more in the [[Custom Log Levels | CustomLogLevels]] page.
+You should also note that you aren't restricted to the 4 pre-defined log levels. You can define them however you want. Learn more in the [Custom Log Levels](CustomLogLevels.md) page.

+ 6 - 6
Documentation/GettingStarted.md

@@ -89,12 +89,12 @@ Which log level you choose per NSLog statement depends, of course, on the severi
 
 These tie into the log level just as you would expect
 
--   If you set the log level to LOG\_LEVEL\_ERROR, then you will only see DDLogError statements.
--   If you set the log level to LOG\_LEVEL\_WARN, then you will only see DDLogError and DDLogWarn statements.
--   If you set the log level to LOG\_LEVEL\_INFO, you'll see Error, Warn and Info statements.
--   If you set the log level to LOG\_LEVEL\_DEBUG, you'll see Error, Warn, Info and Debug statements.
--   If you set the log level to LOG\_LEVEL\_VERBOSE, you'll see all DDLog statements.
--   If you set the log level to LOG\_LEVEL\_OFF, you won't see any DDLog statements.
+-   If you set the log level to DDLogLevelError, then you will only see Error statements.
+-   If you set the log level to DDLogLevelWarn, then you will only see Error and Warn statements.
+-   If you set the log level to DDLogLevelInfo, you'll see Error, Warn and Info statements.
+-   If you set the log level to DDLogLevelDebug, you'll see Error, Warn, Info and Debug statements.
+-   If you set the log level to DDLogLevelVerbose, you'll see all DDLog statements.
+-   If you set the log level to DDLogLevelOff, you won't see any DDLog statements.
 
 Where do I set the log level? Do I have to use a single log level for my entire project?
 

+ 7 - 7
Documentation/LogFileManagement.md

@@ -4,21 +4,21 @@ Compress your log files, or upload them to a server.
 
 When you think about it, there are two components of file logging. One component is the part that actually writes the log messages to the file, and decides when the file needs to be rolled. And the other component is the part that actually manages the log files. This is the part that actually does something with the log files once they're completed. Maybe it compresses them to save disk space. Maybe it uploads them to a server. Maybe both!
 
-The DDFileLogger implementation, as you may now have guessed, is split into two components. DDFileLogger is the component that writes the log messages to the file. And DDLogFileManager is a protocol for managing log files, and deciding what to do with them after they've been rolled.
+The `DDFileLogger` implementation, as you may now have guessed, is split into two components. `DDFileLogger` is the component that writes the log messages to the file. And `DDLogFileManager` is a protocol for managing log files, and deciding what to do with them after they've been rolled.
 
-There are two ways to initialize a DDFileLogger instance:
+There are two ways to initialize a `DDFileLogger` instance:
 ```objective-c
 @interface DDFileLogger : NSObject <DDLogger>
 ...
 
-- (id)init;
-- (id)initWithLogFileManager:(id <DDLogFileManager>)logFileManager;
+- (instancetype)init;
+- (instancetype)initWithLogFileManager:(id <DDLogFileManager>)logFileManager NS_DESIGNATED_INITIALIZER;
 
 ...
 @end
 ```
 
-The default init method simply uses an instance of DDLogFileManagerDefault, which is a class that simply deletes old log files. (It keeps a configurable number around, but any past that amount are simply deleted.)
+The default init method simply uses an instance of `DDLogFileManagerDefault`, which is a class that simply deletes old log files. (It keeps a configurable number around, but any past that amount are simply deleted.)
 
 The alternative init method allows you to pass an instance of your own custom log file manager.
 
@@ -59,8 +59,8 @@ Let's take a look at the DDLogFileManager protocol:
 @end
 ```
 
-There are methods to get the logs directory, and various methods to get the list of log files. Then there is a method to create a new log file (that returns the new log file path). And lastly, there are hooks from DDFileLogger to be notified of when a log file is rolled.
+There are methods to get the logs directory, and various methods to get the list of log files. Then there is a method to create a new log file (that returns the new log file path). And lastly, there are hooks from `DDFileLogger` to be notified of when a log file is rolled.
 
 The hooks are designed to allow you do something with those archived log files!
 
-The framework comes with a sample Xcode project that demonstrates compressing archived log files to save disk space. (It performs the compression using gzip.) The Xcode project name is "LogFileCompressor". The "CompressingLogFileManager" class is ready to be used in your project, or you can use it as a template, or simply learn from it so you can do your own custom log file management.
+The framework comes with a sample Xcode project that demonstrates compressing archived log files to save disk space. (It performs the compression using gzip.) The Xcode project name is `LogFileCompressor`. The `CompressingLogFileManager` class is ready to be used in your project, or you can use it as a template, or simply learn from it so you can do your own custom log file management.

+ 4 - 4
Documentation/PerLoggerLogLevels.md

@@ -1,10 +1,10 @@
 ### Use Log Level per Logger
 
-If you need a different log level for every logger (i.e. if you have a custom logger like Crashlytics logger that should not log Info or Debug info), you can easily achieve this using the `DDLog` `+addLogger:withLogLevel:` method.
+If you need a different log level for every logger (i.e. if you have a custom logger like Crashlytics logger that should not log Info or Debug info), you can easily achieve this using the `[DDLog addLogger:withLevel:]` method.
 
 ```objective-c
-[DDLog addLogger:[DDASLLogger sharedInstance] withLogLevel:LOG_LEVEL_INFO];
-[DDLog addLogger:[DDTTYLogger sharedInstance] withLogLevel:LOG_LEVEL_DEBUG];
+[DDLog addLogger:[DDASLLogger sharedInstance] withLevel:DDLogLevelInfo];
+[DDLog addLogger:[DDTTYLogger sharedInstance] withLevel:DDLogLevelDebug];
 ```
 
-You can still use the old method `+addLogger:`, this one uses the LOG_LEVEL_VERBOSE as default, so no log is excluded.
+You can still use the old method `+addLogger:`, this one uses the `DDLogLevelVerbose` as default, so no log is excluded.

+ 10 - 10
Documentation/PerUserLogLevels.md

@@ -7,32 +7,32 @@ A better solution is using **per-user** log levels:
 ```objective-c
 // Log levels: off, error, warn, info, verbose
 #if defined(DEBUG) && defined(robbie_hanson)
-  static const int ddLogLevel = LOG_LEVEL_VERBOSE; // Log level for robbie (debug)
+  static const DDLogLevel ddLogLevel = DDLogLevelVerbose; // Log level for robbie (debug)
 #elif defined(DEBUG)
-  static const int ddLogLevel = LOG_LEVEL_INFO;    // Log level for other team members (debug)
+  static const DDLogLevel ddLogLevel = DDLogLevelInfo;    // Log level for other team members (debug)
 #else
-  static const int ddLogLevel = LOG_LEVEL_WARN;    // Log level for release build
+  static const DDLogLevel ddLogLevel = DDLogLevelWarn;    // Log level for release build
 #endif
 ```
 
-(Different log levels per debug / release builds are explained in [[Xcode Tricks | XcodeTricks]])
+(Different log levels per debug / release builds are explained in [Xcode Tricks](XcodeTricks.md))
 
 This way, the developer who's currently working on the file can have their own log level. And everyone else just gets the normal log level. The trick is defining that full_username preprocessor macro.
 
-An example of how to do this is included in the repository under the Xcode/PerUserLogLevels project. Which I'll explain here.
+An example of how to do this is included in the repository under the `Xcode/PerUserLogLevels` project. Which I'll explain here.
 
-The first step is adding a new header file to your project. We'll call it "LumberjackUser.h". You can leave the file completely empty. But when it's all said and done, the file will end up looking like this:
+The first step is adding a new header file to your project. We'll call it `LumberjackUser.h`. You can leave the file completely empty. But when it's all said and done, the file will end up looking like this:
 
 ```objective-c
 // This file is automatically generated
 #define robbie_hanson 1
 ```
 
-Of course, when you compile the project on your computer, "robbie_hanson" will get replaced with "whatever_your_full_username_is".
+Of course, when you compile the project on your computer, `robbie_hanson` will get replaced with `whatever_your_full_username_is`.
 
-Note: You should not add "LumberjackUser.h" to source control. But it does need to be added to the Xcode project.
+Note: You should not add `LumberjackUser.h` to source control. But it does need to be added to the Xcode project.
 
-Next we're going to add a script to our project that will automatically generate/update the LumberjackUser.h file. I placed the script in a file named "LumberjackUser.bash":
+Next we're going to add a script to our project that will automatically generate/update the `LumberjackUser.h` file. I placed the script in a file named `LumberjackUser.bash`:
 
 ```
 #!/bin/bash
@@ -84,6 +84,6 @@ Next we're going to add a new "Run Script" Build Phase to our target, ensure it'
 
 ![Screenshot of Xcode](http://www.deusty.com/blog/CocoaLumberjack/PerUserLogLevels1.png)
 
-Finally, you'll want to add LumberjackUser.h and LumberjackUser.temp.h to .gitignore
+Finally, you'll want to add `LumberjackUser.h` and `LumberjackUser.temp.h` to `.gitignore`
 
 And that's all there is to it. Happy Logging.

+ 4 - 4
Documentation/Performance.md

@@ -61,19 +61,19 @@ There are 4 main tests. The base case for each test is a standard NSLog statemen
 -   logging to a file only
 -   logging to the console & file at the same time
 
-Test \# 1:
+#### Test \# 1:
 
 > Asynchronous logging test. Execute 1,000 log statements. All lumberjack log statements are queued onto a background logging thread.
 
-Test \#2:
+#### Test \#2:
 
 > Synchronous logging test. Execute 1,000 log statements. All lumberjack log statements are executed synchronously. They may still be executed on a background logging thread, but the original log statement does not return until the logging has completed.
 
-Test \#3:
+#### Test \#3:
 
 > Real life simulation with an even spread of log statements across various levels. Execute 1,000 log statements. 25% will be above the log level and will be filtered out. 50% will be executed asynchronously. 25% will be executed synchronously.
 
-Test \#4:
+#### Test \#4:
 
 > Real life simulation with an abundance of debug log statements. Execute 1,000 log statements. 90% will be filtered out. 10% will be error messages, executed synchronously.
 

+ 4 - 4
Documentation/XcodeColors.md

@@ -1,11 +1,11 @@
 It's sometimes helpful to color-coordinate your log messages. For example, you may want your error messages to print in red so they stick out.  
-This is possible with DDTTYLogger and XcodeColors.
+This is possible with `DDTTYLogger` and **XcodeColors**.
 
 <a href="http://www.flickr.com/photos/100714763@N06/9576120087/" title="Screen Shot 2013-08-23 at 10.30.09 AM by robbiehanson, on Flickr"><img src="http://farm4.staticflickr.com/3755/9576120087_bf2a3cae91_c.jpg" width="800" height="568" alt="Screen Shot 2013-08-23 at 10.30.09 AM"></a>
 
 ## Install XcodeColors
 
-XcodeColors is a simple plugin for Xcode.  
+**XcodeColors** is a simple plugin for Xcode.  
 It allows you to use colors in the Xcode debugging console.
 
 Full installation instructions can be found on the XcodeColors project page:  
@@ -30,8 +30,8 @@ All it takes is one extra line of code to enable colors in Lumberjack:
 
 The **default color scheme** (if you don't customize it) is:
 
-- DDLogError : Prints in red
-- DDLogWarn  : Prints in orange
+- `DDLogError` : Prints in red
+- `DDLogWarn`  : Prints in orange
 
 However, **you can fully customize the color schemes** however you like!  
 In fact, you can customize the foreground and/or background colors.  

+ 4 - 4
Documentation/XcodeTricks.md

@@ -6,9 +6,9 @@ Starting with Xcode 4, the `DEBUG` preprocessor macro is automatically set when
 
 ```objective-c
 #ifdef DEBUG
-  static const int ddLogLevel = LOG_LEVEL_VERBOSE;
+  static const DDLogLevel ddLogLevel = DDLogLevelVerbose;
 #else
-  static const int ddLogLevel = LOG_LEVEL_WARN;
+  static const DDLogLevel ddLogLevel = DDLogLevelWarn;
 #endif
 ```
 
@@ -22,9 +22,9 @@ When we're done we'll be able to have code like this:
 
 ```objective-c
 #ifdef CONFIGURATION_DEBUG
-  static const int ddLogLevel = LOG_LEVEL_VERBOSE;
+  static const DDLogLevel ddLogLevel = DDLogLevelVerbose;
 #else
-  static const int ddLogLevel = LOG_LEVEL_WARN;
+  static const DDLogLevel ddLogLevel = DDLogLevelWarn;
 #endif
 ```