Next.js自定義日誌記錄:捕獲未捕獲的服務器端異常
Next.js本身無法使用自定義日誌記錄器來處理服務器端未捕獲的異常和拒絕。雖然可以使用next-logger
之類的庫,但它僅限於使用Pino。如果您想使用其他日誌庫,甚至將日誌發送到DataDog等雲提供商,則此方法無效。
LogLayer日誌庫可以解決這個問題。它可以捕獲這些異常並將它們發送到您選擇的日誌庫(例如Pino和DataDog)中。
查看LogLayer網站以了解支持的日誌記錄器和雲提供商。
本指南假設您已設置好Next.js。
首先,安裝所需的軟件包。您可以使用任何您喜歡的傳輸方式 - 此示例中我們將使用Pino:
<code class="language-bash">npm i loglayer @loglayer/transport-pino pino serialize-error</code>
您需要在項目根目錄下創建一個檢測文件。
<code class="language-typescript">// instrumentation.ts import { LogLayer, type ILogLayer } from 'loglayer'; import { PinoTransport } from "@loglayer/transport-pino"; import pino from "pino"; import { serializeError } from "serialize-error"; /** * 去除字符串中的ANSI代码,这是Next.js喜欢注入的内容。 */ function stripAnsiCodes(str: string): string { return str.replace( /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=>/, '' ); } function createConsoleMethod(log: ILogLayer, method: string) { const mappedMethod = method === "error" ? "errorOnly" : method; return (...args: unknown[]): void => { const data: Record<string, unknown> = {}; let hasData = false; let error: Error | null = null; const messages: string[] = []; for (const arg of args) { if (arg instanceof Error) { error = arg; continue; } if (typeof arg === "object" && arg !== null) { Object.assign(data, arg); hasData = true; continue; } if (typeof arg === "string") { messages.push(arg); } } let finalMessage = stripAnsiCodes(messages.join(" ")).trim(); // next.js在错误对象时使用“x”作为错误消息 if (finalMessage === "⨯" && error) { finalMessage = error?.message || ""; } if (error && hasData && messages.length > 0) { log.withError(error).withMetadata(data)[mappedMethod](finalMessage); } else if (error && messages.length > 0) { log.withError(error)[mappedMethod](finalMessage); } else if (hasData && messages.length > 0) { log.withMetadata(data)[mappedMethod](finalMessage); } else if (error && hasData && messages.length === 0) { log.withError(error).withMetadata(data)[mappedMethod](""); } else if (error && messages.length === 0) { log.errorOnly(error); } else if (hasData && messages.length === 0) { log.metadataOnly(data); } else { log[mappedMethod](finalMessage); } }; } export async function register() { const logger = new LogLayer({ errorSerializer: serializeError, transport: [ new PinoTransport({ logger: pino(), }), ] }); if (process.env.NEXT_RUNTIME === "nodejs") { console.error = createConsoleMethod(logger, "error"); console.log = createConsoleMethod(logger, "log"); console.info = createConsoleMethod(logger, "info"); console.warn = createConsoleMethod(logger, "warn"); console.debug = createConsoleMethod(logger, "debug"); } }</code>
如果您從page.tsx
拋出一個未捕獲的錯誤,您應該在終端中看到以下內容:
<code class="language-json">{"err":{"type":"Object","message":"test","stack":"Error: test\n at Page (webpack-internal:///(rsc)/./src/app/page.tsx:12:11)","digest":"699232626","name":"Error"},"msg":"test"}</code>
以上是定制登錄Next.js的詳細內容。更多資訊請關注PHP中文網其他相關文章!