apitally 0.23.0 → 0.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/dist/common/client.cjs +2 -1
  2. package/dist/common/client.cjs.map +1 -1
  3. package/dist/common/client.js +2 -1
  4. package/dist/common/client.js.map +1 -1
  5. package/dist/common/instance.cjs +158 -0
  6. package/dist/common/instance.cjs.map +1 -0
  7. package/dist/common/instance.d.cts +4 -0
  8. package/dist/common/instance.d.ts +4 -0
  9. package/dist/common/instance.js +134 -0
  10. package/dist/common/instance.js.map +1 -0
  11. package/dist/common/requestLogger.cjs +12 -17
  12. package/dist/common/requestLogger.cjs.map +1 -1
  13. package/dist/common/requestLogger.js +12 -17
  14. package/dist/common/requestLogger.js.map +1 -1
  15. package/dist/common/response.cjs +2 -2
  16. package/dist/common/response.cjs.map +1 -1
  17. package/dist/common/response.js +2 -2
  18. package/dist/common/response.js.map +1 -1
  19. package/dist/common/serverErrorCounter.cjs +3 -0
  20. package/dist/common/serverErrorCounter.cjs.map +1 -1
  21. package/dist/common/serverErrorCounter.js +3 -0
  22. package/dist/common/serverErrorCounter.js.map +1 -1
  23. package/dist/common/tempGzipFile.cjs +25 -2
  24. package/dist/common/tempGzipFile.cjs.map +1 -1
  25. package/dist/common/tempGzipFile.d.cts +3 -2
  26. package/dist/common/tempGzipFile.d.ts +3 -2
  27. package/dist/common/tempGzipFile.js +22 -3
  28. package/dist/common/tempGzipFile.js.map +1 -1
  29. package/dist/elysia/plugin.cjs +20 -17
  30. package/dist/elysia/plugin.cjs.map +1 -1
  31. package/dist/elysia/plugin.js +20 -17
  32. package/dist/elysia/plugin.js.map +1 -1
  33. package/dist/fastify/plugin.cjs +2 -2
  34. package/dist/fastify/plugin.cjs.map +1 -1
  35. package/dist/fastify/plugin.js +2 -2
  36. package/dist/fastify/plugin.js.map +1 -1
  37. package/dist/h3/plugin.cjs +2 -2
  38. package/dist/h3/plugin.cjs.map +1 -1
  39. package/dist/h3/plugin.js +2 -2
  40. package/dist/h3/plugin.js.map +1 -1
  41. package/dist/hapi/plugin.cjs +6 -6
  42. package/dist/hapi/plugin.cjs.map +1 -1
  43. package/dist/hapi/plugin.js +6 -6
  44. package/dist/hapi/plugin.js.map +1 -1
  45. package/dist/loggers/pino.cjs +1 -1
  46. package/dist/loggers/pino.cjs.map +1 -1
  47. package/dist/loggers/pino.js +1 -1
  48. package/dist/loggers/pino.js.map +1 -1
  49. package/package.json +5 -5
@@ -1 +1 @@
1
- {"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":";;AAMA,OAAOA,QAAQ;AACf,SAASC,mBAAmBC,qBAAqB;AAEjD,SAASC,sBAAsB;AAC/B,SAASC,kCAAkC;AAC3C,SAASC,0BAA0B;AACnC,SAASC,yBAAyB;AAElC,SAASC,aAAaC,sBAAsB;AAO5C,SACEC,cACAC,iBACAC,iBACAC,oBACK;AAEP,MAAMC,cAAcC,OAAO,eAAA;AAC3B,MAAMC,wBAAwBD,OAAO,mCAAA;AAiBrC,MAAME,iBAAqD,8BACzDC,SACAC,WAAAA;AAEA,QAAMC,SAAS,IAAIhB,eAAee,MAAAA;AAClC,QAAME,SAAqB,CAAA;AAC3B,QAAMC,cAAc,IAAIpB,kBAAAA;AAExB,MAAIkB,OAAOG,cAAcJ,OAAOK,aAAa;AAC3Cd,iBAAaY,WAAAA;AACbT,iBAAaS,WAAAA;AACbV,oBAAgBM,QAAQO,KAAKH,WAAAA;AAC7BX,oBAAgBW,WAAAA;EAClB;AAEAJ,UAAQQ,gBAAgB,oBAAoB,IAAA;AAC5CR,UAAQQ,gBAAgB,sBAAsB,IAAA;AAC9CR,UAAQS,cAAc,WAAW,IAAA;AAEjCT,UAAQU,QAAQ,WAAW,CAACC,iBAAAA;AAC1B,UAAMC,UAAUC,MAAMC,QAAQH,aAAaI,MAAM,IAC7CJ,aAAaI,SACb;MAACJ,aAAaI;;AAClBH,YAAQI,QAAQ,CAACD,WAAAA;AACf,UAAI,CAAC;QAAC;QAAQ;QAAWE,SAASF,OAAOG,YAAW,CAAA,GAAK;AACvDf,eAAOgB,KAAK;UACVJ,QAAQA,OAAOG,YAAW;UAC1BE,MAAMT,aAAaU;QACrB,CAAA;MACF;IACF,CAAA;EACF,CAAA;AAEArB,UAAQU,QAAQ,WAAW,MAAA;AACzBR,WAAOoB,eAAeC,WAAWpB,QAAQF,OAAOuB,UAAU,CAAA;AAC1DtB,WAAOuB,UAAS;EAClB,CAAA;AAEAzB,UAAQU,QAAQ,WAAW,YAAA;AACzB,UAAMR,OAAOwB,eAAc;EAC7B,CAAA;AAGA1B,UAAQU,QAAQ,aAAa,CAACiB,SAASC,OAAOC,SAAAA;AAC5C,QAAI3B,OAAO4B,UAAS,GAAI;AACtB,YAAMC,OAAoB,CAAA;AAC1BJ,cAAQ/B,WAAAA,IAAemC;AACvB3B,kBAAY4B,IAAID,MAAM,MAAA;AACpB,cAAME,gBAAgB,IAAIhD,cAAc,qBAAA;AACxC0C,gBAAQ7B,qBAAAA,IAAyBmC;AACjCA,sBAAcC,gBAAgBL,MAAMF,QAAQQ,GAAG;MACjD,CAAA;IACF,OAAO;AACLN,WAAAA;IACF;EACF,CAAA;AAGA7B,UAAQU,QAAQ,iBAAiB,CAACiB,SAASC,OAAOC,SAAAA;AAChD,QAAI3B,OAAO4B,UAAS,KAAMH,QAAQ7B,qBAAAA,GAAwB;AACxD,YAAMmC,gBAAgBN,QAAQ7B,qBAAAA;AAC9BmC,oBAAcC,gBAAgBL,MAAMF,QAAQQ,GAAG;IACjD,OAAO;AACLN,WAAAA;IACF;EACF,CAAA;AAEA7B,UAAQU,QAAQ,UAAU,CAACiB,SAASC,OAAOQ,SAAcP,SAAAA;AACvD,UAAMQ,cAAcT,MAAMU,UAAU,cAAA;AACpC,QAAIpC,OAAOG,cAAckC,uBAAuBF,WAAAA,GAAc;AAC5DT,YAAMQ,UAAUA;IAClB;AACAP,SAAAA;EACF,CAAA;AAEA7B,UAAQU,QAAQ,WAAW,CAACiB,SAASC,OAAOY,OAAOX,SAAAA;AACjD,QAAI,CAACW,MAAMC,cAAcD,MAAMC,eAAe,KAAK;AACjDb,YAAMc,cAAcF;IACtB;AACAX,SAAAA;EACF,CAAA;AAEA7B,UAAQU,QAAQ,cAAc,CAACiB,SAASC,OAAOC,SAAAA;AA1HjD;AA2HI,QAAI3B,OAAO4B,UAAS,KAAMH,QAAQZ,OAAOG,YAAW,MAAO,WAAW;AAEpE,YAAMyB,WAAWC,YAAYjB,OAAAA;AAC7B,YAAMP,OACJ,kBAAkBO,UACbA,QAAgBhB,aAAaU,MAC7BM,QAAgBkB;AACvB,YAAMC,cAAc1D,mBAAmBuC,QAAQoB,QAAQ,gBAAA,CAAiB;AACxE,YAAMC,eAAe5D,mBACnBwC,MAAMU,UAAU,gBAAA,CAAA;AAElB,YAAMW,eAAeC,gBAAgBtB,KAAAA;AACrC1B,aAAOiD,iBAAiBC,oBAAoBT,QAAAA;AAC5CzC,aAAOmD,eAAeC,WAAW;QAC/BX,UAAUA,qCAAUY;QACpBxC,QAAQY,QAAQZ;QAChBK;QACAqB,YAAYb,MAAMa;QAClBQ;QACAH;QACAE;MACF,CAAA;AAEA,WACGpB,MAAMa,eAAe,OAAOb,MAAMa,eAAe,QAClDb,MAAMQ,SACN;AACA,YAAI;AACF,gBAAMoB,gBAAgBC,KAAKC,MAAM9B,MAAMQ,OAAO;AAC9C,gBAAMuB,mBAAsC,CAAA;AAE5C,eACG,CAACH,cAAcI,QACdJ,cAAcI,SAAS,yBACzB,OAAOJ,cAAcK,YAAY,UACjC;AACAF,6BAAiBxC,KAAI,GAAI2C,iBAAiBN,cAAcK,OAAO,CAAA;UACjE,WAAWhD,MAAMC,QAAQ0C,cAAcK,OAAO,GAAG;AAC/CF,6BAAiBxC,KAAI,GAChB4C,4BAA4BP,cAAcK,OAAO,CAAA;UAExD;AAEAF,2BAAiB3C,QAAQ,CAACwB,UAAAA;AACxBtC,mBAAO8D,uBAAuBC,mBAAmB;cAC/CtB,UAAUA,qCAAUY;cACpBxC,QAAQY,QAAQZ;cAChBK;cACA,GAAGoB;YACL,CAAA;UACF,CAAA;QACF,SAASA,OAAO;QAAC;MACnB;AAEA,UAAIZ,MAAMa,eAAe,OAAOb,MAAMc,aAAa;AACjDxC,eAAOgE,mBAAmBC,eAAe;UACvCxB,UAAUA,qCAAUY;UACpBxC,QAAQY,QAAQZ;UAChBK;UACAgD,MAAMxC,MAAMc,YAAY2B;UACxBC,KAAK1C,MAAMc,YAAYmB;UACvBU,WAAW3C,MAAMc,YAAY8B,SAAS;QACxC,CAAA;MACF;AAEA,UAAItE,OAAOG,cAAcoE,SAAS;AAChC,cAAM1C,OAAOJ,QAAQ/B,WAAAA;AACrBM,eAAOG,cAAcqE,WACnB;UACEC,WAAWC,KAAKC,IAAG,IAAK;UACxB9D,QAAQY,QAAQZ;UAChBK;UACAC,KAAK,GAAGM,QAAQmD,QAAQ,MAAMnD,QAAQoD,QAAQpD,QAAQqD,QAAQ,GAAGrD,QAAQsD,eAAetD,QAAQN,GAAG;UACnG0B,SAASxD,eAAeoC,QAAQoB,OAAO;UACvCmC,MAAMpC;UACNH,UAAUA,qCAAUY;UACpB4B,MAAM7F,YAAYqC,QAAQwD,MAAMxD,QAAQoB,QAAQ,cAAA,CAAe;QACjE,GACA;UACEN,YAAYb,MAAMa;UAClBQ,cAAcA,eAAe;UAC7BF,SAASxD,eAAeqC,MAAMwD,WAAU,CAAA;UACxCF,MAAMlC;UACNmC,MAAM7F,YACJsC,MAAMQ,UACNR,WAAMU,UAAU,cAAA,MAAhBV,mBAAiCyD,UAAAA;QAErC,GACAzD,MAAMc,aACNX,IAAAA;MAEJ;IACF;AAEAF,SAAAA;EACF,CAAA;AACF,GAnL2D;AAqL3D,SAASN,WAAWpB,QAAoBqB,YAAmB;AACzD,QAAM8D,WAAW;IAAC;MAAC;MAAUC,QAAQC,QAAQC,QAAQ,MAAM,EAAA;;;AAC3D,QAAMC,iBAAiBrG,kBAAkB,SAAA;AACzC,QAAMsG,cAActG,kBAAkB,MAAA;AACtC,QAAMuG,gBAAgBvG,kBAAkB,cAAA;AACxC,QAAMwG,kBAAkBxG,kBAAkB,OAAA;AAC1C,MAAIqG,gBAAgB;AAClBJ,aAASnE,KAAK;MAAC;MAAWuE;KAAe;EAC3C;AACA,MAAIC,aAAa;AACfL,aAASnE,KAAK;MAAC;MAAQwE;KAAY;EACrC;AACA,MAAIC,eAAe;AACjBN,aAASnE,KAAK;MAAC;MAAUyE;KAAc;EACzC;AACA,MAAIC,iBAAiB;AACnBP,aAASnE,KAAK;MAAC;MAAY0E;KAAgB;EAC7C;AACA,MAAIrE,YAAY;AACd8D,aAASnE,KAAK;MAAC;MAAOK;KAAW;EACnC;AACA,SAAO;IACLsE,OAAO3F;IACPmF,UAAUS,OAAOC,YAAYV,QAAAA;IAC7BpF,QAAQ;EACV;AACF;AA1BSqB;AA4BF,SAAS0E,YACdtE,SACAgB,UAAsD;AAEtDhB,UAAQuE,mBAAmBvD,YAAYwD;AACzC;AALgBF;AAOhB,SAASrD,YAAYjB,SAAuB;AAC1C,MAAIA,QAAQuE,kBAAkB;AAC5B,WAAO/G,2BAA2BwC,QAAQuE,gBAAgB;EAC5D,WAAWvE,QAAQyE,oBAAoB;AAErCb,YAAQc,YACN,sGACA,oBAAA;AAEF,WAAOlH,2BAA2BwC,QAAQyE,kBAAkB;EAC9D;AACA,SAAO;AACT;AAZSxD;AAcT,SAASM,gBAAgBtB,OAAmB;AAC1C,MAAIA,MAAM0E,gBAAgBH,QAAW;AACnC,WAAOvE,MAAM0E;EACf,WAAY1E,MAAcsB,oBAAoBiD,QAAW;AACvD,WAAQvE,MAAcsB,gBAAe;EACvC;AACA,SAAO;AACT;AAPSA;AAST,SAASY,iBAAiBD,SAAe;AACvC,MAAI;AACF,UAAM0C,QACJ;AACF,UAAMC,UAA8C,CAAA;AACpD,QAAIC;AACJ,YAAQA,QAAQF,MAAMG,KAAK7C,OAAAA,OAAc,MAAM;AAC7C2C,cAAQrF,KAAK;QAAEsF,OAAOA,MAAM,CAAA;QAAIE,OAAOF,MAAME;MAAM,CAAA;IACrD;AAEA,WAAOH,QAAQI,IAAI,CAACC,GAAGC,MAAAA;AACrB,YAAMC,WACJD,IAAI,IAAIN,QAAQQ,SAASR,QAAQM,IAAI,CAAA,EAAGH,QAAQ,IAAI9C,QAAQmD;AAC9D,YAAMC,aAAaJ,EAAEJ,MAAMS,MAAM,MAAA;AACjC,UAAID,WAAW,CAAA,MAAO,eAAe;AACnCA,mBAAW,CAAA,IAAK;MAClB;AACA,aAAO;QACLE,KAAKF,WAAWG,KAAK,GAAA;QACrB9C,KAAKT,QAAQwD,UAAUR,EAAEF,OAAOI,QAAAA;QAChC3C,MAAM;MACR;IACF,CAAA;EACF,SAAS5B,OAAO;AACd,WAAO,CAAA;EACT;AACF;AA1BSsB;AA4BT,SAASC,4BAA4BF,SAAc;AACjD,MAAI;AACF,WAAOA,QACJyD,OAAO,CAAChD,QAAa,OAAOA,QAAQ,QAAA,EACpCsC,IAAI,CAACtC,SAAc;MAClB6C,KAAK;MACL7C;MACAF,MAAM;IACR,EAAA;EACJ,SAAS5B,OAAO;AACd,WAAO,CAAA;EACT;AACF;AAZSuB;AAgBT,IAAA,iBAAehF,GAAGgB,gBAAgB;EAChCsE,MAAM;AACR,CAAA;","names":["fp","AsyncLocalStorage","AsyncResource","ApitallyClient","consumerFromStringOrObject","parseContentLength","getPackageVersion","convertBody","convertHeaders","patchConsole","patchNestLogger","patchPinoLogger","patchWinston","LOGS_SYMBOL","Symbol","ASYNC_RESOURCE_SYMBOL","apitallyPlugin","fastify","config","client","routes","logsContext","requestLogger","captureLogs","log","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","runInAsyncScope","raw","payload","contentType","getHeader","isSupportedContentType","error","statusCode","serverError","consumer","getConsumer","routerPath","requestSize","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","size","body","getHeaders","toString","versions","process","version","replace","fastifyVersion","pinoVersion","nestjsVersion","apitallyVersion","paths","Object","fromEntries","setConsumer","apitallyConsumer","undefined","consumerIdentifier","emitWarning","elapsedTime","regex","matches","match","exec","index","map","m","i","endIndex","length","matchSplit","split","loc","join","substring","filter"]}
1
+ {"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":["fp","AsyncLocalStorage","AsyncResource","ApitallyClient","consumerFromStringOrObject","parseContentLength","getPackageVersion","convertBody","convertHeaders","patchConsole","patchNestLogger","patchPinoLogger","patchWinston","LOGS_SYMBOL","Symbol","ASYNC_RESOURCE_SYMBOL","apitallyPlugin","fastify","config","client","routes","logsContext","requestLogger","captureLogs","log","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","runInAsyncScope","raw","payload","contentType","getHeader","isSupportedContentType","error","statusCode","serverError","consumer","getConsumer","routerPath","requestSize","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","size","body","getHeaders","toString","versions","process","version","replace","fastifyVersion","pinoVersion","nestjsVersion","apitallyVersion","paths","Object","fromEntries","setConsumer","apitallyConsumer","undefined","consumerIdentifier","emitWarning","elapsedTime","regex","matches","match","exec","index","map","m","i","endIndex","length","matchSplit","split","loc","join","substring","filter"]}
@@ -33,8 +33,8 @@ var import_requestLogger = require("../common/requestLogger.js");
33
33
  var import_response = require("../common/response.js");
