blanc-logger
TypeScript icon, indicating that this package has built-in type declarations

1.1.0 • Public • Published

Blanc Logger

Advanced Winston logger with TypeORM support & structured logging.

Blanc Logger는 NestJS 및 TypeORM 애플리케이션을 위한 고급 로깅 라이브러리입니다.
이 라이브러리는 Winston을 기반으로 콘솔 및 파일 로깅을 지원하며,
자동 구조화된 JSON 포맷, SQL 쿼리 하이라이팅, 모듈 기반 로그 추적 등 다양한 기능을 제공합니다.

npm version Node.js TypeScript License: MIT


Installation

npm install blanc-logger

Usage

1. NestJS 전역 Logger 적용 (main.ts)

Blanc Logger를 전역 로거로 적용하면, 애플리케이션 전체에서 동일한 로깅 설정을 사용할 수 있습니다.

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { blancLogger, BlancLoggerMiddleware } from 'blanc-logger';

async function bootstrap() {
  const app = await NestFactory.create(AppModule, {
    logger: blancLogger, // 전역 Logger 적용
  });

  // 미들웨어를 적용하여 요청 시 모듈명 등 컨텍스트 정보를 추가
  app.use(new BlancLoggerMiddleware().use); 

  await app.listen(3000);
}
bootstrap();

2. TypeORM Logger 적용 (AppModule)

TypeORM 설정에서 Blanc Logger의 전용 로거를 사용하여, SQL 쿼리 및 데이터베이스 관련 로그를 효과적으로 기록할 수 있습니다.

import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { TypeOrmBlancLogger } from 'blanc-logger';

@Module({
  imports: [
    TypeOrmModule.forRoot({
      // ... DB 설정
      logging: true,
      logger: new TypeOrmBlancLogger(), // TypeORM용 로거 사용
    }),
    // 다른 모듈들...
  ],
})
export class AppModule {}

기존 Logger 대체 방법

Blanc Logger를 사용하여 기존의 NestJS 내장 로거를 대체할 수 있습니다.

1. 기존 코드

// 기존 NestJS 내장 로거 사용:
this.logger.error('Error message', error.stack);
this.logger.log('Log message');

2. Blanc Logger 사용

// 에러 발생 시, 스택 정보와 함께 기록
blancLogger.error('Error message', { moduleName: 'ModuleName', stack: error.stack });
blancLogger.log('Log message', { moduleName: 'ModuleName' });
blancLogger.warn('Warn message', { moduleName: 'ModuleName' });
blancLogger.verbose('Verbose message', { moduleName: 'ModuleName' });
blancLogger.debug('Debug message', { moduleName: 'ModuleName' });

3. Logs 파일

로그 파일이 자동으로 날짜별로 생성되어 logs 폴더 아래에 다음과 같이 쌓입니다.

logs/
├── combined-2025-03-03.log   # 모든 로그 메시지
├── error-2025-03-03.log      # error 레벨 로그
├── exceptions-2025-03-03.log # 처리되지 않은 예외 로그
└── rejections-2025-03-03.log # 미처리된 Promise 거부 로그

예시 로그 (error-2025-03-03.log 파일):

{"level":"error","message":"HTTP Exception: DUPLICATION","stack":[{"moduleName":"user","path":"/api/user/profile","stack":"ConflictException: DUPLICATION\n    at UserService.getProfile (/path/to/src/user/user.service.ts:60:13)\n    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)"}],"timestamp":"2025-03-03 14:29:51"}

Overview

