最近在写nestjs-bunyan的时候,想要实现decorator自动创建childLogger,记录当前class的功能,最初的实现也很简单粗暴,在decorator上记录当前类名,然后给每个类名创建一个Provider。
但是这样做缺点也很明显,在应用启动后,没法创建新的日志模块,也不能手动添加日志模块。正好最近公司基建在做日志改造,就决定优化一下这个逻辑。
经过一阵深思,觉得nestjs的TRANSIENT作用域比较符合我的要求,相当于每次请求日志都需要给我一个新的对象,但是文档并没有提到如何在provider的构造方法里获知是哪个类需要被注入。
在尝试了一阵this和无脑Google后,并没有找到什么有效的文章,于是决定研究一下源码。
经过一阵阅读和搜索,我找到了https://github.com/nestjs/nest/blob/99ee3fd99341bcddfa408d1604050a9571b19bc9/packages/core/injector/inquirer/inquirer-providers.ts INQUIRER这个Provider,看名字似乎有点符合我的需求,于是顺着这个provider找到了https://github.com/nestjs/nest/issues/3819这个issue,确认了这确实是我要的东西,只是还没有在文档中体现,那剩下的就简单多了,把logger 的provider修改为
{
provide: BunyanLogger,
scope: Scope.TRANSIENT,
inject: [Logger, INQUIRER],
useFactory(logger: Logger, a: Constructor) {
return logger.child({components: a?.constructor.name})
},
}, {
provide: BunyanRequestLogger,
scope: Scope.REQUEST,
inject: [Logger, INQUIRER, REQUEST, 'Options'],
useFactory(logger: Logger, a: Constructor, req: Request, options: IOptions) {
logger = logger.child({components: a?.constructor.name, reqId: req?.headers[options.reqIdHeader]})
if (options.customRequestLogger) {
logger = options.customRequestLogger(logger, req)
}
return logger
},
}