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中文网其他相关文章!