【Node.js从基础到高级运用】十四、Node.js 错误处理与日志记录

引言

在这篇博客文章中,我们将深入探讨Node.js中的错误处理和日志记录的最佳实践。我们会了解如何在Node.js应用程序中有效地捕获和处理错误,并利用日志库如morgan来记录应用程序的活动和错误信息。

第1部分:Node.js中的错误处理

同步代码中的错误处理

在Node.js的同步代码中,我们通常使用try...catch语句来捕获错误。

// 同步代码错误处理示例
try {// 尝试执行可能会抛出错误的代码let result = someSynchronousOperation();console.log('Operation successful:', result);
} catch (error) {// 处理错误console.error('An error occurred:', error);
}

异步代码中的错误处理

异步代码的错误处理稍微复杂一些,因为错误可能在回调函数中发生。

// 异步代码错误处理示例
fs.readFile('/path/to/file', (err, data) => {if (err) {// 处理错误console.error('Error reading file:', err);} else {// 正常处理数据console.log('File content:', data);}
});

Promise中的错误处理

当使用Promise时,我们可以利用.catch()方法来捕获错误。

// Promise中的错误处理示例
someAsyncOperation().then(result => {console.log('Operation successful:', result);}).catch(error => {// 处理错误console.error('An error occurred:', error);});

Express中的错误处理

在Express框架中,错误处理通常通过中间件来实现。

// Express中的错误处理示例
const express = require('express');
const app = express();// 中间件来捕获同步代码中的错误
app.use((req, res, next) => {throw new Error('Something went wrong!');next(); // 这行代码不会执行
});// 错误处理中间件
app.use((err, req, res, next) => {console.error('Error:', err);res.status(500).send('Internal Server Error');
});app.listen(3000, () => {console.log('Server is running on port 3000');
});

第2部分:日志记录

为什么需要日志记录

日志记录是应用程序监控和故障排除的关键组成部分。它可以帮助开发者了解应用程序的运行状态和诊断问题。

使用console进行简单日志记录

对于简单的应用程序,使用console.log()console.error()可能就足够了。

// 使用console记录日志
console.log('This is an informational message');
console.error('This is an error message');

使用morgan进行HTTP请求日志记录

对于Web应用程序,我们通常希望记录HTTP请求。Morgan是一个流行的日志中间件,可以很容易地集成到Express应用程序中。

// 使用morgan记录HTTP请求
const express = require('express');
const morgan = require('morgan');const app = express();
app.use(morgan('combined')); // 'combined'是预定义的日志格式app.get('/', (req, res) => {res.send('Hello, World!');
});app.listen(3000, () => {console.log('Server is running on port 3000');
});

在这里插入图片描述

Morgan预定义的格式化选项

1. combined
combined格式提供了Apache服务器日志的标准组合格式,包括许多有用的信息,适合用于生产环境
它包含以下信息:

  • 客户端地址 (remote-addr)
  • 认证用户 (remote-user)
  • 时间戳 ([date])
  • 请求行 (“method url HTTP/version”)
  • HTTP状态码 (status)
  • 响应内容的长度 (content-length)
  • 引用页 (“referrer”)
  • 用户代理 (“user-agent”)

2. common
common格式类似于combined,但它不包括引用页(“referrer”)和用户代理(“user-agent”)。
它包含以下信息:

  • 客户端地址 (remote-addr)
  • 认证用户 (remote-user)
  • 时间戳 ([date])
  • 请求行 (“method url HTTP/version”)
  • HTTP状态码 (status)
  • 响应内容的长度 (content-length)

3. dev
dev格式主要用于开发环境,因为它的输出是彩色的,便于区分不同的HTTP状态码。

它包含以下信息:

  • 请求方法和URL (`method url)
  • HTTP状态码 (status),如果是4xx或5xx则以红色显示
  • 响应时间 (response-time)

自定义日志记录

在复杂的应用程序中,您可能需要更高级的日志记录解决方案,如WinstonBunyan

// 使用Winston进行自定义日志记录
const winston = require('winston');const logger = winston.createLogger({level: 'info',format: winston.format.json(),transports: [new winston.transports.File({ filename: 'error.log', level: 'error' }),new winston.transports.File({ filename: 'combined.log' })]
});logger.info('This is an informational message');
logger.error('This is an error message');

将会在根目录生成log文件:
在这里插入图片描述

第3部分:结合错误处理与日志记录

结构化错误信息

为了更有效地记录错误,我们可以创建一个结构化的错误对象。

// 结构化错误信息
class AppError extends Error {constructor(message, status) {super(message);this.status = status;this.isOperational = true; // 标记为可预见的操作错误}
}

将错误信息记录到日志中

我们可以将错误对象与日志系统结合起来,以便更详细地记录错误信息。

// 将错误信息记录到日志中
function handleError(err) {logger.error({ message: err.message, stack: err.stack, status: err.status });
}// 在应用程序中使用
try {// 产生错误throw new AppError('Something went wrong!', 500);
} catch (err) {handleError(err);
}

在这里插入图片描述
测试用例:

const fs = require('fs');
const winston = require('winston');// 配置日志记录器
const logger = winston.createLogger({level: 'error',format: winston.format.json(),transports: [new winston.transports.File({ filename: 'error.log' })]
});// 错误记录示例
function readFileAndLog(path) {fs.readFile(path, (err, data) => {if (err) {// 记录错误到日志logger.error('Error reading file', { path: path, error: err });// 进一步的错误处理...} else {// 处理文件内容...}});
}

第四部分:错误通知(警报)、错误恢复策略

错误通知

对于某些关键错误,仅仅记录到日志可能不够,还需要实时通知到开发者或运维团队。这可以通过邮件、短信、即时消息等方式实现。

const nodemailer = require('nodemailer');// 配置邮件发送器
const transporter = nodemailer.createTransport({service: 'gmail',auth: {user: 'your-email@gmail.com',pass: 'your-password'}
});// 错误通知示例
function notifyError(error) {const mailOptions = {from: 'your-email@gmail.com',to: 'dev-team-email@example.com',subject: 'Application Error Alert',text: `An error has occurred: ${error.message}`};transporter.sendMail(mailOptions, function(err, info) {if (err) {console.error('Error sending email:', err);} else {console.log('Error notification sent:', info.response);}});
}

错误恢复策略

错误恢复策略是指当错误发生时,如何保证系统能够继续运行或尽快恢复到正常状态。这可能包括重试失败的操作、切换到备份服务、释放资源等。

// 错误恢复策略示例
function operationWithRetry(operation, maxAttempts) {let attempts = 0;function attempt() {operation((err, result) => {if (err) {attempts++;if (attempts < maxAttempts) {console.log(`Attempt ${attempts}: retrying operation`);attempt(); // 重试操作} else {console.error('Operation failed after retries:', err);// 进行其他恢复操作...}} else {// 操作成功}});}attempt();
}

测试用例

编写测试用例时,应当模拟不同的错误场景,并验证错误处理流程是否按预期工作。

const assert = require('assert');// 测试错误记录
readFileAndLog('/non/existent/file');
// 确认错误.log文件中记录了错误信息// 测试错误通知
notifyError(new Error('Test Error'));
// 确认开发团队收到了错误通知邮件// 测试错误恢复策略
let operationCalled = 0;
const mockOperation = (callback) => {operationCalled++;if (operationCalled < 3) {callback(new Error('Operation failed'));} else {callback(null, 'Success');}
};operationWithRetry(mockOperation, 5);
assert.strictEqual(operationCalled, 3, 'Operation should succeed on the third attempt');

assert.strictEqual 是 Node.js assert 模块提供的一个方法,用来测试两个值是否严格相等。这里的“严格相等”指的是它们的类型和值都必须完全匹配,这与 JavaScript 中的===运算符相同。
在这个例子中,如果 operationCalled不等于 3,那么 assert.strictEqual 会抛出一个错误,并显示提供的错误信息(‘Operation should succeed on the third attempt’)

总结

在Node.js应用程序中,正确地处理错误和记录日志是至关重要的。它不仅有助于开发和调试过程,也是生产环境中保证应用稳定性和可维护性的关键。通过本文的介绍,您应该能够在您的Node.js应用程序中实现高效的错误处理和日志记录策略。

参考资料

Node.js官方文档
Express官方文档
Morgan npm页面
Winston npm页面

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/549408.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

母婴用品网站|基于jsp技术+ Mysql+Java的母婴用品网站设计与实现(可运行源码+数据库+设计文档)

推荐阅读100套最新项目 最新ssmjava项目文档视频演示可运行源码分享 最新jspjava项目文档视频演示可运行源码分享 最新Spring Boot项目文档视频演示可运行源码分享 目录 1. 前台功能效果图 2. 管理员功能效果图 3. 用户功能 4. 系统功能设计 5. 数据库E-R图设计 6. lu…

OpenCV Steger算法提取条纹中心线

文章目录 一、简介二、实现代码三、实现效果参考资料一、简介 Steger 算法是一种常用的图像边缘检测算法,可以用于提取图像中的中心线或边缘信息。它的理论假设是:条纹的亮度是按照高斯分布呈现的,即中心亮两侧渐暗。 其计算过程如下所述: 1、首先,我们需要计算每个点Hess…

el-upload的多个文件与单个文件上传

样式图&#xff1a; 场景多个&#xff1a; 使用el-upload上传多个文件 <el-upload class"upload-demo" :action"uploadUrl" :on-remove"handleRemove1":on-success"handleAvatarSuccess1" multiple :limit"5" :on-exc…

抖音视频爬虫采集工具界面图解|视频批量提取软件

抖音视频爬虫界面图解 一&#xff1a;概述 主要功能&#xff1a;关键词批量提取视频和单独视频提取&#xff0c;提取后下载功能 二&#xff1a;功能解析 2.1&#xff1a;关键词批量提取视频的解析 对某个关键词进行搜索和视频提取&#xff0c;例如输入汽车配件&#xf…

Flutter-自定义表情雨下落动画

简述 今天给大家分享一个Flutter的表情雨的实现&#xff0c;具体的效果见下图&#xff0c;这个效果其实是工作中的一个小小的需求&#xff0c;这里面单独拿出来讲讲下这个效果的实现思路。 在以前特别是新手&#xff0c;遇到一些动画效果都是拿到需求后&#xff0c;在网络上去…

机器人可反向驱动能力与力控架构

反向驱动性是电机传动系统的机械特性&#xff0c;它描述了运动是否可以轻松反转 。特别是&#xff0c;反向驱动能力取决于两个因素&#xff1a;传动运动效率和整体执行器机械阻抗。反向运动中传动装置的低运动效率意味着所施加的外力的大部分被运动反作用力抵消。然而&#xff…

sheng的学习笔记-AI-残差网络-Residual Networks (ResNets)

目录&#xff1a;sheng的学习笔记-AI目录-CSDN博客 非常非常深的神经网络&#xff0c;网络发生了退化&#xff08;degradation&#xff09;的现象&#xff1a;随着网络层数的增多&#xff0c;训练集loss逐渐下降&#xff0c;然后趋于饱和&#xff0c;当你再增加网络深度的话&am…

银行OA系统|基于SpringBoot架构+ Mysql+Java+ B/S结构的银行OA系统设计与实现(可运行源码+数据库+设计文档)

推荐阅读100套最新项目 最新ssmjava项目文档视频演示可运行源码分享 最新jspjava项目文档视频演示可运行源码分享 最新Spring Boot项目文档视频演示可运行源码分享 2024年56套包含java&#xff0c;ssm&#xff0c;springboot的平台设计与实现项目系统开发资源&#xff08;可…

Java实现定时发送邮件(基于Springboot工程)

1、功能概述&#xff1f; 1、在企业中有很多需要定时提醒的任务&#xff1a;如每天下午四点钟给第二天的值班人员发送值班消息&#xff1f;如提前一天给参与第二天会议的人员发送参会消息等。 2、这种定时提醒有很多方式如短信提醒、站内提醒等邮件提醒是其中较为方便且廉价的…

uniapp使用uview - DatetimePicker 时间选择器 /时间戳转化

uniapp使用uview - DatetimePicker 时间选择器 /时间戳转化时转换日期格式后页面仍显示时间戳 单元格内显示时间&#xff0c;点击可出现时间选择器切换时间 <u-cell :isLinktrue click"selectTime" title"开始时间" :value"startTime">…

【已解决】在pycharm终端无法激活conda环境,但在cmd命令行中可以

一、问题描述 在windows下winr启动cmd命令行&#xff0c;可以成功运行conda命令并且激活环境在pycharm中打开Terminal终端&#xff0c;发现无法运行conda和pip命令&#xff0c;报错环境无法激活 无法在管道中间运行文档: D:\software\Anaconda3\condabin\conda.bat。 所在位置…

基于Spring Boot的美食分享系统设计与实现

摘 要 美食分享管理&#xff0c;其工作流程繁杂、多样、管理复杂与设备维护繁琐。而计算机已完全能够胜任美食分享管理工作&#xff0c;而且更加准确、方便、快捷、高效、清晰、透明&#xff0c;它完全可以克服以上所述的不足之处。这将给查询信息和管理带来很大的方便&#x…