深入解析iOS日志庫CocoaLumberjack
我們在開發中經常需要打日志,iOS提供的NSLog只能在Xcode里面查看,這種方式有如下限制:
1、只有處于Debug模式下才能在Xcode看到日志,其他情況無能為力。測試、產品等同事在測試和體驗App的時候由于日志沒有記錄到本地,對于一些無法復現或者復現路徑很難的問題肯定束手無策。
2、發布到App Store的App,下載了這個App的用戶出現了無法復現或者復現路徑很難的問題,我們也只能干著急。
CocoaLumberjack 這個開源日志庫就是為了解決上訴兩個問題的。
一、什么是CocoaLumberjack?
CocoaLumberjack是iOS業界有名的github開源日志庫,提供如下功能:
1、支持日志打印到Xcode控制臺,打印到mac的console程序、打印到文件
2、日志功能支持關閉和打開,支持Error、Warning、Info、Debug、Verbose、All日志等級
3、支持基于DDLogFormatter協議自定義日志格式和繼承DDAbstractLogger和協議DDLogger自定義logger
二、用法
用法很簡單,具體參照github,這里貼一段簡單的代碼
[DDLog addLogger:[DDTTYLogger sharedInstance]]; // TTY = Xcode console
[DDTTYLogger sharedInstance].logFormatter = [[MyCustomDDLogFormatter alloc] init];
DDFileLogger *fileLogger = [[DDFileLogger alloc] init]; // File Logger
fileLogger.rollingFrequency = 60 * 60 * 24; // 24 hour rolling
fileLogger.maximumFileSize = 50 * 1024 * 1024; //50MB
fileLogger.logFileManager.maximumNumberOfLogFiles = 7;
fileLogger.logFormatter = [[MyCustomDDLogFormatter alloc] init];
[DDLog addLogger:fileLogger];
三、架構圖
梳理一下各個類的作用和關系:
1、DDLog,全局單例類。此類通過方法+ (void)addLogger:(id)logger保存了一系列繼承于DDAbstractLogger的logger,通過_loggers屬性保存logger,這些該類相當于一個服務分發器,外部調用DDLogxxx宏(比如DDLogDebug)實際上都會路由到DDLog的log方法,最終通過lt_log方法調用各個logger的logMessage方法實現日志打印。
2、DDAbstractLogger,實現了協議DDLogger,所有logger都繼承于該類。
3、DDLogger協議,最重要的方法是- (void)logMessage:(DDLogMessage *)logMessage,所有繼承于DDAbstractLogger的logger通過實現該方法進行日志的打印。通過logFormatter屬性保存了日志格式化實例
4、DDLogFormatter,通過方法- (NSString *)formatLogMessage:(DDLogMessage *)logMessage格式化DDLogMessage對象
5、DDTTYLogger,通過該類把日志打印到Xcode控制臺。
6、DDASLLogger,通過該類把日志打印到mac的console程序里面。
7、DDFileLogger,通過該類把日志保存到文件。
8、DDAbstractDatabaseLogger,通過實現該類把日志保存到數據庫里面。
四、實現關鍵點:
1、如何實現日志打印不阻塞主線程?
對于每個繼承于DDAbstractLogger的類比如DDFileLogger,內部會創建一個分發對象_loggerQueue,所有的logMessage方法都會運行在這個_loggerQueue里面。
DDLog類創建了一個串行的分發隊列_loggingQueue,通過_loggingQueue把外部的DDLogxxx調用異步路由到lt_log方法里面;通過全局分發組對象dispatch_group_t _loggingGroup來等待外部的DDLogxxx調用分發到相應的logger打印結束;另外,通過信號量_queueSemaphore來控制queueLogMessage最大調用量,最大為1000,大于1000將排隊等待。
2、DDFileLogger的工作機制
rollingFrequency和maximumFileSize如何控制單個日志文件?
CocoaLumberjack在訪問最近創建的一個日志文件時,會根據回滾頻率和日志文件大小決定是否需要創建新的日志文件,如果日志文件存活時間大于等于回滾頻率或者日志文件大小大于等于最大大小,則回滾該日志文件(給該日志文件后綴加上kDDXAttrArchivedName),并且創建一個新的日志文件來存日志;否則繼續用這個日志文件存日志。日志文件存活時間是以日志文件創建時間為基準的。
每次調用logMessage方法的時候都會調用maybeRollLogFileDueToSize檢測日志文件大小是否超過maximumFileSize; 通過dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, self.loggerQueue)創建一個計時器,定時掃描文件來實現文件存活時間功能。
logFileManager屬性maximumNumberOfLogFiles如何控制一系列日志文件。
通過kvo maximumNumberOfLogFiles 和logFilesDiskQuota調用deleteOldLogFiles來實現最多保持maximumNumberOfLogFiles個日志文件。
3、如何實現日志文件上傳到自己的服務器?
后臺下發一個命令字,打包壓縮日志文件上傳即可。也可以通過自己自定義logger來實現
來自:http://www.jianshu.com/p/d8bad0e2683c