真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

深入研究Node.js中的日志信息

當你開始用 JavaScript 進行開發(fā)時,可能學到的第一件事就是如何用 console.log將內(nèi)容記錄到控制臺。如果你去搜索如何調(diào)試 JavaScript,會發(fā)現(xiàn)數(shù)百篇博文和 StackOverflow 文章都會簡單的告訴你用 console.log。因為這是一種很常見的做法,我們甚至會在代碼中使用像 no-console這樣的 linter 規(guī)則來確保不會留下意外的日志信息。但是如果我們真的想要去記錄某些內(nèi)容呢?

讓客戶滿意是我們工作的目標,不斷超越客戶的期望值來自于我們對這個行業(yè)的熱愛。我們立志把好的技術(shù)通過有效、簡單的方式提供給客戶,將通過不懈努力成為客戶在信息化領(lǐng)域值得信任、有價值的長期合作伙伴,公司提供的服務(wù)項目有:域名注冊網(wǎng)站空間、營銷軟件、網(wǎng)站建設(shè)、銅川網(wǎng)站維護、網(wǎng)站推廣。

在本文中,我們將梳理各種情況下要記錄的日志信息,Node.js 中 console.logconsole.error之間的區(qū)別是什么,以及如何在不發(fā)生混亂的情況下把你庫中的日志記錄輸出到用戶控制臺。

【視頻教程推薦:nodejs視頻教程 】

console.log(`Let's go!`);
理論先行:Node.js 的重要細節(jié)

雖然你可以在瀏覽器和 Node.js 中使用 console.logconsole.error,但在使用 Node.js 時要記住一件重要的事。當你在 Node.js 中將以下代碼寫入名為 index.js的文件中時:

console.log('Hello there');
console.error('Bye bye');

并用 node index.js在終端中執(zhí)行它,你會直接看到兩者的輸出:

雖然它們看起來可能一樣,但實際上系統(tǒng)對它們的處理方式是不同的。如果你查閱 Node.js 文檔的 console部分,會看到 console.log是輸出到 stdoutconsole .error用的是 stderr。

每個進程都有三個可用的默認 stream。那些是 stdin,stdoutstderrstdin流用來在處理進程的輸入。例如按下按鈕或重定向輸出。 stdout流用于程序的輸出。最后 stderr用于錯誤消息。如果你想了解為什么會有 stderr存在,以及應(yīng)該在什么時候使用它,可以查看這篇文章。

簡而言之,這允許我們在 shell 中使用重定向(>)和管道(|)來處理錯誤和診斷信息,它們是與程序的實際輸出結(jié)果是分開的。雖然 >允許我們將命令的輸出重定向到文件中,但是 2>允許我們將 stderr的輸出重定向到文件中。例如,下面這個命令會將 “Hello there” 傳給一個名為 hello.log的文件并把 “Bye bye” 傳到一個名為 error.log的文件中。

node index.js > hello.log 2> error.log

應(yīng)該在什么時候記錄日志?

現(xiàn)在我們已經(jīng)了解了日志記錄的底層技術(shù),接下來讓我們談?wù)剳?yīng)該在什么情況下記錄日志內(nèi)容。通常應(yīng)該是以下情況之一:

在開發(fā)過程中快速調(diào)試意外行為基于瀏覽器的分析或診斷日志記錄記錄你服務(wù)器上傳入的請求,以及所有可能發(fā)生的故障使用庫的日志調(diào)試選項來幫助用戶解決問題在 CLI 輸出進度、確認消息或錯誤信息

我們將跳過前兩種情況,并重點介紹基于 Node.js 的后三點。

服務(wù)器程序日志

可能你在服務(wù)器上記錄日志的原因有多種。例如記錄傳入的請求并允許你從中提取諸如統(tǒng)計信息之類的內(nèi)容,比如有多少用戶在點擊時發(fā)生了 404 錯誤,或者用戶瀏覽器的 User-Agent。你也想知道在什么時候因為什么出錯了。

如果你想編碼嘗試下面的內(nèi)容,請先創(chuàng)建一個新的項目目錄。在目錄中創(chuàng)建一個 index.js并運行以下命令來初始化項目并安裝 express

npm init -y
npm install express

讓我們設(shè)置一個帶有中間件的服務(wù)器,每個請求只需用 console.log進行輸出。將以下內(nèi)容復(fù)制到 index.js文件中:

