NestJS Logging 完整指南:從內建 Logger 到 Winston 整合
本文內容基於 NestJS v10.x 與 Winston v3.x 撰寫。NestJS 的 Logger API 在 v8 以後保持穩定,Winston 的核心 API 在 v3 以後也沒有重大變動。如果使用較早的版本,部分 API 可能有所不同,建議參考對應版本的官方文件。
日誌(Logging)是後端開發中不可或缺的一環。無論是除錯、監控還是追蹤問題,一個設計良好的日誌系統都能讓開發事半功倍。NestJS 內建了一套簡潔的日誌機制,同時也提供了高度彈性讓開發者整合第三方日誌套件。
這篇文章會從最基礎的內建 Logger 開始,一步步說明如何自定義 Logger,最後介紹如何整合業界常用的 Winston 日誌套件。
NestJS 內建 Logger
NestJS 內建的 Logger 類別位於 @nestjs/common,開箱即用,不需要額外安裝任何套件。它提供了五種日誌等級,並會在終端機以不同顏色呈現。對於大多數的開發場景來說,內建 Logger 已經足夠使用;只有當需要更進階的功能(如寫入檔案、傳送到遠端服務)時,才需要考慮第三方套件。
基本使用方式
在 Service、Controller 或任何地方使用 NestJS 內建 Logger 的方式非常直覺。我們可以在類別中建立一個 private readonly logger 屬性,並在建構時傳入類別名稱作為 context。這個 context 會出現在每條日誌的中括號中,方便開發者快速辨識這條日誌是從哪個模組發出的。
import { Injectable, Logger } from '@nestjs/common';
@Injectable()
export class UsersService {
private readonly logger = new Logger(UsersService.name);
findAll() {
this.logger.log('正在查詢所有使用者');
// ... 業務邏輯
}
findOne(id: string) {
this.logger.debug(`查詢使用者 ID: ${id}`);
// ...
}
create(dto: CreateUserDto) {
this.logger.warn('這是一個警告訊息');
this.logger.verbose('這是 verbose 層級的訊息');
}
}
執行後,終端機會顯示類似這樣的輸出(顏色會根據日誌等級不同而變化):
[Nest] 12345 - 12/24/2024, 2:30:00 PM LOG [UsersService] 正在查詢所有使用者
[Nest] 12345 - 12/24/2024, 2:30:00 PM DEBUG [UsersService] 查詢使用者 ID: abc123
[Nest] 12345 - 12/24/2024, 2:30:01 PM WARN [UsersService] 這是一個警告訊息
[Nest] 12345 - 12/24/2024, 2:30:01 PM VERBOSE [UsersService] 這是 verbose 層級的訊息
傳入 Logger 建構子的字串稱為 context,官方慣例是使用 ClassName.name 來取得類別名稱。這樣即使之後重構更改類別名稱,日誌的 context 也會自動跟著變動,不需要手動修改字串。