news 2026/7/21 11:59:43

nest-winston错误处理:如何优雅记录和追踪应用异常 [特殊字符]

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
nest-winston错误处理:如何优雅记录和追踪应用异常 [特殊字符]

nest-winston错误处理:如何优雅记录和追踪应用异常 🐛

【免费下载链接】nest-winstonA Nest module wrapper form winston logger项目地址: https://gitcode.com/gh_mirrors/ne/nest-winston

在构建NestJS应用时,优雅的错误处理和日志记录是确保应用稳定性的关键环节。nest-winston作为NestJS的Winston日志模块包装器,为开发者提供了强大的错误追踪能力。本文将为你揭示如何使用nest-winston进行专业的错误处理,让你的应用异常无处遁形!

为什么选择nest-winston进行错误处理? 🤔

nest-winston不仅仅是一个日志记录工具,它是专为NestJS设计的日志解决方案。与原生console.log相比,nest-winston提供了结构化日志、多传输目标、上下文感知等高级功能。对于错误处理而言,这意味着:

  • 结构化错误信息:将错误堆栈、上下文、时间戳等信息统一格式
  • 多目标输出:同时记录到控制台、文件、数据库等不同目标
  • 性能优化:异步日志记录不影响应用性能
  • 与NestJS生态完美集成:无缝替换NestJS内置日志系统

快速配置nest-winston错误日志记录 🚀

首先,在你的NestJS项目中安装nest-winston:

npm install nest-winston winston

然后配置基础的错误日志记录:

