当前位置: 首页 > news >正文

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),仅供参考

http://www.cnnetsun.cn/news/3559313.html

相关文章:

  • Cursor试用限制终极解决方案:三分钟恢复免费AI编程体验
  • 2026本地汽车养护小程序开发十大公司测评:预约、套餐与会员怎么选?含零代码SAAS、AI编程、源码定制交付
  • 多维聚合不是加GROUP BY:业务语义驱动的数据操作指南
  • 计算机毕业设计之基于SpringBoot的线上洗衣洗鞋店管理系统的设计与实现
  • 为什么说‘自动洞察‘是CEO最应该投资的AI能力
  • Bedrock Launcher:为Minecraft基岩版玩家打造的终极启动器解决方案
  • 三步掌握B站视频数据批量采集:免费自动化工具终极指南
  • VC++与MFC大作业实战:从环境搭建到部署的Windows桌面开发全流程
  • 【2024本地AI硬件配置黄金公式】:RTX 4090/AMD RX 7900 XTX/Apple M3 Ultra实测对比,选错一块卡多花8700小时推理时间?
  • 涡轴发动机FADEC系统:从机械控制到智能算法的演进
  • 提示词工程×设计决策链,深度解耦AI设计卡点,释放83%冗余人力成本
  • 5分钟掌握PKHeX自动合法性插件:告别手动调整宝可梦数据的烦恼
  • 开源机械手硬件设计终极指南:从零构建自适应抓取系统
  • 【系统架构设计师】预测试卷六:综合知识(75道选择题)
  • 谷歌AI Studio如何用自然语言生成安卓应用
  • 英雄联盟国服换肤完整指南:5分钟免费解锁全英雄皮肤
  • 3步搭建自托管ProtonMail客户端服务器:告别云端依赖,掌控自己的加密邮件
  • 二叉树、BST、散列表与红黑树核心对比与应用
  • APP渗透测试抓包技术实战与安全防护
  • Java面试进阶:从八股文到场景化解决方案的实战指南
  • 告别手动烦恼:Brigadier一键自动化获取Boot Camp驱动终极指南
  • Java面试短期高效突击攻略:核心考点与实战话术
  • DiskInfo硬盘健康监控工具深度解析:现代化数据守护者实战指南
  • PyWxDump项目下架事件:开源开发者的合规警示与生存指南
  • 计算机毕业设计之行李寄存平台设计与实现
  • 【AIGC标识合规生死线】:2024Q3起欧盟DSA+中国网信办新规双轨生效,未嵌入可追溯标识的内容将自动限流
  • Suno AI API深度解析:开源音乐生成项目的技术演进蓝图
  • 嵌入式系统SYSCFG模块详解:从启动配置到引脚复用的核心控制
  • iOS设备玩转Minecraft Java版:PojavLauncher终极安装配置指南
  • 二叉树数据结构详解:从基础概念到高级应用