30

日志库的设计思路

 4 years ago
source link: https://www.tuicool.com/articles/VnE3Ubn
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

一、基本思路

日志库的设计,抓住最核心的一条,就是日志从产生到到达最终目的地期间的处理流程。 一般而言,为了设计一个灵活可扩展,可配置的日志库,可将日志库抽象为4个部分:记录器、过滤器、格式化器、输出器四部分。

组成 描述 记录器 负责产生日志记录的原始信息,比如(原始信息,日志等级,时间,记录的位置)等信息 过滤器 负责按指定的过滤条件过滤掉我们不需要的日志(比如按日志等级过滤) 格式化器 负责对原始日志信息按照我们想要的格式去格式化 输出器 负责将将要进行记录的日志(一般经过过滤器及格式化器的处理后)记录到日志目的地(例如:输出到文件中或者通过网络发送出去)

通过将日志库分为上面的4个抽象,使之成了一个较为灵活可扩展的日志库。比如你想实现输出到文件和输出到TCP中这两个功能,你只需分别具体实现这两个输出器的抽象即可。

实现了上面的抽象就基本实现日志库的核心功能。在具体实现上,需要设计一个 Logger ,将上面的抽象组合起来。另外还有一些其他的工作需要完善,比如读取日志配置文件,根据配置文件中的配置条件去构建相应的代码等等其他工作。

二、一条日志的生命周期

可能到这里,你对日志库是怎么工作的还是有些模糊,下面以一条日志的生命周期为例来说明日志库是怎么工作的:

  1. 产生。  info!("log information.");

  2. 经过记录器。记录器去获取日志发生的时间,位置,线程信息等等信息,会有一个数据结构去存储你需要的信息(例如:  msg:"log information.",time:2018-3-2010:00:00,level:info,location:main.rs:3lines

  3. 经过过滤器。决定是否记录(例如,过滤条件设为  info 级以下的过滤掉,这里条日志信息等级是  info ,满足条件,继续。)

  4. 经过格式化器。假设我们想输出为  2018-3-2210:00:00[info]log information.

  5. 到输出器。例如输出到文件中,我们就将这条信息写到文件上(  File::write(....); ,文件中会记录  2018-3-2210:00:00[info]log information. ).

  6. 假如你还实现了日志回滚等功能的话,在日志写入文件之后,还要判断是否触发日志回滚操作,如果满足了日志回滚的条件(比如文件  Size 超过某一大小),则进行日志回滚操作。

  7. 到这里,这条日志的生命周期就结束了。

三、伪代码实现:

  1. 从配置文件中读取配置(可通过序列化或其他方式),生成Config。

  2. LoggerBuilder根据Config去构造Logger。

  3. 由Logger实现日志库的核心功能。

四、更多功能细节

上面是日志库设计的主干,可能我们还需要更多的功能,比如日志回滚、运行时修改配置等......

对于日志回滚,可抽象为两部分,一个是触发回滚操作的条件,一个是何种具体的回滚操作。比如,我们希望当文件大小为1G时就触发回滚操作,回滚的具体操作是删除旧的内容从新开始记录。这里需要你做的就是实现(触发条件+具体操作)这两个抽象。

对于运行时修改配置,实质是根据最新的配置重新生成日志实例,具体实现时可设置一个定时器,定时去读取新的配置,依据新的配置重新生成日志实例,再用这个日志实例记录日志......

五、后记

是不是设计日志库的时候功能越多越好呢?个人认为不是的,功能越多,抽象越复杂,代码越臃肿,比如日志回滚功能的实现,实现过程中会不可避免的增加了锁等,造成性能的下降,所以,够用就好。

各种语言对应的日志库已经有很多了,一般都能够满足需要,如果不满足需要,也可以加以扩展已满足自己的项目需要。

最后,欢迎关注微信公众号,感谢支持,共同进步!

6jQjIjm.jpg!web


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK