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/nestjs/index.js
CHANGED
|
@@ -194,6 +194,108 @@ import { unlinkSync as unlinkSync2, writeFileSync } from "fs";
|
|
|
194
194
|
import { tmpdir as tmpdir2 } from "os";
|
|
195
195
|
import { join as join2 } from "path";
|
|
196
196
|
|
|
197
|
+
// src/common/sentry.ts
|
|
198
|
+
var sentry;
|
|
199
|
+
(async () => {
|
|
200
|
+
try {
|
|
201
|
+
sentry = await import("@sentry/node");
|
|
202
|
+
} catch (e) {
|
|
203
|
+
}
|
|
204
|
+
})();
|
|
205
|
+
function getSentryEventId() {
|
|
206
|
+
if (sentry && sentry.lastEventId) {
|
|
207
|
+
return sentry.lastEventId();
|
|
208
|
+
}
|
|
209
|
+
return void 0;
|
|
210
|
+
}
|
|
211
|
+
__name(getSentryEventId, "getSentryEventId");
|
|
212
|
+
|
|
213
|
+
// src/common/serverErrorCounter.ts
|
|
214
|
+
import { createHash } from "crypto";
|
|
215
|
+
var MAX_MSG_LENGTH = 2048;
|
|
216
|
+
var MAX_STACKTRACE_LENGTH = 65536;
|
|
217
|
+
var _ServerErrorCounter = class _ServerErrorCounter {
|
|
218
|
+
errorCounts;
|
|
219
|
+
errorDetails;
|
|
220
|
+
sentryEventIds;
|
|
221
|
+
constructor() {
|
|
222
|
+
this.errorCounts = /* @__PURE__ */ new Map();
|
|
223
|
+
this.errorDetails = /* @__PURE__ */ new Map();
|
|
224
|
+
this.sentryEventIds = /* @__PURE__ */ new Map();
|
|
225
|
+
}
|
|
226
|
+
addServerError(serverError) {
|
|
227
|
+
const key = this.getKey(serverError);
|
|
228
|
+
if (!this.errorDetails.has(key)) {
|
|
229
|
+
this.errorDetails.set(key, serverError);
|
|
230
|
+
}
|
|
231
|
+
this.errorCounts.set(key, (this.errorCounts.get(key) || 0) + 1);
|
|
232
|
+
const sentryEventId = getSentryEventId();
|
|
233
|
+
if (sentryEventId) {
|
|
234
|
+
this.sentryEventIds.set(key, sentryEventId);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
getAndResetServerErrors() {
|
|
238
|
+
const data = [];
|
|
239
|
+
this.errorCounts.forEach((count, key) => {
|
|
240
|
+
const serverError = this.errorDetails.get(key);
|
|
241
|
+
if (serverError) {
|
|
242
|
+
data.push({
|
|
243
|
+
consumer: serverError.consumer || null,
|
|
244
|
+
method: serverError.method,
|
|
245
|
+
path: serverError.path,
|
|
246
|
+
type: serverError.type,
|
|
247
|
+
msg: truncateExceptionMessage(serverError.msg),
|
|
248
|
+
traceback: truncateExceptionStackTrace(serverError.traceback),
|
|
249
|
+
sentry_event_id: this.sentryEventIds.get(key) || null,
|
|
250
|
+
error_count: count
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
});
|
|
254
|
+
this.errorCounts.clear();
|
|
255
|
+
this.errorDetails.clear();
|
|
256
|
+
return data;
|
|
257
|
+
}
|
|
258
|
+
getKey(serverError) {
|
|
259
|
+
const hashInput = [
|
|
260
|
+
serverError.consumer || "",
|
|
261
|
+
serverError.method.toUpperCase(),
|
|
262
|
+
serverError.path,
|
|
263
|
+
serverError.type,
|
|
264
|
+
serverError.msg.trim(),
|
|
265
|
+
serverError.traceback.trim()
|
|
266
|
+
].join("|");
|
|
267
|
+
return createHash("md5").update(hashInput).digest("hex");
|
|
268
|
+
}
|
|
269
|
+
};
|
|
270
|
+
__name(_ServerErrorCounter, "ServerErrorCounter");
|
|
271
|
+
var ServerErrorCounter = _ServerErrorCounter;
|
|
272
|
+
function truncateExceptionMessage(msg) {
|
|
273
|
+
if (msg.length <= MAX_MSG_LENGTH) {
|
|
274
|
+
return msg;
|
|
275
|
+
}
|
|
276
|
+
const suffix = "... (truncated)";
|
|
277
|
+
const cutoff = MAX_MSG_LENGTH - suffix.length;
|
|
278
|
+
return msg.substring(0, cutoff) + suffix;
|
|
279
|
+
}
|
|
280
|
+
__name(truncateExceptionMessage, "truncateExceptionMessage");
|
|
281
|
+
function truncateExceptionStackTrace(stack) {
|
|
282
|
+
const suffix = "... (truncated) ...";
|
|
283
|
+
const cutoff = MAX_STACKTRACE_LENGTH - suffix.length;
|
|
284
|
+
const lines = stack.trim().split("\n");
|
|
285
|
+
const truncatedLines = [];
|
|
286
|
+
let length = 0;
|
|
287
|
+
for (const line of lines) {
|
|
288
|
+
if (length + line.length + 1 > cutoff) {
|
|
289
|
+
truncatedLines.push(suffix);
|
|
290
|
+
break;
|
|
291
|
+
}
|
|
292
|
+
truncatedLines.push(line);
|
|
293
|
+
length += line.length + 1;
|
|
294
|
+
}
|
|
295
|
+
return truncatedLines.join("\n");
|
|
296
|
+
}
|
|
297
|
+
__name(truncateExceptionStackTrace, "truncateExceptionStackTrace");
|
|
298
|
+
|
|
197
299
|
// src/common/tempGzipFile.ts
|
|
198
300
|
import { Buffer as Buffer2 } from "buffer";
|
|
199
301
|
import { randomUUID } from "crypto";
|
|
@@ -316,6 +418,7 @@ var DEFAULT_CONFIG = {
|
|
|
316
418
|
logRequestBody: false,
|
|
317
419
|
logResponseHeaders: true,
|
|
318
420
|
logResponseBody: false,
|
|
421
|
+
logException: true,
|
|
319
422
|
maskQueryParams: [],
|
|
320
423
|
maskHeaders: [],
|
|
321
424
|
excludePaths: []
|
|
@@ -388,7 +491,7 @@ var _RequestLogger = class _RequestLogger {
|
|
|
388
491
|
this.shouldMaskHeader(k) ? MASKED : v
|
|
389
492
|
]);
|
|
390
493
|
}
|
|
391
|
-
logRequest(request, response) {
|
|
494
|
+
logRequest(request, response, error) {
|
|
392
495
|
var _a3, _b, _c;
|
|
393
496
|
if (!this.enabled || this.suspendUntil !== null) return;
|
|
394
497
|
const url = new URL(request.url);
|
|
@@ -436,7 +539,13 @@ var _RequestLogger = class _RequestLogger {
|
|
|
436
539
|
const item = {
|
|
437
540
|
uuid: randomUUID2(),
|
|
438
541
|
request: skipEmptyValues(request),
|
|
439
|
-
response: skipEmptyValues(response)
|
|
542
|
+
response: skipEmptyValues(response),
|
|
543
|
+
exception: error && this.config.logException ? {
|
|
544
|
+
type: error.name,
|
|
545
|
+
message: truncateExceptionMessage(error.message),
|
|
546
|
+
stacktrace: truncateExceptionStackTrace(error.stack || ""),
|
|
547
|
+
sentryEventId: getSentryEventId()
|
|
548
|
+
} : null
|
|
440
549
|
};
|
|
441
550
|
[
|
|
442
551
|
item.request.body,
|
|
@@ -598,104 +707,6 @@ function checkWritableFs() {
|
|
|
598
707
|
}
|
|
599
708
|
__name(checkWritableFs, "checkWritableFs");
|
|
600
709
|
|
|
601
|
-
// src/common/serverErrorCounter.ts
|
|
602
|
-
import { createHash } from "crypto";
|
|
603
|
-
var MAX_MSG_LENGTH = 2048;
|
|
604
|
-
var MAX_STACKTRACE_LENGTH = 65536;
|
|
605
|
-
var _ServerErrorCounter = class _ServerErrorCounter {
|
|
606
|
-
errorCounts;
|
|
607
|
-
errorDetails;
|
|
608
|
-
sentryEventIds;
|
|
609
|
-
sentry;
|
|
610
|
-
constructor() {
|
|
611
|
-
this.errorCounts = /* @__PURE__ */ new Map();
|
|
612
|
-
this.errorDetails = /* @__PURE__ */ new Map();
|
|
613
|
-
this.sentryEventIds = /* @__PURE__ */ new Map();
|
|
614
|
-
this.tryImportSentry();
|
|
615
|
-
}
|
|
616
|
-
addServerError(serverError) {
|
|
617
|
-
const key = this.getKey(serverError);
|
|
618
|
-
if (!this.errorDetails.has(key)) {
|
|
619
|
-
this.errorDetails.set(key, serverError);
|
|
620
|
-
}
|
|
621
|
-
this.errorCounts.set(key, (this.errorCounts.get(key) || 0) + 1);
|
|
622
|
-
this.captureSentryEventId(key);
|
|
623
|
-
}
|
|
624
|
-
getAndResetServerErrors() {
|
|
625
|
-
const data = [];
|
|
626
|
-
this.errorCounts.forEach((count, key) => {
|
|
627
|
-
const serverError = this.errorDetails.get(key);
|
|
628
|
-
if (serverError) {
|
|
629
|
-
data.push({
|
|
630
|
-
consumer: serverError.consumer || null,
|
|
631
|
-
method: serverError.method,
|
|
632
|
-
path: serverError.path,
|
|
633
|
-
type: serverError.type,
|
|
634
|
-
msg: this.getTruncatedMessage(serverError.msg),
|
|
635
|
-
traceback: this.getTruncatedStack(serverError.traceback),
|
|
636
|
-
sentry_event_id: this.sentryEventIds.get(key) || null,
|
|
637
|
-
error_count: count
|
|
638
|
-
});
|
|
639
|
-
}
|
|
640
|
-
});
|
|
641
|
-
this.errorCounts.clear();
|
|
642
|
-
this.errorDetails.clear();
|
|
643
|
-
return data;
|
|
644
|
-
}
|
|
645
|
-
getKey(serverError) {
|
|
646
|
-
const hashInput = [
|
|
647
|
-
serverError.consumer || "",
|
|
648
|
-
serverError.method.toUpperCase(),
|
|
649
|
-
serverError.path,
|
|
650
|
-
serverError.type,
|
|
651
|
-
serverError.msg.trim(),
|
|
652
|
-
serverError.traceback.trim()
|
|
653
|
-
].join("|");
|
|
654
|
-
return createHash("md5").update(hashInput).digest("hex");
|
|
655
|
-
}
|
|
656
|
-
getTruncatedMessage(msg) {
|
|
657
|
-
msg = msg.trim();
|
|
658
|
-
if (msg.length <= MAX_MSG_LENGTH) {
|
|
659
|
-
return msg;
|
|
660
|
-
}
|
|
661
|
-
const suffix = "... (truncated)";
|
|
662
|
-
const cutoff = MAX_MSG_LENGTH - suffix.length;
|
|
663
|
-
return msg.substring(0, cutoff) + suffix;
|
|
664
|
-
}
|
|
665
|
-
getTruncatedStack(stack) {
|
|
666
|
-
const suffix = "... (truncated) ...";
|
|
667
|
-
const cutoff = MAX_STACKTRACE_LENGTH - suffix.length;
|
|
668
|
-
const lines = stack.trim().split("\n");
|
|
669
|
-
const truncatedLines = [];
|
|
670
|
-
let length = 0;
|
|
671
|
-
for (const line of lines) {
|
|
672
|
-
if (length + line.length + 1 > cutoff) {
|
|
673
|
-
truncatedLines.push(suffix);
|
|
674
|
-
break;
|
|
675
|
-
}
|
|
676
|
-
truncatedLines.push(line);
|
|
677
|
-
length += line.length + 1;
|
|
678
|
-
}
|
|
679
|
-
return truncatedLines.join("\n");
|
|
680
|
-
}
|
|
681
|
-
captureSentryEventId(serverErrorKey) {
|
|
682
|
-
if (this.sentry && this.sentry.lastEventId) {
|
|
683
|
-
const eventId = this.sentry.lastEventId();
|
|
684
|
-
if (eventId) {
|
|
685
|
-
this.sentryEventIds.set(serverErrorKey, eventId);
|
|
686
|
-
}
|
|
687
|
-
}
|
|
688
|
-
}
|
|
689
|
-
async tryImportSentry() {
|
|
690
|
-
try {
|
|
691
|
-
this.sentry = await import("@sentry/node");
|
|
692
|
-
} catch (e) {
|
|
693
|
-
}
|
|
694
|
-
}
|
|
695
|
-
};
|
|
696
|
-
__name(_ServerErrorCounter, "ServerErrorCounter");
|
|
697
|
-
var ServerErrorCounter = _ServerErrorCounter;
|
|
698
|
-
|
|
699
710
|
// src/common/validationErrorCounter.ts
|
|
700
711
|
import { createHash as createHash2 } from "crypto";
|
|
701
712
|
var _ValidationErrorCounter = class _ValidationErrorCounter {
|
|
@@ -781,7 +792,7 @@ var _ApitallyClient = class _ApitallyClient {
|
|
|
781
792
|
throw new Error("Apitally client is already initialized");
|
|
782
793
|
}
|
|
783
794
|
if (!isValidClientId(clientId)) {
|
|
784
|
-
throw new Error(`Invalid client ID '${clientId}' (expecting
|
|
795
|
+
throw new Error(`Invalid Apitally client ID '${clientId}' (expecting hexadecimal UUID format)`);
|
|
785
796
|
}
|
|
786
797
|
if (!isValidEnv(env)) {
|
|
787
798
|
throw new Error(`Invalid env '${env}' (expecting 1-32 alphanumeric lowercase characters and hyphens only)`);
|
|
@@ -1036,6 +1047,25 @@ function getPackageVersion(name) {
|
|
|
1036
1047
|
}
|
|
1037
1048
|
__name(getPackageVersion, "getPackageVersion");
|
|
1038
1049
|
|
|
1050
|
+
// src/common/utils.ts
|
|
1051
|
+
function parseContentLength(contentLength) {
|
|
1052
|
+
if (contentLength === void 0 || contentLength === null) {
|
|
1053
|
+
return void 0;
|
|
1054
|
+
}
|
|
1055
|
+
if (typeof contentLength === "number") {
|
|
1056
|
+
return contentLength;
|
|
1057
|
+
}
|
|
1058
|
+
if (typeof contentLength === "string") {
|
|
1059
|
+
const parsed = parseInt(contentLength);
|
|
1060
|
+
return isNaN(parsed) ? void 0 : parsed;
|
|
1061
|
+
}
|
|
1062
|
+
if (Array.isArray(contentLength)) {
|
|
1063
|
+
return parseContentLength(contentLength[0]);
|
|
1064
|
+
}
|
|
1065
|
+
return void 0;
|
|
1066
|
+
}
|
|
1067
|
+
__name(parseContentLength, "parseContentLength");
|
|
1068
|
+
|
|
1039
1069
|
// src/express/utils.js
|
|
1040
1070
|
var regExpToParseExpressPathRegExp = /^\/\^\\?\/?(?:(:?[\w\\.-]*(?:\\\/:?[\w\\.-]*)*)|(\(\?:\\?\/?\([^)]+\)\)))\\\/.*/;
|
|
1041
1071
|
var regExpToReplaceExpressPathRegExpParams = /\(\?:\\?\/?\([^)]+\)\)/;
|
|
@@ -1201,6 +1231,8 @@ var getMiddleware = /* @__PURE__ */ __name((app, client) => {
|
|
|
1201
1231
|
const path = getRoutePath(req);
|
|
1202
1232
|
const consumer = getConsumer(req);
|
|
1203
1233
|
client.consumerRegistry.addOrUpdateConsumer(consumer);
|
|
1234
|
+
const requestSize = parseContentLength(req.get("content-length"));
|
|
1235
|
+
const responseSize = parseContentLength(res.get("content-length"));
|
|
1204
1236
|
if (path) {
|
|
1205
1237
|
client.requestCounter.addRequest({
|
|
1206
1238
|
consumer: consumer == null ? void 0 : consumer.identifier,
|
|
@@ -1208,8 +1240,8 @@ var getMiddleware = /* @__PURE__ */ __name((app, client) => {
|
|
|
1208
1240
|
path,
|
|
1209
1241
|
statusCode: res.statusCode,
|
|
1210
1242
|
responseTime,
|
|
1211
|
-
requestSize
|
|
1212
|
-
responseSize
|
|
1243
|
+
requestSize,
|
|
1244
|
+
responseSize
|
|
1213
1245
|
});
|
|
1214
1246
|
if ((res.statusCode === 400 || res.statusCode === 422) && res.locals.body) {
|
|
1215
1247
|
let jsonBody;
|
|
@@ -1257,16 +1289,16 @@ var getMiddleware = /* @__PURE__ */ __name((app, client) => {
|
|
|
1257
1289
|
path,
|
|
1258
1290
|
url: `${req.protocol}://${req.host}${req.originalUrl}`,
|
|
1259
1291
|
headers: convertHeaders(req.headers),
|
|
1260
|
-
size:
|
|
1292
|
+
size: requestSize,
|
|
1261
1293
|
consumer: consumer == null ? void 0 : consumer.identifier,
|
|
1262
1294
|
body: convertBody(req.body, req.get("content-type"))
|
|
1263
1295
|
}, {
|
|
1264
1296
|
statusCode: res.statusCode,
|
|
1265
1297
|
responseTime: responseTime / 1e3,
|
|
1266
1298
|
headers: convertHeaders(res.getHeaders()),
|
|
1267
|
-
size:
|
|
1299
|
+
size: responseSize,
|
|
1268
1300
|
body: convertBody(res.locals.body, res.get("content-type"))
|
|
1269
|
-
});
|
|
1301
|
+
}, res.locals.serverError);
|
|
1270
1302
|
}
|
|
1271
1303
|
} catch (error) {
|
|
1272
1304
|
client.logger.error("Error while logging request in Apitally middleware.", {
|