34
34
  var import_loggers = require("../loggers/index.js");
35
35
  var import_utils = require("./utils.js");
36
- const REQUEST_TIMESTAMP_SYMBOL = Symbol("apitally.requestTimestamp");
37
- const REQUEST_BODY_SYMBOL = Symbol("apitally.requestBody");
36
+ const REQUEST_TIMESTAMP_SYMBOL = /* @__PURE__ */ Symbol("apitally.requestTimestamp");
37
+ const REQUEST_BODY_SYMBOL = /* @__PURE__ */ Symbol("apitally.requestBody");
38
38
  const jsonHeaders = new Headers({
39
39
  "content-type": "application/json;charset=UTF-8"
40
40
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/h3/plugin.ts"],"sourcesContent":["import type { H3Event, HTTPError } from \"h3\";\nimport { definePlugin, onError, onRequest, onResponse } from \"h3\";\nimport { AsyncLocalStorage } from \"node:async_hooks\";\nimport { performance } from \"node:perf_hooks\";\nimport type { ZodError } from \"zod\";\n\nimport { ApitallyClient } from \"../common/client.js\";\nimport { consumerFromStringOrObject } from \"../common/consumerRegistry.js\";\nimport { mergeHeaders, parseContentLength } from \"../common/headers.js\";\nimport type { LogRecord } from \"../common/requestLogger.js\";\nimport { convertHeaders } from \"../common/requestLogger.js\";\nimport { captureResponse } from \"../common/response.js\";\nimport { ApitallyConfig, ApitallyConsumer } from \"../common/types.js\";\nimport { patchConsole, patchWinston } from \"../loggers/index.js\";\nimport { getAppInfo } from \"./utils.js\";\n\nconst REQUEST_TIMESTAMP_SYMBOL = Symbol(\"apitally.requestTimestamp\");\nconst REQUEST_BODY_SYMBOL = Symbol(\"apitally.requestBody\");\n\ndeclare module \"h3\" {\n interface H3EventContext {\n apitallyConsumer?: ApitallyConsumer | string;\n\n [REQUEST_TIMESTAMP_SYMBOL]?: number;\n [REQUEST_BODY_SYMBOL]?: Buffer;\n }\n}\n\nconst jsonHeaders = new Headers({\n \"content-type\": \"application/json;charset=UTF-8\",\n});\n\nexport const apitallyPlugin = definePlugin<ApitallyConfig>((app, config) => {\n const client = new ApitallyClient(config);\n const logsContext = new AsyncLocalStorage<LogRecord[]>();\n\n const setStartupData = (attempt: number = 1) => {\n const appInfo = getAppInfo(app, config.appVersion);\n if (appInfo.paths.length > 0 || attempt >= 10) {\n client.setStartupData(appInfo);\n client.startSync();\n } else {\n setTimeout(() => setStartupData(attempt + 1), 500);\n }\n };\n setTimeout(() => setStartupData(), 500);\n\n if (client.requestLogger.config.captureLogs) {\n patchConsole(logsContext);\n patchWinston(logsContext);\n }\n\n const handleResponse = async (\n event: H3Event,\n response?: Response,\n error?: HTTPError,\n ) => {\n if (event.req.method.toUpperCase() === \"OPTIONS\") {\n return response;\n }\n\n const startTime = event.context[REQUEST_TIMESTAMP_SYMBOL];\n const path = event.context.matchedRoute?.route;\n\n const consumer = getConsumer(event);\n client.consumerRegistry.addOrUpdateConsumer(consumer);\n\n if (!response) {\n response = new Response(null, {\n status: error?.status || 500,\n statusText: error?.statusText || \"Internal Server Error\",\n headers: error?.headers\n ? mergeHeaders(jsonHeaders, error.headers)\n : jsonHeaders,\n });\n }\n\n const [newResponse, responsePromise] = captureResponse(response, {\n captureBody:\n client.requestLogger.enabled &&\n client.requestLogger.config.logResponseBody,\n maxBodySize: client.requestLogger.maxBodySize,\n });\n\n responsePromise.then(async (capturedResponse) => {\n const responseTime = startTime ? performance.now() - startTime : 0;\n const responseSize = capturedResponse.completed\n ? capturedResponse.size\n : undefined;\n const requestSize = parseContentLength(\n event.req.headers.get(\"content-length\"),\n );\n\n if (path) {\n client.requestCounter.addRequest({\n consumer: consumer?.identifier,\n method: event.req.method,\n path,\n statusCode: response.status,\n responseTime,\n requestSize,\n responseSize,\n });\n }\n\n if (client.requestLogger.enabled) {\n const logs = logsContext.getStore();\n client.requestLogger.logRequest(\n {\n timestamp: (Date.now() - responseTime) / 1000,\n method: event.req.method,\n path,\n url: event.req.url,\n headers: convertHeaders(\n Object.fromEntries(event.req.headers.entries()),\n ),\n size: requestSize,\n consumer: consumer?.identifier,\n body: event.context[REQUEST_BODY_SYMBOL],\n },\n {\n statusCode: response.status,\n responseTime: responseTime / 1000,\n headers: convertHeaders(\n Object.fromEntries(response.headers.entries()),\n ),\n size: responseSize,\n body: capturedResponse.body,\n },\n error?.cause instanceof Error ? error.cause : undefined,\n logs,\n );\n }\n });\n\n if (\n path &&\n error?.status === 400 &&\n error.data &&\n (error.data as any).name === \"ZodError\"\n ) {\n const zodError = error.data as ZodError;\n zodError.issues?.forEach((issue) => {\n client.validationErrorCounter.addValidationError({\n consumer: consumer?.identifier,\n method: event.req.method,\n path,\n loc: issue.path.join(\".\"),\n msg: issue.message,\n type: issue.code,\n });\n });\n }\n\n if (path && error?.status === 500 && error.cause instanceof Error) {\n client.serverErrorCounter.addServerError({\n consumer: consumer?.identifier,\n method: event.req.method,\n path,\n type: error.cause.name,\n msg: error.cause.message,\n traceback: error.cause.stack || \"\",\n });\n }\n\n return newResponse;\n };\n\n app\n .use(\n onRequest(async (event) => {\n logsContext.enterWith([]);\n event.context[REQUEST_TIMESTAMP_SYMBOL] = performance.now();\n const requestContentType = event.req.headers.get(\"content-type\");\n const requestSize =\n parseContentLength(event.req.headers.get(\"content-length\")) ?? 0;\n\n if (\n client.requestLogger.enabled &&\n client.requestLogger.config.logRequestBody &&\n client.requestLogger.isSupportedContentType(requestContentType) &&\n requestSize <= client.requestLogger.maxBodySize\n ) {\n const clonedRequest = event.req.clone();\n const requestBody = Buffer.from(await clonedRequest.arrayBuffer());\n event.context[REQUEST_BODY_SYMBOL] = requestBody;\n }\n }),\n )\n .use(\n onResponse((response, event) => {\n if (client.isEnabled()) {\n return handleResponse(event, response, undefined);\n }\n }),\n )\n .use(\n onError((error, event) => {\n if (client.isEnabled()) {\n handleResponse(event, undefined, error);\n }\n }),\n );\n});\n\nexport function setConsumer(\n event: H3Event,\n consumer: ApitallyConsumer | string | null | undefined,\n) {\n event.context.apitallyConsumer = consumer || undefined;\n}\n\nfunction getConsumer(event: H3Event) {\n const consumer = event.context.apitallyConsumer;\n if (consumer) {\n return consumerFromStringOrObject(consumer);\n }\n return null;\n}\n"],"mappings":"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","names":["REQUEST_TIMESTAMP_SYMBOL","Symbol","REQUEST_BODY_SYMBOL","jsonHeaders","Headers","apitallyPlugin","definePlugin","app","config","client","ApitallyClient","logsContext","AsyncLocalStorage","setStartupData","attempt","appInfo","getAppInfo","appVersion","paths","length","startSync","setTimeout","requestLogger","captureLogs","patchConsole","patchWinston","handleResponse","event","response","error","req","method","toUpperCase","startTime","context","path","matchedRoute","route","consumer","getConsumer","consumerRegistry","addOrUpdateConsumer","Response","status","statusText","headers","mergeHeaders","newResponse","responsePromise","captureResponse","captureBody","enabled","logResponseBody","maxBodySize","then","capturedResponse","responseTime","performance","now","responseSize","completed","size","undefined","requestSize","parseContentLength","get","requestCounter","addRequest","identifier","statusCode","logs","getStore","logRequest","timestamp","Date","url","convertHeaders","Object","fromEntries","entries","body","cause","Error","data","name","zodError","issues","forEach","issue","validationErrorCounter","addValidationError","loc","join","msg","message","type","code","serverErrorCounter","addServerError","traceback","stack","use","onRequest","enterWith","requestContentType","logRequestBody","isSupportedContentType","clonedRequest","clone","requestBody","Buffer","from","arrayBuffer","onResponse","isEnabled","onError","setConsumer","apitallyConsumer","consumerFromStringOrObject"]}
1
+ {"version":3,"sources":["../../src/h3/plugin.ts"],"sourcesContent":["import type { H3Event, HTTPError } from \"h3\";\nimport { definePlugin, onError, onRequest, onResponse } from \"h3\";\nimport { AsyncLocalStorage } from \"node:async_hooks\";\nimport { performance } from \"node:perf_hooks\";\nimport type { ZodError } from \"zod\";\n\nimport { ApitallyClient } from \"../common/client.js\";\nimport { consumerFromStringOrObject } from \"../common/consumerRegistry.js\";\nimport { mergeHeaders, parseContentLength } from \"../common/headers.js\";\nimport type { LogRecord } from \"../common/requestLogger.js\";\nimport { convertHeaders } from \"../common/requestLogger.js\";\nimport { captureResponse } from \"../common/response.js\";\nimport { ApitallyConfig, ApitallyConsumer } from \"../common/types.js\";\nimport { patchConsole, patchWinston } from \"../loggers/index.js\";\nimport { getAppInfo } from \"./utils.js\";\n\nconst REQUEST_TIMESTAMP_SYMBOL = Symbol(\"apitally.requestTimestamp\");\nconst REQUEST_BODY_SYMBOL = Symbol(\"apitally.requestBody\");\n\ndeclare module \"h3\" {\n interface H3EventContext {\n apitallyConsumer?: ApitallyConsumer | string;\n\n [REQUEST_TIMESTAMP_SYMBOL]?: number;\n [REQUEST_BODY_SYMBOL]?: Buffer;\n }\n}\n\nconst jsonHeaders = new Headers({\n \"content-type\": \"application/json;charset=UTF-8\",\n});\n\nexport const apitallyPlugin = definePlugin<ApitallyConfig>((app, config) => {\n const client = new ApitallyClient(config);\n const logsContext = new AsyncLocalStorage<LogRecord[]>();\n\n const setStartupData = (attempt: number = 1) => {\n const appInfo = getAppInfo(app, config.appVersion);\n if (appInfo.paths.length > 0 || attempt >= 10) {\n client.setStartupData(appInfo);\n client.startSync();\n } else {\n setTimeout(() => setStartupData(attempt + 1), 500);\n }\n };\n setTimeout(() => setStartupData(), 500);\n\n if (client.requestLogger.config.captureLogs) {\n patchConsole(logsContext);\n patchWinston(logsContext);\n }\n\n const handleResponse = async (\n event: H3Event,\n response?: Response,\n error?: HTTPError,\n ) => {\n if (event.req.method.toUpperCase() === \"OPTIONS\") {\n return response;\n }\n\n const startTime = event.context[REQUEST_TIMESTAMP_SYMBOL];\n const path = event.context.matchedRoute?.route;\n\n const consumer = getConsumer(event);\n client.consumerRegistry.addOrUpdateConsumer(consumer);\n\n if (!response) {\n response = new Response(null, {\n status: error?.status || 500,\n statusText: error?.statusText || \"Internal Server Error\",\n headers: error?.headers\n ? mergeHeaders(jsonHeaders, error.headers)\n : jsonHeaders,\n });\n }\n\n const [newResponse, responsePromise] = captureResponse(response, {\n captureBody:\n client.requestLogger.enabled &&\n client.requestLogger.config.logResponseBody,\n maxBodySize: client.requestLogger.maxBodySize,\n });\n\n responsePromise.then(async (capturedResponse) => {\n const responseTime = startTime ? performance.now() - startTime : 0;\n const responseSize = capturedResponse.completed\n ? capturedResponse.size\n : undefined;\n const requestSize = parseContentLength(\n event.req.headers.get(\"content-length\"),\n );\n\n if (path) {\n client.requestCounter.addRequest({\n consumer: consumer?.identifier,\n method: event.req.method,\n path,\n statusCode: response.status,\n responseTime,\n requestSize,\n responseSize,\n });\n }\n\n if (client.requestLogger.enabled) {\n const logs = logsContext.getStore();\n client.requestLogger.logRequest(\n {\n timestamp: (Date.now() - responseTime) / 1000,\n method: event.req.method,\n path,\n url: event.req.url,\n headers: convertHeaders(\n Object.fromEntries(event.req.headers.entries()),\n ),\n size: requestSize,\n consumer: consumer?.identifier,\n body: event.context[REQUEST_BODY_SYMBOL],\n },\n {\n statusCode: response.status,\n responseTime: responseTime / 1000,\n headers: convertHeaders(\n Object.fromEntries(response.headers.entries()),\n ),\n size: responseSize,\n body: capturedResponse.body,\n },\n error?.cause instanceof Error ? error.cause : undefined,\n logs,\n );\n }\n });\n\n if (\n path &&\n error?.status === 400 &&\n error.data &&\n (error.data as any).name === \"ZodError\"\n ) {\n const zodError = error.data as ZodError;\n zodError.issues?.forEach((issue) => {\n client.validationErrorCounter.addValidationError({\n consumer: consumer?.identifier,\n method: event.req.method,\n path,\n loc: issue.path.join(\".\"),\n msg: issue.message,\n type: issue.code,\n });\n });\n }\n\n if (path && error?.status === 500 && error.cause instanceof Error) {\n client.serverErrorCounter.addServerError({\n consumer: consumer?.identifier,\n method: event.req.method,\n path,\n type: error.cause.name,\n msg: error.cause.message,\n traceback: error.cause.stack || \"\",\n });\n }\n\n return newResponse;\n };\n\n app\n .use(\n onRequest(async (event) => {\n logsContext.enterWith([]);\n event.context[REQUEST_TIMESTAMP_SYMBOL] = performance.now();\n const requestContentType = event.req.headers.get(\"content-type\");\n const requestSize =\n parseContentLength(event.req.headers.get(\"content-length\")) ?? 0;\n\n if (\n client.requestLogger.enabled &&\n client.requestLogger.config.logRequestBody &&\n client.requestLogger.isSupportedContentType(requestContentType) &&\n requestSize <= client.requestLogger.maxBodySize\n ) {\n const clonedRequest = event.req.clone();\n const requestBody = Buffer.from(await clonedRequest.arrayBuffer());\n event.context[REQUEST_BODY_SYMBOL] = requestBody;\n }\n }),\n )\n .use(\n onResponse((response, event) => {\n if (client.isEnabled()) {\n return handleResponse(event, response, undefined);\n }\n }),\n )\n .use(\n onError((error, event) => {\n if (client.isEnabled()) {\n handleResponse(event, undefined, error);\n }\n }),\n );\n});\n\nexport function setConsumer(\n event: H3Event,\n consumer: ApitallyConsumer | string | null | undefined,\n) {\n event.context.apitallyConsumer = consumer || undefined;\n}\n\nfunction getConsumer(event: H3Event) {\n const consumer = event.context.apitallyConsumer;\n if (consumer) {\n return consumerFromStringOrObject(consumer);\n }\n return null;\n}\n"],"mappings":"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","names":["REQUEST_TIMESTAMP_SYMBOL","Symbol","REQUEST_BODY_SYMBOL","jsonHeaders","Headers","apitallyPlugin","definePlugin","app","config","client","ApitallyClient","logsContext","AsyncLocalStorage","setStartupData","attempt","appInfo","getAppInfo","appVersion","paths","length","startSync","setTimeout","requestLogger","captureLogs","patchConsole","patchWinston","handleResponse","event","response","error","req","method","toUpperCase","startTime","context","path","matchedRoute","route","consumer","getConsumer","consumerRegistry","addOrUpdateConsumer","Response","status","statusText","headers","mergeHeaders","newResponse","responsePromise","captureResponse","captureBody","enabled","logResponseBody","maxBodySize","then","capturedResponse","responseTime","performance","now","responseSize","completed","size","undefined","requestSize","parseContentLength","get","requestCounter","addRequest","identifier","statusCode","logs","getStore","logRequest","timestamp","Date","url","convertHeaders","Object","fromEntries","entries","body","cause","Error","data","name","zodError","issues","forEach","issue","validationErrorCounter","addValidationError","loc","join","msg","message","type","code","serverErrorCounter","addServerError","traceback","stack","use","onRequest","enterWith","requestContentType","logRequestBody","isSupportedContentType","clonedRequest","clone","requestBody","Buffer","from","arrayBuffer","onResponse","isEnabled","onError","setConsumer","apitallyConsumer","consumerFromStringOrObject"]}
package/dist/h3/plugin.js CHANGED
@@ -10,8 +10,8 @@ import { convertHeaders } from "../common/requestLogger.js";
10
10
  import { captureResponse } from "../common/response.js";