Feature Description
다중 전송 로깅 (Multi-Transport Logging) - 콘솔 출력과 파일 저장을 동시에 지원
- 일정 크기(예: 20MB) 또는 일정 주기(예: 15일)에 따라 자동으로 로그 파일 회전
- 로그 파일 예시: combined-YYYY-MM-DD.log, error-YYYY-MM-DD.log, exceptions-YYYY-MM-DD.log, rejections-YYYY-MM-DD.log
구조화된 로그 출력 (Structured Logging) - UUIDv5를 사용해 고유 LogID 생성
- {timestamp, level, message} 형식의 표준 JSON 포맷으로 출력되어 외부 시스템 연동 용이
모듈별 컨텍스트 추적 (Contextual Tracing) - BlancLoggerMiddleware를 활용하여 HTTP 요청에서 모듈명 자동 추출
- [UserService → AuthModule → Subsystem]과 같이 계층 구조로 표시
동적 로그 레벨 관리 (Dynamic Log Levels) - 개발 및 운영 환경에 따라 debug, verbose, info, warn, error 로그 레벨을 실시간으로 조절 가능
- 필요한 정보만 선별 기록하여 로그의 가독성과 관리 효율성을 향상
SQL 구문 하이라이팅 (SQL Syntax Highlighting) - SQL 쿼리의 키워드, 값, 테이블명을 색상 강조 및 들여쓰기로 구분
- 파라미터 값 컨텍스트 인식 강조
쿼리 성능 분석 (Query Analysis) - SQL 성능 저하 유발 패턴 자동 감지 (SELECT *, JOIN 조건 누락 등)
에러 진단 및 스택 추적 (Error Diagnostics) - 에러 발생 시 다중 스택 레이어와 추가 메타데이터를 포함하여 상세한 에러 로그 기록
성능 모니터링 (Performance Monitoring) - HTTP 요청 처리 시간 및 Slow Query(예: 500ms) 경고 로그 생성
- 실행 계획(Explain Plan) 리포트 시각화
커스터마이징 (Customization) - logger-config.yaml파일을 통해 로그 저장 경로, 로그 레벨, 파일 크기, 회전 주기 등을 쉽게 조정 가능

Configuration

Blanc Logger는 기본 설정을 제공하지만, 필요에 따라 사용자 환경에 맞게 커스터마이징 할 수 있습니다.
설정을 변경하려면 프로젝트 루트logger-config.yaml 파일을 생성하고 아래와 같이 Override할 수 있습니다.

LOG_DIR: logs            # 로그 파일 저장 경로 (기본: 프로젝트 루트/logs)
CONSOLE_LOG_LEVEL: info  # 콘솔 출력 로그 레벨 (debug, verbose, info, warn, error)
FILE_LOG_LEVEL: error    # 파일 출력 로그 레벨 (debug, verbose, info, warn, error)
ROTATION_DAYS: 30d       # 로그 파일 보관 기간 (예: 30일)
MAX_FILE_SIZE: 20m       # 단일 파일 최대 크기 (예: 20MB)

Log Output Examples

SQL Query Log Example

╔═ SQL Query ═════════════════════════════════
    SELECT
        "user"."id" AS "userId",
        "user"."email" AS "userEmail"
    FROM "user" "user"
    WHERE "user"."age" > $1
╠═ Parameters ═══════════════════════════════
    [18]
╠═ Analysis ═════════════════════════════════
    ⚠️ Avoid SELECT * - specify columns explicitly
╚═════════════════════════════════════════════

Console Output Log Example

blanc-logger-output-log


Console Error Log Example

blanc-logger-error-log


Using Examples

1. Logging Interceptor 구현

HTTP 요청 처리 시간을 측정하여 로그로 기록하는 인터셉터 예제입니다.
BlancLoggerMiddleware를 통해 설정된 모듈명 정보가 자동으로 포함됩니다.

import { CallHandler, ExecutionContext, Injectable, NestInterceptor } from '@nestjs/common';
import { blancLogger } from 'blanc-logger';
import * as chalk from 'chalk';
import { Observable } from 'rxjs';
import { tap } from 'rxjs/operators';

@Injectable()
export class LoggingInterceptor implements NestInterceptor {
  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    const startTime = Date.now();
    const req = context.switchToHttp().getRequest();
    const decodedUrl = decodeURIComponent(req.url);
    const moduleName = (req as any).moduleName || 'UnknownModule';

    return next.handle().pipe(
      tap(() => {
        const delay = Date.now() - startTime;
        const delayStr =
          delay > 500 ? chalk.bold.red(`${delay}ms 🚨`) : chalk.magenta(`${delay}ms`);
        const message = `Request processed: ${chalk.yellow(req.method)} ${chalk.green(
          decodedUrl,
        )} ${delayStr}`;
        blancLogger.log(message, moduleName);
      }),
    );
  }
}

