当前位置: 首页 > 后端技术 > Node.js

Node.JS应用程序的最佳实践:日志

时间:2023-04-03 10:29:39 Node.js

作者:MaheshHaldar从编写代码的第一天起就已经做了一些事情,但很少有人知道它可以产生的价值和最佳实践。在本文中,我们将讨论以下主题:什么是日志以及它们为何重要?记录日志重要部分的最佳实践正确使用日志记录级别为什么选择Winston?什么是日志,为什么它们很重要?日志是反映程序各个方面的事件,如果编写正确,是对程序进行故障排除和诊断的最简单模式。当你启动一个Node.js服务器时,如果数据库因为某些问题没有运行,或者服务器端口已经被占用,没有日志,你永远不知道服务器失败的原因。作为开发人员,经常需要调试一些问题,我们喜欢使用调试器和断点来定位失败的位置和内容。当您的程序在生产环境中运行时,您会做什么?你能在那里附加一个调试器并重现这个错误吗?很明显不是。所以这是日志可以帮助你的地方。在不使用调试器的情况下,您可以浏览日志来查找问题并了解出错的原因和位置。最佳实践1)日志记录的三个重要部分程序日志记录既适用于人,也适用于机器。人类通过日志来调试问题,机器通过日志生成各种图表,通过数据分析得出客户使用情况的各种结论。每个日志都应该包含三个最重要的部分:日志源当我们有一个微服务架构时,了解日志的来源、服务名称、区域、主机名等是非常重要的。阅读更多关于代码的信息)关于source主要由日志代理处理,它将日志从所有微服务推送到集中式日志系统。用于ELK堆栈的Filebeat是日志记录代理的最佳选择之一。事件发生或日志生成时的时间戳非常重要。因此,请确保每个日志都带有时间戳,以便我们进行排序和过滤。级别和上下文当查看日志以查找错误时,如果日志没有提供足够的信息并且您必须返回到代码,这可能会非常令人沮丧。因此,在记录日志时,我们应该传递足够的上下文,例如。没有上下文的日志将如下所示:操作失败!一个有意义的上下文应该是:创建用户失败,因为用户id已经存在2)如何使用日志日志方法和输入:在调试时,如果我们知道调用了哪个函数,传递了哪些参数,它就完成了它真正的工作。从'../logSetup'导入记录器;getInstallment(月份:数字,计数:数字):数字{logger.debug(`>>>>进入getInstallment(month=${month},count=${count}");//processconstinstallment:number=3;log.debug("<<<>>>和<<<<会给函数输入和退出信息。这是受gitmerge冲突的启发。日志不应评估抛出异常在第7行中,userService.getUser()可以返回null,而.getId()可以抛出异常,因此请避免这些情况。从“../logSetup”导入记录器;processLoan(...){logger.debug(">>>>进入processLoan()");//...processlogger.debug(`正在处理ID为${userService.getUser().getId()}`的用户贷款);//这可能会引发错误,当getUser返回未定义时logger.debug("<<<>>>EnteringcreateUser");//...processlogger.debug("Savinguserloan{}",userInfoRepository.save(userInfo))//不要这样做returntrue;}记录错误和详细信息在描述错误时,提及尝试过的内容和原因它失败了。记录失败的原因以及您接下来做了什么。importloggerfrom'../logSetup';processLoan(id:number,userId:number){try{getLoanDeatilsById()}catch(error){log.error(`FailedtodogetLoanDetailswithid${id},忽略它并尝试getLoanDetailsByUserId`,错误);//很好的例子:提供失败的原因,以及你是如何处理的。//例如这里失败我试图调用其他函数getLoanDetailsByUserId();}}如果你掉入catch部分错误,请注意哪个操作失败并提及你正在抛出错误。importloggerfrom'../logSetup';processLoan(id:number,userId:number){try{getLoanDeatilsById()}catch(error){log.error(`FailedtodogetLoanDetailswithid${id}因此抛出错误`,错误);//很好的例子:提供失败的原因,以及你是如何处理的。//例如这里失败我抛出throwerror;}}3)敏感信息这一系列日志应该反映用户在程序中的活动,以便调试更容易,并且应该记录错误以便尽快采取措施。日志中包含调用了哪些函数、输入了什么、在何处发生错误等信息。在进行日志记录时,我们必须确保不记录用户名和密码等敏感信息,例如信用卡号、CVV号和其他财务信息。作为开发人员,我们应该通过与产品团队沟通准备一份敏感信息列表,并在记录之前屏蔽它。4)日志级别的正确使用如果生产环境中的程序有相当数量的用户事务,理想的日志设置可能每天产生GB级别的日志,所以我们需要将日志分成多个组。根据受众,我们可以在运行时切换日志级别并仅获取适当的日志。例如,如果产品经理想在我们的日志记录仪表板中查看有多少客户交易成功或失败,他不应该看到各种函数调用的混乱,该信息仅供开发人员使用。当生产出现错误时,开发人员应该看到各种功能成功和失败的详细日志。这样可以尽快发现并解决问题。要实现此设置,我们需要更好地了解每个日志级别。让我们讨论最重要的级别及其用法:INFO:一些重要消息,描述任务完成时的事件消息。例如:NewUsercreatedwithidxxx这表示只记录进度信息。DEBUG:这个级别是为开发人员准备的,类似于你在使用调试器或断点时看到的日志信息,比如调用了哪个函数,传递了哪些参数等。它应该记录当前状态,这在当调试并找到确切的问题。警告:这些日志是警告,不会阻止应用程序继续运行,这些日志会在出现问题时提醒您并使用解决方法。示例包括不正确的用户输入、重试等。管理员应在将来修复这些警告。ERROR:当发生错误时,应先排查此处。例如,数据库与其他微服务之间的通信失败,或者未定义所需的输入。主要受众是系统操作员或监控系统。理想情况下,生产中的程序应该具有接近于零的错误日志记录。5)不要使用console.log大多数开发人员使用控制台模块作为获取日志或调试代码的第一个工具,因为它简单、容易且全局可用,无需设置。在Node.Js中,控制台的实现方式与浏览器不同,控制台模块在使用console.log时会在stdout中打印消息,在使用console.error时会打印到stderr。console.log、console.debug和console.info都打印到标准输出,因此我们无法关闭或打开调试和信息。同样,`console.warn和console.error都打印到stderr。生产环境程序难以在各个层级之间切换。我们还需要不同类型的配置,如标准格式、将JSON输出格式发送到ELK堆栈,这些在开箱即用的控制台中不可用。要克服所有这些问题,您可以使用Winston日志记录框架,还有一些其他选项,如Bunyan、Pino等。为什么需要像Winston这样的日志记录库?在上一节中我们讨论了控制台的一些不足,让我们列出一些Winston提供的重要功能:登录集中式仪表板。例如{message:“somethingwrong”,level:“error”}如果需要,您还可以创建自定义级别。格式:Winston有一些高级配置,比如给日志着色,输出JSON格式等等。动态更改日志级别:我们会在生产环境程序中启用警告和错误,可以根据需要更改日志级别进行调试和返回错误,无需重启程序。Winston具有开箱即用的此功能。//logsetupimportwinstonfrom'winston';consttransports={控制台:新温斯顿。运输。控制台({级别:'警告'}),};常量记录器=温斯顿。createLogger({transports:[transports.console,transports.file]});logger.info('这??不会记录在控制台传输中,因为设置了警告!');transports.console.level='info';//changedthelevellogger.info('Thiswillbeloggedinnow!');exportdefault{logger,transport}我们还可以公开一个API来动态更改级别,公开一个RESTAPI并在处理程序中执行第13行以改变水平。传输:对于生产,我们希望有一个集中的日志系统,所有微服务都将推送日志,我们将通过仪表板过滤和搜索日志。这是标准的ELK设置或等效设置。从“温斯顿”进口温斯顿;constlogger=winston.createLogger({level:'info',format:winston.format.json(),transports:[//newwinston.transports.File({filename:'stdout.log'})]});导出默认记录器;通过配置Winston将我们的日志写入文件,这样任何日志传送代理都可以将日志推送到集中式系统。然而,这超出了本文的范围,将在另一篇文章中详细讨论。6)性能影响如果程序频繁写入日志,可能会直接影响程序性能。DEBUG和INFO级别的日志可以占整体的95%以上,这就是为什么你应该只启用ERROR和WARN级别,当你想找出问题时将级别更改为DEBUG,然后再切换回ERROR.当您的应用程序出现问题时,日志是救命稻草。如果您目前没有很好地使用日志,请实施日志记录实践并将日志添加到您的代码审查清单中。