Skip to content

Instantly share code, notes, and snippets.

@balazsorban44
Last active July 21, 2021 12:29
Show Gist options
  • Save balazsorban44/7381bc1f6b9ecfd538902959f8de0140 to your computer and use it in GitHub Desktop.
Save balazsorban44/7381bc1f6b9ecfd538902959f8de0140 to your computer and use it in GitHub Desktop.
Next.js API route that parses minified stacks and sends it to third-party logger.
import { NextApiRequest, NextApiResponse } from "next"
import log, { LogLevel } from "utils/server-logger"
import StackTraceGPS from "stacktrace-gps"
import ErrorStackParser from "error-stack-parser"
import fs from "fs"
import path from "path"
export default async function logger(
req: NextApiRequest,
res: NextApiResponse
) {
try {
const logLevel = req.query.logLevel as LogLevel
const { _message, ...obj } = JSON.parse(req.body)
const message = _message ?? obj.message
if (logLevel === "error") {
const errorLike = {
message,
stack: obj.stack || obj.componentStack,
name: obj.name ?? "Error",
}
const parsedError = await parseStack(errorLike)
log.error(parsedError, message)
return
}
log[logLevel](obj, message)
} catch (error) {
log.error(error, error.message)
} finally {
res.end()
}
}
interface ErrorLike {
name: string
stack: string
message: string
}
async function parseStack(errorLike: ErrorLike) {
try {
const gps = new StackTraceGPS({
async ajax(url: string) {
const filePath = path.join(
process.cwd(),
".next",
url.replace(/.*\/_next/, "")
)
return fs.readFileSync(filePath, "utf8")
},
})
const stackframes = ErrorStackParser.parse(errorLike)
const frames = await Promise.all(stackframes.map((f) => gps.pinpoint(f)))
const stack = frames
.map((frame) => {
frame.fileName = frame.fileName?.replace("webpack://_N_E", "")
return ` at ${frame}`
})
.join("\n")
return {
...errorLike,
stack: `${errorLike.name}: ${errorLike.message}
${stack}`,
}
} catch (error) {
console.error("Could not parse error, returning original", error)
return errorLike
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment