【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.mzph.cn/news/762197.shtml

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

相关文章

推荐的Kubernetes 学习资料

官方文档&#xff1a; Kubernetes 官方文档&#xff1a;https://kubernetes.io/docs/Kubernetes 教程&#xff1a;https://kubernetes.io/docs/tutorials/ 书籍&#xff1a; Kubernetes in Action&#xff0c;Marko Luksa 著Kubernetes Up and Running&#xff0c;Kelsey Hi…

Spring AI Embeddings 和 Vector 入门

在前面 Spring AI Chat 简单示例 中介绍了 Chat 的基本用法&#xff0c;本文在此基础&#xff08;主要是pom.xml&#xff09;上继续探索 Embedding 和 Vector。 官方文档&#xff1a; embeddings: https://docs.spring.io/spring-ai/reference/api/embeddings/openai-embedding…

断点重训教程:如何有效地保护深度学习模型训练进度

在深度学习领域&#xff0c;长时间训练是常见的需求&#xff0c;然而&#xff0c;在训练过程中可能会面临各种意外情况&#xff0c;比如计算机故障、断电等&#xff0c;这些意外情况可能导致训练过程中断&#xff0c;造成已经投入的时间和资源的浪费。为了应对这种情况&#xf…

「Linux系列」有关Shell数组/运算符的故事

文章目录 一、Shell 数组运用1. 定义数组2. 访问数组元素3. 获取数组长度4. 遍历数组5. 追加元素到数组6. 删除数组元素7. 数组切片8. 综合示例&#xff1a;统计数组中元素的个数9. 关联数组&#xff08;Bash 4.0及以上版本&#xff09; 二、Shell 基本运算符1. 数值运算符2. 字…

Avue框架实现图表的基本知识 | 附Demo(全)

目录 前言1. 柱状图2. 折线图3. 饼图4. 刻度盘6. 仪表盘7. 象形图8. 彩蛋8.1 饼图8.2 柱状图8.3 折线图8.4 温度仪表盘8.5 进度条 前言 以下Demo&#xff0c;作为初学者来说&#xff0c;会相应给出一些代码注释&#xff0c;可相应选择你所想要的款式 对于以下Demo&#xff0c…

GStreamer简单看看

主要是现在弄摄像头&#xff0c;要用到这东西。所以学学。 最权威主页&#xff1a;GStreamer: open source multimedia framework 大概看了下&#xff0c;好像命令也不难。 gst-launch-1.0 v4l2src device/dev/video0 ! video/x-raw,formatYUY2,width640,height480,framerat…

说说你对webpack的理解?解决了什么问题?

文章目录 一、背景二、问题三、是什么参考文献 一、背景 Webpack 最初的目标是实现前端项目的模块化&#xff0c;旨在更高效地管理和维护项目中的每一个资源 模块化 最早的时候&#xff0c;我们会通过文件划分的形式实现模块化&#xff0c;也就是将每个功能及其相关状态数据各…

Java 面试宝典:volatile 的使用场景有哪些?

大家好&#xff0c;我是大明哥&#xff0c;一个专注「死磕 Java」系列创作的硬核程序员。 本文已收录到我的技术网站&#xff1a;https://skjava.com。有全网最优质的系列文章、Java 全栈技术文档以及大厂完整面经 回答 volatile 是一种轻量级的同步机制&#xff0c;它能保证共…

Batch Normalization(批量归一化)和 Layer Normalization(层归一化)

Batch Normalization(批量归一化)和 Layer Normalization(层归一化)都是深度学习中用于改善网络训练过程的归一化技术。尽管它们的目标相似,即通过规范化中间层的激活值来加速训练过程并提高性能,但它们在细节上有所不同。 Batch Normalization (批量归一化) Batch Nor…

谷歌地图TMS地图服务地址收集2024,测试可用

对于普通的开发者或者GIS从业者来说&#xff0c;免费的底图影像服务&#xff0c;太重要了。之前写过一篇谷歌地图的TMS地址收集的博文&#xff0c;由于谷歌网站关闭已经不能用。最近又发现了谷歌在国内开放了其他地址&#xff0c;在这里给大家分享一下。 https://gac-geo.googl…

