日志
Midway 为不同场景提供了一套统一的日志接入方式。通过 @midwayjs/logger
包导出的方法,可以方便的接入不同场景的日志系统。
实现的功能有:
- 日志分级
- 按大小和时间自动切割
- 自定义输出格式
- 统一错误日志
当前版本为 3.0 的日志 SDK 文档,如需 2.0 版本,请查看 这个文档。
从 2.0 升级到 3.0
从 midway v3.13.0 开始,支持使用 3.0 版本的 @midwayjs/logger
。
将 package.json
中的依赖版本升级,注意是 dependencies
依赖。
{
"dependencies": {
- "@midwayjs/logger": "2.0.0",
+ "@midwayjs/logger": "^3.0.0"
}
}
如果在配置中没有了 midwayLogger 的类型提示,你需要在 src/interface.ts
中加入日志库的引用。
// src/interface.ts
+ import type {} from '@midwayjs/logger';
在大部分场景下,两个版本是兼容的,但是由于是大版本升级,肯定会有一定的差异性,完整的 Breaking Change 变化,请查看 变更文档。
日志路径和文件
Midway 会在日志根目录创建一些默认的文件。
midway-core.log
框架、组件打印信息的日志,对应coreLogger
。midway-app.log
应用打印信息的日志,对应appLogger
,在@midawyjs/web
中,该文件是midway-web.log
common-error.log
所有错误的日志(所有 Midway 创建出来的日志,都会将错误重复打印一份到该文件中)
本地开发和服务器部署时的 日志路径 和 日志等级 不同,具体请参考 配置日志根目录 和 框架的默认等级。
默认日志对象
Midway 默认在框架提供了三种不同的日志,对应三种不同的行为。
日志 | 释义 | 描述 | 常见使用 |
---|---|---|---|
coreLogger | 框架,组件层面的日志 | 默认会输出控制台日志和文本日志 midway-core.log ,并且默认会将错误日志发送到 common-error.log 。 | 框架和组件的错误,一般会打印到其中。 |
appLogger | 业务层面的日志 | 默认会输出控制台日志和文本日志 midway-app.log ,并且默认会将错误日志发送到 common-error.log ,在 @midawyjs/web 中,该文件是 midway-web.log 。 | 业务使用的日志,一般业务日志会打印到其中。 |
上下文日志(复用 appLogger 的配置) | 请求链路的日志 | 默认使用 appLogger 进行输出,除了会将错误日志发送到 common-error.log 之外,还增加了上下文信息。 | 不同的协议有不同的请求日志格式,比如 HTTP 下就会输出路由信息。 |
使用日志
Midway 的常用日志使用方法。
上下文日志
上下文日志是关联框架上下文对象(Context) 的日志。
我们可以通过 获取到 ctx 对象 后,使用 ctx.logger
对象进行日志打印输出。
比如:
ctx.logger.info("hello world");
ctx.logger.debug('debug info');
ctx.logger.warn('WARNNING!!!!');
// 错误日志记录,直接会将错误日志完整堆栈信息记录下来,并且输出到 errorLog 中
// 为了保证异常可追踪,必须保证所有抛出的异常都是 Error 类型,因为只有 Error 类型才会带上堆栈信息,定位到问题。
ctx.logger.error(new Error('custom error'));
在执行后,我们能在两个地方看到日志输出:
- 控制台看到输出。
- 日志目录的 midway-app.log 文件中
输出结果:
2021-07-22 14:50:59,388 INFO 7739 [-/::ffff:127.0.0.1/-/0ms GET /api/get_user] hello world
在注入的形式中,我们也可以直接使用 @Inject() logger
的形式来注入 ctx.logger
,和直接调用 ctx.logger
等价。
比如:
import { Get, Inject, Controller, Provide } from '@midwayjs/core';
import { ILogger } from '@midwayjs/logger';
@Controller()
export class HelloController {
@Inject()
logger: ILogger;
@Inject()
ctx;
@Get("/")
async hello(){
// ...
// this.logger === ctx.logger
}
}
应用日志(App Logger)
如果我们想做一些应用级别的日志记录,如记录启动阶段的一些数据信息,可以通过 App Logger 来完成。
import { Configuration, Logger } from '@midwayjs/core';
import { ILogger } from '@midwayjs/logger';
@Configuration()
export class MainConfiguration implements ILifeCycle {
@Logger()
logger: ILogger;
async onReady(container: IMidwayContainer): Promise<void> {
this.logger.debug('debug info');
this.logger.info('启动耗时 %d ms', Date.now() - start);
this.logger.warn('warning!');
this.logger.error(someErrorObj);
}
}
注意,这里使用的是 @Logger()
装饰器。
CoreLogger
在组件或者框架层面的研发中,我们会使用 coreLogger 来记录日志。
@Configuration()
export class MainConfiguration implements ILifeCycle {
@Logger('coreLogger')
logger: ILogger;
async onReady(container: IMidwayContainer): Promise<void> {
this.logger.debug('debug info');
this.logger.info('启动耗时 %d ms', Date.now() - start);
this.logger.warn('warning!');
this.logger.error(someErrorObj);
}
}
输出方法和格式
Midway 的日志对象提供 error()
, warn()
, info()
, debug()
,write()
五种方法。
示例如下。
logger.debug('debug info');
logger.info('启动耗时 %d ms', Date.now() - start);
logger.warn('warning!');
logger.error(new Error('my error'));
logger.write('abcdef');
write
方法用于输出用户的原始格式日志。
基于 util.format
的格式化方式。
logger.info('%s %d', 'aaa', 222);
常用的有
%s
字符串占位%d
数字占位%j
json 占位
更多的占位和详细信息,请参考 node.js 的 util.format 方法。
日志类型定义
大部分情况下,用户应该使用 @midwayjs/core
中最简单的 ILogger
定义。
import { Provide, Logger, ILogger } from '@midwayjs/core';
@Provide()
export class UserService {
@Inject()
logger: ILogger;
async getUser() {
this.logger.info('hello user');
}
}
ILogger
定义只提供最简单的 debug
, info
, warn
以及 error
方法。
在某些场景下,我们需要更为复杂的定义,这个时候需要使用 @midwayjs/logger
提供的 ILogger
定义。
import { Provide, Logger } from '@midwayjs/core';
import { ILogger } from '@midwayjs/logger';
@Provide()
export class UserService {
@Inject()
logger: ILogger;
async getUser() {
// ...
}
}
ILogger
的定义可以参考 interface 中的描述,或者查看 代码。