UNPKG

@mgcrea/fastify-request-logger

Version:

Compact request logger plugin for fastify written in TypeScript

1 lines 7.24 kB
{"version":3,"sources":["../src/index.ts","../src/plugin.ts"],"sourcesContent":["import fastifyPlugin from \"fastify-plugin\";\nimport { plugin } from \"./plugin\";\n\nexport type { FastifyRequestLoggerOptions } from \"./plugin\";\n\nexport default fastifyPlugin(plugin, {\n fastify: \">=4\",\n name: \"fastify-request-logger\",\n});\n","/* eslint-disable @typescript-eslint/require-await */\nimport type { FastifyPluginAsync, FastifyRequest } from \"fastify\";\nimport * as color from \"kolorist\";\nimport type pino from \"pino\";\n\nexport type FastifyRequestLoggerOptions = {\n logBody?: boolean;\n logResponseTime?: boolean;\n logBindings?: Record<string, unknown>;\n ignoredPaths?: (string | RegExp)[];\n ignoredBindings?: Record<string, unknown>;\n ignore?: (request: FastifyRequest) => boolean;\n supportsArt?: boolean;\n};\n\nconst IS_WINDOWS = process.platform === \"win32\";\nconst IS_POWERSHELL = IS_WINDOWS && Boolean(process.env[\"PSModulePath\"] ?? process.env[\"PSHOME\"]);\n\nexport const plugin: FastifyPluginAsync<FastifyRequestLoggerOptions> = async (\n fastify,\n options = {},\n): Promise<void> => {\n const {\n logBody = true,\n logResponseTime = true,\n logBindings = { plugin: \"fastify-request-logger\" },\n ignoredPaths = [],\n ignore,\n ignoredBindings,\n // eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison\n supportsArt = !IS_POWERSHELL && color.options.supportLevel >= 2 /* SupportLevel.ansi256 */,\n } = options;\n\n const icons = { req: supportsArt ? \"\" : \"<\", res: supportsArt ? \"\" : \">\" };\n\n const isIgnoredRequest = (request: FastifyRequest): boolean => {\n const { url } = request.routeOptions;\n const isIgnoredPath = ignoredPaths.some((ignoredPath) => {\n if (typeof ignoredPath === \"string\") {\n return ignoredPath === url;\n } else if (ignoredPath instanceof RegExp) {\n return ignoredPath.test(url ?? \"\");\n }\n return false;\n });\n if (isIgnoredPath) {\n return true;\n }\n return ignore ? ignore(request) : false;\n };\n\n fastify.addHook(\"onRequest\", async (request) => {\n if (isIgnoredRequest(request)) {\n if (ignoredBindings) {\n (request.log as pino.Logger).setBindings(ignoredBindings);\n }\n return;\n }\n const contentLength = request.headers[\"content-length\"];\n request.log.info(\n logBindings,\n `${color.bold(color.yellow(icons.req))}${color.yellow(request.method)}:${color.green(\n request.url,\n )} request from ip ${color.blue(request.ip)}${\n contentLength ? ` with a ${color.yellow(contentLength)}-length body` : \"\"\n }`,\n );\n request.log.trace({ ...logBindings, req: request }, `Request trace`);\n });\n\n fastify.addHook(\"preHandler\", async (request) => {\n if (isIgnoredRequest(request)) {\n return;\n }\n const isJson = request.headers[\"content-type\"]?.includes(\"application/json\");\n if (request.body && logBody) {\n if (Buffer.isBuffer(request.body)) {\n request.log.debug({ ...logBindings, body: `<Buffer ${request.body.length} bytes>` }, `Request body`);\n } else if (isJson) {\n request.log.debug({ ...logBindings, body: request.body }, `Request body`);\n }\n }\n });\n\n fastify.addHook(\"onResponse\", async (request, reply) => {\n if (isIgnoredRequest(request)) {\n return;\n }\n const message = `${color.bold(color.yellow(icons.res))}${color.yellow(request.method)}:${color.green(\n request.url,\n )} response with a ${color.magenta(reply.statusCode)}-status${\n logResponseTime ? ` took ${color.magenta(reply.elapsedTime.toFixed(3))}ms` : \"\"\n }`;\n if (reply.statusCode && reply.statusCode >= 500) {\n request.log.error(logBindings, message);\n } else if (reply.statusCode && reply.statusCode >= 400) {\n request.log.warn(logBindings, message);\n } else {\n request.log.info(logBindings, message);\n }\n });\n\n fastify.addHook(\"onError\", async (request, reply, error) => {\n if (isIgnoredRequest(request)) {\n return;\n }\n\n if (error.statusCode && error.statusCode >= 500) {\n request.log.error({ ...logBindings, req: request, res: reply, err: error }, error?.message);\n } else if (reply.statusCode && reply.statusCode >= 400) {\n request.log.warn({ ...logBindings, res: reply, err: error }, error?.message);\n } else {\n request.log.info({ ...logBindings, res: reply, err: error }, error?.message);\n }\n });\n};\n"],"mappings":"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","names":["options","fastifyPlugin"]}