欢迎你们前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~css
本文由 姚啊姚 发表于 云+社区专栏
在本指南中,咱们将重点介绍Winston的日志包,这是一个极其通用的日志库,是基于NPM下载统计信息,可用于Node.js应用程序的日志记录解决方案。Winston的功能包括支持多个存储选项和日志级别,日志查询,甚至是内置的分析器。本教程将展现如何使用Winston记录咱们建立的Node/Express应用程序。还将研究如何将Winston与另外一个名为Morgan的Node.js的HTTP请求中间件记录器结合起来,以便将HTTP请求数据日志与其余信息进行整合。node
完成本教程后,您将拥有一个小型Node /Express应用程序的Ubuntu服务器。您还将用Winston将错误和消息输出到文件和控制台。git
在开始本指南以前,您须要如下内容:github
不会搭建Nodejs的用户能够查看腾讯云实验室提供了搭建Nodejs环境的相关教程,有了这些准备,咱们就能够构建咱们的应用程序并安装Winston。数据库
Winston的一个常见用途是从使用Node.js构建的Web应用程序中记录事件。为了充分展现如何使用Winston,咱们将使用Express框架建立一个简单的Node.js Web应用程序。咱们使用express-generator一个命令行工具来快速运行Node/ Express Web应用程序。由于咱们安装了Node Package Manager,因此可使用npm命令进行安装express-generator。咱们使用-g标志来全局安装软件包。使用如下命令安装软件包:express
$ sudo npm install express-generator -g
咱们可使用express命令建立咱们的应用程序,而后咱们想用咱们的项目目录的名称。这将建立咱们的应用程序,包含了咱们开始所需的一切:npm
$ express myApp
接下来,安装Nodemon,它会在咱们进行任何更改时自动从新加载应用程序。每当对源代码进行更改时,都须要从新启动Node.js应用程序。Nodemon将自动监视更改并为咱们从新启动应用程序。因为咱们但愿用nodemon做命令行工具,咱们将使用-g标志全局安装:json
$ sudo npm install nodemon -g
要完成应用程序的设置,请切换到应用程序目录并安装依赖项,以下所示:浏览器
$ cd myApp $ npm install
默认状况下,使用express-generator
在端口3000上运行建立的应用程序,所以咱们须要确保防火墙不阻止该端口。要打开端口3000,请运行如下命令:服务器
$ sudo ufw allow 3000
咱们如今拥有启动Web应用程序所需的一切。为此,请运行如下命令:
$ nodemon bin/www
这将启动在端口3000上运行的应用程序。咱们能够经过访问Web浏览器来测试它是否正常工做。你应该看到这样的东西:http://your_server_ip:3000
localhost:3000
目前为止咱们一直使用的SSH会话,而且当前正在运行应用程序做为会话A.咱们将使用新的SSH会话来运行命令和编辑文件,咱们将此会话称为会话B.除非另有说明,不然全部剩余命令应在会话B中运行。
建立的默认应用程序在express-generator启动方面作得很好,甚至包括咱们用于记录有关HTTP请求的数据的Morgan HTTP日志记录中间件。因为Morgan支持输出流,所以它与Winston内置的流支持很好地配对,使咱们可以将HTTP请求数据日志与Winston记录的任何其余内容进行整合。
默认状况下,express-generator样板文件在引用包时使用变量记录器morgan。因为咱们将使用morgan和winston,这两个都是记录包,调用其中一个记录器都会变得很困惑。所以,让咱们经过编辑app.js项目根目录中的文件并进行一些更改来改变它。
要打开app.js进行编辑,请使用如下nano命令:
$ nano \~/myApp/app.js
在文件顶部附近找到如下行:
~/myApp/app.js
... var logger = require('morgan'); ...
将其更改成如下内容:
~/myApp/app.js
... var morgan = require('morgan'); ...
咱们还须要找到文件中引用变量记录器的位置并将其更改成morgan。在咱们使用它时,让咱们将morgan包使用的日志格式更改combined为标准的Apache日志格式,并在日志中包含有用信息,例如远程IP地址和用户代理HTTP请求标头。
为此,请找到如下行:
~/myApp/app.js
... app.use(logger('dev')); ...
将其更改成如下内容:
~/myApp/app.js
... app.use(morgan('combined')); ...
在咱们集成Winston配置后,这些更改将有助于咱们更好地了解日志包。经过输入CTRL-X,而后Y,而后ENTER来退出并保存文件。
如今咱们的应用程序已经创建,咱们已准备好开始Winston配置。
咱们如今准备安装和配置Winston。在这一步,咱们将探讨做为winston软件包的一些配置选项,并建立一个将信息记录到文件和控制台的记录器。
要安装,请winston运行如下命令:
$ cd ~/myApp $ npm install winston
建立一个包含winston配置的config文件夹:
$ mkdir ~/myApp/config
如今让咱们建立包含咱们winston配置的文件,咱们将调用它winston.js:
$ touch ~/myApp/config/winston.js
接下来,建立一个包含日志文件的文件夹:
$ mkdir ~/myApp/logs
最后,让咱们安装app-root-path
。此程序包与Winston没有直接关系,但在Node.js代码中指定文件路径时会有很大帮助。咱们将使用它来指定项目根目录中的Winston日志文件的位置,并避免丑陋的相对路径语法:
$ npm install app-root-path --save
咱们须要配置咱们想要如何处理日志记录的全部内容,所以咱们能够继续定义配置设置。首先打开~/myApp/config/winston.js
编辑:
$ nano ~/myApp/config/winston.js
接下来,须要app-root-path
和winston
包:
~/myApp/config/winston.js
var appRoot = require('app-root-path'); var winston = require('winston');
有了这些变量,咱们能够为传输定义配置设置。传输是Winston引入的一个概念,它指的是用于日志的存储/输出机制。Winston带有三个核心传输元素-控制台,文件和HTTP。本教程专一于控制台和文件传输:控制台传输将信息记录传输到控制台,文件传输将信息记录传输到指定的文件。每一个传输定义均可以包含本身的配置设置,例如文件大小,日志级别和日志格式。如下是咱们将使用的每一个传输设置的快速摘要:
记录级别表示消息优先级,并由整数表示。Winston使用npm优先级从0到5(从最高到最低)的日志记录级别:
指定特定传输的日志记录级别时,将记录该级别或更高级别的任何内容。例如,经过指定信息级别,将记录级别为错误,警告或信息的任何内容。调用记录器时指定了日志级别,这意味着咱们能够执行如下操做来记录错误:logger.error('test error message').
咱们能够在配置中定义file和console传输的配置设置,winston以下所示:
~/myApp/config/winston.js
... var options = { file: { level: 'info', filename: `${appRoot}/logs/app.log`, handleExceptions: true, json: true, maxsize: 5242880, // 5MB maxFiles: 5, colorize: false, }, console: { level: 'debug', handleExceptions: true, json: false, colorize: true, }, };
接下来,使用options
变量中定义的属性实例化具备文件和控制台传输的新winston
记录器:
~/myApp/config/winston.js
... var logger = new winston.Logger({ transports: [ new winston.transports.File(options.file), new winston.transports.Console(options.console) ], exitOnError: false, // do not exit on handled exceptions });
默认状况下,只有morgan输出到控制台,因此让咱们定义一个流函数,它能够将morgan生成的输出生成到winston日志文件中。咱们将使用该info级别,所以输出将由两个传输(文件和控制台)拾取:
~/myApp/config/winston.js
... logger.stream = { write: function(message, encoding) { logger.info(message); }, };
最后,导出记录器,以便它能够在应用程序的其余部分中使用:
~/myApp/config/winston.js
... module.exports = logger;
完成的winston配置文件应以下所示:
~/myApp/config/winston.js
var appRoot = require('app-root-path'); var winston = require('winston'); // define the custom settings for each transport (file, console) var options = { file: { level: 'info', filename: `${appRoot}/logs/app.log`, handleExceptions: true, json: true, maxsize: 5242880, // 5MB maxFiles: 5, colorize: false, }, console: { level: 'debug', handleExceptions: true, json: false, colorize: true, }, }; // instantiate a new Winston Logger with the settings defined above var logger = new winston.Logger({ transports: [ new winston.transports.File(options.file), new winston.transports.Console(options.console) ], exitOnError: false, // do not exit on handled exceptions }); // create a stream object with a 'write' function that will be used by `morgan` logger.stream = { write: function(message, encoding) { // use the 'info' log level so the output will be picked up by both transports (file and console) logger.info(message); }, }; module.exports = logger;
退出并保存文件。咱们如今配置了记录器,但咱们的应用程序仍然没有意识到它或如何使用它。咱们如今将记录器与应用程序集成在一块儿。
咱们已经在步骤2中看到咱们app.js中的快速配置,因此让咱们将记录器导入到该文件中。运行如下命令打开文件进行编辑:
$ nano ~/myApp/app.js
winston使用其余命令语句在文件顶部附近导入:
~/myApp/app.js
... var winston = require('./config/winston'); ...
咱们实际使用winston
的第一个地方是morgan
。咱们将使用stream
选项,并将其设置为咱们在winston
配置中建立的流接口。为此,请找到如下行:
~/myApp/app.js
... app.use(morgan('combined')); ...
把它改为这个:
~/myApp/app.js
... app.use(morgan('combined', { stream: winston.stream })); ...
退出并保存文件。
咱们将看到一些日志数据了!若是您在Web浏览器中从新加载页面,您应该在SSH会话A的控制台中看到相似于如下内容的内容:
[nodemon] restarting due to changes... [nodemon] starting `node bin/www` info: ::ffff:72.80.124.207 - - [07/Mar/2018:17:29:36 +0000] "GET / HTTP/1.1" 304 - "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36" info: ::ffff:72.80.124.207 - - [07/Mar/2018:17:29:37 +0000] "GET /stylesheets/style.css HTTP/1.1" 304 - "http://167.99.4.120:3000/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36"
这里有两个日志条目 -第一个用于HTML页面的请求,第二个用于附带的样式表。因为每一个传输都配置为处理info
级别日志数据,咱们还应该在位于\~/myApp/logs/app.log
的文件传输中看到相似的信息。可是,文件传输中的输出应该写为JSON对象,由于咱们json:true
在文件传输配置中指定了它。您能够在咱们的JSON教程简介中了解有关JSON的更多信息。要查看日志文件的内容,请运行如下命令:
$ tail ~/myApp/logs/app.log
您应该看到相似于如下内容的内容:
{"level":"info","message":"::ffff:72.80.124.207 - - [07/Mar/2018:17:29:36 +0000] \"GET / HTTP/1.1\" 304 - \"-\" \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36\"\n","timestamp":"2018-03-07T17:29:36.962Z"} {"level":"info","message":"::ffff:72.80.124.207 - - [07/Mar/2018:17:29:37 +0000] \"GET /stylesheets/style.css HTTP/1.1\" 304 - \"http://167.99.4.120:3000/\" \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36\"\n","timestamp":"2018-03-07T17:29:37.067Z"}
到目前为止,咱们的记录器只记录HTTP请求和相关数据。这是咱们日志中很是重要的信息,有时候咱们须要记录自定义日志消息来记录错误或分析数据库查询性能。为了说明咱们如何作到记录自定义日志消息,让咱们从错误处理程序路由调用记录器。
该express-generator软件包默认包含404和500错误处理程序路由,所以咱们将使用它。打开~/myApp/app.js文件:
$ nano ~/myApp/app.js
找到文件底部的代码块,以下所示:
~/myApp/app.js
... // error handler app.use(function(err, req, res, next) { // set locals, only providing error in development res.locals.message = err.message; res.locals.error = req.app.get('env') === 'development' ? err : {}; // render the error page res.status(err.status || 500); res.render('error'); }); ...
这是最终的错误处理路由,最终将错误响应发送回客户端。因为全部服务器端错误都将经过此路由运行,所以这是包含winston记录器的好地方。
由于咱们如今正在处理错误,因此咱们但愿使用error日志级别。一样,两个传输都配置为记录error级别消息,所以咱们应该在控制台和文件日志中看到输出。咱们能够在日志中包含咱们想要的任何内容,所以请务必包含一些有用的信息,例如:
更新错误处理程序路由以匹配如下内容:
~/myApp/app.js
... // error handler app.use(function(err, req, res, next) { // set locals, only providing error in development res.locals.message = err.message; res.locals.error = req.app.get('env') === 'development' ? err : {}; // add this line to include winston logging winston.error(`${err.status || 500} - ${err.message} - ${req.originalUrl} - ${req.method} - ${req.ip}`); // render the error page res.status(err.status || 500); res.render('error'); }); ...
退出并保存文件。为了测试这个,让咱们尝试访问咱们项目中不存在的页面,这将引起404错误。返回Web浏览器,尝试加载如下URL:http://your_server_ip:3000/foo
,因为快速发生器建立的样板,应用程序已经设置为响应这样的错误。您的浏览器应显示以下所示的错误消息(您的错误消息可能比显示的更详细)
localhost:3000
如今再看看SSH会话A中的控制台。应该有一个错误的日志条目,而且因为colorize设置,它应该很容易找到。
[nodemon] starting `node bin/www` error: 404 - Not Found - /foo - GET - ::ffff:72.80.124.207 info: ::ffff:72.80.124.207 - - [07/Mar/2018:17:40:11 +0000] "GET /foo HTTP/1.1" 404 985 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36" info: ::ffff:72.80.124.207 - - [07/Mar/2018:17:40:11 +0000] "GET /stylesheets/style.css HTTP/1.1" 304 - "http://167.99.4.120:3000/foo" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36"
至于文件记录器,tail再次运行该命令时,应该向咱们显示新的日志记录:
$ tail ~/myApp/logs/app.log
您将看到以下消息:
{"level":"error","message":"404 - Not Found - /foo - GET - ::ffff:72.80.124.207","timestamp":"2018-03-07T17:40:10.622Z"}
错误消息包括咱们专门指示winston做为错误处理程序的一部分记录的全部数据,包括错误状态(404 -未找到),请求的URL(localhost / foo),请求方法(GET),IP地址发出请求,以及发出请求的时间戳。
在本教程中,您构建了一个简单的Node.js Web应用程序并集成了Winston日志记录解决方案。您能够为应用程序构建强大的日志记录解决方案,尤为是在您的需求变得更加复杂时。咱们建议您花点时间查看其余一些文档:
若是您对NodeJs感兴趣,能够访问腾讯云实验查看Nodejs实验相关的更多内容。
参考文献:《How To Use Winston to Log Node.js Applications》
问答
相关阅读
此文已由做者受权腾讯云+社区发布,原文连接:https://cloud.tencent.com/dev...
欢迎你们前往腾讯云+社区或关注云加社区微信公众号(QcloudCommunity),第一时间获取更多海量技术实践干货哦~
海量技术实践经验,尽在云加社区!