apitally
Version:
Simple API monitoring & analytics for REST APIs built with Express, Fastify, NestJS, AdonisJS, Hono, H3, Elysia, Hapi, and Koa.
1 lines • 18 kB
Source Map (JSON)
{"version":3,"sources":["../../src/fastify/plugin.ts"],"sourcesContent":["import type {\n FastifyError,\n FastifyPluginAsync,\n FastifyReply,\n FastifyRequest,\n} from \"fastify\";\nimport fp from \"fastify-plugin\";\nimport { AsyncLocalStorage, AsyncResource } from \"node:async_hooks\";\n\nimport { ApitallyClient } from \"../common/client.js\";\nimport { consumerFromStringOrObject } from \"../common/consumerRegistry.js\";\nimport { parseContentLength } from \"../common/headers.js\";\nimport { getPackageVersion } from \"../common/packageVersions.js\";\nimport type { LogRecord } from \"../common/requestLogger.js\";\nimport { convertBody, convertHeaders } from \"../common/requestLogger.js\";\nimport {\n ApitallyConfig,\n ApitallyConsumer,\n PathInfo,\n ValidationError,\n} from \"../common/types.js\";\nimport {\n patchConsole,\n patchNestLogger,\n patchPinoLogger,\n patchWinston,\n} from \"../loggers/index.js\";\n\nconst LOGS_SYMBOL = Symbol(\"apitally.logs\");\nconst ASYNC_RESOURCE_SYMBOL = Symbol(\"apitally.logsContextAsyncResource\");\n\ndeclare module \"fastify\" {\n interface FastifyReply {\n payload: any;\n serverError?: FastifyError;\n }\n\n interface FastifyRequest {\n apitallyConsumer?: ApitallyConsumer | string | null;\n consumerIdentifier?: ApitallyConsumer | string | null; // For backwards compatibility\n\n [LOGS_SYMBOL]?: LogRecord[];\n [ASYNC_RESOURCE_SYMBOL]?: AsyncResource;\n }\n}\n\nconst apitallyPlugin: FastifyPluginAsync<ApitallyConfig> = async (\n fastify,\n config,\n) => {\n const client = new ApitallyClient(config);\n const routes: PathInfo[] = [];\n const logsContext = new AsyncLocalStorage<LogRecord[]>();\n\n if (client.requestLogger.config.captureLogs) {\n patchConsole(logsContext);\n patchWinston(logsContext);\n patchPinoLogger(fastify.log, logsContext);\n patchNestLogger(logsContext);\n }\n\n fastify.decorateRequest(\"apitallyConsumer\", null);\n fastify.decorateRequest(\"consumerIdentifier\", null); // For backwards compatibility\n fastify.decorateReply(\"payload\", null);\n\n fastify.addHook(\"onRoute\", (routeOptions) => {\n const methods = Array.isArray(routeOptions.method)\n ? routeOptions.method\n : [routeOptions.method];\n methods.forEach((method) => {\n if (![\"HEAD\", \"OPTIONS\"].includes(method.toUpperCase())) {\n routes.push({\n method: method.toUpperCase(),\n path: routeOptions.url,\n });\n }\n });\n });\n\n fastify.addHook(\"onReady\", () => {\n client.setStartupData(getAppInfo(routes, config.appVersion));\n client.startSync();\n });\n\n fastify.addHook(\"onClose\", async () => {\n await client.handleShutdown();\n });\n\n // Establish logs context for each request\n fastify.addHook(\"onRequest\", (request, reply, done) => {\n if (client.isEnabled()) {\n const logs: LogRecord[] = [];\n request[LOGS_SYMBOL] = logs;\n logsContext.run(logs, () => {\n const asyncResource = new AsyncResource(\"ApitallyLogsContext\");\n request[ASYNC_RESOURCE_SYMBOL] = asyncResource;\n asyncResource.runInAsyncScope(done, request.raw);\n });\n } else {\n done();\n }\n });\n\n // Restore async context for later hooks and route handlers\n fastify.addHook(\"preValidation\", (request, reply, done) => {\n if (client.isEnabled() && request[ASYNC_RESOURCE_SYMBOL]) {\n const asyncResource = request[ASYNC_RESOURCE_SYMBOL];\n asyncResource.runInAsyncScope(done, request.raw);\n } else {\n done();\n }\n });\n\n fastify.addHook(\"onSend\", (request, reply, payload: any, done) => {\n const contentType = reply.getHeader(\"content-type\") as string | undefined;\n if (client.requestLogger.isSupportedContentType(contentType)) {\n reply.payload = payload;\n }\n done();\n });\n\n fastify.addHook(\"onError\", (request, reply, error, done) => {\n if (!error.statusCode || error.statusCode === 500) {\n reply.serverError = error;\n }\n done();\n });\n\n fastify.addHook(\"onResponse\", (request, reply, done) => {\n if (client.isEnabled() && request.method.toUpperCase() !== \"OPTIONS\") {\n // Get path from routeOptions if available (from v4), otherwise fallback to deprecated routerPath\n const consumer = getConsumer(request);\n const path =\n \"routeOptions\" in request\n ? (request as any).routeOptions.url\n : (request as any).routerPath;\n const requestSize = parseContentLength(request.headers[\"content-length\"]);\n const responseSize = parseContentLength(\n reply.getHeader(\"content-length\"),\n );\n const responseTime = getResponseTime(reply);\n client.consumerRegistry.addOrUpdateConsumer(consumer);\n client.requestCounter.addRequest({\n consumer: consumer?.identifier,\n method: request.method,\n path,\n statusCode: reply.statusCode,\n responseTime,\n requestSize,\n responseSize,\n });\n\n if (\n (reply.statusCode === 400 || reply.statusCode === 422) &&\n reply.payload\n ) {\n try {\n const parsedPayload = JSON.parse(reply.payload);\n const validationErrors: ValidationError[] = [];\n\n if (\n (!parsedPayload.code ||\n parsedPayload.code === \"FST_ERR_VALIDATION\") &&\n typeof parsedPayload.message === \"string\"\n ) {\n validationErrors.push(...extractAjvErrors(parsedPayload.message));\n } else if (Array.isArray(parsedPayload.message)) {\n validationErrors.push(\n ...extractNestValidationErrors(parsedPayload.message),\n );\n }\n\n validationErrors.forEach((error) => {\n client.validationErrorCounter.addValidationError({\n consumer: consumer?.identifier,\n method: request.method,\n path: path,\n ...error,\n });\n });\n } catch (error) {} // eslint-disable-line no-empty\n }\n\n if (reply.statusCode === 500 && reply.serverError) {\n client.serverErrorCounter.addServerError({\n consumer: consumer?.identifier,\n method: request.method,\n path: path,\n type: reply.serverError.name,\n msg: reply.serverError.message,\n traceback: reply.serverError.stack || \"\",\n });\n }\n\n if (client.requestLogger.enabled) {\n const logs = request[LOGS_SYMBOL];\n client.requestLogger.logRequest(\n {\n timestamp: Date.now() / 1000,\n method: request.method,\n path,\n url: `${request.protocol}://${request.host ?? request.hostname}${request.originalUrl ?? request.url}`,\n headers: convertHeaders(request.headers),\n size: requestSize,\n consumer: consumer?.identifier,\n body: convertBody(request.body, request.headers[\"content-type\"]),\n },\n {\n statusCode: reply.statusCode,\n responseTime: responseTime / 1000,\n headers: convertHeaders(reply.getHeaders()),\n size: responseSize,\n body: convertBody(\n reply.payload,\n reply.getHeader(\"content-type\")?.toString(),\n ),\n },\n reply.serverError,\n logs,\n );\n }\n }\n\n done();\n });\n};\n\nfunction getAppInfo(routes: PathInfo[], appVersion?: string) {\n const versions = [[\"nodejs\", process.version.replace(/^v/, \"\")]];\n const fastifyVersion = getPackageVersion(\"fastify\");\n const pinoVersion = getPackageVersion(\"pino\");\n const nestjsVersion = getPackageVersion(\"@nestjs/core\");\n const apitallyVersion = getPackageVersion(\"../..\");\n if (fastifyVersion) {\n versions.push([\"fastify\", fastifyVersion]);\n }\n if (pinoVersion) {\n versions.push([\"pino\", pinoVersion]);\n }\n if (nestjsVersion) {\n versions.push([\"nestjs\", nestjsVersion]);\n }\n if (apitallyVersion) {\n versions.push([\"apitally\", apitallyVersion]);\n }\n if (appVersion) {\n versions.push([\"app\", appVersion]);\n }\n return {\n paths: routes,\n versions: Object.fromEntries(versions),\n client: \"js:fastify\",\n };\n}\n\nexport function setConsumer(\n request: FastifyRequest,\n consumer: ApitallyConsumer | string | null | undefined,\n) {\n request.apitallyConsumer = consumer || undefined;\n}\n\nfunction getConsumer(request: FastifyRequest) {\n if (request.apitallyConsumer) {\n return consumerFromStringOrObject(request.apitallyConsumer);\n } else if (request.consumerIdentifier) {\n // For backwards compatibility\n process.emitWarning(\n \"The consumerIdentifier property on the request object is deprecated. Use apitallyConsumer instead.\",\n \"DeprecationWarning\",\n );\n return consumerFromStringOrObject(request.consumerIdentifier);\n }\n return null;\n}\n\nfunction getResponseTime(reply: FastifyReply) {\n if (reply.elapsedTime !== undefined) {\n return reply.elapsedTime;\n } else if ((reply as any).getResponseTime !== undefined) {\n return (reply as any).getResponseTime();\n }\n return 0;\n}\n\nfunction extractAjvErrors(message: string): ValidationError[] {\n try {\n const regex =\n /(?<=^|, )((?:headers|params|query|querystring|body)[/.][^ ]+)(?= )/g;\n const matches: { match: string; index: number }[] = [];\n let match: RegExpExecArray | null;\n while ((match = regex.exec(message)) !== null) {\n matches.push({ match: match[0], index: match.index });\n }\n\n return matches.map((m, i) => {\n const endIndex =\n i + 1 < matches.length ? matches[i + 1].index - 2 : message.length;\n const matchSplit = m.match.split(/[/.]/);\n if (matchSplit[0] === \"querystring\") {\n matchSplit[0] = \"query\";\n }\n return {\n loc: matchSplit.join(\".\"),\n msg: message.substring(m.index, endIndex),\n type: \"\",\n };\n });\n } catch (error) {\n return [];\n }\n}\n\nfunction extractNestValidationErrors(message: any[]): ValidationError[] {\n try {\n return message\n .filter((msg: any) => typeof msg === \"string\")\n .map((msg: any) => ({\n loc: \"\",\n msg,\n type: \"\",\n }));\n } catch (error) {\n return [];\n }\n}\n\nexport { apitallyPlugin };\n\nexport default fp(apitallyPlugin, {\n name: \"apitally\",\n});\n"],"mappings":"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","names":["LOGS_SYMBOL","Symbol","ASYNC_RESOURCE_SYMBOL","apitallyPlugin","fastify","config","client","ApitallyClient","routes","logsContext","AsyncLocalStorage","requestLogger","captureLogs","patchConsole","patchWinston","patchPinoLogger","log","patchNestLogger","decorateRequest","decorateReply","addHook","routeOptions","methods","Array","isArray","method","forEach","includes","toUpperCase","push","path","url","setStartupData","getAppInfo","appVersion","startSync","handleShutdown","request","reply","done","isEnabled","logs","run","asyncResource","AsyncResource","runInAsyncScope","raw","payload","contentType","getHeader","isSupportedContentType","error","statusCode","serverError","consumer","getConsumer","routerPath","requestSize","parseContentLength","headers","responseSize","responseTime","getResponseTime","consumerRegistry","addOrUpdateConsumer","requestCounter","addRequest","identifier","parsedPayload","JSON","parse","validationErrors","code","message","extractAjvErrors","extractNestValidationErrors","validationErrorCounter","addValidationError","serverErrorCounter","addServerError","type","name","msg","traceback","stack","enabled","logRequest","timestamp","Date","now","protocol","host","hostname","originalUrl","convertHeaders","size","body","convertBody","getHeaders","toString","versions","process","version","replace","fastifyVersion","getPackageVersion","pinoVersion","nestjsVersion","apitallyVersion","paths","Object","fromEntries","setConsumer","apitallyConsumer","undefined","consumerFromStringOrObject","consumerIdentifier","emitWarning","elapsedTime","regex","matches","match","exec","index","map","m","i","endIndex","length","matchSplit","split","loc","join","substring","filter","fp"]}