Bỏ qua, đến nội dung

@digiforce-nc/logger

Package@digiforce-nc/logger
Importimport { createLogger, createSystemLogger, requestLogger } from '@digiforce-nc/logger'

Tổng quan

@digiforce-nc/logger là thư viện logging tập trung của hệ thống Digiforce, xây dựng trên nền Winston. Package cung cấp:

  • Logger factory - tạo logger instance với cấu hình linh hoạt.
  • System logger - logger có sẵn context ứng dụng (app name, module).
  • Request logger - Koa middleware ghi log request/response.
  • Transport - hỗ trợ console, file, daily rotate file.
  • Cấu hình qua biến môi trường - dễ dàng tuỳ chỉnh theo environment.

Standalone

@digiforce-nc/logger không phụ thuộc vào bất kỳ package core nào khác. Có thể sử dụng độc lập trong bất kỳ project Node.js nào.


Kiến trúc


API

createLogger(options)

Tạo Winston logger instance với cấu hình tuỳ chỉnh.

OptionTypeMặc địnhMô tả
levelstring'info'Log level tối thiểu.
transportsTransport[][console]Danh sách transport.
formatFormatlogfmtFormat output.
dirnamestring-Thư mục chứa log file.
filenamestring-Tên file log.
typescript
import { createLogger } from '@digiforce-nc/logger';

const logger = createLogger({
  level: 'debug',
  transports: ['console', 'file'],
  dirname: '/var/log/myapp',
  filename: 'app.log',
});

logger.info('Application started');
logger.error('Something went wrong', { code: 'ERR_001', detail: '...' });

createConsoleLogger()

Tạo logger chỉ output ra console - tiện cho development:

typescript
import { createConsoleLogger } from '@digiforce-nc/logger';

const logger = createConsoleLogger();
logger.info('Dev mode active');
logger.debug('Variable value:', { x: 42 });

createSystemLogger(options)

Tạo system logger với context ứng dụng (app name, module name). Đây là loại logger chính sử dụng trong các core module.

OptionTypeMô tả
appstringTên ứng dụng - dùng trong log message và tên file.
modulestringTên module - phân biệt nguồn log.
levelstringLog level. Mặc định đọc từ LOGGER_LEVEL.
transportsstring | string[]Transport. Mặc định đọc từ LOGGER_TRANSPORT.
formatstringFormat. Mặc định đọc từ LOGGER_FORMAT.
typescript
import { createSystemLogger } from '@digiforce-nc/logger';

const logger = createSystemLogger({
  app: 'digiforce',
  module: 'auth',
});

logger.info('User signed in', { userId: 123, method: 'email' });
// Output: 2024-03-15 10:30:00 [digiforce:auth] info: User signed in userId=123 method=email

requestLogger(name, options)

Trả về Koa middleware ghi log cho mỗi HTTP request/response.

OptionTypeMô tả
namestringTên logger (dùng cho file name).
skip(ctx) => booleanHàm bỏ qua log cho một số request.
requestWhiteliststring[]Các field request cần log.
responseWhiteliststring[]Các field response cần log.
typescript
import { requestLogger } from '@digiforce-nc/logger';

app.use(requestLogger('api', {
  skip: (ctx) => ctx.path === '/api/health',
  requestWhitelist: ['method', 'url', 'headers.user-agent'],
  responseWhitelist: ['status', 'body.error'],
}));

Mỗi request sẽ được ghi log khi hoàn thành:

2024-03-15 10:30:01 [api] info: POST /api/users:create 201 45ms
2024-03-15 10:30:02 [api] warn: GET /api/posts:list 403 12ms
2024-03-15 10:30:05 [api] error: PUT /api/orders/99 500 230ms error="Internal Server Error"

Utility functions

FunctionMô tả
getLoggerLevel()Đọc log level từ LOGGER_LEVEL env. Mặc định 'info'.
getLoggerFilePath(app)Trả về đường dẫn thư mục log. Mặc định storage/logs/<app>. Đọc từ LOGGER_BASE_PATH.
getLoggerTransport()Đọc transport config từ LOGGER_TRANSPORT env. Mặc định 'console'.
getLoggerFormat()Đọc format config từ LOGGER_FORMAT env. Mặc định 'logfmt'.

SystemLogger

SystemLogger mở rộng Winston logger với context ứng dụng. Mỗi Application instance có một app.logger là SystemLogger.

Mỗi plugin nên tạo logger riêng với module name:

typescript
class MyPlugin extends Plugin {
  async load() {
    const logger = createSystemLogger({
      app: this.app.name,
      module: 'my-plugin',
    });

    logger.info('Plugin loaded');
    logger.debug('Config:', this.options);
  }
}

Transport types

Console

Output ra stdout/stderr với màu sắc (development).

