apitally 0.11.5 → 0.12.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/README.md +2 -2
- package/dist/common/client.cjs +116 -105
- package/dist/common/client.cjs.map +1 -1
- package/dist/common/client.js +111 -100
- package/dist/common/client.js.map +1 -1
- package/dist/common/requestLogger.cjs +55 -2
- package/dist/common/requestLogger.cjs.map +1 -1
- package/dist/common/requestLogger.d.cts +2 -1
- package/dist/common/requestLogger.d.ts +2 -1
- package/dist/common/requestLogger.js +55 -2
- package/dist/common/requestLogger.js.map +1 -1
- package/dist/common/sentry.cjs +55 -0
- package/dist/common/sentry.cjs.map +1 -0
- package/dist/common/sentry.d.cts +6 -0
- package/dist/common/sentry.d.ts +6 -0
- package/dist/common/sentry.js +22 -0
- package/dist/common/sentry.js.map +1 -0
- package/dist/common/serverErrorCounter.cjs +58 -45
- package/dist/common/serverErrorCounter.cjs.map +1 -1
- package/dist/common/serverErrorCounter.d.cts +3 -6
- package/dist/common/serverErrorCounter.d.ts +3 -6
- package/dist/common/serverErrorCounter.js +53 -45
- package/dist/common/serverErrorCounter.js.map +1 -1
- package/dist/express/index.cjs +117 -106
- package/dist/express/index.cjs.map +1 -1
- package/dist/express/index.js +112 -101
- package/dist/express/index.js.map +1 -1
- package/dist/express/middleware.cjs +117 -106
- package/dist/express/middleware.cjs.map +1 -1
- package/dist/express/middleware.js +112 -101
- package/dist/express/middleware.js.map +1 -1
- package/dist/fastify/index.cjs +117 -106
- package/dist/fastify/index.cjs.map +1 -1
- package/dist/fastify/index.js +112 -101
- package/dist/fastify/index.js.map +1 -1
- package/dist/fastify/plugin.cjs +117 -106
- package/dist/fastify/plugin.cjs.map +1 -1
- package/dist/fastify/plugin.js +112 -101
- package/dist/fastify/plugin.js.map +1 -1
- package/dist/hono/index.cjs +117 -106
- package/dist/hono/index.cjs.map +1 -1
- package/dist/hono/index.js +112 -101
- package/dist/hono/index.js.map +1 -1
- package/dist/hono/middleware.cjs +117 -106
- package/dist/hono/middleware.cjs.map +1 -1
- package/dist/hono/middleware.js +112 -101
- package/dist/hono/middleware.js.map +1 -1
- package/dist/koa/index.cjs +119 -106
- package/dist/koa/index.cjs.map +1 -1
- package/dist/koa/index.js +114 -101
- package/dist/koa/index.js.map +1 -1
- package/dist/koa/middleware.cjs +119 -106
- package/dist/koa/middleware.cjs.map +1 -1
- package/dist/koa/middleware.js +114 -101
- package/dist/koa/middleware.js.map +1 -1
- package/dist/nestjs/index.cjs +117 -106
- package/dist/nestjs/index.cjs.map +1 -1
- package/dist/nestjs/index.js +112 -101
- package/dist/nestjs/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -211,14 +211,116 @@ var RequestCounter = _RequestCounter;
|
|
|
211
211
|
// src/common/requestLogger.ts
|
|
212
212
|
var import_async_lock = __toESM(require("async-lock"), 1);
|
|
213
213
|
var import_buffer2 = require("buffer");
|
|
214
|
-
var
|
|
214
|
+
var import_crypto3 = require("crypto");
|
|
215
215
|
var import_fs2 = require("fs");
|
|
216
216
|
var import_os2 = require("os");
|
|
217
217
|
var import_path2 = require("path");
|
|
218
218
|
|
|
219
|
+
// src/common/sentry.ts
|
|
220
|
+
var sentry;
|
|
221
|
+
(async () => {
|
|
222
|
+
try {
|
|
223
|
+
sentry = await import("@sentry/node");
|
|
224
|
+
} catch (e) {
|
|
225
|
+
}
|
|
226
|
+
})();
|
|
227
|
+
function getSentryEventId() {
|
|
228
|
+
if (sentry && sentry.lastEventId) {
|
|
229
|
+
return sentry.lastEventId();
|
|
230
|
+
}
|
|
231
|
+
return void 0;
|
|
232
|
+
}
|
|
233
|
+
__name(getSentryEventId, "getSentryEventId");
|
|
234
|
+
|
|
235
|
+
// src/common/serverErrorCounter.ts
|
|
236
|
+
var import_crypto = require("crypto");
|
|
237
|
+
var MAX_MSG_LENGTH = 2048;
|
|
238
|
+
var MAX_STACKTRACE_LENGTH = 65536;
|
|
239
|
+
var _ServerErrorCounter = class _ServerErrorCounter {
|
|
240
|
+
errorCounts;
|
|
241
|
+
errorDetails;
|
|
242
|
+
sentryEventIds;
|
|
243
|
+
constructor() {
|
|
244
|
+
this.errorCounts = /* @__PURE__ */ new Map();
|
|
245
|
+
this.errorDetails = /* @__PURE__ */ new Map();
|
|
246
|
+
this.sentryEventIds = /* @__PURE__ */ new Map();
|
|
247
|
+
}
|
|
248
|
+
addServerError(serverError) {
|
|
249
|
+
const key = this.getKey(serverError);
|
|
250
|
+
if (!this.errorDetails.has(key)) {
|
|
251
|
+
this.errorDetails.set(key, serverError);
|
|
252
|
+
}
|
|
253
|
+
this.errorCounts.set(key, (this.errorCounts.get(key) || 0) + 1);
|
|
254
|
+
const sentryEventId = getSentryEventId();
|
|
255
|
+
if (sentryEventId) {
|
|
256
|
+
this.sentryEventIds.set(key, sentryEventId);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
getAndResetServerErrors() {
|
|
260
|
+
const data = [];
|
|
261
|
+
this.errorCounts.forEach((count, key) => {
|
|
262
|
+
const serverError = this.errorDetails.get(key);
|
|
263
|
+
if (serverError) {
|
|
264
|
+
data.push({
|
|
265
|
+
consumer: serverError.consumer || null,
|
|
266
|
+
method: serverError.method,
|
|
267
|
+
path: serverError.path,
|
|
268
|
+
type: serverError.type,
|
|
269
|
+
msg: truncateExceptionMessage(serverError.msg),
|
|
270
|
+
traceback: truncateExceptionStackTrace(serverError.traceback),
|
|
271
|
+
sentry_event_id: this.sentryEventIds.get(key) || null,
|
|
272
|
+
error_count: count
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
});
|
|
276
|
+
this.errorCounts.clear();
|
|
277
|
+
this.errorDetails.clear();
|
|
278
|
+
return data;
|
|
279
|
+
}
|
|
280
|
+
getKey(serverError) {
|
|
281
|
+
const hashInput = [
|
|
282
|
+
serverError.consumer || "",
|
|
283
|
+
serverError.method.toUpperCase(),
|
|
284
|
+
serverError.path,
|
|
285
|
+
serverError.type,
|
|
286
|
+
serverError.msg.trim(),
|
|
287
|
+
serverError.traceback.trim()
|
|
288
|
+
].join("|");
|
|
289
|
+
return (0, import_crypto.createHash)("md5").update(hashInput).digest("hex");
|
|
290
|
+
}
|
|
291
|
+
};
|
|
292
|
+
__name(_ServerErrorCounter, "ServerErrorCounter");
|
|
293
|
+
var ServerErrorCounter = _ServerErrorCounter;
|
|
294
|
+
function truncateExceptionMessage(msg) {
|
|
295
|
+
if (msg.length <= MAX_MSG_LENGTH) {
|
|
296
|
+
return msg;
|
|
297
|
+
}
|
|
298
|
+
const suffix = "... (truncated)";
|
|
299
|
+
const cutoff = MAX_MSG_LENGTH - suffix.length;
|
|
300
|
+
return msg.substring(0, cutoff) + suffix;
|
|
301
|
+
}
|
|
302
|
+
__name(truncateExceptionMessage, "truncateExceptionMessage");
|
|
303
|
+
function truncateExceptionStackTrace(stack) {
|
|
304
|
+
const suffix = "... (truncated) ...";
|
|
305
|
+
const cutoff = MAX_STACKTRACE_LENGTH - suffix.length;
|
|
306
|
+
const lines = stack.trim().split("\n");
|
|
307
|
+
const truncatedLines = [];
|
|
308
|
+
let length = 0;
|
|
309
|
+
for (const line of lines) {
|
|
310
|
+
if (length + line.length + 1 > cutoff) {
|
|
311
|
+
truncatedLines.push(suffix);
|
|
312
|
+
break;
|
|
313
|
+
}
|
|
314
|
+
truncatedLines.push(line);
|
|
315
|
+
length += line.length + 1;
|
|
316
|
+
}
|
|
317
|
+
return truncatedLines.join("\n");
|
|
318
|
+
}
|
|
319
|
+
__name(truncateExceptionStackTrace, "truncateExceptionStackTrace");
|
|
320
|
+
|
|
219
321
|
// src/common/tempGzipFile.ts
|
|
220
322
|
var import_buffer = require("buffer");
|
|
221
|
-
var
|
|
323
|
+
var import_crypto2 = require("crypto");
|
|
222
324
|
var import_fs = require("fs");
|
|
223
325
|
var import_os = require("os");
|
|
224
326
|
var import_path = require("path");
|
|
@@ -231,7 +333,7 @@ var _TempGzipFile = class _TempGzipFile {
|
|
|
231
333
|
readyPromise;
|
|
232
334
|
closedPromise;
|
|
233
335
|
constructor() {
|
|
234
|
-
this.uuid = (0,
|
|
336
|
+
this.uuid = (0, import_crypto2.randomUUID)();
|
|
235
337
|
this.filePath = (0, import_path.join)((0, import_os.tmpdir)(), `apitally-${this.uuid}.gz`);
|
|
236
338
|
this.writeStream = (0, import_fs.createWriteStream)(this.filePath);
|
|
237
339
|
this.readyPromise = new Promise((resolve, reject) => {
|
|
@@ -338,6 +440,7 @@ var DEFAULT_CONFIG = {
|
|
|
338
440
|
logRequestBody: false,
|
|
339
441
|
logResponseHeaders: true,
|
|
340
442
|
logResponseBody: false,
|
|
443
|
+
logException: true,
|
|
341
444
|
maskQueryParams: [],
|
|
342
445
|
maskHeaders: [],
|
|
343
446
|
excludePaths: []
|
|
@@ -410,7 +513,7 @@ var _RequestLogger = class _RequestLogger {
|
|
|
410
513
|
this.shouldMaskHeader(k) ? MASKED : v
|
|
411
514
|
]);
|
|
412
515
|
}
|
|
413
|
-
logRequest(request, response) {
|
|
516
|
+
logRequest(request, response, error) {
|
|
414
517
|
var _a2, _b, _c;
|
|
415
518
|
if (!this.enabled || this.suspendUntil !== null) return;
|
|
416
519
|
const url = new URL(request.url);
|
|
@@ -456,9 +559,15 @@ var _RequestLogger = class _RequestLogger {
|
|
|
456
559
|
request.headers = this.config.logRequestHeaders ? this.maskHeaders(request.headers) : [];
|
|
457
560
|
response.headers = this.config.logResponseHeaders ? this.maskHeaders(response.headers) : [];
|
|
458
561
|
const item = {
|
|
459
|
-
uuid: (0,
|
|
562
|
+
uuid: (0, import_crypto3.randomUUID)(),
|
|
460
563
|
request: skipEmptyValues(request),
|
|
461
|
-
response: skipEmptyValues(response)
|
|
564
|
+
response: skipEmptyValues(response),
|
|
565
|
+
exception: error && this.config.logException ? {
|
|
566
|
+
type: error.name,
|
|
567
|
+
message: truncateExceptionMessage(error.message),
|
|
568
|
+
stacktrace: truncateExceptionStackTrace(error.stack || ""),
|
|
569
|
+
sentryEventId: getSentryEventId()
|
|
570
|
+
} : null
|
|
462
571
|
};
|
|
463
572
|
[
|
|
464
573
|
item.request.body,
|
|
@@ -610,7 +719,7 @@ function skipEmptyValues(data) {
|
|
|
610
719
|
__name(skipEmptyValues, "skipEmptyValues");
|
|
611
720
|
function checkWritableFs() {
|
|
612
721
|
try {
|
|
613
|
-
const testPath = (0, import_path2.join)((0, import_os2.tmpdir)(), `apitally-${(0,
|
|
722
|
+
const testPath = (0, import_path2.join)((0, import_os2.tmpdir)(), `apitally-${(0, import_crypto3.randomUUID)()}`);
|
|
614
723
|
(0, import_fs2.writeFileSync)(testPath, "test");
|
|
615
724
|
(0, import_fs2.unlinkSync)(testPath);
|
|
616
725
|
return true;
|
|
@@ -620,104 +729,6 @@ function checkWritableFs() {
|
|
|
620
729
|
}
|
|
621
730
|
__name(checkWritableFs, "checkWritableFs");
|
|
622
731
|
|
|
623
|
-
// src/common/serverErrorCounter.ts
|
|
624
|
-
var import_crypto3 = require("crypto");
|
|
625
|
-
var MAX_MSG_LENGTH = 2048;
|
|
626
|
-
var MAX_STACKTRACE_LENGTH = 65536;
|
|
627
|
-
var _ServerErrorCounter = class _ServerErrorCounter {
|
|
628
|
-
errorCounts;
|
|
629
|
-
errorDetails;
|
|
630
|
-
sentryEventIds;
|
|
631
|
-
sentry;
|
|
632
|
-
constructor() {
|
|
633
|
-
this.errorCounts = /* @__PURE__ */ new Map();
|
|
634
|
-
this.errorDetails = /* @__PURE__ */ new Map();
|
|
635
|
-
this.sentryEventIds = /* @__PURE__ */ new Map();
|
|
636
|
-
this.tryImportSentry();
|
|
637
|
-
}
|
|
638
|
-
addServerError(serverError) {
|
|
639
|
-
const key = this.getKey(serverError);
|
|
640
|
-
if (!this.errorDetails.has(key)) {
|
|
641
|
-
this.errorDetails.set(key, serverError);
|
|
642
|
-
}
|
|
643
|
-
this.errorCounts.set(key, (this.errorCounts.get(key) || 0) + 1);
|
|
644
|
-
this.captureSentryEventId(key);
|
|
645
|
-
}
|
|
646
|
-
getAndResetServerErrors() {
|
|
647
|
-
const data = [];
|
|
648
|
-
this.errorCounts.forEach((count, key) => {
|
|
649
|
-
const serverError = this.errorDetails.get(key);
|
|
650
|
-
if (serverError) {
|
|
651
|
-
data.push({
|
|
652
|
-
consumer: serverError.consumer || null,
|
|
653
|
-
method: serverError.method,
|
|
654
|
-
path: serverError.path,
|
|
655
|
-
type: serverError.type,
|
|
656
|
-
msg: this.getTruncatedMessage(serverError.msg),
|
|
657
|
-
traceback: this.getTruncatedStack(serverError.traceback),
|
|
658
|
-
sentry_event_id: this.sentryEventIds.get(key) || null,
|
|
659
|
-
error_count: count
|
|
660
|
-
});
|
|
661
|
-
}
|
|
662
|
-
});
|
|
663
|
-
this.errorCounts.clear();
|
|
664
|
-
this.errorDetails.clear();
|
|
665
|
-
return data;
|
|
666
|
-
}
|
|
667
|
-
getKey(serverError) {
|
|
668
|
-
const hashInput = [
|
|
669
|
-
serverError.consumer || "",
|
|
670
|
-
serverError.method.toUpperCase(),
|
|
671
|
-
serverError.path,
|
|
672
|
-
serverError.type,
|
|
673
|
-
serverError.msg.trim(),
|
|
674
|
-
serverError.traceback.trim()
|
|
675
|
-
].join("|");
|
|
676
|
-
return (0, import_crypto3.createHash)("md5").update(hashInput).digest("hex");
|
|
677
|
-
}
|
|
678
|
-
getTruncatedMessage(msg) {
|
|
679
|
-
msg = msg.trim();
|
|
680
|
-
if (msg.length <= MAX_MSG_LENGTH) {
|
|
681
|
-
return msg;
|
|
682
|
-
}
|
|
683
|
-
const suffix = "... (truncated)";
|
|
684
|
-
const cutoff = MAX_MSG_LENGTH - suffix.length;
|
|
685
|
-
return msg.substring(0, cutoff) + suffix;
|
|
686
|
-
}
|
|
687
|
-
getTruncatedStack(stack) {
|
|
688
|
-
const suffix = "... (truncated) ...";
|
|
689
|
-
const cutoff = MAX_STACKTRACE_LENGTH - suffix.length;
|
|
690
|
-
const lines = stack.trim().split("\n");
|
|
691
|
-
const truncatedLines = [];
|
|
692
|
-
let length = 0;
|
|
693
|
-
for (const line of lines) {
|
|
694
|
-
if (length + line.length + 1 > cutoff) {
|
|
695
|
-
truncatedLines.push(suffix);
|
|
696
|
-
break;
|
|
697
|
-
}
|
|
698
|
-
truncatedLines.push(line);
|
|
699
|
-
length += line.length + 1;
|
|
700
|
-
}
|
|
701
|
-
return truncatedLines.join("\n");
|
|
702
|
-
}
|
|
703
|
-
captureSentryEventId(serverErrorKey) {
|
|
704
|
-
if (this.sentry && this.sentry.lastEventId) {
|
|
705
|
-
const eventId = this.sentry.lastEventId();
|
|
706
|
-
if (eventId) {
|
|
707
|
-
this.sentryEventIds.set(serverErrorKey, eventId);
|
|
708
|
-
}
|
|
709
|
-
}
|
|
710
|
-
}
|
|
711
|
-
async tryImportSentry() {
|
|
712
|
-
try {
|
|
713
|
-
this.sentry = await import("@sentry/node");
|
|
714
|
-
} catch (e) {
|
|
715
|
-
}
|
|
716
|
-
}
|
|
717
|
-
};
|
|
718
|
-
__name(_ServerErrorCounter, "ServerErrorCounter");
|
|
719
|
-
var ServerErrorCounter = _ServerErrorCounter;
|
|
720
|
-
|
|
721
732
|
// src/common/validationErrorCounter.ts
|
|
722
733
|
var import_crypto4 = require("crypto");
|
|
723
734
|
var _ValidationErrorCounter = class _ValidationErrorCounter {
|
|
@@ -1289,7 +1300,7 @@ var getMiddleware = /* @__PURE__ */ __name((app, client) => {
|
|
|
1289
1300
|
headers: convertHeaders(res.getHeaders()),
|
|
1290
1301
|
size: Number(res.get("content-length")),
|
|
1291
1302
|
body: convertBody(res.locals.body, res.get("content-type"))
|
|
1292
|
-
});
|
|
1303
|
+
}, res.locals.serverError);
|
|
1293
1304
|
}
|
|
1294
1305
|
} catch (error) {
|
|
1295
1306
|
client.logger.error("Error while logging request in Apitally middleware.", {
|