apitally 0.11.5 → 0.13.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 +43 -2
- package/dist/adonisjs/index.cjs +41 -0
- package/dist/adonisjs/index.cjs.map +1 -0
- package/dist/adonisjs/index.d.cts +14 -0
- package/dist/adonisjs/index.d.ts +14 -0
- package/dist/adonisjs/index.js +17 -0
- package/dist/adonisjs/index.js.map +1 -0
- package/dist/adonisjs/middleware.cjs +214 -0
- package/dist/adonisjs/middleware.cjs.map +1 -0
- package/dist/adonisjs/middleware.d.cts +21 -0
- package/dist/adonisjs/middleware.d.ts +21 -0
- package/dist/adonisjs/middleware.js +185 -0
- package/dist/adonisjs/middleware.js.map +1 -0
- package/dist/adonisjs/provider.cjs +1083 -0
- package/dist/adonisjs/provider.cjs.map +1 -0
- package/dist/adonisjs/provider.d.cts +28 -0
- package/dist/adonisjs/provider.d.ts +28 -0
- package/dist/adonisjs/provider.js +1057 -0
- package/dist/adonisjs/provider.js.map +1 -0
- package/dist/common/client.cjs +117 -106
- package/dist/common/client.cjs.map +1 -1
- package/dist/common/client.js +112 -101
- package/dist/common/client.js.map +1 -1
- package/dist/common/consumerRegistry.cjs.map +1 -1
- package/dist/common/consumerRegistry.js.map +1 -1
- package/dist/common/logging.cjs.map +1 -1
- package/dist/common/logging.js.map +1 -1
- package/dist/common/packageVersions.cjs.map +1 -1
- package/dist/common/packageVersions.js.map +1 -1
- package/dist/common/paramValidation.cjs.map +1 -1
- package/dist/common/paramValidation.js.map +1 -1
- package/dist/common/requestCounter.cjs.map +1 -1
- package/dist/common/requestCounter.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/common/tempGzipFile.cjs.map +1 -1
- package/dist/common/tempGzipFile.js.map +1 -1
- package/dist/common/types.cjs.map +1 -1
- package/dist/common/utils.cjs +48 -0
- package/dist/common/utils.cjs.map +1 -0
- package/dist/common/utils.d.cts +5 -0
- package/dist/common/utils.d.ts +5 -0
- package/dist/common/utils.js +25 -0
- package/dist/common/utils.js.map +1 -0
- package/dist/common/validationErrorCounter.cjs.map +1 -1
- package/dist/common/validationErrorCounter.js.map +1 -1
- package/dist/express/index.cjs +143 -111
- package/dist/express/index.cjs.map +1 -1
- package/dist/express/index.js +138 -106
- package/dist/express/index.js.map +1 -1
- package/dist/express/middleware.cjs +143 -111
- package/dist/express/middleware.cjs.map +1 -1
- package/dist/express/middleware.js +138 -106
- package/dist/express/middleware.js.map +1 -1
- package/dist/express/utils.cjs.map +1 -1
- package/dist/express/utils.js.map +1 -1
- package/dist/fastify/index.cjs +139 -112
- package/dist/fastify/index.cjs.map +1 -1
- package/dist/fastify/index.js +134 -107
- package/dist/fastify/index.js.map +1 -1
- package/dist/fastify/plugin.cjs +139 -112
- package/dist/fastify/plugin.cjs.map +1 -1
- package/dist/fastify/plugin.js +134 -107
- package/dist/fastify/plugin.js.map +1 -1
- package/dist/hono/index.cjs +138 -108
- package/dist/hono/index.cjs.map +1 -1
- package/dist/hono/index.js +133 -103
- package/dist/hono/index.js.map +1 -1
- package/dist/hono/middleware.cjs +138 -108
- package/dist/hono/middleware.cjs.map +1 -1
- package/dist/hono/middleware.js +133 -103
- package/dist/hono/middleware.js.map +1 -1
- package/dist/koa/index.cjs +122 -109
- package/dist/koa/index.cjs.map +1 -1
- package/dist/koa/index.js +117 -104
- package/dist/koa/index.js.map +1 -1
- package/dist/koa/middleware.cjs +122 -109
- package/dist/koa/middleware.cjs.map +1 -1
- package/dist/koa/middleware.js +117 -104
- package/dist/koa/middleware.js.map +1 -1
- package/dist/nestjs/index.cjs +143 -111
- package/dist/nestjs/index.cjs.map +1 -1
- package/dist/nestjs/index.js +138 -106
- package/dist/nestjs/index.js.map +1 -1
- package/package.json +46 -1
package/dist/hono/middleware.cjs
CHANGED
|
@@ -212,14 +212,116 @@ var RequestCounter = _RequestCounter;
|
|
|
212
212
|
// src/common/requestLogger.ts
|
|
213
213
|
var import_async_lock = __toESM(require("async-lock"), 1);
|
|
214
214
|
var import_buffer2 = require("buffer");
|
|
215
|
-
var
|
|
215
|
+
var import_crypto3 = require("crypto");
|
|
216
216
|
var import_fs2 = require("fs");
|
|
217
217
|
var import_os2 = require("os");
|
|
218
218
|
var import_path2 = require("path");
|
|
219
219
|
|
|
220
|
+
// src/common/sentry.ts
|
|
221
|
+
var sentry;
|
|
222
|
+
(async () => {
|
|
223
|
+
try {
|
|
224
|
+
sentry = await import("@sentry/node");
|
|
225
|
+
} catch (e) {
|
|
226
|
+
}
|
|
227
|
+
})();
|
|
228
|
+
function getSentryEventId() {
|
|
229
|
+
if (sentry && sentry.lastEventId) {
|
|
230
|
+
return sentry.lastEventId();
|
|
231
|
+
}
|
|
232
|
+
return void 0;
|
|
233
|
+
}
|
|
234
|
+
__name(getSentryEventId, "getSentryEventId");
|
|
235
|
+
|
|
236
|
+
// src/common/serverErrorCounter.ts
|
|
237
|
+
var import_crypto = require("crypto");
|
|
238
|
+
var MAX_MSG_LENGTH = 2048;
|
|
239
|
+
var MAX_STACKTRACE_LENGTH = 65536;
|
|
240
|
+
var _ServerErrorCounter = class _ServerErrorCounter {
|
|
241
|
+
errorCounts;
|
|
242
|
+
errorDetails;
|
|
243
|
+
sentryEventIds;
|
|
244
|
+
constructor() {
|
|
245
|
+
this.errorCounts = /* @__PURE__ */ new Map();
|
|
246
|
+
this.errorDetails = /* @__PURE__ */ new Map();
|
|
247
|
+
this.sentryEventIds = /* @__PURE__ */ new Map();
|
|
248
|
+
}
|
|
249
|
+
addServerError(serverError) {
|
|
250
|
+
const key = this.getKey(serverError);
|
|
251
|
+
if (!this.errorDetails.has(key)) {
|
|
252
|
+
this.errorDetails.set(key, serverError);
|
|
253
|
+
}
|
|
254
|
+
this.errorCounts.set(key, (this.errorCounts.get(key) || 0) + 1);
|
|
255
|
+
const sentryEventId = getSentryEventId();
|
|
256
|
+
if (sentryEventId) {
|
|
257
|
+
this.sentryEventIds.set(key, sentryEventId);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
getAndResetServerErrors() {
|
|
261
|
+
const data = [];
|
|
262
|
+
this.errorCounts.forEach((count, key) => {
|
|
263
|
+
const serverError = this.errorDetails.get(key);
|
|
264
|
+
if (serverError) {
|
|
265
|
+
data.push({
|
|
266
|
+
consumer: serverError.consumer || null,
|
|
267
|
+
method: serverError.method,
|
|
268
|
+
path: serverError.path,
|
|
269
|
+
type: serverError.type,
|
|
270
|
+
msg: truncateExceptionMessage(serverError.msg),
|
|
271
|
+
traceback: truncateExceptionStackTrace(serverError.traceback),
|
|
272
|
+
sentry_event_id: this.sentryEventIds.get(key) || null,
|
|
273
|
+
error_count: count
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
});
|
|
277
|
+
this.errorCounts.clear();
|
|
278
|
+
this.errorDetails.clear();
|
|
279
|
+
return data;
|
|
280
|
+
}
|
|
281
|
+
getKey(serverError) {
|
|
282
|
+
const hashInput = [
|
|
283
|
+
serverError.consumer || "",
|
|
284
|
+
serverError.method.toUpperCase(),
|
|
285
|
+
serverError.path,
|
|
286
|
+
serverError.type,
|
|
287
|
+
serverError.msg.trim(),
|
|
288
|
+
serverError.traceback.trim()
|
|
289
|
+
].join("|");
|
|
290
|
+
return (0, import_crypto.createHash)("md5").update(hashInput).digest("hex");
|
|
291
|
+
}
|
|
292
|
+
};
|
|
293
|
+
__name(_ServerErrorCounter, "ServerErrorCounter");
|
|
294
|
+
var ServerErrorCounter = _ServerErrorCounter;
|
|
295
|
+
function truncateExceptionMessage(msg) {
|
|
296
|
+
if (msg.length <= MAX_MSG_LENGTH) {
|
|
297
|
+
return msg;
|
|
298
|
+
}
|
|
299
|
+
const suffix = "... (truncated)";
|
|
300
|
+
const cutoff = MAX_MSG_LENGTH - suffix.length;
|
|
301
|
+
return msg.substring(0, cutoff) + suffix;
|
|
302
|
+
}
|
|
303
|
+
__name(truncateExceptionMessage, "truncateExceptionMessage");
|
|
304
|
+
function truncateExceptionStackTrace(stack) {
|
|
305
|
+
const suffix = "... (truncated) ...";
|
|
306
|
+
const cutoff = MAX_STACKTRACE_LENGTH - suffix.length;
|
|
307
|
+
const lines = stack.trim().split("\n");
|
|
308
|
+
const truncatedLines = [];
|
|
309
|
+
let length = 0;
|
|
310
|
+
for (const line of lines) {
|
|
311
|
+
if (length + line.length + 1 > cutoff) {
|
|
312
|
+
truncatedLines.push(suffix);
|
|
313
|
+
break;
|
|
314
|
+
}
|
|
315
|
+
truncatedLines.push(line);
|
|
316
|
+
length += line.length + 1;
|
|
317
|
+
}
|
|
318
|
+
return truncatedLines.join("\n");
|
|
319
|
+
}
|
|
320
|
+
__name(truncateExceptionStackTrace, "truncateExceptionStackTrace");
|
|
321
|
+
|
|
220
322
|
// src/common/tempGzipFile.ts
|
|
221
323
|
var import_buffer = require("buffer");
|
|
222
|
-
var
|
|
324
|
+
var import_crypto2 = require("crypto");
|
|
223
325
|
var import_fs = require("fs");
|
|
224
326
|
var import_os = require("os");
|
|
225
327
|
var import_path = require("path");
|
|
@@ -232,7 +334,7 @@ var _TempGzipFile = class _TempGzipFile {
|
|
|
232
334
|
readyPromise;
|
|
233
335
|
closedPromise;
|
|
234
336
|
constructor() {
|
|
235
|
-
this.uuid = (0,
|
|
337
|
+
this.uuid = (0, import_crypto2.randomUUID)();
|
|
236
338
|
this.filePath = (0, import_path.join)((0, import_os.tmpdir)(), `apitally-${this.uuid}.gz`);
|
|
237
339
|
this.writeStream = (0, import_fs.createWriteStream)(this.filePath);
|
|
238
340
|
this.readyPromise = new Promise((resolve, reject) => {
|
|
@@ -339,6 +441,7 @@ var DEFAULT_CONFIG = {
|
|
|
339
441
|
logRequestBody: false,
|
|
340
442
|
logResponseHeaders: true,
|
|
341
443
|
logResponseBody: false,
|
|
444
|
+
logException: true,
|
|
342
445
|
maskQueryParams: [],
|
|
343
446
|
maskHeaders: [],
|
|
344
447
|
excludePaths: []
|
|
@@ -411,7 +514,7 @@ var _RequestLogger = class _RequestLogger {
|
|
|
411
514
|
this.shouldMaskHeader(k) ? MASKED : v
|
|
412
515
|
]);
|
|
413
516
|
}
|
|
414
|
-
logRequest(request, response) {
|
|
517
|
+
logRequest(request, response, error) {
|
|
415
518
|
var _a2, _b, _c;
|
|
416
519
|
if (!this.enabled || this.suspendUntil !== null) return;
|
|
417
520
|
const url = new URL(request.url);
|
|
@@ -457,9 +560,15 @@ var _RequestLogger = class _RequestLogger {
|
|
|
457
560
|
request.headers = this.config.logRequestHeaders ? this.maskHeaders(request.headers) : [];
|
|
458
561
|
response.headers = this.config.logResponseHeaders ? this.maskHeaders(response.headers) : [];
|
|
459
562
|
const item = {
|
|
460
|
-
uuid: (0,
|
|
563
|
+
uuid: (0, import_crypto3.randomUUID)(),
|
|
461
564
|
request: skipEmptyValues(request),
|
|
462
|
-
response: skipEmptyValues(response)
|
|
565
|
+
response: skipEmptyValues(response),
|
|
566
|
+
exception: error && this.config.logException ? {
|
|
567
|
+
type: error.name,
|
|
568
|
+
message: truncateExceptionMessage(error.message),
|
|
569
|
+
stacktrace: truncateExceptionStackTrace(error.stack || ""),
|
|
570
|
+
sentryEventId: getSentryEventId()
|
|
571
|
+
} : null
|
|
463
572
|
};
|
|
464
573
|
[
|
|
465
574
|
item.request.body,
|
|
@@ -579,7 +688,7 @@ function skipEmptyValues(data) {
|
|
|
579
688
|
__name(skipEmptyValues, "skipEmptyValues");
|
|
580
689
|
function checkWritableFs() {
|
|
581
690
|
try {
|
|
582
|
-
const testPath = (0, import_path2.join)((0, import_os2.tmpdir)(), `apitally-${(0,
|
|
691
|
+
const testPath = (0, import_path2.join)((0, import_os2.tmpdir)(), `apitally-${(0, import_crypto3.randomUUID)()}`);
|
|
583
692
|
(0, import_fs2.writeFileSync)(testPath, "test");
|
|
584
693
|
(0, import_fs2.unlinkSync)(testPath);
|
|
585
694
|
return true;
|
|
@@ -589,104 +698,6 @@ function checkWritableFs() {
|
|
|
589
698
|
}
|
|
590
699
|
__name(checkWritableFs, "checkWritableFs");
|
|
591
700
|
|
|
592
|
-
// src/common/serverErrorCounter.ts
|
|
593
|
-
var import_crypto3 = require("crypto");
|
|
594
|
-
var MAX_MSG_LENGTH = 2048;
|
|
595
|
-
var MAX_STACKTRACE_LENGTH = 65536;
|
|
596
|
-
var _ServerErrorCounter = class _ServerErrorCounter {
|
|
597
|
-
errorCounts;
|
|
598
|
-
errorDetails;
|
|
599
|
-
sentryEventIds;
|
|
600
|
-
sentry;
|
|
601
|
-
constructor() {
|
|
602
|
-
this.errorCounts = /* @__PURE__ */ new Map();
|
|
603
|
-
this.errorDetails = /* @__PURE__ */ new Map();
|
|
604
|
-
this.sentryEventIds = /* @__PURE__ */ new Map();
|
|
605
|
-
this.tryImportSentry();
|
|
606
|
-
}
|
|
607
|
-
addServerError(serverError) {
|
|
608
|
-
const key = this.getKey(serverError);
|
|
609
|
-
if (!this.errorDetails.has(key)) {
|
|
610
|
-
this.errorDetails.set(key, serverError);
|
|
611
|
-
}
|
|
612
|
-
this.errorCounts.set(key, (this.errorCounts.get(key) || 0) + 1);
|
|
613
|
-
this.captureSentryEventId(key);
|
|
614
|
-
}
|
|
615
|
-
getAndResetServerErrors() {
|
|
616
|
-
const data = [];
|
|
617
|
-
this.errorCounts.forEach((count, key) => {
|
|
618
|
-
const serverError = this.errorDetails.get(key);
|
|
619
|
-
if (serverError) {
|
|
620
|
-
data.push({
|
|
621
|
-
consumer: serverError.consumer || null,
|
|
622
|
-
method: serverError.method,
|
|
623
|
-
path: serverError.path,
|
|
624
|
-
type: serverError.type,
|
|
625
|
-
msg: this.getTruncatedMessage(serverError.msg),
|
|
626
|
-
traceback: this.getTruncatedStack(serverError.traceback),
|
|
627
|
-
sentry_event_id: this.sentryEventIds.get(key) || null,
|
|
628
|
-
error_count: count
|
|
629
|
-
});
|
|
630
|
-
}
|
|
631
|
-
});
|
|
632
|
-
this.errorCounts.clear();
|
|
633
|
-
this.errorDetails.clear();
|
|
634
|
-
return data;
|
|
635
|
-
}
|
|
636
|
-
getKey(serverError) {
|
|
637
|
-
const hashInput = [
|
|
638
|
-
serverError.consumer || "",
|
|
639
|
-
serverError.method.toUpperCase(),
|
|
640
|
-
serverError.path,
|
|
641
|
-
serverError.type,
|
|
642
|
-
serverError.msg.trim(),
|
|
643
|
-
serverError.traceback.trim()
|
|
644
|
-
].join("|");
|
|
645
|
-
return (0, import_crypto3.createHash)("md5").update(hashInput).digest("hex");
|
|
646
|
-
}
|
|
647
|
-
getTruncatedMessage(msg) {
|
|
648
|
-
msg = msg.trim();
|
|
649
|
-
if (msg.length <= MAX_MSG_LENGTH) {
|
|
650
|
-
return msg;
|
|
651
|
-
}
|
|
652
|
-
const suffix = "... (truncated)";
|
|
653
|
-
const cutoff = MAX_MSG_LENGTH - suffix.length;
|
|
654
|
-
return msg.substring(0, cutoff) + suffix;
|
|
655
|
-
}
|
|
656
|
-
getTruncatedStack(stack) {
|
|
657
|
-
const suffix = "... (truncated) ...";
|
|
658
|
-
const cutoff = MAX_STACKTRACE_LENGTH - suffix.length;
|
|
659
|
-
const lines = stack.trim().split("\n");
|
|
660
|
-
const truncatedLines = [];
|
|
661
|
-
let length = 0;
|
|
662
|
-
for (const line of lines) {
|
|
663
|
-
if (length + line.length + 1 > cutoff) {
|
|
664
|
-
truncatedLines.push(suffix);
|
|
665
|
-
break;
|
|
666
|
-
}
|
|
667
|
-
truncatedLines.push(line);
|
|
668
|
-
length += line.length + 1;
|
|
669
|
-
}
|
|
670
|
-
return truncatedLines.join("\n");
|
|
671
|
-
}
|
|
672
|
-
captureSentryEventId(serverErrorKey) {
|
|
673
|
-
if (this.sentry && this.sentry.lastEventId) {
|
|
674
|
-
const eventId = this.sentry.lastEventId();
|
|
675
|
-
if (eventId) {
|
|
676
|
-
this.sentryEventIds.set(serverErrorKey, eventId);
|
|
677
|
-
}
|
|
678
|
-
}
|
|
679
|
-
}
|
|
680
|
-
async tryImportSentry() {
|
|
681
|
-
try {
|
|
682
|
-
this.sentry = await import("@sentry/node");
|
|
683
|
-
} catch (e) {
|
|
684
|
-
}
|
|
685
|
-
}
|
|
686
|
-
};
|
|
687
|
-
__name(_ServerErrorCounter, "ServerErrorCounter");
|
|
688
|
-
var ServerErrorCounter = _ServerErrorCounter;
|
|
689
|
-
|
|
690
701
|
// src/common/validationErrorCounter.ts
|
|
691
702
|
var import_crypto4 = require("crypto");
|
|
692
703
|
var _ValidationErrorCounter = class _ValidationErrorCounter {
|
|
@@ -772,7 +783,7 @@ var _ApitallyClient = class _ApitallyClient {
|
|
|
772
783
|
throw new Error("Apitally client is already initialized");
|
|
773
784
|
}
|
|
774
785
|
if (!isValidClientId(clientId)) {
|
|
775
|
-
throw new Error(`Invalid client ID '${clientId}' (expecting
|
|
786
|
+
throw new Error(`Invalid Apitally client ID '${clientId}' (expecting hexadecimal UUID format)`);
|
|
776
787
|
}
|
|
777
788
|
if (!isValidEnv(env)) {
|
|
778
789
|
throw new Error(`Invalid env '${env}' (expecting 1-32 alphanumeric lowercase characters and hyphens only)`);
|
|
@@ -1028,6 +1039,25 @@ function getPackageVersion(name) {
|
|
|
1028
1039
|
}
|
|
1029
1040
|
__name(getPackageVersion, "getPackageVersion");
|
|
1030
1041
|
|
|
1042
|
+
// src/common/utils.ts
|
|
1043
|
+
function parseContentLength(contentLength) {
|
|
1044
|
+
if (contentLength === void 0 || contentLength === null) {
|
|
1045
|
+
return void 0;
|
|
1046
|
+
}
|
|
1047
|
+
if (typeof contentLength === "number") {
|
|
1048
|
+
return contentLength;
|
|
1049
|
+
}
|
|
1050
|
+
if (typeof contentLength === "string") {
|
|
1051
|
+
const parsed = parseInt(contentLength);
|
|
1052
|
+
return isNaN(parsed) ? void 0 : parsed;
|
|
1053
|
+
}
|
|
1054
|
+
if (Array.isArray(contentLength)) {
|
|
1055
|
+
return parseContentLength(contentLength[0]);
|
|
1056
|
+
}
|
|
1057
|
+
return void 0;
|
|
1058
|
+
}
|
|
1059
|
+
__name(parseContentLength, "parseContentLength");
|
|
1060
|
+
|
|
1031
1061
|
// src/hono/middleware.ts
|
|
1032
1062
|
var useApitally = /* @__PURE__ */ __name((app, config) => {
|
|
1033
1063
|
const client = new ApitallyClient(config);
|
|
@@ -1048,7 +1078,7 @@ var getMiddleware = /* @__PURE__ */ __name((client) => {
|
|
|
1048
1078
|
let response;
|
|
1049
1079
|
const responseTime = import_perf_hooks.performance.now() - startTime;
|
|
1050
1080
|
const [responseSize, newResponse] = await measureResponseSize(c.res);
|
|
1051
|
-
const requestSize = c.req.header("
|
|
1081
|
+
const requestSize = parseContentLength(c.req.header("content-length"));
|
|
1052
1082
|
const consumer = getConsumer(c);
|
|
1053
1083
|
client.consumerRegistry.addOrUpdateConsumer(consumer);
|
|
1054
1084
|
client.requestCounter.addRequest({
|
|
@@ -1111,7 +1141,7 @@ var getMiddleware = /* @__PURE__ */ __name((client) => {
|
|
|
1111
1141
|
headers: convertHeaders(c.res.headers),
|
|
1112
1142
|
size: responseSize,
|
|
1113
1143
|
body: responseBody
|
|
1114
|
-
});
|
|
1144
|
+
}, c.error);
|
|
1115
1145
|
}
|
|
1116
1146
|
c.res = response;
|
|
1117
1147
|
};
|