天天看點

關于 Node.js 應用裡使用 winston 進行日志記錄的最佳實踐

你怎麼能解決這個問題?也許通過回到代碼并檢查每一行代碼是否按預期運作。這對于小型應用程式來說更容易,但即便如此,嘗試觸發與使用者相同類型的錯誤也可能很困難。想象一下,這在大型應用程式中會有多難。

假設有一個執行個體,應用程式收集一些使用者的資訊并将它們儲存到資料庫中。

如果應用程式失敗,伺服器将向最終使用者傳回系統錯誤。最好能捕獲這些執行個體并解決這些錯誤。在這種情況下,您如何知道使用者 a 或使用者 b 遇到了單個系統錯誤?這些錯誤可能由代碼中的錯誤、損壞的檔案、錯誤的邏輯或資料類型不比對觸發。

如果你需要避免這種挫折,你就無法避免日志記錄。日志是程式員首先要查找的地方,用于跟蹤錯誤和事件流,尤其是來自伺服器的事件。日志會告訴您當應用程式運作并與使用者互動時會發生什麼。日志記錄的一個很好的用例是,例如,如果您的系統中有一個錯誤,并且您想了解導緻其發生的步驟。

日志記錄是将應用程式活動生成的資訊記錄到日志檔案中的過程。儲存在日志檔案中的消息稱為日志。日志是記錄在日志檔案中的單個執行個體。

在 Node.js 中建構應用程式日志至關重要。在本地運作應用程式時,可以将其挂接到調試器上,非常棒,可以在運作應用程式時發現問題。在開發過程中,您通常會使用 console.log 來擷取應用程式日志。

但是當一個應用程式投入生産并且使用者開始與之互動時,你就不能再使用 console.log 了。如果出現問題并且應用程式崩潰,則無法使用控制台進行檢查。如果你有一個簡潔、幹淨和高品質的日志中間件,比如 Winston,那會很有幫助。

Winston 處理您的應用程式活動并将有用的資訊生成到日志檔案或資料庫中。之後,您可以檢查應用程式生成的所有活動。

本指南将在 Winston 的上下文中解釋日志記錄。

了解生産應用程式是否出現問題的唯一方法是建立日志。 記錄重新建立并為您儲存該問題。 如果出現問題或出現問題,日志會告訴您。

了解系統的行為方式。 日志記錄将生成有關系統如何與使用者互動以及進出系統的資訊。

跟蹤您的系統活動。 日志可以顯示執行個體發生的時間以及觸發日志的原因。

通常,日志記錄的臨界值是:

錯誤跟蹤

調試

應用性能

選擇 winston 的收益

Winston 是最好的日志中間件之一,每周下載下傳量約為 4,000,000 次。以下屬性使 Winston 成為整體通用的日志記錄中間件。

它使用簡單且可配置。

日志級别(優先級)。 Winston 提供日志記錄級别。它們表示日志優先級;這使您能夠從需要較少關注的日志中整理出關鍵日志。例如:{錯誤:0,警告:1,資訊:2,詳細:3,調試:4,傻:5}。在這種情況下,錯誤日志的優先級高于詳細日志。

記錄通道(傳輸)。一個好的記錄器有不同的方式來選擇你的日志輸出目的地。使用 Winston,您可以以不同方式發送和儲存日志,例如檔案、資料庫、電子郵件和控制台。

日志格式。 Winston 為您提供了多種日志格式。例如,在将日志儲存到 Mongo 資料庫時,日志格式需要為 JSON 格式。

日志分析。 Winston 可幫助您分析代碼塊并測量成功執行代碼所需的時間。

Winston transporters

Winston 的特性之一是它支援各種傳輸,例如檔案傳輸。 這會将生成的日志消息儲存到日志檔案中。 該檔案是在您的系統中指定的。 如果應用程式建立了它的第一個日志執行個體,該檔案将自動生成。 之後,任何日志都将儲存到建立的檔案中。

