apitally 0.23.1 → 0.25.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.
- package/dist/adonisjs/index.cjs +3 -0
- package/dist/adonisjs/index.cjs.map +1 -1
- package/dist/adonisjs/index.d.cts +2 -0
- package/dist/adonisjs/index.d.ts +2 -0
- package/dist/adonisjs/index.js +2 -0
- package/dist/adonisjs/index.js.map +1 -1
- package/dist/adonisjs/middleware.cjs +6 -2
- package/dist/adonisjs/middleware.cjs.map +1 -1
- package/dist/adonisjs/middleware.d.cts +2 -0
- package/dist/adonisjs/middleware.d.ts +2 -0
- package/dist/adonisjs/middleware.js +6 -2
- package/dist/adonisjs/middleware.js.map +1 -1
- package/dist/adonisjs/provider.d.cts +2 -0
- package/dist/adonisjs/provider.d.ts +2 -0
- package/dist/adonisjs/stubs/config/apitally.stub +1 -0
- package/dist/common/client.cjs +6 -1
- package/dist/common/client.cjs.map +1 -1
- package/dist/common/client.d.cts +3 -0
- package/dist/common/client.d.ts +3 -0
- package/dist/common/client.js +6 -1
- package/dist/common/client.js.map +1 -1
- package/dist/common/consumerRegistry.d.cts +2 -0
- package/dist/common/consumerRegistry.d.ts +2 -0
- package/dist/common/instance.cjs +158 -0
- package/dist/common/instance.cjs.map +1 -0
- package/dist/common/instance.d.cts +4 -0
- package/dist/common/instance.d.ts +4 -0
- package/dist/common/instance.js +134 -0
- package/dist/common/instance.js.map +1 -0
- package/dist/common/requestCounter.d.cts +2 -0
- package/dist/common/requestCounter.d.ts +2 -0
- package/dist/common/requestLogger.cjs +23 -19
- package/dist/common/requestLogger.cjs.map +1 -1
- package/dist/common/requestLogger.d.cts +6 -1
- package/dist/common/requestLogger.d.ts +6 -1
- package/dist/common/requestLogger.js +23 -19
- package/dist/common/requestLogger.js.map +1 -1
- package/dist/common/response.cjs +2 -2
- package/dist/common/response.cjs.map +1 -1
- package/dist/common/response.js +2 -2
- package/dist/common/response.js.map +1 -1
- package/dist/common/serverErrorCounter.cjs +3 -0
- package/dist/common/serverErrorCounter.cjs.map +1 -1
- package/dist/common/serverErrorCounter.d.cts +2 -0
- package/dist/common/serverErrorCounter.d.ts +2 -0
- package/dist/common/serverErrorCounter.js +3 -0
- package/dist/common/serverErrorCounter.js.map +1 -1
- package/dist/common/spanCollector.cjs +217 -0
- package/dist/common/spanCollector.cjs.map +1 -0
- package/dist/common/spanCollector.d.cts +50 -0
- package/dist/common/spanCollector.d.ts +50 -0
- package/dist/common/spanCollector.js +194 -0
- package/dist/common/spanCollector.js.map +1 -0
- package/dist/common/tempGzipFile.cjs +25 -2
- package/dist/common/tempGzipFile.cjs.map +1 -1
- package/dist/common/tempGzipFile.d.cts +3 -2
- package/dist/common/tempGzipFile.d.ts +3 -2
- package/dist/common/tempGzipFile.js +22 -3
- package/dist/common/tempGzipFile.js.map +1 -1
- package/dist/common/types.d.cts +2 -0
- package/dist/common/types.d.ts +2 -0
- package/dist/common/validationErrorCounter.d.cts +2 -0
- package/dist/common/validationErrorCounter.d.ts +2 -0
- package/dist/elysia/index.cjs +3 -0
- package/dist/elysia/index.cjs.map +1 -1
- package/dist/elysia/index.d.cts +2 -0
- package/dist/elysia/index.d.ts +2 -0
- package/dist/elysia/index.js +2 -0
- package/dist/elysia/index.js.map +1 -1
- package/dist/elysia/plugin.cjs +16 -8
- package/dist/elysia/plugin.cjs.map +1 -1
- package/dist/elysia/plugin.d.cts +4 -0
- package/dist/elysia/plugin.d.ts +4 -0
- package/dist/elysia/plugin.js +16 -8
- package/dist/elysia/plugin.js.map +1 -1
- package/dist/elysia/utils.d.cts +2 -0
- package/dist/elysia/utils.d.ts +2 -0
- package/dist/express/index.cjs +3 -0
- package/dist/express/index.cjs.map +1 -1
- package/dist/express/index.d.cts +2 -0
- package/dist/express/index.d.ts +2 -0
- package/dist/express/index.js +2 -0
- package/dist/express/index.js.map +1 -1
- package/dist/express/middleware.cjs +85 -77
- package/dist/express/middleware.cjs.map +1 -1
- package/dist/express/middleware.d.cts +2 -0
- package/dist/express/middleware.d.ts +2 -0
- package/dist/express/middleware.js +85 -77
- package/dist/express/middleware.js.map +1 -1
- package/dist/fastify/index.cjs +3 -0
- package/dist/fastify/index.cjs.map +1 -1
- package/dist/fastify/index.d.cts +2 -0
- package/dist/fastify/index.d.ts +2 -0
- package/dist/fastify/index.js +2 -0
- package/dist/fastify/index.js.map +1 -1
- package/dist/fastify/plugin.cjs +15 -6
- package/dist/fastify/plugin.cjs.map +1 -1
- package/dist/fastify/plugin.d.cts +4 -0
- package/dist/fastify/plugin.d.ts +4 -0
- package/dist/fastify/plugin.js +15 -6
- package/dist/fastify/plugin.js.map +1 -1
- package/dist/h3/index.cjs +3 -0
- package/dist/h3/index.cjs.map +1 -1
- package/dist/h3/index.d.cts +2 -0
- package/dist/h3/index.d.ts +2 -0
- package/dist/h3/index.js +2 -0
- package/dist/h3/index.js.map +1 -1
- package/dist/h3/plugin.cjs +15 -7
- package/dist/h3/plugin.cjs.map +1 -1
- package/dist/h3/plugin.d.cts +4 -0
- package/dist/h3/plugin.d.ts +4 -0
- package/dist/h3/plugin.js +15 -7
- package/dist/h3/plugin.js.map +1 -1
- package/dist/hapi/index.cjs +3 -0
- package/dist/hapi/index.cjs.map +1 -1
- package/dist/hapi/index.d.cts +2 -0
- package/dist/hapi/index.d.ts +2 -0
- package/dist/hapi/index.js +2 -0
- package/dist/hapi/index.js.map +1 -1
- package/dist/hapi/plugin.cjs +16 -9
- package/dist/hapi/plugin.cjs.map +1 -1
- package/dist/hapi/plugin.d.cts +4 -0
- package/dist/hapi/plugin.d.ts +4 -0
- package/dist/hapi/plugin.js +16 -9
- package/dist/hapi/plugin.js.map +1 -1
- package/dist/hapi/utils.d.cts +2 -0
- package/dist/hapi/utils.d.ts +2 -0
- package/dist/hono/index.cjs +3 -0
- package/dist/hono/index.cjs.map +1 -1
- package/dist/hono/index.d.cts +2 -0
- package/dist/hono/index.d.ts +2 -0
- package/dist/hono/index.js +2 -0
- package/dist/hono/index.js.map +1 -1
- package/dist/hono/middleware.cjs +6 -2
- package/dist/hono/middleware.cjs.map +1 -1
- package/dist/hono/middleware.d.cts +2 -0
- package/dist/hono/middleware.d.ts +2 -0
- package/dist/hono/middleware.js +6 -2
- package/dist/hono/middleware.js.map +1 -1
- package/dist/hono/utils.d.cts +2 -0
- package/dist/hono/utils.d.ts +2 -0
- package/dist/koa/index.cjs +3 -0
- package/dist/koa/index.cjs.map +1 -1
- package/dist/koa/index.d.cts +2 -0
- package/dist/koa/index.d.ts +2 -0
- package/dist/koa/index.js +2 -0
- package/dist/koa/index.js.map +1 -1
- package/dist/koa/middleware.cjs +8 -4
- package/dist/koa/middleware.cjs.map +1 -1
- package/dist/koa/middleware.d.cts +2 -0
- package/dist/koa/middleware.d.ts +2 -0
- package/dist/koa/middleware.js +8 -4
- package/dist/koa/middleware.js.map +1 -1
- package/dist/loggers/console.d.cts +4 -0
- package/dist/loggers/console.d.ts +4 -0
- package/dist/loggers/hapi.d.cts +4 -0
- package/dist/loggers/hapi.d.ts +4 -0
- package/dist/loggers/index.d.cts +4 -0
- package/dist/loggers/index.d.ts +4 -0
- package/dist/loggers/nestjs.d.cts +4 -0
- package/dist/loggers/nestjs.d.ts +4 -0
- package/dist/loggers/pino.cjs +1 -1
- package/dist/loggers/pino.cjs.map +1 -1
- package/dist/loggers/pino.d.cts +4 -0
- package/dist/loggers/pino.d.ts +4 -0
- package/dist/loggers/pino.js +1 -1
- package/dist/loggers/pino.js.map +1 -1
- package/dist/loggers/winston.d.cts +4 -0
- package/dist/loggers/winston.d.ts +4 -0
- package/dist/nestjs/index.cjs +3 -0
- package/dist/nestjs/index.cjs.map +1 -1
- package/dist/nestjs/index.d.cts +2 -0
- package/dist/nestjs/index.d.ts +2 -0
- package/dist/nestjs/index.js +2 -0
- package/dist/nestjs/index.js.map +1 -1
- package/package.json +6 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/common/serverErrorCounter.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\n\nimport { getSentryEventId } from \"./sentry.js\";\nimport { ConsumerMethodPath, ServerError, ServerErrorsItem } from \"./types.js\";\n\nconst MAX_MSG_LENGTH = 2048;\nconst MAX_STACKTRACE_LENGTH = 65536;\n\nexport default class ServerErrorCounter {\n private errorCounts: Map<string, number>;\n private errorDetails: Map<string, ConsumerMethodPath & ServerError>;\n private sentryEventIds: Map<string, string>;\n\n constructor() {\n this.errorCounts = new Map();\n this.errorDetails = new Map();\n this.sentryEventIds = new Map();\n }\n\n public addServerError(serverError: ConsumerMethodPath & ServerError) {\n const key = this.getKey(serverError);\n if (!this.errorDetails.has(key)) {\n this.errorDetails.set(key, serverError);\n }\n this.errorCounts.set(key, (this.errorCounts.get(key) || 0) + 1);\n\n const sentryEventId = getSentryEventId();\n if (sentryEventId) {\n this.sentryEventIds.set(key, sentryEventId);\n }\n }\n\n public getAndResetServerErrors() {\n const data: Array<ServerErrorsItem> = [];\n this.errorCounts.forEach((count, key) => {\n const serverError = this.errorDetails.get(key);\n if (serverError) {\n data.push({\n consumer: serverError.consumer || null,\n method: serverError.method,\n path: serverError.path,\n type: serverError.type,\n msg: truncateExceptionMessage(serverError.msg),\n traceback: truncateExceptionStackTrace(serverError.traceback),\n sentry_event_id: this.sentryEventIds.get(key) || null,\n error_count: count,\n });\n }\n });\n this.errorCounts.clear();\n this.errorDetails.clear();\n this.sentryEventIds.clear();\n return data;\n }\n\n private getKey(serverError: ConsumerMethodPath & ServerError) {\n const hashInput = [\n serverError.consumer || \"\",\n serverError.method.toUpperCase(),\n serverError.path,\n serverError.type,\n serverError.msg.trim(),\n serverError.traceback.trim(),\n ].join(\"|\");\n return createHash(\"md5\").update(hashInput).digest(\"hex\");\n }\n}\n\nexport function truncateExceptionMessage(msg: string) {\n if (msg.length <= MAX_MSG_LENGTH) {\n return msg;\n }\n const suffix = \"... (truncated)\";\n const cutoff = MAX_MSG_LENGTH - suffix.length;\n return msg.substring(0, cutoff) + suffix;\n}\n\nexport function truncateExceptionStackTrace(stack: string) {\n const suffix = \"... (truncated) ...\";\n const cutoff = MAX_STACKTRACE_LENGTH - suffix.length;\n const lines = stack.trim().split(\"\\n\");\n const truncatedLines: string[] = [];\n let length = 0;\n for (const line of lines) {\n if (length + line.length + 1 > cutoff) {\n truncatedLines.push(suffix);\n break;\n }\n truncatedLines.push(line);\n length += line.length + 1;\n }\n return truncatedLines.join(\"\\n\");\n}\n"],"mappings":";;AAAA,SAASA,kBAAkB;AAE3B,SAASC,wBAAwB;AAGjC,MAAMC,iBAAiB;AACvB,MAAMC,wBAAwB;AAE9B,MAAqBC,sBAArB,MAAqBA,oBAAAA;EACXC;EACAC;EACAC;EAER,cAAc;AACZ,SAAKF,cAAc,oBAAIG,IAAAA;AACvB,SAAKF,eAAe,oBAAIE,IAAAA;AACxB,SAAKD,iBAAiB,oBAAIC,IAAAA;EAC5B;EAEOC,eAAeC,aAA+C;AACnE,UAAMC,MAAM,KAAKC,OAAOF,WAAAA;AACxB,QAAI,CAAC,KAAKJ,aAAaO,IAAIF,GAAAA,GAAM;AAC/B,WAAKL,aAAaQ,IAAIH,KAAKD,WAAAA;IAC7B;AACA,SAAKL,YAAYS,IAAIH,MAAM,KAAKN,YAAYU,IAAIJ,GAAAA,KAAQ,KAAK,CAAA;AAE7D,UAAMK,gBAAgBf,iBAAAA;AACtB,QAAIe,eAAe;AACjB,WAAKT,eAAeO,IAAIH,KAAKK,aAAAA;IAC/B;EACF;EAEOC,0BAA0B;AAC/B,UAAMC,OAAgC,CAAA;AACtC,SAAKb,YAAYc,QAAQ,CAACC,OAAOT,QAAAA;AAC/B,YAAMD,cAAc,KAAKJ,aAAaS,IAAIJ,GAAAA;AAC1C,UAAID,aAAa;AACfQ,aAAKG,KAAK;UACRC,UAAUZ,YAAYY,YAAY;UAClCC,QAAQb,YAAYa;UACpBC,MAAMd,YAAYc;UAClBC,MAAMf,YAAYe;UAClBC,KAAKC,yBAAyBjB,YAAYgB,GAAG;UAC7CE,WAAWC,4BAA4BnB,YAAYkB,SAAS;UAC5DE,iBAAiB,KAAKvB,eAAeQ,IAAIJ,GAAAA,KAAQ;UACjDoB,aAAaX;QACf,CAAA;MACF;IACF,CAAA;AACA,SAAKf,YAAY2B,MAAK;AACtB,SAAK1B,aAAa0B,MAAK;AACvB,SAAKzB,eAAeyB,MAAK;AACzB,WAAOd;EACT;EAEQN,OAAOF,aAA+C;AAC5D,UAAMuB,YAAY;MAChBvB,YAAYY,YAAY;MACxBZ,YAAYa,OAAOW,YAAW;MAC9BxB,YAAYc;MACZd,YAAYe;MACZf,YAAYgB,IAAIS,KAAI;MACpBzB,YAAYkB,UAAUO,KAAI;MAC1BC,KAAK,GAAA;AACP,WAAOpC,WAAW,KAAA,EAAOqC,OAAOJ,SAAAA,EAAWK,OAAO,KAAA;EACpD;AACF;AA1DqBlC;AAArB,IAAqBA,qBAArB;AA4DO,SAASuB,yBAAyBD,KAAW;AAClD,MAAIA,IAAIa,UAAUrC,gBAAgB;AAChC,WAAOwB;EACT;AACA,QAAMc,SAAS;AACf,QAAMC,SAASvC,iBAAiBsC,OAAOD;AACvC,SAAOb,IAAIgB,UAAU,GAAGD,MAAAA,IAAUD;AACpC;AAPgBb;AAST,SAASE,4BAA4Bc,OAAa;AACvD,QAAMH,SAAS;AACf,QAAMC,SAAStC,wBAAwBqC,OAAOD;AAC9C,QAAMK,QAAQD,MAAMR,KAAI,EAAGU,MAAM,IAAA;AACjC,QAAMC,iBAA2B,CAAA;AACjC,MAAIP,SAAS;AACb,aAAWQ,QAAQH,OAAO;AACxB,QAAIL,SAASQ,KAAKR,SAAS,IAAIE,QAAQ;AACrCK,qBAAezB,KAAKmB,MAAAA;AACpB;IACF;AACAM,mBAAezB,KAAK0B,IAAAA;AACpBR,cAAUQ,KAAKR,SAAS;EAC1B;AACA,SAAOO,eAAeV,KAAK,IAAA;AAC7B;
|
|
1
|
+
{"version":3,"sources":["../../src/common/serverErrorCounter.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\n\nimport { getSentryEventId } from \"./sentry.js\";\nimport { ConsumerMethodPath, ServerError, ServerErrorsItem } from \"./types.js\";\n\nconst MAX_MSG_LENGTH = 2048;\nconst MAX_STACKTRACE_LENGTH = 65536;\n\nexport default class ServerErrorCounter {\n private errorCounts: Map<string, number>;\n private errorDetails: Map<string, ConsumerMethodPath & ServerError>;\n private sentryEventIds: Map<string, string>;\n\n constructor() {\n this.errorCounts = new Map();\n this.errorDetails = new Map();\n this.sentryEventIds = new Map();\n }\n\n public addServerError(serverError: ConsumerMethodPath & ServerError) {\n const key = this.getKey(serverError);\n if (!this.errorDetails.has(key)) {\n this.errorDetails.set(key, serverError);\n }\n this.errorCounts.set(key, (this.errorCounts.get(key) || 0) + 1);\n\n const sentryEventId = getSentryEventId();\n if (sentryEventId) {\n this.sentryEventIds.set(key, sentryEventId);\n }\n }\n\n public getAndResetServerErrors() {\n const data: Array<ServerErrorsItem> = [];\n this.errorCounts.forEach((count, key) => {\n const serverError = this.errorDetails.get(key);\n if (serverError) {\n data.push({\n consumer: serverError.consumer || null,\n method: serverError.method,\n path: serverError.path,\n type: serverError.type,\n msg: truncateExceptionMessage(serverError.msg),\n traceback: truncateExceptionStackTrace(serverError.traceback),\n sentry_event_id: this.sentryEventIds.get(key) || null,\n error_count: count,\n });\n }\n });\n this.errorCounts.clear();\n this.errorDetails.clear();\n this.sentryEventIds.clear();\n return data;\n }\n\n private getKey(serverError: ConsumerMethodPath & ServerError) {\n const hashInput = [\n serverError.consumer || \"\",\n serverError.method.toUpperCase(),\n serverError.path,\n serverError.type,\n serverError.msg.trim(),\n serverError.traceback.trim(),\n ].join(\"|\");\n return createHash(\"md5\").update(hashInput).digest(\"hex\");\n }\n}\n\nexport function truncateExceptionMessage(msg: string) {\n if (msg.length <= MAX_MSG_LENGTH) {\n return msg;\n }\n const suffix = \"... (truncated)\";\n const cutoff = MAX_MSG_LENGTH - suffix.length;\n return msg.substring(0, cutoff) + suffix;\n}\n\nexport function truncateExceptionStackTrace(stack: string) {\n if (stack.length <= MAX_STACKTRACE_LENGTH) {\n return stack;\n }\n const suffix = \"... (truncated) ...\";\n const cutoff = MAX_STACKTRACE_LENGTH - suffix.length;\n const lines = stack.trim().split(\"\\n\");\n const truncatedLines: string[] = [];\n let length = 0;\n for (const line of lines) {\n if (length + line.length + 1 > cutoff) {\n truncatedLines.push(suffix);\n break;\n }\n truncatedLines.push(line);\n length += line.length + 1;\n }\n return truncatedLines.join(\"\\n\");\n}\n"],"mappings":";;AAAA,SAASA,kBAAkB;AAE3B,SAASC,wBAAwB;AAGjC,MAAMC,iBAAiB;AACvB,MAAMC,wBAAwB;AAE9B,MAAqBC,sBAArB,MAAqBA,oBAAAA;EACXC;EACAC;EACAC;EAER,cAAc;AACZ,SAAKF,cAAc,oBAAIG,IAAAA;AACvB,SAAKF,eAAe,oBAAIE,IAAAA;AACxB,SAAKD,iBAAiB,oBAAIC,IAAAA;EAC5B;EAEOC,eAAeC,aAA+C;AACnE,UAAMC,MAAM,KAAKC,OAAOF,WAAAA;AACxB,QAAI,CAAC,KAAKJ,aAAaO,IAAIF,GAAAA,GAAM;AAC/B,WAAKL,aAAaQ,IAAIH,KAAKD,WAAAA;IAC7B;AACA,SAAKL,YAAYS,IAAIH,MAAM,KAAKN,YAAYU,IAAIJ,GAAAA,KAAQ,KAAK,CAAA;AAE7D,UAAMK,gBAAgBf,iBAAAA;AACtB,QAAIe,eAAe;AACjB,WAAKT,eAAeO,IAAIH,KAAKK,aAAAA;IAC/B;EACF;EAEOC,0BAA0B;AAC/B,UAAMC,OAAgC,CAAA;AACtC,SAAKb,YAAYc,QAAQ,CAACC,OAAOT,QAAAA;AAC/B,YAAMD,cAAc,KAAKJ,aAAaS,IAAIJ,GAAAA;AAC1C,UAAID,aAAa;AACfQ,aAAKG,KAAK;UACRC,UAAUZ,YAAYY,YAAY;UAClCC,QAAQb,YAAYa;UACpBC,MAAMd,YAAYc;UAClBC,MAAMf,YAAYe;UAClBC,KAAKC,yBAAyBjB,YAAYgB,GAAG;UAC7CE,WAAWC,4BAA4BnB,YAAYkB,SAAS;UAC5DE,iBAAiB,KAAKvB,eAAeQ,IAAIJ,GAAAA,KAAQ;UACjDoB,aAAaX;QACf,CAAA;MACF;IACF,CAAA;AACA,SAAKf,YAAY2B,MAAK;AACtB,SAAK1B,aAAa0B,MAAK;AACvB,SAAKzB,eAAeyB,MAAK;AACzB,WAAOd;EACT;EAEQN,OAAOF,aAA+C;AAC5D,UAAMuB,YAAY;MAChBvB,YAAYY,YAAY;MACxBZ,YAAYa,OAAOW,YAAW;MAC9BxB,YAAYc;MACZd,YAAYe;MACZf,YAAYgB,IAAIS,KAAI;MACpBzB,YAAYkB,UAAUO,KAAI;MAC1BC,KAAK,GAAA;AACP,WAAOpC,WAAW,KAAA,EAAOqC,OAAOJ,SAAAA,EAAWK,OAAO,KAAA;EACpD;AACF;AA1DqBlC;AAArB,IAAqBA,qBAArB;AA4DO,SAASuB,yBAAyBD,KAAW;AAClD,MAAIA,IAAIa,UAAUrC,gBAAgB;AAChC,WAAOwB;EACT;AACA,QAAMc,SAAS;AACf,QAAMC,SAASvC,iBAAiBsC,OAAOD;AACvC,SAAOb,IAAIgB,UAAU,GAAGD,MAAAA,IAAUD;AACpC;AAPgBb;AAST,SAASE,4BAA4Bc,OAAa;AACvD,MAAIA,MAAMJ,UAAUpC,uBAAuB;AACzC,WAAOwC;EACT;AACA,QAAMH,SAAS;AACf,QAAMC,SAAStC,wBAAwBqC,OAAOD;AAC9C,QAAMK,QAAQD,MAAMR,KAAI,EAAGU,MAAM,IAAA;AACjC,QAAMC,iBAA2B,CAAA;AACjC,MAAIP,SAAS;AACb,aAAWQ,QAAQH,OAAO;AACxB,QAAIL,SAASQ,KAAKR,SAAS,IAAIE,QAAQ;AACrCK,qBAAezB,KAAKmB,MAAAA;AACpB;IACF;AACAM,mBAAezB,KAAK0B,IAAAA;AACpBR,cAAUQ,KAAKR,SAAS;EAC1B;AACA,SAAOO,eAAeV,KAAK,IAAA;AAC7B;AAlBgBP;","names":["createHash","getSentryEventId","MAX_MSG_LENGTH","MAX_STACKTRACE_LENGTH","ServerErrorCounter","errorCounts","errorDetails","sentryEventIds","Map","addServerError","serverError","key","getKey","has","set","get","sentryEventId","getAndResetServerErrors","data","forEach","count","push","consumer","method","path","type","msg","truncateExceptionMessage","traceback","truncateExceptionStackTrace","sentry_event_id","error_count","clear","hashInput","toUpperCase","trim","join","update","digest","length","suffix","cutoff","substring","stack","lines","split","truncatedLines","line"]}
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
20
|
+
var spanCollector_exports = {};
|
|
21
|
+
__export(spanCollector_exports, {
|
|
22
|
+
ApitallySpanProcessor: () => ApitallySpanProcessor,
|
|
23
|
+
default: () => SpanCollector
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(spanCollector_exports);
|
|
26
|
+
var import_api = require("@opentelemetry/api");
|
|
27
|
+
var import_context_async_hooks = require("@opentelemetry/context-async-hooks");
|
|
28
|
+
var import_sdk_trace_base = require("@opentelemetry/sdk-trace-base");
|
|
29
|
+
var import_client = require("./client.js");
|
|
30
|
+
var _a;
|
|
31
|
+
let AsyncLocalStorageContextManager = (_a = class extends import_context_async_hooks.AsyncLocalStorageContextManager {
|
|
32
|
+
enterWith(ctx) {
|
|
33
|
+
this._asyncLocalStorage.enterWith(ctx);
|
|
34
|
+
}
|
|
35
|
+
}, __name(_a, "AsyncLocalStorageContextManager"), _a);
|
|
36
|
+
const TRACE_MAX_AGE = 5 * 60 * 1e3;
|
|
37
|
+
const _SpanCollector = class _SpanCollector {
|
|
38
|
+
enabled;
|
|
39
|
+
includedSpanIds = /* @__PURE__ */ new Map();
|
|
40
|
+
collectedSpans = /* @__PURE__ */ new Map();
|
|
41
|
+
traceStartTimes = /* @__PURE__ */ new Map();
|
|
42
|
+
maintainIntervalId;
|
|
43
|
+
contextManager;
|
|
44
|
+
tracer;
|
|
45
|
+
logger;
|
|
46
|
+
constructor(enabled, logger) {
|
|
47
|
+
this.enabled = enabled;
|
|
48
|
+
this.logger = logger;
|
|
49
|
+
if (enabled) {
|
|
50
|
+
this.setupTracerProvider();
|
|
51
|
+
this.maintainIntervalId = setInterval(() => {
|
|
52
|
+
this.maintain();
|
|
53
|
+
}, 6e4);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
setupTracerProvider() {
|
|
57
|
+
this.contextManager = new AsyncLocalStorageContextManager();
|
|
58
|
+
import_api.context.setGlobalContextManager(this.contextManager);
|
|
59
|
+
const provider = new import_sdk_trace_base.BasicTracerProvider({
|
|
60
|
+
spanProcessors: [
|
|
61
|
+
this
|
|
62
|
+
]
|
|
63
|
+
});
|
|
64
|
+
import_api.trace.setGlobalTracerProvider(provider);
|
|
65
|
+
this.tracer = import_api.trace.getTracer("apitally");
|
|
66
|
+
}
|
|
67
|
+
startSpan() {
|
|
68
|
+
if (!this.enabled || !this.tracer) {
|
|
69
|
+
return {
|
|
70
|
+
setName: /* @__PURE__ */ __name(() => void 0, "setName"),
|
|
71
|
+
runInContext: /* @__PURE__ */ __name((fn) => {
|
|
72
|
+
return fn();
|
|
73
|
+
}, "runInContext"),
|
|
74
|
+
enterContext: /* @__PURE__ */ __name(() => void 0, "enterContext"),
|
|
75
|
+
end: /* @__PURE__ */ __name(() => void 0, "end")
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
const span = this.tracer.startSpan("root");
|
|
79
|
+
const spanCtx = span.spanContext();
|
|
80
|
+
const traceId = spanCtx.traceId;
|
|
81
|
+
const ctx = import_api.trace.setSpan(import_api.context.active(), span);
|
|
82
|
+
let ended = false;
|
|
83
|
+
this.includedSpanIds.set(traceId, /* @__PURE__ */ new Set([
|
|
84
|
+
spanCtx.spanId
|
|
85
|
+
]));
|
|
86
|
+
this.collectedSpans.set(traceId, []);
|
|
87
|
+
this.traceStartTimes.set(traceId, Date.now());
|
|
88
|
+
return {
|
|
89
|
+
traceId,
|
|
90
|
+
setName: /* @__PURE__ */ __name((name) => {
|
|
91
|
+
span.updateName(name);
|
|
92
|
+
}, "setName"),
|
|
93
|
+
runInContext: /* @__PURE__ */ __name((fn) => {
|
|
94
|
+
return import_api.context.with(ctx, fn);
|
|
95
|
+
}, "runInContext"),
|
|
96
|
+
enterContext: /* @__PURE__ */ __name(() => {
|
|
97
|
+
var _a2;
|
|
98
|
+
(_a2 = this.contextManager) == null ? void 0 : _a2.enterWith(ctx);
|
|
99
|
+
}, "enterContext"),
|
|
100
|
+
end: /* @__PURE__ */ __name(() => {
|
|
101
|
+
if (ended) return;
|
|
102
|
+
span.end();
|
|
103
|
+
ended = true;
|
|
104
|
+
return this.getAndClearSpans(traceId);
|
|
105
|
+
}, "end")
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
getAndClearSpans(traceId) {
|
|
109
|
+
const spans = this.collectedSpans.get(traceId) ?? [];
|
|
110
|
+
this.collectedSpans.delete(traceId);
|
|
111
|
+
this.includedSpanIds.delete(traceId);
|
|
112
|
+
this.traceStartTimes.delete(traceId);
|
|
113
|
+
return spans;
|
|
114
|
+
}
|
|
115
|
+
onStart(span) {
|
|
116
|
+
var _a2;
|
|
117
|
+
if (!this.enabled) return;
|
|
118
|
+
const ctx = span.spanContext();
|
|
119
|
+
const traceId = ctx.traceId;
|
|
120
|
+
const spanId = ctx.spanId;
|
|
121
|
+
const includedSpans = this.includedSpanIds.get(traceId);
|
|
122
|
+
if (!includedSpans) return;
|
|
123
|
+
const parentSpanId = (_a2 = span.parentSpanContext) == null ? void 0 : _a2.spanId;
|
|
124
|
+
if (parentSpanId && includedSpans.has(parentSpanId)) {
|
|
125
|
+
includedSpans.add(spanId);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
onEnd(span) {
|
|
129
|
+
if (!this.enabled) return;
|
|
130
|
+
const ctx = span.spanContext();
|
|
131
|
+
const traceId = ctx.traceId;
|
|
132
|
+
const spanId = ctx.spanId;
|
|
133
|
+
const includedSpans = this.includedSpanIds.get(traceId);
|
|
134
|
+
if (!includedSpans || !includedSpans.has(spanId)) return;
|
|
135
|
+
const spans = this.collectedSpans.get(traceId);
|
|
136
|
+
if (spans) {
|
|
137
|
+
spans.push(this.serializeSpan(span));
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
serializeSpan(span) {
|
|
141
|
+
var _a2;
|
|
142
|
+
const ctx = span.spanContext();
|
|
143
|
+
const data = {
|
|
144
|
+
spanId: ctx.spanId,
|
|
145
|
+
parentSpanId: ((_a2 = span.parentSpanContext) == null ? void 0 : _a2.spanId) || null,
|
|
146
|
+
name: span.name,
|
|
147
|
+
kind: import_api.SpanKind[span.kind] ?? "INTERNAL",
|
|
148
|
+
// HrTime is [seconds, nanoseconds], convert to nanoseconds as string to avoid precision loss
|
|
149
|
+
startTime: (BigInt(span.startTime[0]) * 1000000000n + BigInt(span.startTime[1])).toString(),
|
|
150
|
+
endTime: (BigInt(span.endTime[0]) * 1000000000n + BigInt(span.endTime[1])).toString()
|
|
151
|
+
};
|
|
152
|
+
if (span.status.code !== import_api.SpanStatusCode.UNSET) {
|
|
153
|
+
data.status = import_api.SpanStatusCode[span.status.code];
|
|
154
|
+
}
|
|
155
|
+
if (span.attributes && Object.keys(span.attributes).length > 0) {
|
|
156
|
+
data.attributes = {
|
|
157
|
+
...span.attributes
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
return data;
|
|
161
|
+
}
|
|
162
|
+
maintain() {
|
|
163
|
+
const now = Date.now();
|
|
164
|
+
for (const [traceId, startTime] of this.traceStartTimes) {
|
|
165
|
+
if (now - startTime > TRACE_MAX_AGE) {
|
|
166
|
+
this.collectedSpans.delete(traceId);
|
|
167
|
+
this.includedSpanIds.delete(traceId);
|
|
168
|
+
this.traceStartTimes.delete(traceId);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
async shutdown() {
|
|
173
|
+
this.enabled = false;
|
|
174
|
+
this.includedSpanIds.clear();
|
|
175
|
+
this.collectedSpans.clear();
|
|
176
|
+
this.traceStartTimes.clear();
|
|
177
|
+
if (this.maintainIntervalId) {
|
|
178
|
+
clearInterval(this.maintainIntervalId);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
async forceFlush() {
|
|
182
|
+
}
|
|
183
|
+
};
|
|
184
|
+
__name(_SpanCollector, "SpanCollector");
|
|
185
|
+
let SpanCollector = _SpanCollector;
|
|
186
|
+
const _ApitallySpanProcessor = class _ApitallySpanProcessor {
|
|
187
|
+
getCollector() {
|
|
188
|
+
try {
|
|
189
|
+
return import_client.ApitallyClient.getInstance().spanCollector;
|
|
190
|
+
} catch {
|
|
191
|
+
return void 0;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
onStart(span) {
|
|
195
|
+
var _a2;
|
|
196
|
+
(_a2 = this.getCollector()) == null ? void 0 : _a2.onStart(span);
|
|
197
|
+
}
|
|
198
|
+
onEnd(span) {
|
|
199
|
+
var _a2;
|
|
200
|
+
(_a2 = this.getCollector()) == null ? void 0 : _a2.onEnd(span);
|
|
201
|
+
}
|
|
202
|
+
async shutdown() {
|
|
203
|
+
var _a2;
|
|
204
|
+
(_a2 = this.getCollector()) == null ? void 0 : _a2.shutdown();
|
|
205
|
+
}
|
|
206
|
+
async forceFlush() {
|
|
207
|
+
var _a2;
|
|
208
|
+
(_a2 = this.getCollector()) == null ? void 0 : _a2.forceFlush();
|
|
209
|
+
}
|
|
210
|
+
};
|
|
211
|
+
__name(_ApitallySpanProcessor, "ApitallySpanProcessor");
|
|
212
|
+
let ApitallySpanProcessor = _ApitallySpanProcessor;
|
|
213
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
214
|
+
0 && (module.exports = {
|
|
215
|
+
ApitallySpanProcessor
|
|
216
|
+
});
|
|
217
|
+
//# sourceMappingURL=spanCollector.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/common/spanCollector.ts"],"sourcesContent":["import {\n context,\n type Context,\n SpanKind,\n SpanStatusCode,\n trace,\n type Tracer,\n} from \"@opentelemetry/api\";\nimport { AsyncLocalStorageContextManager as _AsyncLocalStorageContextManager } from \"@opentelemetry/context-async-hooks\";\nimport {\n BasicTracerProvider,\n type ReadableSpan,\n type Span,\n SpanProcessor,\n} from \"@opentelemetry/sdk-trace-base\";\n\nimport { ApitallyClient } from \"./client.js\";\nimport { Logger } from \"./logging.js\";\n\n/**\n * Extends the official AsyncLocalStorageContextManager to add enterWith support\n * for frameworks that need to persist context across hook boundaries (e.g. Elysia).\n */\nclass AsyncLocalStorageContextManager extends _AsyncLocalStorageContextManager {\n enterWith(ctx: Context): void {\n // @ts-expect-error: _asyncLocalStorage is private\n this._asyncLocalStorage.enterWith(ctx);\n }\n}\n\nexport type SpanData = {\n spanId: string;\n parentSpanId: string | null;\n name: string;\n kind: string;\n startTime: string; // bigint as string\n endTime: string; // bigint as string\n status?: string;\n attributes?: Record<string, unknown>;\n};\n\nexport type SpanHandle = {\n traceId?: string;\n setName: (name: string) => void;\n runInContext: <T>(fn: () => T) => T;\n enterContext: () => void;\n end: () => SpanData[] | undefined;\n};\n\nconst TRACE_MAX_AGE = 5 * 60 * 1000; // 5 minutes\n\nexport default class SpanCollector implements SpanProcessor {\n public enabled: boolean;\n private includedSpanIds: Map<string, Set<string>> = new Map();\n private collectedSpans: Map<string, SpanData[]> = new Map();\n private traceStartTimes: Map<string, number> = new Map();\n private maintainIntervalId?: NodeJS.Timeout;\n private contextManager?: AsyncLocalStorageContextManager;\n private tracer?: Tracer;\n private logger?: Logger;\n\n constructor(enabled: boolean, logger?: Logger) {\n this.enabled = enabled;\n this.logger = logger;\n\n if (enabled) {\n this.setupTracerProvider();\n this.maintainIntervalId = setInterval(() => {\n this.maintain();\n }, 60_000);\n }\n }\n\n private setupTracerProvider() {\n this.contextManager = new AsyncLocalStorageContextManager();\n context.setGlobalContextManager(this.contextManager);\n\n const provider = new BasicTracerProvider({\n spanProcessors: [this],\n });\n trace.setGlobalTracerProvider(provider);\n this.tracer = trace.getTracer(\"apitally\");\n }\n\n startSpan(): SpanHandle {\n if (!this.enabled || !this.tracer) {\n return {\n setName: () => void 0,\n runInContext: <T>(fn: () => T): T => {\n return fn();\n },\n enterContext: () => void 0,\n end: () => undefined,\n };\n }\n\n const span = this.tracer.startSpan(\"root\");\n const spanCtx = span.spanContext();\n const traceId = spanCtx.traceId;\n const ctx = trace.setSpan(context.active(), span);\n let ended = false;\n\n this.includedSpanIds.set(traceId, new Set([spanCtx.spanId]));\n this.collectedSpans.set(traceId, []);\n this.traceStartTimes.set(traceId, Date.now());\n\n return {\n traceId,\n setName: (name: string) => {\n span.updateName(name);\n },\n runInContext: <T>(fn: () => T): T => {\n return context.with(ctx, fn);\n },\n enterContext: () => {\n this.contextManager?.enterWith(ctx);\n },\n end: () => {\n if (ended) return;\n span.end();\n ended = true;\n return this.getAndClearSpans(traceId);\n },\n };\n }\n\n private getAndClearSpans(traceId: string): SpanData[] {\n const spans = this.collectedSpans.get(traceId) ?? [];\n this.collectedSpans.delete(traceId);\n this.includedSpanIds.delete(traceId);\n this.traceStartTimes.delete(traceId);\n return spans;\n }\n\n onStart(span: Span): void {\n if (!this.enabled) return;\n\n const ctx = span.spanContext();\n const traceId = ctx.traceId;\n const spanId = ctx.spanId;\n\n const includedSpans = this.includedSpanIds.get(traceId);\n if (!includedSpans) return;\n\n const parentSpanId = span.parentSpanContext?.spanId;\n if (parentSpanId && includedSpans.has(parentSpanId)) {\n includedSpans.add(spanId);\n }\n }\n\n onEnd(span: ReadableSpan): void {\n if (!this.enabled) return;\n\n const ctx = span.spanContext();\n const traceId = ctx.traceId;\n const spanId = ctx.spanId;\n\n const includedSpans = this.includedSpanIds.get(traceId);\n if (!includedSpans || !includedSpans.has(spanId)) return;\n\n const spans = this.collectedSpans.get(traceId);\n if (spans) {\n spans.push(this.serializeSpan(span));\n }\n }\n\n private serializeSpan(span: ReadableSpan): SpanData {\n const ctx = span.spanContext();\n\n const data: SpanData = {\n spanId: ctx.spanId,\n parentSpanId: span.parentSpanContext?.spanId || null,\n name: span.name,\n kind: SpanKind[span.kind] ?? \"INTERNAL\",\n // HrTime is [seconds, nanoseconds], convert to nanoseconds as string to avoid precision loss\n startTime: (\n BigInt(span.startTime[0]) * 1_000_000_000n +\n BigInt(span.startTime[1])\n ).toString(),\n endTime: (\n BigInt(span.endTime[0]) * 1_000_000_000n +\n BigInt(span.endTime[1])\n ).toString(),\n };\n\n if (span.status.code !== SpanStatusCode.UNSET) {\n data.status = SpanStatusCode[span.status.code];\n }\n\n if (span.attributes && Object.keys(span.attributes).length > 0) {\n data.attributes = { ...span.attributes };\n }\n\n return data;\n }\n\n private maintain() {\n const now = Date.now();\n for (const [traceId, startTime] of this.traceStartTimes) {\n if (now - startTime > TRACE_MAX_AGE) {\n this.collectedSpans.delete(traceId);\n this.includedSpanIds.delete(traceId);\n this.traceStartTimes.delete(traceId);\n }\n }\n }\n\n async shutdown(): Promise<void> {\n this.enabled = false;\n this.includedSpanIds.clear();\n this.collectedSpans.clear();\n this.traceStartTimes.clear();\n if (this.maintainIntervalId) {\n clearInterval(this.maintainIntervalId);\n }\n }\n\n async forceFlush(): Promise<void> {\n // Nothing to flush since we collect spans synchronously\n }\n}\n\nexport class ApitallySpanProcessor implements SpanProcessor {\n private getCollector(): SpanCollector | undefined {\n try {\n return ApitallyClient.getInstance().spanCollector;\n } catch {\n return undefined;\n }\n }\n\n onStart(span: Span) {\n this.getCollector()?.onStart(span);\n }\n\n onEnd(span: ReadableSpan) {\n this.getCollector()?.onEnd(span);\n }\n\n async shutdown() {\n this.getCollector()?.shutdown();\n }\n\n async forceFlush() {\n this.getCollector()?.forceFlush();\n }\n}\n"],"mappings":"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","names":["AsyncLocalStorageContextManager","_AsyncLocalStorageContextManager","enterWith","ctx","_asyncLocalStorage","TRACE_MAX_AGE","SpanCollector","enabled","includedSpanIds","Map","collectedSpans","traceStartTimes","maintainIntervalId","contextManager","tracer","logger","setupTracerProvider","setInterval","maintain","context","setGlobalContextManager","provider","BasicTracerProvider","spanProcessors","trace","setGlobalTracerProvider","getTracer","startSpan","setName","runInContext","fn","enterContext","end","undefined","span","spanCtx","spanContext","traceId","setSpan","active","ended","set","Set","spanId","Date","now","name","updateName","with","_a","getAndClearSpans","spans","get","delete","onStart","includedSpans","parentSpanId","parentSpanContext","has","add","onEnd","push","serializeSpan","data","kind","SpanKind","startTime","BigInt","toString","endTime","status","code","SpanStatusCode","UNSET","attributes","Object","keys","length","shutdown","clear","clearInterval","forceFlush","ApitallySpanProcessor","getCollector","ApitallyClient","getInstance","spanCollector"]}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { SpanProcessor, Span, ReadableSpan } from '@opentelemetry/sdk-trace-base';
|
|
2
|
+
import { Logger } from './logging.cjs';
|
|
3
|
+
import 'winston';
|
|
4
|
+
|
|
5
|
+
type SpanData = {
|
|
6
|
+
spanId: string;
|
|
7
|
+
parentSpanId: string | null;
|
|
8
|
+
name: string;
|
|
9
|
+
kind: string;
|
|
10
|
+
startTime: string;
|
|
11
|
+
endTime: string;
|
|
12
|
+
status?: string;
|
|
13
|
+
attributes?: Record<string, unknown>;
|
|
14
|
+
};
|
|
15
|
+
type SpanHandle = {
|
|
16
|
+
traceId?: string;
|
|
17
|
+
setName: (name: string) => void;
|
|
18
|
+
runInContext: <T>(fn: () => T) => T;
|
|
19
|
+
enterContext: () => void;
|
|
20
|
+
end: () => SpanData[] | undefined;
|
|
21
|
+
};
|
|
22
|
+
declare class SpanCollector implements SpanProcessor {
|
|
23
|
+
enabled: boolean;
|
|
24
|
+
private includedSpanIds;
|
|
25
|
+
private collectedSpans;
|
|
26
|
+
private traceStartTimes;
|
|
27
|
+
private maintainIntervalId?;
|
|
28
|
+
private contextManager?;
|
|
29
|
+
private tracer?;
|
|
30
|
+
private logger?;
|
|
31
|
+
constructor(enabled: boolean, logger?: Logger);
|
|
32
|
+
private setupTracerProvider;
|
|
33
|
+
startSpan(): SpanHandle;
|
|
34
|
+
private getAndClearSpans;
|
|
35
|
+
onStart(span: Span): void;
|
|
36
|
+
onEnd(span: ReadableSpan): void;
|
|
37
|
+
private serializeSpan;
|
|
38
|
+
private maintain;
|
|
39
|
+
shutdown(): Promise<void>;
|
|
40
|
+
forceFlush(): Promise<void>;
|
|
41
|
+
}
|
|
42
|
+
declare class ApitallySpanProcessor implements SpanProcessor {
|
|
43
|
+
private getCollector;
|
|
44
|
+
onStart(span: Span): void;
|
|
45
|
+
onEnd(span: ReadableSpan): void;
|
|
46
|
+
shutdown(): Promise<void>;
|
|
47
|
+
forceFlush(): Promise<void>;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export { ApitallySpanProcessor, type SpanData, type SpanHandle, SpanCollector as default };
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { SpanProcessor, Span, ReadableSpan } from '@opentelemetry/sdk-trace-base';
|
|
2
|
+
import { Logger } from './logging.js';
|
|
3
|
+
import 'winston';
|
|
4
|
+
|
|
5
|
+
type SpanData = {
|
|
6
|
+
spanId: string;
|
|
7
|
+
parentSpanId: string | null;
|
|
8
|
+
name: string;
|
|
9
|
+
kind: string;
|
|
10
|
+
startTime: string;
|
|
11
|
+
endTime: string;
|
|
12
|
+
status?: string;
|
|
13
|
+
attributes?: Record<string, unknown>;
|
|
14
|
+
};
|
|
15
|
+
type SpanHandle = {
|
|
16
|
+
traceId?: string;
|
|
17
|
+
setName: (name: string) => void;
|
|
18
|
+
runInContext: <T>(fn: () => T) => T;
|
|
19
|
+
enterContext: () => void;
|
|
20
|
+
end: () => SpanData[] | undefined;
|
|
21
|
+
};
|
|
22
|
+
declare class SpanCollector implements SpanProcessor {
|
|
23
|
+
enabled: boolean;
|
|
24
|
+
private includedSpanIds;
|
|
25
|
+
private collectedSpans;
|
|
26
|
+
private traceStartTimes;
|
|
27
|
+
private maintainIntervalId?;
|
|
28
|
+
private contextManager?;
|
|
29
|
+
private tracer?;
|
|
30
|
+
private logger?;
|
|
31
|
+
constructor(enabled: boolean, logger?: Logger);
|
|
32
|
+
private setupTracerProvider;
|
|
33
|
+
startSpan(): SpanHandle;
|
|
34
|
+
private getAndClearSpans;
|
|
35
|
+
onStart(span: Span): void;
|
|
36
|
+
onEnd(span: ReadableSpan): void;
|
|
37
|
+
private serializeSpan;
|
|
38
|
+
private maintain;
|
|
39
|
+
shutdown(): Promise<void>;
|
|
40
|
+
forceFlush(): Promise<void>;
|
|
41
|
+
}
|
|
42
|
+
declare class ApitallySpanProcessor implements SpanProcessor {
|
|
43
|
+
private getCollector;
|
|
44
|
+
onStart(span: Span): void;
|
|
45
|
+
onEnd(span: ReadableSpan): void;
|
|
46
|
+
shutdown(): Promise<void>;
|
|
47
|
+
forceFlush(): Promise<void>;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export { ApitallySpanProcessor, type SpanData, type SpanHandle, SpanCollector as default };
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
3
|
+
var _a;
|
|
4
|
+
import { context, SpanKind, SpanStatusCode, trace } from "@opentelemetry/api";
|
|
5
|
+
import { AsyncLocalStorageContextManager as _AsyncLocalStorageContextManager } from "@opentelemetry/context-async-hooks";
|
|
6
|
+
import { BasicTracerProvider } from "@opentelemetry/sdk-trace-base";
|
|
7
|
+
import { ApitallyClient } from "./client.js";
|
|
8
|
+
let AsyncLocalStorageContextManager = (_a = class extends _AsyncLocalStorageContextManager {
|
|
9
|
+
enterWith(ctx) {
|
|
10
|
+
this._asyncLocalStorage.enterWith(ctx);
|
|
11
|
+
}
|
|
12
|
+
}, __name(_a, "AsyncLocalStorageContextManager"), _a);
|
|
13
|
+
const TRACE_MAX_AGE = 5 * 60 * 1e3;
|
|
14
|
+
const _SpanCollector = class _SpanCollector {
|
|
15
|
+
enabled;
|
|
16
|
+
includedSpanIds = /* @__PURE__ */ new Map();
|
|
17
|
+
collectedSpans = /* @__PURE__ */ new Map();
|
|
18
|
+
traceStartTimes = /* @__PURE__ */ new Map();
|
|
19
|
+
maintainIntervalId;
|
|
20
|
+
contextManager;
|
|
21
|
+
tracer;
|
|
22
|
+
logger;
|
|
23
|
+
constructor(enabled, logger) {
|
|
24
|
+
this.enabled = enabled;
|
|
25
|
+
this.logger = logger;
|
|
26
|
+
if (enabled) {
|
|
27
|
+
this.setupTracerProvider();
|
|
28
|
+
this.maintainIntervalId = setInterval(() => {
|
|
29
|
+
this.maintain();
|
|
30
|
+
}, 6e4);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
setupTracerProvider() {
|
|
34
|
+
this.contextManager = new AsyncLocalStorageContextManager();
|
|
35
|
+
context.setGlobalContextManager(this.contextManager);
|
|
36
|
+
const provider = new BasicTracerProvider({
|
|
37
|
+
spanProcessors: [
|
|
38
|
+
this
|
|
39
|
+
]
|
|
40
|
+
});
|
|
41
|
+
trace.setGlobalTracerProvider(provider);
|
|
42
|
+
this.tracer = trace.getTracer("apitally");
|
|
43
|
+
}
|
|
44
|
+
startSpan() {
|
|
45
|
+
if (!this.enabled || !this.tracer) {
|
|
46
|
+
return {
|
|
47
|
+
setName: /* @__PURE__ */ __name(() => void 0, "setName"),
|
|
48
|
+
runInContext: /* @__PURE__ */ __name((fn) => {
|
|
49
|
+
return fn();
|
|
50
|
+
}, "runInContext"),
|
|
51
|
+
enterContext: /* @__PURE__ */ __name(() => void 0, "enterContext"),
|
|
52
|
+
end: /* @__PURE__ */ __name(() => void 0, "end")
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
const span = this.tracer.startSpan("root");
|
|
56
|
+
const spanCtx = span.spanContext();
|
|
57
|
+
const traceId = spanCtx.traceId;
|
|
58
|
+
const ctx = trace.setSpan(context.active(), span);
|
|
59
|
+
let ended = false;
|
|
60
|
+
this.includedSpanIds.set(traceId, /* @__PURE__ */ new Set([
|
|
61
|
+
spanCtx.spanId
|
|
62
|
+
]));
|
|
63
|
+
this.collectedSpans.set(traceId, []);
|
|
64
|
+
this.traceStartTimes.set(traceId, Date.now());
|
|
65
|
+
return {
|
|
66
|
+
traceId,
|
|
67
|
+
setName: /* @__PURE__ */ __name((name) => {
|
|
68
|
+
span.updateName(name);
|
|
69
|
+
}, "setName"),
|
|
70
|
+
runInContext: /* @__PURE__ */ __name((fn) => {
|
|
71
|
+
return context.with(ctx, fn);
|
|
72
|
+
}, "runInContext"),
|
|
73
|
+
enterContext: /* @__PURE__ */ __name(() => {
|
|
74
|
+
var _a2;
|
|
75
|
+
(_a2 = this.contextManager) == null ? void 0 : _a2.enterWith(ctx);
|
|
76
|
+
}, "enterContext"),
|
|
77
|
+
end: /* @__PURE__ */ __name(() => {
|
|
78
|
+
if (ended) return;
|
|
79
|
+
span.end();
|
|
80
|
+
ended = true;
|
|
81
|
+
return this.getAndClearSpans(traceId);
|
|
82
|
+
}, "end")
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
getAndClearSpans(traceId) {
|
|
86
|
+
const spans = this.collectedSpans.get(traceId) ?? [];
|
|
87
|
+
this.collectedSpans.delete(traceId);
|
|
88
|
+
this.includedSpanIds.delete(traceId);
|
|
89
|
+
this.traceStartTimes.delete(traceId);
|
|
90
|
+
return spans;
|
|
91
|
+
}
|
|
92
|
+
onStart(span) {
|
|
93
|
+
var _a2;
|
|
94
|
+
if (!this.enabled) return;
|
|
95
|
+
const ctx = span.spanContext();
|
|
96
|
+
const traceId = ctx.traceId;
|
|
97
|
+
const spanId = ctx.spanId;
|
|
98
|
+
const includedSpans = this.includedSpanIds.get(traceId);
|
|
99
|
+
if (!includedSpans) return;
|
|
100
|
+
const parentSpanId = (_a2 = span.parentSpanContext) == null ? void 0 : _a2.spanId;
|
|
101
|
+
if (parentSpanId && includedSpans.has(parentSpanId)) {
|
|
102
|
+
includedSpans.add(spanId);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
onEnd(span) {
|
|
106
|
+
if (!this.enabled) return;
|
|
107
|
+
const ctx = span.spanContext();
|
|
108
|
+
const traceId = ctx.traceId;
|
|
109
|
+
const spanId = ctx.spanId;
|
|
110
|
+
const includedSpans = this.includedSpanIds.get(traceId);
|
|
111
|
+
if (!includedSpans || !includedSpans.has(spanId)) return;
|
|
112
|
+
const spans = this.collectedSpans.get(traceId);
|
|
113
|
+
if (spans) {
|
|
114
|
+
spans.push(this.serializeSpan(span));
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
serializeSpan(span) {
|
|
118
|
+
var _a2;
|
|
119
|
+
const ctx = span.spanContext();
|
|
120
|
+
const data = {
|
|
121
|
+
spanId: ctx.spanId,
|
|
122
|
+
parentSpanId: ((_a2 = span.parentSpanContext) == null ? void 0 : _a2.spanId) || null,
|
|
123
|
+
name: span.name,
|
|
124
|
+
kind: SpanKind[span.kind] ?? "INTERNAL",
|
|
125
|
+
// HrTime is [seconds, nanoseconds], convert to nanoseconds as string to avoid precision loss
|
|
126
|
+
startTime: (BigInt(span.startTime[0]) * 1000000000n + BigInt(span.startTime[1])).toString(),
|
|
127
|
+
endTime: (BigInt(span.endTime[0]) * 1000000000n + BigInt(span.endTime[1])).toString()
|
|
128
|
+
};
|
|
129
|
+
if (span.status.code !== SpanStatusCode.UNSET) {
|
|
130
|
+
data.status = SpanStatusCode[span.status.code];
|
|
131
|
+
}
|
|
132
|
+
if (span.attributes && Object.keys(span.attributes).length > 0) {
|
|
133
|
+
data.attributes = {
|
|
134
|
+
...span.attributes
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
return data;
|
|
138
|
+
}
|
|
139
|
+
maintain() {
|
|
140
|
+
const now = Date.now();
|
|
141
|
+
for (const [traceId, startTime] of this.traceStartTimes) {
|
|
142
|
+
if (now - startTime > TRACE_MAX_AGE) {
|
|
143
|
+
this.collectedSpans.delete(traceId);
|
|
144
|
+
this.includedSpanIds.delete(traceId);
|
|
145
|
+
this.traceStartTimes.delete(traceId);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
async shutdown() {
|
|
150
|
+
this.enabled = false;
|
|
151
|
+
this.includedSpanIds.clear();
|
|
152
|
+
this.collectedSpans.clear();
|
|
153
|
+
this.traceStartTimes.clear();
|
|
154
|
+
if (this.maintainIntervalId) {
|
|
155
|
+
clearInterval(this.maintainIntervalId);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
async forceFlush() {
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
__name(_SpanCollector, "SpanCollector");
|
|
162
|
+
let SpanCollector = _SpanCollector;
|
|
163
|
+
const _ApitallySpanProcessor = class _ApitallySpanProcessor {
|
|
164
|
+
getCollector() {
|
|
165
|
+
try {
|
|
166
|
+
return ApitallyClient.getInstance().spanCollector;
|
|
167
|
+
} catch {
|
|
168
|
+
return void 0;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
onStart(span) {
|
|
172
|
+
var _a2;
|
|
173
|
+
(_a2 = this.getCollector()) == null ? void 0 : _a2.onStart(span);
|
|
174
|
+
}
|
|
175
|
+
onEnd(span) {
|
|
176
|
+
var _a2;
|
|
177
|
+
(_a2 = this.getCollector()) == null ? void 0 : _a2.onEnd(span);
|
|
178
|
+
}
|
|
179
|
+
async shutdown() {
|
|
180
|
+
var _a2;
|
|
181
|
+
(_a2 = this.getCollector()) == null ? void 0 : _a2.shutdown();
|
|
182
|
+
}
|
|
183
|
+
async forceFlush() {
|
|
184
|
+
var _a2;
|
|
185
|
+
(_a2 = this.getCollector()) == null ? void 0 : _a2.forceFlush();
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
__name(_ApitallySpanProcessor, "ApitallySpanProcessor");
|
|
189
|
+
let ApitallySpanProcessor = _ApitallySpanProcessor;
|
|
190
|
+
export {
|
|
191
|
+
ApitallySpanProcessor,
|
|
192
|
+
SpanCollector as default
|
|
193
|
+
};
|
|
194
|
+
//# sourceMappingURL=spanCollector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/common/spanCollector.ts"],"sourcesContent":["import {\n context,\n type Context,\n SpanKind,\n SpanStatusCode,\n trace,\n type Tracer,\n} from \"@opentelemetry/api\";\nimport { AsyncLocalStorageContextManager as _AsyncLocalStorageContextManager } from \"@opentelemetry/context-async-hooks\";\nimport {\n BasicTracerProvider,\n type ReadableSpan,\n type Span,\n SpanProcessor,\n} from \"@opentelemetry/sdk-trace-base\";\n\nimport { ApitallyClient } from \"./client.js\";\nimport { Logger } from \"./logging.js\";\n\n/**\n * Extends the official AsyncLocalStorageContextManager to add enterWith support\n * for frameworks that need to persist context across hook boundaries (e.g. Elysia).\n */\nclass AsyncLocalStorageContextManager extends _AsyncLocalStorageContextManager {\n enterWith(ctx: Context): void {\n // @ts-expect-error: _asyncLocalStorage is private\n this._asyncLocalStorage.enterWith(ctx);\n }\n}\n\nexport type SpanData = {\n spanId: string;\n parentSpanId: string | null;\n name: string;\n kind: string;\n startTime: string; // bigint as string\n endTime: string; // bigint as string\n status?: string;\n attributes?: Record<string, unknown>;\n};\n\nexport type SpanHandle = {\n traceId?: string;\n setName: (name: string) => void;\n runInContext: <T>(fn: () => T) => T;\n enterContext: () => void;\n end: () => SpanData[] | undefined;\n};\n\nconst TRACE_MAX_AGE = 5 * 60 * 1000; // 5 minutes\n\nexport default class SpanCollector implements SpanProcessor {\n public enabled: boolean;\n private includedSpanIds: Map<string, Set<string>> = new Map();\n private collectedSpans: Map<string, SpanData[]> = new Map();\n private traceStartTimes: Map<string, number> = new Map();\n private maintainIntervalId?: NodeJS.Timeout;\n private contextManager?: AsyncLocalStorageContextManager;\n private tracer?: Tracer;\n private logger?: Logger;\n\n constructor(enabled: boolean, logger?: Logger) {\n this.enabled = enabled;\n this.logger = logger;\n\n if (enabled) {\n this.setupTracerProvider();\n this.maintainIntervalId = setInterval(() => {\n this.maintain();\n }, 60_000);\n }\n }\n\n private setupTracerProvider() {\n this.contextManager = new AsyncLocalStorageContextManager();\n context.setGlobalContextManager(this.contextManager);\n\n const provider = new BasicTracerProvider({\n spanProcessors: [this],\n });\n trace.setGlobalTracerProvider(provider);\n this.tracer = trace.getTracer(\"apitally\");\n }\n\n startSpan(): SpanHandle {\n if (!this.enabled || !this.tracer) {\n return {\n setName: () => void 0,\n runInContext: <T>(fn: () => T): T => {\n return fn();\n },\n enterContext: () => void 0,\n end: () => undefined,\n };\n }\n\n const span = this.tracer.startSpan(\"root\");\n const spanCtx = span.spanContext();\n const traceId = spanCtx.traceId;\n const ctx = trace.setSpan(context.active(), span);\n let ended = false;\n\n this.includedSpanIds.set(traceId, new Set([spanCtx.spanId]));\n this.collectedSpans.set(traceId, []);\n this.traceStartTimes.set(traceId, Date.now());\n\n return {\n traceId,\n setName: (name: string) => {\n span.updateName(name);\n },\n runInContext: <T>(fn: () => T): T => {\n return context.with(ctx, fn);\n },\n enterContext: () => {\n this.contextManager?.enterWith(ctx);\n },\n end: () => {\n if (ended) return;\n span.end();\n ended = true;\n return this.getAndClearSpans(traceId);\n },\n };\n }\n\n private getAndClearSpans(traceId: string): SpanData[] {\n const spans = this.collectedSpans.get(traceId) ?? [];\n this.collectedSpans.delete(traceId);\n this.includedSpanIds.delete(traceId);\n this.traceStartTimes.delete(traceId);\n return spans;\n }\n\n onStart(span: Span): void {\n if (!this.enabled) return;\n\n const ctx = span.spanContext();\n const traceId = ctx.traceId;\n const spanId = ctx.spanId;\n\n const includedSpans = this.includedSpanIds.get(traceId);\n if (!includedSpans) return;\n\n const parentSpanId = span.parentSpanContext?.spanId;\n if (parentSpanId && includedSpans.has(parentSpanId)) {\n includedSpans.add(spanId);\n }\n }\n\n onEnd(span: ReadableSpan): void {\n if (!this.enabled) return;\n\n const ctx = span.spanContext();\n const traceId = ctx.traceId;\n const spanId = ctx.spanId;\n\n const includedSpans = this.includedSpanIds.get(traceId);\n if (!includedSpans || !includedSpans.has(spanId)) return;\n\n const spans = this.collectedSpans.get(traceId);\n if (spans) {\n spans.push(this.serializeSpan(span));\n }\n }\n\n private serializeSpan(span: ReadableSpan): SpanData {\n const ctx = span.spanContext();\n\n const data: SpanData = {\n spanId: ctx.spanId,\n parentSpanId: span.parentSpanContext?.spanId || null,\n name: span.name,\n kind: SpanKind[span.kind] ?? \"INTERNAL\",\n // HrTime is [seconds, nanoseconds], convert to nanoseconds as string to avoid precision loss\n startTime: (\n BigInt(span.startTime[0]) * 1_000_000_000n +\n BigInt(span.startTime[1])\n ).toString(),\n endTime: (\n BigInt(span.endTime[0]) * 1_000_000_000n +\n BigInt(span.endTime[1])\n ).toString(),\n };\n\n if (span.status.code !== SpanStatusCode.UNSET) {\n data.status = SpanStatusCode[span.status.code];\n }\n\n if (span.attributes && Object.keys(span.attributes).length > 0) {\n data.attributes = { ...span.attributes };\n }\n\n return data;\n }\n\n private maintain() {\n const now = Date.now();\n for (const [traceId, startTime] of this.traceStartTimes) {\n if (now - startTime > TRACE_MAX_AGE) {\n this.collectedSpans.delete(traceId);\n this.includedSpanIds.delete(traceId);\n this.traceStartTimes.delete(traceId);\n }\n }\n }\n\n async shutdown(): Promise<void> {\n this.enabled = false;\n this.includedSpanIds.clear();\n this.collectedSpans.clear();\n this.traceStartTimes.clear();\n if (this.maintainIntervalId) {\n clearInterval(this.maintainIntervalId);\n }\n }\n\n async forceFlush(): Promise<void> {\n // Nothing to flush since we collect spans synchronously\n }\n}\n\nexport class ApitallySpanProcessor implements SpanProcessor {\n private getCollector(): SpanCollector | undefined {\n try {\n return ApitallyClient.getInstance().spanCollector;\n } catch {\n return undefined;\n }\n }\n\n onStart(span: Span) {\n this.getCollector()?.onStart(span);\n }\n\n onEnd(span: ReadableSpan) {\n this.getCollector()?.onEnd(span);\n }\n\n async shutdown() {\n this.getCollector()?.shutdown();\n }\n\n async forceFlush() {\n this.getCollector()?.forceFlush();\n }\n}\n"],"mappings":"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","names":["context","SpanKind","SpanStatusCode","trace","AsyncLocalStorageContextManager","_AsyncLocalStorageContextManager","BasicTracerProvider","ApitallyClient","enterWith","ctx","_asyncLocalStorage","TRACE_MAX_AGE","SpanCollector","enabled","includedSpanIds","Map","collectedSpans","traceStartTimes","maintainIntervalId","contextManager","tracer","logger","setupTracerProvider","setInterval","maintain","setGlobalContextManager","provider","spanProcessors","setGlobalTracerProvider","getTracer","startSpan","setName","runInContext","fn","enterContext","end","undefined","span","spanCtx","spanContext","traceId","setSpan","active","ended","set","Set","spanId","Date","now","name","updateName","with","_a","getAndClearSpans","spans","get","delete","onStart","includedSpans","parentSpanId","parentSpanContext","has","add","onEnd","push","serializeSpan","data","kind","startTime","BigInt","toString","endTime","status","code","UNSET","attributes","Object","keys","length","shutdown","clear","clearInterval","forceFlush","ApitallySpanProcessor","getCollector","getInstance","spanCollector"]}
|
|
@@ -19,6 +19,7 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
19
19
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
20
20
|
var tempGzipFile_exports = {};
|
|
21
21
|
__export(tempGzipFile_exports, {
|
|
22
|
+
checkWritableFs: () => checkWritableFs,
|
|
22
23
|
default: () => TempGzipFile
|
|
23
24
|
});
|
|
24
25
|
module.exports = __toCommonJS(tempGzipFile_exports);
|
|
@@ -29,6 +30,21 @@ var import_promises = require("node:fs/promises");
|
|
|
29
30
|
var import_node_os = require("node:os");
|
|
30
31
|
var import_node_path = require("node:path");
|
|
31
32
|
var import_node_zlib = require("node:zlib");
|
|
33
|
+
const TEMP_DIR = (0, import_node_path.join)((0, import_node_os.tmpdir)(), "apitally");
|
|
34
|
+
function checkWritableFs() {
|
|
35
|
+
try {
|
|
36
|
+
(0, import_node_fs.mkdirSync)(TEMP_DIR, {
|
|
37
|
+
recursive: true
|
|
38
|
+
});
|
|
39
|
+
const testPath = (0, import_node_path.join)(TEMP_DIR, `test_${(0, import_node_crypto.randomUUID)()}`);
|
|
40
|
+
(0, import_node_fs.writeFileSync)(testPath, "test");
|
|
41
|
+
(0, import_node_fs.unlinkSync)(testPath);
|
|
42
|
+
return true;
|
|
43
|
+
} catch (error) {
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
__name(checkWritableFs, "checkWritableFs");
|
|
32
48
|
const _TempGzipFile = class _TempGzipFile {
|
|
33
49
|
uuid;
|
|
34
50
|
filePath;
|
|
@@ -36,9 +52,12 @@ const _TempGzipFile = class _TempGzipFile {
|
|
|
36
52
|
writeStream;
|
|
37
53
|
readyPromise;
|
|
38
54
|
closedPromise;
|
|
39
|
-
constructor() {
|
|
55
|
+
constructor(name) {
|
|
56
|
+
(0, import_node_fs.mkdirSync)(TEMP_DIR, {
|
|
57
|
+
recursive: true
|
|
58
|
+
});
|
|
40
59
|
this.uuid = (0, import_node_crypto.randomUUID)();
|
|
41
|
-
this.filePath = (0, import_node_path.join)(
|
|
60
|
+
this.filePath = (0, import_node_path.join)(TEMP_DIR, `${name}_${this.uuid}.gz`);
|
|
42
61
|
this.writeStream = (0, import_node_fs.createWriteStream)(this.filePath);
|
|
43
62
|
this.readyPromise = new Promise((resolve, reject) => {
|
|
44
63
|
this.writeStream.once("ready", resolve);
|
|
@@ -95,4 +114,8 @@ const _TempGzipFile = class _TempGzipFile {
|
|
|
95
114
|
};
|
|
96
115
|
__name(_TempGzipFile, "TempGzipFile");
|
|
97
116
|
let TempGzipFile = _TempGzipFile;
|
|
117
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
118
|
+
0 && (module.exports = {
|
|
119
|
+
checkWritableFs
|
|
120
|
+
});
|
|
98
121
|
//# sourceMappingURL=tempGzipFile.cjs.map
|