apitally 0.16.2 → 0.17.1

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 (72) hide show
  1. package/dist/adonisjs/middleware.cjs +1 -1
  2. package/dist/adonisjs/middleware.cjs.map +1 -1
  3. package/dist/adonisjs/middleware.js +1 -1
  4. package/dist/adonisjs/middleware.js.map +1 -1
  5. package/dist/adonisjs/provider.cjs +6 -3
  6. package/dist/adonisjs/provider.cjs.map +1 -1
  7. package/dist/adonisjs/provider.js +6 -3
  8. package/dist/adonisjs/provider.js.map +1 -1
  9. package/dist/common/client.cjs +6 -3
  10. package/dist/common/client.cjs.map +1 -1
  11. package/dist/common/client.d.cts +1 -1
  12. package/dist/common/client.d.ts +1 -1
  13. package/dist/common/client.js +6 -3
  14. package/dist/common/client.js.map +1 -1
  15. package/dist/common/types.cjs.map +1 -1
  16. package/dist/common/types.d.cts +3 -1
  17. package/dist/common/types.d.ts +3 -1
  18. package/dist/express/index.cjs +7 -4
  19. package/dist/express/index.cjs.map +1 -1
  20. package/dist/express/index.js +7 -4
  21. package/dist/express/index.js.map +1 -1
  22. package/dist/express/middleware.cjs +7 -4
  23. package/dist/express/middleware.cjs.map +1 -1
  24. package/dist/express/middleware.js +7 -4
  25. package/dist/express/middleware.js.map +1 -1
  26. package/dist/fastify/index.cjs +6 -3
  27. package/dist/fastify/index.cjs.map +1 -1
  28. package/dist/fastify/index.js +6 -3
  29. package/dist/fastify/index.js.map +1 -1
  30. package/dist/fastify/plugin.cjs +6 -3
  31. package/dist/fastify/plugin.cjs.map +1 -1
  32. package/dist/fastify/plugin.js +6 -3
  33. package/dist/fastify/plugin.js.map +1 -1
  34. package/dist/h3/index.cjs +14 -37
  35. package/dist/h3/index.cjs.map +1 -1
  36. package/dist/h3/index.js +14 -37
  37. package/dist/h3/index.js.map +1 -1
  38. package/dist/h3/plugin.cjs +14 -37
  39. package/dist/h3/plugin.cjs.map +1 -1
  40. package/dist/h3/plugin.js +14 -37
  41. package/dist/h3/plugin.js.map +1 -1
  42. package/dist/h3/utils.cjs +5 -34
  43. package/dist/h3/utils.cjs.map +1 -1
  44. package/dist/h3/utils.d.cts +2 -2
  45. package/dist/h3/utils.d.ts +2 -2
  46. package/dist/h3/utils.js +5 -34
  47. package/dist/h3/utils.js.map +1 -1
  48. package/dist/hono/index.cjs +12 -5
  49. package/dist/hono/index.cjs.map +1 -1
  50. package/dist/hono/index.js +12 -5
  51. package/dist/hono/index.js.map +1 -1
  52. package/dist/hono/middleware.cjs +12 -5
  53. package/dist/hono/middleware.cjs.map +1 -1
  54. package/dist/hono/middleware.js +12 -5
  55. package/dist/hono/middleware.js.map +1 -1
  56. package/dist/hono/utils.cjs +5 -1
  57. package/dist/hono/utils.cjs.map +1 -1
  58. package/dist/hono/utils.js +5 -1
  59. package/dist/hono/utils.js.map +1 -1
  60. package/dist/koa/index.cjs +7 -4
  61. package/dist/koa/index.cjs.map +1 -1
  62. package/dist/koa/index.js +7 -4
  63. package/dist/koa/index.js.map +1 -1
  64. package/dist/koa/middleware.cjs +7 -4
  65. package/dist/koa/middleware.cjs.map +1 -1
  66. package/dist/koa/middleware.js +7 -4
  67. package/dist/koa/middleware.js.map +1 -1
  68. package/dist/nestjs/index.cjs +7 -4
  69. package/dist/nestjs/index.cjs.map +1 -1
  70. package/dist/nestjs/index.js +7 -4
  71. package/dist/nestjs/index.js.map +1 -1
  72. package/package.json +38 -38
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/h3/plugin.ts","../../src/common/client.ts","../../src/common/consumerRegistry.ts","../../src/common/logging.ts","../../src/common/paramValidation.ts","../../src/common/requestCounter.ts","../../src/common/requestLogger.ts","../../src/common/sentry.ts","../../src/common/serverErrorCounter.ts","../../src/common/tempGzipFile.ts","../../src/common/validationErrorCounter.ts","../../src/common/headers.ts","../../src/common/response.ts","../../src/common/packageVersions.ts","../../src/h3/utils.ts"],"sourcesContent":["import type { H3Event, HTTPError } from \"h3\";\nimport { definePlugin, onError, onRequest, onResponse } from \"h3\";\nimport { performance } from \"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 { convertHeaders } from \"../common/requestLogger.js\";\nimport { getResponseBody, measureResponseSize } from \"../common/response.js\";\nimport { ApitallyConfig, ApitallyConsumer } from \"../common/types.js\";\nimport { getAppInfo } from \"./utils.js\";\n\ndeclare module \"h3\" {\n interface H3EventContext {\n apitallyConsumer?: ApitallyConsumer | string;\n\n _apitallyRequestTimestamp?: number;\n _apitallyRequestBody?: 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\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 } else {\n setTimeout(() => setStartupData(attempt + 1), 500);\n }\n };\n setTimeout(() => setStartupData(), 500);\n\n const handleResponse = async (\n event: H3Event,\n response?: Response,\n error?: HTTPError,\n ) => {\n const startTime = event.context._apitallyRequestTimestamp;\n const responseTime = startTime ? performance.now() - startTime : 0;\n const path = event.context.matchedRoute?.route;\n const statusCode = response?.status || error?.status || 500;\n\n const requestSize = parseContentLength(\n event.req.headers.get(\"content-length\"),\n );\n let responseSize = 0;\n let newResponse = response;\n if (response) {\n [responseSize, newResponse] = await measureResponseSize(response);\n }\n\n const consumer = getConsumer(event);\n client.consumerRegistry.addOrUpdateConsumer(consumer);\n\n if (path) {\n client.requestCounter.addRequest({\n consumer: consumer?.identifier,\n method: event.req.method,\n path,\n statusCode,\n responseTime,\n requestSize,\n responseSize,\n });\n\n if (error?.status === 400 && (error.data as any).name === \"ZodError\") {\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 (error?.status === 500) {\n client.serverErrorCounter.addServerError({\n consumer: consumer?.identifier,\n method: event.req.method,\n path,\n type: error.name,\n msg: error.message,\n traceback: error.stack || \"\",\n });\n }\n }\n\n if (client.requestLogger.enabled) {\n const responseHeaders = response\n ? response.headers\n : error?.headers\n ? mergeHeaders(jsonHeaders, error.headers)\n : jsonHeaders;\n const responseContentType = responseHeaders.get(\"content-type\");\n let responseBody;\n\n if (\n newResponse &&\n client.requestLogger.config.logResponseBody &&\n client.requestLogger.isSupportedContentType(responseContentType)\n ) {\n [responseBody, newResponse] = await getResponseBody(newResponse);\n } else if (error && client.requestLogger.config.logResponseBody) {\n responseBody = Buffer.from(JSON.stringify(error.toJSON()));\n }\n\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: Number(requestSize),\n consumer: consumer?.identifier,\n body: event.context._apitallyRequestBody,\n },\n {\n statusCode,\n responseTime: responseTime / 1000,\n headers: convertHeaders(\n Object.fromEntries(responseHeaders.entries()),\n ),\n size: responseSize,\n body: responseBody,\n },\n );\n }\n\n return newResponse;\n };\n\n app\n .use(\n onRequest(async (event) => {\n event.context._apitallyRequestTimestamp = 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._apitallyRequestBody = 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 return 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","import { randomUUID } from \"crypto\";\nimport fetchRetry from \"fetch-retry\";\n\nimport ConsumerRegistry from \"./consumerRegistry.js\";\nimport { Logger, getLogger } from \"./logging.js\";\nimport { isValidClientId, isValidEnv } from \"./paramValidation.js\";\nimport RequestCounter from \"./requestCounter.js\";\nimport RequestLogger from \"./requestLogger.js\";\nimport ServerErrorCounter from \"./serverErrorCounter.js\";\nimport {\n ApitallyConfig,\n StartupData,\n StartupPayload,\n SyncPayload,\n} from \"./types.js\";\nimport ValidationErrorCounter from \"./validationErrorCounter.js\";\n\nconst SYNC_INTERVAL = 60000; // 60 seconds\nconst INITIAL_SYNC_INTERVAL = 10000; // 10 seconds\nconst INITIAL_SYNC_INTERVAL_DURATION = 3600000; // 1 hour\nconst MAX_QUEUE_TIME = 3.6e6; // 1 hour\n\nclass HTTPError extends Error {\n public response: Response;\n\n constructor(response: Response) {\n const reason = response.status\n ? `status code ${response.status}`\n : \"an unknown error\";\n super(`Request failed with ${reason}`);\n this.response = response;\n }\n}\n\nexport class ApitallyClient {\n private clientId: string;\n private env: string;\n\n private static instance?: ApitallyClient;\n private instanceUuid: string;\n private syncDataQueue: SyncPayload[];\n private syncIntervalId?: NodeJS.Timeout;\n public startupData?: StartupData;\n private startupDataSent: boolean = false;\n private enabled: boolean = true;\n\n public requestCounter: RequestCounter;\n public requestLogger: RequestLogger;\n public validationErrorCounter: ValidationErrorCounter;\n public serverErrorCounter: ServerErrorCounter;\n public consumerRegistry: ConsumerRegistry;\n public logger: Logger;\n\n constructor({\n clientId,\n env = \"dev\",\n requestLoggingConfig,\n logger,\n }: ApitallyConfig) {\n if (ApitallyClient.instance) {\n throw new Error(\"Apitally client is already initialized\");\n }\n if (!isValidClientId(clientId)) {\n throw new Error(\n `Invalid Apitally client ID '${clientId}' (expecting hexadecimal UUID format)`,\n );\n }\n if (!isValidEnv(env)) {\n throw new Error(\n `Invalid env '${env}' (expecting 1-32 alphanumeric lowercase characters and hyphens only)`,\n );\n }\n\n ApitallyClient.instance = this;\n this.clientId = clientId;\n this.env = env;\n this.instanceUuid = randomUUID();\n this.syncDataQueue = [];\n this.requestCounter = new RequestCounter();\n this.requestLogger = new RequestLogger(requestLoggingConfig);\n this.validationErrorCounter = new ValidationErrorCounter();\n this.serverErrorCounter = new ServerErrorCounter();\n this.consumerRegistry = new ConsumerRegistry();\n this.logger = logger || getLogger();\n\n this.startSync();\n this.handleShutdown = this.handleShutdown.bind(this);\n }\n\n public static getInstance() {\n if (!ApitallyClient.instance) {\n throw new Error(\"Apitally client is not initialized\");\n }\n return ApitallyClient.instance;\n }\n\n public isEnabled() {\n return this.enabled;\n }\n\n public static async shutdown() {\n if (ApitallyClient.instance) {\n await ApitallyClient.instance.handleShutdown();\n }\n }\n\n public async handleShutdown() {\n this.enabled = false;\n this.stopSync();\n await this.sendSyncData();\n await this.sendLogData();\n await this.requestLogger.close();\n ApitallyClient.instance = undefined;\n }\n\n private getHubUrlPrefix() {\n const baseURL =\n process.env.APITALLY_HUB_BASE_URL || \"https://hub.apitally.io\";\n const version = \"v2\";\n return `${baseURL}/${version}/${this.clientId}/${this.env}/`;\n }\n\n private async sendData(url: string, payload: any) {\n const fetchWithRetry = fetchRetry(fetch, {\n retries: 3,\n retryDelay: 1000,\n retryOn: [408, 429, 500, 502, 503, 504],\n });\n const response = await fetchWithRetry(this.getHubUrlPrefix() + url, {\n method: \"POST\",\n body: JSON.stringify(payload),\n headers: { \"Content-Type\": \"application/json\" },\n });\n if (!response.ok) {\n throw new HTTPError(response);\n }\n }\n\n private startSync() {\n this.sync();\n this.syncIntervalId = setInterval(() => {\n this.sync();\n }, INITIAL_SYNC_INTERVAL);\n setTimeout(() => {\n clearInterval(this.syncIntervalId);\n this.syncIntervalId = setInterval(() => {\n this.sync();\n }, SYNC_INTERVAL);\n }, INITIAL_SYNC_INTERVAL_DURATION);\n }\n\n private async sync() {\n try {\n const promises = [this.sendSyncData(), this.sendLogData()];\n if (!this.startupDataSent) {\n promises.push(this.sendStartupData());\n }\n await Promise.all(promises);\n } catch (error) {\n this.logger.error(\"Error while syncing with Apitally Hub\", {\n error,\n });\n }\n }\n\n private stopSync() {\n if (this.syncIntervalId) {\n clearInterval(this.syncIntervalId);\n this.syncIntervalId = undefined;\n }\n }\n\n public setStartupData(data: StartupData) {\n this.startupData = data;\n this.startupDataSent = false;\n this.sendStartupData();\n }\n\n private async sendStartupData() {\n if (this.startupData) {\n this.logger.debug(\"Sending startup data to Apitally Hub\");\n const payload: StartupPayload = {\n instance_uuid: this.instanceUuid,\n message_uuid: randomUUID(),\n ...this.startupData,\n };\n try {\n await this.sendData(\"startup\", payload);\n this.startupDataSent = true;\n } catch (error) {\n const handled = this.handleHubError(error);\n if (!handled) {\n this.logger.error((error as Error).message);\n this.logger.debug(\n \"Error while sending startup data to Apitally Hub (will retry)\",\n { error },\n );\n }\n }\n }\n }\n\n private async sendSyncData() {\n this.logger.debug(\"Synchronizing data with Apitally Hub\");\n const newPayload: SyncPayload = {\n timestamp: Date.now() / 1000,\n instance_uuid: this.instanceUuid,\n message_uuid: randomUUID(),\n requests: this.requestCounter.getAndResetRequests(),\n validation_errors:\n this.validationErrorCounter.getAndResetValidationErrors(),\n server_errors: this.serverErrorCounter.getAndResetServerErrors(),\n consumers: this.consumerRegistry.getAndResetUpdatedConsumers(),\n };\n this.syncDataQueue.push(newPayload);\n\n let i = 0;\n while (this.syncDataQueue.length > 0) {\n const payload = this.syncDataQueue.shift();\n if (payload) {\n try {\n if (Date.now() - payload.timestamp * 1000 <= MAX_QUEUE_TIME) {\n if (i > 0) {\n await this.randomDelay();\n }\n await this.sendData(\"sync\", payload);\n i += 1;\n }\n } catch (error) {\n const handled = this.handleHubError(error);\n if (!handled) {\n this.logger.debug(\n \"Error while synchronizing data with Apitally Hub (will retry)\",\n { error },\n );\n this.syncDataQueue.push(payload);\n break;\n }\n }\n }\n }\n }\n\n private async sendLogData() {\n this.logger.debug(\"Sending request log data to Apitally Hub\");\n await this.requestLogger.rotateFile();\n\n const fetchWithRetry = fetchRetry(fetch, {\n retries: 3,\n retryDelay: 1000,\n retryOn: [408, 429, 500, 502, 503, 504],\n });\n\n let i = 0;\n let logFile;\n while ((logFile = this.requestLogger.getFile())) {\n if (i > 0) {\n await this.randomDelay();\n }\n\n try {\n const response = await fetchWithRetry(\n `${this.getHubUrlPrefix()}log?uuid=${logFile.uuid}`,\n {\n method: \"POST\",\n body: await logFile.getContent(),\n },\n );\n\n if (response.status === 402 && response.headers.has(\"Retry-After\")) {\n const retryAfter = parseInt(\n response.headers.get(\"Retry-After\") ?? \"0\",\n );\n if (retryAfter > 0) {\n this.requestLogger.suspendUntil = Date.now() + retryAfter * 1000;\n this.requestLogger.clear();\n return;\n }\n }\n\n if (!response.ok) {\n throw new HTTPError(response);\n }\n\n logFile.delete();\n } catch (error) {\n this.requestLogger.retryFileLater(logFile);\n break;\n }\n\n i++;\n if (i >= 10) break;\n }\n }\n\n private handleHubError(error: unknown) {\n if (error instanceof HTTPError) {\n if (error.response.status === 404) {\n this.logger.error(`Invalid Apitally client ID: '${this.clientId}'`);\n this.enabled = false;\n this.stopSync();\n return true;\n }\n if (error.response.status === 422) {\n this.logger.error(\"Received validation error from Apitally Hub\");\n return true;\n }\n }\n return false;\n }\n\n private async randomDelay() {\n const delay = 100 + Math.random() * 400;\n await new Promise((resolve) => setTimeout(resolve, delay));\n }\n}\n","import { ApitallyConsumer } from \"./types.js\";\n\nexport const consumerFromStringOrObject = (\n consumer: ApitallyConsumer | string,\n) => {\n if (typeof consumer === \"string\") {\n consumer = String(consumer).trim().substring(0, 128);\n return consumer ? { identifier: consumer } : null;\n } else {\n consumer.identifier = String(consumer.identifier).trim().substring(0, 128);\n consumer.name = consumer.name?.trim().substring(0, 64);\n consumer.group = consumer.group?.trim().substring(0, 64);\n return consumer.identifier ? consumer : null;\n }\n};\n\nexport default class ConsumerRegistry {\n private consumers: Map<string, ApitallyConsumer>;\n private updated: Set<string>;\n\n constructor() {\n this.consumers = new Map();\n this.updated = new Set();\n }\n\n public addOrUpdateConsumer(consumer?: ApitallyConsumer | null) {\n if (!consumer || (!consumer.name && !consumer.group)) {\n return;\n }\n const existing = this.consumers.get(consumer.identifier);\n if (!existing) {\n this.consumers.set(consumer.identifier, consumer);\n this.updated.add(consumer.identifier);\n } else {\n if (consumer.name && consumer.name !== existing.name) {\n existing.name = consumer.name;\n this.updated.add(consumer.identifier);\n }\n if (consumer.group && consumer.group !== existing.group) {\n existing.group = consumer.group;\n this.updated.add(consumer.identifier);\n }\n }\n }\n\n public getAndResetUpdatedConsumers() {\n const data: Array<ApitallyConsumer> = [];\n this.updated.forEach((identifier) => {\n const consumer = this.consumers.get(identifier);\n if (consumer) {\n data.push(consumer);\n }\n });\n this.updated.clear();\n return data;\n }\n}\n","import { createLogger, format, transports } from \"winston\";\n\nexport interface Logger {\n debug: (message: string, meta?: object) => void;\n info: (message: string, meta?: object) => void;\n warn: (message: string, meta?: object) => void;\n error: (message: string, meta?: object) => void;\n}\n\nexport const getLogger = () => {\n return createLogger({\n level: process.env.APITALLY_DEBUG ? \"debug\" : \"warn\",\n format: format.combine(\n format.colorize(),\n format.timestamp(),\n format.printf(\n (info) => `${info.timestamp} ${info.level}: ${info.message}`,\n ),\n ),\n transports: [new transports.Console()],\n });\n};\n","export function isValidClientId(clientId: string): boolean {\n const regexExp =\n /^[0-9a-f]{8}-[0-9a-f]{4}-[4][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;\n return regexExp.test(clientId);\n}\n\nexport function isValidEnv(env: string): boolean {\n const regexExp = /^[\\w-]{1,32}$/;\n return regexExp.test(env);\n}\n","import { RequestInfo, RequestsItem } from \"./types.js\";\n\nexport default class RequestCounter {\n private requestCounts: Map<string, number>;\n private requestSizeSums: Map<string, number>;\n private responseSizeSums: Map<string, number>;\n private responseTimes: Map<string, Map<number, number>>;\n private requestSizes: Map<string, Map<number, number>>;\n private responseSizes: Map<string, Map<number, number>>;\n\n constructor() {\n this.requestCounts = new Map<string, number>();\n this.requestSizeSums = new Map<string, number>();\n this.responseSizeSums = new Map<string, number>();\n this.responseTimes = new Map<string, Map<number, number>>();\n this.requestSizes = new Map<string, Map<number, number>>();\n this.responseSizes = new Map<string, Map<number, number>>();\n }\n\n private getKey(requestInfo: RequestInfo) {\n return [\n requestInfo.consumer || \"\",\n requestInfo.method.toUpperCase(),\n requestInfo.path,\n requestInfo.statusCode,\n ].join(\"|\");\n }\n\n addRequest(requestInfo: RequestInfo) {\n const key = this.getKey(requestInfo);\n\n // Increment request count\n this.requestCounts.set(key, (this.requestCounts.get(key) || 0) + 1);\n\n // Add response time\n if (!this.responseTimes.has(key)) {\n this.responseTimes.set(key, new Map<number, number>());\n }\n const responseTimeMap = this.responseTimes.get(key)!;\n const responseTimeMsBin = Math.floor(requestInfo.responseTime / 10) * 10; // Rounded to nearest 10ms\n responseTimeMap.set(\n responseTimeMsBin,\n (responseTimeMap.get(responseTimeMsBin) || 0) + 1,\n );\n\n // Add request size\n if (requestInfo.requestSize !== undefined) {\n requestInfo.requestSize = Number(requestInfo.requestSize);\n this.requestSizeSums.set(\n key,\n (this.requestSizeSums.get(key) || 0) + requestInfo.requestSize,\n );\n if (!this.requestSizes.has(key)) {\n this.requestSizes.set(key, new Map<number, number>());\n }\n const requestSizeMap = this.requestSizes.get(key)!;\n const requestSizeKbBin = Math.floor(requestInfo.requestSize / 1000); // Rounded down to nearest KB\n requestSizeMap.set(\n requestSizeKbBin,\n (requestSizeMap.get(requestSizeKbBin) || 0) + 1,\n );\n }\n\n // Add response size\n if (requestInfo.responseSize !== undefined) {\n requestInfo.responseSize = Number(requestInfo.responseSize);\n this.responseSizeSums.set(\n key,\n (this.responseSizeSums.get(key) || 0) + requestInfo.responseSize,\n );\n if (!this.responseSizes.has(key)) {\n this.responseSizes.set(key, new Map<number, number>());\n }\n const responseSizeMap = this.responseSizes.get(key)!;\n const responseSizeKbBin = Math.floor(requestInfo.responseSize / 1000); // Rounded down to nearest KB\n responseSizeMap.set(\n responseSizeKbBin,\n (responseSizeMap.get(responseSizeKbBin) || 0) + 1,\n );\n }\n }\n\n getAndResetRequests() {\n const data: Array<RequestsItem> = [];\n this.requestCounts.forEach((count, key) => {\n const [consumer, method, path, statusCodeStr] = key.split(\"|\");\n const responseTimes =\n this.responseTimes.get(key) || new Map<number, number>();\n const requestSizes =\n this.requestSizes.get(key) || new Map<number, number>();\n const responseSizes =\n this.responseSizes.get(key) || new Map<number, number>();\n data.push({\n consumer: consumer || null,\n method,\n path,\n status_code: parseInt(statusCodeStr),\n request_count: count,\n request_size_sum: this.requestSizeSums.get(key) || 0,\n response_size_sum: this.responseSizeSums.get(key) || 0,\n response_times: Object.fromEntries(responseTimes),\n request_sizes: Object.fromEntries(requestSizes),\n response_sizes: Object.fromEntries(responseSizes),\n });\n });\n\n // Reset the counts and times\n this.requestCounts.clear();\n this.requestSizeSums.clear();\n this.responseSizeSums.clear();\n this.responseTimes.clear();\n this.requestSizes.clear();\n this.responseSizes.clear();\n\n return data;\n }\n}\n","import AsyncLock from \"async-lock\";\nimport { Buffer } from \"buffer\";\nimport { randomUUID } from \"crypto\";\nimport { unlinkSync, writeFileSync } from \"fs\";\nimport { IncomingHttpHeaders, OutgoingHttpHeaders } from \"http\";\nimport { tmpdir } from \"os\";\nimport { join } from \"path\";\n\nimport { getSentryEventId } from \"./sentry.js\";\nimport {\n truncateExceptionMessage,\n truncateExceptionStackTrace,\n} from \"./serverErrorCounter.js\";\nimport TempGzipFile from \"./tempGzipFile.js\";\n\nconst MAX_BODY_SIZE = 50_000; // 50 KB (uncompressed)\nconst MAX_FILE_SIZE = 1_000_000; // 1 MB (compressed)\nconst MAX_FILES = 50;\nconst MAX_PENDING_WRITES = 100;\nconst BODY_TOO_LARGE = Buffer.from(\"<body too large>\");\nconst BODY_MASKED = Buffer.from(\"<masked>\");\nconst MASKED = \"******\";\nconst ALLOWED_CONTENT_TYPES = [\n \"application/json\",\n \"application/problem+json\",\n \"application/vnd.api+json\",\n \"text/plain\",\n];\nconst EXCLUDE_PATH_PATTERNS = [\n /\\/_?healthz?$/i,\n /\\/_?health[_-]?checks?$/i,\n /\\/_?heart[_-]?beats?$/i,\n /\\/ping$/i,\n /\\/ready$/i,\n /\\/live$/i,\n];\nconst EXCLUDE_USER_AGENT_PATTERNS = [\n /health[-_ ]?check/i,\n /microsoft-azure-application-lb/i,\n /googlehc/i,\n /kube-probe/i,\n];\nconst MASK_QUERY_PARAM_PATTERNS = [\n /auth/i,\n /api-?key/i,\n /secret/i,\n /token/i,\n /password/i,\n /pwd/i,\n];\nconst MASK_HEADER_PATTERNS = [\n /auth/i,\n /api-?key/i,\n /secret/i,\n /token/i,\n /cookie/i,\n];\nconst MASK_BODY_FIELD_PATTERNS = [\n /password/i,\n /pwd/i,\n /token/i,\n /secret/i,\n /auth/i,\n /card[-_ ]?number/i,\n /ccv/i,\n /ssn/i,\n];\n\nexport type Request = {\n timestamp: number;\n method: string;\n path?: string;\n url: string;\n headers: [string, string][];\n size?: number;\n consumer?: string;\n body?: Buffer;\n};\n\nexport type Response = {\n statusCode: number;\n responseTime: number;\n headers: [string, string][];\n size?: number;\n body?: Buffer;\n};\n\nexport type RequestLoggingConfig = {\n enabled: boolean;\n logQueryParams: boolean;\n logRequestHeaders: boolean;\n logRequestBody: boolean;\n logResponseHeaders: boolean;\n logResponseBody: boolean;\n logException: boolean;\n maskQueryParams: RegExp[];\n maskHeaders: RegExp[];\n maskBodyFields: RegExp[];\n maskRequestBodyCallback?: (request: Request) => Buffer | null | undefined;\n maskResponseBodyCallback?: (\n request: Request,\n response: Response,\n ) => Buffer | null | undefined;\n excludePaths: RegExp[];\n excludeCallback?: (request: Request, response: Response) => boolean;\n};\n\nconst DEFAULT_CONFIG: RequestLoggingConfig = {\n enabled: false,\n logQueryParams: true,\n logRequestHeaders: false,\n logRequestBody: false,\n logResponseHeaders: true,\n logResponseBody: false,\n logException: true,\n maskQueryParams: [],\n maskHeaders: [],\n maskBodyFields: [],\n excludePaths: [],\n};\n\ntype RequestLogItem = {\n uuid: string;\n request: Request;\n response: Response;\n exception?: {\n type: string;\n message: string;\n stacktrace: string;\n sentryEventId?: string;\n };\n};\n\nexport default class RequestLogger {\n public config: RequestLoggingConfig;\n public enabled: boolean;\n public suspendUntil: number | null = null;\n private pendingWrites: RequestLogItem[] = [];\n private currentFile: TempGzipFile | null = null;\n private files: TempGzipFile[] = [];\n private maintainIntervalId?: NodeJS.Timeout;\n private lock = new AsyncLock();\n\n constructor(config?: Partial<RequestLoggingConfig>) {\n this.config = { ...DEFAULT_CONFIG, ...config };\n this.enabled = this.config.enabled && checkWritableFs();\n\n if (this.enabled) {\n this.maintainIntervalId = setInterval(() => {\n this.maintain();\n }, 1000);\n }\n }\n\n get maxBodySize() {\n return MAX_BODY_SIZE;\n }\n\n private shouldExcludePath(urlPath: string) {\n const patterns = [...this.config.excludePaths, ...EXCLUDE_PATH_PATTERNS];\n return matchPatterns(urlPath, patterns);\n }\n\n private shouldExcludeUserAgent(userAgent?: string) {\n return userAgent\n ? matchPatterns(userAgent, EXCLUDE_USER_AGENT_PATTERNS)\n : false;\n }\n\n private shouldMaskQueryParam(name: string) {\n const patterns = [\n ...this.config.maskQueryParams,\n ...MASK_QUERY_PARAM_PATTERNS,\n ];\n return matchPatterns(name, patterns);\n }\n\n private shouldMaskHeader(name: string) {\n const patterns = [...this.config.maskHeaders, ...MASK_HEADER_PATTERNS];\n return matchPatterns(name, patterns);\n }\n\n private shouldMaskBodyField(name: string) {\n const patterns = [\n ...this.config.maskBodyFields,\n ...MASK_BODY_FIELD_PATTERNS,\n ];\n return matchPatterns(name, patterns);\n }\n\n private hasSupportedContentType(headers: [string, string][]) {\n const contentType = headers.find(\n ([k]) => k.toLowerCase() === \"content-type\",\n )?.[1];\n return this.isSupportedContentType(contentType);\n }\n\n private hasJsonContentType(headers: [string, string][]) {\n const contentType = headers.find(\n ([k]) => k.toLowerCase() === \"content-type\",\n )?.[1];\n return contentType ? /\\bjson\\b/i.test(contentType) : null;\n }\n\n public isSupportedContentType(contentType?: string | null) {\n return (\n typeof contentType === \"string\" &&\n ALLOWED_CONTENT_TYPES.some((t) => contentType.startsWith(t))\n );\n }\n\n private maskQueryParams(search: string) {\n const params = new URLSearchParams(search);\n for (const [key] of params) {\n if (this.shouldMaskQueryParam(key)) {\n params.set(key, MASKED);\n }\n }\n return params.toString();\n }\n\n private maskHeaders(headers: [string, string][]): [string, string][] {\n return headers.map(([k, v]) => [k, this.shouldMaskHeader(k) ? MASKED : v]);\n }\n\n private maskBody(data: any): any {\n if (typeof data === \"object\" && data !== null && !Array.isArray(data)) {\n const result: any = {};\n for (const [key, value] of Object.entries(data)) {\n if (typeof value === \"string\" && this.shouldMaskBodyField(key)) {\n result[key] = MASKED;\n } else {\n result[key] = this.maskBody(value);\n }\n }\n return result;\n }\n if (Array.isArray(data)) {\n return data.map((item) => this.maskBody(item));\n }\n return data;\n }\n\n private applyMasking(item: RequestLogItem) {\n // Apply user-provided maskRequestBodyCallback function\n if (\n this.config.maskRequestBodyCallback &&\n item.request.body &&\n item.request.body !== BODY_TOO_LARGE\n ) {\n try {\n const maskedBody = this.config.maskRequestBodyCallback(item.request);\n item.request.body = maskedBody ?? BODY_MASKED;\n } catch {\n item.request.body = undefined;\n }\n }\n\n // Apply user-provided maskResponseBodyCallback function\n if (\n this.config.maskResponseBodyCallback &&\n item.response.body &&\n item.response.body !== BODY_TOO_LARGE\n ) {\n try {\n const maskedBody = this.config.maskResponseBodyCallback(\n item.request,\n item.response,\n );\n item.response.body = maskedBody ?? BODY_MASKED;\n } catch {\n item.response.body = undefined;\n }\n }\n\n // Check request and response body sizes\n if (item.request.body && item.request.body.length > MAX_BODY_SIZE) {\n item.request.body = BODY_TOO_LARGE;\n }\n if (item.response.body && item.response.body.length > MAX_BODY_SIZE) {\n item.response.body = BODY_TOO_LARGE;\n }\n\n // Mask request and response body fields\n for (const key of [\"request\", \"response\"] as const) {\n const bodyData = item[key].body;\n if (\n !bodyData ||\n bodyData === BODY_TOO_LARGE ||\n bodyData === BODY_MASKED\n ) {\n continue;\n }\n\n const headers = item[key].headers;\n const hasJsonContent = this.hasJsonContentType(headers);\n if (hasJsonContent === null || hasJsonContent) {\n try {\n const parsedBody = JSON.parse(bodyData.toString());\n const maskedBody = this.maskBody(parsedBody);\n item[key].body = Buffer.from(JSON.stringify(maskedBody));\n } catch {\n // If parsing fails, leave body as is\n }\n }\n }\n\n // Mask request and response headers\n item.request.headers = this.config.logRequestHeaders\n ? this.maskHeaders(item.request.headers)\n : [];\n item.response.headers = this.config.logResponseHeaders\n ? this.maskHeaders(item.response.headers)\n : [];\n\n // Mask query params\n const url = new URL(item.request.url);\n url.search = this.config.logQueryParams\n ? this.maskQueryParams(url.search)\n : \"\";\n item.request.url = url.toString();\n\n return item;\n }\n\n logRequest(request: Request, response: Response, error?: Error) {\n if (!this.enabled || this.suspendUntil !== null) return;\n\n const url = new URL(request.url);\n const path = request.path ?? url.pathname;\n const userAgent = request.headers.find(\n ([k]) => k.toLowerCase() === \"user-agent\",\n )?.[1];\n\n if (\n this.shouldExcludePath(path) ||\n this.shouldExcludeUserAgent(userAgent) ||\n (this.config.excludeCallback?.(request, response) ?? false)\n ) {\n return;\n }\n\n if (\n !this.config.logRequestBody ||\n !this.hasSupportedContentType(request.headers)\n ) {\n request.body = undefined;\n }\n if (\n !this.config.logResponseBody ||\n !this.hasSupportedContentType(response.headers)\n ) {\n response.body = undefined;\n }\n\n if (request.size !== undefined && request.size < 0) {\n request.size = undefined;\n }\n if (response.size !== undefined && response.size < 0) {\n response.size = undefined;\n }\n\n const item: RequestLogItem = {\n uuid: randomUUID(),\n request: request,\n response: response,\n exception:\n error && this.config.logException\n ? {\n type: error.name,\n message: truncateExceptionMessage(error.message),\n stacktrace: truncateExceptionStackTrace(error.stack || \"\"),\n sentryEventId: getSentryEventId(),\n }\n : undefined,\n };\n this.pendingWrites.push(item);\n\n if (this.pendingWrites.length > MAX_PENDING_WRITES) {\n this.pendingWrites.shift();\n }\n }\n\n async writeToFile() {\n if (!this.enabled || this.pendingWrites.length === 0) {\n return;\n }\n return this.lock.acquire(\"file\", async () => {\n if (!this.currentFile) {\n this.currentFile = new TempGzipFile();\n }\n while (this.pendingWrites.length > 0) {\n let item = this.pendingWrites.shift();\n if (item) {\n item = this.applyMasking(item);\n\n const finalItem = {\n uuid: item.uuid,\n request: skipEmptyValues(item.request),\n response: skipEmptyValues(item.response),\n exception: item.exception,\n };\n\n // Set up body serialization for JSON\n [finalItem.request.body, finalItem.response.body].forEach((body) => {\n if (body) {\n // @ts-expect-error Override Buffer's default JSON serialization\n body.toJSON = function () {\n return this.toString(\"base64\");\n };\n }\n });\n\n await this.currentFile.writeLine(\n Buffer.from(JSON.stringify(finalItem)),\n );\n }\n }\n });\n }\n\n getFile() {\n return this.files.shift();\n }\n\n retryFileLater(file: TempGzipFile) {\n this.files.unshift(file);\n }\n\n async rotateFile() {\n return this.lock.acquire(\"file\", async () => {\n if (this.currentFile) {\n await this.currentFile.close();\n this.files.push(this.currentFile);\n this.currentFile = null;\n }\n });\n }\n\n async maintain() {\n await this.writeToFile();\n if (this.currentFile && this.currentFile.size > MAX_FILE_SIZE) {\n await this.rotateFile();\n }\n while (this.files.length > MAX_FILES) {\n const file = this.files.shift();\n file?.delete();\n }\n if (this.suspendUntil !== null && this.suspendUntil < Date.now()) {\n this.suspendUntil = null;\n }\n }\n\n async clear() {\n this.pendingWrites = [];\n await this.rotateFile();\n this.files.forEach((file) => {\n file.delete();\n });\n this.files = [];\n }\n\n async close() {\n this.enabled = false;\n await this.clear();\n if (this.maintainIntervalId) {\n clearInterval(this.maintainIntervalId);\n }\n }\n}\n\nexport function convertHeaders(\n headers:\n | Headers\n | IncomingHttpHeaders\n | OutgoingHttpHeaders\n | Record<string, string | string[] | number | undefined>,\n) {\n if (headers instanceof Headers) {\n return Array.from(headers.entries());\n }\n return Object.entries(headers).flatMap(([key, value]) => {\n if (value === undefined) {\n return [];\n }\n if (Array.isArray(value)) {\n return value.map((v) => [key, v]);\n }\n return [[key, value.toString()]];\n }) as [string, string][];\n}\n\nexport function convertBody(body: any, contentType?: string | null) {\n if (!body || !contentType) {\n return;\n }\n try {\n if (contentType.startsWith(\"application/json\")) {\n if (isValidJsonString(body)) {\n return Buffer.from(body);\n } else {\n return Buffer.from(JSON.stringify(body));\n }\n }\n if (contentType.startsWith(\"text/\") && typeof body === \"string\") {\n return Buffer.from(body);\n }\n } catch (error) {\n return;\n }\n}\n\nfunction isValidJsonString(body: any) {\n if (typeof body !== \"string\") {\n return false;\n }\n try {\n JSON.parse(body);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction matchPatterns(value: string, patterns: RegExp[]) {\n return patterns.some((pattern) => {\n return pattern.test(value);\n });\n}\n\nfunction skipEmptyValues<T extends Record<string, any>>(data: T) {\n return Object.fromEntries(\n Object.entries(data).filter(([_, v]) => {\n if (v == null || Number.isNaN(v)) return false;\n if (Array.isArray(v) || Buffer.isBuffer(v) || typeof v === \"string\") {\n return v.length > 0;\n }\n return true;\n }),\n ) as Partial<T>;\n}\n\nfunction checkWritableFs() {\n try {\n const testPath = join(tmpdir(), `apitally-${randomUUID()}`);\n writeFileSync(testPath, \"test\");\n unlinkSync(testPath);\n return true;\n } catch (error) {\n return false;\n }\n}\n","import type * as Sentry from \"@sentry/node\";\n\nlet sentry: typeof Sentry | undefined;\n\n// Initialize Sentry when the module is loaded\n(async () => {\n try {\n sentry = await import(\"@sentry/node\");\n } catch (e) {\n // Sentry SDK is not installed, ignore\n }\n})();\n\n/**\n * Returns the last Sentry event ID if available\n */\nexport function getSentryEventId(): string | undefined {\n if (sentry && sentry.lastEventId) {\n return sentry.lastEventId();\n }\n return undefined;\n}\n","import { createHash } from \"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 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","import { Buffer } from \"buffer\";\nimport { randomUUID } from \"crypto\";\nimport { createWriteStream, readFile, unlinkSync, WriteStream } from \"fs\";\nimport { tmpdir } from \"os\";\nimport { join } from \"path\";\nimport { createGzip, Gzip } from \"zlib\";\n\nexport default class TempGzipFile {\n public uuid: string;\n private filePath: string;\n private gzip: Gzip;\n private writeStream: WriteStream;\n private readyPromise: Promise<void>;\n private closedPromise: Promise<void>;\n\n constructor() {\n this.uuid = randomUUID();\n this.filePath = join(tmpdir(), `apitally-${this.uuid}.gz`);\n this.writeStream = createWriteStream(this.filePath);\n this.readyPromise = new Promise<void>((resolve, reject) => {\n this.writeStream.once(\"ready\", resolve);\n this.writeStream.once(\"error\", reject);\n });\n this.closedPromise = new Promise<void>((resolve, reject) => {\n this.writeStream.once(\"close\", resolve);\n this.writeStream.once(\"error\", reject);\n });\n this.gzip = createGzip();\n this.gzip.pipe(this.writeStream);\n }\n\n get size() {\n return this.writeStream.bytesWritten;\n }\n\n async writeLine(data: Buffer) {\n await this.readyPromise;\n return new Promise<void>((resolve, reject) => {\n this.gzip.write(Buffer.concat([data, Buffer.from(\"\\n\")]), (error) => {\n if (error) {\n reject(error);\n } else {\n resolve();\n }\n });\n });\n }\n\n async getContent() {\n return new Promise<Buffer>((resolve, reject) => {\n readFile(this.filePath, (error, data) => {\n if (error) {\n reject(error);\n } else {\n resolve(data);\n }\n });\n });\n }\n\n async close() {\n await new Promise<void>((resolve) => {\n this.gzip.end(() => {\n resolve();\n });\n });\n await this.closedPromise;\n }\n\n async delete() {\n await this.close();\n unlinkSync(this.filePath);\n }\n}\n","import { createHash } from \"crypto\";\n\nimport {\n ConsumerMethodPath,\n ValidationError,\n ValidationErrorsItem,\n} from \"./types.js\";\n\nexport default class ValidationErrorCounter {\n private errorCounts: Map<string, number>;\n private errorDetails: Map<string, ConsumerMethodPath & ValidationError>;\n\n constructor() {\n this.errorCounts = new Map();\n this.errorDetails = new Map();\n }\n\n public addValidationError(\n validationError: ConsumerMethodPath & ValidationError,\n ) {\n const key = this.getKey(validationError);\n if (!this.errorDetails.has(key)) {\n this.errorDetails.set(key, validationError);\n }\n this.errorCounts.set(key, (this.errorCounts.get(key) || 0) + 1);\n }\n\n public getAndResetValidationErrors() {\n const data: Array<ValidationErrorsItem> = [];\n this.errorCounts.forEach((count, key) => {\n const validationError = this.errorDetails.get(key);\n if (validationError) {\n data.push({\n consumer: validationError.consumer || null,\n method: validationError.method,\n path: validationError.path,\n loc: validationError.loc.split(\".\"),\n msg: validationError.msg,\n type: validationError.type,\n error_count: count,\n });\n }\n });\n this.errorCounts.clear();\n this.errorDetails.clear();\n return data;\n }\n\n private getKey(validationError: ConsumerMethodPath & ValidationError) {\n const hashInput = [\n validationError.consumer || \"\",\n validationError.method.toUpperCase(),\n validationError.path,\n validationError.loc,\n validationError.msg.trim(),\n validationError.type,\n ].join(\"|\");\n return createHash(\"md5\").update(hashInput).digest(\"hex\");\n }\n}\n","import { OutgoingHttpHeader } from \"http\";\n\nexport function parseContentLength(\n contentLength: OutgoingHttpHeader | undefined | null,\n): number | undefined {\n if (contentLength === undefined || contentLength === null) {\n return undefined;\n }\n if (typeof contentLength === \"number\") {\n return contentLength;\n }\n if (typeof contentLength === \"string\") {\n const parsed = parseInt(contentLength);\n return isNaN(parsed) ? undefined : parsed;\n }\n if (Array.isArray(contentLength)) {\n return parseContentLength(contentLength[0]);\n }\n return undefined;\n}\n\nexport function mergeHeaders(base: Headers, merge: Headers) {\n const mergedHeaders = new Headers(base);\n for (const [name, value] of merge)\n if (name === \"set-cookie\") mergedHeaders.append(name, value);\n else mergedHeaders.set(name, value);\n return mergedHeaders;\n}\n","export async function measureResponseSize(\n response: Response,\n): Promise<[number, Response]> {\n const [newResponse1, newResponse2] = await teeResponse(response);\n let size = 0;\n if (newResponse2.body) {\n let done = false;\n const reader = newResponse2.body.getReader();\n while (!done) {\n const result = await reader.read();\n done = result.done;\n if (!done && result.value) {\n size += result.value.byteLength;\n }\n }\n }\n return [size, newResponse1];\n}\n\nexport async function getResponseBody(\n response: Response,\n): Promise<[Buffer, Response]> {\n const [newResponse1, newResponse2] = await teeResponse(response);\n const responseBuffer = Buffer.from(await newResponse2.arrayBuffer());\n return [responseBuffer, newResponse1];\n}\n\nexport async function getResponseJson(\n response: Response,\n): Promise<[any, Response]> {\n const contentType = response.headers.get(\"content-type\");\n if (contentType?.includes(\"application/json\")) {\n const [newResponse1, newResponse2] = await teeResponse(response);\n const responseJson = await newResponse2.json();\n return [responseJson, newResponse1];\n }\n return [null, response];\n}\n\nexport async function teeResponse(\n response: Response,\n): Promise<[Response, Response]> {\n if (!response.body) {\n return [response, response];\n }\n const [stream1, stream2] = response.body.tee();\n const newResponse1 = new Response(stream1, {\n status: response.status,\n statusText: response.statusText,\n headers: response.headers,\n });\n const newResponse2 = new Response(stream2, {\n status: response.status,\n statusText: response.statusText,\n headers: response.headers,\n });\n return [newResponse1, newResponse2];\n}\n","import { createRequire } from \"module\";\n\nexport function getPackageVersion(name: string): string | null {\n const packageJsonPath = `${name}/package.json`;\n try {\n return require(packageJsonPath).version || null;\n } catch (error) {\n try {\n const _require = createRequire(import.meta.url);\n return _require(packageJsonPath).version || null;\n } catch (error) {\n return null;\n }\n }\n}\n","import { H3, H3Route } from \"h3\";\n\nimport { getPackageVersion } from \"../common/packageVersions.js\";\n\nexport function getAppInfo(h3: H3, appVersion?: string) {\n const routes = h3._routes ? listAllRoutes<H3Route>(h3._routes.root) : [];\n\n const versions: Array<[string, string]> = [];\n if (process.versions.node) {\n versions.push([\"nodejs\", process.versions.node]);\n }\n if (process.versions.bun) {\n versions.push([\"bun\", process.versions.bun]);\n }\n const h3Version = getPackageVersion(\"h3\");\n const apitallyVersion = getPackageVersion(\"../..\");\n if (h3Version) {\n versions.push([\"h3\", h3Version]);\n }\n if (apitallyVersion) {\n versions.push([\"apitally\", apitallyVersion]);\n }\n if (appVersion) {\n versions.push([\"app\", appVersion]);\n }\n\n return {\n paths: routes\n .map((route) => ({\n method: route.method || \"\",\n path: route.route || \"\",\n }))\n .filter((route) => route.method && route.path),\n versions: Object.fromEntries(versions),\n client: \"js:h3\",\n };\n}\n\n// Types from rou3\ntype MethodData<T = unknown> = { data: T };\ninterface Node<T = unknown> {\n key: string;\n static?: Record<string, Node<T>>;\n param?: Node<T>;\n wildcard?: Node<T>;\n methods?: Record<string, MethodData<T>[] | undefined>;\n}\n\nfunction listAllRoutes<T>(node: Node<T>): T[] {\n const routes: T[] = [];\n _collectAllRoutes(node, routes);\n return routes;\n}\n\nfunction _collectAllRoutes<T>(node: Node<T>, routes: T[] = []): void {\n // Collect routes from current node methods\n if (node.methods) {\n for (const methodData of Object.values(node.methods)) {\n if (Array.isArray(methodData)) {\n for (const item of methodData) {\n if (item.data) {\n routes.push(item.data);\n }\n }\n }\n }\n }\n\n // Traverse static children\n if (node.static) {\n for (const staticChild of Object.values(node.static)) {\n _collectAllRoutes(staticChild, routes);\n }\n }\n\n // Traverse param child\n if (node.param) {\n _collectAllRoutes(node.param, routes);\n }\n\n // Traverse wildcard child\n if (node.wildcard) {\n _collectAllRoutes(node.wildcard, routes);\n }\n}\n"],"mappings":"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","names":["import_crypto","consumerFromStringOrObject","consumer","_a","String","trim","substring","identifier","name","group","ConsumerRegistry","consumers","updated","Map","Set","addOrUpdateConsumer","existing","get","set","add","getAndResetUpdatedConsumers","data","forEach","push","clear","getLogger","createLogger","level","process","env","APITALLY_DEBUG","format","combine","colorize","timestamp","printf","info","message","transports","Console","isValidClientId","clientId","regexExp","test","isValidEnv","env","RequestCounter","requestCounts","requestSizeSums","responseSizeSums","responseTimes","requestSizes","responseSizes","Map","getKey","requestInfo","consumer","method","toUpperCase","path","statusCode","join","addRequest","key","set","get","has","responseTimeMap","responseTimeMsBin","Math","floor","responseTime","requestSize","undefined","Number","requestSizeMap","requestSizeKbBin","responseSize","responseSizeMap","responseSizeKbBin","getAndResetRequests","data","forEach","count","statusCodeStr","split","push","status_code","parseInt","request_count","request_size_sum","response_size_sum","response_times","Object","fromEntries","request_sizes","response_sizes","clear","import_buffer","import_crypto","import_fs","import_os","import_path","sentry","e","getSentryEventId","lastEventId","undefined","MAX_MSG_LENGTH","MAX_STACKTRACE_LENGTH","ServerErrorCounter","errorCounts","errorDetails","sentryEventIds","Map","addServerError","serverError","key","getKey","has","set","get","sentryEventId","getSentryEventId","getAndResetServerErrors","data","forEach","count","push","consumer","method","path","type","msg","truncateExceptionMessage","traceback","truncateExceptionStackTrace","sentry_event_id","error_count","clear","hashInput","toUpperCase","trim","join","createHash","update","digest","length","suffix","cutoff","substring","stack","lines","split","truncatedLines","line","import_crypto","TempGzipFile","uuid","filePath","gzip","writeStream","readyPromise","closedPromise","randomUUID","join","tmpdir","createWriteStream","Promise","resolve","reject","once","createGzip","pipe","size","bytesWritten","writeLine","data","write","Buffer","concat","from","error","getContent","readFile","close","end","delete","unlinkSync","MAX_BODY_SIZE","MAX_FILE_SIZE","MAX_FILES","MAX_PENDING_WRITES","BODY_TOO_LARGE","Buffer","from","BODY_MASKED","MASKED","ALLOWED_CONTENT_TYPES","EXCLUDE_PATH_PATTERNS","EXCLUDE_USER_AGENT_PATTERNS","MASK_QUERY_PARAM_PATTERNS","MASK_HEADER_PATTERNS","MASK_BODY_FIELD_PATTERNS","DEFAULT_CONFIG","enabled","logQueryParams","logRequestHeaders","logRequestBody","logResponseHeaders","logResponseBody","logException","maskQueryParams","maskHeaders","maskBodyFields","excludePaths","RequestLogger","config","suspendUntil","pendingWrites","currentFile","files","maintainIntervalId","lock","AsyncLock","checkWritableFs","setInterval","maintain","maxBodySize","shouldExcludePath","urlPath","patterns","matchPatterns","shouldExcludeUserAgent","userAgent","shouldMaskQueryParam","name","shouldMaskHeader","shouldMaskBodyField","hasSupportedContentType","headers","_a","contentType","find","k","toLowerCase","isSupportedContentType","hasJsonContentType","test","some","t","startsWith","search","params","URLSearchParams","key","set","toString","map","v","maskBody","data","Array","isArray","result","value","Object","entries","item","applyMasking","maskRequestBodyCallback","request","body","maskedBody","undefined","maskResponseBodyCallback","response","length","bodyData","hasJsonContent","parsedBody","JSON","parse","stringify","url","URL","logRequest","error","path","pathname","excludeCallback","size","uuid","randomUUID","exception","type","message","truncateExceptionMessage","stacktrace","truncateExceptionStackTrace","stack","sentryEventId","getSentryEventId","push","shift","writeToFile","acquire","TempGzipFile","finalItem","skipEmptyValues","forEach","toJSON","writeLine","getFile","retryFileLater","file","unshift","rotateFile","close","delete","Date","now","clear","clearInterval","convertHeaders","Headers","flatMap","matchPatterns","value","patterns","some","pattern","test","skipEmptyValues","data","Object","fromEntries","entries","filter","_","v","Number","isNaN","Array","isArray","Buffer","isBuffer","length","checkWritableFs","testPath","join","tmpdir","randomUUID","writeFileSync","unlinkSync","error","import_crypto","ValidationErrorCounter","errorCounts","errorDetails","Map","addValidationError","validationError","key","getKey","has","set","get","getAndResetValidationErrors","data","forEach","count","push","consumer","method","path","loc","split","msg","type","error_count","clear","hashInput","toUpperCase","trim","join","createHash","update","digest","SYNC_INTERVAL","INITIAL_SYNC_INTERVAL","INITIAL_SYNC_INTERVAL_DURATION","MAX_QUEUE_TIME","HTTPError","Error","response","reason","status","ApitallyClient","clientId","env","instanceUuid","syncDataQueue","syncIntervalId","startupData","startupDataSent","enabled","requestCounter","requestLogger","validationErrorCounter","serverErrorCounter","consumerRegistry","logger","requestLoggingConfig","instance","isValidClientId","isValidEnv","randomUUID","RequestCounter","RequestLogger","ValidationErrorCounter","ServerErrorCounter","ConsumerRegistry","getLogger","startSync","handleShutdown","bind","getInstance","isEnabled","shutdown","stopSync","sendSyncData","sendLogData","close","undefined","getHubUrlPrefix","baseURL","process","APITALLY_HUB_BASE_URL","version","sendData","url","payload","fetchWithRetry","fetchRetry","fetch","retries","retryDelay","retryOn","method","body","JSON","stringify","headers","ok","sync","setInterval","setTimeout","clearInterval","promises","push","sendStartupData","Promise","all","error","setStartupData","data","debug","instance_uuid","message_uuid","handled","handleHubError","message","newPayload","timestamp","Date","now","requests","getAndResetRequests","validation_errors","getAndResetValidationErrors","server_errors","getAndResetServerErrors","consumers","getAndResetUpdatedConsumers","i","length","shift","randomDelay","rotateFile","logFile","getFile","uuid","getContent","has","retryAfter","parseInt","get","suspendUntil","clear","delete","retryFileLater","delay","Math","random","resolve","parseContentLength","contentLength","undefined","parsed","parseInt","isNaN","Array","isArray","mergeHeaders","base","merge","mergedHeaders","Headers","name","value","append","set","measureResponseSize","response","newResponse1","newResponse2","teeResponse","size","body","done","reader","getReader","result","read","value","byteLength","getResponseBody","responseBuffer","Buffer","from","arrayBuffer","teeResponse","response","body","stream1","stream2","tee","newResponse1","Response","status","statusText","headers","newResponse2","getPackageVersion","name","packageJsonPath","require","version","error","_require","createRequire","url","getAppInfo","h3","appVersion","routes","_routes","listAllRoutes","root","versions","process","node","push","bun","h3Version","getPackageVersion","apitallyVersion","paths","map","route","method","path","filter","Object","fromEntries","client","_collectAllRoutes","methods","methodData","values","Array","isArray","item","data","static","staticChild","param","wildcard","jsonHeaders","Headers","apitallyPlugin","definePlugin","app","config","client","ApitallyClient","setStartupData","attempt","appInfo","getAppInfo","appVersion","paths","length","setTimeout","handleResponse","event","response","error","_a","startTime","context","_apitallyRequestTimestamp","responseTime","performance","now","path","matchedRoute","route","statusCode","status","requestSize","parseContentLength","req","headers","get","responseSize","newResponse","measureResponseSize","consumer","getConsumer","consumerRegistry","addOrUpdateConsumer","requestCounter","addRequest","identifier","method","data","name","zodError","issues","forEach","issue","validationErrorCounter","addValidationError","loc","join","msg","message","type","code","serverErrorCounter","addServerError","traceback","stack","requestLogger","enabled","responseHeaders","mergeHeaders","responseContentType","responseBody","logResponseBody","isSupportedContentType","getResponseBody","Buffer","from","JSON","stringify","toJSON","logRequest","timestamp","Date","url","convertHeaders","Object","fromEntries","entries","size","Number","body","_apitallyRequestBody","use","onRequest","requestContentType","logRequestBody","maxBodySize","clonedRequest","clone","requestBody","arrayBuffer","onResponse","isEnabled","undefined","onError","setConsumer","apitallyConsumer","consumerFromStringOrObject"]}
1
+ {"version":3,"sources":["../../src/h3/plugin.ts","../../src/common/client.ts","../../src/common/consumerRegistry.ts","../../src/common/logging.ts","../../src/common/paramValidation.ts","../../src/common/requestCounter.ts","../../src/common/requestLogger.ts","../../src/common/sentry.ts","../../src/common/serverErrorCounter.ts","../../src/common/tempGzipFile.ts","../../src/common/validationErrorCounter.ts","../../src/common/headers.ts","../../src/common/response.ts","../../src/common/packageVersions.ts","../../src/h3/utils.ts"],"sourcesContent":["import type { H3Event, HTTPError } from \"h3\";\nimport { definePlugin, onError, onRequest, onResponse } from \"h3\";\nimport { performance } from \"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 { convertHeaders } from \"../common/requestLogger.js\";\nimport { getResponseBody, measureResponseSize } from \"../common/response.js\";\nimport { ApitallyConfig, ApitallyConsumer } from \"../common/types.js\";\nimport { getAppInfo } from \"./utils.js\";\n\ndeclare module \"h3\" {\n interface H3EventContext {\n apitallyConsumer?: ApitallyConsumer | string;\n\n _apitallyRequestTimestamp?: number;\n _apitallyRequestBody?: 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\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 } else {\n setTimeout(() => setStartupData(attempt + 1), 500);\n }\n };\n setTimeout(() => setStartupData(), 500);\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._apitallyRequestTimestamp;\n const responseTime = startTime ? performance.now() - startTime : 0;\n const path = event.context.matchedRoute?.route;\n const statusCode = response?.status || error?.status || 500;\n\n const requestSize = parseContentLength(\n event.req.headers.get(\"content-length\"),\n );\n let responseSize = 0;\n let newResponse = response;\n if (response) {\n [responseSize, newResponse] = await measureResponseSize(response);\n }\n\n const consumer = getConsumer(event);\n client.consumerRegistry.addOrUpdateConsumer(consumer);\n\n if (path) {\n client.requestCounter.addRequest({\n consumer: consumer?.identifier,\n method: event.req.method,\n path,\n statusCode,\n responseTime,\n requestSize,\n responseSize,\n });\n\n if (error?.status === 400 && (error.data as any).name === \"ZodError\") {\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 (error?.status === 500) {\n client.serverErrorCounter.addServerError({\n consumer: consumer?.identifier,\n method: event.req.method,\n path,\n type: error.name,\n msg: error.message,\n traceback: error.stack || \"\",\n });\n }\n }\n\n if (client.requestLogger.enabled) {\n const responseHeaders = response\n ? response.headers\n : error?.headers\n ? mergeHeaders(jsonHeaders, error.headers)\n : jsonHeaders;\n const responseContentType = responseHeaders.get(\"content-type\");\n let responseBody;\n\n if (\n newResponse &&\n client.requestLogger.config.logResponseBody &&\n client.requestLogger.isSupportedContentType(responseContentType)\n ) {\n [responseBody, newResponse] = await getResponseBody(newResponse);\n } else if (error && client.requestLogger.config.logResponseBody) {\n responseBody = Buffer.from(JSON.stringify(error.toJSON()));\n }\n\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: Number(requestSize),\n consumer: consumer?.identifier,\n body: event.context._apitallyRequestBody,\n },\n {\n statusCode,\n responseTime: responseTime / 1000,\n headers: convertHeaders(\n Object.fromEntries(responseHeaders.entries()),\n ),\n size: responseSize,\n body: responseBody,\n },\n );\n }\n\n return newResponse;\n };\n\n app\n .use(\n onRequest(async (event) => {\n event.context._apitallyRequestTimestamp = 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._apitallyRequestBody = 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 return 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","import { randomUUID } from \"crypto\";\nimport fetchRetry from \"fetch-retry\";\n\nimport ConsumerRegistry from \"./consumerRegistry.js\";\nimport { Logger, getLogger } from \"./logging.js\";\nimport { isValidClientId, isValidEnv } from \"./paramValidation.js\";\nimport RequestCounter from \"./requestCounter.js\";\nimport RequestLogger from \"./requestLogger.js\";\nimport ServerErrorCounter from \"./serverErrorCounter.js\";\nimport {\n ApitallyConfig,\n StartupData,\n StartupPayload,\n SyncPayload,\n} from \"./types.js\";\nimport ValidationErrorCounter from \"./validationErrorCounter.js\";\n\nconst SYNC_INTERVAL = 60000; // 60 seconds\nconst INITIAL_SYNC_INTERVAL = 10000; // 10 seconds\nconst INITIAL_SYNC_INTERVAL_DURATION = 3600000; // 1 hour\nconst MAX_QUEUE_TIME = 3.6e6; // 1 hour\n\nclass HTTPError extends Error {\n public response: Response;\n\n constructor(response: Response) {\n const reason = response.status\n ? `status code ${response.status}`\n : \"an unknown error\";\n super(`Request failed with ${reason}`);\n this.response = response;\n }\n}\n\nexport class ApitallyClient {\n private clientId: string;\n private env: string;\n\n private static instance?: ApitallyClient;\n private instanceUuid: string;\n private syncDataQueue: SyncPayload[];\n private syncIntervalId?: NodeJS.Timeout;\n public startupData?: StartupData;\n private startupDataSent: boolean = false;\n private enabled: boolean = true;\n\n public requestCounter: RequestCounter;\n public requestLogger: RequestLogger;\n public validationErrorCounter: ValidationErrorCounter;\n public serverErrorCounter: ServerErrorCounter;\n public consumerRegistry: ConsumerRegistry;\n public logger: Logger;\n\n constructor({\n clientId,\n env = \"dev\",\n requestLogging,\n requestLoggingConfig,\n logger,\n }: ApitallyConfig) {\n if (ApitallyClient.instance) {\n throw new Error(\"Apitally client is already initialized\");\n }\n if (!isValidClientId(clientId)) {\n throw new Error(\n `Invalid Apitally client ID '${clientId}' (expecting hexadecimal UUID format)`,\n );\n }\n if (!isValidEnv(env)) {\n throw new Error(\n `Invalid env '${env}' (expecting 1-32 alphanumeric lowercase characters and hyphens only)`,\n );\n }\n if (requestLoggingConfig && !requestLogging) {\n console.warn(\n \"requestLoggingConfig is deprecated, use requestLogging instead.\",\n );\n }\n\n ApitallyClient.instance = this;\n this.clientId = clientId;\n this.env = env;\n this.instanceUuid = randomUUID();\n this.syncDataQueue = [];\n this.requestCounter = new RequestCounter();\n this.requestLogger = new RequestLogger(\n requestLogging ?? requestLoggingConfig,\n );\n this.validationErrorCounter = new ValidationErrorCounter();\n this.serverErrorCounter = new ServerErrorCounter();\n this.consumerRegistry = new ConsumerRegistry();\n this.logger = logger ?? getLogger();\n\n this.startSync();\n this.handleShutdown = this.handleShutdown.bind(this);\n }\n\n public static getInstance() {\n if (!ApitallyClient.instance) {\n throw new Error(\"Apitally client is not initialized\");\n }\n return ApitallyClient.instance;\n }\n\n public isEnabled() {\n return this.enabled;\n }\n\n public static async shutdown() {\n if (ApitallyClient.instance) {\n await ApitallyClient.instance.handleShutdown();\n }\n }\n\n public async handleShutdown() {\n this.enabled = false;\n this.stopSync();\n await this.sendSyncData();\n await this.sendLogData();\n await this.requestLogger.close();\n ApitallyClient.instance = undefined;\n }\n\n private getHubUrlPrefix() {\n const baseURL =\n process.env.APITALLY_HUB_BASE_URL || \"https://hub.apitally.io\";\n const version = \"v2\";\n return `${baseURL}/${version}/${this.clientId}/${this.env}/`;\n }\n\n private async sendData(url: string, payload: any) {\n const fetchWithRetry = fetchRetry(fetch, {\n retries: 3,\n retryDelay: 1000,\n retryOn: [408, 429, 500, 502, 503, 504],\n });\n const response = await fetchWithRetry(this.getHubUrlPrefix() + url, {\n method: \"POST\",\n body: JSON.stringify(payload),\n headers: { \"Content-Type\": \"application/json\" },\n });\n if (!response.ok) {\n throw new HTTPError(response);\n }\n }\n\n private startSync() {\n this.sync();\n this.syncIntervalId = setInterval(() => {\n this.sync();\n }, INITIAL_SYNC_INTERVAL);\n setTimeout(() => {\n clearInterval(this.syncIntervalId);\n this.syncIntervalId = setInterval(() => {\n this.sync();\n }, SYNC_INTERVAL);\n }, INITIAL_SYNC_INTERVAL_DURATION);\n }\n\n private async sync() {\n try {\n const promises = [this.sendSyncData(), this.sendLogData()];\n if (!this.startupDataSent) {\n promises.push(this.sendStartupData());\n }\n await Promise.all(promises);\n } catch (error) {\n this.logger.error(\"Error while syncing with Apitally Hub\", {\n error,\n });\n }\n }\n\n private stopSync() {\n if (this.syncIntervalId) {\n clearInterval(this.syncIntervalId);\n this.syncIntervalId = undefined;\n }\n }\n\n public setStartupData(data: StartupData) {\n this.startupData = data;\n this.startupDataSent = false;\n this.sendStartupData();\n }\n\n private async sendStartupData() {\n if (this.startupData) {\n this.logger.debug(\"Sending startup data to Apitally Hub\");\n const payload: StartupPayload = {\n instance_uuid: this.instanceUuid,\n message_uuid: randomUUID(),\n ...this.startupData,\n };\n try {\n await this.sendData(\"startup\", payload);\n this.startupDataSent = true;\n } catch (error) {\n const handled = this.handleHubError(error);\n if (!handled) {\n this.logger.error((error as Error).message);\n this.logger.debug(\n \"Error while sending startup data to Apitally Hub (will retry)\",\n { error },\n );\n }\n }\n }\n }\n\n private async sendSyncData() {\n this.logger.debug(\"Synchronizing data with Apitally Hub\");\n const newPayload: SyncPayload = {\n timestamp: Date.now() / 1000,\n instance_uuid: this.instanceUuid,\n message_uuid: randomUUID(),\n requests: this.requestCounter.getAndResetRequests(),\n validation_errors:\n this.validationErrorCounter.getAndResetValidationErrors(),\n server_errors: this.serverErrorCounter.getAndResetServerErrors(),\n consumers: this.consumerRegistry.getAndResetUpdatedConsumers(),\n };\n this.syncDataQueue.push(newPayload);\n\n let i = 0;\n while (this.syncDataQueue.length > 0) {\n const payload = this.syncDataQueue.shift();\n if (payload) {\n try {\n if (Date.now() - payload.timestamp * 1000 <= MAX_QUEUE_TIME) {\n if (i > 0) {\n await this.randomDelay();\n }\n await this.sendData(\"sync\", payload);\n i += 1;\n }\n } catch (error) {\n const handled = this.handleHubError(error);\n if (!handled) {\n this.logger.debug(\n \"Error while synchronizing data with Apitally Hub (will retry)\",\n { error },\n );\n this.syncDataQueue.push(payload);\n break;\n }\n }\n }\n }\n }\n\n private async sendLogData() {\n this.logger.debug(\"Sending request log data to Apitally Hub\");\n await this.requestLogger.rotateFile();\n\n const fetchWithRetry = fetchRetry(fetch, {\n retries: 3,\n retryDelay: 1000,\n retryOn: [408, 429, 500, 502, 503, 504],\n });\n\n let i = 0;\n let logFile;\n while ((logFile = this.requestLogger.getFile())) {\n if (i > 0) {\n await this.randomDelay();\n }\n\n try {\n const response = await fetchWithRetry(\n `${this.getHubUrlPrefix()}log?uuid=${logFile.uuid}`,\n {\n method: \"POST\",\n body: await logFile.getContent(),\n },\n );\n\n if (response.status === 402 && response.headers.has(\"Retry-After\")) {\n const retryAfter = parseInt(\n response.headers.get(\"Retry-After\") ?? \"0\",\n );\n if (retryAfter > 0) {\n this.requestLogger.suspendUntil = Date.now() + retryAfter * 1000;\n this.requestLogger.clear();\n return;\n }\n }\n\n if (!response.ok) {\n throw new HTTPError(response);\n }\n\n logFile.delete();\n } catch (error) {\n this.requestLogger.retryFileLater(logFile);\n break;\n }\n\n i++;\n if (i >= 10) break;\n }\n }\n\n private handleHubError(error: unknown) {\n if (error instanceof HTTPError) {\n if (error.response.status === 404) {\n this.logger.error(`Invalid Apitally client ID: '${this.clientId}'`);\n this.enabled = false;\n this.stopSync();\n return true;\n }\n if (error.response.status === 422) {\n this.logger.error(\"Received validation error from Apitally Hub\");\n return true;\n }\n }\n return false;\n }\n\n private async randomDelay() {\n const delay = 100 + Math.random() * 400;\n await new Promise((resolve) => setTimeout(resolve, delay));\n }\n}\n","import { ApitallyConsumer } from \"./types.js\";\n\nexport const consumerFromStringOrObject = (\n consumer: ApitallyConsumer | string,\n) => {\n if (typeof consumer === \"string\") {\n consumer = String(consumer).trim().substring(0, 128);\n return consumer ? { identifier: consumer } : null;\n } else {\n consumer.identifier = String(consumer.identifier).trim().substring(0, 128);\n consumer.name = consumer.name?.trim().substring(0, 64);\n consumer.group = consumer.group?.trim().substring(0, 64);\n return consumer.identifier ? consumer : null;\n }\n};\n\nexport default class ConsumerRegistry {\n private consumers: Map<string, ApitallyConsumer>;\n private updated: Set<string>;\n\n constructor() {\n this.consumers = new Map();\n this.updated = new Set();\n }\n\n public addOrUpdateConsumer(consumer?: ApitallyConsumer | null) {\n if (!consumer || (!consumer.name && !consumer.group)) {\n return;\n }\n const existing = this.consumers.get(consumer.identifier);\n if (!existing) {\n this.consumers.set(consumer.identifier, consumer);\n this.updated.add(consumer.identifier);\n } else {\n if (consumer.name && consumer.name !== existing.name) {\n existing.name = consumer.name;\n this.updated.add(consumer.identifier);\n }\n if (consumer.group && consumer.group !== existing.group) {\n existing.group = consumer.group;\n this.updated.add(consumer.identifier);\n }\n }\n }\n\n public getAndResetUpdatedConsumers() {\n const data: Array<ApitallyConsumer> = [];\n this.updated.forEach((identifier) => {\n const consumer = this.consumers.get(identifier);\n if (consumer) {\n data.push(consumer);\n }\n });\n this.updated.clear();\n return data;\n }\n}\n","import { createLogger, format, transports } from \"winston\";\n\nexport interface Logger {\n debug: (message: string, meta?: object) => void;\n info: (message: string, meta?: object) => void;\n warn: (message: string, meta?: object) => void;\n error: (message: string, meta?: object) => void;\n}\n\nexport const getLogger = () => {\n return createLogger({\n level: process.env.APITALLY_DEBUG ? \"debug\" : \"warn\",\n format: format.combine(\n format.colorize(),\n format.timestamp(),\n format.printf(\n (info) => `${info.timestamp} ${info.level}: ${info.message}`,\n ),\n ),\n transports: [new transports.Console()],\n });\n};\n","export function isValidClientId(clientId: string): boolean {\n const regexExp =\n /^[0-9a-f]{8}-[0-9a-f]{4}-[4][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;\n return regexExp.test(clientId);\n}\n\nexport function isValidEnv(env: string): boolean {\n const regexExp = /^[\\w-]{1,32}$/;\n return regexExp.test(env);\n}\n","import { RequestInfo, RequestsItem } from \"./types.js\";\n\nexport default class RequestCounter {\n private requestCounts: Map<string, number>;\n private requestSizeSums: Map<string, number>;\n private responseSizeSums: Map<string, number>;\n private responseTimes: Map<string, Map<number, number>>;\n private requestSizes: Map<string, Map<number, number>>;\n private responseSizes: Map<string, Map<number, number>>;\n\n constructor() {\n this.requestCounts = new Map<string, number>();\n this.requestSizeSums = new Map<string, number>();\n this.responseSizeSums = new Map<string, number>();\n this.responseTimes = new Map<string, Map<number, number>>();\n this.requestSizes = new Map<string, Map<number, number>>();\n this.responseSizes = new Map<string, Map<number, number>>();\n }\n\n private getKey(requestInfo: RequestInfo) {\n return [\n requestInfo.consumer || \"\",\n requestInfo.method.toUpperCase(),\n requestInfo.path,\n requestInfo.statusCode,\n ].join(\"|\");\n }\n\n addRequest(requestInfo: RequestInfo) {\n const key = this.getKey(requestInfo);\n\n // Increment request count\n this.requestCounts.set(key, (this.requestCounts.get(key) || 0) + 1);\n\n // Add response time\n if (!this.responseTimes.has(key)) {\n this.responseTimes.set(key, new Map<number, number>());\n }\n const responseTimeMap = this.responseTimes.get(key)!;\n const responseTimeMsBin = Math.floor(requestInfo.responseTime / 10) * 10; // Rounded to nearest 10ms\n responseTimeMap.set(\n responseTimeMsBin,\n (responseTimeMap.get(responseTimeMsBin) || 0) + 1,\n );\n\n // Add request size\n if (requestInfo.requestSize !== undefined) {\n requestInfo.requestSize = Number(requestInfo.requestSize);\n this.requestSizeSums.set(\n key,\n (this.requestSizeSums.get(key) || 0) + requestInfo.requestSize,\n );\n if (!this.requestSizes.has(key)) {\n this.requestSizes.set(key, new Map<number, number>());\n }\n const requestSizeMap = this.requestSizes.get(key)!;\n const requestSizeKbBin = Math.floor(requestInfo.requestSize / 1000); // Rounded down to nearest KB\n requestSizeMap.set(\n requestSizeKbBin,\n (requestSizeMap.get(requestSizeKbBin) || 0) + 1,\n );\n }\n\n // Add response size\n if (requestInfo.responseSize !== undefined) {\n requestInfo.responseSize = Number(requestInfo.responseSize);\n this.responseSizeSums.set(\n key,\n (this.responseSizeSums.get(key) || 0) + requestInfo.responseSize,\n );\n if (!this.responseSizes.has(key)) {\n this.responseSizes.set(key, new Map<number, number>());\n }\n const responseSizeMap = this.responseSizes.get(key)!;\n const responseSizeKbBin = Math.floor(requestInfo.responseSize / 1000); // Rounded down to nearest KB\n responseSizeMap.set(\n responseSizeKbBin,\n (responseSizeMap.get(responseSizeKbBin) || 0) + 1,\n );\n }\n }\n\n getAndResetRequests() {\n const data: Array<RequestsItem> = [];\n this.requestCounts.forEach((count, key) => {\n const [consumer, method, path, statusCodeStr] = key.split(\"|\");\n const responseTimes =\n this.responseTimes.get(key) || new Map<number, number>();\n const requestSizes =\n this.requestSizes.get(key) || new Map<number, number>();\n const responseSizes =\n this.responseSizes.get(key) || new Map<number, number>();\n data.push({\n consumer: consumer || null,\n method,\n path,\n status_code: parseInt(statusCodeStr),\n request_count: count,\n request_size_sum: this.requestSizeSums.get(key) || 0,\n response_size_sum: this.responseSizeSums.get(key) || 0,\n response_times: Object.fromEntries(responseTimes),\n request_sizes: Object.fromEntries(requestSizes),\n response_sizes: Object.fromEntries(responseSizes),\n });\n });\n\n // Reset the counts and times\n this.requestCounts.clear();\n this.requestSizeSums.clear();\n this.responseSizeSums.clear();\n this.responseTimes.clear();\n this.requestSizes.clear();\n this.responseSizes.clear();\n\n return data;\n }\n}\n","import AsyncLock from \"async-lock\";\nimport { Buffer } from \"buffer\";\nimport { randomUUID } from \"crypto\";\nimport { unlinkSync, writeFileSync } from \"fs\";\nimport { IncomingHttpHeaders, OutgoingHttpHeaders } from \"http\";\nimport { tmpdir } from \"os\";\nimport { join } from \"path\";\n\nimport { getSentryEventId } from \"./sentry.js\";\nimport {\n truncateExceptionMessage,\n truncateExceptionStackTrace,\n} from \"./serverErrorCounter.js\";\nimport TempGzipFile from \"./tempGzipFile.js\";\n\nconst MAX_BODY_SIZE = 50_000; // 50 KB (uncompressed)\nconst MAX_FILE_SIZE = 1_000_000; // 1 MB (compressed)\nconst MAX_FILES = 50;\nconst MAX_PENDING_WRITES = 100;\nconst BODY_TOO_LARGE = Buffer.from(\"<body too large>\");\nconst BODY_MASKED = Buffer.from(\"<masked>\");\nconst MASKED = \"******\";\nconst ALLOWED_CONTENT_TYPES = [\n \"application/json\",\n \"application/problem+json\",\n \"application/vnd.api+json\",\n \"text/plain\",\n];\nconst EXCLUDE_PATH_PATTERNS = [\n /\\/_?healthz?$/i,\n /\\/_?health[_-]?checks?$/i,\n /\\/_?heart[_-]?beats?$/i,\n /\\/ping$/i,\n /\\/ready$/i,\n /\\/live$/i,\n];\nconst EXCLUDE_USER_AGENT_PATTERNS = [\n /health[-_ ]?check/i,\n /microsoft-azure-application-lb/i,\n /googlehc/i,\n /kube-probe/i,\n];\nconst MASK_QUERY_PARAM_PATTERNS = [\n /auth/i,\n /api-?key/i,\n /secret/i,\n /token/i,\n /password/i,\n /pwd/i,\n];\nconst MASK_HEADER_PATTERNS = [\n /auth/i,\n /api-?key/i,\n /secret/i,\n /token/i,\n /cookie/i,\n];\nconst MASK_BODY_FIELD_PATTERNS = [\n /password/i,\n /pwd/i,\n /token/i,\n /secret/i,\n /auth/i,\n /card[-_ ]?number/i,\n /ccv/i,\n /ssn/i,\n];\n\nexport type Request = {\n timestamp: number;\n method: string;\n path?: string;\n url: string;\n headers: [string, string][];\n size?: number;\n consumer?: string;\n body?: Buffer;\n};\n\nexport type Response = {\n statusCode: number;\n responseTime: number;\n headers: [string, string][];\n size?: number;\n body?: Buffer;\n};\n\nexport type RequestLoggingConfig = {\n enabled: boolean;\n logQueryParams: boolean;\n logRequestHeaders: boolean;\n logRequestBody: boolean;\n logResponseHeaders: boolean;\n logResponseBody: boolean;\n logException: boolean;\n maskQueryParams: RegExp[];\n maskHeaders: RegExp[];\n maskBodyFields: RegExp[];\n maskRequestBodyCallback?: (request: Request) => Buffer | null | undefined;\n maskResponseBodyCallback?: (\n request: Request,\n response: Response,\n ) => Buffer | null | undefined;\n excludePaths: RegExp[];\n excludeCallback?: (request: Request, response: Response) => boolean;\n};\n\nconst DEFAULT_CONFIG: RequestLoggingConfig = {\n enabled: false,\n logQueryParams: true,\n logRequestHeaders: false,\n logRequestBody: false,\n logResponseHeaders: true,\n logResponseBody: false,\n logException: true,\n maskQueryParams: [],\n maskHeaders: [],\n maskBodyFields: [],\n excludePaths: [],\n};\n\ntype RequestLogItem = {\n uuid: string;\n request: Request;\n response: Response;\n exception?: {\n type: string;\n message: string;\n stacktrace: string;\n sentryEventId?: string;\n };\n};\n\nexport default class RequestLogger {\n public config: RequestLoggingConfig;\n public enabled: boolean;\n public suspendUntil: number | null = null;\n private pendingWrites: RequestLogItem[] = [];\n private currentFile: TempGzipFile | null = null;\n private files: TempGzipFile[] = [];\n private maintainIntervalId?: NodeJS.Timeout;\n private lock = new AsyncLock();\n\n constructor(config?: Partial<RequestLoggingConfig>) {\n this.config = { ...DEFAULT_CONFIG, ...config };\n this.enabled = this.config.enabled && checkWritableFs();\n\n if (this.enabled) {\n this.maintainIntervalId = setInterval(() => {\n this.maintain();\n }, 1000);\n }\n }\n\n get maxBodySize() {\n return MAX_BODY_SIZE;\n }\n\n private shouldExcludePath(urlPath: string) {\n const patterns = [...this.config.excludePaths, ...EXCLUDE_PATH_PATTERNS];\n return matchPatterns(urlPath, patterns);\n }\n\n private shouldExcludeUserAgent(userAgent?: string) {\n return userAgent\n ? matchPatterns(userAgent, EXCLUDE_USER_AGENT_PATTERNS)\n : false;\n }\n\n private shouldMaskQueryParam(name: string) {\n const patterns = [\n ...this.config.maskQueryParams,\n ...MASK_QUERY_PARAM_PATTERNS,\n ];\n return matchPatterns(name, patterns);\n }\n\n private shouldMaskHeader(name: string) {\n const patterns = [...this.config.maskHeaders, ...MASK_HEADER_PATTERNS];\n return matchPatterns(name, patterns);\n }\n\n private shouldMaskBodyField(name: string) {\n const patterns = [\n ...this.config.maskBodyFields,\n ...MASK_BODY_FIELD_PATTERNS,\n ];\n return matchPatterns(name, patterns);\n }\n\n private hasSupportedContentType(headers: [string, string][]) {\n const contentType = headers.find(\n ([k]) => k.toLowerCase() === \"content-type\",\n )?.[1];\n return this.isSupportedContentType(contentType);\n }\n\n private hasJsonContentType(headers: [string, string][]) {\n const contentType = headers.find(\n ([k]) => k.toLowerCase() === \"content-type\",\n )?.[1];\n return contentType ? /\\bjson\\b/i.test(contentType) : null;\n }\n\n public isSupportedContentType(contentType?: string | null) {\n return (\n typeof contentType === \"string\" &&\n ALLOWED_CONTENT_TYPES.some((t) => contentType.startsWith(t))\n );\n }\n\n private maskQueryParams(search: string) {\n const params = new URLSearchParams(search);\n for (const [key] of params) {\n if (this.shouldMaskQueryParam(key)) {\n params.set(key, MASKED);\n }\n }\n return params.toString();\n }\n\n private maskHeaders(headers: [string, string][]): [string, string][] {\n return headers.map(([k, v]) => [k, this.shouldMaskHeader(k) ? MASKED : v]);\n }\n\n private maskBody(data: any): any {\n if (typeof data === \"object\" && data !== null && !Array.isArray(data)) {\n const result: any = {};\n for (const [key, value] of Object.entries(data)) {\n if (typeof value === \"string\" && this.shouldMaskBodyField(key)) {\n result[key] = MASKED;\n } else {\n result[key] = this.maskBody(value);\n }\n }\n return result;\n }\n if (Array.isArray(data)) {\n return data.map((item) => this.maskBody(item));\n }\n return data;\n }\n\n private applyMasking(item: RequestLogItem) {\n // Apply user-provided maskRequestBodyCallback function\n if (\n this.config.maskRequestBodyCallback &&\n item.request.body &&\n item.request.body !== BODY_TOO_LARGE\n ) {\n try {\n const maskedBody = this.config.maskRequestBodyCallback(item.request);\n item.request.body = maskedBody ?? BODY_MASKED;\n } catch {\n item.request.body = undefined;\n }\n }\n\n // Apply user-provided maskResponseBodyCallback function\n if (\n this.config.maskResponseBodyCallback &&\n item.response.body &&\n item.response.body !== BODY_TOO_LARGE\n ) {\n try {\n const maskedBody = this.config.maskResponseBodyCallback(\n item.request,\n item.response,\n );\n item.response.body = maskedBody ?? BODY_MASKED;\n } catch {\n item.response.body = undefined;\n }\n }\n\n // Check request and response body sizes\n if (item.request.body && item.request.body.length > MAX_BODY_SIZE) {\n item.request.body = BODY_TOO_LARGE;\n }\n if (item.response.body && item.response.body.length > MAX_BODY_SIZE) {\n item.response.body = BODY_TOO_LARGE;\n }\n\n // Mask request and response body fields\n for (const key of [\"request\", \"response\"] as const) {\n const bodyData = item[key].body;\n if (\n !bodyData ||\n bodyData === BODY_TOO_LARGE ||\n bodyData === BODY_MASKED\n ) {\n continue;\n }\n\n const headers = item[key].headers;\n const hasJsonContent = this.hasJsonContentType(headers);\n if (hasJsonContent === null || hasJsonContent) {\n try {\n const parsedBody = JSON.parse(bodyData.toString());\n const maskedBody = this.maskBody(parsedBody);\n item[key].body = Buffer.from(JSON.stringify(maskedBody));\n } catch {\n // If parsing fails, leave body as is\n }\n }\n }\n\n // Mask request and response headers\n item.request.headers = this.config.logRequestHeaders\n ? this.maskHeaders(item.request.headers)\n : [];\n item.response.headers = this.config.logResponseHeaders\n ? this.maskHeaders(item.response.headers)\n : [];\n\n // Mask query params\n const url = new URL(item.request.url);\n url.search = this.config.logQueryParams\n ? this.maskQueryParams(url.search)\n : \"\";\n item.request.url = url.toString();\n\n return item;\n }\n\n logRequest(request: Request, response: Response, error?: Error) {\n if (!this.enabled || this.suspendUntil !== null) return;\n\n const url = new URL(request.url);\n const path = request.path ?? url.pathname;\n const userAgent = request.headers.find(\n ([k]) => k.toLowerCase() === \"user-agent\",\n )?.[1];\n\n if (\n this.shouldExcludePath(path) ||\n this.shouldExcludeUserAgent(userAgent) ||\n (this.config.excludeCallback?.(request, response) ?? false)\n ) {\n return;\n }\n\n if (\n !this.config.logRequestBody ||\n !this.hasSupportedContentType(request.headers)\n ) {\n request.body = undefined;\n }\n if (\n !this.config.logResponseBody ||\n !this.hasSupportedContentType(response.headers)\n ) {\n response.body = undefined;\n }\n\n if (request.size !== undefined && request.size < 0) {\n request.size = undefined;\n }\n if (response.size !== undefined && response.size < 0) {\n response.size = undefined;\n }\n\n const item: RequestLogItem = {\n uuid: randomUUID(),\n request: request,\n response: response,\n exception:\n error && this.config.logException\n ? {\n type: error.name,\n message: truncateExceptionMessage(error.message),\n stacktrace: truncateExceptionStackTrace(error.stack || \"\"),\n sentryEventId: getSentryEventId(),\n }\n : undefined,\n };\n this.pendingWrites.push(item);\n\n if (this.pendingWrites.length > MAX_PENDING_WRITES) {\n this.pendingWrites.shift();\n }\n }\n\n async writeToFile() {\n if (!this.enabled || this.pendingWrites.length === 0) {\n return;\n }\n return this.lock.acquire(\"file\", async () => {\n if (!this.currentFile) {\n this.currentFile = new TempGzipFile();\n }\n while (this.pendingWrites.length > 0) {\n let item = this.pendingWrites.shift();\n if (item) {\n item = this.applyMasking(item);\n\n const finalItem = {\n uuid: item.uuid,\n request: skipEmptyValues(item.request),\n response: skipEmptyValues(item.response),\n exception: item.exception,\n };\n\n // Set up body serialization for JSON\n [finalItem.request.body, finalItem.response.body].forEach((body) => {\n if (body) {\n // @ts-expect-error Override Buffer's default JSON serialization\n body.toJSON = function () {\n return this.toString(\"base64\");\n };\n }\n });\n\n await this.currentFile.writeLine(\n Buffer.from(JSON.stringify(finalItem)),\n );\n }\n }\n });\n }\n\n getFile() {\n return this.files.shift();\n }\n\n retryFileLater(file: TempGzipFile) {\n this.files.unshift(file);\n }\n\n async rotateFile() {\n return this.lock.acquire(\"file\", async () => {\n if (this.currentFile) {\n await this.currentFile.close();\n this.files.push(this.currentFile);\n this.currentFile = null;\n }\n });\n }\n\n async maintain() {\n await this.writeToFile();\n if (this.currentFile && this.currentFile.size > MAX_FILE_SIZE) {\n await this.rotateFile();\n }\n while (this.files.length > MAX_FILES) {\n const file = this.files.shift();\n file?.delete();\n }\n if (this.suspendUntil !== null && this.suspendUntil < Date.now()) {\n this.suspendUntil = null;\n }\n }\n\n async clear() {\n this.pendingWrites = [];\n await this.rotateFile();\n this.files.forEach((file) => {\n file.delete();\n });\n this.files = [];\n }\n\n async close() {\n this.enabled = false;\n await this.clear();\n if (this.maintainIntervalId) {\n clearInterval(this.maintainIntervalId);\n }\n }\n}\n\nexport function convertHeaders(\n headers:\n | Headers\n | IncomingHttpHeaders\n | OutgoingHttpHeaders\n | Record<string, string | string[] | number | undefined>,\n) {\n if (headers instanceof Headers) {\n return Array.from(headers.entries());\n }\n return Object.entries(headers).flatMap(([key, value]) => {\n if (value === undefined) {\n return [];\n }\n if (Array.isArray(value)) {\n return value.map((v) => [key, v]);\n }\n return [[key, value.toString()]];\n }) as [string, string][];\n}\n\nexport function convertBody(body: any, contentType?: string | null) {\n if (!body || !contentType) {\n return;\n }\n try {\n if (contentType.startsWith(\"application/json\")) {\n if (isValidJsonString(body)) {\n return Buffer.from(body);\n } else {\n return Buffer.from(JSON.stringify(body));\n }\n }\n if (contentType.startsWith(\"text/\") && typeof body === \"string\") {\n return Buffer.from(body);\n }\n } catch (error) {\n return;\n }\n}\n\nfunction isValidJsonString(body: any) {\n if (typeof body !== \"string\") {\n return false;\n }\n try {\n JSON.parse(body);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction matchPatterns(value: string, patterns: RegExp[]) {\n return patterns.some((pattern) => {\n return pattern.test(value);\n });\n}\n\nfunction skipEmptyValues<T extends Record<string, any>>(data: T) {\n return Object.fromEntries(\n Object.entries(data).filter(([_, v]) => {\n if (v == null || Number.isNaN(v)) return false;\n if (Array.isArray(v) || Buffer.isBuffer(v) || typeof v === \"string\") {\n return v.length > 0;\n }\n return true;\n }),\n ) as Partial<T>;\n}\n\nfunction checkWritableFs() {\n try {\n const testPath = join(tmpdir(), `apitally-${randomUUID()}`);\n writeFileSync(testPath, \"test\");\n unlinkSync(testPath);\n return true;\n } catch (error) {\n return false;\n }\n}\n","import type * as Sentry from \"@sentry/node\";\n\nlet sentry: typeof Sentry | undefined;\n\n// Initialize Sentry when the module is loaded\n(async () => {\n try {\n sentry = await import(\"@sentry/node\");\n } catch (e) {\n // Sentry SDK is not installed, ignore\n }\n})();\n\n/**\n * Returns the last Sentry event ID if available\n */\nexport function getSentryEventId(): string | undefined {\n if (sentry && sentry.lastEventId) {\n return sentry.lastEventId();\n }\n return undefined;\n}\n","import { createHash } from \"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 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","import { Buffer } from \"buffer\";\nimport { randomUUID } from \"crypto\";\nimport { createWriteStream, readFile, unlinkSync, WriteStream } from \"fs\";\nimport { tmpdir } from \"os\";\nimport { join } from \"path\";\nimport { createGzip, Gzip } from \"zlib\";\n\nexport default class TempGzipFile {\n public uuid: string;\n private filePath: string;\n private gzip: Gzip;\n private writeStream: WriteStream;\n private readyPromise: Promise<void>;\n private closedPromise: Promise<void>;\n\n constructor() {\n this.uuid = randomUUID();\n this.filePath = join(tmpdir(), `apitally-${this.uuid}.gz`);\n this.writeStream = createWriteStream(this.filePath);\n this.readyPromise = new Promise<void>((resolve, reject) => {\n this.writeStream.once(\"ready\", resolve);\n this.writeStream.once(\"error\", reject);\n });\n this.closedPromise = new Promise<void>((resolve, reject) => {\n this.writeStream.once(\"close\", resolve);\n this.writeStream.once(\"error\", reject);\n });\n this.gzip = createGzip();\n this.gzip.pipe(this.writeStream);\n }\n\n get size() {\n return this.writeStream.bytesWritten;\n }\n\n async writeLine(data: Buffer) {\n await this.readyPromise;\n return new Promise<void>((resolve, reject) => {\n this.gzip.write(Buffer.concat([data, Buffer.from(\"\\n\")]), (error) => {\n if (error) {\n reject(error);\n } else {\n resolve();\n }\n });\n });\n }\n\n async getContent() {\n return new Promise<Buffer>((resolve, reject) => {\n readFile(this.filePath, (error, data) => {\n if (error) {\n reject(error);\n } else {\n resolve(data);\n }\n });\n });\n }\n\n async close() {\n await new Promise<void>((resolve) => {\n this.gzip.end(() => {\n resolve();\n });\n });\n await this.closedPromise;\n }\n\n async delete() {\n await this.close();\n unlinkSync(this.filePath);\n }\n}\n","import { createHash } from \"crypto\";\n\nimport {\n ConsumerMethodPath,\n ValidationError,\n ValidationErrorsItem,\n} from \"./types.js\";\n\nexport default class ValidationErrorCounter {\n private errorCounts: Map<string, number>;\n private errorDetails: Map<string, ConsumerMethodPath & ValidationError>;\n\n constructor() {\n this.errorCounts = new Map();\n this.errorDetails = new Map();\n }\n\n public addValidationError(\n validationError: ConsumerMethodPath & ValidationError,\n ) {\n const key = this.getKey(validationError);\n if (!this.errorDetails.has(key)) {\n this.errorDetails.set(key, validationError);\n }\n this.errorCounts.set(key, (this.errorCounts.get(key) || 0) + 1);\n }\n\n public getAndResetValidationErrors() {\n const data: Array<ValidationErrorsItem> = [];\n this.errorCounts.forEach((count, key) => {\n const validationError = this.errorDetails.get(key);\n if (validationError) {\n data.push({\n consumer: validationError.consumer || null,\n method: validationError.method,\n path: validationError.path,\n loc: validationError.loc.split(\".\"),\n msg: validationError.msg,\n type: validationError.type,\n error_count: count,\n });\n }\n });\n this.errorCounts.clear();\n this.errorDetails.clear();\n return data;\n }\n\n private getKey(validationError: ConsumerMethodPath & ValidationError) {\n const hashInput = [\n validationError.consumer || \"\",\n validationError.method.toUpperCase(),\n validationError.path,\n validationError.loc,\n validationError.msg.trim(),\n validationError.type,\n ].join(\"|\");\n return createHash(\"md5\").update(hashInput).digest(\"hex\");\n }\n}\n","import { OutgoingHttpHeader } from \"http\";\n\nexport function parseContentLength(\n contentLength: OutgoingHttpHeader | undefined | null,\n): number | undefined {\n if (contentLength === undefined || contentLength === null) {\n return undefined;\n }\n if (typeof contentLength === \"number\") {\n return contentLength;\n }\n if (typeof contentLength === \"string\") {\n const parsed = parseInt(contentLength);\n return isNaN(parsed) ? undefined : parsed;\n }\n if (Array.isArray(contentLength)) {\n return parseContentLength(contentLength[0]);\n }\n return undefined;\n}\n\nexport function mergeHeaders(base: Headers, merge: Headers) {\n const mergedHeaders = new Headers(base);\n for (const [name, value] of merge)\n if (name === \"set-cookie\") mergedHeaders.append(name, value);\n else mergedHeaders.set(name, value);\n return mergedHeaders;\n}\n","export async function measureResponseSize(\n response: Response,\n): Promise<[number, Response]> {\n const [newResponse1, newResponse2] = await teeResponse(response);\n let size = 0;\n if (newResponse2.body) {\n let done = false;\n const reader = newResponse2.body.getReader();\n while (!done) {\n const result = await reader.read();\n done = result.done;\n if (!done && result.value) {\n size += result.value.byteLength;\n }\n }\n }\n return [size, newResponse1];\n}\n\nexport async function getResponseBody(\n response: Response,\n): Promise<[Buffer, Response]> {\n const [newResponse1, newResponse2] = await teeResponse(response);\n const responseBuffer = Buffer.from(await newResponse2.arrayBuffer());\n return [responseBuffer, newResponse1];\n}\n\nexport async function getResponseJson(\n response: Response,\n): Promise<[any, Response]> {\n const contentType = response.headers.get(\"content-type\");\n if (contentType?.includes(\"application/json\")) {\n const [newResponse1, newResponse2] = await teeResponse(response);\n const responseJson = await newResponse2.json();\n return [responseJson, newResponse1];\n }\n return [null, response];\n}\n\nexport async function teeResponse(\n response: Response,\n): Promise<[Response, Response]> {\n if (!response.body) {\n return [response, response];\n }\n const [stream1, stream2] = response.body.tee();\n const newResponse1 = new Response(stream1, {\n status: response.status,\n statusText: response.statusText,\n headers: response.headers,\n });\n const newResponse2 = new Response(stream2, {\n status: response.status,\n statusText: response.statusText,\n headers: response.headers,\n });\n return [newResponse1, newResponse2];\n}\n","import { createRequire } from \"module\";\n\nexport function getPackageVersion(name: string): string | null {\n const packageJsonPath = `${name}/package.json`;\n try {\n return require(packageJsonPath).version || null;\n } catch (error) {\n try {\n const _require = createRequire(import.meta.url);\n return _require(packageJsonPath).version || null;\n } catch (error) {\n return null;\n }\n }\n}\n","import { H3Core } from \"h3\";\n\nimport { getPackageVersion } from \"../common/packageVersions.js\";\n\nexport function getAppInfo(h3: H3Core, appVersion?: string) {\n const versions: Array<[string, string]> = [];\n if (process.versions.node) {\n versions.push([\"nodejs\", process.versions.node]);\n }\n if (process.versions.bun) {\n versions.push([\"bun\", process.versions.bun]);\n }\n const h3Version = getPackageVersion(\"h3\");\n const apitallyVersion = getPackageVersion(\"../..\");\n if (h3Version) {\n versions.push([\"h3\", h3Version]);\n }\n if (apitallyVersion) {\n versions.push([\"apitally\", apitallyVersion]);\n }\n if (appVersion) {\n versions.push([\"app\", appVersion]);\n }\n\n return {\n paths: h3._routes\n .map((route) => ({\n method: route.method || \"\",\n path: route.route || \"\",\n }))\n .filter(\n (route) =>\n route.method &&\n route.path &&\n ![\"HEAD\", \"OPTIONS\"].includes(route.method.toUpperCase()),\n ),\n versions: Object.fromEntries(versions),\n client: \"js:h3\",\n };\n}\n"],"mappings":"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","names":["import_crypto","consumerFromStringOrObject","consumer","_a","String","trim","substring","identifier","name","group","ConsumerRegistry","consumers","updated","Map","Set","addOrUpdateConsumer","existing","get","set","add","getAndResetUpdatedConsumers","data","forEach","push","clear","getLogger","createLogger","level","process","env","APITALLY_DEBUG","format","combine","colorize","timestamp","printf","info","message","transports","Console","isValidClientId","clientId","regexExp","test","isValidEnv","env","RequestCounter","requestCounts","requestSizeSums","responseSizeSums","responseTimes","requestSizes","responseSizes","Map","getKey","requestInfo","consumer","method","toUpperCase","path","statusCode","join","addRequest","key","set","get","has","responseTimeMap","responseTimeMsBin","Math","floor","responseTime","requestSize","undefined","Number","requestSizeMap","requestSizeKbBin","responseSize","responseSizeMap","responseSizeKbBin","getAndResetRequests","data","forEach","count","statusCodeStr","split","push","status_code","parseInt","request_count","request_size_sum","response_size_sum","response_times","Object","fromEntries","request_sizes","response_sizes","clear","import_buffer","import_crypto","import_fs","import_os","import_path","sentry","e","getSentryEventId","lastEventId","undefined","MAX_MSG_LENGTH","MAX_STACKTRACE_LENGTH","ServerErrorCounter","errorCounts","errorDetails","sentryEventIds","Map","addServerError","serverError","key","getKey","has","set","get","sentryEventId","getSentryEventId","getAndResetServerErrors","data","forEach","count","push","consumer","method","path","type","msg","truncateExceptionMessage","traceback","truncateExceptionStackTrace","sentry_event_id","error_count","clear","hashInput","toUpperCase","trim","join","createHash","update","digest","length","suffix","cutoff","substring","stack","lines","split","truncatedLines","line","import_crypto","TempGzipFile","uuid","filePath","gzip","writeStream","readyPromise","closedPromise","randomUUID","join","tmpdir","createWriteStream","Promise","resolve","reject","once","createGzip","pipe","size","bytesWritten","writeLine","data","write","Buffer","concat","from","error","getContent","readFile","close","end","delete","unlinkSync","MAX_BODY_SIZE","MAX_FILE_SIZE","MAX_FILES","MAX_PENDING_WRITES","BODY_TOO_LARGE","Buffer","from","BODY_MASKED","MASKED","ALLOWED_CONTENT_TYPES","EXCLUDE_PATH_PATTERNS","EXCLUDE_USER_AGENT_PATTERNS","MASK_QUERY_PARAM_PATTERNS","MASK_HEADER_PATTERNS","MASK_BODY_FIELD_PATTERNS","DEFAULT_CONFIG","enabled","logQueryParams","logRequestHeaders","logRequestBody","logResponseHeaders","logResponseBody","logException","maskQueryParams","maskHeaders","maskBodyFields","excludePaths","RequestLogger","config","suspendUntil","pendingWrites","currentFile","files","maintainIntervalId","lock","AsyncLock","checkWritableFs","setInterval","maintain","maxBodySize","shouldExcludePath","urlPath","patterns","matchPatterns","shouldExcludeUserAgent","userAgent","shouldMaskQueryParam","name","shouldMaskHeader","shouldMaskBodyField","hasSupportedContentType","headers","_a","contentType","find","k","toLowerCase","isSupportedContentType","hasJsonContentType","test","some","t","startsWith","search","params","URLSearchParams","key","set","toString","map","v","maskBody","data","Array","isArray","result","value","Object","entries","item","applyMasking","maskRequestBodyCallback","request","body","maskedBody","undefined","maskResponseBodyCallback","response","length","bodyData","hasJsonContent","parsedBody","JSON","parse","stringify","url","URL","logRequest","error","path","pathname","excludeCallback","size","uuid","randomUUID","exception","type","message","truncateExceptionMessage","stacktrace","truncateExceptionStackTrace","stack","sentryEventId","getSentryEventId","push","shift","writeToFile","acquire","TempGzipFile","finalItem","skipEmptyValues","forEach","toJSON","writeLine","getFile","retryFileLater","file","unshift","rotateFile","close","delete","Date","now","clear","clearInterval","convertHeaders","Headers","flatMap","matchPatterns","value","patterns","some","pattern","test","skipEmptyValues","data","Object","fromEntries","entries","filter","_","v","Number","isNaN","Array","isArray","Buffer","isBuffer","length","checkWritableFs","testPath","join","tmpdir","randomUUID","writeFileSync","unlinkSync","error","import_crypto","ValidationErrorCounter","errorCounts","errorDetails","Map","addValidationError","validationError","key","getKey","has","set","get","getAndResetValidationErrors","data","forEach","count","push","consumer","method","path","loc","split","msg","type","error_count","clear","hashInput","toUpperCase","trim","join","createHash","update","digest","SYNC_INTERVAL","INITIAL_SYNC_INTERVAL","INITIAL_SYNC_INTERVAL_DURATION","MAX_QUEUE_TIME","HTTPError","Error","response","reason","status","ApitallyClient","clientId","env","instanceUuid","syncDataQueue","syncIntervalId","startupData","startupDataSent","enabled","requestCounter","requestLogger","validationErrorCounter","serverErrorCounter","consumerRegistry","logger","requestLogging","requestLoggingConfig","instance","isValidClientId","isValidEnv","console","warn","randomUUID","RequestCounter","RequestLogger","ValidationErrorCounter","ServerErrorCounter","ConsumerRegistry","getLogger","startSync","handleShutdown","bind","getInstance","isEnabled","shutdown","stopSync","sendSyncData","sendLogData","close","undefined","getHubUrlPrefix","baseURL","process","APITALLY_HUB_BASE_URL","version","sendData","url","payload","fetchWithRetry","fetchRetry","fetch","retries","retryDelay","retryOn","method","body","JSON","stringify","headers","ok","sync","setInterval","setTimeout","clearInterval","promises","push","sendStartupData","Promise","all","error","setStartupData","data","debug","instance_uuid","message_uuid","handled","handleHubError","message","newPayload","timestamp","Date","now","requests","getAndResetRequests","validation_errors","getAndResetValidationErrors","server_errors","getAndResetServerErrors","consumers","getAndResetUpdatedConsumers","i","length","shift","randomDelay","rotateFile","logFile","getFile","uuid","getContent","has","retryAfter","parseInt","get","suspendUntil","clear","delete","retryFileLater","delay","Math","random","resolve","parseContentLength","contentLength","undefined","parsed","parseInt","isNaN","Array","isArray","mergeHeaders","base","merge","mergedHeaders","Headers","name","value","append","set","measureResponseSize","response","newResponse1","newResponse2","teeResponse","size","body","done","reader","getReader","result","read","value","byteLength","getResponseBody","responseBuffer","Buffer","from","arrayBuffer","teeResponse","response","body","stream1","stream2","tee","newResponse1","Response","status","statusText","headers","newResponse2","getPackageVersion","name","packageJsonPath","require","version","error","_require","createRequire","url","getAppInfo","h3","appVersion","versions","process","node","push","bun","h3Version","getPackageVersion","apitallyVersion","paths","_routes","map","route","method","path","filter","includes","toUpperCase","Object","fromEntries","client","jsonHeaders","Headers","apitallyPlugin","definePlugin","app","config","client","ApitallyClient","setStartupData","attempt","appInfo","getAppInfo","appVersion","paths","length","setTimeout","handleResponse","event","response","error","_a","req","method","toUpperCase","startTime","context","_apitallyRequestTimestamp","responseTime","performance","now","path","matchedRoute","route","statusCode","status","requestSize","parseContentLength","headers","get","responseSize","newResponse","measureResponseSize","consumer","getConsumer","consumerRegistry","addOrUpdateConsumer","requestCounter","addRequest","identifier","data","name","zodError","issues","forEach","issue","validationErrorCounter","addValidationError","loc","join","msg","message","type","code","serverErrorCounter","addServerError","traceback","stack","requestLogger","enabled","responseHeaders","mergeHeaders","responseContentType","responseBody","logResponseBody","isSupportedContentType","getResponseBody","Buffer","from","JSON","stringify","toJSON","logRequest","timestamp","Date","url","convertHeaders","Object","fromEntries","entries","size","Number","body","_apitallyRequestBody","use","onRequest","requestContentType","logRequestBody","maxBodySize","clonedRequest","clone","requestBody","arrayBuffer","onResponse","isEnabled","undefined","onError","setConsumer","apitallyConsumer","consumerFromStringOrObject"]}
package/dist/h3/plugin.js CHANGED
@@ -829,7 +829,7 @@ var _ApitallyClient = class _ApitallyClient {
829
829
  serverErrorCounter;
830
830
  consumerRegistry;
831
831
  logger;
832
- constructor({ clientId, env = "dev", requestLoggingConfig, logger }) {
832
+ constructor({ clientId, env = "dev", requestLogging, requestLoggingConfig, logger }) {
833
833
  if (_ApitallyClient.instance) {
834
834
  throw new Error("Apitally client is already initialized");
835
835
  }
@@ -839,17 +839,20 @@ var _ApitallyClient = class _ApitallyClient {
839
839
  if (!isValidEnv(env)) {
840
840
  throw new Error(`Invalid env '${env}' (expecting 1-32 alphanumeric lowercase characters and hyphens only)`);
841
841
  }
842
+ if (requestLoggingConfig && !requestLogging) {
843
+ console.warn("requestLoggingConfig is deprecated, use requestLogging instead.");
844
+ }
842
845
  _ApitallyClient.instance = this;
843
846
  this.clientId = clientId;
844
847
  this.env = env;
845
848
  this.instanceUuid = randomUUID3();
846
849
  this.syncDataQueue = [];
847
850
  this.requestCounter = new RequestCounter();
848
- this.requestLogger = new RequestLogger(requestLoggingConfig);
851
+ this.requestLogger = new RequestLogger(requestLogging ?? requestLoggingConfig);
849
852
  this.validationErrorCounter = new ValidationErrorCounter();
850
853
  this.serverErrorCounter = new ServerErrorCounter();
851
854
  this.consumerRegistry = new ConsumerRegistry();
852
- this.logger = logger || getLogger();
855
+ this.logger = logger ?? getLogger();
853
856
  this.startSync();
854
857
  this.handleShutdown = this.handleShutdown.bind(this);
855
858
  }
@@ -1172,7 +1175,6 @@ __name(getPackageVersion, "getPackageVersion");
1172
1175
 
1173
1176
  // src/h3/utils.ts
1174
1177
  function getAppInfo(h3, appVersion) {
1175
- const routes = h3._routes ? listAllRoutes(h3._routes.root) : [];
1176
1178
  const versions = [];
1177
1179
  if (process.versions.node) {
1178
1180
  versions.push([
@@ -1207,46 +1209,18 @@ function getAppInfo(h3, appVersion) {
1207
1209
  ]);
1208
1210
  }
1209
1211
  return {
1210
- paths: routes.map((route) => ({
1212
+ paths: h3._routes.map((route) => ({
1211
1213
  method: route.method || "",
1212
1214
  path: route.route || ""
1213
- })).filter((route) => route.method && route.path),
1215
+ })).filter((route) => route.method && route.path && ![
1216
+ "HEAD",
1217
+ "OPTIONS"
1218
+ ].includes(route.method.toUpperCase())),
1214
1219
  versions: Object.fromEntries(versions),
1215
1220
  client: "js:h3"
1216
1221
  };
1217
1222
  }
1218
1223
  __name(getAppInfo, "getAppInfo");
1219
- function listAllRoutes(node) {
1220
- const routes = [];
1221
- _collectAllRoutes(node, routes);
1222
- return routes;
1223
- }
1224
- __name(listAllRoutes, "listAllRoutes");
1225
- function _collectAllRoutes(node, routes = []) {
1226
- if (node.methods) {
1227
- for (const methodData of Object.values(node.methods)) {
1228
- if (Array.isArray(methodData)) {
1229
- for (const item of methodData) {
1230
- if (item.data) {
1231
- routes.push(item.data);
1232
- }
1233
- }
1234
- }
1235
- }
1236
- }
1237
- if (node.static) {
1238
- for (const staticChild of Object.values(node.static)) {
1239
- _collectAllRoutes(staticChild, routes);
1240
- }
1241
- }
1242
- if (node.param) {
1243
- _collectAllRoutes(node.param, routes);
1244
- }
1245
- if (node.wildcard) {
1246
- _collectAllRoutes(node.wildcard, routes);
1247
- }
1248
- }
1249
- __name(_collectAllRoutes, "_collectAllRoutes");
1250
1224
 
1251
1225
  // src/h3/plugin.ts
1252
1226
  var jsonHeaders = new Headers({
@@ -1265,6 +1239,9 @@ var apitallyPlugin = definePlugin((app, config) => {
1265
1239
  setTimeout(() => setStartupData(), 500);
1266
1240
  const handleResponse = /* @__PURE__ */ __name(async (event, response, error) => {
1267
1241
  var _a2, _b;
1242
+ if (event.req.method.toUpperCase() === "OPTIONS") {
1243
+ return response;
1244
+ }
1268
1245
  const startTime = event.context._apitallyRequestTimestamp;
1269
1246
  const responseTime = startTime ? performance.now() - startTime : 0;
1270
1247
  const path = (_a2 = event.context.matchedRoute) == null ? void 0 : _a2.route;