Ant Design Vue和VUE3下的upload组件使用以及文件预览

Ant Design Vue和VUE3下的upload组件使用以及文件预览 文章目录 Ant Design Vue和VUE3下的upload组件使用以及文件预览一、多文件上传1.需求2.样例3.代码 二、单文件上传1. 需求2. 样例3.代码 二、多文件上传产生的时间超时问题三、文件系统名称更改1. 修改文件index.html2. 修…

【Java初阶(三)】方法的使用

❣博主主页: 33的博客❣ ▶文章专栏分类: Java从入门到精通◀ &#x1f69a;我的代码仓库: 33的代码仓库&#x1f69a; 目录 1.前言2.方法的概念2.1方法定义2.2 实参和形参的关系 3. 方法的重载3.1方法重载的概念 4.递归4.1递归的概念4.2递归过程分析4.3 递归练习 5.总结 1.前言…

java核心面试题解析

1.索引 1.1创建索引: create index 索引名称 on 某张表 (列名) 示例: create index index_name on table (Column names) 1.2索引优化 MySQL数据库索引优化是提高查询性能的重要手段。以下是一些关键的索引优化策略: 选择正确的索引列: 经常需要排序、分组和联…

Leetcode热题100:图论

Leetcode 200. 岛屿数量 深度优先搜索法&#xff1a; 对于这道题来说&#xff0c;是一个非常经典的图的问题&#xff0c;我们可以先从宏观上面来看问题&#xff0c;也就是说在不想具体算法的前提下&#xff0c;简单的说出如何找到所有的岛屿呢&#xff1f; 如图中所示&#x…

win git filter-repo教程

git filter-repo 是一个用于过滤和清理 Git 仓库历史的工具&#xff0c;它可以高效地批量修改提交历史中的文件内容、删除文件、重命名文件以及进行其他历史重构操作。相较于 git filter-branch&#xff0c;它通常更快且更易于使用。 以下是一个基本示例&#xff0c;说明如何使…

oracle 19c单机版本补丁升级

文章目录 一、补丁包概述二、备份opatch三、替换高版本opatch四、打DB补丁1、关闭数据库2、关闭监听3、解压补丁4、冲突检测5、补丁空间检查6、执行补丁升级7、将更新内容加载到数据库8、最后查看数据库版本9、卸载补丁包 一、补丁包概述 补丁升级包 链接&#xff1a;https://…

【系统架构设计师】计算机系统基础知识 03

系统架构设计师 - 系列文章目录 01 系统工程与信息系统基础 02 软件架构设计 03 计算机系统基础知识 文章目录 系统架构设计师 - 系列文章目录 文章目录 前言 一、计算机系统概述 1.计算机组成 ​编辑2.存储系统 二、操作系统 ★★★★ 1.进程管理 2.存储管理 1.页式存储 …

Golang Gorm 自动分批查询

场景&#xff1a; 目标查询全量数据&#xff0c;但需要每次Limit分批查询&#xff0c;保护数据库 文档&#xff1a; https://gorm.io/zh_CN/docs/advanced_query.html // Param: // dest 目标地址 // batchSize 大小 // fc 处理函数func (db *DB) FindInBatc…

安卓 Android Activity 生命周期

文章目录 Intro生命周期方法 & 执行顺序结论code Intro 本文提供一个测试类通过打印的方式展示在多个Activity之间互相跳转的时候&#xff0c;各个Activity的生命周期相关方法的执行顺序。 生命周期方法 & 执行顺序结论 下图出自 郭霖 《第一行代码&#xff08;第二…

速盾:免备案cdn的好处

免备案CDN&#xff08;Content Delivery Network&#xff09;是指不需要进行备案手续即可使用的CDN服务。备案是指在中国大陆地区提供互联网信息服务的网站必须向相关部门进行备案登记&#xff0c;以确保其合法合规的运营。 那么&#xff0c;免备案CDN有哪些好处呢&#xff1f…