npm i nest-winston winston
winston-daily-rotate-file
추가 설치npm i winston-daily-rotate-file
.env
에서 NODE_ENV
, APP_NAME
, LOG_DIR
등 환경변수 설정하여 활용AppModule
에서 정의해도 되지만, logger 를 위한 module을 만들고 import 하는 것이 개발 및 테스트하기 좋다.import * as winston from 'winston';
import {
utilities as nestWinstonModuleUtilities,
WinstonModule,
} from 'nest-winston';
import * as winstonDaily from 'winston-daily-rotate-file'
@Module{(
imports: [
ConfigModule.forRoot({ isGlobal: true})
WinstonModule.forRoot({
transports: [
new winston.transports.Console({
level: process.env.NODE_ENV === 'production' ? 'info' : 'silly',
format: winston.format.combine(
winston.format.timestamp(),
nestWinstonModuleUtilities.format.nestLike(process.env.APP_NAME, { prettyPrint: true }),
),
}),
new winstonDaily ({
level: process.env.NODE_ENV === 'production' ? 'info' : 'silly',
format: winston.format.combine(
winston.format.timestamp({
format: 'YYYY-MM-DD HH:mm:ss',
}),
winston.format.printf(
(info) =>
`[${info.timestamp}] ${process.env.APP_NAME}.${info.level}: ${info.message}`,
),
),
dirname: process.env.LOG_DIR
filename: '%DATE%.log',
datePattern: 'YYYY-MM-DD',
zippedArchive: true,
maxSize: '20m',
maxFiles: '14d',
}),
],
}),
],
})
export class LoggerModule { }
@Module({
imports: [
ConfigModule.forRoot({ isGlobal: true }),
LoggerModule,
...
],
...
})
export class AppModule() {
...
}
import { Logger } from 'winston';
import { WINSTON_MODULE_PROVIDER } from 'nest-winston';
...
export class UsersController {
constructor(
@Inject(WINSTON_MODULE_PROVIDER) private readonly logger: Logger,
) { }
private printWinstonLog(dto) {
console.log(this.logger.name);
this.logger.error('error: ', dto);
this.logger.warn('warn: ', dto);
this.logger.info('info: ', dto);
this.logger.http('http: ', dto);
this.logger.verbose('verbose: ', dto);
this.logger.debug('debug: ', dto);
this.logger.silly('silly: ', dto);
}
생성자를 통해 winston 의 Logger 를 주입하기 때문에, 테스트코드에도 이를 반영해야 한다.
describe(‘UserController’, () => {
let userController: UserController
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
imports: [ConfigModule],
providers: [
ConfigService,
{ provide: WINSTON_MODULE_PROVIDER, useValue: {
silly: jest.fn(),
debug: jest.fn(),
verbose: jest.fn(),
http: jest.fn(),
info: jest.fn(),
warn: jest.fn(),
error: jest.fn(),
log: jest.fn()
}, // winston logger
...
],
controllers: [
UserController
]
}).compile()
userController = module.get<UserController>(UserController)
})
it('should be defined', () => {
expect(userController).toBeDefined()
})
describe(‘UserController’, () => {
let userController: UserController
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
imports: [ConfigModule, LoggerModule],
providers: [
ConfigService,
...
],
controllers: [
UserController
]
}).compile()
userController = module.get<UserController>(UserController)
})
it('should be defined', () => {
expect(userController).toBeDefined()
})