apitally 0.21.5 → 0.22.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.
- package/dist/common/requestLogger.cjs +23 -12
- package/dist/common/requestLogger.cjs.map +1 -1
- package/dist/common/requestLogger.d.cts +1 -1
- package/dist/common/requestLogger.d.ts +1 -1
- package/dist/common/requestLogger.js +23 -12
- package/dist/common/requestLogger.js.map +1 -1
- package/dist/common/response.cjs +63 -105
- package/dist/common/response.cjs.map +1 -1
- package/dist/common/response.d.cts +14 -6
- package/dist/common/response.d.ts +14 -6
- package/dist/common/response.js +61 -100
- package/dist/common/response.js.map +1 -1
- package/dist/common/sentry.cjs +4 -1
- package/dist/common/sentry.cjs.map +1 -1
- package/dist/common/sentry.js +4 -1
- package/dist/common/sentry.js.map +1 -1
- package/dist/elysia/index.d.cts +6 -0
- package/dist/elysia/index.d.ts +6 -0
- package/dist/elysia/plugin.cjs +104 -76
- package/dist/elysia/plugin.cjs.map +1 -1
- package/dist/elysia/plugin.d.cts +10 -0
- package/dist/elysia/plugin.d.ts +10 -0
- package/dist/elysia/plugin.js +105 -77
- package/dist/elysia/plugin.js.map +1 -1
- package/dist/h3/plugin.cjs +59 -59
- package/dist/h3/plugin.cjs.map +1 -1
- package/dist/h3/plugin.js +60 -60
- package/dist/h3/plugin.js.map +1 -1
- package/dist/h3/utils.cjs +1 -1
- package/dist/h3/utils.cjs.map +1 -1
- package/dist/h3/utils.js +1 -1
- package/dist/h3/utils.js.map +1 -1
- package/dist/hono/middleware.cjs +63 -64
- package/dist/hono/middleware.cjs.map +1 -1
- package/dist/hono/middleware.js +64 -65
- package/dist/hono/middleware.js.map +1 -1
- package/dist/loggers/nestjs.cjs +4 -1
- package/dist/loggers/nestjs.cjs.map +1 -1
- package/dist/loggers/nestjs.js +4 -1
- package/dist/loggers/nestjs.js.map +1 -1
- package/dist/loggers/pino.cjs +4 -1
- package/dist/loggers/pino.cjs.map +1 -1
- package/dist/loggers/pino.js +4 -1
- package/dist/loggers/pino.js.map +1 -1
- package/dist/loggers/winston.cjs +5 -1
- package/dist/loggers/winston.cjs.map +1 -1
- package/dist/loggers/winston.js +5 -1
- package/dist/loggers/winston.js.map +1 -1
- package/package.json +7 -3
|
@@ -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 {\n getResponseBody,\n getResponseJson,\n measureResponseSize,\n} 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 let response;\n const responseTime = performance.now() - startTime;\n const [responseSize, newResponse] = await measureResponseSize(c.res);\n const requestSize = parseContentLength(c.req.header(\"content-length\"));\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: c.res.status,\n responseTime,\n requestSize,\n responseSize,\n });\n\n response = newResponse;\n\n if (c.res.status === 400) {\n const [responseJson, newResponse] = await getResponseJson(response);\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 response = newResponse;\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 let responseBody;\n let newResponse = response;\n const requestContentType = c.req.header(\"content-type\");\n const responseContentType = c.res.headers.get(\"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 if (\n client.requestLogger.config.logResponseBody &&\n client.requestLogger.isSupportedContentType(responseContentType)\n ) {\n [responseBody, newResponse] = await getResponseBody(response);\n response = newResponse;\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: c.res.status,\n responseTime: responseTime / 1000,\n headers: convertHeaders(c.res.headers),\n size: responseSize,\n body: responseBody,\n },\n c.error,\n logs,\n );\n }\n c.res = response;\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","response","responseTime","responseSize","newResponse","measureResponseSize","res","requestSize","parseContentLength","header","consumer","getConsumer","consumerRegistry","addOrUpdateConsumer","requestCounter","addRequest","identifier","path","routePath","statusCode","status","responseJson","getResponseJson","validationErrors","extractZodErrors","forEach","error","validationErrorCounter","addValidationError","serverErrorCounter","addServerError","type","name","msg","message","traceback","stack","enabled","requestBody","responseBody","requestContentType","responseContentType","headers","get","logRequestBody","isSupportedContentType","Buffer","from","arrayBuffer","logResponseBody","getResponseBody","logs","getStore","logRequest","url","convertHeaders","size","body","setConsumer","set","undefined","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 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"]}
|
package/dist/hono/middleware.js
CHANGED
|
@@ -6,7 +6,7 @@ import { ApitallyClient } from "../common/client.js";
|
|
|
6
6
|
import { consumerFromStringOrObject } from "../common/consumerRegistry.js";
|
|
7
7
|
import { parseContentLength } from "../common/headers.js";
|
|
8
8
|
import { convertHeaders } from "../common/requestLogger.js";
|
|
9
|
-
import {
|
|
9
|
+
import { captureResponse, getResponseJson } from "../common/response.js";
|
|
10
10
|
import { patchConsole, patchWinston } from "../loggers/index.js";
|
|
11
11
|
import { extractZodErrors, getAppInfo } from "./utils.js";
|
|
12
12
|
function useApitally(app, config) {
|
|
@@ -40,77 +40,76 @@ function getMiddleware(client) {
|
|
|
40
40
|
const timestamp = Date.now() / 1e3;
|
|
41
41
|
const startTime = performance.now();
|
|
42
42
|
await next();
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
const requestSize = parseContentLength(c.req.header("content-length"));
|
|
47
|
-
const consumer = getConsumer(c);
|
|
48
|
-
client.consumerRegistry.addOrUpdateConsumer(consumer);
|
|
49
|
-
client.requestCounter.addRequest({
|
|
50
|
-
consumer: consumer == null ? void 0 : consumer.identifier,
|
|
51
|
-
method: c.req.method,
|
|
52
|
-
path: c.req.routePath,
|
|
53
|
-
statusCode: c.res.status,
|
|
54
|
-
responseTime,
|
|
55
|
-
requestSize,
|
|
56
|
-
responseSize
|
|
43
|
+
const [newResponse, responsePromise] = captureResponse(c.res, {
|
|
44
|
+
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
|
+
maxBodySize: client.requestLogger.maxBodySize
|
|
57
46
|
});
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
});
|
|
69
|
-
});
|
|
70
|
-
response = newResponse2;
|
|
71
|
-
}
|
|
72
|
-
if (c.error) {
|
|
73
|
-
client.serverErrorCounter.addServerError({
|
|
47
|
+
c.res = newResponse;
|
|
48
|
+
const statusCode = c.res.status;
|
|
49
|
+
const responseHeaders = c.res.headers;
|
|
50
|
+
responsePromise.then(async (capturedResponse) => {
|
|
51
|
+
const responseTime = performance.now() - startTime;
|
|
52
|
+
const requestSize = parseContentLength(c.req.header("content-length"));
|
|
53
|
+
const responseSize = capturedResponse.completed ? capturedResponse.size : void 0;
|
|
54
|
+
const consumer = getConsumer(c);
|
|
55
|
+
client.consumerRegistry.addOrUpdateConsumer(consumer);
|
|
56
|
+
client.requestCounter.addRequest({
|
|
74
57
|
consumer: consumer == null ? void 0 : consumer.identifier,
|
|
75
58
|
method: c.req.method,
|
|
76
59
|
path: c.req.routePath,
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
60
|
+
statusCode,
|
|
61
|
+
responseTime,
|
|
62
|
+
requestSize,
|
|
63
|
+
responseSize
|
|
80
64
|
});
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
65
|
+
if (statusCode === 400 && capturedResponse.body) {
|
|
66
|
+
const responseJson = getResponseJson(capturedResponse.body);
|
|
67
|
+
const validationErrors = extractZodErrors(responseJson);
|
|
68
|
+
validationErrors.forEach((error) => {
|
|
69
|
+
client.validationErrorCounter.addValidationError({
|
|
70
|
+
consumer: consumer == null ? void 0 : consumer.identifier,
|
|
71
|
+
method: c.req.method,
|
|
72
|
+
path: c.req.routePath,
|
|
73
|
+
...error
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
if (c.error) {
|
|
78
|
+
client.serverErrorCounter.addServerError({
|
|
79
|
+
consumer: consumer == null ? void 0 : consumer.identifier,
|
|
80
|
+
method: c.req.method,
|
|
81
|
+
path: c.req.routePath,
|
|
82
|
+
type: c.error.name,
|
|
83
|
+
msg: c.error.message,
|
|
84
|
+
traceback: c.error.stack || ""
|
|
85
|
+
});
|
|
90
86
|
}
|
|
91
|
-
if (client.requestLogger.
|
|
92
|
-
|
|
93
|
-
|
|
87
|
+
if (client.requestLogger.enabled) {
|
|
88
|
+
let requestBody;
|
|
89
|
+
const responseBody = capturedResponse.body;
|
|
90
|
+
const requestContentType = c.req.header("content-type");
|
|
91
|
+
if (client.requestLogger.config.logRequestBody && client.requestLogger.isSupportedContentType(requestContentType)) {
|
|
92
|
+
requestBody = Buffer.from(await c.req.arrayBuffer());
|
|
93
|
+
}
|
|
94
|
+
const logs = logsContext.getStore();
|
|
95
|
+
client.requestLogger.logRequest({
|
|
96
|
+
timestamp,
|
|
97
|
+
method: c.req.method,
|
|
98
|
+
path: c.req.routePath,
|
|
99
|
+
url: c.req.url,
|
|
100
|
+
headers: convertHeaders(c.req.header()),
|
|
101
|
+
size: requestSize,
|
|
102
|
+
consumer: consumer == null ? void 0 : consumer.identifier,
|
|
103
|
+
body: requestBody
|
|
104
|
+
}, {
|
|
105
|
+
statusCode,
|
|
106
|
+
responseTime: responseTime / 1e3,
|
|
107
|
+
headers: convertHeaders(responseHeaders),
|
|
108
|
+
size: responseSize,
|
|
109
|
+
body: responseBody
|
|
110
|
+
}, c.error, logs);
|
|
94
111
|
}
|
|
95
|
-
|
|
96
|
-
client.requestLogger.logRequest({
|
|
97
|
-
timestamp,
|
|
98
|
-
method: c.req.method,
|
|
99
|
-
path: c.req.routePath,
|
|
100
|
-
url: c.req.url,
|
|
101
|
-
headers: convertHeaders(c.req.header()),
|
|
102
|
-
size: requestSize,
|
|
103
|
-
consumer: consumer == null ? void 0 : consumer.identifier,
|
|
104
|
-
body: requestBody
|
|
105
|
-
}, {
|
|
106
|
-
statusCode: c.res.status,
|
|
107
|
-
responseTime: responseTime / 1e3,
|
|
108
|
-
headers: convertHeaders(c.res.headers),
|
|
109
|
-
size: responseSize,
|
|
110
|
-
body: responseBody
|
|
111
|
-
}, c.error, logs);
|
|
112
|
-
}
|
|
113
|
-
c.res = response;
|
|
112
|
+
});
|
|
114
113
|
});
|
|
115
114
|
};
|
|
116
115
|
}
|
|
@@ -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 {\n getResponseBody,\n getResponseJson,\n measureResponseSize,\n} 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 let response;\n const responseTime = performance.now() - startTime;\n const [responseSize, newResponse] = await measureResponseSize(c.res);\n const requestSize = parseContentLength(c.req.header(\"content-length\"));\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: c.res.status,\n responseTime,\n requestSize,\n responseSize,\n });\n\n response = newResponse;\n\n if (c.res.status === 400) {\n const [responseJson, newResponse] = await getResponseJson(response);\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 response = newResponse;\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 let responseBody;\n let newResponse = response;\n const requestContentType = c.req.header(\"content-type\");\n const responseContentType = c.res.headers.get(\"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 if (\n client.requestLogger.config.logResponseBody &&\n client.requestLogger.isSupportedContentType(responseContentType)\n ) {\n [responseBody, newResponse] = await getResponseBody(response);\n response = newResponse;\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: c.res.status,\n responseTime: responseTime / 1000,\n headers: convertHeaders(c.res.headers),\n size: responseSize,\n body: responseBody,\n },\n c.error,\n logs,\n );\n }\n c.res = response;\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","getResponseBody","getResponseJson","measureResponseSize","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","response","responseTime","responseSize","newResponse","res","requestSize","header","consumer","getConsumer","consumerRegistry","addOrUpdateConsumer","requestCounter","addRequest","identifier","path","routePath","statusCode","status","responseJson","validationErrors","forEach","error","validationErrorCounter","addValidationError","serverErrorCounter","addServerError","type","name","msg","message","traceback","stack","enabled","requestBody","responseBody","requestContentType","responseContentType","headers","get","logRequestBody","isSupportedContentType","Buffer","from","arrayBuffer","logResponseBody","logs","getStore","logRequest","url","size","body","setConsumer","set","undefined"]}
|
|
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":";;AAEA,SAASA,yBAAyB;AAClC,SAASC,mBAAmB;AAE5B,SAASC,sBAAsB;AAC/B,SAASC,kCAAkC;AAC3C,SAASC,0BAA0B;AAEnC,SAASC,sBAAsB;AAC/B,SAASC,iBAAiBC,uBAAuB;AAEjD,SAASC,cAAcC,oBAAoB;AAC3C,SAASC,kBAAkBC,kBAAkB;AAQtC,SAASC,YAAYC,KAAWC,QAAsB;AAC3D,QAAMC,SAAS,IAAIb,eAAeY,MAAAA;AAClC,QAAME,aAAaC,cAAcF,MAAAA;AACjCF,MAAIK,IAAIF,UAAAA;AAER,QAAMG,iBAAiB,wBAACC,UAAkB,MAAC;AACzC,UAAMC,UAAUV,WAAWE,KAAKC,OAAOQ,UAAU;AACjD,QAAID,QAAQE,MAAMC,SAAS,KAAKJ,WAAW,IAAI;AAC7CL,aAAOI,eAAeE,OAAAA;AACtBN,aAAOU,UAAS;IAClB,OAAO;AACLC,iBAAW,MAAMP,eAAeC,UAAU,CAAA,GAAI,GAAA;IAChD;EACF,GARuB;AASvBM,aAAW,MAAMP,eAAAA,GAAkB,GAAA;AACrC;AAfgBP;AAiBhB,SAASK,cAAcF,QAAsB;AAC3C,QAAMY,cAAc,IAAI3B,kBAAAA;AAExB,MAAIe,OAAOa,cAAcd,OAAOe,aAAa;AAC3CrB,iBAAamB,WAAAA;AACblB,iBAAakB,WAAAA;EACf;AAEA,SAAO,OAAOG,GAAGC,SAAAA;AACf,QAAI,CAAChB,OAAOiB,UAAS,KAAMF,EAAEG,IAAIC,OAAOC,YAAW,MAAO,WAAW;AACnE,YAAMJ,KAAAA;AACN;IACF;AAEA,UAAMJ,YAAYS,IAAI,CAAA,GAAI,YAAA;AACxB,YAAMC,YAAYC,KAAKC,IAAG,IAAK;AAC/B,YAAMC,YAAYvC,YAAYsC,IAAG;AAEjC,YAAMR,KAAAA;AAEN,YAAM,CAACU,aAAaC,eAAAA,IAAmBpC,gBAAgBwB,EAAEa,KAAK;QAC5DC,aACG7B,OAAOa,cAAciB,WACpB9B,OAAOa,cAAcd,OAAOgC,mBAC5B/B,OAAOa,cAAcmB,uBACnBjB,EAAEa,IAAIK,QAAQC,IAAI,cAAA,CAAA,KAErBnB,EAAEa,IAAIO,WAAW,OAChBpB,EAAEa,IAAIK,QAAQC,IAAI,cAAA,MAAoB;QAC1CE,aAAapC,OAAOa,cAAcuB;MACpC,CAAA;AACArB,QAAEa,MAAMF;AAER,YAAMW,aAAatB,EAAEa,IAAIO;AACzB,YAAMG,kBAAkBvB,EAAEa,IAAIK;AAE9BN,sBAAgBY,KAAK,OAAOC,qBAAAA;AAC1B,cAAMC,eAAevD,YAAYsC,IAAG,IAAKC;AACzC,cAAMiB,cAAcrD,mBAAmB0B,EAAEG,IAAIyB,OAAO,gBAAA,CAAA;AACpD,cAAMC,eAAeJ,iBAAiBK,YAClCL,iBAAiBM,OACjBC;AAEJ,cAAMC,WAAWC,YAAYlC,CAAAA;AAC7Bf,eAAOkD,iBAAiBC,oBAAoBH,QAAAA;AAE5ChD,eAAOoD,eAAeC,WAAW;UAC/BL,UAAUA,qCAAUM;UACpBnC,QAAQJ,EAAEG,IAAIC;UACdoC,MAAMxC,EAAEG,IAAIsC;UACZnB;UACAI;UACAC;UACAE;QACF,CAAA;AAEA,YAAIP,eAAe,OAAOG,iBAAiBiB,MAAM;AAC/C,gBAAMC,eAAelE,gBAAgBgD,iBAAiBiB,IAAI;AAC1D,gBAAME,mBAAmBhE,iBAAiB+D,YAAAA;AAC1CC,2BAAiBC,QAAQ,CAACC,UAAAA;AACxB7D,mBAAO8D,uBAAuBC,mBAAmB;cAC/Cf,UAAUA,qCAAUM;cACpBnC,QAAQJ,EAAEG,IAAIC;cACdoC,MAAMxC,EAAEG,IAAIsC;cACZ,GAAGK;YACL,CAAA;UACF,CAAA;QACF;AAEA,YAAI9C,EAAE8C,OAAO;AACX7D,iBAAOgE,mBAAmBC,eAAe;YACvCjB,UAAUA,qCAAUM;YACpBnC,QAAQJ,EAAEG,IAAIC;YACdoC,MAAMxC,EAAEG,IAAIsC;YACZU,MAAMnD,EAAE8C,MAAMM;YACdC,KAAKrD,EAAE8C,MAAMQ;YACbC,WAAWvD,EAAE8C,MAAMU,SAAS;UAC9B,CAAA;QACF;AAEA,YAAIvE,OAAOa,cAAciB,SAAS;AAChC,cAAI0C;AACJ,gBAAMC,eAAejC,iBAAiBiB;AACtC,gBAAMiB,qBAAqB3D,EAAEG,IAAIyB,OAAO,cAAA;AACxC,cACE3C,OAAOa,cAAcd,OAAO4E,kBAC5B3E,OAAOa,cAAcmB,uBAAuB0C,kBAAAA,GAC5C;AACAF,0BAAcI,OAAOC,KAAK,MAAM9D,EAAEG,IAAI4D,YAAW,CAAA;UACnD;AACA,gBAAMC,OAAOnE,YAAYoE,SAAQ;AACjChF,iBAAOa,cAAcoE,WACnB;YACE3D;YACAH,QAAQJ,EAAEG,IAAIC;YACdoC,MAAMxC,EAAEG,IAAIsC;YACZ0B,KAAKnE,EAAEG,IAAIgE;YACXjD,SAAS3C,eAAeyB,EAAEG,IAAIyB,OAAM,CAAA;YACpCG,MAAMJ;YACNM,UAAUA,qCAAUM;YACpBG,MAAMe;UACR,GACA;YACEnC;YACAI,cAAcA,eAAe;YAC7BR,SAAS3C,eAAegD,eAAAA;YACxBQ,MAAMF;YACNa,MAAMgB;UACR,GACA1D,EAAE8C,OACFkB,IAAAA;QAEJ;MACF,CAAA;IACF,CAAA;EACF;AACF;AApHS7E;AAsHF,SAASiF,YACdpE,GACAiC,UAAsD;AAEtDjC,IAAEqE,IAAI,oBAAoBpC,YAAYD,MAAAA;AACxC;AALgBoC;AAOhB,SAASlC,YAAYlC,GAAU;AAC7B,QAAMiC,WAAWjC,EAAEmB,IAAI,kBAAA;AACvB,MAAIc,UAAU;AACZ,WAAO5D,2BAA2B4D,QAAAA;EACpC;AACA,SAAO;AACT;AANSC;","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"]}
|
package/dist/loggers/nestjs.cjs
CHANGED
|
@@ -42,7 +42,10 @@ async function patchNestLogger(logsContext) {
|
|
|
42
42
|
return;
|
|
43
43
|
}
|
|
44
44
|
try {
|
|
45
|
-
const { Logger } = await import(
|
|
45
|
+
const { Logger } = await import(
|
|
46
|
+
/* webpackIgnore: true */
|
|
47
|
+
"@nestjs/common"
|
|
48
|
+
);
|
|
46
49
|
const logMethods = [
|
|
47
50
|
"log",
|
|
48
51
|
"error",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/loggers/nestjs.ts"],"sourcesContent":["import { AsyncLocalStorage } from \"node:async_hooks\";\n\nimport type { LogRecord } from \"../common/requestLogger.js\";\nimport { formatMessage } from \"./utils.js\";\n\ntype LogLevel = \"log\" | \"error\" | \"warn\" | \"debug\" | \"verbose\" | \"fatal\";\n\nconst MAX_BUFFER_SIZE = 1000;\n\nlet isPatched = false;\nlet globalLogsContext: AsyncLocalStorage<LogRecord[]>;\n\nexport async function patchNestLogger(\n logsContext: AsyncLocalStorage<LogRecord[]>,\n) {\n globalLogsContext = logsContext;\n\n if (isPatched) {\n return;\n }\n\n try {\n const { Logger } = await import(\"@nestjs/common\");\n const logMethods: LogLevel[] = [\n \"log\",\n \"error\",\n \"warn\",\n \"debug\",\n \"verbose\",\n \"fatal\",\n ];\n\n // Patch static methods\n logMethods.forEach((method) => {\n const originalMethod = Logger[method];\n Logger[method] = function (message: any, ...args: any[]) {\n captureLog(method, [message, ...args]);\n return originalMethod.apply(Logger, [message, ...args]);\n };\n });\n\n // Patch prototype methods to affect all instances (new and existing)\n logMethods.forEach((method) => {\n const originalMethod = Logger.prototype[method];\n Logger.prototype[method] = function (message: any, ...args: any[]) {\n captureLog(method, [message, ...args], this.context);\n return originalMethod.apply(this, [message, ...args]);\n };\n });\n\n isPatched = true;\n } catch {\n // @nestjs/common is not installed, silently ignore\n }\n}\n\nfunction captureLog(level: LogLevel, args: any[], context?: string) {\n const logs = globalLogsContext?.getStore();\n if (logs && logs.length < MAX_BUFFER_SIZE) {\n logs.push({\n timestamp: Date.now() / 1000,\n logger: context,\n level,\n message: formatMessage(args[0], ...args.slice(1)),\n });\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAGA;;;;;AAAA,mBAA8B;AAI9B,MAAMA,kBAAkB;AAExB,IAAIC,YAAY;AAChB,IAAIC;AAEJ,eAAsBC,gBACpBC,aAA2C;AAE3CF,sBAAoBE;AAEpB,MAAIH,WAAW;AACb;EACF;AAEA,MAAI;AACF,UAAM,EAAEI,OAAM,IAAK,MAAM
|
|
1
|
+
{"version":3,"sources":["../../src/loggers/nestjs.ts"],"sourcesContent":["import { AsyncLocalStorage } from \"node:async_hooks\";\n\nimport type { LogRecord } from \"../common/requestLogger.js\";\nimport { formatMessage } from \"./utils.js\";\n\ntype LogLevel = \"log\" | \"error\" | \"warn\" | \"debug\" | \"verbose\" | \"fatal\";\n\nconst MAX_BUFFER_SIZE = 1000;\n\nlet isPatched = false;\nlet globalLogsContext: AsyncLocalStorage<LogRecord[]>;\n\nexport async function patchNestLogger(\n logsContext: AsyncLocalStorage<LogRecord[]>,\n) {\n globalLogsContext = logsContext;\n\n if (isPatched) {\n return;\n }\n\n try {\n const { Logger } = await import(/* webpackIgnore: true */ \"@nestjs/common\");\n const logMethods: LogLevel[] = [\n \"log\",\n \"error\",\n \"warn\",\n \"debug\",\n \"verbose\",\n \"fatal\",\n ];\n\n // Patch static methods\n logMethods.forEach((method) => {\n const originalMethod = Logger[method];\n Logger[method] = function (message: any, ...args: any[]) {\n captureLog(method, [message, ...args]);\n return originalMethod.apply(Logger, [message, ...args]);\n };\n });\n\n // Patch prototype methods to affect all instances (new and existing)\n logMethods.forEach((method) => {\n const originalMethod = Logger.prototype[method];\n Logger.prototype[method] = function (message: any, ...args: any[]) {\n captureLog(method, [message, ...args], this.context);\n return originalMethod.apply(this, [message, ...args]);\n };\n });\n\n isPatched = true;\n } catch {\n // @nestjs/common is not installed, silently ignore\n }\n}\n\nfunction captureLog(level: LogLevel, args: any[], context?: string) {\n const logs = globalLogsContext?.getStore();\n if (logs && logs.length < MAX_BUFFER_SIZE) {\n logs.push({\n timestamp: Date.now() / 1000,\n logger: context,\n level,\n message: formatMessage(args[0], ...args.slice(1)),\n });\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAGA;;;;;AAAA,mBAA8B;AAI9B,MAAMA,kBAAkB;AAExB,IAAIC,YAAY;AAChB,IAAIC;AAEJ,eAAsBC,gBACpBC,aAA2C;AAE3CF,sBAAoBE;AAEpB,MAAIH,WAAW;AACb;EACF;AAEA,MAAI;AACF,UAAM,EAAEI,OAAM,IAAK,MAAM;;MAAiC;IAAA;AAC1D,UAAMC,aAAyB;MAC7B;MACA;MACA;MACA;MACA;MACA;;AAIFA,eAAWC,QAAQ,CAACC,WAAAA;AAClB,YAAMC,iBAAiBJ,OAAOG,MAAAA;AAC9BH,aAAOG,MAAAA,IAAU,SAAUE,YAAiBC,MAAW;AACrDC,mBAAWJ,QAAQ;UAACE;aAAYC;SAAK;AACrC,eAAOF,eAAeI,MAAMR,QAAQ;UAACK;aAAYC;SAAK;MACxD;IACF,CAAA;AAGAL,eAAWC,QAAQ,CAACC,WAAAA;AAClB,YAAMC,iBAAiBJ,OAAOS,UAAUN,MAAAA;AACxCH,aAAOS,UAAUN,MAAAA,IAAU,SAAUE,YAAiBC,MAAW;AAC/DC,mBAAWJ,QAAQ;UAACE;aAAYC;WAAO,KAAKI,OAAO;AACnD,eAAON,eAAeI,MAAM,MAAM;UAACH;aAAYC;SAAK;MACtD;IACF,CAAA;AAEAV,gBAAY;EACd,QAAQ;EAER;AACF;AA1CsBE;AA4CtB,SAASS,WAAWI,OAAiBL,MAAaI,SAAgB;AAChE,QAAME,OAAOf,uDAAmBgB;AAChC,MAAID,QAAQA,KAAKE,SAASnB,iBAAiB;AACzCiB,SAAKG,KAAK;MACRC,WAAWC,KAAKC,IAAG,IAAK;MACxBC,QAAQT;MACRC;MACAN,aAASe,4BAAcd,KAAK,CAAA,GAAE,GAAKA,KAAKe,MAAM,CAAA,CAAA;IAChD,CAAA;EACF;AACF;AAVSd;","names":["MAX_BUFFER_SIZE","isPatched","globalLogsContext","patchNestLogger","logsContext","Logger","logMethods","forEach","method","originalMethod","message","args","captureLog","apply","prototype","context","level","logs","getStore","length","push","timestamp","Date","now","logger","formatMessage","slice"]}
|
package/dist/loggers/nestjs.js
CHANGED
|
@@ -10,7 +10,10 @@ async function patchNestLogger(logsContext) {
|
|
|
10
10
|
return;
|
|
11
11
|
}
|
|
12
12
|
try {
|
|
13
|
-
const { Logger } = await import(
|
|
13
|
+
const { Logger } = await import(
|
|
14
|
+
/* webpackIgnore: true */
|
|
15
|
+
"@nestjs/common"
|
|
16
|
+
);
|
|
14
17
|
const logMethods = [
|
|
15
18
|
"log",
|
|
16
19
|
"error",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/loggers/nestjs.ts"],"sourcesContent":["import { AsyncLocalStorage } from \"node:async_hooks\";\n\nimport type { LogRecord } from \"../common/requestLogger.js\";\nimport { formatMessage } from \"./utils.js\";\n\ntype LogLevel = \"log\" | \"error\" | \"warn\" | \"debug\" | \"verbose\" | \"fatal\";\n\nconst MAX_BUFFER_SIZE = 1000;\n\nlet isPatched = false;\nlet globalLogsContext: AsyncLocalStorage<LogRecord[]>;\n\nexport async function patchNestLogger(\n logsContext: AsyncLocalStorage<LogRecord[]>,\n) {\n globalLogsContext = logsContext;\n\n if (isPatched) {\n return;\n }\n\n try {\n const { Logger } = await import(\"@nestjs/common\");\n const logMethods: LogLevel[] = [\n \"log\",\n \"error\",\n \"warn\",\n \"debug\",\n \"verbose\",\n \"fatal\",\n ];\n\n // Patch static methods\n logMethods.forEach((method) => {\n const originalMethod = Logger[method];\n Logger[method] = function (message: any, ...args: any[]) {\n captureLog(method, [message, ...args]);\n return originalMethod.apply(Logger, [message, ...args]);\n };\n });\n\n // Patch prototype methods to affect all instances (new and existing)\n logMethods.forEach((method) => {\n const originalMethod = Logger.prototype[method];\n Logger.prototype[method] = function (message: any, ...args: any[]) {\n captureLog(method, [message, ...args], this.context);\n return originalMethod.apply(this, [message, ...args]);\n };\n });\n\n isPatched = true;\n } catch {\n // @nestjs/common is not installed, silently ignore\n }\n}\n\nfunction captureLog(level: LogLevel, args: any[], context?: string) {\n const logs = globalLogsContext?.getStore();\n if (logs && logs.length < MAX_BUFFER_SIZE) {\n logs.push({\n timestamp: Date.now() / 1000,\n logger: context,\n level,\n message: formatMessage(args[0], ...args.slice(1)),\n });\n }\n}\n"],"mappings":";;AAGA,SAASA,qBAAqB;AAI9B,MAAMC,kBAAkB;AAExB,IAAIC,YAAY;AAChB,IAAIC;AAEJ,eAAsBC,gBACpBC,aAA2C;AAE3CF,sBAAoBE;AAEpB,MAAIH,WAAW;AACb;EACF;AAEA,MAAI;AACF,UAAM,EAAEI,OAAM,IAAK,MAAM
|
|
1
|
+
{"version":3,"sources":["../../src/loggers/nestjs.ts"],"sourcesContent":["import { AsyncLocalStorage } from \"node:async_hooks\";\n\nimport type { LogRecord } from \"../common/requestLogger.js\";\nimport { formatMessage } from \"./utils.js\";\n\ntype LogLevel = \"log\" | \"error\" | \"warn\" | \"debug\" | \"verbose\" | \"fatal\";\n\nconst MAX_BUFFER_SIZE = 1000;\n\nlet isPatched = false;\nlet globalLogsContext: AsyncLocalStorage<LogRecord[]>;\n\nexport async function patchNestLogger(\n logsContext: AsyncLocalStorage<LogRecord[]>,\n) {\n globalLogsContext = logsContext;\n\n if (isPatched) {\n return;\n }\n\n try {\n const { Logger } = await import(/* webpackIgnore: true */ \"@nestjs/common\");\n const logMethods: LogLevel[] = [\n \"log\",\n \"error\",\n \"warn\",\n \"debug\",\n \"verbose\",\n \"fatal\",\n ];\n\n // Patch static methods\n logMethods.forEach((method) => {\n const originalMethod = Logger[method];\n Logger[method] = function (message: any, ...args: any[]) {\n captureLog(method, [message, ...args]);\n return originalMethod.apply(Logger, [message, ...args]);\n };\n });\n\n // Patch prototype methods to affect all instances (new and existing)\n logMethods.forEach((method) => {\n const originalMethod = Logger.prototype[method];\n Logger.prototype[method] = function (message: any, ...args: any[]) {\n captureLog(method, [message, ...args], this.context);\n return originalMethod.apply(this, [message, ...args]);\n };\n });\n\n isPatched = true;\n } catch {\n // @nestjs/common is not installed, silently ignore\n }\n}\n\nfunction captureLog(level: LogLevel, args: any[], context?: string) {\n const logs = globalLogsContext?.getStore();\n if (logs && logs.length < MAX_BUFFER_SIZE) {\n logs.push({\n timestamp: Date.now() / 1000,\n logger: context,\n level,\n message: formatMessage(args[0], ...args.slice(1)),\n });\n }\n}\n"],"mappings":";;AAGA,SAASA,qBAAqB;AAI9B,MAAMC,kBAAkB;AAExB,IAAIC,YAAY;AAChB,IAAIC;AAEJ,eAAsBC,gBACpBC,aAA2C;AAE3CF,sBAAoBE;AAEpB,MAAIH,WAAW;AACb;EACF;AAEA,MAAI;AACF,UAAM,EAAEI,OAAM,IAAK,MAAM;;MAAiC;IAAA;AAC1D,UAAMC,aAAyB;MAC7B;MACA;MACA;MACA;MACA;MACA;;AAIFA,eAAWC,QAAQ,CAACC,WAAAA;AAClB,YAAMC,iBAAiBJ,OAAOG,MAAAA;AAC9BH,aAAOG,MAAAA,IAAU,SAAUE,YAAiBC,MAAW;AACrDC,mBAAWJ,QAAQ;UAACE;aAAYC;SAAK;AACrC,eAAOF,eAAeI,MAAMR,QAAQ;UAACK;aAAYC;SAAK;MACxD;IACF,CAAA;AAGAL,eAAWC,QAAQ,CAACC,WAAAA;AAClB,YAAMC,iBAAiBJ,OAAOS,UAAUN,MAAAA;AACxCH,aAAOS,UAAUN,MAAAA,IAAU,SAAUE,YAAiBC,MAAW;AAC/DC,mBAAWJ,QAAQ;UAACE;aAAYC;WAAO,KAAKI,OAAO;AACnD,eAAON,eAAeI,MAAM,MAAM;UAACH;aAAYC;SAAK;MACtD;IACF,CAAA;AAEAV,gBAAY;EACd,QAAQ;EAER;AACF;AA1CsBE;AA4CtB,SAASS,WAAWI,OAAiBL,MAAaI,SAAgB;AAChE,QAAME,OAAOf,uDAAmBgB;AAChC,MAAID,QAAQA,KAAKE,SAASnB,iBAAiB;AACzCiB,SAAKG,KAAK;MACRC,WAAWC,KAAKC,IAAG,IAAK;MACxBC,QAAQT;MACRC;MACAN,SAASX,cAAcY,KAAK,CAAA,GAAE,GAAKA,KAAKc,MAAM,CAAA,CAAA;IAChD,CAAA;EACF;AACF;AAVSb;","names":["formatMessage","MAX_BUFFER_SIZE","isPatched","globalLogsContext","patchNestLogger","logsContext","Logger","logMethods","forEach","method","originalMethod","message","args","captureLog","apply","prototype","context","level","logs","getStore","length","push","timestamp","Date","now","logger","slice"]}
|
package/dist/loggers/pino.cjs
CHANGED
|
@@ -60,7 +60,10 @@ async function patchPinoLogger(logger, logsContext) {
|
|
|
60
60
|
}
|
|
61
61
|
const originalStream = logger[originalStreamSym];
|
|
62
62
|
if (originalStream) {
|
|
63
|
-
const pino = await import(
|
|
63
|
+
const pino = await import(
|
|
64
|
+
/* webpackIgnore: true */
|
|
65
|
+
"pino"
|
|
66
|
+
);
|
|
64
67
|
const captureStream = new ApitallyLogCaptureStream(logsContext, logger[messageKeySym]);
|
|
65
68
|
logger[streamSym] = pino.default.multistream([
|
|
66
69
|
{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/loggers/pino.ts"],"sourcesContent":["import { AsyncLocalStorage } from \"node:async_hooks\";\n\nimport type { LogRecord } from \"../common/requestLogger.js\";\nimport { formatMessage, removeKeys } from \"./utils.js\";\n\nconst MAX_BUFFER_SIZE = 1000;\n\nconst originalStreamSym = Symbol.for(\"apitally.originalStream\");\nconst logLevelMap: Record<number, string> = {\n 10: \"trace\",\n 20: \"debug\",\n 30: \"info\",\n 40: \"warn\",\n 50: \"error\",\n 60: \"fatal\",\n};\n\nexport async function patchPinoLogger(\n logger: any,\n logsContext: AsyncLocalStorage<LogRecord[]>,\n) {\n try {\n // Find stream and message key symbols on the logger and its prototype\n const symbols = [\n ...Object.getOwnPropertySymbols(logger),\n ...Object.getOwnPropertySymbols(Object.getPrototypeOf(logger)),\n ];\n const streamSym = symbols.find(\n (sym) => sym.toString() === \"Symbol(pino.stream)\",\n );\n const messageKeySym = symbols.find(\n (sym) => sym.toString() === \"Symbol(pino.messageKey)\",\n );\n if (!streamSym || !messageKeySym) {\n // not a pino logger\n return false;\n }\n\n if (!(originalStreamSym in logger)) {\n logger[originalStreamSym] = logger[streamSym];\n }\n\n const originalStream = logger[originalStreamSym];\n if (originalStream) {\n const pino = await import(\"pino\");\n const captureStream = new ApitallyLogCaptureStream(\n logsContext,\n logger[messageKeySym],\n );\n logger[streamSym] = pino.default.multistream(\n [\n { level: 0, stream: originalStream },\n { level: 0, stream: captureStream },\n ],\n {\n levels: logger.levels,\n },\n );\n }\n return true;\n } catch {\n // ignore errors\n return false;\n }\n}\n\nfunction filterLogs(obj: any, messageKey: string) {\n return obj[messageKey] !== \"request completed\";\n}\n\nclass ApitallyLogCaptureStream {\n private logsContext: AsyncLocalStorage<LogRecord[]>;\n private messageKey: string;\n\n constructor(logsContext: AsyncLocalStorage<LogRecord[]>, messageKey: string) {\n this.logsContext = logsContext;\n this.messageKey = messageKey;\n }\n\n write(msg: string): void {\n const logs = this.logsContext.getStore();\n if (!logs || !msg || logs.length >= MAX_BUFFER_SIZE) {\n return;\n }\n\n let obj: any;\n try {\n obj = JSON.parse(msg);\n } catch (e) {\n return;\n }\n if (\n obj === null ||\n typeof obj !== \"object\" ||\n !filterLogs(obj, this.messageKey)\n ) {\n return;\n }\n\n try {\n let message = obj[this.messageKey];\n const ignoreKeys = [\n \"hostname\",\n \"level\",\n this.messageKey,\n \"pid\",\n \"time\",\n \"reqId\",\n \"req\",\n \"res\",\n ];\n if (!message && \"data\" in obj && \"tags\" in obj) {\n // hapi-pino uses data and tags instead of the message key\n message = obj.data;\n ignoreKeys.push(\"data\");\n ignoreKeys.push(\"tags\");\n }\n const rest = removeKeys(obj, ignoreKeys);\n const formattedMessage = formatMessage(message, rest);\n if (formattedMessage) {\n logs.push({\n timestamp: this.convertTime(obj.time),\n level: logLevelMap[obj.level] || \"info\",\n message: formattedMessage,\n });\n }\n } catch (e) {\n // ignore\n }\n }\n\n private convertTime(time: any): number {\n if (typeof time === \"number\" && !isNaN(time)) {\n return time / 1000; // Convert milliseconds to seconds\n }\n return Date.now() / 1000; // Fallback to current time\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAGA;;;;;AAAA,mBAA0C;AAA1C;AAEA,MAAMA,kBAAkB;AAExB,MAAMC,oBAAoBC,OAAOC,IAAI,yBAAA;AACrC,MAAMC,cAAsC;EAC1C,IAAI;EACJ,IAAI;EACJ,IAAI;EACJ,IAAI;EACJ,IAAI;EACJ,IAAI;AACN;AAEA,eAAsBC,gBACpBC,QACAC,aAA2C;AAE3C,MAAI;AAEF,UAAMC,UAAU;SACXC,OAAOC,sBAAsBJ,MAAAA;SAC7BG,OAAOC,sBAAsBD,OAAOE,eAAeL,MAAAA,CAAAA;;AAExD,UAAMM,YAAYJ,QAAQK,KACxB,CAACC,QAAQA,IAAIC,SAAQ,MAAO,qBAAA;AAE9B,UAAMC,gBAAgBR,QAAQK,KAC5B,CAACC,QAAQA,IAAIC,SAAQ,MAAO,yBAAA;AAE9B,QAAI,CAACH,aAAa,CAACI,eAAe;AAEhC,aAAO;IACT;AAEA,QAAI,EAAEf,qBAAqBK,SAAS;AAClCA,aAAOL,iBAAAA,IAAqBK,OAAOM,SAAAA;IACrC;AAEA,UAAMK,iBAAiBX,OAAOL,iBAAAA;AAC9B,QAAIgB,gBAAgB;AAClB,YAAMC,OAAO,MAAM
|
|
1
|
+
{"version":3,"sources":["../../src/loggers/pino.ts"],"sourcesContent":["import { AsyncLocalStorage } from \"node:async_hooks\";\n\nimport type { LogRecord } from \"../common/requestLogger.js\";\nimport { formatMessage, removeKeys } from \"./utils.js\";\n\nconst MAX_BUFFER_SIZE = 1000;\n\nconst originalStreamSym = Symbol.for(\"apitally.originalStream\");\nconst logLevelMap: Record<number, string> = {\n 10: \"trace\",\n 20: \"debug\",\n 30: \"info\",\n 40: \"warn\",\n 50: \"error\",\n 60: \"fatal\",\n};\n\nexport async function patchPinoLogger(\n logger: any,\n logsContext: AsyncLocalStorage<LogRecord[]>,\n) {\n try {\n // Find stream and message key symbols on the logger and its prototype\n const symbols = [\n ...Object.getOwnPropertySymbols(logger),\n ...Object.getOwnPropertySymbols(Object.getPrototypeOf(logger)),\n ];\n const streamSym = symbols.find(\n (sym) => sym.toString() === \"Symbol(pino.stream)\",\n );\n const messageKeySym = symbols.find(\n (sym) => sym.toString() === \"Symbol(pino.messageKey)\",\n );\n if (!streamSym || !messageKeySym) {\n // not a pino logger\n return false;\n }\n\n if (!(originalStreamSym in logger)) {\n logger[originalStreamSym] = logger[streamSym];\n }\n\n const originalStream = logger[originalStreamSym];\n if (originalStream) {\n const pino = await import(/* webpackIgnore: true */ \"pino\");\n const captureStream = new ApitallyLogCaptureStream(\n logsContext,\n logger[messageKeySym],\n );\n logger[streamSym] = pino.default.multistream(\n [\n { level: 0, stream: originalStream },\n { level: 0, stream: captureStream },\n ],\n {\n levels: logger.levels,\n },\n );\n }\n return true;\n } catch {\n // ignore errors\n return false;\n }\n}\n\nfunction filterLogs(obj: any, messageKey: string) {\n return obj[messageKey] !== \"request completed\";\n}\n\nclass ApitallyLogCaptureStream {\n private logsContext: AsyncLocalStorage<LogRecord[]>;\n private messageKey: string;\n\n constructor(logsContext: AsyncLocalStorage<LogRecord[]>, messageKey: string) {\n this.logsContext = logsContext;\n this.messageKey = messageKey;\n }\n\n write(msg: string): void {\n const logs = this.logsContext.getStore();\n if (!logs || !msg || logs.length >= MAX_BUFFER_SIZE) {\n return;\n }\n\n let obj: any;\n try {\n obj = JSON.parse(msg);\n } catch (e) {\n return;\n }\n if (\n obj === null ||\n typeof obj !== \"object\" ||\n !filterLogs(obj, this.messageKey)\n ) {\n return;\n }\n\n try {\n let message = obj[this.messageKey];\n const ignoreKeys = [\n \"hostname\",\n \"level\",\n this.messageKey,\n \"pid\",\n \"time\",\n \"reqId\",\n \"req\",\n \"res\",\n ];\n if (!message && \"data\" in obj && \"tags\" in obj) {\n // hapi-pino uses data and tags instead of the message key\n message = obj.data;\n ignoreKeys.push(\"data\");\n ignoreKeys.push(\"tags\");\n }\n const rest = removeKeys(obj, ignoreKeys);\n const formattedMessage = formatMessage(message, rest);\n if (formattedMessage) {\n logs.push({\n timestamp: this.convertTime(obj.time),\n level: logLevelMap[obj.level] || \"info\",\n message: formattedMessage,\n });\n }\n } catch (e) {\n // ignore\n }\n }\n\n private convertTime(time: any): number {\n if (typeof time === \"number\" && !isNaN(time)) {\n return time / 1000; // Convert milliseconds to seconds\n }\n return Date.now() / 1000; // Fallback to current time\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAGA;;;;;AAAA,mBAA0C;AAA1C;AAEA,MAAMA,kBAAkB;AAExB,MAAMC,oBAAoBC,OAAOC,IAAI,yBAAA;AACrC,MAAMC,cAAsC;EAC1C,IAAI;EACJ,IAAI;EACJ,IAAI;EACJ,IAAI;EACJ,IAAI;EACJ,IAAI;AACN;AAEA,eAAsBC,gBACpBC,QACAC,aAA2C;AAE3C,MAAI;AAEF,UAAMC,UAAU;SACXC,OAAOC,sBAAsBJ,MAAAA;SAC7BG,OAAOC,sBAAsBD,OAAOE,eAAeL,MAAAA,CAAAA;;AAExD,UAAMM,YAAYJ,QAAQK,KACxB,CAACC,QAAQA,IAAIC,SAAQ,MAAO,qBAAA;AAE9B,UAAMC,gBAAgBR,QAAQK,KAC5B,CAACC,QAAQA,IAAIC,SAAQ,MAAO,yBAAA;AAE9B,QAAI,CAACH,aAAa,CAACI,eAAe;AAEhC,aAAO;IACT;AAEA,QAAI,EAAEf,qBAAqBK,SAAS;AAClCA,aAAOL,iBAAAA,IAAqBK,OAAOM,SAAAA;IACrC;AAEA,UAAMK,iBAAiBX,OAAOL,iBAAAA;AAC9B,QAAIgB,gBAAgB;AAClB,YAAMC,OAAO,MAAM;;QAAiC;MAAA;AACpD,YAAMC,gBAAgB,IAAIC,yBACxBb,aACAD,OAAOU,aAAAA,CAAc;AAEvBV,aAAOM,SAAAA,IAAaM,KAAKG,QAAQC,YAC/B;QACE;UAAEC,OAAO;UAAGC,QAAQP;QAAe;QACnC;UAAEM,OAAO;UAAGC,QAAQL;QAAc;SAEpC;QACEM,QAAQnB,OAAOmB;MACjB,CAAA;IAEJ;AACA,WAAO;EACT,QAAQ;AAEN,WAAO;EACT;AACF;AA/CsBpB;AAiDtB,SAASqB,WAAWC,KAAUC,YAAkB;AAC9C,SAAOD,IAAIC,UAAAA,MAAgB;AAC7B;AAFSF;AAIT,IAAMN,4BAAN,WAAMA;EACIb;EACAqB;EAER,YAAYrB,aAA6CqB,YAAoB;AAC3E,SAAKrB,cAAcA;AACnB,SAAKqB,aAAaA;EACpB;EAEAC,MAAMC,KAAmB;AACvB,UAAMC,OAAO,KAAKxB,YAAYyB,SAAQ;AACtC,QAAI,CAACD,QAAQ,CAACD,OAAOC,KAAKE,UAAUjC,iBAAiB;AACnD;IACF;AAEA,QAAI2B;AACJ,QAAI;AACFA,YAAMO,KAAKC,MAAML,GAAAA;IACnB,SAASM,GAAG;AACV;IACF;AACA,QACET,QAAQ,QACR,OAAOA,QAAQ,YACf,CAACD,WAAWC,KAAK,KAAKC,UAAU,GAChC;AACA;IACF;AAEA,QAAI;AACF,UAAIS,UAAUV,IAAI,KAAKC,UAAU;AACjC,YAAMU,aAAa;QACjB;QACA;QACA,KAAKV;QACL;QACA;QACA;QACA;QACA;;AAEF,UAAI,CAACS,WAAW,UAAUV,OAAO,UAAUA,KAAK;AAE9CU,kBAAUV,IAAIY;AACdD,mBAAWE,KAAK,MAAA;AAChBF,mBAAWE,KAAK,MAAA;MAClB;AACA,YAAMC,WAAOC,yBAAWf,KAAKW,UAAAA;AAC7B,YAAMK,uBAAmBC,4BAAcP,SAASI,IAAAA;AAChD,UAAIE,kBAAkB;AACpBZ,aAAKS,KAAK;UACRK,WAAW,KAAKC,YAAYnB,IAAIoB,IAAI;UACpCxB,OAAOnB,YAAYuB,IAAIJ,KAAK,KAAK;UACjCc,SAASM;QACX,CAAA;MACF;IACF,SAASP,GAAG;IAEZ;EACF;EAEQU,YAAYC,MAAmB;AACrC,QAAI,OAAOA,SAAS,YAAY,CAACC,MAAMD,IAAAA,GAAO;AAC5C,aAAOA,OAAO;IAChB;AACA,WAAOE,KAAKC,IAAG,IAAK;EACtB;AACF,GAnEM9B,wCAAN;","names":["MAX_BUFFER_SIZE","originalStreamSym","Symbol","for","logLevelMap","patchPinoLogger","logger","logsContext","symbols","Object","getOwnPropertySymbols","getPrototypeOf","streamSym","find","sym","toString","messageKeySym","originalStream","pino","captureStream","ApitallyLogCaptureStream","default","multistream","level","stream","levels","filterLogs","obj","messageKey","write","msg","logs","getStore","length","JSON","parse","e","message","ignoreKeys","data","push","rest","removeKeys","formattedMessage","formatMessage","timestamp","convertTime","time","isNaN","Date","now"]}
|
package/dist/loggers/pino.js
CHANGED
|
@@ -28,7 +28,10 @@ async function patchPinoLogger(logger, logsContext) {
|
|
|
28
28
|
}
|
|
29
29
|
const originalStream = logger[originalStreamSym];
|
|
30
30
|
if (originalStream) {
|
|
31
|
-
const pino = await import(
|
|
31
|
+
const pino = await import(
|
|
32
|
+
/* webpackIgnore: true */
|
|
33
|
+
"pino"
|
|
34
|
+
);
|
|
32
35
|
const captureStream = new ApitallyLogCaptureStream(logsContext, logger[messageKeySym]);
|
|
33
36
|
logger[streamSym] = pino.default.multistream([
|
|
34
37
|
{
|
package/dist/loggers/pino.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/loggers/pino.ts"],"sourcesContent":["import { AsyncLocalStorage } from \"node:async_hooks\";\n\nimport type { LogRecord } from \"../common/requestLogger.js\";\nimport { formatMessage, removeKeys } from \"./utils.js\";\n\nconst MAX_BUFFER_SIZE = 1000;\n\nconst originalStreamSym = Symbol.for(\"apitally.originalStream\");\nconst logLevelMap: Record<number, string> = {\n 10: \"trace\",\n 20: \"debug\",\n 30: \"info\",\n 40: \"warn\",\n 50: \"error\",\n 60: \"fatal\",\n};\n\nexport async function patchPinoLogger(\n logger: any,\n logsContext: AsyncLocalStorage<LogRecord[]>,\n) {\n try {\n // Find stream and message key symbols on the logger and its prototype\n const symbols = [\n ...Object.getOwnPropertySymbols(logger),\n ...Object.getOwnPropertySymbols(Object.getPrototypeOf(logger)),\n ];\n const streamSym = symbols.find(\n (sym) => sym.toString() === \"Symbol(pino.stream)\",\n );\n const messageKeySym = symbols.find(\n (sym) => sym.toString() === \"Symbol(pino.messageKey)\",\n );\n if (!streamSym || !messageKeySym) {\n // not a pino logger\n return false;\n }\n\n if (!(originalStreamSym in logger)) {\n logger[originalStreamSym] = logger[streamSym];\n }\n\n const originalStream = logger[originalStreamSym];\n if (originalStream) {\n const pino = await import(\"pino\");\n const captureStream = new ApitallyLogCaptureStream(\n logsContext,\n logger[messageKeySym],\n );\n logger[streamSym] = pino.default.multistream(\n [\n { level: 0, stream: originalStream },\n { level: 0, stream: captureStream },\n ],\n {\n levels: logger.levels,\n },\n );\n }\n return true;\n } catch {\n // ignore errors\n return false;\n }\n}\n\nfunction filterLogs(obj: any, messageKey: string) {\n return obj[messageKey] !== \"request completed\";\n}\n\nclass ApitallyLogCaptureStream {\n private logsContext: AsyncLocalStorage<LogRecord[]>;\n private messageKey: string;\n\n constructor(logsContext: AsyncLocalStorage<LogRecord[]>, messageKey: string) {\n this.logsContext = logsContext;\n this.messageKey = messageKey;\n }\n\n write(msg: string): void {\n const logs = this.logsContext.getStore();\n if (!logs || !msg || logs.length >= MAX_BUFFER_SIZE) {\n return;\n }\n\n let obj: any;\n try {\n obj = JSON.parse(msg);\n } catch (e) {\n return;\n }\n if (\n obj === null ||\n typeof obj !== \"object\" ||\n !filterLogs(obj, this.messageKey)\n ) {\n return;\n }\n\n try {\n let message = obj[this.messageKey];\n const ignoreKeys = [\n \"hostname\",\n \"level\",\n this.messageKey,\n \"pid\",\n \"time\",\n \"reqId\",\n \"req\",\n \"res\",\n ];\n if (!message && \"data\" in obj && \"tags\" in obj) {\n // hapi-pino uses data and tags instead of the message key\n message = obj.data;\n ignoreKeys.push(\"data\");\n ignoreKeys.push(\"tags\");\n }\n const rest = removeKeys(obj, ignoreKeys);\n const formattedMessage = formatMessage(message, rest);\n if (formattedMessage) {\n logs.push({\n timestamp: this.convertTime(obj.time),\n level: logLevelMap[obj.level] || \"info\",\n message: formattedMessage,\n });\n }\n } catch (e) {\n // ignore\n }\n }\n\n private convertTime(time: any): number {\n if (typeof time === \"number\" && !isNaN(time)) {\n return time / 1000; // Convert milliseconds to seconds\n }\n return Date.now() / 1000; // Fallback to current time\n }\n}\n"],"mappings":";;AAGA;SAASA,eAAeC,kBAAkB;AAE1C,MAAMC,kBAAkB;AAExB,MAAMC,oBAAoBC,OAAOC,IAAI,yBAAA;AACrC,MAAMC,cAAsC;EAC1C,IAAI;EACJ,IAAI;EACJ,IAAI;EACJ,IAAI;EACJ,IAAI;EACJ,IAAI;AACN;AAEA,eAAsBC,gBACpBC,QACAC,aAA2C;AAE3C,MAAI;AAEF,UAAMC,UAAU;SACXC,OAAOC,sBAAsBJ,MAAAA;SAC7BG,OAAOC,sBAAsBD,OAAOE,eAAeL,MAAAA,CAAAA;;AAExD,UAAMM,YAAYJ,QAAQK,KACxB,CAACC,QAAQA,IAAIC,SAAQ,MAAO,qBAAA;AAE9B,UAAMC,gBAAgBR,QAAQK,KAC5B,CAACC,QAAQA,IAAIC,SAAQ,MAAO,yBAAA;AAE9B,QAAI,CAACH,aAAa,CAACI,eAAe;AAEhC,aAAO;IACT;AAEA,QAAI,EAAEf,qBAAqBK,SAAS;AAClCA,aAAOL,iBAAAA,IAAqBK,OAAOM,SAAAA;IACrC;AAEA,UAAMK,iBAAiBX,OAAOL,iBAAAA;AAC9B,QAAIgB,gBAAgB;AAClB,YAAMC,OAAO,MAAM
|
|
1
|
+
{"version":3,"sources":["../../src/loggers/pino.ts"],"sourcesContent":["import { AsyncLocalStorage } from \"node:async_hooks\";\n\nimport type { LogRecord } from \"../common/requestLogger.js\";\nimport { formatMessage, removeKeys } from \"./utils.js\";\n\nconst MAX_BUFFER_SIZE = 1000;\n\nconst originalStreamSym = Symbol.for(\"apitally.originalStream\");\nconst logLevelMap: Record<number, string> = {\n 10: \"trace\",\n 20: \"debug\",\n 30: \"info\",\n 40: \"warn\",\n 50: \"error\",\n 60: \"fatal\",\n};\n\nexport async function patchPinoLogger(\n logger: any,\n logsContext: AsyncLocalStorage<LogRecord[]>,\n) {\n try {\n // Find stream and message key symbols on the logger and its prototype\n const symbols = [\n ...Object.getOwnPropertySymbols(logger),\n ...Object.getOwnPropertySymbols(Object.getPrototypeOf(logger)),\n ];\n const streamSym = symbols.find(\n (sym) => sym.toString() === \"Symbol(pino.stream)\",\n );\n const messageKeySym = symbols.find(\n (sym) => sym.toString() === \"Symbol(pino.messageKey)\",\n );\n if (!streamSym || !messageKeySym) {\n // not a pino logger\n return false;\n }\n\n if (!(originalStreamSym in logger)) {\n logger[originalStreamSym] = logger[streamSym];\n }\n\n const originalStream = logger[originalStreamSym];\n if (originalStream) {\n const pino = await import(/* webpackIgnore: true */ \"pino\");\n const captureStream = new ApitallyLogCaptureStream(\n logsContext,\n logger[messageKeySym],\n );\n logger[streamSym] = pino.default.multistream(\n [\n { level: 0, stream: originalStream },\n { level: 0, stream: captureStream },\n ],\n {\n levels: logger.levels,\n },\n );\n }\n return true;\n } catch {\n // ignore errors\n return false;\n }\n}\n\nfunction filterLogs(obj: any, messageKey: string) {\n return obj[messageKey] !== \"request completed\";\n}\n\nclass ApitallyLogCaptureStream {\n private logsContext: AsyncLocalStorage<LogRecord[]>;\n private messageKey: string;\n\n constructor(logsContext: AsyncLocalStorage<LogRecord[]>, messageKey: string) {\n this.logsContext = logsContext;\n this.messageKey = messageKey;\n }\n\n write(msg: string): void {\n const logs = this.logsContext.getStore();\n if (!logs || !msg || logs.length >= MAX_BUFFER_SIZE) {\n return;\n }\n\n let obj: any;\n try {\n obj = JSON.parse(msg);\n } catch (e) {\n return;\n }\n if (\n obj === null ||\n typeof obj !== \"object\" ||\n !filterLogs(obj, this.messageKey)\n ) {\n return;\n }\n\n try {\n let message = obj[this.messageKey];\n const ignoreKeys = [\n \"hostname\",\n \"level\",\n this.messageKey,\n \"pid\",\n \"time\",\n \"reqId\",\n \"req\",\n \"res\",\n ];\n if (!message && \"data\" in obj && \"tags\" in obj) {\n // hapi-pino uses data and tags instead of the message key\n message = obj.data;\n ignoreKeys.push(\"data\");\n ignoreKeys.push(\"tags\");\n }\n const rest = removeKeys(obj, ignoreKeys);\n const formattedMessage = formatMessage(message, rest);\n if (formattedMessage) {\n logs.push({\n timestamp: this.convertTime(obj.time),\n level: logLevelMap[obj.level] || \"info\",\n message: formattedMessage,\n });\n }\n } catch (e) {\n // ignore\n }\n }\n\n private convertTime(time: any): number {\n if (typeof time === \"number\" && !isNaN(time)) {\n return time / 1000; // Convert milliseconds to seconds\n }\n return Date.now() / 1000; // Fallback to current time\n }\n}\n"],"mappings":";;AAGA;SAASA,eAAeC,kBAAkB;AAE1C,MAAMC,kBAAkB;AAExB,MAAMC,oBAAoBC,OAAOC,IAAI,yBAAA;AACrC,MAAMC,cAAsC;EAC1C,IAAI;EACJ,IAAI;EACJ,IAAI;EACJ,IAAI;EACJ,IAAI;EACJ,IAAI;AACN;AAEA,eAAsBC,gBACpBC,QACAC,aAA2C;AAE3C,MAAI;AAEF,UAAMC,UAAU;SACXC,OAAOC,sBAAsBJ,MAAAA;SAC7BG,OAAOC,sBAAsBD,OAAOE,eAAeL,MAAAA,CAAAA;;AAExD,UAAMM,YAAYJ,QAAQK,KACxB,CAACC,QAAQA,IAAIC,SAAQ,MAAO,qBAAA;AAE9B,UAAMC,gBAAgBR,QAAQK,KAC5B,CAACC,QAAQA,IAAIC,SAAQ,MAAO,yBAAA;AAE9B,QAAI,CAACH,aAAa,CAACI,eAAe;AAEhC,aAAO;IACT;AAEA,QAAI,EAAEf,qBAAqBK,SAAS;AAClCA,aAAOL,iBAAAA,IAAqBK,OAAOM,SAAAA;IACrC;AAEA,UAAMK,iBAAiBX,OAAOL,iBAAAA;AAC9B,QAAIgB,gBAAgB;AAClB,YAAMC,OAAO,MAAM;;QAAiC;MAAA;AACpD,YAAMC,gBAAgB,IAAIC,yBACxBb,aACAD,OAAOU,aAAAA,CAAc;AAEvBV,aAAOM,SAAAA,IAAaM,KAAKG,QAAQC,YAC/B;QACE;UAAEC,OAAO;UAAGC,QAAQP;QAAe;QACnC;UAAEM,OAAO;UAAGC,QAAQL;QAAc;SAEpC;QACEM,QAAQnB,OAAOmB;MACjB,CAAA;IAEJ;AACA,WAAO;EACT,QAAQ;AAEN,WAAO;EACT;AACF;AA/CsBpB;AAiDtB,SAASqB,WAAWC,KAAUC,YAAkB;AAC9C,SAAOD,IAAIC,UAAAA,MAAgB;AAC7B;AAFSF;AAIT,IAAMN,4BAAN,WAAMA;EACIb;EACAqB;EAER,YAAYrB,aAA6CqB,YAAoB;AAC3E,SAAKrB,cAAcA;AACnB,SAAKqB,aAAaA;EACpB;EAEAC,MAAMC,KAAmB;AACvB,UAAMC,OAAO,KAAKxB,YAAYyB,SAAQ;AACtC,QAAI,CAACD,QAAQ,CAACD,OAAOC,KAAKE,UAAUjC,iBAAiB;AACnD;IACF;AAEA,QAAI2B;AACJ,QAAI;AACFA,YAAMO,KAAKC,MAAML,GAAAA;IACnB,SAASM,GAAG;AACV;IACF;AACA,QACET,QAAQ,QACR,OAAOA,QAAQ,YACf,CAACD,WAAWC,KAAK,KAAKC,UAAU,GAChC;AACA;IACF;AAEA,QAAI;AACF,UAAIS,UAAUV,IAAI,KAAKC,UAAU;AACjC,YAAMU,aAAa;QACjB;QACA;QACA,KAAKV;QACL;QACA;QACA;QACA;QACA;;AAEF,UAAI,CAACS,WAAW,UAAUV,OAAO,UAAUA,KAAK;AAE9CU,kBAAUV,IAAIY;AACdD,mBAAWE,KAAK,MAAA;AAChBF,mBAAWE,KAAK,MAAA;MAClB;AACA,YAAMC,OAAO1C,WAAW4B,KAAKW,UAAAA;AAC7B,YAAMI,mBAAmB5C,cAAcuC,SAASI,IAAAA;AAChD,UAAIC,kBAAkB;AACpBX,aAAKS,KAAK;UACRG,WAAW,KAAKC,YAAYjB,IAAIkB,IAAI;UACpCtB,OAAOnB,YAAYuB,IAAIJ,KAAK,KAAK;UACjCc,SAASK;QACX,CAAA;MACF;IACF,SAASN,GAAG;IAEZ;EACF;EAEQQ,YAAYC,MAAmB;AACrC,QAAI,OAAOA,SAAS,YAAY,CAACC,MAAMD,IAAAA,GAAO;AAC5C,aAAOA,OAAO;IAChB;AACA,WAAOE,KAAKC,IAAG,IAAK;EACtB;AACF,GAnEM5B,wCAAN;","names":["formatMessage","removeKeys","MAX_BUFFER_SIZE","originalStreamSym","Symbol","for","logLevelMap","patchPinoLogger","logger","logsContext","symbols","Object","getOwnPropertySymbols","getPrototypeOf","streamSym","find","sym","toString","messageKeySym","originalStream","pino","captureStream","ApitallyLogCaptureStream","default","multistream","level","stream","levels","filterLogs","obj","messageKey","write","msg","logs","getStore","length","JSON","parse","e","message","ignoreKeys","data","push","rest","formattedMessage","timestamp","convertTime","time","isNaN","Date","now"]}
|
package/dist/loggers/winston.cjs
CHANGED
|
@@ -43,7 +43,11 @@ async function patchWinston(logsContext) {
|
|
|
43
43
|
return;
|
|
44
44
|
}
|
|
45
45
|
try {
|
|
46
|
-
const loggerModule = await import(
|
|
46
|
+
const loggerModule = await import(
|
|
47
|
+
// @ts-expect-error - file is not typed
|
|
48
|
+
/* webpackIgnore: true */
|
|
49
|
+
"winston/lib/winston/logger.js"
|
|
50
|
+
);
|
|
47
51
|
if ((_b = (_a = loggerModule.default) == null ? void 0 : _a.prototype) == null ? void 0 : _b.write) {
|
|
48
52
|
const originalWrite = loggerModule.default.prototype.write;
|
|
49
53
|
loggerModule.default.prototype.write = function(info) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/loggers/winston.ts"],"sourcesContent":["import { AsyncLocalStorage } from \"node:async_hooks\";\n\nimport type { LogRecord } from \"../common/requestLogger.js\";\nimport { formatMessage, removeKeys } from \"./utils.js\";\n\nconst MAX_BUFFER_SIZE = 1000;\n\nlet isPatched = false;\nlet globalLogsContext: AsyncLocalStorage<LogRecord[]>;\n\nexport async function patchWinston(\n logsContext: AsyncLocalStorage<LogRecord[]>,\n) {\n globalLogsContext = logsContext;\n\n if (isPatched) {\n return;\n }\n\n try {\n // @ts-expect-error - file is not typed\n
|
|
1
|
+
{"version":3,"sources":["../../src/loggers/winston.ts"],"sourcesContent":["import { AsyncLocalStorage } from \"node:async_hooks\";\n\nimport type { LogRecord } from \"../common/requestLogger.js\";\nimport { formatMessage, removeKeys } from \"./utils.js\";\n\nconst MAX_BUFFER_SIZE = 1000;\n\nlet isPatched = false;\nlet globalLogsContext: AsyncLocalStorage<LogRecord[]>;\n\nexport async function patchWinston(\n logsContext: AsyncLocalStorage<LogRecord[]>,\n) {\n globalLogsContext = logsContext;\n\n if (isPatched) {\n return;\n }\n\n try {\n const loggerModule = await import(\n // @ts-expect-error - file is not typed\n /* webpackIgnore: true */ \"winston/lib/winston/logger.js\"\n );\n if (loggerModule.default?.prototype?.write) {\n const originalWrite = loggerModule.default.prototype.write;\n loggerModule.default.prototype.write = function (info: any) {\n captureLog(info);\n return originalWrite.call(this, info);\n };\n }\n } catch {\n // winston is not installed, silently ignore\n }\n\n isPatched = true;\n}\n\nfunction captureLog(info: any) {\n const logs = globalLogsContext?.getStore();\n if (!logs || !info || logs.length >= MAX_BUFFER_SIZE) {\n return;\n }\n\n try {\n const rest = removeKeys(info, [\"timestamp\", \"level\", \"message\", \"splat\"]);\n const formattedMessage = formatMessage(info.message, rest);\n if (formattedMessage) {\n logs.push({\n timestamp: parseTimestamp(info.timestamp),\n level: info.level || \"info\",\n message: formattedMessage.trim(),\n });\n }\n } catch (e) {\n // ignore\n }\n}\n\nfunction parseTimestamp(timestamp: any) {\n if (timestamp) {\n const ts = new Date(timestamp).getTime();\n if (!isNaN(ts)) {\n return ts / 1000;\n }\n }\n return Date.now() / 1000;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAGA;;;;;AAAA,mBAA0C;AAE1C,MAAMA,kBAAkB;AAExB,IAAIC,YAAY;AAChB,IAAIC;AAEJ,eAAsBC,aACpBC,aAA2C;AAR7C;AAUEF,sBAAoBE;AAEpB,MAAIH,WAAW;AACb;EACF;AAEA,MAAI;AACF,UAAMI,eAAe,MAAM;;;MAEC;IAAA;AAE5B,SAAIA,wBAAaC,YAAbD,mBAAsBE,cAAtBF,mBAAiCG,OAAO;AAC1C,YAAMC,gBAAgBJ,aAAaC,QAAQC,UAAUC;AACrDH,mBAAaC,QAAQC,UAAUC,QAAQ,SAAUE,MAAS;AACxDC,mBAAWD,IAAAA;AACX,eAAOD,cAAcG,KAAK,MAAMF,IAAAA;MAClC;IACF;EACF,QAAQ;EAER;AAEAT,cAAY;AACd;AA1BsBE;AA4BtB,SAASQ,WAAWD,MAAS;AAC3B,QAAMG,OAAOX,uDAAmBY;AAChC,MAAI,CAACD,QAAQ,CAACH,QAAQG,KAAKE,UAAUf,iBAAiB;AACpD;EACF;AAEA,MAAI;AACF,UAAMgB,WAAOC,yBAAWP,MAAM;MAAC;MAAa;MAAS;MAAW;KAAQ;AACxE,UAAMQ,uBAAmBC,4BAAcT,KAAKU,SAASJ,IAAAA;AACrD,QAAIE,kBAAkB;AACpBL,WAAKQ,KAAK;QACRC,WAAWC,eAAeb,KAAKY,SAAS;QACxCE,OAAOd,KAAKc,SAAS;QACrBJ,SAASF,iBAAiBO,KAAI;MAChC,CAAA;IACF;EACF,SAASC,GAAG;EAEZ;AACF;AAnBSf;AAqBT,SAASY,eAAeD,WAAc;AACpC,MAAIA,WAAW;AACb,UAAMK,KAAK,IAAIC,KAAKN,SAAAA,EAAWO,QAAO;AACtC,QAAI,CAACC,MAAMH,EAAAA,GAAK;AACd,aAAOA,KAAK;IACd;EACF;AACA,SAAOC,KAAKG,IAAG,IAAK;AACtB;AARSR;","names":["MAX_BUFFER_SIZE","isPatched","globalLogsContext","patchWinston","logsContext","loggerModule","default","prototype","write","originalWrite","info","captureLog","call","logs","getStore","length","rest","removeKeys","formattedMessage","formatMessage","message","push","timestamp","parseTimestamp","level","trim","e","ts","Date","getTime","isNaN","now"]}
|
package/dist/loggers/winston.js
CHANGED
|
@@ -11,7 +11,11 @@ async function patchWinston(logsContext) {
|
|
|
11
11
|
return;
|
|
12
12
|
}
|
|
13
13
|
try {
|
|
14
|
-
const loggerModule = await import(
|
|
14
|
+
const loggerModule = await import(
|
|
15
|
+
// @ts-expect-error - file is not typed
|
|
16
|
+
/* webpackIgnore: true */
|
|
17
|
+
"winston/lib/winston/logger.js"
|
|
18
|
+
);
|
|
15
19
|
if ((_b = (_a = loggerModule.default) == null ? void 0 : _a.prototype) == null ? void 0 : _b.write) {
|
|
16
20
|
const originalWrite = loggerModule.default.prototype.write;
|
|
17
21
|
loggerModule.default.prototype.write = function(info) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/loggers/winston.ts"],"sourcesContent":["import { AsyncLocalStorage } from \"node:async_hooks\";\n\nimport type { LogRecord } from \"../common/requestLogger.js\";\nimport { formatMessage, removeKeys } from \"./utils.js\";\n\nconst MAX_BUFFER_SIZE = 1000;\n\nlet isPatched = false;\nlet globalLogsContext: AsyncLocalStorage<LogRecord[]>;\n\nexport async function patchWinston(\n logsContext: AsyncLocalStorage<LogRecord[]>,\n) {\n globalLogsContext = logsContext;\n\n if (isPatched) {\n return;\n }\n\n try {\n // @ts-expect-error - file is not typed\n
|
|
1
|
+
{"version":3,"sources":["../../src/loggers/winston.ts"],"sourcesContent":["import { AsyncLocalStorage } from \"node:async_hooks\";\n\nimport type { LogRecord } from \"../common/requestLogger.js\";\nimport { formatMessage, removeKeys } from \"./utils.js\";\n\nconst MAX_BUFFER_SIZE = 1000;\n\nlet isPatched = false;\nlet globalLogsContext: AsyncLocalStorage<LogRecord[]>;\n\nexport async function patchWinston(\n logsContext: AsyncLocalStorage<LogRecord[]>,\n) {\n globalLogsContext = logsContext;\n\n if (isPatched) {\n return;\n }\n\n try {\n const loggerModule = await import(\n // @ts-expect-error - file is not typed\n /* webpackIgnore: true */ \"winston/lib/winston/logger.js\"\n );\n if (loggerModule.default?.prototype?.write) {\n const originalWrite = loggerModule.default.prototype.write;\n loggerModule.default.prototype.write = function (info: any) {\n captureLog(info);\n return originalWrite.call(this, info);\n };\n }\n } catch {\n // winston is not installed, silently ignore\n }\n\n isPatched = true;\n}\n\nfunction captureLog(info: any) {\n const logs = globalLogsContext?.getStore();\n if (!logs || !info || logs.length >= MAX_BUFFER_SIZE) {\n return;\n }\n\n try {\n const rest = removeKeys(info, [\"timestamp\", \"level\", \"message\", \"splat\"]);\n const formattedMessage = formatMessage(info.message, rest);\n if (formattedMessage) {\n logs.push({\n timestamp: parseTimestamp(info.timestamp),\n level: info.level || \"info\",\n message: formattedMessage.trim(),\n });\n }\n } catch (e) {\n // ignore\n }\n}\n\nfunction parseTimestamp(timestamp: any) {\n if (timestamp) {\n const ts = new Date(timestamp).getTime();\n if (!isNaN(ts)) {\n return ts / 1000;\n }\n }\n return Date.now() / 1000;\n}\n"],"mappings":";;AAGA,SAASA,eAAeC,kBAAkB;AAE1C,MAAMC,kBAAkB;AAExB,IAAIC,YAAY;AAChB,IAAIC;AAEJ,eAAsBC,aACpBC,aAA2C;AAR7C;AAUEF,sBAAoBE;AAEpB,MAAIH,WAAW;AACb;EACF;AAEA,MAAI;AACF,UAAMI,eAAe,MAAM;;;MAEC;IAAA;AAE5B,SAAIA,wBAAaC,YAAbD,mBAAsBE,cAAtBF,mBAAiCG,OAAO;AAC1C,YAAMC,gBAAgBJ,aAAaC,QAAQC,UAAUC;AACrDH,mBAAaC,QAAQC,UAAUC,QAAQ,SAAUE,MAAS;AACxDC,mBAAWD,IAAAA;AACX,eAAOD,cAAcG,KAAK,MAAMF,IAAAA;MAClC;IACF;EACF,QAAQ;EAER;AAEAT,cAAY;AACd;AA1BsBE;AA4BtB,SAASQ,WAAWD,MAAS;AAC3B,QAAMG,OAAOX,uDAAmBY;AAChC,MAAI,CAACD,QAAQ,CAACH,QAAQG,KAAKE,UAAUf,iBAAiB;AACpD;EACF;AAEA,MAAI;AACF,UAAMgB,OAAOjB,WAAWW,MAAM;MAAC;MAAa;MAAS;MAAW;KAAQ;AACxE,UAAMO,mBAAmBnB,cAAcY,KAAKQ,SAASF,IAAAA;AACrD,QAAIC,kBAAkB;AACpBJ,WAAKM,KAAK;QACRC,WAAWC,eAAeX,KAAKU,SAAS;QACxCE,OAAOZ,KAAKY,SAAS;QACrBJ,SAASD,iBAAiBM,KAAI;MAChC,CAAA;IACF;EACF,SAASC,GAAG;EAEZ;AACF;AAnBSb;AAqBT,SAASU,eAAeD,WAAc;AACpC,MAAIA,WAAW;AACb,UAAMK,KAAK,IAAIC,KAAKN,SAAAA,EAAWO,QAAO;AACtC,QAAI,CAACC,MAAMH,EAAAA,GAAK;AACd,aAAOA,KAAK;IACd;EACF;AACA,SAAOC,KAAKG,IAAG,IAAK;AACtB;AARSR;","names":["formatMessage","removeKeys","MAX_BUFFER_SIZE","isPatched","globalLogsContext","patchWinston","logsContext","loggerModule","default","prototype","write","originalWrite","info","captureLog","call","logs","getStore","length","rest","formattedMessage","message","push","timestamp","parseTimestamp","level","trim","e","ts","Date","getTime","isNaN","now"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "apitally",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.22.1",
|
|
4
4
|
"description": "Simple API monitoring & analytics for REST APIs built with Express, Fastify, NestJS, AdonisJS, Hono, H3, Elysia, Hapi, and Koa.",
|
|
5
5
|
"author": "Apitally <hello@apitally.io>",
|
|
6
6
|
"license": "MIT",
|
|
@@ -221,7 +221,8 @@
|
|
|
221
221
|
"fastify-plugin": "^4 || ^5",
|
|
222
222
|
"h3": "^2",
|
|
223
223
|
"hono": "^4",
|
|
224
|
-
"koa": "^2 || ^3"
|
|
224
|
+
"koa": "^2 || ^3",
|
|
225
|
+
"pino": "^8 || ^9 || ^10"
|
|
225
226
|
},
|
|
226
227
|
"peerDependenciesMeta": {
|
|
227
228
|
"@adonisjs/core": {
|
|
@@ -265,6 +266,9 @@
|
|
|
265
266
|
},
|
|
266
267
|
"koa": {
|
|
267
268
|
"optional": true
|
|
269
|
+
},
|
|
270
|
+
"pino": {
|
|
271
|
+
"optional": true
|
|
268
272
|
}
|
|
269
273
|
},
|
|
270
274
|
"devDependencies": {
|
|
@@ -302,7 +306,7 @@
|
|
|
302
306
|
"fastify": "^5.0.0",
|
|
303
307
|
"fastify-plugin": "^5.0.1",
|
|
304
308
|
"globals": "^16.2.0",
|
|
305
|
-
"h3": "2.0.
|
|
309
|
+
"h3": "2.0.1-rc.5",
|
|
306
310
|
"hono": "^4.6.5",
|
|
307
311
|
"koa": "^3.0.0",
|
|
308
312
|
"koa-bodyparser": "^4.4.1",
|