Loki 環境變數可參考 Day 20 文章的 Grafana Data Source settings 設定
本文將介紹如何將 Nest.js Pino 整合 Grafana Loki 進行日誌收集。原本我們僅在開發環境中啟用 pino-pretty
來美化控制台的日誌輸出,現在將進一步設定生產環境的日誌系統。首先需要在 .env
中配置 LOKI_URL
、LOKI_USER
、LOKI_PASSWORD
等環境變數。
本日程式碼的範例連結
透過 nodeEnv
環境變數進行條件判斷,在生產環境強制要求完整配置 Loki
參數,開發環境則可選填。
config/configuration.ts
const configSchema = Joi.object({
// Loki 日誌系統相關設定
loki: Joi.object({
url: Joi.string().uri().when(Joi.ref('/nodeEnv'), {
is: 'production',
then: Joi.required(), // 生產環境:必填
otherwise: Joi.optional(), // 開發環境:選填
}),
user: Joi.string().when(Joi.ref('/nodeEnv'), {
is: 'production',
then: Joi.required(),
otherwise: Joi.optional(),
}),
password: Joi.string().when(Joi.ref('/nodeEnv'), {
is: 'production',
then: Joi.required(),
otherwise: Joi.optional(),
}),
}).optional(),
});
export default () => {
const config = {
// Loki 日誌系統相關設定
loki: {
url: process.env.LOKI_URL,
user: process.env.LOKI_USER,
password: process.env.LOKI_PASSWORD,
},
};
const { error, value } = configSchema.validate(config, {
abortEarly: false, // 顯示所有錯誤,而不是第一個錯誤就停止檢查
});
if (error) throw new Error(`環境變數驗證錯誤: ${error.message}`);
return value;
};
執行以下指令安裝套件:
pnpm i pino-loki
透過 Pino 的 transport 機制將日誌傳輸至 Grafana Loki。在生產環境使用 pino-loki 透過 HTTP 將日誌傳送至 Grafana Cloud Loki,同時搭配 pino/file 輸出至控制台,確保本地使用生產環境時,也能即時查看日誌記錄。
針對 Loki 配置了以下參數:
app: nestjs-test
,方便在 Grafana 中篩選日誌config/logger.config.ts
/// 略
transport:
nodeEnv !== 'production'
? {
// 開發環境專用 pino-pretty 美化 log 輸出
target: 'pino-pretty',
options: {
colorize: true, // 顏色輸出
singleLine: true, // 單行日誌
messageFormat:
'{if context}【{context}】- {end}{if msg}{msg}{end} {if responseTime}(took {responseTime}ms){end}', // 日誌顯示格式
ignore: 'context,pid,hostname,responseTime,req,res', // 忽略屬性
translateTime: 'yyyy-mm-dd HH:MM:ss', //時間格式
levelFirst: true, // 日誌等級在最前面
},
}
: {
targets: [
{
target: 'pino/file', // 生產環境下載控制台也顯示紀錄
options: {
destination: 1,
},
},
{
target: 'pino-loki',
options: {
interval: 10, // 批次傳送紀錄的時間,單位是秒。
labels: { app: 'nestjs-test' }, // Grafana Loki 查詢標籤
host: lokiUrl,
basicAuth: {
username: lokiUser,
password: lokiPassword,
},
},
},
],
}
啟動前需先執行 pnpm run build 進行專案打包
啟動後端伺服器後,可在 Grafana Loki 觀察到伺服器啟動訊息已成功記錄,確認 Nest Pino 與 Grafana Loki 已正確整合。
接著透過 LineBot 進行對話測試,驗證請求過程是否完整記錄。
【 Grafana Loki Line Format 小技巧 】
Grafana 使用 LogQL語法進行日誌查詢。目前顯示的訊息資訊較多,可透過 LogQL 語法調整顯示內容。
建議使用 Builder 模式進行操作,同時觀察 Code 部分的對應語法,有助於理解 pipeline 的執行流程:
以 JSON parser 為例
Step 1:解析 JSON 日誌格式
透過 JSON parser 將日誌解析後,各個欄位(如 level、method、url、statusCode)會轉換為可查詢的標籤,方便後續篩選與處理。
JSON Parser 設定
解析後的欄位結構
Step 2:使用 Line format 自訂顯示格式
搭配 printf 模板函數自訂顯示內容。將前面 JSON 解析出的標籤直接套用,並加上換行符號,讓每則日誌顯示更好閱讀。
LINE Format 規則:{{ printf "method: %s\npath: %s\nstatus: %v\nduration: %vms" .req_method .req_url .res_statusCode .responseTime }}
Line Format 設定
格式化後的顯示結果
今日完成 Nest.js Pino 與 Grafana Loki 的整合,從環境變數驗證、套件安裝到 transport 配置,完成生產環境的日誌監控。並且透過 LogQL 搭配 JSON parser 與 printf 模板函數,把原本難讀的日誌整理成結構化格式,多加練習就能體會標籤查詢日誌的便利性。