npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

blanc-logger

v1.1.0

Published

Advanced Winston logger for NestJS & TypeORM with structured logging.

Readme

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


Console Error Log Example


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) 초과 시 강조


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

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

{"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에 따라 배포 및 사용이 가능합니다.