成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Node.js 日志輸出指南

csRyan / 3243人閱讀

摘要:將如下代碼寫入到文件中,并在環(huán)境里執(zhí)行如圖雖然這兩個(gè)輸出看起來可能一樣,但系統(tǒng)實(shí)際上對(duì)它的處理方式有不同。如圖如果你沒有啟動(dòng)調(diào)試日志,則不會(huì)看到任何這樣的日志輸出。

原文地址: https://www.twilio.com/blog/g...

原文作者: DOMINIK KUNDEL

翻譯作者: icepy

翻譯出處: https://github.com/lightningm...

當(dāng)你開始使用 JavaScript 做開發(fā)時(shí),你可能學(xué)習(xí)到的第一件事情就是如何使用 console.log 將內(nèi)容打印到控制臺(tái)。如果你搜索如何調(diào)試 JavaScript,你會(huì)發(fā)現(xiàn)數(shù)百個(gè)博客文章和 StackOverflow 的文章都指向簡(jiǎn)單的 console.log 。因?yàn)檫@是一種常見的做法,我們甚至可以使用 no-console 這樣的規(guī)則來確保生產(chǎn)環(huán)境不會(huì)留下日志。但是,如果我們真的想要記錄這些信息呢?

在這篇博文中,我們將介紹你想要記錄信息的各種情況,Node.js 中的 console.logconsole.error 之間的區(qū)別是什么,以及如何在不使用戶控制臺(tái)混亂的情況下在庫(kù)中發(fā)送日志記錄。

console.log(`Let"s go!`);
Theory First: Important Details for Node.js

雖然你可以在瀏覽器和 Node.js 環(huán)境中使用 console.logconsole.error,但在 Node.js 中使用時(shí)一定要記住一件重要的事情。

將如下代碼寫入到 index.js 文件中,并在 Node.js 環(huán)境里執(zhí)行:

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

如圖:

雖然這兩個(gè)輸出看起來可能一樣,但系統(tǒng)實(shí)際上對(duì)它的處理方式有不同。如果你檢查一下 console section of the Node.js documentation 你會(huì)發(fā)現(xiàn) console.log 使用 stdout 打印而 console.error 則使用 stderr。

每一個(gè)進(jìn)程都有三個(gè)可以使用的默認(rèn) streams,它們是 stdin ,stdoutstderrstdin 可以處理進(jìn)程的輸入,例如按下按鈕或重定向輸出。stdout 可以用于處理進(jìn)程的輸出。最后 stderr 則用于錯(cuò)誤消息。如果你想了解 stderr 為什么存在以及何時(shí)使用它,可以訪問:When to use STDERR instead of STDOUT。

簡(jiǎn)而言之,這允許我們使用重定向 > 和管道 | 運(yùn)算符來處理與應(yīng)用程序的實(shí)際結(jié)果分開的錯(cuò)誤和診斷信息。而 > 允許我們將命令的輸出重定向到文件,2> 允許我們將 stderr 的輸出重定向到文件。我們來看一個(gè)例子,它會(huì)將 Hello there 重定向輸出到 hello.log ,Bye bye 重定向輸出到 error.log。:

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

如圖:

When Do You Want to Log?

現(xiàn)在我們已經(jīng)了解了日志記錄的基礎(chǔ)技術(shù),那么讓我們來談?wù)勀憧赡芟胍涗浤承﹥?nèi)容的不同例子,通常這些例子都屬于以下類別之一:

快速調(diào)試開發(fā)階段的意外行為

基于瀏覽器的分析和診斷日志記錄

記錄服務(wù)器應(yīng)用程序傳入的請(qǐng)求以及可能發(fā)生的任何故障

某些庫(kù)的可選調(diào)試日志

CLI的進(jìn)度輸出

我們將跳過本博文中的前兩篇文章,并將重點(diǎn)介紹基于Node.js的三篇文章。

Your Server Application Logs

你希望在服務(wù)器上記錄內(nèi)容的原因可能有多種,例如:記錄傳入的請(qǐng)求,統(tǒng)計(jì)信息,有多少404用戶正在訪問,另外你也想知道什么時(shí)候出錯(cuò)以及為什么。

初始化項(xiàng)目:

$ npm init -y
$ npm install express

讓我們?cè)O(shè)置一個(gè)帶有中間件的服務(wù)器,只需要 console.log 為你的請(qǐng)求提供打?。?/p>

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); 來記錄整個(gè)對(duì)象。

當(dāng)你運(yùn)行 node index.js 并訪問 http://localhost:3000 你會(huì)注意到打印的很多信息并不是我們需要的。

如果將起更改為 console.log("%s",req) 我們也不會(huì)獲取太多的信息。

我們可以編寫自己的日志功能,只打印我們關(guān)心的信息。但讓我們先退一步,談?wù)勎覀兺ǔjP(guān)心的事情。雖然這些信息經(jīng)常成為我們關(guān)注的焦點(diǎn),但實(shí)際上我們可能需要其他信息,例如:

時(shí)間戳-知道事情何時(shí)發(fā)生

計(jì)算機(jī)/服務(wù)器名稱-如果你運(yùn)行的是分布式系統(tǒng)的話

進(jìn)程ID-如果你使用 pm2 運(yùn)行著多個(gè) Node.js 進(jìn)程

消息-包含某些內(nèi)容的實(shí)際消息

堆棧追蹤

也許是一些額外的變量或信息

另外,既然我們知道打印最后都會(huì)落到 stdoutstderr 上,那么我們可能想要不同日志級(jí)別的記錄以及過濾它的能力。

我們可以通過訪問流程的各個(gè)部分并編寫一堆 JavaScript 代碼來獲取上述的信息,但 npm 生態(tài)已經(jīng)給我們提供了各種各樣的庫(kù)來使用,例如:

pino

winston

roarr

bunyan

我個(gè)人喜歡 pino,因?yàn)樗俣瓤?,生態(tài)全。那么,讓我們來看一看 pino 是如何幫助我們記錄日志的。

$ npm install pino express-pino-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);
});

運(yùn)行 node index.js 并訪問 http://localhost:3000 你可以看到一行一行的 JSON 輸出:

如果你檢查此 JSON ,你會(huì)看到前面提到的時(shí)間戳。你可能還注意到了我們 logger.debug 語(yǔ)句并未打印,那是因?yàn)槲覀儽仨毟哪J(rèn)日志級(jí)別才能使其可見,試試 LOG_LEVEL=debug node index.js 來調(diào)整日志級(jí)別。

在此之前我們還需要解決一下日志信息的可讀性,pino 遵循了一個(gè)理念,就是為了性能,你應(yīng)該通過管道將輸出的處理移動(dòng)到多帶帶的進(jìn)程中,你可以去查看一下文檔,了解其中 pino 的錯(cuò)誤為什么不會(huì)寫入 stderr。

讓我們使用 pino-pretty 工具來查看更易讀的日志:

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

運(yùn)行 LOG_LEVEL=debug node index.js | ./node_modules/.bin/pino-pretty 并訪問 http://localhost:3000。

如圖:

另外還有各種各樣的庫(kù)可以來美化你的日志,甚至你可以使用 pino-coladaemojis 來顯示它們。這些對(duì)于你的本地開發(fā)非常有用,在運(yùn)行到生產(chǎn)服務(wù)器之后,你可能希望將日志的管道轉(zhuǎn)移到另外一個(gè)管道,使用 > 將它們寫入硬盤以便稍后處理它們。

比如:

$ LOG_LEVEL=debug node index.js | ./node_modules/.bin/pino-pretty | > success.log 2> s_error.log
Your Library Logs

既然我們研究了如何有效的為服務(wù)器應(yīng)用程序編寫日志,那么為什么不能將它用在我們的某些庫(kù)中呢?問題是,你的庫(kù)可能希望記錄用于調(diào)試的內(nèi)容,但實(shí)際上不應(yīng)該讓使用者的應(yīng)用程序變得混亂。相反,如果需要調(diào)試某些東西,使用者應(yīng)該能夠啟動(dòng)日志。你的庫(kù)默認(rèn)情況下不會(huì)處理這些,并將輸入輸出的操作留給使用者。

express 就是一個(gè)很好的例子。