11
11
  import { patchConsole, patchWinston } from "../loggers/index.js";
12
12
  import { getAppInfo } from "./utils.js";
13
- const REQUEST_TIMESTAMP_SYMBOL = Symbol("apitally.requestTimestamp");
14
- const REQUEST_BODY_SYMBOL = Symbol("apitally.requestBody");
13
+ const REQUEST_TIMESTAMP_SYMBOL = /* @__PURE__ */ Symbol("apitally.requestTimestamp");
14
+ const REQUEST_BODY_SYMBOL = /* @__PURE__ */ Symbol("apitally.requestBody");
15
15
  const jsonHeaders = new Headers({
16
16
  "content-type": "application/json;charset=UTF-8"
17
17
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/h3/plugin.ts"],"sourcesContent":["import type { H3Event, HTTPError } from \"h3\";\nimport { definePlugin, onError, onRequest, onResponse } from \"h3\";\nimport { AsyncLocalStorage } from \"node:async_hooks\";\nimport { performance } from \"node:perf_hooks\";\nimport type { ZodError } from \"zod\";\n\nimport { ApitallyClient } from \"../common/client.js\";\nimport { consumerFromStringOrObject } from \"../common/consumerRegistry.js\";\nimport { mergeHeaders, parseContentLength } from \"../common/headers.js\";\nimport type { LogRecord } from \"../common/requestLogger.js\";\nimport { convertHeaders } from \"../common/requestLogger.js\";\nimport { captureResponse } from \"../common/response.js\";\nimport { ApitallyConfig, ApitallyConsumer } from \"../common/types.js\";\nimport { patchConsole, patchWinston } from \"../loggers/index.js\";\nimport { getAppInfo } from \"./utils.js\";\n\nconst REQUEST_TIMESTAMP_SYMBOL = Symbol(\"apitally.requestTimestamp\");\nconst REQUEST_BODY_SYMBOL = Symbol(\"apitally.requestBody\");\n\ndeclare module \"h3\" {\n interface H3EventContext {\n apitallyConsumer?: ApitallyConsumer | string;\n\n [REQUEST_TIMESTAMP_SYMBOL]?: number;\n [REQUEST_BODY_SYMBOL]?: Buffer;\n }\n}\n\nconst jsonHeaders = new Headers({\n \"content-type\": \"application/json;charset=UTF-8\",\n});\n\nexport const apitallyPlugin = definePlugin<ApitallyConfig>((app, config) => {\n const client = new ApitallyClient(config);\n const logsContext = new AsyncLocalStorage<LogRecord[]>();\n\n const setStartupData = (attempt: number = 1) => {\n const appInfo = getAppInfo(app, config.appVersion);\n if (appInfo.paths.length > 0 || attempt >= 10) {\n client.setStartupData(appInfo);\n client.startSync();\n } else {\n setTimeout(() => setStartupData(attempt + 1), 500);\n }\n };\n setTimeout(() => setStartupData(), 500);\n\n if (client.requestLogger.config.captureLogs) {\n patchConsole(logsContext);\n patchWinston(logsContext);\n }\n\n const handleResponse = async (\n event: H3Event,\n response?: Response,\n error?: HTTPError,\n ) => {\n if (event.req.method.toUpperCase() === \"OPTIONS\") {\n return response;\n }\n\n const startTime = event.context[REQUEST_TIMESTAMP_SYMBOL];\n const path = event.context.matchedRoute?.route;\n\n const consumer = getConsumer(event);\n client.consumerRegistry.addOrUpdateConsumer(consumer);\n\n if (!response) {\n response = new Response(null, {\n status: error?.status || 500,\n statusText: error?.statusText || \"Internal Server Error\",\n headers: error?.headers\n ? mergeHeaders(jsonHeaders, error.headers)\n : jsonHeaders,\n });\n }\n\n const [newResponse, responsePromise] = captureResponse(response, {\n captureBody:\n client.requestLogger.enabled &&\n client.requestLogger.config.logResponseBody,\n maxBodySize: client.requestLogger.maxBodySize,\n });\n\n responsePromise.then(async (capturedResponse) => {\n const responseTime = startTime ? performance.now() - startTime : 0;\n const responseSize = capturedResponse.completed\n ? capturedResponse.size\n : undefined;\n const requestSize = parseContentLength(\n event.req.headers.get(\"content-length\"),\n );\n\n if (path) {\n client.requestCounter.addRequest({\n consumer: consumer?.identifier,\n method: event.req.method,\n path,\n statusCode: response.status,\n responseTime,\n requestSize,\n responseSize,\n });\n }\n\n if (client.requestLogger.enabled) {\n const logs = logsContext.getStore();\n client.requestLogger.logRequest(\n {\n timestamp: (Date.now() - responseTime) / 1000,\n method: event.req.method,\n path,\n url: event.req.url,\n headers: convertHeaders(\n Object.fromEntries(event.req.headers.entries()),\n ),\n size: requestSize,\n consumer: consumer?.identifier,\n body: event.context[REQUEST_BODY_SYMBOL],\n },\n {\n statusCode: response.status,\n responseTime: responseTime / 1000,\n headers: convertHeaders(\n Object.fromEntries(response.headers.entries()),\n ),\n size: responseSize,\n body: capturedResponse.body,\n },\n error?.cause instanceof Error ? error.cause : undefined,\n logs,\n );\n }\n });\n\n if (\n path &&\n error?.status === 400 &&\n error.data &&\n (error.data as any).name === \"ZodError\"\n ) {\n const zodError = error.data as ZodError;\n zodError.issues?.forEach((issue) => {\n client.validationErrorCounter.addValidationError({\n consumer: consumer?.identifier,\n method: event.req.method,\n path,\n loc: issue.path.join(\".\"),\n msg: issue.message,\n type: issue.code,\n });\n });\n }\n\n if (path && error?.status === 500 && error.cause instanceof Error) {\n client.serverErrorCounter.addServerError({\n consumer: consumer?.identifier,\n method: event.req.method,\n path,\n type: error.cause.name,\n msg: error.cause.message,\n traceback: error.cause.stack || \"\",\n });\n }\n\n return newResponse;\n };\n\n app\n .use(\n onRequest(async (event) => {\n logsContext.enterWith([]);\n event.context[REQUEST_TIMESTAMP_SYMBOL] = performance.now();\n const requestContentType = event.req.headers.get(\"content-type\");\n const requestSize =\n parseContentLength(event.req.headers.get(\"content-length\")) ?? 0;\n\n if (\n client.requestLogger.enabled &&\n client.requestLogger.config.logRequestBody &&\n client.requestLogger.isSupportedContentType(requestContentType) &&\n requestSize <= client.requestLogger.maxBodySize\n ) {\n const clonedRequest = event.req.clone();\n const requestBody = Buffer.from(await clonedRequest.arrayBuffer());\n event.context[REQUEST_BODY_SYMBOL] = requestBody;\n }\n }),\n )\n .use(\n onResponse((response, event) => {\n if (client.isEnabled()) {\n return handleResponse(event, response, undefined);\n }\n }),\n )\n .use(\n onError((error, event) => {\n if (client.isEnabled()) {\n handleResponse(event, undefined, error);\n }\n }),\n );\n});\n\nexport function setConsumer(\n event: H3Event,\n consumer: ApitallyConsumer | string | null | undefined,\n) {\n event.context.apitallyConsumer = consumer || undefined;\n}\n\nfunction getConsumer(event: H3Event) {\n const consumer = event.context.apitallyConsumer;\n if (consumer) {\n return consumerFromStringOrObject(consumer);\n }\n return null;\n}\n"],"mappings":"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","names":["definePlugin","onError","onRequest","onResponse","AsyncLocalStorage","performance","ApitallyClient","consumerFromStringOrObject","mergeHeaders","parseContentLength","convertHeaders","captureResponse","patchConsole","patchWinston","getAppInfo","REQUEST_TIMESTAMP_SYMBOL","Symbol","REQUEST_BODY_SYMBOL","jsonHeaders","Headers","apitallyPlugin","app","config","client","logsContext","setStartupData","attempt","appInfo","appVersion","paths","length","startSync","setTimeout","requestLogger","captureLogs","handleResponse","event","response","error","req","method","toUpperCase","startTime","context","path","matchedRoute","route","consumer","getConsumer","consumerRegistry","addOrUpdateConsumer","Response","status","statusText","headers","newResponse","responsePromise","captureBody","enabled","logResponseBody","maxBodySize","then","capturedResponse","responseTime","now","responseSize","completed","size","undefined","requestSize","get","requestCounter","addRequest","identifier","statusCode","logs","getStore","logRequest","timestamp","Date","url","Object","fromEntries","entries","body","cause","Error","data","name","zodError","issues","forEach","issue","validationErrorCounter","addValidationError","loc","join","msg","message","type","code","serverErrorCounter","addServerError","traceback","stack","use","enterWith","requestContentType","logRequestBody","isSupportedContentType","clonedRequest","clone","requestBody","Buffer","from","arrayBuffer","isEnabled","setConsumer","apitallyConsumer"]}
1
+ {"version":3,"sources":["../../src/h3/plugin.ts"],"sourcesContent":["import type { H3Event, HTTPError } from \"h3\";\nimport { definePlugin, onError, onRequest, onResponse } from \"h3\";\nimport { AsyncLocalStorage } from \"node:async_hooks\";\nimport { performance } from \"node:perf_hooks\";\nimport type { ZodError } from \"zod\";\n\nimport { ApitallyClient } from \"../common/client.js\";\nimport { consumerFromStringOrObject } from \"../common/consumerRegistry.js\";\nimport { mergeHeaders, parseContentLength } from \"../common/headers.js\";\nimport type { LogRecord } from \"../common/requestLogger.js\";\nimport { convertHeaders } from \"../common/requestLogger.js\";\nimport { captureResponse } from \"../common/response.js\";\nimport { ApitallyConfig, ApitallyConsumer } from \"../common/types.js\";\nimport { patchConsole, patchWinston } from \"../loggers/index.js\";\nimport { getAppInfo } from \"./utils.js\";\n\nconst REQUEST_TIMESTAMP_SYMBOL = Symbol(\"apitally.requestTimestamp\");\nconst REQUEST_BODY_SYMBOL = Symbol(\"apitally.requestBody\");\n\ndeclare module \"h3\" {\n interface H3EventContext {\n apitallyConsumer?: ApitallyConsumer | string;\n\n [REQUEST_TIMESTAMP_SYMBOL]?: number;\n [REQUEST_BODY_SYMBOL]?: Buffer;\n }\n}\n\nconst jsonHeaders = new Headers({\n \"content-type\": \"application/json;charset=UTF-8\",\n});\n\nexport const apitallyPlugin = definePlugin<ApitallyConfig>((app, config) => {\n const client = new ApitallyClient(config);\n const logsContext = new AsyncLocalStorage<LogRecord[]>();\n\n const setStartupData = (attempt: number = 1) => {\n const appInfo = getAppInfo(app, config.appVersion);\n if (appInfo.paths.length > 0 || attempt >= 10) {\n client.setStartupData(appInfo);\n client.startSync();\n } else {\n setTimeout(() => setStartupData(attempt + 1), 500);\n }\n };\n setTimeout(() => setStartupData(), 500);\n\n if (client.requestLogger.config.captureLogs) {\n patchConsole(logsContext);\n patchWinston(logsContext);\n }\n\n const handleResponse = async (\n event: H3Event,\n response?: Response,\n error?: HTTPError,\n ) => {\n if (event.req.method.toUpperCase() === \"OPTIONS\") {\n return response;\n }\n\n const startTime = event.context[REQUEST_TIMESTAMP_SYMBOL];\n const path = event.context.matchedRoute?.route;\n\n const consumer = getConsumer(event);\n client.consumerRegistry.addOrUpdateConsumer(consumer);\n\n if (!response) {\n response = new Response(null, {\n status: error?.status || 500,\n statusText: error?.statusText || \"Internal Server Error\",\n headers: error?.headers\n ? mergeHeaders(jsonHeaders, error.headers)\n : jsonHeaders,\n });\n }\n\n const [newResponse, responsePromise] = captureResponse(response, {\n captureBody:\n client.requestLogger.enabled &&\n client.requestLogger.config.logResponseBody,\n maxBodySize: client.requestLogger.maxBodySize,\n });\n\n responsePromise.then(async (capturedResponse) => {\n const responseTime = startTime ? performance.now() - startTime : 0;\n const responseSize = capturedResponse.completed\n ? capturedResponse.size\n : undefined;\n const requestSize = parseContentLength(\n event.req.headers.get(\"content-length\"),\n );\n\n if (path) {\n client.requestCounter.addRequest({\n consumer: consumer?.identifier,\n method: event.req.method,\n path,\n statusCode: response.status,\n responseTime,\n requestSize,\n responseSize,\n });\n }\n\n if (client.requestLogger.enabled) {\n const logs = logsContext.getStore();\n client.requestLogger.logRequest(\n {\n timestamp: (Date.now() - responseTime) / 1000,\n method: event.req.method,\n path,\n url: event.req.url,\n headers: convertHeaders(\n Object.fromEntries(event.req.headers.entries()),\n ),\n size: requestSize,\n consumer: consumer?.identifier,\n body: event.context[REQUEST_BODY_SYMBOL],\n },\n {\n statusCode: response.status,\n responseTime: responseTime / 1000,\n headers: convertHeaders(\n Object.fromEntries(response.headers.entries()),\n ),\n size: responseSize,\n body: capturedResponse.body,\n },\n error?.cause instanceof Error ? error.cause : undefined,\n logs,\n );\n }\n });\n\n if (\n path &&\n error?.status === 400 &&\n error.data &&\n (error.data as any).name === \"ZodError\"\n ) {\n const zodError = error.data as ZodError;\n zodError.issues?.forEach((issue) => {\n client.validationErrorCounter.addValidationError({\n consumer: consumer?.identifier,\n method: event.req.method,\n path,\n loc: issue.path.join(\".\"),\n msg: issue.message,\n type: issue.code,\n });\n });\n }\n\n if (path && error?.status === 500 && error.cause instanceof Error) {\n client.serverErrorCounter.addServerError({\n consumer: consumer?.identifier,\n method: event.req.method,\n path,\n type: error.cause.name,\n msg: error.cause.message,\n traceback: error.cause.stack || \"\",\n });\n }\n\n return newResponse;\n };\n\n app\n .use(\n onRequest(async (event) => {\n logsContext.enterWith([]);\n event.context[REQUEST_TIMESTAMP_SYMBOL] = performance.now();\n const requestContentType = event.req.headers.get(\"content-type\");\n const requestSize =\n parseContentLength(event.req.headers.get(\"content-length\")) ?? 0;\n\n if (\n client.requestLogger.enabled &&\n client.requestLogger.config.logRequestBody &&\n client.requestLogger.isSupportedContentType(requestContentType) &&\n requestSize <= client.requestLogger.maxBodySize\n ) {\n const clonedRequest = event.req.clone();\n const requestBody = Buffer.from(await clonedRequest.arrayBuffer());\n event.context[REQUEST_BODY_SYMBOL] = requestBody;\n }\n }),\n )\n .use(\n onResponse((response, event) => {\n if (client.isEnabled()) {\n return handleResponse(event, response, undefined);\n }\n }),\n )\n .use(\n onError((error, event) => {\n if (client.isEnabled()) {\n handleResponse(event, undefined, error);\n }\n }),\n );\n});\n\nexport function setConsumer(\n event: H3Event,\n consumer: ApitallyConsumer | string | null | undefined,\n) {\n event.context.apitallyConsumer = consumer || undefined;\n}\n\nfunction getConsumer(event: H3Event) {\n const consumer = event.context.apitallyConsumer;\n if (consumer) {\n return consumerFromStringOrObject(consumer);\n }\n return null;\n}\n"],"mappings":"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","names":["definePlugin","onError","onRequest","onResponse","AsyncLocalStorage","performance","ApitallyClient","consumerFromStringOrObject","mergeHeaders","parseContentLength","convertHeaders","captureResponse","patchConsole","patchWinston","getAppInfo","REQUEST_TIMESTAMP_SYMBOL","Symbol","REQUEST_BODY_SYMBOL","jsonHeaders","Headers","apitallyPlugin","app","config","client","logsContext","setStartupData","attempt","appInfo","appVersion","paths","length","startSync","setTimeout","requestLogger","captureLogs","handleResponse","event","response","error","req","method","toUpperCase","startTime","context","path","matchedRoute","route","consumer","getConsumer","consumerRegistry","addOrUpdateConsumer","Response","status","statusText","headers","newResponse","responsePromise","captureBody","enabled","logResponseBody","maxBodySize","then","capturedResponse","responseTime","now","responseSize","completed","size","undefined","requestSize","get","requestCounter","addRequest","identifier","statusCode","logs","getStore","logRequest","timestamp","Date","url","Object","fromEntries","entries","body","cause","Error","data","name","zodError","issues","forEach","issue","validationErrorCounter","addValidationError","loc","join","msg","message","type","code","serverErrorCounter","addServerError","traceback","stack","use","enterWith","requestContentType","logRequestBody","isSupportedContentType","clonedRequest","clone","requestBody","Buffer","from","arrayBuffer","isEnabled","setConsumer","apitallyConsumer"]}
@@ -30,12 +30,12 @@ var import_consumerRegistry = require("../common/consumerRegistry.js");
30
30
  var import_requestLogger = require("../common/requestLogger.js");