전역 인터셉터로 적용하려면 AppModule에 아래와 같이 등록합니다

import { Module } from '@nestjs/common';
import { APP_INTERCEPTOR } from '@nestjs/core';
import { LoggingInterceptor } from './commons/interceptors/logging.interceptor';

@Module({
  providers: [
    {
      provide: APP_INTERCEPTOR,
      useClass: LoggingInterceptor, // 전역 인터셉터로 등록
    },
  ],
})
export class AppModule {}

Console Output Log Example
- 응답 시간 (예: 500ms) 초과 시 강조

blanc-logger-output-log


2. Global Exception Filter 구현

Blanc Logger를 사용하여 예외 발생 시 상세한 에러 정보를 로그로 기록하는 전역 익셉션 필터 예제입니다.
BlancLoggerMiddleware를 통해 설정된 모듈명 정보가 자동으로 포함됩니다.

import {
  ArgumentsHost,
  Catch,
  ExceptionFilter,
  HttpException,
  InternalServerErrorException,
} from '@nestjs/common';
import { blancLogger } from 'blanc-logger';
import { Request, Response } from 'express';

interface ExceptionResponse {
  status: number;
  message: string;
  stack?: string;
}

/** 예외 객체를 처리하여 상태, 메시지, 스택을 반환하는 함수 */
const handleException = (exception: unknown, _request: Request): ExceptionResponse => {
  if (exception instanceof HttpException) {
    const status = exception.getStatus();
    const res = exception.getResponse();
    const message =
      typeof res === 'object' && res !== null
        ? (res as any).message ?? exception.message
        : exception.message;
    return {
      status,
      message: `HTTP Exception: ${message}`,
      stack: exception instanceof Error ? exception.stack : '',
    };
  }
  if (exception instanceof Error) {
    const status = new InternalServerErrorException().getStatus();
    return {
      status,
      message: `Unhandled exception: ${exception.message}`,
      stack: exception.stack,
    };
  }
  return { status: 500, message: 'Unknown error' };
};

@Catch()
export class GlobalExceptionFilter implements ExceptionFilter {
  catch(exception: unknown, host: ArgumentsHost): void {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse<Response>();
    const request = ctx.getRequest<Request>();

    const moduleName = (request as any)?.moduleName ?? 'Global';
    const { status, message, stack } = handleException(exception, request);

    blancLogger.error(message, {
      moduleName,
      path: request.url,
      stack,
    });

    response.status(status).json({
      statusCode: status,
      status: message,
      timestamp: new Date().toISOString(),
      path: request.url,
    });
  }
}

전역 필터로 적용하려면 AppModule에 아래와 같이 등록합니다

import { Module } from '@nestjs/common';
import { APP_FILTER } from '@nestjs/core';
import { GlobalExceptionFilter } from './commons/filters/global-exception.filter';

@Module({
  providers: [
    {
      provide: APP_FILTER,
      useClass: GlobalExceptionFilter, // 전역 필터로 등록
    },
  ],
})
export class AppModule {}

전역 익셉션 필터를 적용한 후, 다음과 같이 예외를 던질 경우

throw new ConflictException('DUPLICATION');

Console Output Log Example

blanc-logger-output-log

또한, 동일하게 로그 파일도 생성됩니다.

{"level":"error","message":"HTTP Exception: DUPLICATION","stack":[{"moduleName":"user","path":"/api/user/profile","stack":"ConflictException: DUPLICATION\n    at UserService.getProfile (/path/to/src/user/user.service.ts:60:13)\n    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)"}],"timestamp":"2025-03-03 14:29:51"}

License

이 프로젝트는 MIT License에 따라 배포 및 사용이 가능합니다.


Package Sidebar

Install

npm i blanc-logger

Weekly Downloads

17

Version

1.1.0

License

MIT

Unpacked Size

39.4 kB

Total Files

19

Last publish

Collaborators

  • iamblanc