NestJS Winstonでロギングを整える
nest-winston を使って構造化ログ(JSON)を出力し、ログレベル・フォーマットを環境ごとに切り替える
最終更新:2026/06/05
NestJSの基礎まで終えている前提。
この記事では、NestJS 標準の Logger を Winston に差し替えて、開発環境では見やすいカラーログ、本番環境では JSON ログを出力する最小構成を実装する。
この記事でやること
winston/nest-winstonを導入するAppModuleにWinstonModuleを設定し、標準 Logger を差し替える- 開発環境:カラー付きテキストログ、本番環境:JSON ログを切り替える
UsersServiceにロガーを注入してログを出力する- 実際に動かしてログを確認する
触るファイル一覧
api-sample/
└─ src/
├─ app.module.ts # WinstonModule を設定・NestJS Logger を差し替え
├─ main.ts # app.useLogger() を追加
└─ users/
└─ users.service.ts # Logger を注入してログ出力1. パッケージを追加する
pnpm の場合。
pnpm add winston nest-winstonnpm の場合。
npm install winston nest-winston2. AppModule に WinstonModule を設定する
編集するファイルは api-sample/src/app.module.ts。
import { Module } from "@nestjs/common";
import { WinstonModule } from "nest-winston";
import * as winston from "winston";
import { UsersModule } from "./users/users.module";
const isDev = process.env.NODE_ENV !== "production";
@Module({
imports: [
WinstonModule.forRoot({
level: isDev ? "debug" : "info",
transports: [
new winston.transports.Console({
format: isDev
? winston.format.combine(
winston.format.colorize(),
winston.format.timestamp({ format: "HH:mm:ss" }),
winston.format.printf(
({ level, message, timestamp, context }) =>
`${timestamp} [${context ?? "App"}] ${level}: ${message}`
)
)
: winston.format.combine(
winston.format.timestamp(),
winston.format.json()
),
}),
],
}),
UsersModule,
],
})
export class AppModule {}ポイント
NODE_ENVがproduction以外の場合は開発向けフォーマット(カラー + 短いタイムスタンプ)を使う。- 本番では
winston.format.json()で1行JSONを出力する。CloudWatch / Datadog などのログ収集ツールが自動パースできる形式。 level: "debug"にするとdebug以上すべてを出力する。本番で"info"にするとdebugログが出ない。
3. main.ts でアプリのロガーを差し替える
編集するファイルは api-sample/src/main.ts。
import { NestFactory } from "@nestjs/core";
import { AppModule } from "./app.module";
import { WINSTON_MODULE_NEST_PROVIDER } from "nest-winston";
async function bootstrap() {
const app = await NestFactory.create(AppModule);
// NestJS 内部ログ(起動ログ等)も Winston に差し替える
app.useLogger(app.get(WINSTON_MODULE_NEST_PROVIDER));
await app.listen(3000);
}
bootstrap();WINSTON_MODULE_NEST_PROVIDER は nest-winston が提供するトークン。
これを useLogger に渡すことで、フレームワーク自身のログ(モジュール起動ログ等)も Winston 経由で出力される。
4. UsersService にロガーを注入する
編集するファイルは api-sample/src/users/users.service.ts。
import { Injectable, Inject, NotFoundException } from "@nestjs/common";
import { WINSTON_MODULE_PROVIDER } from "nest-winston";
import { Logger } from "winston";
@Injectable()
export class UsersService {
constructor(
@Inject(WINSTON_MODULE_PROVIDER) private readonly logger: Logger
) {}
findAll() {
this.logger.info("全ユーザーを取得", { context: "UsersService" });
return [{ id: 1, name: "Alice" }];
}
findOne(id: number) {
this.logger.debug(`ユーザーを取得: id=${id}`, { context: "UsersService" });
const user = { id, name: "Alice" };
if (!user) {
this.logger.warn(`ユーザーが見つからない: id=${id}`, { context: "UsersService" });
throw new NotFoundException(`User ${id} not found`);
}
return user;
}
}5. 動かして確認する
サーバーを起動する。
pnpm start:dev開発環境の出力例
12:34:56 [NestFactory] info: Starting Nest application...
12:34:56 [InstanceLoader] info: AppModule dependencies initialized
12:34:56 [RoutesResolver] info: UsersController {/users}:
12:34:56 [NestApplication] info: Nest application successfully startedGET /users を叩く。
curl http://localhost:3000/users12:34:57 [UsersService] info: 全ユーザーを取得本番環境の出力例(JSON)
NODE_ENV=production で起動すると1行JSONになる。
{"level":"info","message":"全ユーザーを取得","context":"UsersService","timestamp":"2026-06-05T03:34:57.123Z"}ログレベルの使い分け
| レベル | 用途の目安 |
|---|---|
error | 予期しないエラー、例外キャッチ |
warn | 異常ではないが注意が必要な状態(リソース不足など) |
info | 正常な操作の記録(リクエスト受付、処理完了など) |
debug | 開発時のデバッグ情報(変数の中身など) |
本番では level: "info" にして debug ログを出力しないのが一般的。
ファイルへの出力を追加する(オプション)
コンソールに加えてファイルにも出力したい場合は transports に追加する。
transports: [
new winston.transports.Console({ ... }),
new winston.transports.File({
filename: "logs/error.log",
level: "error", // error ログのみ記録
format: winston.format.combine(
winston.format.timestamp(),
winston.format.json()
),
}),
new winston.transports.File({
filename: "logs/combined.log", // 全レベルを記録
format: winston.format.combine(
winston.format.timestamp(),
winston.format.json()
),
}),
],logs/ ディレクトリは事前に作成するか、.gitignore に追加しておく。
mkdir -p logs
echo "logs/" >> .gitignore