CocoaLumberjack源码分析

1.使用

  1. 自定义custom context,自定义flag
  2. 自定义日志的格式
  3. 自定义日志级别,取消DDLog实现自定义。
  4. 动态更改日志级别、使用userDefault保持上次更改记录、动态注册,为每个类添加日志的级别。
  5. 仅过滤出想要的日志级别,如LOG_ERROR;将同类型的日志归为一组。

2.文件结构

这份代码看到了面向接口编程的影子,与敏捷开发案例中的代码结构类似。

2.1 DDLogger

  1. DDAbstractLogger实现了DDLogger协议,子类: DDASLLogger、DDFileLogger、DDOSLogger、DDTTYLogger
  2. DDASLLogger:此类为终端输出或Xcode控制台输出提供了记录器,logMessage是C的,没看懂。
  3. DDFileLogger:管理文件。
  4. DDOSLogger:mac系统日志,暂时不用
  5. DDTTYLogger:此类为终端输出或Xcode控制台输出提供了记录器,与DDASLLogger处理控制台颜色,暂时不用

DDLoggerNode:model,DDLogger、loggerQueue、level的一个封装
DDLog单例:_loggers管理多个对象
DDLogMessage:消息对象

DDLogger:logMessage:DDLogMessage 添加消息时,带入消息对象到各个管理文件进行不同操作。在此之前会对数据按自定义或默认格式进行格式化
_logFormatter:提前配置好的。

2.2DDLogFormatter

DDContextFilterLogFormatter:过滤消息,白名单输出日志,黑名单不输出日志
DDDispatchQueueLogFormatter:打印队列日志
DDMultiFormatter:可添加多个日志格式消息;再次验证,栅栏函数使用自定义并发队列,在添加、移除时使用栅栏函数,获取消息时使用同步访问。

3.宏定义直接调用方法:DDlog

3.1宏的调用流程

__ PRETTY_FUNCTION __ 宏产生整个函数签名 - 返回类型,类名和所有参数,可能很长
## __VA_ARGS__ 是一个可变参数的宏,实现思想就是宏定义中参数列表的最后一个参数为省略号(也就是三个点)
#undef 取消宏定义

#define LOG_MACRO(isAsynchronous, lvl, flg, ctx, atag, fnct, frmt, ...) \
        [DDLog log : isAsynchronous                                     \
             level : lvl                                                \
              flag : flg                                                \
           context : ctx                                                \
              file : __FILE__                                           \
          function : fnct                                               \
              line : __LINE__                                           \
               tag : atag                                               \
            format : (frmt), ## __VA_ARGS__]

#define LOG_MAYBE(async, lvl, flg, ctx, fnct, frmt, ...)                       \
        do { if(lvl & flg) LOG_MACRO(async, lvl, flg, ctx, nil, fnct, frmt, ##__VA_ARGS__); } while(0)

#define LOG_OBJC_MAYBE(async, lvl, flg, ctx, frmt, ...) \
        LOG_MAYBE(async, lvl, flg, ctx, __PRETTY_FUNCTION__, frmt, ## __VA_ARGS__)

//if(lvl & flg) 定义了lvl才能打印,调用了DDLog log

3.2 分析DDLogDebug

#define DDLogDebug(frmt, ...) LOG_OBJC_MAYBE(LOG_ASYNC_DEBUG, LOG_LEVEL_DEF, LOG_FLAG_DEBUG, 0, frmt, ##VA_ARGS)

  1. 第一个参数LOG_ASYNC_DEBUG
    #define LOG_ASYNC_ENABLED YES
    #define LOG_ASYNC_ERROR ( NO && LOG_ASYNC_ENABLED)
    #define LOG_ASYNC_DEBUG (YES && LOG_ASYNC_ENABLED)
    该字段表示是否异步,除了DDLogError是同步,其余都是异步日志。

  2. 第二个参数
    #ifndef LOG_LEVEL_DEF
    #define LOG_LEVEL_DEF ddLogLevel
    #endif
    #ifndef 如果没有定义LOG_LEVEL_DEF,定义一个默认的ddLogLevel,用户自定义的

  3. 第三个参数
    LOG_FLAG_DEBUG:与DDLogFlag宏对应,采用的是位偏移量
    lvl & flg可以产生想要的结果

  4. 其他参数
    定义可变参数

4.OC代码流程

4.1流程

  1. 调用宏->+log(DDLog)->消息封装成DDLogMessage->queueLogMessage(DDLog)->lt_log(DDLog)
  2. 遍历数组_loggers调用logMessage进行消息分发

4.2 思路

DDLog 管理一个队列,队列中存放的是id对象(日志、打印到控制台、改变颜色等),该对象都继承自DDAbstractLogger实现DDLogger协议。
+logFormatter:DDLogFormatter 获取日志时,通过DDLogFormatter获取不同格式的日志,包括黑白名单、队列、多日志等。

5.文件管理

分为两部分:一部分是写入文件、另一部分是管理文件
滚动
maximumFileSize:最大文件个数
rollingFrequency:按时间进行滚动
日志压缩上传

您可能已经猜到了DDFileLogger实现,它分为两个部分。 DDFileLogger是将日志消息写入文件的组件。 DDLogFileManager是一种协议,用于管理日志文件,并决定在滚动日志文件后如何处理。

6. 感想

  1. 初看时,作者的架构非常清晰,面向接口编程。有UML图给出类关系,document详细的日志,每个类的头部都带有简介说明此类作用,重要方法都有详细注释。
  2. 再看,发现作者对宏的使用出神入化。可变参数,打印函数的返回值、方法名、参数等,#ifndef定义ddLogLevel,取消作者定义的宏实现用户自定义
  3. 再看,发现框架扩展性非常强。日志级别、日志格式、Context、flag、动态修改LogLevel、每个用户等都是可以自定义。这才是可扩展的框架。

你可能感兴趣的:(CocoaLumberjack源码分析)