31
31
  var import_loggers = require("../loggers/index.js");
32
32
  var import_utils = require("./utils.js");
33
- const START_TIME_SYMBOL = Symbol("apitally.startTime");
34
- const REQUEST_BODY_SYMBOL = Symbol("apitally.requestBody");
35
- const REQUEST_SIZE_SYMBOL = Symbol("apitally.requestSize");
36
- const RESPONSE_BODY_SYMBOL = Symbol("apitally.responseBody");
37
- const RESPONSE_SIZE_SYMBOL = Symbol("apitally.responseSize");
38
- const LOGS_SYMBOL = Symbol("apitally.logs");
33
+ const START_TIME_SYMBOL = /* @__PURE__ */ Symbol("apitally.startTime");
34
+ const REQUEST_BODY_SYMBOL = /* @__PURE__ */ Symbol("apitally.requestBody");
35
+ const REQUEST_SIZE_SYMBOL = /* @__PURE__ */ Symbol("apitally.requestSize");
36
+ const RESPONSE_BODY_SYMBOL = /* @__PURE__ */ Symbol("apitally.responseBody");
37
+ const RESPONSE_SIZE_SYMBOL = /* @__PURE__ */ Symbol("apitally.responseSize");
38
+ const LOGS_SYMBOL = /* @__PURE__ */ Symbol("apitally.logs");
39
39
  function apitallyPlugin(config) {
40
40
  const client = new import_client.ApitallyClient(config);
41
41
  const logsContext = new import_node_async_hooks.AsyncLocalStorage();
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/hapi/plugin.ts"],"sourcesContent":["import type { Request, Server } from \"@hapi/hapi\";\nimport { AsyncLocalStorage } from \"node:async_hooks\";\nimport { performance } from \"node:perf_hooks\";\n\nimport { ApitallyClient } from \"../common/client.js\";\nimport { consumerFromStringOrObject } from \"../common/consumerRegistry.js\";\nimport type { LogRecord } from \"../common/requestLogger.js\";\nimport { convertHeaders } from \"../common/requestLogger.js\";\nimport { ApitallyConfig, ApitallyConsumer } from \"../common/types.js\";\nimport {\n handleHapiRequestEvent,\n patchConsole,\n patchPinoLogger,\n patchWinston,\n} from \"../loggers/index.js\";\nimport { getAppInfo, isBoom } from \"./utils.js\";\n\nconst START_TIME_SYMBOL = Symbol(\"apitally.startTime\");\nconst REQUEST_BODY_SYMBOL = Symbol(\"apitally.requestBody\");\nconst REQUEST_SIZE_SYMBOL = Symbol(\"apitally.requestSize\");\nconst RESPONSE_BODY_SYMBOL = Symbol(\"apitally.responseBody\");\nconst RESPONSE_SIZE_SYMBOL = Symbol(\"apitally.responseSize\");\nconst LOGS_SYMBOL = Symbol(\"apitally.logs\");\n\ndeclare module \"@hapi/hapi\" {\n interface Request {\n [START_TIME_SYMBOL]?: number;\n [REQUEST_BODY_SYMBOL]?: Buffer;\n [REQUEST_SIZE_SYMBOL]?: number;\n [RESPONSE_BODY_SYMBOL]?: Buffer;\n [RESPONSE_SIZE_SYMBOL]?: number;\n [LOGS_SYMBOL]?: LogRecord[];\n apitallyConsumer?: ApitallyConsumer | string;\n }\n\n interface ResponseObject {\n readonly contentType: string | null; // Missing in Hapi types\n }\n}\n\nexport default function apitallyPlugin(config: ApitallyConfig) {\n const client = new ApitallyClient(config);\n const logsContext = new AsyncLocalStorage<LogRecord[]>();\n let pinoLoggerPatched = false;\n\n if (client.requestLogger.enabled && client.requestLogger.config.captureLogs) {\n patchConsole(logsContext);\n patchWinston(logsContext);\n }\n\n return {\n name: \"apitally\",\n register: async function (server: Server) {\n server.ext(\"onPostStart\", async () => {\n if (\n \"logger\" in server &&\n client.requestLogger.enabled &&\n client.requestLogger.config.captureLogs\n ) {\n pinoLoggerPatched = await patchPinoLogger(\n (server as any).logger,\n logsContext,\n );\n }\n });\n\n server.ext(\"onPostStart\", () => {\n const appInfo = getAppInfo(server, config.appVersion);\n client.setStartupData(appInfo);\n client.startSync();\n });\n\n server.ext(\"onPreStop\", async () => {\n await client.handleShutdown();\n });\n\n server.events.on(\"request\", (_, event) => {\n if (\n !pinoLoggerPatched &&\n client.requestLogger.enabled &&\n client.requestLogger.config.captureLogs &&\n event.channel === \"app\"\n ) {\n handleHapiRequestEvent(event, logsContext);\n }\n });\n\n server.ext(\"onRequest\", async (request, h) => {\n if (!client.isEnabled() || request.method.toUpperCase() === \"OPTIONS\") {\n return h.continue;\n }\n\n request[START_TIME_SYMBOL] = performance.now();\n\n // Patch the lifecycle function to run with the logs context\n const lifecycle = (request as any)._lifecycle.bind(request);\n const logs: LogRecord[] = [];\n request[LOGS_SYMBOL] = logs;\n (request as any)._lifecycle = () => logsContext.run(logs, lifecycle);\n\n const captureRequestBody =\n client.requestLogger.enabled &&\n client.requestLogger.config.logRequestBody &&\n client.requestLogger.isSupportedContentType(\n request.headers[\"content-type\"],\n );\n const chunks: Buffer[] = [];\n let size = 0;\n request.events.on(\"peek\", (chunk: string, encoding: string) => {\n if (captureRequestBody) {\n chunks.push(Buffer.from(chunk, encoding as BufferEncoding));\n }\n size += Buffer.byteLength(chunk, encoding as BufferEncoding);\n });\n request.events.once(\"finish\", () => {\n if (chunks.length > 0) {\n request[REQUEST_BODY_SYMBOL] = Buffer.concat(chunks);\n }\n request[REQUEST_SIZE_SYMBOL] = size;\n });\n\n return h.continue;\n });\n\n server.ext(\"onPreResponse\", async (request, h) => {\n if (\n !client.isEnabled() ||\n request.method.toUpperCase() === \"OPTIONS\" ||\n isBoom(request.response)\n ) {\n return h.continue;\n }\n\n const captureResponseBody =\n client.requestLogger.enabled &&\n client.requestLogger.config.logResponseBody &&\n client.requestLogger.isSupportedContentType(\n request.response.contentType,\n );\n const chunks: Buffer[] = [];\n let size = 0;\n request.response.events.on(\n \"peek\",\n (chunk: string, encoding: string) => {\n if (captureResponseBody) {\n chunks.push(Buffer.from(chunk, encoding as BufferEncoding));\n }\n size += Buffer.byteLength(chunk, encoding as BufferEncoding);\n },\n );\n request.response.events.once(\"finish\", () => {\n if (chunks.length > 0) {\n request[RESPONSE_BODY_SYMBOL] = Buffer.concat(chunks);\n }\n request[RESPONSE_SIZE_SYMBOL] = size;\n });\n\n return h.continue;\n });\n\n server.ext(\"onPostResponse\", async (request, h) => {\n if (!client.isEnabled() || request.method.toUpperCase() === \"OPTIONS\") {\n return h.continue;\n }\n\n const startTime = request[START_TIME_SYMBOL];\n const responseTime = startTime ? performance.now() - startTime : 0;\n const timestamp = (Date.now() - responseTime) / 1000;\n const requestBody = request[REQUEST_BODY_SYMBOL];\n const requestSize = request[REQUEST_SIZE_SYMBOL];\n const response = request.response;\n let statusCode: number;\n let responseHeaders: Record<string, any>;\n let responseBody = request[RESPONSE_BODY_SYMBOL];\n let responseSize = request[RESPONSE_SIZE_SYMBOL];\n const error =\n (response as any)._error instanceof Error\n ? (response as any)._error\n : undefined;\n\n if (isBoom(response)) {\n // Handle Boom error object\n statusCode = response.output?.statusCode ?? 500;\n responseHeaders = response.output?.headers ?? {};\n } else {\n // Handle normal ResponseObject\n statusCode = response.statusCode ?? 200;\n responseHeaders = response.headers ?? {};\n }\n\n if (\n !responseBody &&\n (response as any)._payload &&\n client.requestLogger.enabled &&\n client.requestLogger.config.logResponseBody &&\n (isBoom(response) ||\n client.requestLogger.isSupportedContentType(response.contentType))\n ) {\n const responsePayload = (response as any)._payload;\n if (\n responsePayload &&\n responsePayload._data &&\n responsePayload._encoding &&\n typeof responsePayload._data === \"string\" &&\n typeof responsePayload._encoding === \"string\"\n ) {\n responseBody = Buffer.from(\n responsePayload._data,\n responsePayload._encoding as BufferEncoding,\n );\n }\n }\n\n if (!responseSize && responseBody) {\n responseSize = responseBody.length;\n }\n\n const consumer = request.apitallyConsumer\n ? consumerFromStringOrObject(request.apitallyConsumer)\n : null;\n client.consumerRegistry.addOrUpdateConsumer(consumer);\n\n if (request.route.path) {\n client.requestCounter.addRequest({\n consumer: consumer?.identifier,\n method: request.method,\n path: request.route.path,\n statusCode,\n responseTime,\n requestSize,\n responseSize,\n });\n\n if (statusCode === 500 && error) {\n client.serverErrorCounter.addServerError({\n consumer: consumer?.identifier,\n method: request.method,\n path: request.route.path,\n type: error.name,\n msg: error.message,\n traceback: error.stack || \"\",\n });\n }\n }\n\n if (client.requestLogger.enabled) {\n const logs = request[LOGS_SYMBOL];\n client.requestLogger.logRequest(\n {\n timestamp,\n consumer: consumer?.identifier,\n method: request.method,\n path: request.route.path,\n url: request.url?.href || \"\",\n headers: convertHeaders(request.headers),\n size: requestSize,\n body: requestBody,\n },\n {\n statusCode,\n responseTime: responseTime / 1000,\n headers: convertHeaders(responseHeaders),\n size: responseSize,\n body: responseBody,\n },\n error,\n logs,\n );\n }\n\n return h.continue;\n });\n },\n };\n}\n\nexport function setConsumer(\n request: Request,\n consumer: ApitallyConsumer | string | null | undefined,\n) {\n request.apitallyConsumer = consumer || undefined;\n}\n"],"mappings":"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","names":["START_TIME_SYMBOL","Symbol","REQUEST_BODY_SYMBOL","REQUEST_SIZE_SYMBOL","RESPONSE_BODY_SYMBOL","RESPONSE_SIZE_SYMBOL","LOGS_SYMBOL","config","client","ApitallyClient","logsContext","AsyncLocalStorage","pinoLoggerPatched","requestLogger","enabled","captureLogs","patchConsole","patchWinston","name","register","server","ext","patchPinoLogger","logger","appInfo","getAppInfo","appVersion","setStartupData","startSync","handleShutdown","events","on","_","event","channel","handleHapiRequestEvent","request","h","isEnabled","method","toUpperCase","continue","performance","now","lifecycle","_lifecycle","bind","logs","run","captureRequestBody","logRequestBody","isSupportedContentType","headers","chunks","size","chunk","encoding","push","Buffer","from","byteLength","once","length","concat","isBoom","response","captureResponseBody","logResponseBody","contentType","startTime","responseTime","timestamp","Date","requestBody","requestSize","statusCode","responseHeaders","responseBody","responseSize","error","_error","Error","undefined","output","_payload","responsePayload","_data","_encoding","consumer","apitallyConsumer","consumerFromStringOrObject","consumerRegistry","addOrUpdateConsumer","route","path","requestCounter","addRequest","identifier","serverErrorCounter","addServerError","type","msg","message","traceback","stack","logRequest","url","href","convertHeaders","body","apitallyPlugin","setConsumer"]}
1
+ {"version":3,"sources":["../../src/hapi/plugin.ts"],"sourcesContent":["import type { Request, Server } from \"@hapi/hapi\";\nimport { AsyncLocalStorage } from \"node:async_hooks\";\nimport { performance } from \"node:perf_hooks\";\n\nimport { ApitallyClient } from \"../common/client.js\";\nimport { consumerFromStringOrObject } from \"../common/consumerRegistry.js\";\nimport type { LogRecord } from \"../common/requestLogger.js\";\nimport { convertHeaders } from \"../common/requestLogger.js\";\nimport { ApitallyConfig, ApitallyConsumer } from \"../common/types.js\";\nimport {\n handleHapiRequestEvent,\n patchConsole,\n patchPinoLogger,\n patchWinston,\n} from \"../loggers/index.js\";\nimport { getAppInfo, isBoom } from \"./utils.js\";\n\nconst START_TIME_SYMBOL = Symbol(\"apitally.startTime\");\nconst REQUEST_BODY_SYMBOL = Symbol(\"apitally.requestBody\");\nconst REQUEST_SIZE_SYMBOL = Symbol(\"apitally.requestSize\");\nconst RESPONSE_BODY_SYMBOL = Symbol(\"apitally.responseBody\");\nconst RESPONSE_SIZE_SYMBOL = Symbol(\"apitally.responseSize\");\nconst LOGS_SYMBOL = Symbol(\"apitally.logs\");\n\ndeclare module \"@hapi/hapi\" {\n interface Request {\n [START_TIME_SYMBOL]?: number;\n [REQUEST_BODY_SYMBOL]?: Buffer;\n [REQUEST_SIZE_SYMBOL]?: number;\n [RESPONSE_BODY_SYMBOL]?: Buffer;\n [RESPONSE_SIZE_SYMBOL]?: number;\n [LOGS_SYMBOL]?: LogRecord[];\n apitallyConsumer?: ApitallyConsumer | string;\n }\n\n interface ResponseObject {\n readonly contentType: string | null; // Missing in Hapi types\n }\n}\n\nexport default function apitallyPlugin(config: ApitallyConfig) {\n const client = new ApitallyClient(config);\n const logsContext = new AsyncLocalStorage<LogRecord[]>();\n let pinoLoggerPatched = false;\n\n if (client.requestLogger.enabled && client.requestLogger.config.captureLogs) {\n patchConsole(logsContext);\n patchWinston(logsContext);\n }\n\n return {\n name: \"apitally\",\n register: async function (server: Server) {\n server.ext(\"onPostStart\", async () => {\n if (\n \"logger\" in server &&\n client.requestLogger.enabled &&\n client.requestLogger.config.captureLogs\n ) {\n pinoLoggerPatched = await patchPinoLogger(\n (server as any).logger,\n logsContext,\n );\n }\n });\n\n server.ext(\"onPostStart\", () => {\n const appInfo = getAppInfo(server, config.appVersion);\n client.setStartupData(appInfo);\n client.startSync();\n });\n\n server.ext(\"onPreStop\", async () => {\n await client.handleShutdown();\n });\n\n server.events.on(\"request\", (_, event) => {\n if (\n !pinoLoggerPatched &&\n client.requestLogger.enabled &&\n client.requestLogger.config.captureLogs &&\n event.channel === \"app\"\n ) {\n handleHapiRequestEvent(event, logsContext);\n }\n });\n\n server.ext(\"onRequest\", async (request, h) => {\n if (!client.isEnabled() || request.method.toUpperCase() === \"OPTIONS\") {\n return h.continue;\n }\n\n request[START_TIME_SYMBOL] = performance.now();\n\n // Patch the lifecycle function to run with the logs context\n const lifecycle = (request as any)._lifecycle.bind(request);\n const logs: LogRecord[] = [];\n request[LOGS_SYMBOL] = logs;\n (request as any)._lifecycle = () => logsContext.run(logs, lifecycle);\n\n const captureRequestBody =\n client.requestLogger.enabled &&\n client.requestLogger.config.logRequestBody &&\n client.requestLogger.isSupportedContentType(\n request.headers[\"content-type\"],\n );\n const chunks: Buffer[] = [];\n let size = 0;\n request.events.on(\"peek\", (chunk: string, encoding: string) => {\n if (captureRequestBody) {\n chunks.push(Buffer.from(chunk, encoding as BufferEncoding));\n }\n size += Buffer.byteLength(chunk, encoding as BufferEncoding);\n });\n request.events.once(\"finish\", () => {\n if (chunks.length > 0) {\n request[REQUEST_BODY_SYMBOL] = Buffer.concat(chunks);\n }\n request[REQUEST_SIZE_SYMBOL] = size;\n });\n\n return h.continue;\n });\n\n server.ext(\"onPreResponse\", async (request, h) => {\n if (\n !client.isEnabled() ||\n request.method.toUpperCase() === \"OPTIONS\" ||\n isBoom(request.response)\n ) {\n return h.continue;\n }\n\n const captureResponseBody =\n client.requestLogger.enabled &&\n client.requestLogger.config.logResponseBody &&\n client.requestLogger.isSupportedContentType(\n request.response.contentType,\n );\n const chunks: Buffer[] = [];\n let size = 0;\n request.response.events.on(\n \"peek\",\n (chunk: string, encoding: string) => {\n if (captureResponseBody) {\n chunks.push(Buffer.from(chunk, encoding as BufferEncoding));\n }\n size += Buffer.byteLength(chunk, encoding as BufferEncoding);\n },\n );\n request.response.events.once(\"finish\", () => {\n if (chunks.length > 0) {\n request[RESPONSE_BODY_SYMBOL] = Buffer.concat(chunks);\n }\n request[RESPONSE_SIZE_SYMBOL] = size;\n });\n\n return h.continue;\n });\n\n server.ext(\"onPostResponse\", async (request, h) => {\n if (!client.isEnabled() || request.method.toUpperCase() === \"OPTIONS\") {\n return h.continue;\n }\n\n const startTime = request[START_TIME_SYMBOL];\n const responseTime = startTime ? performance.now() - startTime : 0;\n const timestamp = (Date.now() - responseTime) / 1000;\n const requestBody = request[REQUEST_BODY_SYMBOL];\n const requestSize = request[REQUEST_SIZE_SYMBOL];\n const response = request.response;\n let statusCode: number;\n let responseHeaders: Record<string, any>;\n let responseBody = request[RESPONSE_BODY_SYMBOL];\n let responseSize = request[RESPONSE_SIZE_SYMBOL];\n const error =\n (response as any)._error instanceof Error\n ? (response as any)._error\n : undefined;\n\n if (isBoom(response)) {\n // Handle Boom error object\n statusCode = response.output?.statusCode ?? 500;\n responseHeaders = response.output?.headers ?? {};\n } else {\n // Handle normal ResponseObject\n statusCode = response.statusCode ?? 200;\n responseHeaders = response.headers ?? {};\n }\n\n if (\n !responseBody &&\n (response as any)._payload &&\n client.requestLogger.enabled &&\n client.requestLogger.config.logResponseBody &&\n (isBoom(response) ||\n client.requestLogger.isSupportedContentType(response.contentType))\n ) {\n const responsePayload = (response as any)._payload;\n if (\n responsePayload &&\n responsePayload._data &&\n responsePayload._encoding &&\n typeof responsePayload._data === \"string\" &&\n typeof responsePayload._encoding === \"string\"\n ) {\n responseBody = Buffer.from(\n responsePayload._data,\n responsePayload._encoding as BufferEncoding,\n );\n }\n }\n\n if (!responseSize && responseBody) {\n responseSize = responseBody.length;\n }\n\n const consumer = request.apitallyConsumer\n ? consumerFromStringOrObject(request.apitallyConsumer)\n : null;\n client.consumerRegistry.addOrUpdateConsumer(consumer);\n\n if (request.route.path) {\n client.requestCounter.addRequest({\n consumer: consumer?.identifier,\n method: request.method,\n path: request.route.path,\n statusCode,\n responseTime,\n requestSize,\n responseSize,\n });\n\n if (statusCode === 500 && error) {\n client.serverErrorCounter.addServerError({\n consumer: consumer?.identifier,\n method: request.method,\n path: request.route.path,\n type: error.name,\n msg: error.message,\n traceback: error.stack || \"\",\n });\n }\n }\n\n if (client.requestLogger.enabled) {\n const logs = request[LOGS_SYMBOL];\n client.requestLogger.logRequest(\n {\n timestamp,\n consumer: consumer?.identifier,\n method: request.method,\n path: request.route.path,\n url: request.url?.href || \"\",\n headers: convertHeaders(request.headers),\n size: requestSize,\n body: requestBody,\n },\n {\n statusCode,\n responseTime: responseTime / 1000,\n headers: convertHeaders(responseHeaders),\n size: responseSize,\n body: responseBody,\n },\n error,\n logs,\n );\n }\n\n return h.continue;\n });\n },\n };\n}\n\nexport function setConsumer(\n request: Request,\n consumer: ApitallyConsumer | string | null | undefined,\n) {\n request.apitallyConsumer = consumer || undefined;\n}\n"],"mappings":"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","names":["START_TIME_SYMBOL","Symbol","REQUEST_BODY_SYMBOL","REQUEST_SIZE_SYMBOL","RESPONSE_BODY_SYMBOL","RESPONSE_SIZE_SYMBOL","LOGS_SYMBOL","config","client","ApitallyClient","logsContext","AsyncLocalStorage","pinoLoggerPatched","requestLogger","enabled","captureLogs","patchConsole","patchWinston","name","register","server","ext","patchPinoLogger","logger","appInfo","getAppInfo","appVersion","setStartupData","startSync","handleShutdown","events","on","_","event","channel","handleHapiRequestEvent","request","h","isEnabled","method","toUpperCase","continue","performance","now","lifecycle","_lifecycle","bind","logs","run","captureRequestBody","logRequestBody","isSupportedContentType","headers","chunks","size","chunk","encoding","push","Buffer","from","byteLength","once","length","concat","isBoom","response","captureResponseBody","logResponseBody","contentType","startTime","responseTime","timestamp","Date","requestBody","requestSize","statusCode","responseHeaders","responseBody","responseSize","error","_error","Error","undefined","output","_payload","responsePayload","_data","_encoding","consumer","apitallyConsumer","consumerFromStringOrObject","consumerRegistry","addOrUpdateConsumer","route","path","requestCounter","addRequest","identifier","serverErrorCounter","addServerError","type","msg","message","traceback","stack","logRequest","url","href","convertHeaders","body","apitallyPlugin","setConsumer"]}
@@ -7,12 +7,12 @@ import { consumerFromStringOrObject } from "../common/consumerRegistry.js";
7
7
  import { convertHeaders } from "../common/requestLogger.js";
