ログ出力ライブラリのCocoaLumberjackを使う


iOSのログ出力ライブラリとしては長らくLibComponentLoggingを使っていましたが、外部ライブラリのcocoapods化を進めるにあたって、導入方法や使い方がよりシンプルなCocoaLumberjackに移行しました。

また、人気もあり継続的にメンテナンスされているので安心です。
[CocoaLumberjack](https://github.com/CocoaLumberjack/CocoaLumberjack)

## 導入方法

Podfileに追加して、pod udpateをかけます。

```Podfile
pod 'CocoaLumberjack', '~> 1.0'
```

## ログレベル設定

### ログレベル固定の場合

ddLogLevelの宣言を、ログ出力している全ての箇所からimportされているヘッダー（const.h/common.h等）または.pchファイルに追加します。

```objc:const.h
const int ddLogLevel = LOG_LEVEL_DEBUG;
```

### ログレベル可変の場合

ログのON/OFFを設定に持たせる場合、また別のライブラリがCocoaLumberjackを使用している場合（MagicalRecord等）もログレベルを可変にしておく必要があります。

ddLogLevelの宣言を、ログ出力している全ての箇所からimportされているヘッダー（const.h/common.h等）または.pchファイルに追加します。

```objc:const.h
extern int ddLogLevel;
```

ddLogLevelの初期値設定をAppDelegate等の適当な.mファイルで行います。（グローバルスコープです）

```objc:AppDelegate.m
int ddLogLevel = LOG_LEVEL_DEBUG;
```

## ロガーの初期化

NSLogのようにXcodeのコンソールにログを出力するには、DDTTYLoggerを設定します。
ログをファイル出力する場合はDDFileLoggerを設定します。

```objc:AppDelegate.m
#import "DDLog.h"
#import "DDTTYLogger.h"
#import "DDFileLogger.h"

-(BOOL) application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
	// コンソールログ
	DDTTYLogger *ttyLogger = [DDTTYLogger sharedInstance];
	ttyLogger.logFormatter = [[LogFormatter alloc] init];
	[DDLog addLogger:ttyLogger];


	// ファイル出力ログ
	// ログファイル保存場所
	NSString *logPath = [NSHomeDirectory() stringByAppendingPathComponent:@"Library/Logs/"];	
	DDLogFileManagerDefault *logFileManager = [[DDLogFileManagerDefault alloc] initWithLogsDirectory:logPath];
	self.fileLogger = [[DDFileLogger alloc] initWithLogFileManager:logFileManager];
	self.fileLogger.logFormatter = [[LogFormatter alloc] init];
	// ログファイル最大サイズ:10MB
	self.fileLogger.maximumFileSize = 10 * 1024 * 1024;
	// ログファイル最大個数:5個
	self.fileLogger.logFileManager.maximumNumberOfLogFiles = 5;
	[DDLog addLogger:self.fileLogger];

	...
}
```

## ログ出力
NSLogと使い方は大体同じです。ログレベルによってマクロ名が変わっているので、適当に使い分けます。自分の場合はError,Info,Debugの3つを使っています。

1. DDLogError
- DDLogWarn
- DDLogInfo
- DDLogDebug
- DDLogVerbose


```objc:Hoge.m
-(void) hoge {
	DDLogDebug(@"begin");
	
	if (error) {
		DDLogError(@"error: %@", error);
	} else {
		DDLogInfo(@"no error");
	}

	DDLogDebug(@"end");
}
```

## ロガーのフォーマットカスタマイズ

公式の情報を参考に、ログ出力行のカスタマイズをしてみます。
https://github.com/CocoaLumberjack/CocoaLumberjack/wiki/CustomFormatters

```objc:LogFormatter.m
-(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;
        default             : logLevel = @"V"; break;
    }
    
    NSString *dateAndTime = [self stringFromDate:(logMessage->timestamp)];
    NSString *logMsg = logMessage->logMsg;
	NSString *fileName = logMessage.fileName;
	NSString *methodName = logMessage.methodName;
    int lineNumber = logMessage->lineNumber;
	NSString *threadID = logMessage.threadID;
	
    return [NSString stringWithFormat:@"%@ (%@) %@ [%@(%d) %@] %@",
			dateAndTime, threadID, logLevel, fileName, lineNumber, methodName, logMsg];
}
```

こんな感じでログが出力されるようになります。

```
2014/03/04 11:20:42:886 (70b) D [MessageCell(103) onSingleTap:] <message body:test, user:<user name:anonymous>>
2014/03/04 11:20:42:886 (70b) D [UserDetailView(48) setUser:] <user name:anonymous>
```