為此,記錄器配置對象需要指向一個檔案(檔案傳輸器)。 隻需将新 winston.transports.File 中的傳輸配置對象 .transports.Console() 替換為 .transports.File() 即可,如下所示。

關于 Node.js 應用裡使用 winston 進行日志記錄的最佳實踐

const logConfiguration = {
    transports: [
        new winston.transports.Console({
            level: 'warn'
        }),
        new winston.transports.File({
            level: 'error',
            // Create the log directory if it does not exist
            filename: 'logs/example.log'
        })
    ]
};

const logger = winston.createLogger(logConfiguration);

// Log some messages
logger.error("Hello, Winston logger, the first error!");
logger.warn("Hello, Winston logger, the first warning!");
logger.warn("Hello, Winston logger, the second warning!");
logger.error("Hello, Winston logger, the second error!");
logger.info("Hello, Winston logger, some info!");
logger.debug("Hello, Winston logger, a debug!");
      

這規定:

日志将顯示在控制台輸出中。

隻有屬于錯誤級别的日志才會記錄在 example.log 檔案中。

使用 Winston,您可以指定儲存日志的預設格式。

例如,假設我們想以 JSON 格式登入,我們可以使用 Winston.format 指定,并且日志執行個體将以 JSON 格式儲存。

format: winston.format(

)

該格式采用其他日志表單屬性,例如

ms() - 自記錄上次日志以來的時間(以毫秒為機關)。

label() - 向記錄的消息添加标簽。

timestamp() - 收到日志消息的時間戳。

splat() - 提供字元串插值。

要将其應用到您的日志中,您需要使用 format.combine,如下例所示。

關于 Node.js 應用裡使用 winston 進行日志記錄的最佳實踐
關于 Node.js 應用裡使用 winston 進行日志記錄的最佳實踐
const express = require('express');

// Require logger.js
const logger = require('./utils/logger');
const app = express();
const port = 3000;
const host = "localhost";

// Dummy Express GET call
app.get('/',(req,res) => {
    res.send("Hello World!");
    logger.info("Server Sent A Hello World!");
})

// Introduce error by using undefined variable 'y'
app.get('/calc',(req,res) => {
    const x = y + 10;
    res.send(x.toString());
})

// Capture 500 errors
app.use((err,req,res,next) => {
res.status(500).send('Could not perform the calculation!');
   logger.error(`${err.status || 500} - ${res.statusMessage} - ${err.message} - ${req.originalUrl} - ${req.method} - ${req.ip}`);
})

// Capture 404 erors
app.use((req,res,next) => {
    res.status(404).send("PAGE NOT FOUND");
    logger.error(`400 || ${res.statusMessage} - ${req.originalUrl} - ${req.method} - ${req.ip}`);
})
// Run the server
app.listen(port, () => {
    console.log("Server started...");
    logger.info(`Server started and running on http://${host}:${port}`)
})
      

每次伺服器啟動時,Winston 都會将日志記錄到 server.log 檔案中。

伺服器運作時,通路以下頁面會在每次調用連結時建立日志。

http://localhost:3000/ - 伺服器将發送一條 hello world 消息。 我們希望 Winston 捕獲它并将其記錄在我們的日志檔案中。

http://localhost:3000/calc - 我們試圖将變量 y 添加到變量 x。 在這種情況下,未定義變量 y。 這将産生一個錯誤,我們希望 Winston 為我們捕獲這個執行個體。

http://localhost:3000/hello - 我們建立的伺服器沒有這樣的 URL。 我們希望 Winston 在指向我們 IP 位址的連結被通路但無法找到時通知我們; 那是 404 錯誤。

output:

info: Nov-12-2020 10:07:59: Server started and running on http://localhost:3000

info: Nov-12-2020 10:08:02: Server Sent A Hello World!

error: Nov-12-2020 10:08:05: 500 - Internal Server Error - y is not defined - /calc - GET - ::1

error: Nov-12-2020 10:08:10: 400 || Not Found - /hello - GET - ::1