typescript
const logger = createLogger({
  transports: ['console'],
});

File

Ghi log vào file cố định, tự động rotate khi đạt maxsize.

typescript
const logger = createLogger({
  transports: ['file'],
  dirname: 'storage/logs',
  filename: 'app.log',
});

Daily Rotate File

Tự động tạo file log mới mỗi ngày, xoá file cũ sau maxFiles ngày.

typescript
const logger = createLogger({
  transports: ['dailyRotateFile'],
  dirname: 'storage/logs',
  filename: 'app-%DATE%.log',
});
OptionMặc địnhMô tả
datePattern'YYYY-MM-DD'Pattern ngày trong tên file
maxSize'20m'Kích thước tối đa mỗi file
maxFiles'14d'Giữ log trong 14 ngày

Production recommendation

Trong production, nên dùng dailyRotateFile kết hợp console:

bash
LOGGER_TRANSPORT=console,dailyRotateFile

Log levels

Theo thứ tự ưu tiên giảm dần:

LevelSốDùng khi
error0Lỗi nghiêm trọng, ứng dụng không thể xử lý
warn1Cảnh báo - vẫn chạy được nhưng cần chú ý
info2Thông tin quan trọng - startup, shutdown, request summary
debug3Thông tin chi tiết - chỉ bật khi debug

Khi set level: 'warn', chỉ log errorwarn được ghi.

Performance

Level debug có thể tạo rất nhiều output. Chỉ bật trong development hoặc khi debug issue cụ thể. Trong production, dùng info hoặc warn.


Biến môi trường

BiếnMô tảGiá trị hợp lệMặc định
LOGGER_LEVELLog level tối thiểuerror, warn, info, debuginfo
LOGGER_TRANSPORTTransport types (phân cách bằng ,)console, file, dailyRotateFileconsole
LOGGER_FORMATOutput formatlogfmt, json, delimiter, consolelogfmt
LOGGER_BASE_PATHThư mục gốc chứa log fileĐường dẫn tuyệt đối hoặc tương đốistorage/logs

Format types

FormatMô tảVí dụ output
logfmtKey-value pairs, dễ parse bằng toollevel=info msg="User created" userId=123 ts=2024-03-15T10:30:00Z
jsonJSON structured, tốt cho log aggregator{"level":"info","message":"User created","userId":123}
delimiterPipe-delimited2024-03-15 10:30:00 | info | User created | userId=123
consoleHuman-friendly với màu sắc[10:30:00] INFO: User created { userId: 123 }

Chọn format

  • Development: console - dễ đọc với highlight màu.
  • Production: json hoặc logfmt - dễ parse bằng ELK/Grafana/Datadog.

Ví dụ tổng hợp

Tạo logger cho application

typescript
import {
  createSystemLogger,
  createLogger,
  requestLogger,
  getLoggerLevel,
  getLoggerTransport,
  getLoggerFilePath,
} from '@digiforce-nc/logger';

// 1. System logger cho app core
const appLogger = createSystemLogger({
  app: 'digiforce',
  module: 'core',
});

appLogger.info('Application initializing...');

// 2. Custom logger cho module cụ thể
const emailLogger = createLogger({
  level: 'debug',
  transports: ['file', 'console'],
  dirname: getLoggerFilePath('digiforce'),
  filename: 'email.log',
});

emailLogger.info('Sending email', { to: 'user@example.com', template: 'welcome' });
emailLogger.error('Email send failed', { error: err.message, stack: err.stack });

// 3. Request logging middleware
app.use(requestLogger('http', {
  skip: (ctx) => ctx.path.startsWith('/health'),
}));

Cấu hình theo environment

bash
# Development
LOGGER_LEVEL=debug
LOGGER_TRANSPORT=console
LOGGER_FORMAT=console

# Staging
LOGGER_LEVEL=info
LOGGER_TRANSPORT=console,dailyRotateFile
LOGGER_FORMAT=logfmt
LOGGER_BASE_PATH=/var/log/digiforce

# Production
LOGGER_LEVEL=warn
LOGGER_TRANSPORT=dailyRotateFile
LOGGER_FORMAT=json
LOGGER_BASE_PATH=/var/log/digiforce

Custom transport

typescript
import { createLogger } from '@digiforce-nc/logger';
import winston from 'winston';

const logger = createLogger({
  level: 'info',
  transports: [
    new winston.transports.Console(),
    new winston.transports.Http({
      host: 'log-collector.internal',
      port: 8080,
      path: '/logs',
    }),
  ],
});

Phụ thuộc

@digiforce-nc/logger là package standalone - không phụ thuộc vào bất kỳ package core nào khác.

Dependencies ngoài:

PackageVai trò
winstonLogger engine
winston-daily-rotate-fileDaily rotate file transport

Đọc thêm