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

news2024/10/6 12:35:05

引言

在这篇博客文章中,我们将深入探讨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.coloradmin.cn/o/1526000.html

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

相关文章

Aigtek电压放大器的作用及优点是什么

电压放大器是电子技术领域中重要的设备&#xff0c;其作用是将输入信号的电压放大到所需的输出电压水平。电压放大器具有多种优点&#xff0c;下面安泰电子将详细介绍其作用及主要优点。 电压放大器的主要作用是增加信号的电压幅值。通过放大信号的电压&#xff0c;可以增强信号…

苹果MacOS电脑使用内网穿透轻松远程桌面本地Windows系统电脑

文章目录 1. 测试本地局域网内远程控制1.1 Windows打开远程桌面1.2 局域网远程控制windows 2. 测试Mac公网远程控制windows2.1 在windows电脑上安装cpolar2.2 Mac公网远程windows 3. 配置公网固定TCP地址 日常工作生活中&#xff0c;有时候会涉及到不同设备不同操作系统之间需要…

Soul打造多元社交元宇宙,满足年轻人多样化的设计需求

近年来,元宇宙概念备受瞩目,成为全球关注的热门话题。其中,Soul App凭借其独特的Gamified游戏化社交理念,早早成为了元宇宙的开拓者之一。通过持续布局元宇宙赛道,加大技术创新力度,以及创新平台玩法和场景,Soul为用户打造了一个真实、温暖、多元的社交元宇宙,深受Z世代用户的喜…

Python脚本:用py处理PDF的五大功能

一、代码 【第三方库】3个 【Py版本】3.9 【使用前提】关闭所有的word文档 import os from datetime import datetime from docx2pdf import convert from pdf2docx import parse from PyPDF2 import PdfMerger from PyPDF2 import PdfReader,PdfWriter#将文件夹中的所有Wo…

Python从COCO数据集中抽取某类别的数据

1、问题描述 今天需要训练一个人工智能检测模型&#xff0c;用于检测图片或视频中的人。自行收集训练数据费时费力&#xff0c;因而选择从公开数据集COCO中进行抽取。 2、数据准备 2.1 下载 COCO2017 数据集 train:http://images.cocodataset.org/zips/train2017.zip valid…

杉德支付配合调查 - 数字藏品服务

最近&#xff0c;数字收藏品平台淘派发布了一则公告&#xff0c;宣布支付通道杉德已暂停接口服务&#xff0c;以配合调查。 近期发现多个异常账户&#xff0c;涉嫌盗取他人信息和银行卡&#xff0c;利用平台从事非法交易。淘派已第一时间报警&#xff0c;协助警方追回资金(回执…

学生能力是如何被封印的

为了避免无法发表&#xff0c;需要借助人工智能。 为什么一直没写 这个主题其实很多年前就明晰了&#xff0c;但是没有勇气去写出来。 责任全在人工智能 如下是人工智能的回复&#xff0c;如有责任&#xff0c;全都是人工智能的责任。 在学生的情境中&#xff0c;“能力被封印…

Kigo Netflix Video Downloader:Mac与Windows用户的视频下载利器

随着网络的发展和普及&#xff0c;越来越多的人开始使用在线流媒体服务来观看电影、电视剧和其他视频内容。其中&#xff0c;Netflix是世界上最受欢迎的流媒体平台之一。然而&#xff0c;对于想要离线观看这些视频内容的用户来说&#xff0c;下载它们可能会变得有些困难。幸运的…

一文教会你SpringBoot是如何启动的

SpringBoot启动流程分析 流程图 源码剖析 运行Application.run()方法 我们在创建好一个 SpringBoot 程序之后&#xff0c;肯定会包含一个类&#xff1a;xxxApplication&#xff0c;我们也是通过这个类来启动我们的程序的&#xff08;梦开始的地方&#xff09;&#xff0c;而…

J.砍树【蓝桥杯】树上差分+LCA

树上差分 多次对树上的一些路径做加法操作&#xff0c;然后询问某个点或某条边经过操作后的值&#xff0c;就要考虑树上差分了。 点差分 模拟这个过程 对x到y路径上的点权值均1&#xff0c;可以等价成对x和y的权值加1&#xff0c;对lca的权值-1&#xff0c;对fa[lca]的权值-…