8
8
  import { handleHapiRequestEvent, patchConsole, patchPinoLogger, patchWinston } from "../loggers/index.js";
9
9
  import { getAppInfo, isBoom } from "./utils.js";
10
- const START_TIME_SYMBOL = Symbol("apitally.startTime");
11
- const REQUEST_BODY_SYMBOL = Symbol("apitally.requestBody");
12
- const REQUEST_SIZE_SYMBOL = Symbol("apitally.requestSize");
13
- const RESPONSE_BODY_SYMBOL = Symbol("apitally.responseBody");
14
- const RESPONSE_SIZE_SYMBOL = Symbol("apitally.responseSize");
15
- const LOGS_SYMBOL = Symbol("apitally.logs");
10
+ const START_TIME_SYMBOL = /* @__PURE__ */ Symbol("apitally.startTime");
11
+ const REQUEST_BODY_SYMBOL = /* @__PURE__ */ Symbol("apitally.requestBody");
12
+ const REQUEST_SIZE_SYMBOL = /* @__PURE__ */ Symbol("apitally.requestSize");
13
+ const RESPONSE_BODY_SYMBOL = /* @__PURE__ */ Symbol("apitally.responseBody");
14
+ const RESPONSE_SIZE_SYMBOL = /* @__PURE__ */ Symbol("apitally.responseSize");
15
+ const LOGS_SYMBOL = /* @__PURE__ */ Symbol("apitally.logs");
16
16
  function apitallyPlugin(config) {
17
17
  const client = new ApitallyClient(config);
18
18
  const logsContext = new AsyncLocalStorage();
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/hapi/plugin.ts"],"sourcesContent":["import type { Request, Server } from \"@hapi/hapi\";\nimport { AsyncLocalStorage } from \"node:async_hooks\";\nimport { performance } from \"node:perf_hooks\";\n\nimport { ApitallyClient } from \"../common/client.js\";\nimport { consumerFromStringOrObject } from \"../common/consumerRegistry.js\";\nimport type { LogRecord } from \"../common/requestLogger.js\";\nimport { convertHeaders } from \"../common/requestLogger.js\";\nimport { ApitallyConfig, ApitallyConsumer } from \"../common/types.js\";\nimport {\n handleHapiRequestEvent,\n patchConsole,\n patchPinoLogger,\n patchWinston,\n} from \"../loggers/index.js\";\nimport { getAppInfo, isBoom } from \"./utils.js\";\n\nconst START_TIME_SYMBOL = Symbol(\"apitally.startTime\");\nconst REQUEST_BODY_SYMBOL = Symbol(\"apitally.requestBody\");\nconst REQUEST_SIZE_SYMBOL = Symbol(\"apitally.requestSize\");\nconst RESPONSE_BODY_SYMBOL = Symbol(\"apitally.responseBody\");\nconst RESPONSE_SIZE_SYMBOL = Symbol(\"apitally.responseSize\");\nconst LOGS_SYMBOL = Symbol(\"apitally.logs\");\n\ndeclare module \"@hapi/hapi\" {\n interface Request {\n [START_TIME_SYMBOL]?: number;\n [REQUEST_BODY_SYMBOL]?: Buffer;\n [REQUEST_SIZE_SYMBOL]?: number;\n [RESPONSE_BODY_SYMBOL]?: Buffer;\n [RESPONSE_SIZE_SYMBOL]?: number;\n [LOGS_SYMBOL]?: LogRecord[];\n apitallyConsumer?: ApitallyConsumer | string;\n }\n\n interface ResponseObject {\n readonly contentType: string | null; // Missing in Hapi types\n }\n}\n\nexport default function apitallyPlugin(config: ApitallyConfig) {\n const client = new ApitallyClient(config);\n const logsContext = new AsyncLocalStorage<LogRecord[]>();\n let pinoLoggerPatched = false;\n\n if (client.requestLogger.enabled && client.requestLogger.config.captureLogs) {\n patchConsole(logsContext);\n patchWinston(logsContext);\n }\n\n return {\n name: \"apitally\",\n register: async function (server: Server) {\n server.ext(\"onPostStart\", async () => {\n if (\n \"logger\" in server &&\n client.requestLogger.enabled &&\n client.requestLogger.config.captureLogs\n ) {\n pinoLoggerPatched = await patchPinoLogger(\n (server as any).logger,\n logsContext,\n );\n }\n });\n\n server.ext(\"onPostStart\", () => {\n const appInfo = getAppInfo(server, config.appVersion);\n client.setStartupData(appInfo);\n client.startSync();\n });\n\n server.ext(\"onPreStop\", async () => {\n await client.handleShutdown();\n });\n\n server.events.on(\"request\", (_, event) => {\n if (\n !pinoLoggerPatched &&\n client.requestLogger.enabled &&\n client.requestLogger.config.captureLogs &&\n event.channel === \"app\"\n ) {\n handleHapiRequestEvent(event, logsContext);\n }\n });\n\n server.ext(\"onRequest\", async (request, h) => {\n if (!client.isEnabled() || request.method.toUpperCase() === \"OPTIONS\") {\n return h.continue;\n }\n\n request[START_TIME_SYMBOL] = performance.now();\n\n // Patch the lifecycle function to run with the logs context\n const lifecycle = (request as any)._lifecycle.bind(request);\n const logs: LogRecord[] = [];\n request[LOGS_SYMBOL] = logs;\n (request as any)._lifecycle = () => logsContext.run(logs, lifecycle);\n\n const captureRequestBody =\n client.requestLogger.enabled &&\n client.requestLogger.config.logRequestBody &&\n client.requestLogger.isSupportedContentType(\n request.headers[\"content-type\"],\n );\n const chunks: Buffer[] = [];\n let size = 0;\n request.events.on(\"peek\", (chunk: string, encoding: string) => {\n if (captureRequestBody) {\n chunks.push(Buffer.from(chunk, encoding as BufferEncoding));\n }\n size += Buffer.byteLength(chunk, encoding as BufferEncoding);\n });\n request.events.once(\"finish\", () => {\n if (chunks.length > 0) {\n request[REQUEST_BODY_SYMBOL] = Buffer.concat(chunks);\n }\n request[REQUEST_SIZE_SYMBOL] = size;\n });\n\n return h.continue;\n });\n\n server.ext(\"onPreResponse\", async (request, h) => {\n if (\n !client.isEnabled() ||\n request.method.toUpperCase() === \"OPTIONS\" ||\n isBoom(request.response)\n ) {\n return h.continue;\n }\n\n const captureResponseBody =\n client.requestLogger.enabled &&\n client.requestLogger.config.logResponseBody &&\n client.requestLogger.isSupportedContentType(\n request.response.contentType,\n );\n const chunks: Buffer[] = [];\n let size = 0;\n request.response.events.on(\n \"peek\",\n (chunk: string, encoding: string) => {\n if (captureResponseBody) {\n chunks.push(Buffer.from(chunk, encoding as BufferEncoding));\n }\n size += Buffer.byteLength(chunk, encoding as BufferEncoding);\n },\n );\n request.response.events.once(\"finish\", () => {\n if (chunks.length > 0) {\n request[RESPONSE_BODY_SYMBOL] = Buffer.concat(chunks);\n }\n request[RESPONSE_SIZE_SYMBOL] = size;\n });\n\n return h.continue;\n });\n\n server.ext(\"onPostResponse\", async (request, h) => {\n if (!client.isEnabled() || request.method.toUpperCase() === \"OPTIONS\") {\n return h.continue;\n }\n\n const startTime = request[START_TIME_SYMBOL];\n const responseTime = startTime ? performance.now() - startTime : 0;\n const timestamp = (Date.now() - responseTime) / 1000;\n const requestBody = request[REQUEST_BODY_SYMBOL];\n const requestSize = request[REQUEST_SIZE_SYMBOL];\n const response = request.response;\n let statusCode: number;\n let responseHeaders: Record<string, any>;\n let responseBody = request[RESPONSE_BODY_SYMBOL];\n let responseSize = request[RESPONSE_SIZE_SYMBOL];\n const error =\n (response as any)._error instanceof Error\n ? (response as any)._error\n : undefined;\n\n if (isBoom(response)) {\n // Handle Boom error object\n statusCode = response.output?.statusCode ?? 500;\n responseHeaders = response.output?.headers ?? {};\n } else {\n // Handle normal ResponseObject\n statusCode = response.statusCode ?? 200;\n responseHeaders = response.headers ?? {};\n }\n\n if (\n !responseBody &&\n (response as any)._payload &&\n client.requestLogger.enabled &&\n client.requestLogger.config.logResponseBody &&\n (isBoom(response) ||\n client.requestLogger.isSupportedContentType(response.contentType))\n ) {\n const responsePayload = (response as any)._payload;\n if (\n responsePayload &&\n responsePayload._data &&\n responsePayload._encoding &&\n typeof responsePayload._data === \"string\" &&\n typeof responsePayload._encoding === \"string\"\n ) {\n responseBody = Buffer.from(\n responsePayload._data,\n responsePayload._encoding as BufferEncoding,\n );\n }\n }\n\n if (!responseSize && responseBody) {\n responseSize = responseBody.length;\n }\n\n const consumer = request.apitallyConsumer\n ? consumerFromStringOrObject(request.apitallyConsumer)\n : null;\n client.consumerRegistry.addOrUpdateConsumer(consumer);\n\n if (request.route.path) {\n client.requestCounter.addRequest({\n consumer: consumer?.identifier,\n method: request.method,\n path: request.route.path,\n statusCode,\n responseTime,\n requestSize,\n responseSize,\n });\n\n if (statusCode === 500 && error) {\n client.serverErrorCounter.addServerError({\n consumer: consumer?.identifier,\n method: request.method,\n path: request.route.path,\n type: error.name,\n msg: error.message,\n traceback: error.stack || \"\",\n });\n }\n }\n\n if (client.requestLogger.enabled) {\n const logs = request[LOGS_SYMBOL];\n client.requestLogger.logRequest(\n {\n timestamp,\n consumer: consumer?.identifier,\n method: request.method,\n path: request.route.path,\n url: request.url?.href || \"\",\n headers: convertHeaders(request.headers),\n size: requestSize,\n body: requestBody,\n },\n {\n statusCode,\n responseTime: responseTime / 1000,\n headers: convertHeaders(responseHeaders),\n size: responseSize,\n body: responseBody,\n },\n error,\n logs,\n );\n }\n\n return h.continue;\n });\n },\n };\n}\n\nexport function setConsumer(\n request: Request,\n consumer: ApitallyConsumer | string | null | undefined,\n) {\n request.apitallyConsumer = consumer || undefined;\n}\n"],"mappings":"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","names":["AsyncLocalStorage","performance","ApitallyClient","consumerFromStringOrObject","convertHeaders","handleHapiRequestEvent","patchConsole","patchPinoLogger","patchWinston","getAppInfo","isBoom","START_TIME_SYMBOL","Symbol","REQUEST_BODY_SYMBOL","REQUEST_SIZE_SYMBOL","RESPONSE_BODY_SYMBOL","RESPONSE_SIZE_SYMBOL","LOGS_SYMBOL","config","client","logsContext","pinoLoggerPatched","requestLogger","enabled","captureLogs","name","register","server","ext","logger","appInfo","appVersion","setStartupData","startSync","handleShutdown","events","on","_","event","channel","request","h","isEnabled","method","toUpperCase","continue","now","lifecycle","_lifecycle","bind","logs","run","captureRequestBody","logRequestBody","isSupportedContentType","headers","chunks","size","chunk","encoding","push","Buffer","from","byteLength","once","length","concat","response","captureResponseBody","logResponseBody","contentType","startTime","responseTime","timestamp","Date","requestBody","requestSize","statusCode","responseHeaders","responseBody","responseSize","error","_error","Error","undefined","output","_payload","responsePayload","_data","_encoding","consumer","apitallyConsumer","consumerRegistry","addOrUpdateConsumer","route","path","requestCounter","addRequest","identifier","serverErrorCounter","addServerError","type","msg","message","traceback","stack","logRequest","url","href","body","apitallyPlugin","setConsumer"]}
1
+ {"version":3,"sources":["../../src/hapi/plugin.ts"],"sourcesContent":["import type { Request, Server } from \"@hapi/hapi\";\nimport { AsyncLocalStorage } from \"node:async_hooks\";\nimport { performance } from \"node:perf_hooks\";\n\nimport { ApitallyClient } from \"../common/client.js\";\nimport { consumerFromStringOrObject } from \"../common/consumerRegistry.js\";\nimport type { LogRecord } from \"../common/requestLogger.js\";\nimport { convertHeaders } from \"../common/requestLogger.js\";\nimport { ApitallyConfig, ApitallyConsumer } from \"../common/types.js\";\nimport {\n handleHapiRequestEvent,\n patchConsole,\n patchPinoLogger,\n patchWinston,\n} from \"../loggers/index.js\";\nimport { getAppInfo, isBoom } from \"./utils.js\";\n\nconst START_TIME_SYMBOL = Symbol(\"apitally.startTime\");\nconst REQUEST_BODY_SYMBOL = Symbol(\"apitally.requestBody\");\nconst REQUEST_SIZE_SYMBOL = Symbol(\"apitally.requestSize\");\nconst RESPONSE_BODY_SYMBOL = Symbol(\"apitally.responseBody\");\nconst RESPONSE_SIZE_SYMBOL = Symbol(\"apitally.responseSize\");\nconst LOGS_SYMBOL = Symbol(\"apitally.logs\");\n\ndeclare module \"@hapi/hapi\" {\n interface Request {\n [START_TIME_SYMBOL]?: number;\n [REQUEST_BODY_SYMBOL]?: Buffer;\n [REQUEST_SIZE_SYMBOL]?: number;\n [RESPONSE_BODY_SYMBOL]?: Buffer;\n [RESPONSE_SIZE_SYMBOL]?: number;\n [LOGS_SYMBOL]?: LogRecord[];\n apitallyConsumer?: ApitallyConsumer | string;\n }\n\n interface ResponseObject {\n readonly contentType: string | null; // Missing in Hapi types\n }\n}\n\nexport default function apitallyPlugin(config: ApitallyConfig) {\n const client = new ApitallyClient(config);\n const logsContext = new AsyncLocalStorage<LogRecord[]>();\n let pinoLoggerPatched = false;\n\n if (client.requestLogger.enabled && client.requestLogger.config.captureLogs) {\n patchConsole(logsContext);\n patchWinston(logsContext);\n }\n\n return {\n name: \"apitally\",\n register: async function (server: Server) {\n server.ext(\"onPostStart\", async () => {\n if (\n \"logger\" in server &&\n client.requestLogger.enabled &&\n client.requestLogger.config.captureLogs\n ) {\n pinoLoggerPatched = await patchPinoLogger(\n (server as any).logger,\n logsContext,\n );\n }\n });\n\n server.ext(\"onPostStart\", () => {\n const appInfo = getAppInfo(server, config.appVersion);\n client.setStartupData(appInfo);\n client.startSync();\n });\n\n server.ext(\"onPreStop\", async () => {\n await client.handleShutdown();\n });\n\n server.events.on(\"request\", (_, event) => {\n if (\n !pinoLoggerPatched &&\n client.requestLogger.enabled &&\n client.requestLogger.config.captureLogs &&\n event.channel === \"app\"\n ) {\n handleHapiRequestEvent(event, logsContext);\n }\n });\n\n server.ext(\"onRequest\", async (request, h) => {\n if (!client.isEnabled() || request.method.toUpperCase() === \"OPTIONS\") {\n return h.continue;\n }\n\n request[START_TIME_SYMBOL] = performance.now();\n\n // Patch the lifecycle function to run with the logs context\n const lifecycle = (request as any)._lifecycle.bind(request);\n const logs: LogRecord[] = [];\n request[LOGS_SYMBOL] = logs;\n (request as any)._lifecycle = () => logsContext.run(logs, lifecycle);\n\n const captureRequestBody =\n client.requestLogger.enabled &&\n client.requestLogger.config.logRequestBody &&\n client.requestLogger.isSupportedContentType(\n request.headers[\"content-type\"],\n );\n const chunks: Buffer[] = [];\n let size = 0;\n request.events.on(\"peek\", (chunk: string, encoding: string) => {\n if (captureRequestBody) {\n chunks.push(Buffer.from(chunk, encoding as BufferEncoding));\n }\n size += Buffer.byteLength(chunk, encoding as BufferEncoding);\n });\n request.events.once(\"finish\", () => {\n if (chunks.length > 0) {\n request[REQUEST_BODY_SYMBOL] = Buffer.concat(chunks);\n }\n request[REQUEST_SIZE_SYMBOL] = size;\n });\n\n return h.continue;\n });\n\n server.ext(\"onPreResponse\", async (request, h) => {\n if (\n !client.isEnabled() ||\n request.method.toUpperCase() === \"OPTIONS\" ||\n isBoom(request.response)\n ) {\n return h.continue;\n }\n\n const captureResponseBody =\n client.requestLogger.enabled &&\n client.requestLogger.config.logResponseBody &&\n client.requestLogger.isSupportedContentType(\n request.response.contentType,\n );\n const chunks: Buffer[] = [];\n let size = 0;\n request.response.events.on(\n \"peek\",\n (chunk: string, encoding: string) => {\n if (captureResponseBody) {\n chunks.push(Buffer.from(chunk, encoding as BufferEncoding));\n }\n size += Buffer.byteLength(chunk, encoding as BufferEncoding);\n },\n );\n request.response.events.once(\"finish\", () => {\n if (chunks.length > 0) {\n request[RESPONSE_BODY_SYMBOL] = Buffer.concat(chunks);\n }\n request[RESPONSE_SIZE_SYMBOL] = size;\n });\n\n return h.continue;\n });\n\n server.ext(\"onPostResponse\", async (request, h) => {\n if (!client.isEnabled() || request.method.toUpperCase() === \"OPTIONS\") {\n return h.continue;\n }\n\n const startTime = request[START_TIME_SYMBOL];\n const responseTime = startTime ? performance.now() - startTime : 0;\n const timestamp = (Date.now() - responseTime) / 1000;\n const requestBody = request[REQUEST_BODY_SYMBOL];\n const requestSize = request[REQUEST_SIZE_SYMBOL];\n const response = request.response;\n let statusCode: number;\n let responseHeaders: Record<string, any>;\n let responseBody = request[RESPONSE_BODY_SYMBOL];\n let responseSize = request[RESPONSE_SIZE_SYMBOL];\n const error =\n (response as any)._error instanceof Error\n ? (response as any)._error\n : undefined;\n\n if (isBoom(response)) {\n // Handle Boom error object\n statusCode = response.output?.statusCode ?? 500;\n responseHeaders = response.output?.headers ?? {};\n } else {\n // Handle normal ResponseObject\n statusCode = response.statusCode ?? 200;\n responseHeaders = response.headers ?? {};\n }\n\n if (\n !responseBody &&\n (response as any)._payload &&\n client.requestLogger.enabled &&\n client.requestLogger.config.logResponseBody &&\n (isBoom(response) ||\n client.requestLogger.isSupportedContentType(response.contentType))\n ) {\n const responsePayload = (response as any)._payload;\n if (\n responsePayload &&\n responsePayload._data &&\n responsePayload._encoding &&\n typeof responsePayload._data === \"string\" &&\n typeof responsePayload._encoding === \"string\"\n ) {\n responseBody = Buffer.from(\n responsePayload._data,\n responsePayload._encoding as BufferEncoding,\n );\n }\n }\n\n if (!responseSize && responseBody) {\n responseSize = responseBody.length;\n }\n\n const consumer = request.apitallyConsumer\n ? consumerFromStringOrObject(request.apitallyConsumer)\n : null;\n client.consumerRegistry.addOrUpdateConsumer(consumer);\n\n if (request.route.path) {\n client.requestCounter.addRequest({\n consumer: consumer?.identifier,\n method: request.method,\n path: request.route.path,\n statusCode,\n responseTime,\n requestSize,\n responseSize,\n });\n\n if (statusCode === 500 && error) {\n client.serverErrorCounter.addServerError({\n consumer: consumer?.identifier,\n method: request.method,\n path: request.route.path,\n type: error.name,\n msg: error.message,\n traceback: error.stack || \"\",\n });\n }\n }\n\n if (client.requestLogger.enabled) {\n const logs = request[LOGS_SYMBOL];\n client.requestLogger.logRequest(\n {\n timestamp,\n consumer: consumer?.identifier,\n method: request.method,\n path: request.route.path,\n url: request.url?.href || \"\",\n headers: convertHeaders(request.headers),\n size: requestSize,\n body: requestBody,\n },\n {\n statusCode,\n responseTime: responseTime / 1000,\n headers: convertHeaders(responseHeaders),\n size: responseSize,\n body: responseBody,\n },\n error,\n logs,\n );\n }\n\n return h.continue;\n });\n },\n };\n}\n\nexport function setConsumer(\n request: Request,\n consumer: ApitallyConsumer | string | null | undefined,\n) {\n request.apitallyConsumer = consumer || undefined;\n}\n"],"mappings":"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","names":["AsyncLocalStorage","performance","ApitallyClient","consumerFromStringOrObject","convertHeaders","handleHapiRequestEvent","patchConsole","patchPinoLogger","patchWinston","getAppInfo","isBoom","START_TIME_SYMBOL","Symbol","REQUEST_BODY_SYMBOL","REQUEST_SIZE_SYMBOL","RESPONSE_BODY_SYMBOL","RESPONSE_SIZE_SYMBOL","LOGS_SYMBOL","config","client","logsContext","pinoLoggerPatched","requestLogger","enabled","captureLogs","name","register","server","ext","logger","appInfo","appVersion","setStartupData","startSync","handleShutdown","events","on","_","event","channel","request","h","isEnabled","method","toUpperCase","continue","now","lifecycle","_lifecycle","bind","logs","run","captureRequestBody","logRequestBody","isSupportedContentType","headers","chunks","size","chunk","encoding","push","Buffer","from","byteLength","once","length","concat","response","captureResponseBody","logResponseBody","contentType","startTime","responseTime","timestamp","Date","requestBody","requestSize","statusCode","responseHeaders","responseBody","responseSize","error","_error","Error","undefined","output","_payload","responsePayload","_data","_encoding","consumer","apitallyConsumer","consumerRegistry","addOrUpdateConsumer","route","path","requestCounter","addRequest","identifier","serverErrorCounter","addServerError","type","msg","message","traceback","stack","logRequest","url","href","body","apitallyPlugin","setConsumer"]}
@@ -35,7 +35,7 @@ module.exports = __toCommonJS(pino_exports);
35
35
  var import_utils = require("./utils.js");
