nestjs 를 사용하면서 내장 로거로 로그를 남길 수 있는데 파일 저장은 지원하지 않기 때문에
winston 이라는 패키지를 사용해 로그를 파일로 기록 해야 한다
npm i nest-winston winston winston-daily-rotate-file
winston-daily-ratate-file 패키지와 함께 사용하면 로그파일을 날짜별로 관리 할 수 있다
그 다음 src 폴더 아래에 utils 라는 폴더를 생성하고 winston.util.ts 파일을 생성한다
import { utilities, WinstonModule } from 'nest-winston'
import * as winstonDaily from 'winston-daily-rotate-file'
import * as winston from 'winston'
const logDir = 'logs'
const createDailyLogFile = (
level: string,
): winstonDaily.DailyRotateFileTransportOptions => {
return {
level,
datePattern: 'YYYY-MM-DD',
format: winston.format.combine(
winston.format.timestamp({
format: 'YYYY-MM-DD HH:mm:ss',
}),
winston.format.json(),
),
dirname: logDir + `/${level}`,
filename: `%DATE%.${level}.log`, // 날짜-로그레벨 명으로 파일 생성
maxFiles: 30, // 30일치 로그 저장
zippedArchive: true, // 로그가 쌓이면 압축해서 관리
}
}
const color = {
error: 'red',
warn: 'yellow',
info: 'green',
}
winston.addColors(color)
// error: 0, warn: 1, info: 2, http: 3, verbose: 4, debug: 5, silly: 6
export const winstonLogger = WinstonModule.createLogger({
transports: [
new winston.transports.Console({
level: process.env.DEV_TYPE === 'dev' ? 'silly' : 'info',
format: winston.format.combine(
winston.format.colorize({ all: true }),
winston.format.timestamp(),
utilities.format.nestLike('프로젝트명', {
prettyPrint: true,
}),
),
}),
new winstonDaily(createDailyLogFile('info')),
new winstonDaily(createDailyLogFile('warn')),
new winstonDaily(createDailyLogFile('error')),
],
})
createDailyLogFile 함수는 로그 레벨별로 파일을 생성하기 위해 함수로 만들었다
그리고 color 옵션을 설정하기 위해 각 로그레벨 별로 컬러를 설정하고 winston.addColors에 넣어주면 된다
그 다음 윈스턴로거 인스턴스를 생성해 주면 된다
new winstonDaily 각 로그레벨별 파일을 만들어 저장한다
이제 윈스턴로거 인스턴스를 main.ts 에 주입해줘야 하는데 nest 기본 로거를 윈스턴로거로 교체 하는 작업이다
async function bootstrap() {
const app = await NestFactory.create(AppModule, {
logger: winstonLogger,
})
const PORT = process.env.WEB_PORT
await app.listen(PORT)
}
bootstrap()
main.ts 에 우리가 만든 윈스턴로거 인스턴스를 기본로거로 사용하겠다고 명시해 주면 된다
이 방법을 사용 하면 app.module.ts 파일에 WinstonModule.forRoot로 설정을 하면 안된다
Important: by doing this, you give up the dependency injection, meaning that forRoot and forRootAsync are not needed and shouldn't be used. Remove them from your main module.
위 처럼 공식문서에 나와 있는 내용이다
그런 다음 서버를 시작해 보면 아래와 같이 로그 파일들이 잘 생성이 되었을 것이다
그 다음 app.module.ts 파일에 Logger를 provider 시켜 줘야 한다
import { Logger, Module } from '@nestjs/common';
@Module({
providers: [Logger],
})
export class AppModule {}
그럼 이제 윈스톤 로거를 사용할 준비가 끝났다
로거를 사용하려는 소스파일에서 아래와 같이 호출해서 사용하면 된다
import { Controller, Get, Logger } from '@nestjs/common'
@Controller()
export class AppController {
constructor(private readonly logger: Logger) {}
@Get('')
getMain() {
this.logger.error('error Test', 'error', AppController.name)
this.logger.warn('warn Test', AppController.name)
this.logger.log('info Test', AppController.name)
return 'hello world'
}
}
위 방법 말고 공식문서에서는 아래와 같은 방법도 지원한다
import { Controller, Inject, Logger, LoggerService } from '@nestjs/common';
@Controller()
export class AppController {
constructor(@Inject(Logger) private readonly logger: LoggerService) {}
}
@Inject 데코레이터를 활용해 LoggerService를 사용 할 수도 있다
이렇게 하면 모든 설정이 끝났고 윈스턴으로 로그파일을 관리 할 수 있게 되었다
만약 라우트 핸들러를 지나기 전에 로그를 남길 필요가 있다면 미들웨어 설정을 해주면 된다
src/middleware/logger.middleware.ts
import {
Inject,
Injectable,
Logger,
LoggerService,
NestMiddleware,
} from '@nestjs/common'
import { Request, Response, NextFunction } from 'express'
@Injectable()
export class LoggerMiddleware implements NestMiddleware {
constructor(@Inject(Logger) private readonly logger: LoggerService) {}
use(req: Request, res: Response, next: NextFunction) {
const { ip, method, originalUrl } = req
const { statusCode } = res
this.logger.log(`${method} ${originalUrl} ${statusCode} ${ip}`)
next()
}
}
사용자가 요청한 정보등을 로그로 남긴 후에 라우터로 넘겨주는 미들웨어이다
app.module.ts
import { Logger, Module, NestModule, MiddlewareConsumer } from '@nestjs/common';
import { LoggerMiddleware } from './middleware/logger.middleware'
@Module({
providers: [Logger],
})
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer.apply(LoggerMiddleware).forRoutes('*')
}
}
미들웨어 파일을 생성한 후에 app.module.ts 파일에 위와 같이 설정해 주면 라우터 핸들러를 지나기 전에 미들웨어에서 로그를 먼저 처리 할 수 있다
'프로그래밍 > node.js' 카테고리의 다른 글
[node.js] parcel-bundler 개발 및 빌드 (0) | 2021.08.12 |
---|---|
[node.js] ESLint + Prettier + Airbnb 설정 하기 (0) | 2021.07.24 |