express 框架下有很多事情要做,在調(diào)試應(yīng)用程序時(shí),你可能希望了解一下框架的內(nèi)容。如果我們查詢文檔,你會(huì)注意到你可以在命令行的前面加上 DEBUG=express:* 來啟動(dòng)。

$ DEBUG=express:* node index.js

如圖:

如果你沒有啟動(dòng)調(diào)試日志,則不會(huì)看到任何這樣的日志輸出。這是通過一個(gè)叫 debug 的包來完成的。

$ npm install debug

讓我們創(chuàng)建一個(gè)新的文件 random-id.js 來使用它:

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 };

這里會(huì)創(chuàng)建一個(gè)帶有命名空間為 mylib:randomiddebug 記錄器,然后會(huì)將這兩種消息記錄上去。

我們可以在 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 來重新運(yùn)行你的 index.js 文件,如圖:

有意思的是,如果你的庫(kù)使用者想把這些調(diào)試信息集成到自己的 pino 日志中去,那么他們可以使用一個(gè)叫 pino-debug 的庫(kù)來正確的格式化這些日志。

$ npm install pino-debug

pino-debug 在我們第一次使用之前需要初始化一次 debug,最簡(jiǎn)單的方法就是在啟動(dòng)之前使用 Node.js 的 -r--require 命令來初始化。

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

如圖:

Your CLI Output

我將在這篇博文中介紹最后一個(gè)案例,針對(duì) CLI 的日志記錄。我的理念是將邏輯日志和你的 CLI 輸出分開。對(duì)于任何邏輯日志來說,你應(yīng)該使用類似 debug 這樣的包。這樣你或其他人就可以重寫邏輯,而不受 CLI 的約束。

一種情況是你的 CLI 在持續(xù)集成的系統(tǒng)中被使用,因此你可能希望刪除各種花里胡哨的輸出。有些 CI 系統(tǒng)設(shè)置了一個(gè)被稱為 CI 的環(huán)境標(biāo)志。如果你想更安全的檢查自己是否在 CI 系統(tǒng)中,你可以使用 is-ci 這個(gè)庫(kù)。

有些庫(kù)例如 chalk 已經(jīng)為你檢查了 CI 并幫你刪除了顏色。

$ npm install chalk
const chalk = require("chalk");

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

運(yùn)行 node cli.js,如圖:

當(dāng)你運(yùn)行 CI=true node cli.js,如圖:

你要記住的是另外一個(gè)場(chǎng)景 stdout 能否在終端模式中運(yùn)行。如果是這種情況,我們可以使用類似 boxen 的東西來顯示所有漂流的輸出。但如果不是,則可能會(huì)將輸出重定向到文件或輸出到其他地方。

你可以使用 isTTY 來檢查 stdout,stdin,stderr 是否在終端模式。

如:

process.stdout.isTTY

根據(jù) Node.js 的啟動(dòng)方式,這個(gè)三個(gè)的值可能不同。你可以在文檔中找到更多關(guān)于它的信息。

讓我們看看 process.stdout.isTTY 在不同情況下的變化:

const chalk = require("chalk");
console.log(process.stdout.isTTY);
console.log("%s Hi there", chalk.cyan("INFO"));

然后運(yùn)行 node index.js ,如圖:

之后運(yùn)行相同的內(nèi)容,但將其輸出重定向到一個(gè)文件中,這次你會(huì)看見它會(huì)打印一個(gè) undefined 后面跟著一個(gè)簡(jiǎn)單的無色消息。

這是因?yàn)?stdout 關(guān)閉了終端模式下 stdout 的重定向。

chalk 使用了 supports-color ,它會(huì)在引擎里檢查各個(gè)流的 isTTY。

chalk 這樣的庫(kù)已經(jīng)幫你處理了這些行為,但在開發(fā) CLI 的過程中還是要注意,在 CI 模式下運(yùn)行或輸出被重定向的問題。

例如,你可以在終端以一種漂亮的方式來排列數(shù)據(jù),如果 isTTYundefined 時(shí),則切換到更容易解析的方式上。

In Summary

在 JavaScript 中使用 console.log 是非??斓?,但當(dāng)你將代碼部署到生產(chǎn)環(huán)境時(shí),你應(yīng)該要考慮更多關(guān)于記錄的內(nèi)容。