const express = require('express');

const PORT = process.env.PORT || 3000;
const app = express();

app.use((req, res, next) => {
 console.log('%O', req);
 next();
});

app.get('/', (req, res) => {
 res.send('Hello World');
});

app.listen(PORT, () => {
 console.log('Server running on port %d', PORT);
});

在這里用 console.log('%O', req)來記錄整個對象的信息。 console.log在底層使用了 util.format來支持 %O占位符。你可以在 Node.js 文檔中查閱它們的細節(jié)。

當你運行 node index.js來啟動你的服務(wù)器并導航到 http://localhost:3000 時,會發(fā)現(xiàn)它會打印出很多我們確實需要但不知道的信息。

如果將其更改為 console.log('%s', req)不打印整個對象,我們就不會獲得更多信息。

![終端中輸出的 "[object Object]" 信息](https://s3.amazonaws.com/com....

可以通過編寫自己的日志函數(shù)只輸出我們關(guān)心的東西,但是先等等,談?wù)勎覀兺ǔjP(guān)心的東西。雖然這些信息經(jīng)常成為我們關(guān)注的焦點,但實際上可能還需要其他信息:

時間戳 - 知道事情何時發(fā)生計算機/服務(wù)器名稱 - 如果你運行的是分布式系統(tǒng)進程ID - 如果你用了 pm2來運行多個Node進程消息 - 包含某些內(nèi)容的實際消息可能會需要的其它變量或信息

既然一切都會被轉(zhuǎn)到 stdoutstderr,那么我們可能會想要不同的日志級別,還有配置和過濾日志的能力。

我們可以通過依賴 process的各個部分并編寫一堆 JavaScript 來獲得所有這些,但關(guān)于 Node.js 的好消息是有 npm這個生態(tài)系統(tǒng),里面已經(jīng)有了各種各樣的庫供我們使用。其中一些是:

pino winston roarr bunyan(請注意,這個已經(jīng) 2 年沒有更新了)

我更喜歡pino,因為它速度很快。接下來看看怎樣使用 pino來幫助我們記錄日志。同時我們可以用 express-pino-logger包來記錄請求。

安裝 pinoexpress-pino-logger

npm install pino express-pino-logger

用下面的代碼更新你的 index.js文件以使用 logger 和中間件:

const express = require('express');
const pino = require('pino');
const expressPino = require('express-pino-logger');

const logger = pino({ level: process.env.LOG_LEVEL || 'info' });
const expressLogger = expressPino({ logger });

const PORT = process.env.PORT || 3000;
const app = express();

app.use(expressLogger);

app.get('/', (req, res) => {
 logger.debug('Calling res.send');
 res.send('Hello World');
});

app.listen(PORT, () => {
 logger.info('Server running on port %d', PORT);
});

在這段代碼中,我們創(chuàng)建了一個 pino的實例 logger,并將其傳給 express-pino-logger創(chuàng)建一個新的 logger中間件來調(diào)用 app.use。另外,我們用 logger.info替換了服務(wù)器啟動時的 console.log,并在路由中添加了一個額外的 logger.debug來顯示不同的日志級別。

再次運行 node index.js重新啟動服務(wù)器,你會看到一個完全不同的輸出,它每一行打印一個 JSON。再次導航到 http://localhost:3000 ,你會看到添加了另一行JSON。

如果你檢查這些 JSON,將看到它包含所有前面所提到的信息,例如時間戳等。你可能還會注意到 logger.debug語句沒有打印出來。那是因為我們必須修改默認日志級別才能看到。當我們創(chuàng)建 logger實例時,將值設(shè)置為 process.env.LOG_LEVEL,這意味著我們可以通過它修改值,或接受默認的 info。通過執(zhí)行 LOG_LEVEL = debug node index.js,就可以調(diào)整日志級別。

在這之前要先解決一個問題,即現(xiàn)在的輸出不適合人類閱讀。pino遵循一種理念,為了提高性能,你應(yīng)該通過管道(使用 |)將輸出的任何處理移動到一個單獨的進程中。這包括使其可讀或?qū)⑵渖蟼鞯皆浦鳈C。這些被稱為 transports??梢酝ㄟ^查看 transports文檔了解為什么 pino中的錯誤不會寫入 stderr

