我們在開發(fā)中經(jīng)常需要打日志压鉴,iOS提供的NSLog只能在Xcode里面查看宦赠,這種方式有如下限制:
1、只有處于Debug模式下才能在Xcode看到日志队萤,其他情況無能為力轮锥。測試、產(chǎn)品等同事在測試和體驗(yàn)App的時(shí)候由于日志沒有記錄到本地要尔,對于一些無法復(fù)現(xiàn)或者復(fù)現(xiàn)路徑很難的問題肯定束手無策舍杜。
2、發(fā)布到App Store的App赵辕,下載了這個(gè)App的用戶出現(xiàn)了無法復(fù)現(xiàn)或者復(fù)現(xiàn)路徑很難的問題既绩,我們也只能干著急。
CocoaLumberjack這個(gè)開源日志庫就是為了解決上訴兩個(gè)問題的匆帚。
一熬词、什么是CocoaLumberjack?
CocoaLumberjack是iOS業(yè)界有名的github開源日志庫吸重,提供如下功能:
1互拾、支持日志打印到Xcode控制臺,打印到mac的console程序嚎幸、打印到文件
2颜矿、日志功能支持關(guān)閉和打開,支持Error嫉晶、Warning骑疆、Info田篇、Debug、Verbose箍铭、All日志等級
3泊柬、支持基于DDLogFormatter協(xié)議自定義日志格式和繼承DDAbstractLogger和協(xié)議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];
三、架構(gòu)圖
梳理一下各個(gè)類的作用和關(guān)系:
1冷守、DDLog刀崖,全局單例類。此類通過方法+ (void)addLogger:(id)logger保存了一系列繼承于DDAbstractLogger的logger拍摇,通過_loggers屬性保存logger亮钦,該類相當(dāng)于一個(gè)服務(wù)分發(fā)器,外部調(diào)用DDLogxxx宏(比如DDLogDebug)實(shí)際上都會(huì)路由到DDLog的log方法充活,最終通過lt_log方法調(diào)用各個(gè)logger的logMessage方法實(shí)現(xiàn)日志打印蜂莉。
2、DDAbstractLogger堪唐,實(shí)現(xiàn)了協(xié)議DDLogger巡语,所有l(wèi)ogger都繼承于該類。
3淮菠、DDLogger協(xié)議男公,最重要的方法是- (void)logMessage:(DDLogMessage *)logMessage,所有繼承于DDAbstractLogger的logger通過實(shí)現(xiàn)該方法進(jìn)行日志的打印合陵。通過logFormatter屬性保存了日志格式化實(shí)例
4枢赔、DDLogFormatter,通過方法- (NSString *)formatLogMessage:(DDLogMessage *)logMessage格式化DDLogMessage對象
5拥知、DDTTYLogger踏拜,通過該類把日志打印到Xcode控制臺。
6低剔、DDASLLogger速梗,通過該類把日志打印到mac的console程序里面。
7襟齿、DDFileLogger姻锁,通過該類把日志保存到文件。
8猜欺、DDAbstractDatabaseLogger位隶,通過實(shí)現(xiàn)該類把日志保存到數(shù)據(jù)庫里面。
四开皿、實(shí)現(xiàn)關(guān)鍵點(diǎn):
1涧黄、如何實(shí)現(xiàn)日志打印不阻塞主線程篮昧?
對于每個(gè)繼承于DDAbstractLogger的類比如DDFileLogger,內(nèi)部會(huì)創(chuàng)建一個(gè)分發(fā)對象_loggerQueue笋妥,所有的logMessage方法都會(huì)運(yùn)行在這個(gè)_loggerQueue里面懊昨。
DDLog類創(chuàng)建了一個(gè)串行的分發(fā)隊(duì)列_loggingQueue,通過_loggingQueue把外部的DDLogxxx調(diào)用異步路由到lt_log方法里面春宣;通過全局分發(fā)組對象dispatch_group_t _loggingGroup來等待外部的DDLogxxx調(diào)用分發(fā)到相應(yīng)的logger打印結(jié)束疚颊;另外,通過信號量_queueSemaphore來控制queueLogMessage最大調(diào)用量信认,最大為1000,大于1000將排隊(duì)等待均抽。
2、DDFileLogger的工作機(jī)制
rollingFrequency和maximumFileSize如何控制單個(gè)日志文件?
CocoaLumberjack在訪問最近創(chuàng)建的一個(gè)日志文件時(shí)嗅定,會(huì)根據(jù)回滾頻率和日志文件大小決定是否需要?jiǎng)?chuàng)建新的日志文件暇检,如果日志文件存活時(shí)間大于等于回滾頻率或者日志文件大小大于等于最大大小,則回滾該日志文件(給該日志文件后綴加上kDDXAttrArchivedName)深寥,并且創(chuàng)建一個(gè)新的日志文件來存日志攘乒;否則繼續(xù)用這個(gè)日志文件存日志。日志文件存活時(shí)間是以日志文件創(chuàng)建時(shí)間為基準(zhǔn)的惋鹅。
每次調(diào)用logMessage方法的時(shí)候都會(huì)調(diào)用maybeRollLogFileDueToSize檢測日志文件大小是否超過maximumFileSize则酝; 通過dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, self.loggerQueue)創(chuàng)建一個(gè)計(jì)時(shí)器,定時(shí)掃描文件來實(shí)現(xiàn)文件存活時(shí)間功能闰集。
logFileManager屬性maximumNumberOfLogFiles如何控制一系列日志文件沽讹。
通過kvo maximumNumberOfLogFiles 和logFilesDiskQuota調(diào)用deleteOldLogFiles來實(shí)現(xiàn)最多保持maximumNumberOfLogFiles個(gè)日志文件。
3武鲁、如何實(shí)現(xiàn)日志文件上傳到自己的服務(wù)器爽雄?
后臺下發(fā)一個(gè)命令字,打包壓縮日志文件上傳即可沐鼠。也可以通過自己自定義logger來實(shí)現(xiàn)