36
36
  var _a;
37
37
  const MAX_BUFFER_SIZE = 1e3;
38
- const originalStreamSym = Symbol.for("apitally.originalStream");
38
+ const originalStreamSym = /* @__PURE__ */ Symbol.for("apitally.originalStream");
39
39
  const logLevelMap = {
40
40
  10: "trace",
41
41
  20: "debug",
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/loggers/pino.ts"],"sourcesContent":["import { AsyncLocalStorage } from \"node:async_hooks\";\n\nimport type { LogRecord } from \"../common/requestLogger.js\";\nimport { formatMessage, removeKeys } from \"./utils.js\";\n\nconst MAX_BUFFER_SIZE = 1000;\n\nconst originalStreamSym = Symbol.for(\"apitally.originalStream\");\nconst logLevelMap: Record<number, string> = {\n 10: \"trace\",\n 20: \"debug\",\n 30: \"info\",\n 40: \"warn\",\n 50: \"error\",\n 60: \"fatal\",\n};\n\nexport async function patchPinoLogger(\n logger: any,\n logsContext: AsyncLocalStorage<LogRecord[]>,\n) {\n try {\n // Find stream and message key symbols on the logger and its prototype\n const symbols = [\n ...Object.getOwnPropertySymbols(logger),\n ...Object.getOwnPropertySymbols(Object.getPrototypeOf(logger)),\n ];\n const streamSym = symbols.find(\n (sym) => sym.toString() === \"Symbol(pino.stream)\",\n );\n const messageKeySym = symbols.find(\n (sym) => sym.toString() === \"Symbol(pino.messageKey)\",\n );\n if (!streamSym || !messageKeySym) {\n // not a pino logger\n return false;\n }\n\n if (!(originalStreamSym in logger)) {\n logger[originalStreamSym] = logger[streamSym];\n }\n\n const originalStream = logger[originalStreamSym];\n if (originalStream) {\n const pino = await import(/* webpackIgnore: true */ \"pino\");\n const captureStream = new ApitallyLogCaptureStream(\n logsContext,\n logger[messageKeySym],\n );\n logger[streamSym] = pino.default.multistream(\n [\n { level: 0, stream: originalStream },\n { level: 0, stream: captureStream },\n ],\n {\n levels: logger.levels,\n },\n );\n }\n return true;\n } catch {\n // ignore errors\n return false;\n }\n}\n\nfunction filterLogs(obj: any, messageKey: string) {\n return obj[messageKey] !== \"request completed\";\n}\n\nclass ApitallyLogCaptureStream {\n private logsContext: AsyncLocalStorage<LogRecord[]>;\n private messageKey: string;\n\n constructor(logsContext: AsyncLocalStorage<LogRecord[]>, messageKey: string) {\n this.logsContext = logsContext;\n this.messageKey = messageKey;\n }\n\n write(msg: string): void {\n const logs = this.logsContext.getStore();\n if (!logs || !msg || logs.length >= MAX_BUFFER_SIZE) {\n return;\n }\n\n let obj: any;\n try {\n obj = JSON.parse(msg);\n } catch (e) {\n return;\n }\n if (\n obj === null ||\n typeof obj !== \"object\" ||\n !filterLogs(obj, this.messageKey)\n ) {\n return;\n }\n\n try {\n let message = obj[this.messageKey];\n const ignoreKeys = [\n \"hostname\",\n \"level\",\n this.messageKey,\n \"pid\",\n \"time\",\n \"reqId\",\n \"req\",\n \"res\",\n ];\n if (!message && \"data\" in obj && \"tags\" in obj) {\n // hapi-pino uses data and tags instead of the message key\n message = obj.data;\n ignoreKeys.push(\"data\");\n ignoreKeys.push(\"tags\");\n }\n const rest = removeKeys(obj, ignoreKeys);\n const formattedMessage = formatMessage(message, rest);\n if (formattedMessage) {\n logs.push({\n timestamp: this.convertTime(obj.time),\n level: logLevelMap[obj.level] || \"info\",\n message: formattedMessage,\n });\n }\n } catch (e) {\n // ignore\n }\n }\n\n private convertTime(time: any): number {\n if (typeof time === \"number\" && !isNaN(time)) {\n return time / 1000; // Convert milliseconds to seconds\n }\n return Date.now() / 1000; // Fallback to current time\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAGA;;;;;AAAA,mBAA0C;AAA1C;AAEA,MAAMA,kBAAkB;AAExB,MAAMC,oBAAoBC,OAAOC,IAAI,yBAAA;AACrC,MAAMC,cAAsC;EAC1C,IAAI;EACJ,IAAI;EACJ,IAAI;EACJ,IAAI;EACJ,IAAI;EACJ,IAAI;AACN;AAEA,eAAsBC,gBACpBC,QACAC,aAA2C;AAE3C,MAAI;AAEF,UAAMC,UAAU;SACXC,OAAOC,sBAAsBJ,MAAAA;SAC7BG,OAAOC,sBAAsBD,OAAOE,eAAeL,MAAAA,CAAAA;;AAExD,UAAMM,YAAYJ,QAAQK,KACxB,CAACC,QAAQA,IAAIC,SAAQ,MAAO,qBAAA;AAE9B,UAAMC,gBAAgBR,QAAQK,KAC5B,CAACC,QAAQA,IAAIC,SAAQ,MAAO,yBAAA;AAE9B,QAAI,CAACH,aAAa,CAACI,eAAe;AAEhC,aAAO;IACT;AAEA,QAAI,EAAEf,qBAAqBK,SAAS;AAClCA,aAAOL,iBAAAA,IAAqBK,OAAOM,SAAAA;IACrC;AAEA,UAAMK,iBAAiBX,OAAOL,iBAAAA;AAC9B,QAAIgB,gBAAgB;AAClB,YAAMC,OAAO,MAAM;;QAAiC;MAAA;AACpD,YAAMC,gBAAgB,IAAIC,yBACxBb,aACAD,OAAOU,aAAAA,CAAc;AAEvBV,aAAOM,SAAAA,IAAaM,KAAKG,QAAQC,YAC/B;QACE;UAAEC,OAAO;UAAGC,QAAQP;QAAe;QACnC;UAAEM,OAAO;UAAGC,QAAQL;QAAc;SAEpC;QACEM,QAAQnB,OAAOmB;MACjB,CAAA;IAEJ;AACA,WAAO;EACT,QAAQ;AAEN,WAAO;EACT;AACF;AA/CsBpB;AAiDtB,SAASqB,WAAWC,KAAUC,YAAkB;AAC9C,SAAOD,IAAIC,UAAAA,MAAgB;AAC7B;AAFSF;AAIT,IAAMN,4BAAN,WAAMA;EACIb;EACAqB;EAER,YAAYrB,aAA6CqB,YAAoB;AAC3E,SAAKrB,cAAcA;AACnB,SAAKqB,aAAaA;EACpB;EAEAC,MAAMC,KAAmB;AACvB,UAAMC,OAAO,KAAKxB,YAAYyB,SAAQ;AACtC,QAAI,CAACD,QAAQ,CAACD,OAAOC,KAAKE,UAAUjC,iBAAiB;AACnD;IACF;AAEA,QAAI2B;AACJ,QAAI;AACFA,YAAMO,KAAKC,MAAML,GAAAA;IACnB,SAASM,GAAG;AACV;IACF;AACA,QACET,QAAQ,QACR,OAAOA,QAAQ,YACf,CAACD,WAAWC,KAAK,KAAKC,UAAU,GAChC;AACA;IACF;AAEA,QAAI;AACF,UAAIS,UAAUV,IAAI,KAAKC,UAAU;AACjC,YAAMU,aAAa;QACjB;QACA;QACA,KAAKV;QACL;QACA;QACA;QACA;QACA;;AAEF,UAAI,CAACS,WAAW,UAAUV,OAAO,UAAUA,KAAK;AAE9CU,kBAAUV,IAAIY;AACdD,mBAAWE,KAAK,MAAA;AAChBF,mBAAWE,KAAK,MAAA;MAClB;AACA,YAAMC,WAAOC,yBAAWf,KAAKW,UAAAA;AAC7B,YAAMK,uBAAmBC,4BAAcP,SAASI,IAAAA;AAChD,UAAIE,kBAAkB;AACpBZ,aAAKS,KAAK;UACRK,WAAW,KAAKC,YAAYnB,IAAIoB,IAAI;UACpCxB,OAAOnB,YAAYuB,IAAIJ,KAAK,KAAK;UACjCc,SAASM;QACX,CAAA;MACF;IACF,SAASP,GAAG;IAEZ;EACF;EAEQU,YAAYC,MAAmB;AACrC,QAAI,OAAOA,SAAS,YAAY,CAACC,MAAMD,IAAAA,GAAO;AAC5C,aAAOA,OAAO;IAChB;AACA,WAAOE,KAAKC,IAAG,IAAK;EACtB;AACF,GAnEM9B,wCAAN;","names":["MAX_BUFFER_SIZE","originalStreamSym","Symbol","for","logLevelMap","patchPinoLogger","logger","logsContext","symbols","Object","getOwnPropertySymbols","getPrototypeOf","streamSym","find","sym","toString","messageKeySym","originalStream","pino","captureStream","ApitallyLogCaptureStream","default","multistream","level","stream","levels","filterLogs","obj","messageKey","write","msg","logs","getStore","length","JSON","parse","e","message","ignoreKeys","data","push","rest","removeKeys","formattedMessage","formatMessage","timestamp","convertTime","time","isNaN","Date","now"]}
1
+ {"version":3,"sources":["../../src/loggers/pino.ts"],"sourcesContent":["import { AsyncLocalStorage } from \"node:async_hooks\";\n\nimport type { LogRecord } from \"../common/requestLogger.js\";\nimport { formatMessage, removeKeys } from \"./utils.js\";\n\nconst MAX_BUFFER_SIZE = 1000;\n\nconst originalStreamSym = Symbol.for(\"apitally.originalStream\");\nconst logLevelMap: Record<number, string> = {\n 10: \"trace\",\n 20: \"debug\",\n 30: \"info\",\n 40: \"warn\",\n 50: \"error\",\n 60: \"fatal\",\n};\n\nexport async function patchPinoLogger(\n logger: any,\n logsContext: AsyncLocalStorage<LogRecord[]>,\n) {\n try {\n // Find stream and message key symbols on the logger and its prototype\n const symbols = [\n ...Object.getOwnPropertySymbols(logger),\n ...Object.getOwnPropertySymbols(Object.getPrototypeOf(logger)),\n ];\n const streamSym = symbols.find(\n (sym) => sym.toString() === \"Symbol(pino.stream)\",\n );\n const messageKeySym = symbols.find(\n (sym) => sym.toString() === \"Symbol(pino.messageKey)\",\n );\n if (!streamSym || !messageKeySym) {\n // not a pino logger\n return false;\n }\n\n if (!(originalStreamSym in logger)) {\n logger[originalStreamSym] = logger[streamSym];\n }\n\n const originalStream = logger[originalStreamSym];\n if (originalStream) {\n const pino = await import(/* webpackIgnore: true */ \"pino\");\n const captureStream = new ApitallyLogCaptureStream(\n logsContext,\n logger[messageKeySym],\n );\n logger[streamSym] = pino.default.multistream(\n [\n { level: 0, stream: originalStream },\n { level: 0, stream: captureStream },\n ],\n {\n levels: logger.levels,\n },\n );\n }\n return true;\n } catch {\n // ignore errors\n return false;\n }\n}\n\nfunction filterLogs(obj: any, messageKey: string) {\n return obj[messageKey] !== \"request completed\";\n}\n\nclass ApitallyLogCaptureStream {\n private logsContext: AsyncLocalStorage<LogRecord[]>;\n private messageKey: string;\n\n constructor(logsContext: AsyncLocalStorage<LogRecord[]>, messageKey: string) {\n this.logsContext = logsContext;\n this.messageKey = messageKey;\n }\n\n write(msg: string): void {\n const logs = this.logsContext.getStore();\n if (!logs || !msg || logs.length >= MAX_BUFFER_SIZE) {\n return;\n }\n\n let obj: any;\n try {\n obj = JSON.parse(msg);\n } catch (e) {\n return;\n }\n if (\n obj === null ||\n typeof obj !== \"object\" ||\n !filterLogs(obj, this.messageKey)\n ) {\n return;\n }\n\n try {\n let message = obj[this.messageKey];\n const ignoreKeys = [\n \"hostname\",\n \"level\",\n this.messageKey,\n \"pid\",\n \"time\",\n \"reqId\",\n \"req\",\n \"res\",\n ];\n if (!message && \"data\" in obj && \"tags\" in obj) {\n // hapi-pino uses data and tags instead of the message key\n message = obj.data;\n ignoreKeys.push(\"data\");\n ignoreKeys.push(\"tags\");\n }\n const rest = removeKeys(obj, ignoreKeys);\n const formattedMessage = formatMessage(message, rest);\n if (formattedMessage) {\n logs.push({\n timestamp: this.convertTime(obj.time),\n level: logLevelMap[obj.level] || \"info\",\n message: formattedMessage,\n });\n }\n } catch (e) {\n // ignore\n }\n }\n\n private convertTime(time: any): number {\n if (typeof time === \"number\" && !isNaN(time)) {\n return time / 1000; // Convert milliseconds to seconds\n }\n return Date.now() / 1000; // Fallback to current time\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAGA;;;;;AAAA,mBAA0C;AAA1C;AAEA,MAAMA,kBAAkB;AAExB,MAAMC,oBAAoBC,uBAAOC,IAAI,yBAAA;AACrC,MAAMC,cAAsC;EAC1C,IAAI;EACJ,IAAI;EACJ,IAAI;EACJ,IAAI;EACJ,IAAI;EACJ,IAAI;AACN;AAEA,eAAsBC,gBACpBC,QACAC,aAA2C;AAE3C,MAAI;AAEF,UAAMC,UAAU;SACXC,OAAOC,sBAAsBJ,MAAAA;SAC7BG,OAAOC,sBAAsBD,OAAOE,eAAeL,MAAAA,CAAAA;;AAExD,UAAMM,YAAYJ,QAAQK,KACxB,CAACC,QAAQA,IAAIC,SAAQ,MAAO,qBAAA;AAE9B,UAAMC,gBAAgBR,QAAQK,KAC5B,CAACC,QAAQA,IAAIC,SAAQ,MAAO,yBAAA;AAE9B,QAAI,CAACH,aAAa,CAACI,eAAe;AAEhC,aAAO;IACT;AAEA,QAAI,EAAEf,qBAAqBK,SAAS;AAClCA,aAAOL,iBAAAA,IAAqBK,OAAOM,SAAAA;IACrC;AAEA,UAAMK,iBAAiBX,OAAOL,iBAAAA;AAC9B,QAAIgB,gBAAgB;AAClB,YAAMC,OAAO,MAAM;;QAAiC;MAAA;AACpD,YAAMC,gBAAgB,IAAIC,yBACxBb,aACAD,OAAOU,aAAAA,CAAc;AAEvBV,aAAOM,SAAAA,IAAaM,KAAKG,QAAQC,YAC/B;QACE;UAAEC,OAAO;UAAGC,QAAQP;QAAe;QACnC;UAAEM,OAAO;UAAGC,QAAQL;QAAc;SAEpC;QACEM,QAAQnB,OAAOmB;MACjB,CAAA;IAEJ;AACA,WAAO;EACT,QAAQ;AAEN,WAAO;EACT;AACF;AA/CsBpB;AAiDtB,SAASqB,WAAWC,KAAUC,YAAkB;AAC9C,SAAOD,IAAIC,UAAAA,MAAgB;AAC7B;AAFSF;AAIT,IAAMN,4BAAN,WAAMA;EACIb;EACAqB;EAER,YAAYrB,aAA6CqB,YAAoB;AAC3E,SAAKrB,cAAcA;AACnB,SAAKqB,aAAaA;EACpB;EAEAC,MAAMC,KAAmB;AACvB,UAAMC,OAAO,KAAKxB,YAAYyB,SAAQ;AACtC,QAAI,CAACD,QAAQ,CAACD,OAAOC,KAAKE,UAAUjC,iBAAiB;AACnD;IACF;AAEA,QAAI2B;AACJ,QAAI;AACFA,YAAMO,KAAKC,MAAML,GAAAA;IACnB,SAASM,GAAG;AACV;IACF;AACA,QACET,QAAQ,QACR,OAAOA,QAAQ,YACf,CAACD,WAAWC,KAAK,KAAKC,UAAU,GAChC;AACA;IACF;AAEA,QAAI;AACF,UAAIS,UAAUV,IAAI,KAAKC,UAAU;AACjC,YAAMU,aAAa;QACjB;QACA;QACA,KAAKV;QACL;QACA;QACA;QACA;QACA;;AAEF,UAAI,CAACS,WAAW,UAAUV,OAAO,UAAUA,KAAK;AAE9CU,kBAAUV,IAAIY;AACdD,mBAAWE,KAAK,MAAA;AAChBF,mBAAWE,KAAK,MAAA;MAClB;AACA,YAAMC,WAAOC,yBAAWf,KAAKW,UAAAA;AAC7B,YAAMK,uBAAmBC,4BAAcP,SAASI,IAAAA;AAChD,UAAIE,kBAAkB;AACpBZ,aAAKS,KAAK;UACRK,WAAW,KAAKC,YAAYnB,IAAIoB,IAAI;UACpCxB,OAAOnB,YAAYuB,IAAIJ,KAAK,KAAK;UACjCc,SAASM;QACX,CAAA;MACF;IACF,SAASP,GAAG;IAEZ;EACF;EAEQU,YAAYC,MAAmB;AACrC,QAAI,OAAOA,SAAS,YAAY,CAACC,MAAMD,IAAAA,GAAO;AAC5C,aAAOA,OAAO;IAChB;AACA,WAAOE,KAAKC,IAAG,IAAK;EACtB;AACF,GAnEM9B,wCAAN;","names":["MAX_BUFFER_SIZE","originalStreamSym","Symbol","for","logLevelMap","patchPinoLogger","logger","logsContext","symbols","Object","getOwnPropertySymbols","getPrototypeOf","streamSym","find","sym","toString","messageKeySym","originalStream","pino","captureStream","ApitallyLogCaptureStream","default","multistream","level","stream","levels","filterLogs","obj","messageKey","write","msg","logs","getStore","length","JSON","parse","e","message","ignoreKeys","data","push","rest","removeKeys","formattedMessage","formatMessage","timestamp","convertTime","time","isNaN","Date","now"]}
@@ -3,7 +3,7 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
3
3
  var _a;
4
4
  import { formatMessage, removeKeys } from "./utils.js";
5
5
  const MAX_BUFFER_SIZE = 1e3;
6
- const originalStreamSym = Symbol.for("apitally.originalStream");
6
+ const originalStreamSym = /* @__PURE__ */ Symbol.for("apitally.originalStream");
7
7
  const logLevelMap = {
8
8
  10: "trace",
9
9
  20: "debug",
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/loggers/pino.ts"],"sourcesContent":["import { AsyncLocalStorage } from \"node:async_hooks\";\n\nimport type { LogRecord } from \"../common/requestLogger.js\";\nimport { formatMessage, removeKeys } from \"./utils.js\";\n\nconst MAX_BUFFER_SIZE = 1000;\n\nconst originalStreamSym = Symbol.for(\"apitally.originalStream\");\nconst logLevelMap: Record<number, string> = {\n 10: \"trace\",\n 20: \"debug\",\n 30: \"info\",\n 40: \"warn\",\n 50: \"error\",\n 60: \"fatal\",\n};\n\nexport async function patchPinoLogger(\n logger: any,\n logsContext: AsyncLocalStorage<LogRecord[]>,\n) {\n try {\n // Find stream and message key symbols on the logger and its prototype\n const symbols = [\n ...Object.getOwnPropertySymbols(logger),\n ...Object.getOwnPropertySymbols(Object.getPrototypeOf(logger)),\n ];\n const streamSym = symbols.find(\n (sym) => sym.toString() === \"Symbol(pino.stream)\",\n );\n const messageKeySym = symbols.find(\n (sym) => sym.toString() === \"Symbol(pino.messageKey)\",\n );\n if (!streamSym || !messageKeySym) {\n // not a pino logger\n return false;\n }\n\n if (!(originalStreamSym in logger)) {\n logger[originalStreamSym] = logger[streamSym];\n }\n\n const originalStream = logger[originalStreamSym];\n if (originalStream) {\n const pino = await import(/* webpackIgnore: true */ \"pino\");\n const captureStream = new ApitallyLogCaptureStream(\n logsContext,\n logger[messageKeySym],\n );\n logger[streamSym] = pino.default.multistream(\n [\n { level: 0, stream: originalStream },\n { level: 0, stream: captureStream },\n ],\n {\n levels: logger.levels,\n },\n );\n }\n return true;\n } catch {\n // ignore errors\n return false;\n }\n}\n\nfunction filterLogs(obj: any, messageKey: string) {\n return obj[messageKey] !== \"request completed\";\n}\n\nclass ApitallyLogCaptureStream {\n private logsContext: AsyncLocalStorage<LogRecord[]>;\n private messageKey: string;\n\n constructor(logsContext: AsyncLocalStorage<LogRecord[]>, messageKey: string) {\n this.logsContext = logsContext;\n this.messageKey = messageKey;\n }\n\n write(msg: string): void {\n const logs = this.logsContext.getStore();\n if (!logs || !msg || logs.length >= MAX_BUFFER_SIZE) {\n return;\n }\n\n let obj: any;\n try {\n obj = JSON.parse(msg);\n } catch (e) {\n return;\n }\n if (\n obj === null ||\n typeof obj !== \"object\" ||\n !filterLogs(obj, this.messageKey)\n ) {\n return;\n }\n\n try {\n let message = obj[this.messageKey];\n const ignoreKeys = [\n \"hostname\",\n \"level\",\n this.messageKey,\n \"pid\",\n \"time\",\n \"reqId\",\n \"req\",\n \"res\",\n ];\n if (!message && \"data\" in obj && \"tags\" in obj) {\n // hapi-pino uses data and tags instead of the message key\n message = obj.data;\n ignoreKeys.push(\"data\");\n ignoreKeys.push(\"tags\");\n }\n const rest = removeKeys(obj, ignoreKeys);\n const formattedMessage = formatMessage(message, rest);\n if (formattedMessage) {\n logs.push({\n timestamp: this.convertTime(obj.time),\n level: logLevelMap[obj.level] || \"info\",\n message: formattedMessage,\n });\n }\n } catch (e) {\n // ignore\n }\n }\n\n private convertTime(time: any): number {\n if (typeof time === \"number\" && !isNaN(time)) {\n return time / 1000; // Convert milliseconds to seconds\n }\n return Date.now() / 1000; // Fallback to current time\n }\n}\n"],"mappings":";;AAGA;SAASA,eAAeC,kBAAkB;AAE1C,MAAMC,kBAAkB;AAExB,MAAMC,oBAAoBC,OAAOC,IAAI,yBAAA;AACrC,MAAMC,cAAsC;EAC1C,IAAI;EACJ,IAAI;EACJ,IAAI;EACJ,IAAI;EACJ,IAAI;EACJ,IAAI;AACN;AAEA,eAAsBC,gBACpBC,QACAC,aAA2C;AAE3C,MAAI;AAEF,UAAMC,UAAU;SACXC,OAAOC,sBAAsBJ,MAAAA;SAC7BG,OAAOC,sBAAsBD,OAAOE,eAAeL,MAAAA,CAAAA;;AAExD,UAAMM,YAAYJ,QAAQK,KACxB,CAACC,QAAQA,IAAIC,SAAQ,MAAO,qBAAA;AAE9B,UAAMC,gBAAgBR,QAAQK,KAC5B,CAACC,QAAQA,IAAIC,SAAQ,MAAO,yBAAA;AAE9B,QAAI,CAACH,aAAa,CAACI,eAAe;AAEhC,aAAO;IACT;AAEA,QAAI,EAAEf,qBAAqBK,SAAS;AAClCA,aAAOL,iBAAAA,IAAqBK,OAAOM,SAAAA;IACrC;AAEA,UAAMK,iBAAiBX,OAAOL,iBAAAA;AAC9B,QAAIgB,gBAAgB;AAClB,YAAMC,OAAO,MAAM;;QAAiC;MAAA;AACpD,YAAMC,gBAAgB,IAAIC,yBACxBb,aACAD,OAAOU,aAAAA,CAAc;AAEvBV,aAAOM,SAAAA,IAAaM,KAAKG,QAAQC,YAC/B;QACE;UAAEC,OAAO;UAAGC,QAAQP;QAAe;QACnC;UAAEM,OAAO;UAAGC,QAAQL;QAAc;SAEpC;QACEM,QAAQnB,OAAOmB;MACjB,CAAA;IAEJ;AACA,WAAO;EACT,QAAQ;AAEN,WAAO;EACT;AACF;AA/CsBpB;AAiDtB,SAASqB,WAAWC,KAAUC,YAAkB;AAC9C,SAAOD,IAAIC,UAAAA,MAAgB;AAC7B;AAFSF;AAIT,IAAMN,4BAAN,WAAMA;EACIb;EACAqB;EAER,YAAYrB,aAA6CqB,YAAoB;AAC3E,SAAKrB,cAAcA;AACnB,SAAKqB,aAAaA;EACpB;EAEAC,MAAMC,KAAmB;AACvB,UAAMC,OAAO,KAAKxB,YAAYyB,SAAQ;AACtC,QAAI,CAACD,QAAQ,CAACD,OAAOC,KAAKE,UAAUjC,iBAAiB;AACnD;IACF;AAEA,QAAI2B;AACJ,QAAI;AACFA,YAAMO,KAAKC,MAAML,GAAAA;IACnB,SAASM,GAAG;AACV;IACF;AACA,QACET,QAAQ,QACR,OAAOA,QAAQ,YACf,CAACD,WAAWC,KAAK,KAAKC,UAAU,GAChC;AACA;IACF;AAEA,QAAI;AACF,UAAIS,UAAUV,IAAI,KAAKC,UAAU;AACjC,YAAMU,aAAa;QACjB;QACA;QACA,KAAKV;QACL;QACA;QACA;QACA;QACA;;AAEF,UAAI,CAACS,WAAW,UAAUV,OAAO,UAAUA,KAAK;AAE9CU,kBAAUV,IAAIY;AACdD,mBAAWE,KAAK,MAAA;AAChBF,mBAAWE,KAAK,MAAA;MAClB;AACA,YAAMC,OAAO1C,WAAW4B,KAAKW,UAAAA;AAC7B,YAAMI,mBAAmB5C,cAAcuC,SAASI,IAAAA;AAChD,UAAIC,kBAAkB;AACpBX,aAAKS,KAAK;UACRG,WAAW,KAAKC,YAAYjB,IAAIkB,IAAI;UACpCtB,OAAOnB,YAAYuB,IAAIJ,KAAK,KAAK;UACjCc,SAASK;QACX,CAAA;MACF;IACF,SAASN,GAAG;IAEZ;EACF;EAEQQ,YAAYC,MAAmB;AACrC,QAAI,OAAOA,SAAS,YAAY,CAACC,MAAMD,IAAAA,GAAO;AAC5C,aAAOA,OAAO;IAChB;AACA,WAAOE,KAAKC,IAAG,IAAK;EACtB;AACF,GAnEM5B,wCAAN;","names":["formatMessage","removeKeys","MAX_BUFFER_SIZE","originalStreamSym","Symbol","for","logLevelMap","patchPinoLogger","logger","logsContext","symbols","Object","getOwnPropertySymbols","getPrototypeOf","streamSym","find","sym","toString","messageKeySym","originalStream","pino","captureStream","ApitallyLogCaptureStream","default","multistream","level","stream","levels","filterLogs","obj","messageKey","write","msg","logs","getStore","length","JSON","parse","e","message","ignoreKeys","data","push","rest","formattedMessage","timestamp","convertTime","time","isNaN","Date","now"]}
1
+ {"version":3,"sources":["../../src/loggers/pino.ts"],"sourcesContent":["import { AsyncLocalStorage } from \"node:async_hooks\";\n\nimport type { LogRecord } from \"../common/requestLogger.js\";\nimport { formatMessage, removeKeys } from \"./utils.js\";\n\nconst MAX_BUFFER_SIZE = 1000;\n\nconst originalStreamSym = Symbol.for(\"apitally.originalStream\");\nconst logLevelMap: Record<number, string> = {\n 10: \"trace\",\n 20: \"debug\",\n 30: \"info\",\n 40: \"warn\",\n 50: \"error\",\n 60: \"fatal\",\n};\n\nexport async function patchPinoLogger(\n logger: any,\n logsContext: AsyncLocalStorage<LogRecord[]>,\n) {\n try {\n // Find stream and message key symbols on the logger and its prototype\n const symbols = [\n ...Object.getOwnPropertySymbols(logger),\n ...Object.getOwnPropertySymbols(Object.getPrototypeOf(logger)),\n ];\n const streamSym = symbols.find(\n (sym) => sym.toString() === \"Symbol(pino.stream)\",\n );\n const messageKeySym = symbols.find(\n (sym) => sym.toString() === \"Symbol(pino.messageKey)\",\n );\n if (!streamSym || !messageKeySym) {\n // not a pino logger\n return false;\n }\n\n if (!(originalStreamSym in logger)) {\n logger[originalStreamSym] = logger[streamSym];\n }\n\n const originalStream = logger[originalStreamSym];\n if (originalStream) {\n const pino = await import(/* webpackIgnore: true */ \"pino\");\n const captureStream = new ApitallyLogCaptureStream(\n logsContext,\n logger[messageKeySym],\n );\n logger[streamSym] = pino.default.multistream(\n [\n { level: 0, stream: originalStream },\n { level: 0, stream: captureStream },\n ],\n {\n levels: logger.levels,\n },\n );\n }\n return true;\n } catch {\n // ignore errors\n return false;\n }\n}\n\nfunction filterLogs(obj: any, messageKey: string) {\n return obj[messageKey] !== \"request completed\";\n}\n\nclass ApitallyLogCaptureStream {\n private logsContext: AsyncLocalStorage<LogRecord[]>;\n private messageKey: string;\n\n constructor(logsContext: AsyncLocalStorage<LogRecord[]>, messageKey: string) {\n this.logsContext = logsContext;\n this.messageKey = messageKey;\n }\n\n write(msg: string): void {\n const logs = this.logsContext.getStore();\n if (!logs || !msg || logs.length >= MAX_BUFFER_SIZE) {\n return;\n }\n\n let obj: any;\n try {\n obj = JSON.parse(msg);\n } catch (e) {\n return;\n }\n if (\n obj === null ||\n typeof obj !== \"object\" ||\n !filterLogs(obj, this.messageKey)\n ) {\n return;\n }\n\n try {\n let message = obj[this.messageKey];\n const ignoreKeys = [\n \"hostname\",\n \"level\",\n this.messageKey,\n \"pid\",\n \"time\",\n \"reqId\",\n \"req\",\n \"res\",\n ];\n if (!message && \"data\" in obj && \"tags\" in obj) {\n // hapi-pino uses data and tags instead of the message key\n message = obj.data;\n ignoreKeys.push(\"data\");\n ignoreKeys.push(\"tags\");\n }\n const rest = removeKeys(obj, ignoreKeys);\n const formattedMessage = formatMessage(message, rest);\n if (formattedMessage) {\n logs.push({\n timestamp: this.convertTime(obj.time),\n level: logLevelMap[obj.level] || \"info\",\n message: formattedMessage,\n });\n }\n } catch (e) {\n // ignore\n }\n }\n\n private convertTime(time: any): number {\n if (typeof time === \"number\" && !isNaN(time)) {\n return time / 1000; // Convert milliseconds to seconds\n }\n return Date.now() / 1000; // Fallback to current time\n }\n}\n"],"mappings":";;AAGA;SAASA,eAAeC,kBAAkB;AAE1C,MAAMC,kBAAkB;AAExB,MAAMC,oBAAoBC,uBAAOC,IAAI,yBAAA;AACrC,MAAMC,cAAsC;EAC1C,IAAI;EACJ,IAAI;EACJ,IAAI;EACJ,IAAI;EACJ,IAAI;EACJ,IAAI;AACN;AAEA,eAAsBC,gBACpBC,QACAC,aAA2C;AAE3C,MAAI;AAEF,UAAMC,UAAU;SACXC,OAAOC,sBAAsBJ,MAAAA;SAC7BG,OAAOC,sBAAsBD,OAAOE,eAAeL,MAAAA,CAAAA;;AAExD,UAAMM,YAAYJ,QAAQK,KACxB,CAACC,QAAQA,IAAIC,SAAQ,MAAO,qBAAA;AAE9B,UAAMC,gBAAgBR,QAAQK,KAC5B,CAACC,QAAQA,IAAIC,SAAQ,MAAO,yBAAA;AAE9B,QAAI,CAACH,aAAa,CAACI,eAAe;AAEhC,aAAO;IACT;AAEA,QAAI,EAAEf,qBAAqBK,SAAS;AAClCA,aAAOL,iBAAAA,IAAqBK,OAAOM,SAAAA;IACrC;AAEA,UAAMK,iBAAiBX,OAAOL,iBAAAA;AAC9B,QAAIgB,gBAAgB;AAClB,YAAMC,OAAO,MAAM;;QAAiC;MAAA;AACpD,YAAMC,gBAAgB,IAAIC,yBACxBb,aACAD,OAAOU,aAAAA,CAAc;AAEvBV,aAAOM,SAAAA,IAAaM,KAAKG,QAAQC,YAC/B;QACE;UAAEC,OAAO;UAAGC,QAAQP;QAAe;QACnC;UAAEM,OAAO;UAAGC,QAAQL;QAAc;SAEpC;QACEM,QAAQnB,OAAOmB;MACjB,CAAA;IAEJ;AACA,WAAO;EACT,QAAQ;AAEN,WAAO;EACT;AACF;AA/CsBpB;AAiDtB,SAASqB,WAAWC,KAAUC,YAAkB;AAC9C,SAAOD,IAAIC,UAAAA,MAAgB;AAC7B;AAFSF;AAIT,IAAMN,4BAAN,WAAMA;EACIb;EACAqB;EAER,YAAYrB,aAA6CqB,YAAoB;AAC3E,SAAKrB,cAAcA;AACnB,SAAKqB,aAAaA;EACpB;EAEAC,MAAMC,KAAmB;AACvB,UAAMC,OAAO,KAAKxB,YAAYyB,SAAQ;AACtC,QAAI,CAACD,QAAQ,CAACD,OAAOC,KAAKE,UAAUjC,iBAAiB;AACnD;IACF;AAEA,QAAI2B;AACJ,QAAI;AACFA,YAAMO,KAAKC,MAAML,GAAAA;IACnB,SAASM,GAAG;AACV;IACF;AACA,QACET,QAAQ,QACR,OAAOA,QAAQ,YACf,CAACD,WAAWC,KAAK,KAAKC,UAAU,GAChC;AACA;IACF;AAEA,QAAI;AACF,UAAIS,UAAUV,IAAI,KAAKC,UAAU;AACjC,YAAMU,aAAa;QACjB;QACA;QACA,KAAKV;QACL;QACA;QACA;QACA;QACA;;AAEF,UAAI,CAACS,WAAW,UAAUV,OAAO,UAAUA,KAAK;AAE9CU,kBAAUV,IAAIY;AACdD,mBAAWE,KAAK,MAAA;AAChBF,mBAAWE,KAAK,MAAA;MAClB;AACA,YAAMC,OAAO1C,WAAW4B,KAAKW,UAAAA;AAC7B,YAAMI,mBAAmB5C,cAAcuC,SAASI,IAAAA;AAChD,UAAIC,kBAAkB;AACpBX,aAAKS,KAAK;UACRG,WAAW,KAAKC,YAAYjB,IAAIkB,IAAI;UACpCtB,OAAOnB,YAAYuB,IAAIJ,KAAK,KAAK;UACjCc,SAASK;QACX,CAAA;MACF;IACF,SAASN,GAAG;IAEZ;EACF;EAEQQ,YAAYC,MAAmB;AACrC,QAAI,OAAOA,SAAS,YAAY,CAACC,MAAMD,IAAAA,GAAO;AAC5C,aAAOA,OAAO;IAChB;AACA,WAAOE,KAAKC,IAAG,IAAK;EACtB;AACF,GAnEM5B,wCAAN;","names":["formatMessage","removeKeys","MAX_BUFFER_SIZE","originalStreamSym","Symbol","for","logLevelMap","patchPinoLogger","logger","logsContext","symbols","Object","getOwnPropertySymbols","getPrototypeOf","streamSym","find","sym","toString","messageKeySym","originalStream","pino","captureStream","ApitallyLogCaptureStream","default","multistream","level","stream","levels","filterLogs","obj","messageKey","write","msg","logs","getStore","length","JSON","parse","e","message","ignoreKeys","data","push","rest","formattedMessage","timestamp","convertTime","time","isNaN","Date","now"]}