讓我們用工具 pino-pretty來查看更易閱讀的日志版本。在你的終端中運行:

npm install --save-dev pino-pretty
LOG_LEVEL=debug node index.js | ./node_modules/.bin/pino-pretty

現(xiàn)在所有的日志都被用 |運算符輸入給 pino-pretty命令,你的輸出應(yīng)該會經(jīng)過美化,并且還會包含一些關(guān)鍵信息,而且應(yīng)該是彩色的。如果再次請求 http://localhost:3000 ,你還應(yīng)該看到debug消息。

有各種各樣的 transports 來美化或轉(zhuǎn)換你的日志。你甚至可以用 pino-colada顯示 emoji。這些對你的本地開發(fā)很有用。在生產(chǎn)中運行服務(wù)器之后,你可能希望將日志傳輸?shù)搅硪粋€ transports,再用 >或者用像 tee) 這樣的命令將它們寫入磁盤以便稍后處理。

這個文檔 中還將包含有關(guān)輪換日志文件、過濾和把日志寫入不同文件等內(nèi)容的信息。

庫的日志

現(xiàn)在討論一下怎樣有效地為我們的服務(wù)器程序編寫日志,為什么不對我們的庫使用相同的技術(shù)呢?

問題是你的庫可能希望通過記錄日志來進行調(diào)試,但是不應(yīng)該與使用者的程序相混淆。如果需要調(diào)試某些內(nèi)容,使用者應(yīng)該能夠啟用日志。默認情況下,你的庫應(yīng)該是靜默的,并將是否輸出日志的決策權(quán)留給用戶。

一個很好的例子是 express。 express的底層有很多東西,你可能想在調(diào)試自己的程序時偷看它。如果我們查閱 express文檔,就會注意到你可以在自己的命令之前添加 DEBUG=express:*,如下所示:

DEBUG=express:* node index.js

如果你運行這個命令,將看到許多其他的輸出,這些可幫助你調(diào)試程序中的問題。

如果你沒有啟用調(diào)試日志記錄,則不會看到任何此類日志。這是通過一個稱為 debug的包來完成的。它允許我們在“命名空間”下編寫日志消息,如果庫的用戶包含該命名空間或在 DEBUG環(huán)境變量 中匹配了它的通配符,就會輸出這些。要使用 debug庫,首先要安裝它:

npm install debug

讓我們通過創(chuàng)建一個名為 random-id.js的新文件來模擬我們的庫,并將以下代碼復(fù)制到其中:

const debug = require('debug');

const log = debug('mylib:randomid');

log('Library loaded');

function getRandomId() {
 log('Computing random ID');
 const outcome = Math.random()
   .toString(36)
   .substr(2);
 log('Random ID is "%s"', outcome);
 return outcome;
}

module.exports = { getRandomId };

這將創(chuàng)建一個帶有命名空間 mylib:randomid的新 debug記錄器,然后將兩條消息輸出到日志。讓我們在前面的 index.js中使用它:

const express = require('express');
const pino = require('pino');
const expressPino = require('express-pino-logger');

const randomId = require('./random-id');

const logger = pino({ level: process.env.LOG_LEVEL || 'info' });
const expressLogger = expressPino({ logger });

const PORT = process.env.PORT || 3000;
const app = express();

app.use(expressLogger);

app.get('/', (req, res) => {
 logger.debug('Calling res.send');
 const id = randomId.getRandomId();
 res.send(`Hello World [${id}]`);
});

app.listen(PORT, () => {
 logger.info('Server running on port %d', PORT);
});

如果用 DEBUG=mylib:randomid node index.js重新運行我們的服務(wù)器,它會打印前面“庫”的調(diào)試日志。

如果你的庫的用戶想要將這個調(diào)試信息放到他們的 pino日志中,他們可以用 pino團隊開發(fā)的名為 pino-debug的庫來正確的格式化這些日志。

用以下命令安裝庫:

npm install pino-debug

在我們第一次使用debug之前,需要初始化pino-debug。最簡單的方法是在啟動 javascript 腳本的命令之前使用 Node.js 的 -r--require標志來 require 模塊。使用如下命令重新運行你的服務(wù)器(假設(shè)你安裝了pino-colada):

DEBUG=mylib:randomid node -r pino-debug index.js | ./node_modules/.bin/pino-colada