import { Module } from '@nestjs/common'; import { WinstonModule } from 'nest-winston'; import * as winston from 'winston'; import { utilities as nestWinstonModuleUtilities } from 'nest-winston'; @Module({ imports: [ WinstonModule.forRoot({ transports: [ new winston.transports.Console({ level: 'error', // 只记录错误级别日志 format: winston.format.combine( winston.format.timestamp(), winston.format.errors({ stack: true }), // 捕获错误堆栈 nestWinstonModuleUtilities.format.nestLike('MyApp', { colors: true, prettyPrint: true, }), ), }), new winston.transports.File({ filename: 'logs/error.log', level: 'error', format: winston.format.combine( winston.format.timestamp(), winston.format.json(), // JSON格式便于分析 ), }), ], }), ], }) export class AppModule {}

三种错误记录方式对比 📊

nest-winston提供了三种不同的错误记录方式,每种方式都有其适用场景:

1. 基础Winston记录器(仅应用日志)

使用WINSTON_MODULE_PROVIDER注入令牌,适合只需要记录应用业务日志的场景:

import { Controller, Get, Inject } from '@nestjs/common'; import { WINSTON_MODULE_PROVIDER } from 'nest-winston'; import { Logger } from 'winston'; @Controller('users') export class UsersController { constructor( @Inject(WINSTON_MODULE_PROVIDER) private readonly logger: Logger, ) {} @Get() async findAll() { try { // 业务逻辑 return await this.userService.findAll(); } catch (error) { // 记录详细错误信息 this.logger.error('获取用户列表失败', { error: error.message, stack: error.stack, timestamp: new Date().toISOString(), context: 'UsersController', }); throw error; // 重新抛出,让全局过滤器处理 } } }

2. NestJS系统日志替换(推荐)

使用WINSTON_MODULE_NEST_PROVIDER替换NestJS内置日志系统,统一应用和系统日志:

// main.ts import { WINSTON_MODULE_NEST_PROVIDER } from 'nest-winston'; async function bootstrap() { const app = await NestFactory.create(AppModule); app.useLogger(app.get(WINSTON_MODULE_NEST_PROVIDER)); await app.listen(3000); } bootstrap(); // 控制器中使用 import { Controller, Get, Inject, LoggerService } from '@nestjs/common'; import { WINSTON_MODULE_NEST_PROVIDER } from 'nest-winston'; @Controller('products') export class ProductsController { constructor( @Inject(WINSTON_MODULE_NEST_PROVIDER) private readonly logger: LoggerService, ) {} @Get() async findAll() { this.logger.log('开始查询产品列表', ProductsController.name); try { const result = await this.productService.findAll(); this.logger.log('产品查询成功', ProductsController.name); return result; } catch (error) { this.logger.error( '产品查询失败', error.stack, // 错误堆栈 ProductsController.name, // 上下文 ); throw error; } } }

3. 完全替换NestJS日志(包含启动日志)

使用WinstonModule.createLogger()在应用启动时完全替换NestJS日志系统:

// main.ts import { WinstonModule } from 'nest-winston'; import * as winston from 'winston'; async function bootstrap() { const app = await NestFactory.create(AppModule, { logger: WinstonModule.createLogger({ transports: [ new winston.transports.Console({ format: winston.format.combine( winston.format.timestamp(), winston.format.errors({ stack: true }), winston.format.simple(), ), }), new winston.transports.File({ filename: 'logs/combined.log', level: 'info', }), new winston.transports.File({ filename: 'logs/errors.log', level: 'error', }), ], }), }); await app.listen(3000); } bootstrap();

高级错误处理技巧 🔧

1. 自定义错误格式化

通过创建自定义格式化器,你可以为错误信息添加更多上下文:

const errorFormatter = winston.format((info) => { if (info instanceof Error) { return { ...info, message: info.message, stack: info.stack, type: info.constructor.name, }; } return info; }); // 在配置中使用 WinstonModule.forRoot({ format: winston.format.combine( errorFormatter(), winston.format.json(), ), transports: [/* ... */], })

2. 错误分类与过滤

根据错误类型进行不同的处理:

// 创建不同级别的错误处理器 const errorTransports = [ new winston.transports.File({ filename: 'logs/database-errors.log', level: 'error', filter: (info) => info.context?.includes('Database'), }), new winston.transports.File({ filename: 'logs/validation-errors.log', level: 'error', filter: (info) => info.context?.includes('Validation'), }), new winston.transports.File({ filename: 'logs/http-errors.log', level: 'error', filter: (info) => info.context?.includes('Http'), }), ];

3. 异步错误处理

对于异步操作,确保错误被正确捕获:

@Injectable() export class UserService { constructor( @Inject(WINSTON_MODULE_PROVIDER) private readonly logger: Logger, ) {} async createUser(userData: CreateUserDto) { try { // 异步数据库操作 const user = await this.userRepository.save(userData); this.logger.log(`用户创建成功: ${user.id}`, 'UserService'); return user; } catch (error) { this.logger.error('用户创建失败', { error: error.message, stack: error.stack, userData, timestamp: new Date().toISOString(), }); // 根据错误类型返回不同的响应 if (error.code === '23505') { throw new ConflictException('用户已存在'); } throw new InternalServerErrorException('创建用户时发生错误'); } } }

错误监控与告警集成 📈

1. 集成Sentry等错误监控平台

import * as Sentry from '@sentry/node'; import { Logger } from 'winston'; class SentryTransport extends winston.Transport { log(info: any, callback: Function) { if (info.level === 'error') { Sentry.captureException(info.error || new Error(info.message), { extra: info, }); } callback(); } } // 添加到传输列表 transports: [ new winston.transports.Console(), new SentryTransport(), ]

2. 性能监控与错误关联

@Injectable() export class PerformanceMonitorInterceptor implements NestInterceptor { constructor( @Inject(WINSTON_MODULE_PROVIDER) private readonly logger: Logger, ) {} intercept(context: ExecutionContext, next: CallHandler): Observable<any> { const startTime = Date.now(); const request = context.switchToHttp().getRequest(); return next.handle().pipe( tap(() => { const duration = Date.now() - startTime; this.logger.info(`请求完成`, { method: request.method, url: request.url, duration: `${duration}ms`, status: 'success', }); }), catchError((error) => { const duration = Date.now() - startTime; this.logger.error(`请求失败`, { method: request.method, url: request.url, duration: `${duration}ms`, error: error.message, stack: error.stack, status: 'error', }); return throwError(() => error); }), ); } }

最佳实践总结 ✅

  1. 统一错误格式:确保所有错误都包含时间戳、上下文、错误信息和堆栈跟踪
  2. 分级处理:根据错误严重程度使用不同的日志级别(error、warn、info)
  3. 上下文丰富:在错误日志中包含请求ID、用户ID等上下文信息
  4. 敏感信息过滤:避免在日志中记录密码、令牌等敏感信息
  5. 定期清理:设置日志轮转策略,避免日志文件过大
  6. 监控集成:将错误日志与监控系统集成,实现实时告警

常见问题解答 ❓

Q: 如何在生产环境中配置nest-winston?A: 在生产环境中,建议禁用控制台颜色,使用JSON格式,并配置日志轮转:

WinstonModule.forRoot({ format: winston.format.combine( winston.format.timestamp(), winston.format.json(), ), transports: [ new winston.transports.File({ filename: 'logs/error-%DATE%.log', datePattern: 'YYYY-MM-DD', maxSize: '20m', maxFiles: '30d', level: 'error', }), new winston.transports.File({ filename: 'logs/combined-%DATE%.log', datePattern: 'YYYY-MM-DD', maxSize: '20m', maxFiles: '7d', }), ], })

Q: 如何处理未捕获的异常?A: 使用NestJS的异常过滤器结合nest-winston:

@Catch() export class AllExceptionsFilter implements ExceptionFilter { constructor( @Inject(WINSTON_MODULE_PROVIDER) private readonly logger: Logger, ) {} catch(exception: unknown, host: ArgumentsHost) { const ctx = host.switchToHttp(); const response = ctx.getResponse<Response>(); const request = ctx.getRequest<Request>(); const status = exception instanceof HttpException ? exception.getStatus() : HttpStatus.INTERNAL_SERVER_ERROR; this.logger.error('未捕获的异常', { statusCode: status, timestamp: new Date().toISOString(), path: request.url, method: request.method, exception: exception, }); response.status(status).json({ statusCode: status, timestamp: new Date().toISOString(), path: request.url, message: '内部服务器错误', }); } }

结语 🎯

通过nest-winston的强大功能,你可以构建出专业级的错误处理系统。记住,好的错误处理不仅仅是记录错误,更是为了快速定位问题、分析原因并预防未来类似问题的发生。现在就开始使用nest-winston,让你的NestJS应用更加健壮可靠吧!

想要了解更多高级用法?查看项目中的示例代码:sample/quick-start/src/app.controller.ts 和 sample/replace-nest-logger/src/app.controller.ts 获取更多灵感!

【免费下载链接】nest-winstonA Nest module wrapper form winston logger项目地址: https://gitcode.com/gh_mirrors/ne/nest-winston

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/21 11:59:39

Cursor试用限制终极解决方案:三分钟恢复免费AI编程体验

Cursor试用限制终极解决方案&#xff1a;三分钟恢复免费AI编程体验 【免费下载链接】go-cursor-help 解决Cursor在免费订阅期间出现以下提示的问题: Your request has been blocked as our system has detected suspicious activity / Youve reached your trial request limit.…

作者头像 李华
网站建设 2026/7/21 11:57:58

2026本地汽车养护小程序开发十大公司测评:预约、套餐与会员怎么选?含零代码SAAS、AI编程、源码定制交付

2026本地汽车养护小程序开发十大公司测评&#xff1a;预约、套餐与会员怎么选&#xff1f; 前言 洗车、美容、保养、维修和汽车用品门店的小程序&#xff0c;需要连接车辆档案、预约、套餐次卡、商城、核销与复购。本文重点分析BBWEYY和餐宝盈在本地汽车服务中的适配。 选型…

作者头像 李华
网站建设 2026/7/21 11:57:52

多维聚合不是加GROUP BY:业务语义驱动的数据操作指南

1. 项目概述&#xff1a;为什么多维聚合中的数据操作不是“加个GROUP BY”就能搞定的 “Part 20: Data Manipulation in Multi-Dimensional Aggregation”这个标题乍看像教科书里一个平平无奇的章节编号&#xff0c;但如果你正在处理销售漏斗分析、用户行为路径建模、IoT设备时…

作者头像 李华
网站建设 2026/7/21 11:55:48

为什么说‘自动洞察‘是CEO最应该投资的AI能力

导语 如果只允许CEO在这一轮AI投入里押注一件事&#xff0c;我的答案可能会让不少人意外&#xff1a;不是ChatBI&#xff0c;不是大模型对话&#xff0c;而是"自动洞察"&#xff08;Auto Insight&#xff09;。 这个判断听起来反直觉。过去一年&#xff0c;聊天式BI的…

作者头像 李华
网站建设 2026/7/21 11:54:59

Bedrock Launcher:为Minecraft基岩版玩家打造的终极启动器解决方案

Bedrock Launcher&#xff1a;为Minecraft基岩版玩家打造的终极启动器解决方案 【免费下载链接】BedrockLauncher 项目地址: https://gitcode.com/gh_mirrors/be/BedrockLauncher 你是否曾羡慕Java版玩家拥有功能强大的启动器&#xff0c;而基岩版却只能使用简陋的原生…

作者头像 李华