操作系统知识-存储管理+文件管理管理-嵌入式系统设计师备考笔记

0、前言 本专栏为个人备考软考嵌入式系统设计师的复习笔记&#xff0c;未经本人许可&#xff0c;请勿转载&#xff0c;如发现本笔记内容的错误还望各位不吝赐教&#xff08;笔记内容可能有误怕产生错误引导&#xff09;。 本章的主要内容见下图&#xff1a; 1、存储管理&#…

【数据结构取经之路】归并排序

简介 归并排序是建立在归并操作上的一种有效&#xff0c;稳定的排序算法&#xff0c;该算法是采用分治法&#xff08;Divide and Conquer&#xff09;的一个非常典型的应用。将已有序的子序列合并&#xff0c;得到完全有序的序列&#xff1b;即先使每个子序列有序&#xff0c;…

在Docker上传我们自己的镜像(以springboot项目为例)

首先确定好在我们的centOS服务器上已经安装并配置好docker 配置自己的springboot镜像并运行 获取springboot的jar包 maven clean--》mavenue package --》复制target目录下生成的jar包 在服务器选择一个文件夹上传jar包&#xff0c;我这里选用的文件夹叫做/opt/dockertest…

如何在HomeAssistant智能家居系统中添加HACS集成并实现无公网IP远程连接家中设备

文章目录 基本条件一、下载HACS源码二、添加HACS集成三、绑定米家设备 ​ 上文介绍了如何实现群晖Docker部署HomeAssistant&#xff0c;通过内网穿透在户外控制家庭中枢。本文将介绍如何安装HACS插件商店&#xff0c;将米家&#xff0c;果家设备接入 Home Assistant。 基本条件…

Python the code is unreachable

Python the code is unreachable 正文 正文 相信有不少小伙伴在使用 Python 的时候有时候会遇到 the code is unreachable 这样的 warning 提示。这种提示表示在我们当前书写的代码种有一部分代码被屏蔽了。可能会存在潜在的 bug&#xff0c;需要我们注意&#xff0c;那么什么…

2023年蓝桥杯省赛——幸运数字

目录 题目链接&#xff1a;0幸运数字 - 蓝桥云课 (lanqiao.cn) 解法 思路 高级思路 总结 题目链接&#xff1a;0幸运数字 - 蓝桥云课 (lanqiao.cn) 解法 首先是我写了差不多一个小时的解法&#xff0c;裂开了&#xff0c;为什么我如此废物 思路 寻找第2023个在二进制、八…

弱电工程是什么?常见的类型有哪些?

一、什么是弱电工程?强电和弱电的区别有哪些? 弱电工程又叫智能建筑&#xff0c;也叫系统集成工程&#xff0c;所有与信息有关的都属于弱电这一块的。弱电是相对于强电而言的强电和弱电从概念上讲&#xff0c;一般是容易区别的&#xff0c;主要区别是用途的不同。强电是用作…

Compute Express Link (CXL): An Open Interconnect for Cloud Infrastructure——论文阅读

DAC 2023 Paper CXL论文阅读笔记整理 背景 Compute Express Link是一种开放的行业标准互连&#xff0c;在PCI Express&#xff08;PCIe&#xff09;之上提供缓存和内存语义&#xff0c;具有资源池和织物功能。本文探讨了CXL在解决云基础设施中的一些挑战方面的作用。 CXL主要…

Python:文件的操作

注意&#xff1a;本文引用自专业人工智能社区Venus AI 更多AI知识请参考原站 &#xff08;[www.aideeplearning.cn]&#xff09; Python的os库主要用于与操作系统进行交互&#xff0c;它提供了多种功能&#xff0c;使得在Python程序中处理操作系统级任务变得容易。这里是一些…

外包干了3个月,技术明显进步。。。。。

在湖南的一个安静角落&#xff0c;我&#xff0c;一个普通的大专生&#xff0c;开始了我的软件测试之旅。四年的外包生涯&#xff0c;让我在舒适区里逐渐失去了锐气&#xff0c;技术停滞不前&#xff0c;仿佛被时间遗忘。然而&#xff0c;生活的转机总是在不经意间降临。 与女…