你現(xiàn)在將用與程序日志相同的格式查看庫的調(diào)試日志。

CLI 輸出

本文介紹的最后一個案例是針對 CLI 進行日志記錄的特殊情況。我的理念是將“邏輯日志”與 CLI 的輸出 “日志” 分離。對于所有的邏輯日志,你應(yīng)該用像 debug這樣的庫。這樣你或其他人就可以重新使用該邏輯,而不受 CLI 的特定用例的約束。

當你用 Node.js 構(gòu)建 CLI 時,可能希望添加一些看上去很漂亮顏色,或者用有視覺吸引力的方式格式化信息。但是,在構(gòu)建 CLI 時,應(yīng)該記住以下這幾種情況。

一種情況是你的 CLI 可能會在持續(xù)集成(CI)系統(tǒng)的上下文中使用,因此你可能希望刪除顏色和花哨的裝飾輸出。一些 CI 系統(tǒng)設(shè)置了一個名為 CI的環(huán)境標志。如果你想更安全地檢查自己是否在 CI 中,那就是使用像 is-ci這樣的包去支持一堆 CI 系統(tǒng)。

chalk這樣的庫已經(jīng)為你檢測了CI 并為你刪除了顏色。我們來看看它的樣子。

使用 npm install chalk安裝 chalk并創(chuàng)建一個名為 cli.js的文件。將以下內(nèi)容復(fù)制到其中:

const chalk = require('chalk');

console.log('%s Hi there', chalk.cyan('INFO'));

Now if you would run this script using node cli.jsyou'll see colored output.
現(xiàn)在如果你用 node cli.js運行這個腳本,將會看到彩色輸出。

但是如果你用 CI=true node cli.js運行它,你會看到顏色被消除了:

你要記住的另一個場景是 stdout是否以終端模式運行,也就是將內(nèi)容寫入終端。如果是這種情況,我們可以使用 boxen之類的東西顯示所有漂亮的輸出。如果不是,則可能會將輸出重定向到文件或用管道傳輸?shù)侥程帯?/p>

你可以通過檢查相應(yīng)流上的 isTTY屬性來檢查 stdin、stdoutstderr是否處于終端模式。例如:process.stdout.isTTY。 TTY的意思是 “電傳打印機(teletypewriter)”,在這種情況下專門用于終端。

根據(jù) Node.js 進程的啟動方式,這三個流每個流的值可能不同。你可以在 Node.js 文檔的"process I/O" 這一部分中詳細了解它。

讓我們來看看 process.stdout.isTTY的值在不同情況下是如何變化的。先更新你的 cli.js

const chalk = require('chalk');

console.log(process.stdout.isTTY);
console.log('%s Hi there', chalk.cyan('INFO'));

在終端中運行 node cli.js,你會看到輸出的 true被著色了。

之后運行相同的內(nèi)容,但是將輸出重定向到一個文件,然后檢查內(nèi)容:

node cli.js > output.log
cat output.log

你會看到這次它打印了 undefined后面跟著一個簡單的無色消息,因為 stdout的重定向關(guān)閉了它的終端模式。因為 chalk用了 supports-color,它們會在相應(yīng)的流上檢查 isTTY。

chalk這樣的工具已經(jīng)為你處理了這種行為,但是在開發(fā) CLI 時,你應(yīng)該始終了解 CLI 可能在 CI 模式下運行或重定向輸出的情況。它還可以幫助你進一步獲得 CLI 的體驗。例如你可以在終端中以漂亮的方式排列數(shù)據(jù),如果isTTYundefined,你可以切換到更容易解析的方式。

總結(jié)

剛開始用 JavaScript 開發(fā)時用 console.log記錄你的第一行日志確實很快,但是當你將代碼投入生產(chǎn)環(huán)境時,應(yīng)該考慮更多關(guān)于日志記錄的內(nèi)容。本文純粹是對各種方式和可用的日志記錄解決方案的介紹。我建議你去看一些自己喜歡的開源項目,看看它們是怎樣解決日志記錄問題的,還有它們所用到的工具。

如果你知道或找到了我沒有提及的工具,或者有什么疑問,請留言。

原文地址: https://www.twilio.com/blog/guide-node-js-logging

相關(guān)推薦:node js教程
標題名稱:深入研究Node.js中的日志信息
鏈接分享:http://weahome.cn/article/cgepph.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部