这是我日志系统项目的基础版本,目的是先实现一个基础版本的日志系统,后续在对其进行扩展,丰富更多功能
一、日志的重要性
1.什么是日志?
在软件开发当中,日志是一种记录系统运行时信息的方式。
日志当中记录了程序的运行状态、错误信息、警告和调试信息等,通常被记录到文件当中,当然也可以记录到数据库当中,或者发送到远程服务器当中
正因为日志记录了运行状态、(错误、警告、调试)信息等,因此日志在软件开发当中便具有了以下意义:
2.排查BUG
因为日志记录了(错误、警告、调试信息),因此当代码出现BUG时,可以通过查看日志了解程序在执行过程中的各个步骤和状态,帮助快速定位和分析问题
尤其是因为有些BUG很难复现,所以通过日志就可以精准捕获任何BUG,无需再去复现了
3.监控系统
因为日志记录了运行状态,因此日志可以用来监控系统事件(系统启动、关闭、重启和故障)
这可以帮助管理员更好的了解系统健康状况,及时发现和解决潜在的问题
4.监控程序性能
因为日志记录了运行状态,因此日志可以用来监控应用程序的运行状况和性能,可以记录关键指标:(响应时间,数据库查询次数,内存使用情况。。。)
通过分析这些日志数据,开发人员可以及时发现潜在的性能问题,并采取措施来改进应用程序的性能
二、日志系统技术
日志的落地方向,主要分为三种:
- printf / cout 打印到控制台
- 将日志写入文件
- 将日志写入数据库 -> 为了方便查询和分析日志
在执行角度又分为:
- 同步写日志
- 异步写日志
1.同步写日志
当输出日志时,必须等待日志输出任务结束之后,才能继续下面的业务逻辑
每次输出日志都要调用一次write,磁盘IO较为频繁,而IO操作本身就慢,所以有可能会延迟业务线程对业务逻辑的处理
这是一个业务线程串行化打印日志的过程
2.异步写日志
同步写日志有一个很大的缺陷,就是它让业务线程打印日志串行化了,在日志成功输出之前,业务线程无法处理接下来的业务逻辑
因此就有了异步写日志:
业务线程要打印日志时,只需要将日志放入日志缓冲区即可
会专门有日志线程从缓冲区当中拿日志并进行输出
这就是一个生产消费模型,业务线程就是生产者,日志线程就是消费者
一般来说,日志线程的数量都不会多,因为线程还是要多分配给业务模块,毕竟线程不是越多越好
3.日志文件轮换方案
因为服务器是24小时永远不停止服务的,所以日志肯定不可能全都往一个文件当中堆,否则查询和分析日志时就非常麻烦了
1.日志分类方式
- 按日志等级进行分类
- 按时间进行分类(年月日时分秒)
- 按模块进行分类(系统日志、应用程序日志、安全日志)
- 按错误类型进行分类(系统错误、应用程序错误、配置错误)
分类方式还有很多,具体问题具体分析,分类方式很灵活
2.日志轮换方案
一种类型的日志也不能无限制的往一个文件当中堆,照样会提高查询和分析日志的复杂程度
因此,日志需要轮换:
- 按文件大小进行轮换(到达指定的文件大小之后进行轮换)
- 按时间进行轮换(时,分,秒)
因此日志落地当中:向文件当中落地又可以细分为:
- 向固定文件落地
- 向滚动文件(轮换文件)落地
三、项目设计
1.目标
我们要实现一个线程安全的,支持同步,异步,多落地方式的日志系统
2.设计
1.日志消息模块
日志系统,首先要有日志消息结构体
这个模块就是定义日志消息结构体的模块
注意:日志往往需要包含以下字段:
- 时间(年月日时分秒)
- 日志等级
- 文件名和行号
- 线程ID
- 消息主体
因为这些字段太多,记录日志时,有时我们不太需要线程ID,有时可能只想记录消息主体
因此为了让日志的记录方式更加灵活,我们参照printf的格式化占位符设计思想,设计出了日志格式化模块
2.日志格式化模块
日志格式化模块主要负责:
- 约定各种格式化占位符
- 允许用户传入自定义格式化字符串,在内部解析
- 把用户传入的消息主体格式化为日志消息
能够把消息转为日志之后,下面我们就要考虑如何将日志落地到不同的位置:
- 标准输出
- 文件
- 数据库
- 远程服务器
因此,我们就需要日志落地模块
3.日志消息落地模块
日志落地模块主要负责将格式化之后的日志消息输出到指定的落地方向
关键是支持多落地方向:
- 标准输出
- 指定文件
- 滚动文件(按大小进行滚动)
而且还支持用户灵活扩展
能够将日志落地到指定方向之后,因为一条日志可以落地到不同位置,而且这三个模块需要整合一下
因此就有了下面这个整合模块:日志器模块
4.日志器模块
日志器模块主要负责对:
日志消息模块、日志格式化模块、日志消息落地模块进行整合
对外提供便捷,好用的接口来完成消息的输出
注意:
- 一个日志器支持多个落地方向
- 一个日志器只支持一种日志格式
- 日志器是日志打印的基本单位
- 日志器分为同步日志器和异步日志器,
分别负责同步日志记录和异步日志记录
日志格式不同,便需要不同的日志,因此日志器会存在多份,所以需要一个日志器管理类
5.日志器管理模块
所谓管理,在这里就是增删查改
6.异步日志器模块
对于同步日志器来说,上面那些模块就足够了
而对于异步日志器来说,还差一个交易场所和消费者
因此,这个模块除了基本的日志器模块之外,需要一个缓存(交易场所)模块和一个异步工作器模块(消费者线程)
实现一个打印日志的生产消费模型