本文僅僅是介紹了各種方法和可用的日志記錄解決方案,它不包含你需要知道的一切。

因此我建議你多看一看你喜歡的開源項(xiàng)目,看看它們是如何解決日志記錄問題以及它們所使用的工具。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/104630.html

相關(guān)文章

  • Node.js 指南(Docker化Node.js Web應(yīng)用程序)

    摘要:化應(yīng)用程序此示例的目的是向你展示如何將應(yīng)用程序放入容器中,該指南旨在用于開發(fā),而不用于生產(chǎn)部署,本指南還假設(shè)你有一個(gè)有效的安裝,并且基本了解應(yīng)用程序的結(jié)構(gòu)。 Docker化Node.js Web應(yīng)用程序 此示例的目的是向你展示如何將Node.js應(yīng)用程序放入Docker容器中,該指南旨在用于開發(fā),而不用于生產(chǎn)部署,本指南還假設(shè)你有一個(gè)有效的Docker安裝,并且基本了解Node.js應(yīng)...

    李世贊 評(píng)論0 收藏0
  • Node.js 開發(fā)指南 讀書筆記

    摘要:為指定事件注冊(cè)一個(gè)監(jiān)聽器,接受一個(gè)字符串和一個(gè)回調(diào)函數(shù)。發(fā)射事件,傳遞若干可選參數(shù)到事件監(jiān)聽器的參數(shù)表。為指定事件注冊(cè)一個(gè)單次監(jiān)聽器,即監(jiān)聽器最多只會(huì)觸發(fā)一次,觸發(fā)后立刻解除該監(jiān)聽器。 1.Node.js 簡(jiǎn)介 Node.js 其實(shí)就是借助谷歌的 V8 引擎,將桌面端的 js 帶到了服務(wù)器端,它的出現(xiàn)我將其歸結(jié)為兩點(diǎn): V8 引擎的出色; js 異步 io 與事件驅(qū)動(dòng)給服務(wù)器帶來極高...

    CocoaChina 評(píng)論0 收藏0
  • 手把手教你搭A(yù)PM之Skywalking搭建指南(支持Java/C#/Node.js)

    摘要:通過跟蹤請(qǐng)求的處理過程,來對(duì)應(yīng)用系統(tǒng)在前后端處理服務(wù)端調(diào)用的性能消耗進(jìn)行跟蹤,關(guān)于的介紹可以看這個(gè)鏈接,大規(guī)模分布式系統(tǒng)的跟蹤系統(tǒng)作者刀把五鏈接來源知乎著作權(quán)歸作者所有。 手把手教你搭A(yù)PM之Skywalking 前言 什么是APM?全稱:Application Performance Management 可以參考這里: 現(xiàn)代APM體系,基本都是參考Google的Dapper(大規(guī)模...

    ingood 評(píng)論0 收藏0
  • 前端周刊第63期:前端新人如何快速提高?

    摘要:最近公司入職了個(gè)實(shí)習(xí)同學(xué),本期收錄了關(guān)于實(shí)習(xí)同學(xué)如何快速掌握熟練工程師的工作流程開發(fā)套路來自我提升的多條精彩內(nèi)容。想知道我接下來會(huì)寫些什么歡迎訂閱我的掘金專欄或知乎專欄前端周刊讓你在前端領(lǐng)域跟上時(shí)代的腳步。 showImg(https://segmentfault.com/img/bVQ9QE?w=1920&h=1080); 共 1818 字,讀完需 3 分鐘。本周 JSConf Ch...

    shiyang6017 評(píng)論0 收藏0
  • 前端周刊第64期:你真的會(huì)提問么?

    摘要:但是究竟什么是區(qū)塊鏈呢如何基于區(qū)塊鏈構(gòu)建去中心化的應(yīng)用這個(gè)系列文章很有料,有圖文解釋有代碼實(shí)例,非常適合入門。想知道我接下來會(huì)寫些什么歡迎訂閱我的掘金專欄或知乎專欄前端周刊讓你在前端領(lǐng)域跟上時(shí)代的腳步。 showImg(https://segmentfault.com/img/remote/1460000010417511); 共 2044 字,讀完需 4 分鐘。本期以《提問的智慧》作...

    wfc_666 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<