apitally 0.23.1 → 0.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adonisjs/index.cjs +3 -0
- package/dist/adonisjs/index.cjs.map +1 -1
- package/dist/adonisjs/index.d.cts +2 -0
- package/dist/adonisjs/index.d.ts +2 -0
- package/dist/adonisjs/index.js +2 -0
- package/dist/adonisjs/index.js.map +1 -1
- package/dist/adonisjs/middleware.cjs +6 -2
- package/dist/adonisjs/middleware.cjs.map +1 -1
- package/dist/adonisjs/middleware.d.cts +2 -0
- package/dist/adonisjs/middleware.d.ts +2 -0
- package/dist/adonisjs/middleware.js +6 -2
- package/dist/adonisjs/middleware.js.map +1 -1
- package/dist/adonisjs/provider.d.cts +2 -0
- package/dist/adonisjs/provider.d.ts +2 -0
- package/dist/adonisjs/stubs/config/apitally.stub +1 -0
- package/dist/common/client.cjs +6 -1
- package/dist/common/client.cjs.map +1 -1
- package/dist/common/client.d.cts +3 -0
- package/dist/common/client.d.ts +3 -0
- package/dist/common/client.js +6 -1
- package/dist/common/client.js.map +1 -1
- package/dist/common/consumerRegistry.d.cts +2 -0
- package/dist/common/consumerRegistry.d.ts +2 -0
- package/dist/common/instance.cjs +158 -0
- package/dist/common/instance.cjs.map +1 -0
- package/dist/common/instance.d.cts +4 -0
- package/dist/common/instance.d.ts +4 -0
- package/dist/common/instance.js +134 -0
- package/dist/common/instance.js.map +1 -0
- package/dist/common/requestCounter.d.cts +2 -0
- package/dist/common/requestCounter.d.ts +2 -0
- package/dist/common/requestLogger.cjs +23 -19
- package/dist/common/requestLogger.cjs.map +1 -1
- package/dist/common/requestLogger.d.cts +6 -1
- package/dist/common/requestLogger.d.ts +6 -1
- package/dist/common/requestLogger.js +23 -19
- package/dist/common/requestLogger.js.map +1 -1
- package/dist/common/response.cjs +2 -2
- package/dist/common/response.cjs.map +1 -1
- package/dist/common/response.js +2 -2
- package/dist/common/response.js.map +1 -1
- package/dist/common/serverErrorCounter.cjs +3 -0
- package/dist/common/serverErrorCounter.cjs.map +1 -1
- package/dist/common/serverErrorCounter.d.cts +2 -0
- package/dist/common/serverErrorCounter.d.ts +2 -0
- package/dist/common/serverErrorCounter.js +3 -0
- package/dist/common/serverErrorCounter.js.map +1 -1
- package/dist/common/spanCollector.cjs +217 -0
- package/dist/common/spanCollector.cjs.map +1 -0
- package/dist/common/spanCollector.d.cts +50 -0
- package/dist/common/spanCollector.d.ts +50 -0
- package/dist/common/spanCollector.js +194 -0
- package/dist/common/spanCollector.js.map +1 -0
- package/dist/common/tempGzipFile.cjs +25 -2
- package/dist/common/tempGzipFile.cjs.map +1 -1
- package/dist/common/tempGzipFile.d.cts +3 -2
- package/dist/common/tempGzipFile.d.ts +3 -2
- package/dist/common/tempGzipFile.js +22 -3
- package/dist/common/tempGzipFile.js.map +1 -1
- package/dist/common/types.d.cts +2 -0
- package/dist/common/types.d.ts +2 -0
- package/dist/common/validationErrorCounter.d.cts +2 -0
- package/dist/common/validationErrorCounter.d.ts +2 -0
- package/dist/elysia/index.cjs +3 -0
- package/dist/elysia/index.cjs.map +1 -1
- package/dist/elysia/index.d.cts +2 -0
- package/dist/elysia/index.d.ts +2 -0
- package/dist/elysia/index.js +2 -0
- package/dist/elysia/index.js.map +1 -1
- package/dist/elysia/plugin.cjs +16 -8
- package/dist/elysia/plugin.cjs.map +1 -1
- package/dist/elysia/plugin.d.cts +4 -0
- package/dist/elysia/plugin.d.ts +4 -0
- package/dist/elysia/plugin.js +16 -8
- package/dist/elysia/plugin.js.map +1 -1
- package/dist/elysia/utils.d.cts +2 -0
- package/dist/elysia/utils.d.ts +2 -0
- package/dist/express/index.cjs +3 -0
- package/dist/express/index.cjs.map +1 -1
- package/dist/express/index.d.cts +2 -0
- package/dist/express/index.d.ts +2 -0
- package/dist/express/index.js +2 -0
- package/dist/express/index.js.map +1 -1
- package/dist/express/middleware.cjs +85 -77
- package/dist/express/middleware.cjs.map +1 -1
- package/dist/express/middleware.d.cts +2 -0
- package/dist/express/middleware.d.ts +2 -0
- package/dist/express/middleware.js +85 -77
- package/dist/express/middleware.js.map +1 -1
- package/dist/fastify/index.cjs +3 -0
- package/dist/fastify/index.cjs.map +1 -1
- package/dist/fastify/index.d.cts +2 -0
- package/dist/fastify/index.d.ts +2 -0
- package/dist/fastify/index.js +2 -0
- package/dist/fastify/index.js.map +1 -1
- package/dist/fastify/plugin.cjs +15 -6
- package/dist/fastify/plugin.cjs.map +1 -1
- package/dist/fastify/plugin.d.cts +4 -0
- package/dist/fastify/plugin.d.ts +4 -0
- package/dist/fastify/plugin.js +15 -6
- package/dist/fastify/plugin.js.map +1 -1
- package/dist/h3/index.cjs +3 -0
- package/dist/h3/index.cjs.map +1 -1
- package/dist/h3/index.d.cts +2 -0
- package/dist/h3/index.d.ts +2 -0
- package/dist/h3/index.js +2 -0
- package/dist/h3/index.js.map +1 -1
- package/dist/h3/plugin.cjs +15 -7
- package/dist/h3/plugin.cjs.map +1 -1
- package/dist/h3/plugin.d.cts +4 -0
- package/dist/h3/plugin.d.ts +4 -0
- package/dist/h3/plugin.js +15 -7
- package/dist/h3/plugin.js.map +1 -1
- package/dist/hapi/index.cjs +3 -0
- package/dist/hapi/index.cjs.map +1 -1
- package/dist/hapi/index.d.cts +2 -0
- package/dist/hapi/index.d.ts +2 -0
- package/dist/hapi/index.js +2 -0
- package/dist/hapi/index.js.map +1 -1
- package/dist/hapi/plugin.cjs +16 -9
- package/dist/hapi/plugin.cjs.map +1 -1
- package/dist/hapi/plugin.d.cts +4 -0
- package/dist/hapi/plugin.d.ts +4 -0
- package/dist/hapi/plugin.js +16 -9
- package/dist/hapi/plugin.js.map +1 -1
- package/dist/hapi/utils.d.cts +2 -0
- package/dist/hapi/utils.d.ts +2 -0
- package/dist/hono/index.cjs +3 -0
- package/dist/hono/index.cjs.map +1 -1
- package/dist/hono/index.d.cts +2 -0
- package/dist/hono/index.d.ts +2 -0
- package/dist/hono/index.js +2 -0
- package/dist/hono/index.js.map +1 -1
- package/dist/hono/middleware.cjs +6 -2
- package/dist/hono/middleware.cjs.map +1 -1
- package/dist/hono/middleware.d.cts +2 -0
- package/dist/hono/middleware.d.ts +2 -0
- package/dist/hono/middleware.js +6 -2
- package/dist/hono/middleware.js.map +1 -1
- package/dist/hono/utils.d.cts +2 -0
- package/dist/hono/utils.d.ts +2 -0
- package/dist/koa/index.cjs +3 -0
- package/dist/koa/index.cjs.map +1 -1
- package/dist/koa/index.d.cts +2 -0
- package/dist/koa/index.d.ts +2 -0
- package/dist/koa/index.js +2 -0
- package/dist/koa/index.js.map +1 -1
- package/dist/koa/middleware.cjs +8 -4
- package/dist/koa/middleware.cjs.map +1 -1
- package/dist/koa/middleware.d.cts +2 -0
- package/dist/koa/middleware.d.ts +2 -0
- package/dist/koa/middleware.js +8 -4
- package/dist/koa/middleware.js.map +1 -1
- package/dist/loggers/console.d.cts +4 -0
- package/dist/loggers/console.d.ts +4 -0
- package/dist/loggers/hapi.d.cts +4 -0
- package/dist/loggers/hapi.d.ts +4 -0
- package/dist/loggers/index.d.cts +4 -0
- package/dist/loggers/index.d.ts +4 -0
- package/dist/loggers/nestjs.d.cts +4 -0
- package/dist/loggers/nestjs.d.ts +4 -0
- package/dist/loggers/pino.cjs +1 -1
- package/dist/loggers/pino.cjs.map +1 -1
- package/dist/loggers/pino.d.cts +4 -0
- package/dist/loggers/pino.d.ts +4 -0
- package/dist/loggers/pino.js +1 -1
- package/dist/loggers/pino.js.map +1 -1
- package/dist/loggers/winston.d.cts +4 -0
- package/dist/loggers/winston.d.ts +4 -0
- package/dist/nestjs/index.cjs +3 -0
- package/dist/nestjs/index.cjs.map +1 -1
- package/dist/nestjs/index.d.cts +2 -0
- package/dist/nestjs/index.d.ts +2 -0
- package/dist/nestjs/index.js +2 -0
- package/dist/nestjs/index.js.map +1 -1
- package/package.json +6 -3
package/dist/hapi/plugin.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/hapi/plugin.ts"],"sourcesContent":["import type { Request, Server } from \"@hapi/hapi\";\nimport { AsyncLocalStorage } from \"node:async_hooks\";\nimport { performance } from \"node:perf_hooks\";\n\nimport { ApitallyClient } from \"../common/client.js\";\nimport { consumerFromStringOrObject } from \"../common/consumerRegistry.js\";\nimport type { LogRecord } from \"../common/requestLogger.js\";\nimport { convertHeaders } from \"../common/requestLogger.js\";\nimport { ApitallyConfig, ApitallyConsumer } from \"../common/types.js\";\nimport {\n handleHapiRequestEvent,\n patchConsole,\n patchPinoLogger,\n patchWinston,\n} from \"../loggers/index.js\";\nimport { getAppInfo, isBoom } from \"./utils.js\";\n\nconst START_TIME_SYMBOL = Symbol(\"apitally.startTime\");\nconst REQUEST_BODY_SYMBOL = Symbol(\"apitally.requestBody\");\nconst REQUEST_SIZE_SYMBOL = Symbol(\"apitally.requestSize\");\nconst RESPONSE_BODY_SYMBOL = Symbol(\"apitally.responseBody\");\nconst RESPONSE_SIZE_SYMBOL = Symbol(\"apitally.responseSize\");\nconst LOGS_SYMBOL = Symbol(\"apitally.logs\");\n\ndeclare module \"@hapi/hapi\" {\n interface Request {\n [START_TIME_SYMBOL]?: number;\n [REQUEST_BODY_SYMBOL]?: Buffer;\n [REQUEST_SIZE_SYMBOL]?: number;\n [RESPONSE_BODY_SYMBOL]?: Buffer;\n [RESPONSE_SIZE_SYMBOL]?: number;\n [LOGS_SYMBOL]?: LogRecord[];\n apitallyConsumer?: ApitallyConsumer | string;\n }\n\n interface ResponseObject {\n readonly contentType: string | null; // Missing in Hapi types\n }\n}\n\nexport default function apitallyPlugin(config: ApitallyConfig) {\n const client = new ApitallyClient(config);\n const logsContext = new AsyncLocalStorage<LogRecord[]>();\n let pinoLoggerPatched = false;\n\n if (client.requestLogger.enabled && client.requestLogger.config.captureLogs) {\n patchConsole(logsContext);\n patchWinston(logsContext);\n }\n\n return {\n name: \"apitally\",\n register: async function (server: Server) {\n server.ext(\"onPostStart\", async () => {\n if (\n \"logger\" in server &&\n client.requestLogger.enabled &&\n client.requestLogger.config.captureLogs\n ) {\n pinoLoggerPatched = await patchPinoLogger(\n (server as any).logger,\n logsContext,\n );\n }\n });\n\n server.ext(\"onPostStart\", () => {\n const appInfo = getAppInfo(server, config.appVersion);\n client.setStartupData(appInfo);\n client.startSync();\n });\n\n server.ext(\"onPreStop\", async () => {\n await client.handleShutdown();\n });\n\n server.events.on(\"request\", (_, event) => {\n if (\n !pinoLoggerPatched &&\n client.requestLogger.enabled &&\n client.requestLogger.config.captureLogs &&\n event.channel === \"app\"\n ) {\n handleHapiRequestEvent(event, logsContext);\n }\n });\n\n server.ext(\"onRequest\", async (request, h) => {\n if (!client.isEnabled() || request.method.toUpperCase() === \"OPTIONS\") {\n return h.continue;\n }\n\n request[START_TIME_SYMBOL] = performance.now();\n\n // Patch the lifecycle function to run with the logs context\n const lifecycle = (request as any)._lifecycle.bind(request);\n const logs: LogRecord[] = [];\n request[LOGS_SYMBOL] = logs;\n (request as any)._lifecycle = () => logsContext.run(logs, lifecycle);\n\n const captureRequestBody =\n client.requestLogger.enabled &&\n client.requestLogger.config.logRequestBody &&\n client.requestLogger.isSupportedContentType(\n request.headers[\"content-type\"],\n );\n const chunks: Buffer[] = [];\n let size = 0;\n request.events.on(\"peek\", (chunk: string, encoding: string) => {\n if (captureRequestBody) {\n chunks.push(Buffer.from(chunk, encoding as BufferEncoding));\n }\n size += Buffer.byteLength(chunk, encoding as BufferEncoding);\n });\n request.events.once(\"finish\", () => {\n if (chunks.length > 0) {\n request[REQUEST_BODY_SYMBOL] = Buffer.concat(chunks);\n }\n request[REQUEST_SIZE_SYMBOL] = size;\n });\n\n return h.continue;\n });\n\n server.ext(\"onPreResponse\", async (request, h) => {\n if (\n !client.isEnabled() ||\n request.method.toUpperCase() === \"OPTIONS\" ||\n isBoom(request.response)\n ) {\n return h.continue;\n }\n\n const captureResponseBody =\n client.requestLogger.enabled &&\n client.requestLogger.config.logResponseBody &&\n client.requestLogger.isSupportedContentType(\n request.response.contentType,\n );\n const chunks: Buffer[] = [];\n let size = 0;\n request.response.events.on(\n \"peek\",\n (chunk: string, encoding: string) => {\n if (captureResponseBody) {\n chunks.push(Buffer.from(chunk, encoding as BufferEncoding));\n }\n size += Buffer.byteLength(chunk, encoding as BufferEncoding);\n },\n );\n request.response.events.once(\"finish\", () => {\n if (chunks.length > 0) {\n request[RESPONSE_BODY_SYMBOL] = Buffer.concat(chunks);\n }\n request[RESPONSE_SIZE_SYMBOL] = size;\n });\n\n return h.continue;\n });\n\n server.ext(\"onPostResponse\", async (request, h) => {\n if (!client.isEnabled() || request.method.toUpperCase() === \"OPTIONS\") {\n return h.continue;\n }\n\n const startTime = request[START_TIME_SYMBOL];\n const responseTime = startTime ? performance.now() - startTime : 0;\n const timestamp = (Date.now() - responseTime) / 1000;\n const requestBody = request[REQUEST_BODY_SYMBOL];\n const requestSize = request[REQUEST_SIZE_SYMBOL];\n const response = request.response;\n let statusCode: number;\n let responseHeaders: Record<string, any>;\n let responseBody = request[RESPONSE_BODY_SYMBOL];\n let responseSize = request[RESPONSE_SIZE_SYMBOL];\n const error =\n (response as any)._error instanceof Error\n ? (response as any)._error\n : undefined;\n\n if (isBoom(response)) {\n // Handle Boom error object\n statusCode = response.output?.statusCode ?? 500;\n responseHeaders = response.output?.headers ?? {};\n } else {\n // Handle normal ResponseObject\n statusCode = response.statusCode ?? 200;\n responseHeaders = response.headers ?? {};\n }\n\n if (\n !responseBody &&\n (response as any)._payload &&\n client.requestLogger.enabled &&\n client.requestLogger.config.logResponseBody &&\n (isBoom(response) ||\n client.requestLogger.isSupportedContentType(response.contentType))\n ) {\n const responsePayload = (response as any)._payload;\n if (\n responsePayload &&\n responsePayload._data &&\n responsePayload._encoding &&\n typeof responsePayload._data === \"string\" &&\n typeof responsePayload._encoding === \"string\"\n ) {\n responseBody = Buffer.from(\n responsePayload._data,\n responsePayload._encoding as BufferEncoding,\n );\n }\n }\n\n if (!responseSize && responseBody) {\n responseSize = responseBody.length;\n }\n\n const consumer = request.apitallyConsumer\n ? consumerFromStringOrObject(request.apitallyConsumer)\n : null;\n client.consumerRegistry.addOrUpdateConsumer(consumer);\n\n if (request.route.path) {\n client.requestCounter.addRequest({\n consumer: consumer?.identifier,\n method: request.method,\n path: request.route.path,\n statusCode,\n responseTime,\n requestSize,\n responseSize,\n });\n\n if (statusCode === 500 && error) {\n client.serverErrorCounter.addServerError({\n consumer: consumer?.identifier,\n method: request.method,\n path: request.route.path,\n type: error.name,\n msg: error.message,\n traceback: error.stack || \"\",\n });\n }\n }\n\n if (client.requestLogger.enabled) {\n const logs = request[LOGS_SYMBOL];\n client.requestLogger.logRequest(\n {\n timestamp,\n consumer: consumer?.identifier,\n method: request.method,\n path: request.route.path,\n url: request.url?.href || \"\",\n headers: convertHeaders(request.headers),\n size: requestSize,\n body: requestBody,\n },\n {\n statusCode,\n responseTime: responseTime / 1000,\n headers: convertHeaders(responseHeaders),\n size: responseSize,\n body: responseBody,\n },\n error,\n logs,\n );\n }\n\n return h.continue;\n });\n },\n };\n}\n\nexport function setConsumer(\n request: Request,\n consumer: ApitallyConsumer | string | null | undefined,\n) {\n request.apitallyConsumer = consumer || undefined;\n}\n"],"mappings":"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","names":["AsyncLocalStorage","performance","ApitallyClient","consumerFromStringOrObject","convertHeaders","handleHapiRequestEvent","patchConsole","patchPinoLogger","patchWinston","getAppInfo","isBoom","START_TIME_SYMBOL","Symbol","REQUEST_BODY_SYMBOL","REQUEST_SIZE_SYMBOL","RESPONSE_BODY_SYMBOL","RESPONSE_SIZE_SYMBOL","LOGS_SYMBOL","config","client","logsContext","pinoLoggerPatched","requestLogger","enabled","captureLogs","name","register","server","ext","logger","appInfo","appVersion","setStartupData","startSync","handleShutdown","events","on","_","event","channel","request","h","isEnabled","method","toUpperCase","continue","now","lifecycle","_lifecycle","bind","logs","run","captureRequestBody","logRequestBody","isSupportedContentType","headers","chunks","size","chunk","encoding","push","Buffer","from","byteLength","once","length","concat","response","captureResponseBody","logResponseBody","contentType","startTime","responseTime","timestamp","Date","requestBody","requestSize","statusCode","responseHeaders","responseBody","responseSize","error","_error","Error","undefined","output","_payload","responsePayload","_data","_encoding","consumer","apitallyConsumer","consumerRegistry","addOrUpdateConsumer","route","path","requestCounter","addRequest","identifier","serverErrorCounter","addServerError","type","msg","message","traceback","stack","logRequest","url","href","body","apitallyPlugin","setConsumer"]}
|
|
1
|
+
{"version":3,"sources":["../../src/hapi/plugin.ts"],"sourcesContent":["import type { Request, Server } from \"@hapi/hapi\";\nimport { AsyncLocalStorage } from \"node:async_hooks\";\nimport { performance } from \"node:perf_hooks\";\n\nimport { ApitallyClient } from \"../common/client.js\";\nimport { consumerFromStringOrObject } from \"../common/consumerRegistry.js\";\nimport type { LogRecord } from \"../common/requestLogger.js\";\nimport { convertHeaders } from \"../common/requestLogger.js\";\nimport type { SpanHandle } from \"../common/spanCollector.js\";\nimport { ApitallyConfig, ApitallyConsumer } from \"../common/types.js\";\nimport {\n handleHapiRequestEvent,\n patchConsole,\n patchPinoLogger,\n patchWinston,\n} from \"../loggers/index.js\";\nimport { getAppInfo, isBoom } from \"./utils.js\";\n\nconst START_TIME_SYMBOL = Symbol(\"apitally.startTime\");\nconst REQUEST_BODY_SYMBOL = Symbol(\"apitally.requestBody\");\nconst REQUEST_SIZE_SYMBOL = Symbol(\"apitally.requestSize\");\nconst RESPONSE_BODY_SYMBOL = Symbol(\"apitally.responseBody\");\nconst RESPONSE_SIZE_SYMBOL = Symbol(\"apitally.responseSize\");\nconst LOGS_SYMBOL = Symbol(\"apitally.logs\");\nconst SPAN_HANDLE_SYMBOL = Symbol(\"apitally.spanHandle\");\n\ndeclare module \"@hapi/hapi\" {\n interface Request {\n [START_TIME_SYMBOL]?: number;\n [REQUEST_BODY_SYMBOL]?: Buffer;\n [REQUEST_SIZE_SYMBOL]?: number;\n [RESPONSE_BODY_SYMBOL]?: Buffer;\n [RESPONSE_SIZE_SYMBOL]?: number;\n [LOGS_SYMBOL]?: LogRecord[];\n [SPAN_HANDLE_SYMBOL]?: SpanHandle;\n apitallyConsumer?: ApitallyConsumer | string;\n }\n\n interface ResponseObject {\n readonly contentType: string | null; // Missing in Hapi types\n }\n}\n\nexport default function apitallyPlugin(config: ApitallyConfig) {\n const client = new ApitallyClient(config);\n const logsContext = new AsyncLocalStorage<LogRecord[]>();\n let pinoLoggerPatched = false;\n\n if (client.requestLogger.enabled && client.requestLogger.config.captureLogs) {\n patchConsole(logsContext);\n patchWinston(logsContext);\n }\n\n return {\n name: \"apitally\",\n register: async function (server: Server) {\n server.ext(\"onPostStart\", async () => {\n if (\n \"logger\" in server &&\n client.requestLogger.enabled &&\n client.requestLogger.config.captureLogs\n ) {\n pinoLoggerPatched = await patchPinoLogger(\n (server as any).logger,\n logsContext,\n );\n }\n });\n\n server.ext(\"onPostStart\", () => {\n const appInfo = getAppInfo(server, config.appVersion);\n client.setStartupData(appInfo);\n client.startSync();\n });\n\n server.ext(\"onPreStop\", async () => {\n await client.handleShutdown();\n });\n\n server.events.on(\"request\", (_, event) => {\n if (\n !pinoLoggerPatched &&\n client.requestLogger.enabled &&\n client.requestLogger.config.captureLogs &&\n event.channel === \"app\"\n ) {\n handleHapiRequestEvent(event, logsContext);\n }\n });\n\n server.ext(\"onRequest\", async (request, h) => {\n if (!client.isEnabled() || request.method.toUpperCase() === \"OPTIONS\") {\n return h.continue;\n }\n\n request[START_TIME_SYMBOL] = performance.now();\n\n // Patch the lifecycle function to run with span and logs context\n const spanHandle = client.spanCollector.startSpan();\n const logs: LogRecord[] = [];\n request[SPAN_HANDLE_SYMBOL] = spanHandle;\n request[LOGS_SYMBOL] = logs;\n const lifecycle = (request as any)._lifecycle.bind(request);\n (request as any)._lifecycle = () =>\n spanHandle.runInContext(() => logsContext.run(logs, lifecycle));\n\n const captureRequestBody =\n client.requestLogger.enabled &&\n client.requestLogger.config.logRequestBody &&\n client.requestLogger.isSupportedContentType(\n request.headers[\"content-type\"],\n );\n const chunks: Buffer[] = [];\n let size = 0;\n request.events.on(\"peek\", (chunk: string, encoding: string) => {\n if (captureRequestBody) {\n chunks.push(Buffer.from(chunk, encoding as BufferEncoding));\n }\n size += Buffer.byteLength(chunk, encoding as BufferEncoding);\n });\n request.events.once(\"finish\", () => {\n if (chunks.length > 0) {\n request[REQUEST_BODY_SYMBOL] = Buffer.concat(chunks);\n }\n request[REQUEST_SIZE_SYMBOL] = size;\n });\n\n return h.continue;\n });\n\n server.ext(\"onPreResponse\", async (request, h) => {\n if (\n !client.isEnabled() ||\n request.method.toUpperCase() === \"OPTIONS\" ||\n isBoom(request.response)\n ) {\n return h.continue;\n }\n\n const captureResponseBody =\n client.requestLogger.enabled &&\n client.requestLogger.config.logResponseBody &&\n client.requestLogger.isSupportedContentType(\n request.response.contentType,\n );\n const chunks: Buffer[] = [];\n let size = 0;\n request.response.events.on(\n \"peek\",\n (chunk: string, encoding: string) => {\n if (captureResponseBody) {\n chunks.push(Buffer.from(chunk, encoding as BufferEncoding));\n }\n size += Buffer.byteLength(chunk, encoding as BufferEncoding);\n },\n );\n request.response.events.once(\"finish\", () => {\n if (chunks.length > 0) {\n request[RESPONSE_BODY_SYMBOL] = Buffer.concat(chunks);\n }\n request[RESPONSE_SIZE_SYMBOL] = size;\n });\n\n return h.continue;\n });\n\n server.ext(\"onPostResponse\", async (request, h) => {\n if (!client.isEnabled() || request.method.toUpperCase() === \"OPTIONS\") {\n return h.continue;\n }\n\n const startTime = request[START_TIME_SYMBOL];\n const responseTime = startTime ? performance.now() - startTime : 0;\n const timestamp = (Date.now() - responseTime) / 1000;\n\n const spanHandle = request[SPAN_HANDLE_SYMBOL];\n spanHandle?.setName(\n `${request.method.toUpperCase()} ${request.route.path}`,\n );\n const spans = spanHandle?.end();\n const traceId = spanHandle?.traceId;\n\n const requestBody = request[REQUEST_BODY_SYMBOL];\n const requestSize = request[REQUEST_SIZE_SYMBOL];\n const response = request.response;\n let statusCode: number;\n let responseHeaders: Record<string, any>;\n let responseBody = request[RESPONSE_BODY_SYMBOL];\n let responseSize = request[RESPONSE_SIZE_SYMBOL];\n const error =\n (response as any)._error instanceof Error\n ? (response as any)._error\n : undefined;\n\n if (isBoom(response)) {\n // Handle Boom error object\n statusCode = response.output?.statusCode ?? 500;\n responseHeaders = response.output?.headers ?? {};\n } else {\n // Handle normal ResponseObject\n statusCode = response.statusCode ?? 200;\n responseHeaders = response.headers ?? {};\n }\n\n if (\n !responseBody &&\n (response as any)._payload &&\n client.requestLogger.enabled &&\n client.requestLogger.config.logResponseBody &&\n (isBoom(response) ||\n client.requestLogger.isSupportedContentType(response.contentType))\n ) {\n const responsePayload = (response as any)._payload;\n if (\n responsePayload &&\n responsePayload._data &&\n responsePayload._encoding &&\n typeof responsePayload._data === \"string\" &&\n typeof responsePayload._encoding === \"string\"\n ) {\n responseBody = Buffer.from(\n responsePayload._data,\n responsePayload._encoding as BufferEncoding,\n );\n }\n }\n\n if (!responseSize && responseBody) {\n responseSize = responseBody.length;\n }\n\n const consumer = request.apitallyConsumer\n ? consumerFromStringOrObject(request.apitallyConsumer)\n : null;\n client.consumerRegistry.addOrUpdateConsumer(consumer);\n\n if (request.route.path) {\n client.requestCounter.addRequest({\n consumer: consumer?.identifier,\n method: request.method,\n path: request.route.path,\n statusCode,\n responseTime,\n requestSize,\n responseSize,\n });\n\n if (statusCode === 500 && error) {\n client.serverErrorCounter.addServerError({\n consumer: consumer?.identifier,\n method: request.method,\n path: request.route.path,\n type: error.name,\n msg: error.message,\n traceback: error.stack || \"\",\n });\n }\n }\n\n if (client.requestLogger.enabled) {\n const logs = request[LOGS_SYMBOL];\n client.requestLogger.logRequest(\n {\n timestamp,\n consumer: consumer?.identifier,\n method: request.method,\n path: request.route.path,\n url: request.url?.href || \"\",\n headers: convertHeaders(request.headers),\n size: requestSize,\n body: requestBody,\n },\n {\n statusCode,\n responseTime: responseTime / 1000,\n headers: convertHeaders(responseHeaders),\n size: responseSize,\n body: responseBody,\n },\n error,\n logs,\n spans,\n traceId,\n );\n }\n\n return h.continue;\n });\n },\n };\n}\n\nexport function setConsumer(\n request: Request,\n consumer: ApitallyConsumer | string | null | undefined,\n) {\n request.apitallyConsumer = consumer || undefined;\n}\n"],"mappings":";;AACA,SAASA,yBAAyB;AAClC,SAASC,mBAAmB;AAE5B,SAASC,sBAAsB;AAC/B,SAASC,kCAAkC;AAE3C,SAASC,sBAAsB;AAG/B,SACEC,wBACAC,cACAC,iBACAC,oBACK;AACP,SAASC,YAAYC,cAAc;AAEnC,MAAMC,oBAAoBC,uBAAO,oBAAA;AACjC,MAAMC,sBAAsBD,uBAAO,sBAAA;AACnC,MAAME,sBAAsBF,uBAAO,sBAAA;AACnC,MAAMG,uBAAuBH,uBAAO,uBAAA;AACpC,MAAMI,uBAAuBJ,uBAAO,uBAAA;AACpC,MAAMK,cAAcL,uBAAO,eAAA;AAC3B,MAAMM,qBAAqBN,uBAAO,qBAAA;AAmBnB,SAAf,eAAuCO,QAAsB;AAC3D,QAAMC,SAAS,IAAIlB,eAAeiB,MAAAA;AAClC,QAAME,cAAc,IAAIrB,kBAAAA;AACxB,MAAIsB,oBAAoB;AAExB,MAAIF,OAAOG,cAAcC,WAAWJ,OAAOG,cAAcJ,OAAOM,aAAa;AAC3EnB,iBAAae,WAAAA;AACbb,iBAAaa,WAAAA;EACf;AAEA,SAAO;IACLK,MAAM;IACNC,UAAU,sCAAgBC,QAAc;AACtCA,aAAOC,IAAI,eAAe,YAAA;AACxB,YACE,YAAYD,UACZR,OAAOG,cAAcC,WACrBJ,OAAOG,cAAcJ,OAAOM,aAC5B;AACAH,8BAAoB,MAAMf,gBACvBqB,OAAeE,QAChBT,WAAAA;QAEJ;MACF,CAAA;AAEAO,aAAOC,IAAI,eAAe,MAAA;AACxB,cAAME,UAAUtB,WAAWmB,QAAQT,OAAOa,UAAU;AACpDZ,eAAOa,eAAeF,OAAAA;AACtBX,eAAOc,UAAS;MAClB,CAAA;AAEAN,aAAOC,IAAI,aAAa,YAAA;AACtB,cAAMT,OAAOe,eAAc;MAC7B,CAAA;AAEAP,aAAOQ,OAAOC,GAAG,WAAW,CAACC,GAAGC,UAAAA;AAC9B,YACE,CAACjB,qBACDF,OAAOG,cAAcC,WACrBJ,OAAOG,cAAcJ,OAAOM,eAC5Bc,MAAMC,YAAY,OAClB;AACAnC,iCAAuBkC,OAAOlB,WAAAA;QAChC;MACF,CAAA;AAEAO,aAAOC,IAAI,aAAa,OAAOY,SAASC,MAAAA;AACtC,YAAI,CAACtB,OAAOuB,UAAS,KAAMF,QAAQG,OAAOC,YAAW,MAAO,WAAW;AACrE,iBAAOH,EAAEI;QACX;AAEAL,gBAAQ9B,iBAAAA,IAAqBV,YAAY8C,IAAG;AAG5C,cAAMC,aAAa5B,OAAO6B,cAAcC,UAAS;AACjD,cAAMC,OAAoB,CAAA;AAC1BV,gBAAQvB,kBAAAA,IAAsB8B;AAC9BP,gBAAQxB,WAAAA,IAAekC;AACvB,cAAMC,YAAaX,QAAgBY,WAAWC,KAAKb,OAAAA;AAClDA,gBAAgBY,aAAa,MAC5BL,WAAWO,aAAa,MAAMlC,YAAYmC,IAAIL,MAAMC,SAAAA,CAAAA;AAEtD,cAAMK,qBACJrC,OAAOG,cAAcC,WACrBJ,OAAOG,cAAcJ,OAAOuC,kBAC5BtC,OAAOG,cAAcoC,uBACnBlB,QAAQmB,QAAQ,cAAA,CAAe;AAEnC,cAAMC,SAAmB,CAAA;AACzB,YAAIC,OAAO;AACXrB,gBAAQL,OAAOC,GAAG,QAAQ,CAAC0B,OAAeC,aAAAA;AACxC,cAAIP,oBAAoB;AACtBI,mBAAOI,KAAKC,OAAOC,KAAKJ,OAAOC,QAAAA,CAAAA;UACjC;AACAF,kBAAQI,OAAOE,WAAWL,OAAOC,QAAAA;QACnC,CAAA;AACAvB,gBAAQL,OAAOiC,KAAK,UAAU,MAAA;AAC5B,cAAIR,OAAOS,SAAS,GAAG;AACrB7B,oBAAQ5B,mBAAAA,IAAuBqD,OAAOK,OAAOV,MAAAA;UAC/C;AACApB,kBAAQ3B,mBAAAA,IAAuBgD;QACjC,CAAA;AAEA,eAAOpB,EAAEI;MACX,CAAA;AAEAlB,aAAOC,IAAI,iBAAiB,OAAOY,SAASC,MAAAA;AAC1C,YACE,CAACtB,OAAOuB,UAAS,KACjBF,QAAQG,OAAOC,YAAW,MAAO,aACjCnC,OAAO+B,QAAQ+B,QAAQ,GACvB;AACA,iBAAO9B,EAAEI;QACX;AAEA,cAAM2B,sBACJrD,OAAOG,cAAcC,WACrBJ,OAAOG,cAAcJ,OAAOuD,mBAC5BtD,OAAOG,cAAcoC,uBACnBlB,QAAQ+B,SAASG,WAAW;AAEhC,cAAMd,SAAmB,CAAA;AACzB,YAAIC,OAAO;AACXrB,gBAAQ+B,SAASpC,OAAOC,GACtB,QACA,CAAC0B,OAAeC,aAAAA;AACd,cAAIS,qBAAqB;AACvBZ,mBAAOI,KAAKC,OAAOC,KAAKJ,OAAOC,QAAAA,CAAAA;UACjC;AACAF,kBAAQI,OAAOE,WAAWL,OAAOC,QAAAA;QACnC,CAAA;AAEFvB,gBAAQ+B,SAASpC,OAAOiC,KAAK,UAAU,MAAA;AACrC,cAAIR,OAAOS,SAAS,GAAG;AACrB7B,oBAAQ1B,oBAAAA,IAAwBmD,OAAOK,OAAOV,MAAAA;UAChD;AACApB,kBAAQzB,oBAAAA,IAAwB8C;QAClC,CAAA;AAEA,eAAOpB,EAAEI;MACX,CAAA;AAEAlB,aAAOC,IAAI,kBAAkB,OAAOY,SAASC,MAAAA;AArKnD;AAsKQ,YAAI,CAACtB,OAAOuB,UAAS,KAAMF,QAAQG,OAAOC,YAAW,MAAO,WAAW;AACrE,iBAAOH,EAAEI;QACX;AAEA,cAAM8B,YAAYnC,QAAQ9B,iBAAAA;AAC1B,cAAMkE,eAAeD,YAAY3E,YAAY8C,IAAG,IAAK6B,YAAY;AACjE,cAAME,aAAaC,KAAKhC,IAAG,IAAK8B,gBAAgB;AAEhD,cAAM7B,aAAaP,QAAQvB,kBAAAA;AAC3B8B,iDAAYgC,QACV,GAAGvC,QAAQG,OAAOC,YAAW,CAAA,IAAMJ,QAAQwC,MAAMC,IAAI;AAEvD,cAAMC,QAAQnC,yCAAYoC;AAC1B,cAAMC,UAAUrC,yCAAYqC;AAE5B,cAAMC,cAAc7C,QAAQ5B,mBAAAA;AAC5B,cAAM0E,cAAc9C,QAAQ3B,mBAAAA;AAC5B,cAAM0D,WAAW/B,QAAQ+B;AACzB,YAAIgB;AACJ,YAAIC;AACJ,YAAIC,eAAejD,QAAQ1B,oBAAAA;AAC3B,YAAI4E,eAAelD,QAAQzB,oBAAAA;AAC3B,cAAM4E,QACHpB,SAAiBqB,kBAAkBC,QAC/BtB,SAAiBqB,SAClBE;AAEN,YAAIrF,OAAO8D,QAAAA,GAAW;AAEpBgB,yBAAahB,cAASwB,WAATxB,mBAAiBgB,eAAc;AAC5CC,8BAAkBjB,cAASwB,WAATxB,mBAAiBZ,YAAW,CAAC;QACjD,OAAO;AAEL4B,uBAAahB,SAASgB,cAAc;AACpCC,4BAAkBjB,SAASZ,WAAW,CAAC;QACzC;AAEA,YACE,CAAC8B,gBACAlB,SAAiByB,YAClB7E,OAAOG,cAAcC,WACrBJ,OAAOG,cAAcJ,OAAOuD,oBAC3BhE,OAAO8D,QAAAA,KACNpD,OAAOG,cAAcoC,uBAAuBa,SAASG,WAAW,IAClE;AACA,gBAAMuB,kBAAmB1B,SAAiByB;AAC1C,cACEC,mBACAA,gBAAgBC,SAChBD,gBAAgBE,aAChB,OAAOF,gBAAgBC,UAAU,YACjC,OAAOD,gBAAgBE,cAAc,UACrC;AACAV,2BAAexB,OAAOC,KACpB+B,gBAAgBC,OAChBD,gBAAgBE,SAAS;UAE7B;QACF;AAEA,YAAI,CAACT,gBAAgBD,cAAc;AACjCC,yBAAeD,aAAapB;QAC9B;AAEA,cAAM+B,WAAW5D,QAAQ6D,mBACrBnG,2BAA2BsC,QAAQ6D,gBAAgB,IACnD;AACJlF,eAAOmF,iBAAiBC,oBAAoBH,QAAAA;AAE5C,YAAI5D,QAAQwC,MAAMC,MAAM;AACtB9D,iBAAOqF,eAAeC,WAAW;YAC/BL,UAAUA,qCAAUM;YACpB/D,QAAQH,QAAQG;YAChBsC,MAAMzC,QAAQwC,MAAMC;YACpBM;YACAX;YACAU;YACAI;UACF,CAAA;AAEA,cAAIH,eAAe,OAAOI,OAAO;AAC/BxE,mBAAOwF,mBAAmBC,eAAe;cACvCR,UAAUA,qCAAUM;cACpB/D,QAAQH,QAAQG;cAChBsC,MAAMzC,QAAQwC,MAAMC;cACpB4B,MAAMlB,MAAMlE;cACZqF,KAAKnB,MAAMoB;cACXC,WAAWrB,MAAMsB,SAAS;YAC5B,CAAA;UACF;QACF;AAEA,YAAI9F,OAAOG,cAAcC,SAAS;AAChC,gBAAM2B,OAAOV,QAAQxB,WAAAA;AACrBG,iBAAOG,cAAc4F,WACnB;YACErC;YACAuB,UAAUA,qCAAUM;YACpB/D,QAAQH,QAAQG;YAChBsC,MAAMzC,QAAQwC,MAAMC;YACpBkC,OAAK3E,aAAQ2E,QAAR3E,mBAAa4E,SAAQ;YAC1BzD,SAASxD,eAAeqC,QAAQmB,OAAO;YACvCE,MAAMyB;YACN+B,MAAMhC;UACR,GACA;YACEE;YACAX,cAAcA,eAAe;YAC7BjB,SAASxD,eAAeqF,eAAAA;YACxB3B,MAAM6B;YACN2B,MAAM5B;UACR,GACAE,OACAzC,MACAgC,OACAE,OAAAA;QAEJ;AAEA,eAAO3C,EAAEI;MACX,CAAA;IACF,GAzOU;EA0OZ;AACF;AAvPwByE;AAyPjB,SAASC,YACd/E,SACA4D,UAAsD;AAEtD5D,UAAQ6D,mBAAmBD,YAAYN;AACzC;AALgByB;","names":["AsyncLocalStorage","performance","ApitallyClient","consumerFromStringOrObject","convertHeaders","handleHapiRequestEvent","patchConsole","patchPinoLogger","patchWinston","getAppInfo","isBoom","START_TIME_SYMBOL","Symbol","REQUEST_BODY_SYMBOL","REQUEST_SIZE_SYMBOL","RESPONSE_BODY_SYMBOL","RESPONSE_SIZE_SYMBOL","LOGS_SYMBOL","SPAN_HANDLE_SYMBOL","config","client","logsContext","pinoLoggerPatched","requestLogger","enabled","captureLogs","name","register","server","ext","logger","appInfo","appVersion","setStartupData","startSync","handleShutdown","events","on","_","event","channel","request","h","isEnabled","method","toUpperCase","continue","now","spanHandle","spanCollector","startSpan","logs","lifecycle","_lifecycle","bind","runInContext","run","captureRequestBody","logRequestBody","isSupportedContentType","headers","chunks","size","chunk","encoding","push","Buffer","from","byteLength","once","length","concat","response","captureResponseBody","logResponseBody","contentType","startTime","responseTime","timestamp","Date","setName","route","path","spans","end","traceId","requestBody","requestSize","statusCode","responseHeaders","responseBody","responseSize","error","_error","Error","undefined","output","_payload","responsePayload","_data","_encoding","consumer","apitallyConsumer","consumerRegistry","addOrUpdateConsumer","requestCounter","addRequest","identifier","serverErrorCounter","addServerError","type","msg","message","traceback","stack","logRequest","url","href","body","apitallyPlugin","setConsumer"]}
|
package/dist/hapi/utils.d.cts
CHANGED
|
@@ -6,6 +6,8 @@ import 'winston';
|
|
|
6
6
|
import '../common/requestLogger.cjs';
|
|
7
7
|
import 'node:buffer';
|
|
8
8
|
import 'node:http';
|
|
9
|
+
import '../common/spanCollector.cjs';
|
|
10
|
+
import '@opentelemetry/sdk-trace-base';
|
|
9
11
|
import '../common/tempGzipFile.cjs';
|
|
10
12
|
|
|
11
13
|
declare function getAppInfo(server: Server, appVersion?: string): StartupData;
|
package/dist/hapi/utils.d.ts
CHANGED
|
@@ -6,6 +6,8 @@ import 'winston';
|
|
|
6
6
|
import '../common/requestLogger.js';
|
|
7
7
|
import 'node:buffer';
|
|
8
8
|
import 'node:http';
|
|
9
|
+
import '../common/spanCollector.js';
|
|
10
|
+
import '@opentelemetry/sdk-trace-base';
|
|
9
11
|
import '../common/tempGzipFile.js';
|
|
10
12
|
|
|
11
13
|
declare function getAppInfo(server: Server, appVersion?: string): StartupData;
|
package/dist/hono/index.cjs
CHANGED
|
@@ -18,13 +18,16 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
18
18
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
19
|
var hono_exports = {};
|
|
20
20
|
__export(hono_exports, {
|
|
21
|
+
ApitallySpanProcessor: () => import_spanCollector.ApitallySpanProcessor,
|
|
21
22
|
setConsumer: () => import_middleware.setConsumer,
|
|
22
23
|
useApitally: () => import_middleware.useApitally
|
|
23
24
|
});
|
|
24
25
|
module.exports = __toCommonJS(hono_exports);
|
|
26
|
+
var import_spanCollector = require("../common/spanCollector.js");
|
|
25
27
|
var import_middleware = require("./middleware.js");
|
|
26
28
|
// Annotate the CommonJS export names for ESM import in node:
|
|
27
29
|
0 && (module.exports = {
|
|
30
|
+
ApitallySpanProcessor,
|
|
28
31
|
setConsumer,
|
|
29
32
|
useApitally
|
|
30
33
|
});
|
package/dist/hono/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/hono/index.ts"],"sourcesContent":["export type { ApitallyConfig, ApitallyConsumer } from \"../common/types.js\";\nexport { setConsumer, useApitally } from \"./middleware.js\";\n"],"mappings":";;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"sources":["../../src/hono/index.ts"],"sourcesContent":["export { ApitallySpanProcessor } from \"../common/spanCollector.js\";\nexport type { ApitallyConfig, ApitallyConsumer } from \"../common/types.js\";\nexport { setConsumer, useApitally } from \"./middleware.js\";\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;;;;;;;2BAAsC;AAEtC,wBAAyC;","names":[]}
|
package/dist/hono/index.d.cts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
export { ApitallySpanProcessor } from '../common/spanCollector.cjs';
|
|
1
2
|
export { ApitallyConfig, ApitallyConsumer } from '../common/types.cjs';
|
|
2
3
|
export { setConsumer, useApitally } from './middleware.cjs';
|
|
4
|
+
import '@opentelemetry/sdk-trace-base';
|
|
3
5
|
import '../common/logging.cjs';
|
|
4
6
|
import 'winston';
|
|
5
7
|
import '../common/requestLogger.cjs';
|
package/dist/hono/index.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
export { ApitallySpanProcessor } from '../common/spanCollector.js';
|
|
1
2
|
export { ApitallyConfig, ApitallyConsumer } from '../common/types.js';
|
|
2
3
|
export { setConsumer, useApitally } from './middleware.js';
|
|
4
|
+
import '@opentelemetry/sdk-trace-base';
|
|
3
5
|
import '../common/logging.js';
|
|
4
6
|
import 'winston';
|
|
5
7
|
import '../common/requestLogger.js';
|
package/dist/hono/index.js
CHANGED
package/dist/hono/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/hono/index.ts"],"sourcesContent":["export type { ApitallyConfig, ApitallyConsumer } from \"../common/types.js\";\nexport { setConsumer, useApitally } from \"./middleware.js\";\n"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../../src/hono/index.ts"],"sourcesContent":["export { ApitallySpanProcessor } from \"../common/spanCollector.js\";\nexport type { ApitallyConfig, ApitallyConsumer } from \"../common/types.js\";\nexport { setConsumer, useApitally } from \"./middleware.js\";\n"],"mappings":"AAAA,SAASA,6BAA6B;AAEtC,SAASC,aAAaC,mBAAmB;","names":["ApitallySpanProcessor","setConsumer","useApitally"]}
|
package/dist/hono/middleware.cjs
CHANGED
|
@@ -62,7 +62,8 @@ function getMiddleware(client) {
|
|
|
62
62
|
await logsContext.run([], async () => {
|
|
63
63
|
const timestamp = Date.now() / 1e3;
|
|
64
64
|
const startTime = import_node_perf_hooks.performance.now();
|
|
65
|
-
|
|
65
|
+
const spanHandle = client.spanCollector.startSpan();
|
|
66
|
+
await spanHandle.runInContext(next);
|
|
66
67
|
const [newResponse, responsePromise] = (0, import_response.captureResponse)(c.res, {
|
|
67
68
|
captureBody: client.requestLogger.enabled && client.requestLogger.config.logResponseBody && client.requestLogger.isSupportedContentType(c.res.headers.get("content-type")) || c.res.status === 400 && c.res.headers.get("content-type") === "application/json",
|
|
68
69
|
maxBodySize: client.requestLogger.maxBodySize
|
|
@@ -72,6 +73,9 @@ function getMiddleware(client) {
|
|
|
72
73
|
const responseHeaders = c.res.headers;
|
|
73
74
|
responsePromise.then(async (capturedResponse) => {
|
|
74
75
|
const responseTime = import_node_perf_hooks.performance.now() - startTime;
|
|
76
|
+
spanHandle.setName(`${c.req.method} ${c.req.routePath}`);
|
|
77
|
+
const spans = spanHandle.end();
|
|
78
|
+
const traceId = spanHandle.traceId;
|
|
75
79
|
const requestSize = (0, import_headers.parseContentLength)(c.req.header("content-length"));
|
|
76
80
|
const responseSize = capturedResponse.completed ? capturedResponse.size : void 0;
|
|
77
81
|
const consumer = getConsumer(c);
|
|
@@ -130,7 +134,7 @@ function getMiddleware(client) {
|
|
|
130
134
|
headers: (0, import_requestLogger.convertHeaders)(responseHeaders),
|
|
131
135
|
size: responseSize,
|
|
132
136
|
body: responseBody
|
|
133
|
-
}, c.error, logs);
|
|
137
|
+
}, c.error, logs, spans, traceId);
|
|
134
138
|
}
|
|
135
139
|
});
|
|
136
140
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/hono/middleware.ts"],"sourcesContent":["import { Context, Hono } from \"hono\";\nimport { MiddlewareHandler } from \"hono/types\";\nimport { AsyncLocalStorage } from \"node:async_hooks\";\nimport { performance } from \"node:perf_hooks\";\n\nimport { ApitallyClient } from \"../common/client.js\";\nimport { consumerFromStringOrObject } from \"../common/consumerRegistry.js\";\nimport { parseContentLength } from \"../common/headers.js\";\nimport type { LogRecord } from \"../common/requestLogger.js\";\nimport { convertHeaders } from \"../common/requestLogger.js\";\nimport { captureResponse, getResponseJson } from \"../common/response.js\";\nimport { ApitallyConfig, ApitallyConsumer } from \"../common/types.js\";\nimport { patchConsole, patchWinston } from \"../loggers/index.js\";\nimport { extractZodErrors, getAppInfo } from \"./utils.js\";\n\ndeclare module \"hono\" {\n interface ContextVariableMap {\n apitallyConsumer?: ApitallyConsumer | string;\n }\n}\n\nexport function useApitally(app: Hono, config: ApitallyConfig) {\n const client = new ApitallyClient(config);\n const middleware = getMiddleware(client);\n app.use(middleware);\n\n const setStartupData = (attempt: number = 1) => {\n const appInfo = getAppInfo(app, config.appVersion);\n if (appInfo.paths.length > 0 || attempt >= 10) {\n client.setStartupData(appInfo);\n client.startSync();\n } else {\n setTimeout(() => setStartupData(attempt + 1), 500);\n }\n };\n setTimeout(() => setStartupData(), 500);\n}\n\nfunction getMiddleware(client: ApitallyClient): MiddlewareHandler {\n const logsContext = new AsyncLocalStorage<LogRecord[]>();\n\n if (client.requestLogger.config.captureLogs) {\n patchConsole(logsContext);\n patchWinston(logsContext);\n }\n\n return async (c, next) => {\n if (!client.isEnabled() || c.req.method.toUpperCase() === \"OPTIONS\") {\n await next();\n return;\n }\n\n await logsContext.run([], async () => {\n const timestamp = Date.now() / 1000;\n const startTime = performance.now();\n\n await next();\n\n const [newResponse, responsePromise] = captureResponse(c.res, {\n captureBody:\n (client.requestLogger.enabled &&\n client.requestLogger.config.logResponseBody &&\n client.requestLogger.isSupportedContentType(\n c.res.headers.get(\"content-type\"),\n )) ||\n (c.res.status === 400 &&\n c.res.headers.get(\"content-type\") === \"application/json\"),\n maxBodySize: client.requestLogger.maxBodySize,\n });\n c.res = newResponse;\n\n const statusCode = c.res.status;\n const responseHeaders = c.res.headers;\n\n responsePromise.then(async (capturedResponse) => {\n const responseTime = performance.now() - startTime;\n const requestSize = parseContentLength(c.req.header(\"content-length\"));\n const responseSize = capturedResponse.completed\n ? capturedResponse.size\n : undefined;\n\n const consumer = getConsumer(c);\n client.consumerRegistry.addOrUpdateConsumer(consumer);\n\n client.requestCounter.addRequest({\n consumer: consumer?.identifier,\n method: c.req.method,\n path: c.req.routePath,\n statusCode,\n responseTime,\n requestSize,\n responseSize,\n });\n\n if (statusCode === 400 && capturedResponse.body) {\n const responseJson = getResponseJson(capturedResponse.body);\n const validationErrors = extractZodErrors(responseJson);\n validationErrors.forEach((error) => {\n client.validationErrorCounter.addValidationError({\n consumer: consumer?.identifier,\n method: c.req.method,\n path: c.req.routePath,\n ...error,\n });\n });\n }\n\n if (c.error) {\n client.serverErrorCounter.addServerError({\n consumer: consumer?.identifier,\n method: c.req.method,\n path: c.req.routePath,\n type: c.error.name,\n msg: c.error.message,\n traceback: c.error.stack || \"\",\n });\n }\n\n if (client.requestLogger.enabled) {\n let requestBody;\n const responseBody = capturedResponse.body;\n const requestContentType = c.req.header(\"content-type\");\n if (\n client.requestLogger.config.logRequestBody &&\n client.requestLogger.isSupportedContentType(requestContentType)\n ) {\n requestBody = Buffer.from(await c.req.arrayBuffer());\n }\n const logs = logsContext.getStore();\n client.requestLogger.logRequest(\n {\n timestamp,\n method: c.req.method,\n path: c.req.routePath,\n url: c.req.url,\n headers: convertHeaders(c.req.header()),\n size: requestSize,\n consumer: consumer?.identifier,\n body: requestBody,\n },\n {\n statusCode: statusCode,\n responseTime: responseTime / 1000,\n headers: convertHeaders(responseHeaders),\n size: responseSize,\n body: responseBody,\n },\n c.error,\n logs,\n );\n }\n });\n });\n };\n}\n\nexport function setConsumer(\n c: Context,\n consumer: ApitallyConsumer | string | null | undefined,\n) {\n c.set(\"apitallyConsumer\", consumer || undefined);\n}\n\nfunction getConsumer(c: Context) {\n const consumer = c.get(\"apitallyConsumer\");\n if (consumer) {\n return consumerFromStringOrObject(consumer);\n }\n return null;\n}\n"],"mappings":"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","names":["useApitally","app","config","client","ApitallyClient","middleware","getMiddleware","use","setStartupData","attempt","appInfo","getAppInfo","appVersion","paths","length","startSync","setTimeout","logsContext","AsyncLocalStorage","requestLogger","captureLogs","patchConsole","patchWinston","c","next","isEnabled","req","method","toUpperCase","run","timestamp","Date","now","startTime","performance","newResponse","responsePromise","captureResponse","res","captureBody","enabled","logResponseBody","isSupportedContentType","headers","get","status","maxBodySize","statusCode","responseHeaders","then","capturedResponse","responseTime","requestSize","parseContentLength","header","responseSize","completed","size","undefined","consumer","getConsumer","consumerRegistry","addOrUpdateConsumer","requestCounter","addRequest","identifier","path","routePath","body","responseJson","getResponseJson","validationErrors","extractZodErrors","forEach","error","validationErrorCounter","addValidationError","serverErrorCounter","addServerError","type","name","msg","message","traceback","stack","requestBody","responseBody","requestContentType","logRequestBody","Buffer","from","arrayBuffer","logs","getStore","logRequest","url","convertHeaders","setConsumer","set","consumerFromStringOrObject"]}
|
|
1
|
+
{"version":3,"sources":["../../src/hono/middleware.ts"],"sourcesContent":["import { Context, Hono } from \"hono\";\nimport { MiddlewareHandler } from \"hono/types\";\nimport { AsyncLocalStorage } from \"node:async_hooks\";\nimport { performance } from \"node:perf_hooks\";\n\nimport { ApitallyClient } from \"../common/client.js\";\nimport { consumerFromStringOrObject } from \"../common/consumerRegistry.js\";\nimport { parseContentLength } from \"../common/headers.js\";\nimport type { LogRecord } from \"../common/requestLogger.js\";\nimport { convertHeaders } from \"../common/requestLogger.js\";\nimport { captureResponse, getResponseJson } from \"../common/response.js\";\nimport { ApitallyConfig, ApitallyConsumer } from \"../common/types.js\";\nimport { patchConsole, patchWinston } from \"../loggers/index.js\";\nimport { extractZodErrors, getAppInfo } from \"./utils.js\";\n\ndeclare module \"hono\" {\n interface ContextVariableMap {\n apitallyConsumer?: ApitallyConsumer | string;\n }\n}\n\nexport function useApitally(app: Hono, config: ApitallyConfig) {\n const client = new ApitallyClient(config);\n const middleware = getMiddleware(client);\n app.use(middleware);\n\n const setStartupData = (attempt: number = 1) => {\n const appInfo = getAppInfo(app, config.appVersion);\n if (appInfo.paths.length > 0 || attempt >= 10) {\n client.setStartupData(appInfo);\n client.startSync();\n } else {\n setTimeout(() => setStartupData(attempt + 1), 500);\n }\n };\n setTimeout(() => setStartupData(), 500);\n}\n\nfunction getMiddleware(client: ApitallyClient): MiddlewareHandler {\n const logsContext = new AsyncLocalStorage<LogRecord[]>();\n\n if (client.requestLogger.config.captureLogs) {\n patchConsole(logsContext);\n patchWinston(logsContext);\n }\n\n return async (c, next) => {\n if (!client.isEnabled() || c.req.method.toUpperCase() === \"OPTIONS\") {\n await next();\n return;\n }\n\n await logsContext.run([], async () => {\n const timestamp = Date.now() / 1000;\n const startTime = performance.now();\n\n const spanHandle = client.spanCollector.startSpan();\n await spanHandle.runInContext(next);\n\n const [newResponse, responsePromise] = captureResponse(c.res, {\n captureBody:\n (client.requestLogger.enabled &&\n client.requestLogger.config.logResponseBody &&\n client.requestLogger.isSupportedContentType(\n c.res.headers.get(\"content-type\"),\n )) ||\n (c.res.status === 400 &&\n c.res.headers.get(\"content-type\") === \"application/json\"),\n maxBodySize: client.requestLogger.maxBodySize,\n });\n c.res = newResponse;\n\n const statusCode = c.res.status;\n const responseHeaders = c.res.headers;\n\n responsePromise.then(async (capturedResponse) => {\n const responseTime = performance.now() - startTime;\n\n spanHandle.setName(`${c.req.method} ${c.req.routePath}`);\n const spans = spanHandle.end();\n const traceId = spanHandle.traceId;\n\n const requestSize = parseContentLength(c.req.header(\"content-length\"));\n const responseSize = capturedResponse.completed\n ? capturedResponse.size\n : undefined;\n\n const consumer = getConsumer(c);\n client.consumerRegistry.addOrUpdateConsumer(consumer);\n\n client.requestCounter.addRequest({\n consumer: consumer?.identifier,\n method: c.req.method,\n path: c.req.routePath,\n statusCode,\n responseTime,\n requestSize,\n responseSize,\n });\n\n if (statusCode === 400 && capturedResponse.body) {\n const responseJson = getResponseJson(capturedResponse.body);\n const validationErrors = extractZodErrors(responseJson);\n validationErrors.forEach((error) => {\n client.validationErrorCounter.addValidationError({\n consumer: consumer?.identifier,\n method: c.req.method,\n path: c.req.routePath,\n ...error,\n });\n });\n }\n\n if (c.error) {\n client.serverErrorCounter.addServerError({\n consumer: consumer?.identifier,\n method: c.req.method,\n path: c.req.routePath,\n type: c.error.name,\n msg: c.error.message,\n traceback: c.error.stack || \"\",\n });\n }\n\n if (client.requestLogger.enabled) {\n let requestBody;\n const responseBody = capturedResponse.body;\n const requestContentType = c.req.header(\"content-type\");\n if (\n client.requestLogger.config.logRequestBody &&\n client.requestLogger.isSupportedContentType(requestContentType)\n ) {\n requestBody = Buffer.from(await c.req.arrayBuffer());\n }\n const logs = logsContext.getStore();\n client.requestLogger.logRequest(\n {\n timestamp,\n method: c.req.method,\n path: c.req.routePath,\n url: c.req.url,\n headers: convertHeaders(c.req.header()),\n size: requestSize,\n consumer: consumer?.identifier,\n body: requestBody,\n },\n {\n statusCode: statusCode,\n responseTime: responseTime / 1000,\n headers: convertHeaders(responseHeaders),\n size: responseSize,\n body: responseBody,\n },\n c.error,\n logs,\n spans,\n traceId,\n );\n }\n });\n });\n };\n}\n\nexport function setConsumer(\n c: Context,\n consumer: ApitallyConsumer | string | null | undefined,\n) {\n c.set(\"apitallyConsumer\", consumer || undefined);\n}\n\nfunction getConsumer(c: Context) {\n const consumer = c.get(\"apitallyConsumer\");\n if (consumer) {\n return consumerFromStringOrObject(consumer);\n }\n return null;\n}\n"],"mappings":"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","names":["useApitally","app","config","client","ApitallyClient","middleware","getMiddleware","use","setStartupData","attempt","appInfo","getAppInfo","appVersion","paths","length","startSync","setTimeout","logsContext","AsyncLocalStorage","requestLogger","captureLogs","patchConsole","patchWinston","c","next","isEnabled","req","method","toUpperCase","run","timestamp","Date","now","startTime","performance","spanHandle","spanCollector","startSpan","runInContext","newResponse","responsePromise","captureResponse","res","captureBody","enabled","logResponseBody","isSupportedContentType","headers","get","status","maxBodySize","statusCode","responseHeaders","then","capturedResponse","responseTime","setName","routePath","spans","end","traceId","requestSize","parseContentLength","header","responseSize","completed","size","undefined","consumer","getConsumer","consumerRegistry","addOrUpdateConsumer","requestCounter","addRequest","identifier","path","body","responseJson","getResponseJson","validationErrors","extractZodErrors","forEach","error","validationErrorCounter","addValidationError","serverErrorCounter","addServerError","type","name","msg","message","traceback","stack","requestBody","responseBody","requestContentType","logRequestBody","Buffer","from","arrayBuffer","logs","getStore","logRequest","url","convertHeaders","setConsumer","set","consumerFromStringOrObject"]}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import '../common/spanCollector.cjs';
|
|
1
2
|
import { ApitallyConsumer, ApitallyConfig } from '../common/types.cjs';
|
|
2
3
|
import { Context, Hono } from 'hono';
|
|
4
|
+
import '@opentelemetry/sdk-trace-base';
|
|
3
5
|
import '../common/logging.cjs';
|
|
4
6
|
import 'winston';
|
|
5
7
|
import '../common/requestLogger.cjs';
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import '../common/spanCollector.js';
|
|
1
2
|
import { ApitallyConsumer, ApitallyConfig } from '../common/types.js';
|
|
2
3
|
import { Context, Hono } from 'hono';
|
|
4
|
+
import '@opentelemetry/sdk-trace-base';
|
|
3
5
|
import '../common/logging.js';
|
|
4
6
|
import 'winston';
|
|
5
7
|
import '../common/requestLogger.js';
|
package/dist/hono/middleware.js
CHANGED
|
@@ -39,7 +39,8 @@ function getMiddleware(client) {
|
|
|
39
39
|
await logsContext.run([], async () => {
|
|
40
40
|
const timestamp = Date.now() / 1e3;
|
|
41
41
|
const startTime = performance.now();
|
|
42
|
-
|
|
42
|
+
const spanHandle = client.spanCollector.startSpan();
|
|
43
|
+
await spanHandle.runInContext(next);
|
|
43
44
|
const [newResponse, responsePromise] = captureResponse(c.res, {
|
|
44
45
|
captureBody: client.requestLogger.enabled && client.requestLogger.config.logResponseBody && client.requestLogger.isSupportedContentType(c.res.headers.get("content-type")) || c.res.status === 400 && c.res.headers.get("content-type") === "application/json",
|
|
45
46
|
maxBodySize: client.requestLogger.maxBodySize
|
|
@@ -49,6 +50,9 @@ function getMiddleware(client) {
|
|
|
49
50
|
const responseHeaders = c.res.headers;
|
|
50
51
|
responsePromise.then(async (capturedResponse) => {
|
|
51
52
|
const responseTime = performance.now() - startTime;
|
|
53
|
+
spanHandle.setName(`${c.req.method} ${c.req.routePath}`);
|
|
54
|
+
const spans = spanHandle.end();
|
|
55
|
+
const traceId = spanHandle.traceId;
|
|
52
56
|
const requestSize = parseContentLength(c.req.header("content-length"));
|
|
53
57
|
const responseSize = capturedResponse.completed ? capturedResponse.size : void 0;
|
|
54
58
|
const consumer = getConsumer(c);
|
|
@@ -107,7 +111,7 @@ function getMiddleware(client) {
|
|
|
107
111
|
headers: convertHeaders(responseHeaders),
|
|
108
112
|
size: responseSize,
|
|
109
113
|
body: responseBody
|
|
110
|
-
}, c.error, logs);
|
|
114
|
+
}, c.error, logs, spans, traceId);
|
|
111
115
|
}
|
|
112
116
|
});
|
|
113
117
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/hono/middleware.ts"],"sourcesContent":["import { Context, Hono } from \"hono\";\nimport { MiddlewareHandler } from \"hono/types\";\nimport { AsyncLocalStorage } from \"node:async_hooks\";\nimport { performance } from \"node:perf_hooks\";\n\nimport { ApitallyClient } from \"../common/client.js\";\nimport { consumerFromStringOrObject } from \"../common/consumerRegistry.js\";\nimport { parseContentLength } from \"../common/headers.js\";\nimport type { LogRecord } from \"../common/requestLogger.js\";\nimport { convertHeaders } from \"../common/requestLogger.js\";\nimport { captureResponse, getResponseJson } from \"../common/response.js\";\nimport { ApitallyConfig, ApitallyConsumer } from \"../common/types.js\";\nimport { patchConsole, patchWinston } from \"../loggers/index.js\";\nimport { extractZodErrors, getAppInfo } from \"./utils.js\";\n\ndeclare module \"hono\" {\n interface ContextVariableMap {\n apitallyConsumer?: ApitallyConsumer | string;\n }\n}\n\nexport function useApitally(app: Hono, config: ApitallyConfig) {\n const client = new ApitallyClient(config);\n const middleware = getMiddleware(client);\n app.use(middleware);\n\n const setStartupData = (attempt: number = 1) => {\n const appInfo = getAppInfo(app, config.appVersion);\n if (appInfo.paths.length > 0 || attempt >= 10) {\n client.setStartupData(appInfo);\n client.startSync();\n } else {\n setTimeout(() => setStartupData(attempt + 1), 500);\n }\n };\n setTimeout(() => setStartupData(), 500);\n}\n\nfunction getMiddleware(client: ApitallyClient): MiddlewareHandler {\n const logsContext = new AsyncLocalStorage<LogRecord[]>();\n\n if (client.requestLogger.config.captureLogs) {\n patchConsole(logsContext);\n patchWinston(logsContext);\n }\n\n return async (c, next) => {\n if (!client.isEnabled() || c.req.method.toUpperCase() === \"OPTIONS\") {\n await next();\n return;\n }\n\n await logsContext.run([], async () => {\n const timestamp = Date.now() / 1000;\n const startTime = performance.now();\n\n await next();\n\n const [newResponse, responsePromise] = captureResponse(c.res, {\n captureBody:\n (client.requestLogger.enabled &&\n client.requestLogger.config.logResponseBody &&\n client.requestLogger.isSupportedContentType(\n c.res.headers.get(\"content-type\"),\n )) ||\n (c.res.status === 400 &&\n c.res.headers.get(\"content-type\") === \"application/json\"),\n maxBodySize: client.requestLogger.maxBodySize,\n });\n c.res = newResponse;\n\n const statusCode = c.res.status;\n const responseHeaders = c.res.headers;\n\n responsePromise.then(async (capturedResponse) => {\n const responseTime = performance.now() - startTime;\n const requestSize = parseContentLength(c.req.header(\"content-length\"));\n const responseSize = capturedResponse.completed\n ? capturedResponse.size\n : undefined;\n\n const consumer = getConsumer(c);\n client.consumerRegistry.addOrUpdateConsumer(consumer);\n\n client.requestCounter.addRequest({\n consumer: consumer?.identifier,\n method: c.req.method,\n path: c.req.routePath,\n statusCode,\n responseTime,\n requestSize,\n responseSize,\n });\n\n if (statusCode === 400 && capturedResponse.body) {\n const responseJson = getResponseJson(capturedResponse.body);\n const validationErrors = extractZodErrors(responseJson);\n validationErrors.forEach((error) => {\n client.validationErrorCounter.addValidationError({\n consumer: consumer?.identifier,\n method: c.req.method,\n path: c.req.routePath,\n ...error,\n });\n });\n }\n\n if (c.error) {\n client.serverErrorCounter.addServerError({\n consumer: consumer?.identifier,\n method: c.req.method,\n path: c.req.routePath,\n type: c.error.name,\n msg: c.error.message,\n traceback: c.error.stack || \"\",\n });\n }\n\n if (client.requestLogger.enabled) {\n let requestBody;\n const responseBody = capturedResponse.body;\n const requestContentType = c.req.header(\"content-type\");\n if (\n client.requestLogger.config.logRequestBody &&\n client.requestLogger.isSupportedContentType(requestContentType)\n ) {\n requestBody = Buffer.from(await c.req.arrayBuffer());\n }\n const logs = logsContext.getStore();\n client.requestLogger.logRequest(\n {\n timestamp,\n method: c.req.method,\n path: c.req.routePath,\n url: c.req.url,\n headers: convertHeaders(c.req.header()),\n size: requestSize,\n consumer: consumer?.identifier,\n body: requestBody,\n },\n {\n statusCode: statusCode,\n responseTime: responseTime / 1000,\n headers: convertHeaders(responseHeaders),\n size: responseSize,\n body: responseBody,\n },\n c.error,\n logs,\n );\n }\n });\n });\n };\n}\n\nexport function setConsumer(\n c: Context,\n consumer: ApitallyConsumer | string | null | undefined,\n) {\n c.set(\"apitallyConsumer\", consumer || undefined);\n}\n\nfunction getConsumer(c: Context) {\n const consumer = c.get(\"apitallyConsumer\");\n if (consumer) {\n return consumerFromStringOrObject(consumer);\n }\n return null;\n}\n"],"mappings":"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","names":["AsyncLocalStorage","performance","ApitallyClient","consumerFromStringOrObject","parseContentLength","convertHeaders","captureResponse","getResponseJson","patchConsole","patchWinston","extractZodErrors","getAppInfo","useApitally","app","config","client","middleware","getMiddleware","use","setStartupData","attempt","appInfo","appVersion","paths","length","startSync","setTimeout","logsContext","requestLogger","captureLogs","c","next","isEnabled","req","method","toUpperCase","run","timestamp","Date","now","startTime","newResponse","responsePromise","res","captureBody","enabled","logResponseBody","isSupportedContentType","headers","get","status","maxBodySize","statusCode","responseHeaders","then","capturedResponse","responseTime","requestSize","header","responseSize","completed","size","undefined","consumer","getConsumer","consumerRegistry","addOrUpdateConsumer","requestCounter","addRequest","identifier","path","routePath","body","responseJson","validationErrors","forEach","error","validationErrorCounter","addValidationError","serverErrorCounter","addServerError","type","name","msg","message","traceback","stack","requestBody","responseBody","requestContentType","logRequestBody","Buffer","from","arrayBuffer","logs","getStore","logRequest","url","setConsumer","set"]}
|
|
1
|
+
{"version":3,"sources":["../../src/hono/middleware.ts"],"sourcesContent":["import { Context, Hono } from \"hono\";\nimport { MiddlewareHandler } from \"hono/types\";\nimport { AsyncLocalStorage } from \"node:async_hooks\";\nimport { performance } from \"node:perf_hooks\";\n\nimport { ApitallyClient } from \"../common/client.js\";\nimport { consumerFromStringOrObject } from \"../common/consumerRegistry.js\";\nimport { parseContentLength } from \"../common/headers.js\";\nimport type { LogRecord } from \"../common/requestLogger.js\";\nimport { convertHeaders } from \"../common/requestLogger.js\";\nimport { captureResponse, getResponseJson } from \"../common/response.js\";\nimport { ApitallyConfig, ApitallyConsumer } from \"../common/types.js\";\nimport { patchConsole, patchWinston } from \"../loggers/index.js\";\nimport { extractZodErrors, getAppInfo } from \"./utils.js\";\n\ndeclare module \"hono\" {\n interface ContextVariableMap {\n apitallyConsumer?: ApitallyConsumer | string;\n }\n}\n\nexport function useApitally(app: Hono, config: ApitallyConfig) {\n const client = new ApitallyClient(config);\n const middleware = getMiddleware(client);\n app.use(middleware);\n\n const setStartupData = (attempt: number = 1) => {\n const appInfo = getAppInfo(app, config.appVersion);\n if (appInfo.paths.length > 0 || attempt >= 10) {\n client.setStartupData(appInfo);\n client.startSync();\n } else {\n setTimeout(() => setStartupData(attempt + 1), 500);\n }\n };\n setTimeout(() => setStartupData(), 500);\n}\n\nfunction getMiddleware(client: ApitallyClient): MiddlewareHandler {\n const logsContext = new AsyncLocalStorage<LogRecord[]>();\n\n if (client.requestLogger.config.captureLogs) {\n patchConsole(logsContext);\n patchWinston(logsContext);\n }\n\n return async (c, next) => {\n if (!client.isEnabled() || c.req.method.toUpperCase() === \"OPTIONS\") {\n await next();\n return;\n }\n\n await logsContext.run([], async () => {\n const timestamp = Date.now() / 1000;\n const startTime = performance.now();\n\n const spanHandle = client.spanCollector.startSpan();\n await spanHandle.runInContext(next);\n\n const [newResponse, responsePromise] = captureResponse(c.res, {\n captureBody:\n (client.requestLogger.enabled &&\n client.requestLogger.config.logResponseBody &&\n client.requestLogger.isSupportedContentType(\n c.res.headers.get(\"content-type\"),\n )) ||\n (c.res.status === 400 &&\n c.res.headers.get(\"content-type\") === \"application/json\"),\n maxBodySize: client.requestLogger.maxBodySize,\n });\n c.res = newResponse;\n\n const statusCode = c.res.status;\n const responseHeaders = c.res.headers;\n\n responsePromise.then(async (capturedResponse) => {\n const responseTime = performance.now() - startTime;\n\n spanHandle.setName(`${c.req.method} ${c.req.routePath}`);\n const spans = spanHandle.end();\n const traceId = spanHandle.traceId;\n\n const requestSize = parseContentLength(c.req.header(\"content-length\"));\n const responseSize = capturedResponse.completed\n ? capturedResponse.size\n : undefined;\n\n const consumer = getConsumer(c);\n client.consumerRegistry.addOrUpdateConsumer(consumer);\n\n client.requestCounter.addRequest({\n consumer: consumer?.identifier,\n method: c.req.method,\n path: c.req.routePath,\n statusCode,\n responseTime,\n requestSize,\n responseSize,\n });\n\n if (statusCode === 400 && capturedResponse.body) {\n const responseJson = getResponseJson(capturedResponse.body);\n const validationErrors = extractZodErrors(responseJson);\n validationErrors.forEach((error) => {\n client.validationErrorCounter.addValidationError({\n consumer: consumer?.identifier,\n method: c.req.method,\n path: c.req.routePath,\n ...error,\n });\n });\n }\n\n if (c.error) {\n client.serverErrorCounter.addServerError({\n consumer: consumer?.identifier,\n method: c.req.method,\n path: c.req.routePath,\n type: c.error.name,\n msg: c.error.message,\n traceback: c.error.stack || \"\",\n });\n }\n\n if (client.requestLogger.enabled) {\n let requestBody;\n const responseBody = capturedResponse.body;\n const requestContentType = c.req.header(\"content-type\");\n if (\n client.requestLogger.config.logRequestBody &&\n client.requestLogger.isSupportedContentType(requestContentType)\n ) {\n requestBody = Buffer.from(await c.req.arrayBuffer());\n }\n const logs = logsContext.getStore();\n client.requestLogger.logRequest(\n {\n timestamp,\n method: c.req.method,\n path: c.req.routePath,\n url: c.req.url,\n headers: convertHeaders(c.req.header()),\n size: requestSize,\n consumer: consumer?.identifier,\n body: requestBody,\n },\n {\n statusCode: statusCode,\n responseTime: responseTime / 1000,\n headers: convertHeaders(responseHeaders),\n size: responseSize,\n body: responseBody,\n },\n c.error,\n logs,\n spans,\n traceId,\n );\n }\n });\n });\n };\n}\n\nexport function setConsumer(\n c: Context,\n consumer: ApitallyConsumer | string | null | undefined,\n) {\n c.set(\"apitallyConsumer\", consumer || undefined);\n}\n\nfunction getConsumer(c: Context) {\n const consumer = c.get(\"apitallyConsumer\");\n if (consumer) {\n return consumerFromStringOrObject(consumer);\n }\n return null;\n}\n"],"mappings":"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","names":["AsyncLocalStorage","performance","ApitallyClient","consumerFromStringOrObject","parseContentLength","convertHeaders","captureResponse","getResponseJson","patchConsole","patchWinston","extractZodErrors","getAppInfo","useApitally","app","config","client","middleware","getMiddleware","use","setStartupData","attempt","appInfo","appVersion","paths","length","startSync","setTimeout","logsContext","requestLogger","captureLogs","c","next","isEnabled","req","method","toUpperCase","run","timestamp","Date","now","startTime","spanHandle","spanCollector","startSpan","runInContext","newResponse","responsePromise","res","captureBody","enabled","logResponseBody","isSupportedContentType","headers","get","status","maxBodySize","statusCode","responseHeaders","then","capturedResponse","responseTime","setName","routePath","spans","end","traceId","requestSize","header","responseSize","completed","size","undefined","consumer","getConsumer","consumerRegistry","addOrUpdateConsumer","requestCounter","addRequest","identifier","path","body","responseJson","validationErrors","forEach","error","validationErrorCounter","addValidationError","serverErrorCounter","addServerError","type","name","msg","message","traceback","stack","requestBody","responseBody","requestContentType","logRequestBody","Buffer","from","arrayBuffer","logs","getStore","logRequest","url","setConsumer","set"]}
|
package/dist/hono/utils.d.cts
CHANGED
|
@@ -5,6 +5,8 @@ import 'winston';
|
|
|
5
5
|
import '../common/requestLogger.cjs';
|
|
6
6
|
import 'node:buffer';
|
|
7
7
|
import 'node:http';
|
|
8
|
+
import '../common/spanCollector.cjs';
|
|
9
|
+
import '@opentelemetry/sdk-trace-base';
|
|
8
10
|
import '../common/tempGzipFile.cjs';
|
|
9
11
|
|
|
10
12
|
declare function getAppInfo(app: Hono, appVersion?: string): StartupData;
|
package/dist/hono/utils.d.ts
CHANGED
|
@@ -5,6 +5,8 @@ import 'winston';
|
|
|
5
5
|
import '../common/requestLogger.js';
|
|
6
6
|
import 'node:buffer';
|
|
7
7
|
import 'node:http';
|
|
8
|
+
import '../common/spanCollector.js';
|
|
9
|
+
import '@opentelemetry/sdk-trace-base';
|
|
8
10
|
import '../common/tempGzipFile.js';
|
|
9
11
|
|
|
10
12
|
declare function getAppInfo(app: Hono, appVersion?: string): StartupData;
|
package/dist/koa/index.cjs
CHANGED
|
@@ -18,13 +18,16 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
18
18
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
19
|
var koa_exports = {};
|
|
20
20
|
__export(koa_exports, {
|
|
21
|
+
ApitallySpanProcessor: () => import_spanCollector.ApitallySpanProcessor,
|
|
21
22
|
setConsumer: () => import_middleware.setConsumer,
|
|
22
23
|
useApitally: () => import_middleware.useApitally
|
|
23
24
|
});
|
|
24
25
|
module.exports = __toCommonJS(koa_exports);
|
|
26
|
+
var import_spanCollector = require("../common/spanCollector.js");
|
|
25
27
|
var import_middleware = require("./middleware.js");
|
|
26
28
|
// Annotate the CommonJS export names for ESM import in node:
|
|
27
29
|
0 && (module.exports = {
|
|
30
|
+
ApitallySpanProcessor,
|
|
28
31
|
setConsumer,
|
|
29
32
|
useApitally
|
|
30
33
|
});
|
package/dist/koa/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/koa/index.ts"],"sourcesContent":["export type { ApitallyConfig, ApitallyConsumer } from \"../common/types.js\";\nexport { setConsumer, useApitally } from \"./middleware.js\";\n"],"mappings":";;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"sources":["../../src/koa/index.ts"],"sourcesContent":["export { ApitallySpanProcessor } from \"../common/spanCollector.js\";\nexport type { ApitallyConfig, ApitallyConsumer } from \"../common/types.js\";\nexport { setConsumer, useApitally } from \"./middleware.js\";\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;;;;;;;2BAAsC;AAEtC,wBAAyC;","names":[]}
|
package/dist/koa/index.d.cts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
export { ApitallySpanProcessor } from '../common/spanCollector.cjs';
|
|
1
2
|
export { ApitallyConfig, ApitallyConsumer } from '../common/types.cjs';
|
|
2
3
|
export { setConsumer, useApitally } from './middleware.cjs';
|
|
4
|
+
import '@opentelemetry/sdk-trace-base';
|
|
3
5
|
import '../common/logging.cjs';
|
|
4
6
|
import 'winston';
|
|
5
7
|
import '../common/requestLogger.cjs';
|
package/dist/koa/index.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
export { ApitallySpanProcessor } from '../common/spanCollector.js';
|
|
1
2
|
export { ApitallyConfig, ApitallyConsumer } from '../common/types.js';
|
|
2
3
|
export { setConsumer, useApitally } from './middleware.js';
|
|
4
|
+
import '@opentelemetry/sdk-trace-base';
|
|
3
5
|
import '../common/logging.js';
|
|
4
6
|
import 'winston';
|
|
5
7
|
import '../common/requestLogger.js';
|
package/dist/koa/index.js
CHANGED
package/dist/koa/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/koa/index.ts"],"sourcesContent":["export type { ApitallyConfig, ApitallyConsumer } from \"../common/types.js\";\nexport { setConsumer, useApitally } from \"./middleware.js\";\n"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../../src/koa/index.ts"],"sourcesContent":["export { ApitallySpanProcessor } from \"../common/spanCollector.js\";\nexport type { ApitallyConfig, ApitallyConsumer } from \"../common/types.js\";\nexport { setConsumer, useApitally } from \"./middleware.js\";\n"],"mappings":"AAAA,SAASA,6BAA6B;AAEtC,SAASC,aAAaC,mBAAmB;","names":["ApitallySpanProcessor","setConsumer","useApitally"]}
|
package/dist/koa/middleware.cjs
CHANGED
|
@@ -62,8 +62,9 @@ function getMiddleware(client) {
|
|
|
62
62
|
let statusCode;
|
|
63
63
|
let serverError;
|
|
64
64
|
const startTime = performance.now();
|
|
65
|
+
const spanHandle = client.spanCollector.startSpan();
|
|
65
66
|
try {
|
|
66
|
-
await next
|
|
67
|
+
await spanHandle.runInContext(next);
|
|
67
68
|
} catch (error) {
|
|
68
69
|
path = getPath(ctx);
|
|
69
70
|
statusCode = error.statusCode || error.status || 500;
|
|
@@ -81,11 +82,14 @@ function getMiddleware(client) {
|
|
|
81
82
|
throw error;
|
|
82
83
|
} finally {
|
|
83
84
|
const responseTime = performance.now() - startTime;
|
|
84
|
-
const consumer = getConsumer(ctx);
|
|
85
|
-
client.consumerRegistry.addOrUpdateConsumer(consumer);
|
|
86
85
|
if (!path) {
|
|
87
86
|
path = getPath(ctx);
|
|
88
87
|
}
|
|
88
|
+
spanHandle.setName(`${ctx.request.method} ${path}`);
|
|
89
|
+
const spans = spanHandle.end();
|
|
90
|
+
const traceId = spanHandle.traceId;
|
|
91
|
+
const consumer = getConsumer(ctx);
|
|
92
|
+
client.consumerRegistry.addOrUpdateConsumer(consumer);
|
|
89
93
|
if (path) {
|
|
90
94
|
try {
|
|
91
95
|
client.requestCounter.addRequest({
|
|
@@ -121,7 +125,7 @@ function getMiddleware(client) {
|
|
|
121
125
|
headers: (0, import_requestLogger.convertHeaders)(ctx.response.headers),
|
|
122
126
|
size: ctx.response.length,
|
|
123
127
|
body: (0, import_requestLogger.convertBody)(ctx.response.body, ctx.response.get("content-type"))
|
|
124
|
-
}, serverError, logs);
|
|
128
|
+
}, serverError, logs, spans, traceId);
|
|
125
129
|
}
|
|
126
130
|
}
|
|
127
131
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/koa/middleware.ts"],"sourcesContent":["import Koa from \"koa\";\nimport { AsyncLocalStorage } from \"node:async_hooks\";\n\nimport { ApitallyClient } from \"../common/client.js\";\nimport { consumerFromStringOrObject } from \"../common/consumerRegistry.js\";\nimport { getPackageVersion } from \"../common/packageVersions.js\";\nimport type { LogRecord } from \"../common/requestLogger.js\";\nimport { convertBody, convertHeaders } from \"../common/requestLogger.js\";\nimport {\n ApitallyConfig,\n ApitallyConsumer,\n PathInfo,\n StartupData,\n} from \"../common/types.js\";\nimport { patchConsole, patchWinston } from \"../loggers/index.js\";\n\nexport function useApitally(app: Koa, config: ApitallyConfig) {\n const client = new ApitallyClient(config);\n const middleware = getMiddleware(client);\n app.use(middleware);\n\n const setStartupData = (attempt: number = 1) => {\n const appInfo = getAppInfo(app, config.appVersion);\n if (appInfo.paths.length > 0 || attempt >= 10) {\n client.setStartupData(appInfo);\n client.startSync();\n } else {\n setTimeout(() => setStartupData(attempt + 1), 500);\n }\n };\n setTimeout(() => setStartupData(), 500);\n}\n\nfunction getMiddleware(client: ApitallyClient) {\n const logsContext = new AsyncLocalStorage<LogRecord[]>();\n\n if (client.requestLogger.config.captureLogs) {\n patchConsole(logsContext);\n patchWinston(logsContext);\n }\n\n return async (ctx: Koa.Context, next: Koa.Next) => {\n if (!client.isEnabled() || ctx.request.method.toUpperCase() === \"OPTIONS\") {\n await next();\n return;\n }\n\n await logsContext.run([], async () => {\n let path: string | undefined;\n let statusCode: number | undefined;\n let serverError: Error | undefined;\n const startTime = performance.now();\n try {\n await next();\n } catch (error: any) {\n path = getPath(ctx);\n statusCode = error.statusCode || error.status || 500;\n if (path && statusCode === 500 && error instanceof Error) {\n serverError = error;\n client.serverErrorCounter.addServerError({\n consumer: getConsumer(ctx)?.identifier,\n method: ctx.request.method,\n path,\n type: error.name,\n msg: error.message,\n traceback: error.stack || \"\",\n });\n }\n throw error;\n } finally {\n const responseTime = performance.now() - startTime;\n const consumer = getConsumer(ctx);\n client.consumerRegistry.addOrUpdateConsumer(consumer);\n if (!path) {\n path = getPath(ctx);\n }\n if (path) {\n try {\n client.requestCounter.addRequest({\n consumer: consumer?.identifier,\n method: ctx.request.method,\n path,\n statusCode: statusCode || ctx.response.status,\n responseTime,\n requestSize: ctx.request.length,\n responseSize: ctx.response.length,\n });\n } catch (error) {\n client.logger.error(\n \"Error while logging request in Apitally middleware.\",\n { context: ctx, error },\n );\n }\n }\n if (client.requestLogger.enabled) {\n const logs = logsContext.getStore();\n client.requestLogger.logRequest(\n {\n timestamp: Date.now() / 1000,\n method: ctx.request.method,\n path,\n url: ctx.request.href,\n headers: convertHeaders(ctx.request.headers),\n size: ctx.request.length,\n consumer: consumer?.identifier,\n body: convertBody(\n ctx.request.body,\n ctx.request.get(\"content-type\"),\n ),\n },\n {\n statusCode: statusCode || ctx.response.status,\n responseTime: responseTime / 1000,\n headers: convertHeaders(ctx.response.headers),\n size: ctx.response.length,\n body: convertBody(\n ctx.response.body,\n ctx.response.get(\"content-type\"),\n ),\n },\n serverError,\n logs,\n );\n }\n }\n });\n };\n}\n\nfunction getPath(ctx: Koa.Context) {\n return ctx._matchedRoute || ctx.routePath; // _matchedRoute is set by koa-router, routePath is set by koa-route\n}\n\nexport function setConsumer(\n ctx: Koa.Context,\n consumer: ApitallyConsumer | string | null | undefined,\n) {\n ctx.state.apitallyConsumer = consumer || undefined;\n}\n\nfunction getConsumer(ctx: Koa.Context) {\n if (ctx.state.apitallyConsumer) {\n return consumerFromStringOrObject(ctx.state.apitallyConsumer);\n } else if (ctx.state.consumerIdentifier) {\n // For backwards compatibility\n process.emitWarning(\n \"The consumerIdentifier property on the ctx.state object is deprecated. Use apitallyConsumer instead.\",\n \"DeprecationWarning\",\n );\n return consumerFromStringOrObject(ctx.state.consumerIdentifier);\n }\n return null;\n}\n\nfunction getAppInfo(app: Koa, appVersion?: string): StartupData {\n const versions: Array<[string, string]> = [\n [\"nodejs\", process.version.replace(/^v/, \"\")],\n ];\n const koaVersion = getPackageVersion(\"koa\");\n const apitallyVersion = getPackageVersion(\"../..\");\n if (koaVersion) {\n versions.push([\"koa\", koaVersion]);\n }\n if (apitallyVersion) {\n versions.push([\"apitally\", apitallyVersion]);\n }\n if (appVersion) {\n versions.push([\"app\", appVersion]);\n }\n return {\n paths: listEndpoints(app),\n versions: Object.fromEntries(versions),\n client: \"js:koa\",\n };\n}\n\nfunction isKoaRouterMiddleware(middleware: any) {\n return (\n typeof middleware === \"function\" &&\n middleware.router &&\n Array.isArray(middleware.router.stack)\n );\n}\n\nfunction listEndpoints(app: Koa) {\n const endpoints: Array<PathInfo> = [];\n app.middleware.forEach((middleware: any) => {\n if (isKoaRouterMiddleware(middleware)) {\n middleware.router.stack.forEach((layer: any) => {\n if (layer.methods && layer.methods.length > 0) {\n layer.methods.forEach((method: string) => {\n if (![\"HEAD\", \"OPTIONS\"].includes(method.toUpperCase())) {\n endpoints.push({\n method: method.toUpperCase(),\n path: layer.path,\n });\n }\n });\n }\n });\n }\n });\n return endpoints;\n}\n"],"mappings":"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","names":["useApitally","app","config","client","ApitallyClient","middleware","getMiddleware","use","setStartupData","attempt","appInfo","getAppInfo","appVersion","paths","length","startSync","setTimeout","logsContext","AsyncLocalStorage","requestLogger","captureLogs","patchConsole","patchWinston","ctx","next","isEnabled","request","method","toUpperCase","run","path","statusCode","serverError","startTime","performance","now","error","getPath","status","Error","serverErrorCounter","addServerError","consumer","getConsumer","identifier","type","name","msg","message","traceback","stack","responseTime","consumerRegistry","addOrUpdateConsumer","requestCounter","addRequest","response","requestSize","responseSize","logger","context","enabled","logs","getStore","logRequest","timestamp","Date","url","href","headers","convertHeaders","size","body","convertBody","get","_matchedRoute","routePath","setConsumer","state","apitallyConsumer","undefined","consumerFromStringOrObject","consumerIdentifier","process","emitWarning","versions","version","replace","koaVersion","getPackageVersion","apitallyVersion","push","listEndpoints","Object","fromEntries","isKoaRouterMiddleware","router","Array","isArray","endpoints","forEach","layer","methods","includes"]}
|
|
1
|
+
{"version":3,"sources":["../../src/koa/middleware.ts"],"sourcesContent":["import Koa from \"koa\";\nimport { AsyncLocalStorage } from \"node:async_hooks\";\n\nimport { ApitallyClient } from \"../common/client.js\";\nimport { consumerFromStringOrObject } from \"../common/consumerRegistry.js\";\nimport { getPackageVersion } from \"../common/packageVersions.js\";\nimport type { LogRecord } from \"../common/requestLogger.js\";\nimport { convertBody, convertHeaders } from \"../common/requestLogger.js\";\nimport {\n ApitallyConfig,\n ApitallyConsumer,\n PathInfo,\n StartupData,\n} from \"../common/types.js\";\nimport { patchConsole, patchWinston } from \"../loggers/index.js\";\n\nexport function useApitally(app: Koa, config: ApitallyConfig) {\n const client = new ApitallyClient(config);\n const middleware = getMiddleware(client);\n app.use(middleware);\n\n const setStartupData = (attempt: number = 1) => {\n const appInfo = getAppInfo(app, config.appVersion);\n if (appInfo.paths.length > 0 || attempt >= 10) {\n client.setStartupData(appInfo);\n client.startSync();\n } else {\n setTimeout(() => setStartupData(attempt + 1), 500);\n }\n };\n setTimeout(() => setStartupData(), 500);\n}\n\nfunction getMiddleware(client: ApitallyClient) {\n const logsContext = new AsyncLocalStorage<LogRecord[]>();\n\n if (client.requestLogger.config.captureLogs) {\n patchConsole(logsContext);\n patchWinston(logsContext);\n }\n\n return async (ctx: Koa.Context, next: Koa.Next) => {\n if (!client.isEnabled() || ctx.request.method.toUpperCase() === \"OPTIONS\") {\n await next();\n return;\n }\n\n await logsContext.run([], async () => {\n let path: string | undefined;\n let statusCode: number | undefined;\n let serverError: Error | undefined;\n const startTime = performance.now();\n const spanHandle = client.spanCollector.startSpan();\n try {\n await spanHandle.runInContext(next);\n } catch (error: any) {\n path = getPath(ctx);\n statusCode = error.statusCode || error.status || 500;\n if (path && statusCode === 500 && error instanceof Error) {\n serverError = error;\n client.serverErrorCounter.addServerError({\n consumer: getConsumer(ctx)?.identifier,\n method: ctx.request.method,\n path,\n type: error.name,\n msg: error.message,\n traceback: error.stack || \"\",\n });\n }\n throw error;\n } finally {\n const responseTime = performance.now() - startTime;\n\n if (!path) {\n path = getPath(ctx);\n }\n\n spanHandle.setName(`${ctx.request.method} ${path}`);\n const spans = spanHandle.end();\n const traceId = spanHandle.traceId;\n\n const consumer = getConsumer(ctx);\n client.consumerRegistry.addOrUpdateConsumer(consumer);\n\n if (path) {\n try {\n client.requestCounter.addRequest({\n consumer: consumer?.identifier,\n method: ctx.request.method,\n path,\n statusCode: statusCode || ctx.response.status,\n responseTime,\n requestSize: ctx.request.length,\n responseSize: ctx.response.length,\n });\n } catch (error) {\n client.logger.error(\n \"Error while logging request in Apitally middleware.\",\n { context: ctx, error },\n );\n }\n }\n\n if (client.requestLogger.enabled) {\n const logs = logsContext.getStore();\n client.requestLogger.logRequest(\n {\n timestamp: Date.now() / 1000,\n method: ctx.request.method,\n path,\n url: ctx.request.href,\n headers: convertHeaders(ctx.request.headers),\n size: ctx.request.length,\n consumer: consumer?.identifier,\n body: convertBody(\n ctx.request.body,\n ctx.request.get(\"content-type\"),\n ),\n },\n {\n statusCode: statusCode || ctx.response.status,\n responseTime: responseTime / 1000,\n headers: convertHeaders(ctx.response.headers),\n size: ctx.response.length,\n body: convertBody(\n ctx.response.body,\n ctx.response.get(\"content-type\"),\n ),\n },\n serverError,\n logs,\n spans,\n traceId,\n );\n }\n }\n });\n };\n}\n\nfunction getPath(ctx: Koa.Context) {\n return ctx._matchedRoute || ctx.routePath; // _matchedRoute is set by koa-router, routePath is set by koa-route\n}\n\nexport function setConsumer(\n ctx: Koa.Context,\n consumer: ApitallyConsumer | string | null | undefined,\n) {\n ctx.state.apitallyConsumer = consumer || undefined;\n}\n\nfunction getConsumer(ctx: Koa.Context) {\n if (ctx.state.apitallyConsumer) {\n return consumerFromStringOrObject(ctx.state.apitallyConsumer);\n } else if (ctx.state.consumerIdentifier) {\n // For backwards compatibility\n process.emitWarning(\n \"The consumerIdentifier property on the ctx.state object is deprecated. Use apitallyConsumer instead.\",\n \"DeprecationWarning\",\n );\n return consumerFromStringOrObject(ctx.state.consumerIdentifier);\n }\n return null;\n}\n\nfunction getAppInfo(app: Koa, appVersion?: string): StartupData {\n const versions: Array<[string, string]> = [\n [\"nodejs\", process.version.replace(/^v/, \"\")],\n ];\n const koaVersion = getPackageVersion(\"koa\");\n const apitallyVersion = getPackageVersion(\"../..\");\n if (koaVersion) {\n versions.push([\"koa\", koaVersion]);\n }\n if (apitallyVersion) {\n versions.push([\"apitally\", apitallyVersion]);\n }\n if (appVersion) {\n versions.push([\"app\", appVersion]);\n }\n return {\n paths: listEndpoints(app),\n versions: Object.fromEntries(versions),\n client: \"js:koa\",\n };\n}\n\nfunction isKoaRouterMiddleware(middleware: any) {\n return (\n typeof middleware === \"function\" &&\n middleware.router &&\n Array.isArray(middleware.router.stack)\n );\n}\n\nfunction listEndpoints(app: Koa) {\n const endpoints: Array<PathInfo> = [];\n app.middleware.forEach((middleware: any) => {\n if (isKoaRouterMiddleware(middleware)) {\n middleware.router.stack.forEach((layer: any) => {\n if (layer.methods && layer.methods.length > 0) {\n layer.methods.forEach((method: string) => {\n if (![\"HEAD\", \"OPTIONS\"].includes(method.toUpperCase())) {\n endpoints.push({\n method: method.toUpperCase(),\n path: layer.path,\n });\n }\n });\n }\n });\n }\n });\n return endpoints;\n}\n"],"mappings":"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","names":["useApitally","app","config","client","ApitallyClient","middleware","getMiddleware","use","setStartupData","attempt","appInfo","getAppInfo","appVersion","paths","length","startSync","setTimeout","logsContext","AsyncLocalStorage","requestLogger","captureLogs","patchConsole","patchWinston","ctx","next","isEnabled","request","method","toUpperCase","run","path","statusCode","serverError","startTime","performance","now","spanHandle","spanCollector","startSpan","runInContext","error","getPath","status","Error","serverErrorCounter","addServerError","consumer","getConsumer","identifier","type","name","msg","message","traceback","stack","responseTime","setName","spans","end","traceId","consumerRegistry","addOrUpdateConsumer","requestCounter","addRequest","response","requestSize","responseSize","logger","context","enabled","logs","getStore","logRequest","timestamp","Date","url","href","headers","convertHeaders","size","body","convertBody","get","_matchedRoute","routePath","setConsumer","state","apitallyConsumer","undefined","consumerFromStringOrObject","consumerIdentifier","process","emitWarning","versions","version","replace","koaVersion","getPackageVersion","apitallyVersion","push","listEndpoints","Object","fromEntries","isKoaRouterMiddleware","router","Array","isArray","endpoints","forEach","layer","methods","includes"]}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import '../common/spanCollector.cjs';
|
|
1
2
|
import { ApitallyConsumer, ApitallyConfig } from '../common/types.cjs';
|
|
2
3
|
import Koa from 'koa';
|
|
4
|
+
import '@opentelemetry/sdk-trace-base';
|
|
3
5
|
import '../common/logging.cjs';
|
|
4
6
|
import 'winston';
|
|
5
7
|
import '../common/requestLogger.cjs';
|
package/dist/koa/middleware.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import '../common/spanCollector.js';
|
|
1
2
|
import { ApitallyConsumer, ApitallyConfig } from '../common/types.js';
|
|
2
3
|
import Koa from 'koa';
|
|
4
|
+
import '@opentelemetry/sdk-trace-base';
|
|
3
5
|
import '../common/logging.js';
|
|
4
6
|
import 'winston';
|
|
5
7
|
import '../common/requestLogger.js';
|
package/dist/koa/middleware.js
CHANGED
|
@@ -39,8 +39,9 @@ function getMiddleware(client) {
|
|
|
39
39
|
let statusCode;
|
|
40
40
|
let serverError;
|
|
41
41
|
const startTime = performance.now();
|
|
42
|
+
const spanHandle = client.spanCollector.startSpan();
|
|
42
43
|
try {
|
|
43
|
-
await next
|
|
44
|
+
await spanHandle.runInContext(next);
|
|
44
45
|
} catch (error) {
|
|
45
46
|
path = getPath(ctx);
|
|
46
47
|
statusCode = error.statusCode || error.status || 500;
|
|
@@ -58,11 +59,14 @@ function getMiddleware(client) {
|
|
|
58
59
|
throw error;
|
|
59
60
|
} finally {
|
|
60
61
|
const responseTime = performance.now() - startTime;
|
|
61
|
-
const consumer = getConsumer(ctx);
|
|
62
|
-
client.consumerRegistry.addOrUpdateConsumer(consumer);
|
|
63
62
|
if (!path) {
|
|
64
63
|
path = getPath(ctx);
|
|
65
64
|
}
|
|
65
|
+
spanHandle.setName(`${ctx.request.method} ${path}`);
|
|
66
|
+
const spans = spanHandle.end();
|
|
67
|
+
const traceId = spanHandle.traceId;
|
|
68
|
+
const consumer = getConsumer(ctx);
|
|
69
|
+
client.consumerRegistry.addOrUpdateConsumer(consumer);
|
|
66
70
|
if (path) {
|
|
67
71
|
try {
|
|
68
72
|
client.requestCounter.addRequest({
|
|
@@ -98,7 +102,7 @@ function getMiddleware(client) {
|
|
|
98
102
|
headers: convertHeaders(ctx.response.headers),
|
|
99
103
|
size: ctx.response.length,
|
|
100
104
|
body: convertBody(ctx.response.body, ctx.response.get("content-type"))
|
|
101
|
-
}, serverError, logs);
|
|
105
|
+
}, serverError, logs, spans, traceId);
|
|
102
106
|
}
|
|
103
107
|
}
|
|
104
108
|
});
|