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
package/dist/hono/index.cjs
CHANGED
|
@@ -214,14 +214,116 @@ var RequestCounter = _RequestCounter;
|
|
|
214
214
|
// src/common/requestLogger.ts
|
|
215
215
|
var import_async_lock = __toESM(require("async-lock"), 1);
|
|
216
216
|
var import_buffer2 = require("buffer");
|
|
217
|
-
var
|
|
217
|
+
var import_crypto3 = require("crypto");
|
|
218
218
|
var import_fs2 = require("fs");
|
|
219
219
|
var import_os2 = require("os");
|
|
220
220
|
var import_path2 = require("path");
|
|
221
221
|
|
|
222
|
+
// src/common/sentry.ts
|
|
223
|
+
var sentry;
|
|
224
|
+
(async () => {
|
|
225
|
+
try {
|
|
226
|
+
sentry = await import("@sentry/node");
|
|
227
|
+
} catch (e) {
|
|
228
|
+
}
|
|
229
|
+
})();
|
|
230
|
+
function getSentryEventId() {
|
|
231
|
+
if (sentry && sentry.lastEventId) {
|
|
232
|
+
return sentry.lastEventId();
|
|
233
|
+
}
|
|
234
|
+
return void 0;
|
|
235
|
+
}
|
|
236
|
+
__name(getSentryEventId, "getSentryEventId");
|
|
237
|
+
|
|
238
|
+
// src/common/serverErrorCounter.ts
|
|
239
|
+
var import_crypto = require("crypto");
|
|
240
|
+
var MAX_MSG_LENGTH = 2048;
|
|
241
|
+
var MAX_STACKTRACE_LENGTH = 65536;
|
|
242
|
+
var _ServerErrorCounter = class _ServerErrorCounter {
|
|
243
|
+
errorCounts;
|
|
244
|
+
errorDetails;
|
|
245
|
+
sentryEventIds;
|
|
246
|
+
constructor() {
|
|
247
|
+
this.errorCounts = /* @__PURE__ */ new Map();
|
|
248
|
+
this.errorDetails = /* @__PURE__ */ new Map();
|
|
249
|
+
this.sentryEventIds = /* @__PURE__ */ new Map();
|
|
250
|
+
}
|
|
251
|
+
addServerError(serverError) {
|
|
252
|
+
const key = this.getKey(serverError);
|
|
253
|
+
if (!this.errorDetails.has(key)) {
|
|
254
|
+
this.errorDetails.set(key, serverError);
|
|
255
|
+
}
|
|
256
|
+
this.errorCounts.set(key, (this.errorCounts.get(key) || 0) + 1);
|
|
257
|
+
const sentryEventId = getSentryEventId();
|
|
258
|
+
if (sentryEventId) {
|
|
259
|
+
this.sentryEventIds.set(key, sentryEventId);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
getAndResetServerErrors() {
|
|
263
|
+
const data = [];
|
|
264
|
+
this.errorCounts.forEach((count, key) => {
|
|
265
|
+
const serverError = this.errorDetails.get(key);
|
|
266
|
+
if (serverError) {
|
|
267
|
+
data.push({
|
|
268
|
+
consumer: serverError.consumer || null,
|
|
269
|
+
method: serverError.method,
|
|
270
|
+
path: serverError.path,
|
|
271
|
+
type: serverError.type,
|
|
272
|
+
msg: truncateExceptionMessage(serverError.msg),
|
|
273
|
+
traceback: truncateExceptionStackTrace(serverError.traceback),
|
|
274
|
+
sentry_event_id: this.sentryEventIds.get(key) || null,
|
|
275
|
+
error_count: count
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
});
|
|
279
|
+
this.errorCounts.clear();
|
|
280
|
+
this.errorDetails.clear();
|
|
281
|
+
return data;
|
|
282
|
+
}
|
|
283
|
+
getKey(serverError) {
|
|
284
|
+
const hashInput = [
|
|
285
|
+
serverError.consumer || "",
|
|
286
|
+
serverError.method.toUpperCase(),
|
|
287
|
+
serverError.path,
|
|
288
|
+
serverError.type,
|
|
289
|
+
serverError.msg.trim(),
|
|
290
|
+
serverError.traceback.trim()
|
|
291
|
+
].join("|");
|
|
292
|
+
return (0, import_crypto.createHash)("md5").update(hashInput).digest("hex");
|
|
293
|
+
}
|
|
294
|
+
};
|
|
295
|
+
__name(_ServerErrorCounter, "ServerErrorCounter");
|
|
296
|
+
var ServerErrorCounter = _ServerErrorCounter;
|
|
297
|
+
function truncateExceptionMessage(msg) {
|
|
298
|
+
if (msg.length <= MAX_MSG_LENGTH) {
|
|
299
|
+
return msg;
|
|
300
|
+
}
|
|
301
|
+
const suffix = "... (truncated)";
|
|
302
|
+
const cutoff = MAX_MSG_LENGTH - suffix.length;
|
|
303
|
+
return msg.substring(0, cutoff) + suffix;
|
|
304
|
+
}
|
|
305
|
+
__name(truncateExceptionMessage, "truncateExceptionMessage");
|
|
306
|
+
function truncateExceptionStackTrace(stack) {
|
|
307
|
+
const suffix = "... (truncated) ...";
|
|
308
|
+
const cutoff = MAX_STACKTRACE_LENGTH - suffix.length;
|
|
309
|
+
const lines = stack.trim().split("\n");
|
|
310
|
+
const truncatedLines = [];
|
|
311
|
+
let length = 0;
|
|
312
|
+
for (const line of lines) {
|
|
313
|
+
if (length + line.length + 1 > cutoff) {
|
|
314
|
+
truncatedLines.push(suffix);
|
|
315
|
+
break;
|
|
316
|
+
}
|
|
317
|
+
truncatedLines.push(line);
|
|
318
|
+
length += line.length + 1;
|
|
319
|
+
}
|
|
320
|
+
return truncatedLines.join("\n");
|
|
321
|
+
}
|
|
322
|
+
__name(truncateExceptionStackTrace, "truncateExceptionStackTrace");
|
|
323
|
+
|
|
222
324
|
// src/common/tempGzipFile.ts
|
|
223
325
|
var import_buffer = require("buffer");
|
|
224
|
-
var
|
|
326
|
+
var import_crypto2 = require("crypto");
|
|
225
327
|
var import_fs = require("fs");
|
|
226
328
|
var import_os = require("os");
|
|
227
329
|
var import_path = require("path");
|
|
@@ -234,7 +336,7 @@ var _TempGzipFile = class _TempGzipFile {
|
|
|
234
336
|
readyPromise;
|
|
235
337
|
closedPromise;
|
|
236
338
|
constructor() {
|
|
237
|
-
this.uuid = (0,
|
|
339
|
+
this.uuid = (0, import_crypto2.randomUUID)();
|
|
238
340
|
this.filePath = (0, import_path.join)((0, import_os.tmpdir)(), `apitally-${this.uuid}.gz`);
|
|
239
341
|
this.writeStream = (0, import_fs.createWriteStream)(this.filePath);
|
|
240
342
|
this.readyPromise = new Promise((resolve, reject) => {
|
|
@@ -341,6 +443,7 @@ var DEFAULT_CONFIG = {
|
|
|
341
443
|
logRequestBody: false,
|
|
342
444
|
logResponseHeaders: true,
|
|
343
445
|
logResponseBody: false,
|
|
446
|
+
logException: true,
|
|
344
447
|
maskQueryParams: [],
|
|
345
448
|
maskHeaders: [],
|
|
346
449
|
excludePaths: []
|
|
@@ -413,7 +516,7 @@ var _RequestLogger = class _RequestLogger {
|
|
|
413
516
|
this.shouldMaskHeader(k) ? MASKED : v
|
|
414
517
|
]);
|
|
415
518
|
}
|
|
416
|
-
logRequest(request, response) {
|
|
519
|
+
logRequest(request, response, error) {
|
|
417
520
|
var _a2, _b, _c;
|
|
418
521
|
if (!this.enabled || this.suspendUntil !== null) return;
|
|
419
522
|
const url = new URL(request.url);
|
|
@@ -459,9 +562,15 @@ var _RequestLogger = class _RequestLogger {
|
|
|
459
562
|
request.headers = this.config.logRequestHeaders ? this.maskHeaders(request.headers) : [];
|
|
460
563
|
response.headers = this.config.logResponseHeaders ? this.maskHeaders(response.headers) : [];
|
|
461
564
|
const item = {
|
|
462
|
-
uuid: (0,
|
|
565
|
+
uuid: (0, import_crypto3.randomUUID)(),
|
|
463
566
|
request: skipEmptyValues(request),
|
|
464
|
-
response: skipEmptyValues(response)
|
|
567
|
+
response: skipEmptyValues(response),
|
|
568
|
+
exception: error && this.config.logException ? {
|
|
569
|
+
type: error.name,
|
|
570
|
+
message: truncateExceptionMessage(error.message),
|
|
571
|
+
stacktrace: truncateExceptionStackTrace(error.stack || ""),
|
|
572
|
+
sentryEventId: getSentryEventId()
|
|
573
|
+
} : null
|
|
465
574
|
};
|
|
466
575
|
[
|
|
467
576
|
item.request.body,
|
|
@@ -581,7 +690,7 @@ function skipEmptyValues(data) {
|
|
|
581
690
|
__name(skipEmptyValues, "skipEmptyValues");
|
|
582
691
|
function checkWritableFs() {
|
|
583
692
|
try {
|
|
584
|
-
const testPath = (0, import_path2.join)((0, import_os2.tmpdir)(), `apitally-${(0,
|
|
693
|
+
const testPath = (0, import_path2.join)((0, import_os2.tmpdir)(), `apitally-${(0, import_crypto3.randomUUID)()}`);
|
|
585
694
|
(0, import_fs2.writeFileSync)(testPath, "test");
|
|
586
695
|
(0, import_fs2.unlinkSync)(testPath);
|
|
587
696
|
return true;
|
|
@@ -591,104 +700,6 @@ function checkWritableFs() {
|
|
|
591
700
|
}
|
|
592
701
|
__name(checkWritableFs, "checkWritableFs");
|
|
593
702
|
|
|
594
|
-
// src/common/serverErrorCounter.ts
|
|
595
|
-
var import_crypto3 = require("crypto");
|
|
596
|
-
var MAX_MSG_LENGTH = 2048;
|
|
597
|
-
var MAX_STACKTRACE_LENGTH = 65536;
|
|
598
|
-
var _ServerErrorCounter = class _ServerErrorCounter {
|
|
599
|
-
errorCounts;
|
|
600
|
-
errorDetails;
|
|
601
|
-
sentryEventIds;
|
|
602
|
-
sentry;
|
|
603
|
-
constructor() {
|
|
604
|
-
this.errorCounts = /* @__PURE__ */ new Map();
|
|
605
|
-
this.errorDetails = /* @__PURE__ */ new Map();
|
|
606
|
-
this.sentryEventIds = /* @__PURE__ */ new Map();
|
|
607
|
-
this.tryImportSentry();
|
|
608
|
-
}
|
|
609
|
-
addServerError(serverError) {
|
|
610
|
-
const key = this.getKey(serverError);
|
|
611
|
-
if (!this.errorDetails.has(key)) {
|
|
612
|
-
this.errorDetails.set(key, serverError);
|
|
613
|
-
}
|
|
614
|
-
this.errorCounts.set(key, (this.errorCounts.get(key) || 0) + 1);
|
|
615
|
-
this.captureSentryEventId(key);
|
|
616
|
-
}
|
|
617
|
-
getAndResetServerErrors() {
|
|
618
|
-
const data = [];
|
|
619
|
-
this.errorCounts.forEach((count, key) => {
|
|
620
|
-
const serverError = this.errorDetails.get(key);
|
|
621
|
-
if (serverError) {
|
|
622
|
-
data.push({
|
|
623
|
-
consumer: serverError.consumer || null,
|
|
624
|
-
method: serverError.method,
|
|
625
|
-
path: serverError.path,
|
|
626
|
-
type: serverError.type,
|
|
627
|
-
msg: this.getTruncatedMessage(serverError.msg),
|
|
628
|
-
traceback: this.getTruncatedStack(serverError.traceback),
|
|
629
|
-
sentry_event_id: this.sentryEventIds.get(key) || null,
|
|
630
|
-
error_count: count
|
|
631
|
-
});
|
|
632
|
-
}
|
|
633
|
-
});
|
|
634
|
-
this.errorCounts.clear();
|
|
635
|
-
this.errorDetails.clear();
|
|
636
|
-
return data;
|
|
637
|
-
}
|
|
638
|
-
getKey(serverError) {
|
|
639
|
-
const hashInput = [
|
|
640
|
-
serverError.consumer || "",
|
|
641
|
-
serverError.method.toUpperCase(),
|
|
642
|
-
serverError.path,
|
|
643
|
-
serverError.type,
|
|
644
|
-
serverError.msg.trim(),
|
|
645
|
-
serverError.traceback.trim()
|
|
646
|
-
].join("|");
|
|
647
|
-
return (0, import_crypto3.createHash)("md5").update(hashInput).digest("hex");
|
|
648
|
-
}
|
|
649
|
-
getTruncatedMessage(msg) {
|
|
650
|
-
msg = msg.trim();
|
|
651
|
-
if (msg.length <= MAX_MSG_LENGTH) {
|
|
652
|
-
return msg;
|
|
653
|
-
}
|
|
654
|
-
const suffix = "... (truncated)";
|
|
655
|
-
const cutoff = MAX_MSG_LENGTH - suffix.length;
|
|
656
|
-
return msg.substring(0, cutoff) + suffix;
|
|
657
|
-
}
|
|
658
|
-
getTruncatedStack(stack) {
|
|
659
|
-
const suffix = "... (truncated) ...";
|
|
660
|
-
const cutoff = MAX_STACKTRACE_LENGTH - suffix.length;
|
|
661
|
-
const lines = stack.trim().split("\n");
|
|
662
|
-
const truncatedLines = [];
|
|
663
|
-
let length = 0;
|
|
664
|
-
for (const line of lines) {
|
|
665
|
-
if (length + line.length + 1 > cutoff) {
|
|
666
|
-
truncatedLines.push(suffix);
|
|
667
|
-
break;
|
|
668
|
-
}
|
|
669
|
-
truncatedLines.push(line);
|
|
670
|
-
length += line.length + 1;
|
|
671
|
-
}
|
|
672
|
-
return truncatedLines.join("\n");
|
|
673
|
-
}
|
|
674
|
-
captureSentryEventId(serverErrorKey) {
|
|
675
|
-
if (this.sentry && this.sentry.lastEventId) {
|
|
676
|
-
const eventId = this.sentry.lastEventId();
|
|
677
|
-
if (eventId) {
|
|
678
|
-
this.sentryEventIds.set(serverErrorKey, eventId);
|
|
679
|
-
}
|
|
680
|
-
}
|
|
681
|
-
}
|
|
682
|
-
async tryImportSentry() {
|
|
683
|
-
try {
|
|
684
|
-
this.sentry = await import("@sentry/node");
|
|
685
|
-
} catch (e) {
|
|
686
|
-
}
|
|
687
|
-
}
|
|
688
|
-
};
|
|
689
|
-
__name(_ServerErrorCounter, "ServerErrorCounter");
|
|
690
|
-
var ServerErrorCounter = _ServerErrorCounter;
|
|
691
|
-
|
|
692
703
|
// src/common/validationErrorCounter.ts
|
|
693
704
|
var import_crypto4 = require("crypto");
|
|
694
705
|
var _ValidationErrorCounter = class _ValidationErrorCounter {
|
|
@@ -1113,7 +1124,7 @@ var getMiddleware = /* @__PURE__ */ __name((client) => {
|
|
|
1113
1124
|
headers: convertHeaders(c.res.headers),
|
|
1114
1125
|
size: responseSize,
|
|
1115
1126
|
body: responseBody
|
|
1116
|
-
});
|
|
1127
|
+
}, c.error);
|
|
1117
1128
|
}
|
|
1118
1129
|
c.res = response;
|
|
1119
1130
|
};
|