NestJS Winston Logger Module with HTTP Request/Response Logging
- ๐ฏ Winston ๊ธฐ๋ฐ ๋ก๊น ๋ชจ๋
- ๐ HTTP ์์ฒญ/์๋ต ๊ฐ๊ฒฐํ ๋ก๊น (method, url, statusCode, responseTime)
- โฑ๏ธ ์๋ต ์๊ฐ ์ธก์ (์ด ๋จ์)
# pnpm
pnpm add git+https://github.com/dsrvlabs/nest-logger.git
# npm
npm install git+https://github.com/dsrvlabs/nest-logger.git
# yarn
yarn add git+https://github.com/dsrvlabs/nest-logger.git์ฐธ๊ณ : ๋น๋๋ ํ์ผ์ด ํฌํจ๋์ด ์์ด pnpm approve-builds ์์ด ๋ฐ๋ก ์ฌ์ฉํ ์ ์์ต๋๋ค.
import { Module } from '@nestjs/common';
import { LoggerModule } from 'nest-logger';
@Module({
imports: [LoggerModule],
// ...
})
export class AppModule {}import { Module, NestModule, MiddlewareConsumer } from '@nestjs/common';
import { LoggerModule, HttpLoggerMiddleware } from 'nest-logger';
@Module({
imports: [LoggerModule],
})
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer.apply(HttpLoggerMiddleware).forRoutes('*');
}
}๋๋ ํน์ ๊ฒฝ๋ก์๋ง ์ ์ฉ:
import { Module, NestModule, MiddlewareConsumer } from '@nestjs/common';
import { LoggerModule, HttpLoggerMiddleware } from 'nest-logger';
@Module({
imports: [LoggerModule],
})
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer.apply(HttpLoggerMiddleware).forRoutes('api/*'); // ํน์ ๊ฒฝ๋ก์๋ง ์ ์ฉ
}
}import { Injectable } from '@nestjs/common';
import { LoggerService } from 'nest-logger';
@Injectable()
export class YourService {
constructor(private readonly logger: LoggerService) {}
someMethod() {
// context์ ํจ์ ์ด๋ฆ์ ๋ช
์์ ์ผ๋ก ์ ๋ฌ
this.logger.log(
'Info message',
`${this.constructor.name}.${this.someMethod.name}`,
);
this.logger.error(
'Error message',
'stack trace',
`${this.constructor.name}.${this.someMethod.name}`,
);
this.logger.warn(
'Warning message',
`${this.constructor.name}.${this.someMethod.name}`,
);
this.logger.debug(
'Debug message',
`${this.constructor.name}.${this.someMethod.name}`,
);
this.logger.verbose(
'Verbose message',
`${this.constructor.name}.${this.someMethod.name}`,
);
}
// ๋๋ ํด๋์ค ์ด๋ฆ๋ง ์ฌ์ฉ
anotherMethod() {
this.logger.log('Info message', this.constructor.name);
}
// ๋๋ ํจ์ ์ด๋ฆ๋ง ์ฌ์ฉ
thirdMethod() {
this.logger.log('Info message', this.thirdMethod.name);
}
}winston Logger ์ธ์คํด์ค๋ฅผ ์ง์ ์ฃผ์ ๋ฐ์ ์ฌ์ฉํ ์ ์์ต๋๋ค:
import { Injectable, Inject } from '@nestjs/common';
import { WINSTON_MODULE_PROVIDER } from 'nest-logger';
import type { Logger } from 'winston';
@Injectable()
export class YourService {
constructor(
@Inject(WINSTON_MODULE_PROVIDER) private readonly logger: Logger,
) {}
someMethod() {
// winston Logger์ ๋ชจ๋ ๋ฉ์๋ ์ฌ์ฉ ๊ฐ๋ฅ
this.logger.info('Info message', { context: 'YourService', userId: 123 });
j;
this.logger.error('Error message', {
error: new Error('Something went wrong'),
});
this.logger.warn('Warning message', { data: { key: 'value' } });
this.logger.debug('Debug message', { metadata: 'some data' });
// winston์ ๊ณ ๊ธ ๊ธฐ๋ฅ ์ฌ์ฉ
this.logger.log({
level: 'info',
message: 'Custom log',
timestamp: new Date().toISOString(),
metadata: { custom: 'data' },
});
}
}๋๋ LoggerService๋ฅผ ํตํด winston Logger ์ธ์คํด์ค ๊ฐ์ ธ์ค๊ธฐ:
import { Injectable } from '@nestjs/common';
import { LoggerService } from 'nest-logger';
@Injectable()
export class YourService {
constructor(private readonly loggerService: LoggerService) {}
someMethod() {
const winstonLogger = this.loggerService.getWinstonLogger();
// winston Logger ์ง์ ์ฌ์ฉ
winstonLogger.info('Info message', { context: 'YourService' });
winstonLogger.error('Error message', { error: new Error('Error') });
}
}HTTP ์์ฒญ/์๋ต ๋ก๊ทธ๋ ์ค๋ฐ๊ฟ ์์ด ํ ์ค๋ก ์ถ๋ ฅ๋ฉ๋๋ค.
2024-01-01 12:00:00 info [HttpLogger] REQ {"method":"GET","url":"/api/users","body":{"name":"test"},"query":{"page":"1"},"params":{"id":"123"}}
2024-01-01 12:00:00 info [HttpLogger] RES {"method":"GET","url":"/api/users","statusCode":200,"responseTime":"0.123s","body":{"data":"result"}}
import { LoggerModule } from 'nest-logger';
import * as winston from 'winston';
@Module({
imports: [
LoggerModule.forRoot({
transports: [
new winston.transports.File({
filename: 'error.log',
level: 'error',
}),
new winston.transports.Console(),
],
}),
],
})
export class AppModule {}ํ๋ก์ ํธ๋ฅผ ์์ ํ ํ GitHub์ ํธ์ํ๊ธฐ ์ ์ ๋ฐ๋์ ๋น๋๋ฅผ ์คํํด์ผ ํฉ๋๋ค:
# ๋น๋ ์คํ
pnpm build
# ๋๋ prepush ์คํฌ๋ฆฝํธ ์ฌ์ฉ (๋น๋ + git add dist/)
pnpm run prepush
# ์ปค๋ฐ ๋ฐ ํธ์
git commit -m "Your changes"
git push์ค์: ์์ค ์ฝ๋(src/)๋ฅผ ์์ ํ ๊ฒฝ์ฐ ๋ฐ๋์ ๋น๋ ํ ํธ์ํด์ผ ํฉ๋๋ค. ๊ทธ๋ ์ง ์์ผ๋ฉด ๋ค๋ฅธ ํ๋ก์ ํธ์์ ์ค๋๋ ๋น๋ ํ์ผ์ ์ฌ์ฉํ๊ฒ ๋ฉ๋๋ค.
์๋์ผ๋ก ๋น๋ํ๋ ค๋ฉด .git/hooks/pre-push hook์ ์ค์ ํ ์ ์์ต๋๋ค:
chmod +x .git/hooks/pre-push์ด๋ ๊ฒ ํ๋ฉด git push ์ ์๋์ผ๋ก ๋น๋๊ฐ ์คํ๋ฉ๋๋ค.
MIT