轻松打造高效日志系统
本文介绍了如何设计并实现高效日志系统,介绍了一个有效的日志系统需要考虑的关键问题,强调了日志在系统调试和监控中的重要性。原文:Design And Building A Logging System
作为开发者,经常需要在调试时查看检查日志,缺乏日志或者不清楚如何通过日志分析问题,就无法定位出错的代码。
对于每天为成千上万甚至上百万用户提供服务的系统来说,日志必不可少,因为:
日志可以帮助我们找到影响最终用户的错误。
日志可以跟踪系统的 "健康状况",在系统出问题之前察觉到某些 "异常迹象"。
……等等
由此可见,在开发或运行系统时,日志至关重要,因此,设计和实施完善的日志系统有助于简化监控工作。
本文将分享我在设计和构建日志系统方面的经验和理解。希望通过这篇文章,你能:
了解在操作系统中记录日志的重要性。
可以作为实施日志系统时的参考。
日志策略
下面列出了我们在实施日志系统之前应该问自己的问题。
Why(为什么):日志记录的目的是什么?
Who(谁): 哪个模块将生成日志?
When(何时):何时输出日志?
Where(哪里):在哪里输出日志(发送到 Slack 或 BigQuery 等)
What(什么):日志能提供什么信息?
How(如何): 如何输出日志?
日志级别
了解日志的目的后,应该对日志进行分级
案例
定义日志级别后,必须明确要输出的日志类型。
本节将针对每种日志类型回答以下六个问题。
Why(为什么)
Who(谁)
When(何时)
Where(哪里)
What(什么)
How(如何)
系统日志(System Log)
Why: 当系统出现错误时,系统日志将用于调试。
Who: 系统本身将输出日志。
When:出错时输出日志。
Where:
FATAL / ERROR
:通知开发人员立即处理。WARN / INFO
:在系统或日志管理工具中输出。DEBUG / TRACE
:输出到预发环境中的console.log
。What:
FATAL / ERROR
:堆栈跟踪。WARN / INFO / DEBUG/ TRACE
:要通知的内容。How:
FATAL / ERROR
:通过日志管理工具或 Slack、SMS......(推模式)输出。WARN / INFO / DEBUG / TRACE
:通过日志管理工具或系统内部输出(拉模式)。
访问日志(Access Log)
Why: 输出日志以跟踪发送和接收请求的过程。
Who: 系统本身或基础设施。
When: 在发送或接收请求时输出。
Where: 在 INFO 级别和拉模式中。由于日志量可能很大,必须注意查找日志的速度。
What: 输出谁、如何、何时进入系统。
How: 根据目的不同,可能会有一些差异。
操作日志(Action Log)
Why: 分析用户操作,从而在此基础上改进服务。
Who: 系统本身或外部工具。
When: 某些操作发生时。
Where: 日志分析工具(BigQuery 等)。
What: 取决于目的。
How: 根据目的不同,可能会有一些差异。
认证日志(Auth Log)
Why: 跟踪用户验证的输出。
Who: 系统本身。
When: 验证用户。
Where: 在 INFO 级别和拉模式中。
What: 输出认证的时间、用户、方式。
How: 根据认证方法不同,可能会有一些差异。
示例
概念就介绍到这里,下面来看一个示例项目。
有关代码的更多详情,请参阅Github。
选择日志库
我选择 log4js 库,原因很简单,因为 log4js 构建日志级别的方式与我的想法一致。
实施
步骤 1 - 定义日志类
首先定义日志类:
在 Logger
类中定义了日志级别:
fatal
error
warn
info
debug
trace
基于此,我又定义了日志类型:
system
api
access_req
access_res
sql
auth
第 2 步 - 将 Logger 应用到项目中
将 Logger
类应用到由 NestJS 框架实现的项目中。
通过 NestJS 的 Interceptor
(拦截器)功能,将日志类注入到项目中。
选择 Interceptor
的原因是 NestJS 拦截器不仅能封装请求流,还能封装从 API 输入和输出的响应流,因此使用拦截器是捕获请求日志和响应日志的最简单方法。我是这样定义 LoggerInterceptor
类的:
定义了三种方法:
requestLogger
: 用于记录请求信息。responseLogger
: 用于记录响应信息。responseErrorLogger
: 用于记录错误信息。
像这样:
定义完 LoggerInterceptor
后,将此拦截器应用到应用程序中:
在 NestJS 应用程序中应用自定义拦截器并不难,因为这是 NestJS 的内置功能。
对于 fatal
和 debug
日志,我将在用例层或基础架构层中使用,以达到以下目的:
通知无法连接数据库等致命错误。
当用户遇到问题时进行调试。
只要这样做:
可以将 fatal
日志输出到控制台或 Slack 等通知管道......
结果如下:
首先是访问请求日志和响应日志(当没有发生错误时)。
可以看到,与请求相关的信息,如 method
、body
等都已清晰显示。
如果出错:
同时显示错误类型和错误信息。
fatal
日志会是这样的:
同样会输出错误信息和错误类型。
结论
本文分享了如何设计和实施一个基本的日志系统。
通过简单的示例,希望你能理解建立日志系统的重要性和必要性,这将有助于系统的运行和调试。
你好,我是俞凡,在 Motorola 做过研发,现在在 Mavenir 做技术工作,对通信、网络、后端架构、云原生、DevOps、CICD、区块链、AI 等技术始终保持着浓厚的兴趣,平时喜欢阅读、思考,相信持续学习、终身成长,欢迎一起交流学习。为了方便大家以后能第一时间看到文章,请朋友们关注公众号"DeepNoMind",并设个星标吧,如果能一键三连(转发、点赞、在看),则能给我带来更多的支持和动力,激励我持续写下去,和大家共同成长进步!
版权声明: 本文为 InfoQ 作者【俞凡】的原创文章。
原文链接:【http://xie.infoq.cn/article/459024e2442ffdfe659f4d5f7】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论