歡迎你們前往騰訊雲+社區,獲取更多騰訊海量技術實踐乾貨哦~css
在本指南中,咱們將重點介紹Winston的日誌包,這是一個極其通用的日誌庫,是基於NPM下載統計信息,可用於Node.js應用程序的日誌記錄解決方案。Winston的功能包括支持多個存儲選項和日誌級別,日誌查詢,甚至是內置的分析器。本教程將展現如何使用Winston記錄咱們建立的Node/Express應用程序。還將研究如何將Winston與另外一個名爲Morgan的Node.js的HTTP請求中間件記錄器結合起來,以便將HTTP請求數據日誌與其餘信息進行整合。git
完成本教程後,您將擁有一個小型Node /Express應用程序的Ubuntu服務器。您還將用Winston將錯誤和消息輸出到文件和控制檯。github
在開始本指南以前,您須要如下內容:數據庫
不會搭建Nodejs的用戶能夠查看騰訊雲實驗室提供了搭建Nodejs環境的相關教程,有了這些準備,咱們就能夠構建咱們的應用程序並安裝Winston。express
Winston的一個常見用途是從使用Node.js構建的Web應用程序中記錄事件。爲了充分展現如何使用Winston,咱們將使用Express框架建立一個簡單的Node.js Web應用程序。咱們使用express-generator一個命令行工具來快速運行Node/ Express Web應用程序。由於咱們安裝了Node Package Manager,因此可使用npm命令進行安裝express-generator。咱們使用-g標誌來全局安裝軟件包。使用如下命令安裝軟件包:npm
$ sudo npm install express-generator -g
複製代碼
咱們可使用express命令建立咱們的應用程序,而後咱們想用咱們的項目目錄的名稱。這將建立咱們的應用程序,包含了咱們開始所需的一切:json
$ express myApp
複製代碼
接下來,安裝Nodemon,它會在咱們進行任何更改時自動從新加載應用程序。每當對源代碼進行更改時,都須要從新啓動Node.js應用程序。Nodemon將自動監視更改併爲咱們從新啓動應用程序。因爲咱們但願用nodemon做命令行工具,咱們將使用-g標誌全局安裝:瀏覽器
$ sudo npm install nodemon -g
複製代碼
要完成應用程序的設置,請切換到應用程序目錄並安裝依賴項,以下所示:bash
$ cd myApp
$ npm install
複製代碼
默認狀況下,使用express-generator
在端口3000上運行建立的應用程序,所以咱們須要確保防火牆不阻止該端口。要打開端口3000,請運行如下命令:
$ sudo ufw allow 3000
複製代碼
咱們如今擁有啓動Web應用程序所需的一切。爲此,請運行如下命令:
$ nodemon bin/www
複製代碼
這將啓動在端口3000上運行的應用程序。咱們能夠經過訪問Web瀏覽器來測試它是否正常工做。你應該看到這樣的東西:http://your_server_ip: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
,因爲快速發生器建立的樣板,應用程序已經設置爲響應這樣的錯誤。您的瀏覽器應顯示以下所示的錯誤消息(您的錯誤消息可能比顯示的更詳細)
如今再看看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/developer/article/1164177?fromSource=waitui
歡迎你們前往騰訊雲+社區或關注雲加社區微信公衆號(QcloudCommunity),第一時間獲取更多海量技術實踐乾貨哦~
海量技術實踐經驗,盡在雲加社區!