无法使用 NestJS 注入 winston 的记录器实例
Unable to inject winston's logger instance with NestJS
我正在使用 NestJS 7.0.7
和 Winston 3.2.1
(使用 nest-winston 1.3.3
)。
我正在尝试将 Winston 集成到 NestJS 中,但到目前为止,我无法将记录器实例(实际记录任何内容)注入任何 controller/service.
因为我想在引导过程中跨应用程序 AND 使用 Winston,所以我使用 approach 作为主要的 Nest 记录器:
// main.ts
import { NestFactory } from "@nestjs/core";
import { WinstonModule } from "nest-winston";
import { format, transports } from "winston";
import { AppModule } from "./app.module";
async function bootstrap(): Promise<void> {
const app = await NestFactory.create(AppModule, {
logger: WinstonModule.createLogger({
exitOnError: false,
format: format.combine(format.colorize(), format.timestamp(), format.printf(msg => {
return `${msg.timestamp} [${msg.level}] - ${msg.message}`;
})),
transports: [new transports.Console({ level: "debug" })], // alert > error > warning > notice > info > debug
}),
});
app.use(helmet());
await app.listen(process.env.PORT || 3_000);
}
bootstrap().then(() => {
// ...
});
我没有做任何关于登录的事情 app.module.ts
:
// app.module.ts
import { SomeController } from "@controller/some.controller";
import { Module } from "@nestjs/common";
import { SomeService } from "@service/some.service";
@Module({
controllers: [SomeController],
imports: [],
providers: [SomeService],
})
export class AppModule {
// ...
}
// some.controller.ts
import { Controller, Get, Inject, Param, ParseUUIDPipe, Post } from "@nestjs/common";
import { SomeService } from "@service/some.service";
import { WINSTON_MODULE_PROVIDER } from "nest-winston";
import { Logger } from "winston";
@Controller("/api/some-path")
export class SomeController {
constructor(@Inject(WINSTON_MODULE_PROVIDER) private readonly logger: Logger, private readonly service: SomeService) {
// ...
}
...
}
应用程序尝试启动但在某个时候失败:
2020-04-06T18:51:08.779Z [info] - Starting Nest application...
2020-04-06T18:51:08.787Z [error] - Nest can't resolve dependencies of the SomeController (?, SomeService). Please make sure that the argument winston at index [0] is available in the AppModule context.
Potential solutions:
- If winston is a provider, is it part of the current AppModule?
- If winston is exported from a separate @Module, is that module imported within AppModule?
@Module({
imports: [ /* the Module containing winston */ ]
})
尝试在根 AppModule 中导入 WinstonModule,如官方文档中所述:https://github.com/gremo/nest-winston:
import { Module } from '@nestjs/common';
import { WinstonModule } from 'nest-winston';
import * as winston from 'winston';
const logger: LoggerConfig = new LoggerConfig();
@Module({
imports: [WinstonModule.forRoot(logger.console())],
})
export class AppModule {}
为了不必复制记录器选项,创建某种 factory/Logging-Config 可能是个好主意。
import winston, { format, transports } from "winston";
export class LoggerConfig {
private readonly options: winston.LoggerOptions;
constructor() {
this.options = {
exitOnError: false,
format: format.combine(format.colorize(), format.timestamp(), format.printf(msg => {
return `${msg.timestamp} [${msg.level}] - ${msg.message}`;
})),
transports: [new transports.Console({ level: "debug" })], // alert > error > warning > notice > info > debug
};
}
public console(): object {
return this.options;
}
}
在 NestJs 项目中实现 Winston 自定义记录器
先决条件:
npm install --save nest-winston winston winston-daily-rotate-file
import { NestFactory } from '@nestjs/core';
import { WinstonModule } from 'nest-winston';
import * as winston from 'winston';
import * as winstonDailyRotateFile from 'winston-daily-rotate-file';
import { AppModule } from './app.module';
const transports = {
console: new winston.transports.Console({
level: 'silly',
format: winston.format.combine(
winston.format.timestamp({
format: 'YYYY-MM-DD HH:mm:ss',
}),
winston.format.colorize({
colors: {
info: 'blue',
debug: 'yellow',
error: 'red',
},
}),
winston.format.printf((info) => {
return `${info.timestamp} [${info.level}] [${
info.context ? info.context : info.stack
}] ${info.message}`;
}),
// winston.format.align(),
),
}),
combinedFile: new winstonDailyRotateFile({
dirname: 'logs',
filename: 'combined',
extension: '.log',
level: 'info',
}),
errorFile: new winstonDailyRotateFile({
dirname: 'logs',
filename: 'error',
extension: '.log',
level: 'error',
}),
};
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.useLogger(
WinstonModule.createLogger({
format: winston.format.combine(
winston.format.timestamp({
format: 'YYYY-MM-DD HH:mm:ss',
}),
winston.format.errors({ stack: true }),
winston.format.splat(),
winston.format.json(),
),
transports: [
transports.console,
transports.combinedFile,
transports.errorFile,
],
}),
);
await app.listen(4000);
}
bootstrap();
NestJs Winston NPM Documentation
Note
日志级别、文件名、日期格式您可以根据需要进行编辑。更多选项请关注官方文档。
我正在使用 NestJS 7.0.7
和 Winston 3.2.1
(使用 nest-winston 1.3.3
)。
我正在尝试将 Winston 集成到 NestJS 中,但到目前为止,我无法将记录器实例(实际记录任何内容)注入任何 controller/service.
因为我想在引导过程中跨应用程序 AND 使用 Winston,所以我使用 approach 作为主要的 Nest 记录器:
// main.ts
import { NestFactory } from "@nestjs/core";
import { WinstonModule } from "nest-winston";
import { format, transports } from "winston";
import { AppModule } from "./app.module";
async function bootstrap(): Promise<void> {
const app = await NestFactory.create(AppModule, {
logger: WinstonModule.createLogger({
exitOnError: false,
format: format.combine(format.colorize(), format.timestamp(), format.printf(msg => {
return `${msg.timestamp} [${msg.level}] - ${msg.message}`;
})),
transports: [new transports.Console({ level: "debug" })], // alert > error > warning > notice > info > debug
}),
});
app.use(helmet());
await app.listen(process.env.PORT || 3_000);
}
bootstrap().then(() => {
// ...
});
我没有做任何关于登录的事情 app.module.ts
:
// app.module.ts
import { SomeController } from "@controller/some.controller";
import { Module } from "@nestjs/common";
import { SomeService } from "@service/some.service";
@Module({
controllers: [SomeController],
imports: [],
providers: [SomeService],
})
export class AppModule {
// ...
}
// some.controller.ts
import { Controller, Get, Inject, Param, ParseUUIDPipe, Post } from "@nestjs/common";
import { SomeService } from "@service/some.service";
import { WINSTON_MODULE_PROVIDER } from "nest-winston";
import { Logger } from "winston";
@Controller("/api/some-path")
export class SomeController {
constructor(@Inject(WINSTON_MODULE_PROVIDER) private readonly logger: Logger, private readonly service: SomeService) {
// ...
}
...
}
应用程序尝试启动但在某个时候失败:
2020-04-06T18:51:08.779Z [info] - Starting Nest application...
2020-04-06T18:51:08.787Z [error] - Nest can't resolve dependencies of the SomeController (?, SomeService). Please make sure that the argument winston at index [0] is available in the AppModule context.
Potential solutions:
- If winston is a provider, is it part of the current AppModule?
- If winston is exported from a separate @Module, is that module imported within AppModule?
@Module({
imports: [ /* the Module containing winston */ ]
})
尝试在根 AppModule 中导入 WinstonModule,如官方文档中所述:https://github.com/gremo/nest-winston:
import { Module } from '@nestjs/common';
import { WinstonModule } from 'nest-winston';
import * as winston from 'winston';
const logger: LoggerConfig = new LoggerConfig();
@Module({
imports: [WinstonModule.forRoot(logger.console())],
})
export class AppModule {}
为了不必复制记录器选项,创建某种 factory/Logging-Config 可能是个好主意。
import winston, { format, transports } from "winston";
export class LoggerConfig {
private readonly options: winston.LoggerOptions;
constructor() {
this.options = {
exitOnError: false,
format: format.combine(format.colorize(), format.timestamp(), format.printf(msg => {
return `${msg.timestamp} [${msg.level}] - ${msg.message}`;
})),
transports: [new transports.Console({ level: "debug" })], // alert > error > warning > notice > info > debug
};
}
public console(): object {
return this.options;
}
}
在 NestJs 项目中实现 Winston 自定义记录器
先决条件:
npm install --save nest-winston winston winston-daily-rotate-file
import { NestFactory } from '@nestjs/core';
import { WinstonModule } from 'nest-winston';
import * as winston from 'winston';
import * as winstonDailyRotateFile from 'winston-daily-rotate-file';
import { AppModule } from './app.module';
const transports = {
console: new winston.transports.Console({
level: 'silly',
format: winston.format.combine(
winston.format.timestamp({
format: 'YYYY-MM-DD HH:mm:ss',
}),
winston.format.colorize({
colors: {
info: 'blue',
debug: 'yellow',
error: 'red',
},
}),
winston.format.printf((info) => {
return `${info.timestamp} [${info.level}] [${
info.context ? info.context : info.stack
}] ${info.message}`;
}),
// winston.format.align(),
),
}),
combinedFile: new winstonDailyRotateFile({
dirname: 'logs',
filename: 'combined',
extension: '.log',
level: 'info',
}),
errorFile: new winstonDailyRotateFile({
dirname: 'logs',
filename: 'error',
extension: '.log',
level: 'error',
}),
};
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.useLogger(
WinstonModule.createLogger({
format: winston.format.combine(
winston.format.timestamp({
format: 'YYYY-MM-DD HH:mm:ss',
}),
winston.format.errors({ stack: true }),
winston.format.splat(),
winston.format.json(),
),
transports: [
transports.console,
transports.combinedFile,
transports.errorFile,
],
}),
);
await app.listen(4000);
}
bootstrap();
NestJs Winston NPM Documentation
Note
日志级别、文件名、日期格式您可以根据需要进行编辑。更多选项请关注官方文档。