Nestjs Winston模块,提供灵活的日志记录方式。
参考自 nest-winston
安装
npm install --save nest-winston-module winston
快速开始
导入 WinstonModule 至 nest应用的根module(通常是AppModule),并使用forRoot()方法来配置nest-winston-module. 创建参数与winston.createLogger方法所需的参数一致,可参考winston官方文档:createLogger()
import { Module } from '@nestjs/common';
import { WinstonModule } from 'nest-winston-module';
import * as winston from 'winston';
@Module({
imports: [
WinstonModule.forRoot({
// options
}),
],
})
export class AppModule {}
在此之后,我们便可以使用Winstontoken将Winston实例注入我们的nest应用中去,
nest-winston-module为应用的不同模块提供了一个token枚举,从而使处理不同类型的日志更加容易。看看下边这个示例:
enum WinstonProviderEnum {
/**
* @description 替换 nest core Logger
*/
coreProvider = 'winstonCoreProvider',
/**
* @description 应用层级 level Logger
*/
appProvider = 'winstonAppProvider',
/**
* @description controller Logger
*/
controllerProvider = 'winstonControllerProvider',
/**
* @description graphQL resolver Logger
*/
resolverProvider = 'winstonResolverProvider',
/**
* @description service Logger
*/
serviceProvider = 'winstonServiceProvider',
/**
* @description 控制台 Logger
*/
consoleProvider = 'winstonConsoleProvider',
/**
* @description 所有Loggers的集合
*/
loggersProvider = 'winstonLoggersProvider',
}
这是在Nest Contrroler中使用WinstonLogger的示例:
import { Controller, Inject } from '@nestjs/common';
import { WinstonProviderEnum, NestWinstonLogger } from 'nest-winston-module';
@Controller('cats')
export class CatsController {
// 使用提供的WinstonProviderEnum枚举来注入Winstoncontroller Logger至Cats Controller中去
constructor(@Inject(WinstonProviderEnum.controllerProvider) private readonly logger: NestWinstonLogger) { }
}
请注意,WinstonModule是一个全局模块,它将在所有功能模块中可用。
Nest Async configuration(异步配置注入)
有时我们需要异步传递options,例如,当服务的启动依赖于动态配置项的读取。 在这种情况下,请使用forRootAsync()方法,并从useFactory方法返回一个选项对象:
import { Module } from '@nestjs/common';
import { WinstonModule } from 'nest-winston-module';
import * as winston from 'winston';
@Module({
imports: [
WinstonModule.forRootAsync({
useFactory: () => ({
// options, 后续会有配置示例
}),
inject: [],
}),
],
})
export class AppModule {}
useFactory创建模块的步骤可能是异步的,我们可以使用inject选项注入依赖项,并可以使用imports选项导入其他模块。
另外,我们可以使用useClass语法:
WinstonModule.forRootAsync({
useClass: WinstonConfigService,
})
使用上述代码,Nest将创建一个新的WinstonConfigService实例,并调用其方法createWinstonModuleOptions以提供模块选项。
替换Nest Core Logger
除了应用程序层级的日志记录之外,nest-winston-module还提供了WinstonLogger定制实现,可与Nest自带的日志记录系统一起使用。 以下是示例main.ts文件:
import { WinstonProviderEnum } from 'nest-winston-module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.useLogger(app.get(WinstonProviderEnum.coreProvider));
}
bootstrap();
NestApplication实例上的get()方法用于检索WinstonLogger类的实例,该实例仍使用WinstonModule.forRoot或WinstonModule.forRootAsync方法进行配置。
注意,当我们替换Nest Core Logger时,只能使用WinstonProviderEnum.coreProvider token来做替换。 因为Winston与Nest所遵循的Logger接口并不完全相同,我们在框架内部对coreProvider做了微妙的适配。
替换Nest Core Logger (并且用作启动服务实例)
使用如上方式有一个小缺点。 Nest必须先引导应用程序(实例化模块和提供程序,注入依赖关系等),在此过程中,WinstonLogger实例尚不可用,这意味着Nest会退回到内部Logger。
这里还有一种解决方案,是使用createLogger函数在应用程序生命周期之外创建Logger,并将其传递给NestFactory.create:
import { WinstonModule } from 'nest-winston-module';
async function bootstrap() {
const app = await NestFactory.create(AppModule, {
logger: WinstonModule.createLogger({
// options (same as WinstonModule.forRoot() options)
})
});
}
bootstrap();
不过使用这种方式,我们便无法使用Nest的依赖注入特性了。这意味着WinstonModule.forRoot和WinstonModule.forRootAsync方法么得用了。
要在我们的应用程序中也使用core Logger,请看如下示例:
import { Logger, Module } from '@nestjs/common';
@Module({
providers: [Logger],
})
export class AppModule {}
import { Controller, Inject, Logger, LoggerService } from '@nestjs/common';
@Controller('cats')
export class CatsController {
constructor(@Inject(Logger) private readonly logger: LoggerService) { }
}
上述代码之所以可行,是因为Nest Logger包装了我们的WinstonLogger(由createLogger方法返回的相同实例)并将所有调用转发给它。
配置
我们可以使用nest-winston-module提供的默认配置项,或者根据业务的不同进行自定义操作:
import { Module } from '@nestjs/common';
import {
coreOptions,
appOptions,
controllerOptions,
resolverOptions,
serviceOptions,
consoleOptions,
} from 'nest-winston-module';
import * as winston from 'winston';
@Module({
imports: [
WinstonModule.forRoot({
core: coreOptions,
app: appOptions,
resolver: resolverOptions,
controller: controllerOptions,
service: serviceOptions,
console: consoleOptions,
directory: process.cwd() + '/logs',
}),
],
})
export class AppModule {}
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!