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/koa/middleware.js
CHANGED
|
@@ -187,6 +187,108 @@ import { unlinkSync as unlinkSync2, writeFileSync } from "fs";
|
|
|
187
187
|
import { tmpdir as tmpdir2 } from "os";
|
|
188
188
|
import { join as join2 } from "path";
|
|
189
189
|
|
|
190
|
+
// src/common/sentry.ts
|
|
191
|
+
var sentry;
|
|
192
|
+
(async () => {
|
|
193
|
+
try {
|
|
194
|
+
sentry = await import("@sentry/node");
|
|
195
|
+
} catch (e) {
|
|
196
|
+
}
|
|
197
|
+
})();
|
|
198
|
+
function getSentryEventId() {
|
|
199
|
+
if (sentry && sentry.lastEventId) {
|
|
200
|
+
return sentry.lastEventId();
|
|
201
|
+
}
|
|
202
|
+
return void 0;
|
|
203
|
+
}
|
|
204
|
+
__name(getSentryEventId, "getSentryEventId");
|
|
205
|
+
|
|
206
|
+
// src/common/serverErrorCounter.ts
|
|
207
|
+
import { createHash } from "crypto";
|
|
208
|
+
var MAX_MSG_LENGTH = 2048;
|
|
209
|
+
var MAX_STACKTRACE_LENGTH = 65536;
|
|
210
|
+
var _ServerErrorCounter = class _ServerErrorCounter {
|
|
211
|
+
errorCounts;
|
|
212
|
+
errorDetails;
|
|
213
|
+
sentryEventIds;
|
|
214
|
+
constructor() {
|
|
215
|
+
this.errorCounts = /* @__PURE__ */ new Map();
|
|
216
|
+
this.errorDetails = /* @__PURE__ */ new Map();
|
|
217
|
+
this.sentryEventIds = /* @__PURE__ */ new Map();
|
|
218
|
+
}
|
|
219
|
+
addServerError(serverError) {
|
|
220
|
+
const key = this.getKey(serverError);
|
|
221
|
+
if (!this.errorDetails.has(key)) {
|
|
222
|
+
this.errorDetails.set(key, serverError);
|
|
223
|
+
}
|
|
224
|
+
this.errorCounts.set(key, (this.errorCounts.get(key) || 0) + 1);
|
|
225
|
+
const sentryEventId = getSentryEventId();
|
|
226
|
+
if (sentryEventId) {
|
|
227
|
+
this.sentryEventIds.set(key, sentryEventId);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
getAndResetServerErrors() {
|
|
231
|
+
const data = [];
|
|
232
|
+
this.errorCounts.forEach((count, key) => {
|
|
233
|
+
const serverError = this.errorDetails.get(key);
|
|
234
|
+
if (serverError) {
|
|
235
|
+
data.push({
|
|
236
|
+
consumer: serverError.consumer || null,
|
|
237
|
+
method: serverError.method,
|
|
238
|
+
path: serverError.path,
|
|
239
|
+
type: serverError.type,
|
|
240
|
+
msg: truncateExceptionMessage(serverError.msg),
|
|
241
|
+
traceback: truncateExceptionStackTrace(serverError.traceback),
|
|
242
|
+
sentry_event_id: this.sentryEventIds.get(key) || null,
|
|
243
|
+
error_count: count
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
});
|
|
247
|
+
this.errorCounts.clear();
|
|
248
|
+
this.errorDetails.clear();
|
|
249
|
+
return data;
|
|
250
|
+
}
|
|
251
|
+
getKey(serverError) {
|
|
252
|
+
const hashInput = [
|
|
253
|
+
serverError.consumer || "",
|
|
254
|
+
serverError.method.toUpperCase(),
|
|
255
|
+
serverError.path,
|
|
256
|
+
serverError.type,
|
|
257
|
+
serverError.msg.trim(),
|
|
258
|
+
serverError.traceback.trim()
|
|
259
|
+
].join("|");
|
|
260
|
+
return createHash("md5").update(hashInput).digest("hex");
|
|
261
|
+
}
|
|
262
|
+
};
|
|
263
|
+
__name(_ServerErrorCounter, "ServerErrorCounter");
|
|
264
|
+
var ServerErrorCounter = _ServerErrorCounter;
|
|
265
|
+
function truncateExceptionMessage(msg) {
|
|
266
|
+
if (msg.length <= MAX_MSG_LENGTH) {
|
|
267
|
+
return msg;
|
|
268
|
+
}
|
|
269
|
+
const suffix = "... (truncated)";
|
|
270
|
+
const cutoff = MAX_MSG_LENGTH - suffix.length;
|
|
271
|
+
return msg.substring(0, cutoff) + suffix;
|
|
272
|
+
}
|
|
273
|
+
__name(truncateExceptionMessage, "truncateExceptionMessage");
|
|
274
|
+
function truncateExceptionStackTrace(stack) {
|
|
275
|
+
const suffix = "... (truncated) ...";
|
|
276
|
+
const cutoff = MAX_STACKTRACE_LENGTH - suffix.length;
|
|
277
|
+
const lines = stack.trim().split("\n");
|
|
278
|
+
const truncatedLines = [];
|
|
279
|
+
let length = 0;
|
|
280
|
+
for (const line of lines) {
|
|
281
|
+
if (length + line.length + 1 > cutoff) {
|
|
282
|
+
truncatedLines.push(suffix);
|
|
283
|
+
break;
|
|
284
|
+
}
|
|
285
|
+
truncatedLines.push(line);
|
|
286
|
+
length += line.length + 1;
|
|
287
|
+
}
|
|
288
|
+
return truncatedLines.join("\n");
|
|
289
|
+
}
|
|
290
|
+
__name(truncateExceptionStackTrace, "truncateExceptionStackTrace");
|
|
291
|
+
|
|
190
292
|
// src/common/tempGzipFile.ts
|
|
191
293
|
import { Buffer as Buffer2 } from "buffer";
|
|
192
294
|
import { randomUUID } from "crypto";
|
|
@@ -309,6 +411,7 @@ var DEFAULT_CONFIG = {
|
|
|
309
411
|
logRequestBody: false,
|
|
310
412
|
logResponseHeaders: true,
|
|
311
413
|
logResponseBody: false,
|
|
414
|
+
logException: true,
|
|
312
415
|
maskQueryParams: [],
|
|
313
416
|
maskHeaders: [],
|
|
314
417
|
excludePaths: []
|
|
@@ -381,7 +484,7 @@ var _RequestLogger = class _RequestLogger {
|
|
|
381
484
|
this.shouldMaskHeader(k) ? MASKED : v
|
|
382
485
|
]);
|
|
383
486
|
}
|
|
384
|
-
logRequest(request, response) {
|
|
487
|
+
logRequest(request, response, error) {
|
|
385
488
|
var _a2, _b, _c;
|
|
386
489
|
if (!this.enabled || this.suspendUntil !== null) return;
|
|
387
490
|
const url = new URL(request.url);
|
|
@@ -429,7 +532,13 @@ var _RequestLogger = class _RequestLogger {
|
|
|
429
532
|
const item = {
|
|
430
533
|
uuid: randomUUID2(),
|
|
431
534
|
request: skipEmptyValues(request),
|
|
432
|
-
response: skipEmptyValues(response)
|
|
535
|
+
response: skipEmptyValues(response),
|
|
536
|
+
exception: error && this.config.logException ? {
|
|
537
|
+
type: error.name,
|
|
538
|
+
message: truncateExceptionMessage(error.message),
|
|
539
|
+
stacktrace: truncateExceptionStackTrace(error.stack || ""),
|
|
540
|
+
sentryEventId: getSentryEventId()
|
|
541
|
+
} : null
|
|
433
542
|
};
|
|
434
543
|
[
|
|
435
544
|
item.request.body,
|
|
@@ -591,104 +700,6 @@ function checkWritableFs() {
|
|
|
591
700
|
}
|
|
592
701
|
__name(checkWritableFs, "checkWritableFs");
|
|
593
702
|
|
|
594
|
-
// src/common/serverErrorCounter.ts
|
|
595
|
-
import { createHash } from "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 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
|
import { createHash as createHash2 } from "crypto";
|
|
694
705
|
var _ValidationErrorCounter = class _ValidationErrorCounter {
|
|
@@ -774,7 +785,7 @@ var _ApitallyClient = class _ApitallyClient {
|
|
|
774
785
|
throw new Error("Apitally client is already initialized");
|
|
775
786
|
}
|
|
776
787
|
if (!isValidClientId(clientId)) {
|
|
777
|
-
throw new Error(`Invalid client ID '${clientId}' (expecting
|
|
788
|
+
throw new Error(`Invalid Apitally client ID '${clientId}' (expecting hexadecimal UUID format)`);
|
|
778
789
|
}
|
|
779
790
|
if (!isValidEnv(env)) {
|
|
780
791
|
throw new Error(`Invalid env '${env}' (expecting 1-32 alphanumeric lowercase characters and hyphens only)`);
|
|
@@ -1047,6 +1058,7 @@ var getMiddleware = /* @__PURE__ */ __name((client) => {
|
|
|
1047
1058
|
}
|
|
1048
1059
|
let path;
|
|
1049
1060
|
let statusCode;
|
|
1061
|
+
let serverError;
|
|
1050
1062
|
const startTime = performance.now();
|
|
1051
1063
|
try {
|
|
1052
1064
|
await next();
|
|
@@ -1054,6 +1066,7 @@ var getMiddleware = /* @__PURE__ */ __name((client) => {
|
|
|
1054
1066
|
path = getPath(ctx);
|
|
1055
1067
|
statusCode = error.statusCode || error.status || 500;
|
|
1056
1068
|
if (path && statusCode === 500 && error instanceof Error) {
|
|
1069
|
+
serverError = error;
|
|
1057
1070
|
client.serverErrorCounter.addServerError({
|
|
1058
1071
|
consumer: (_a2 = getConsumer(ctx)) == null ? void 0 : _a2.identifier,
|
|
1059
1072
|
method: ctx.request.method,
|
|
@@ -1096,16 +1109,16 @@ var getMiddleware = /* @__PURE__ */ __name((client) => {
|
|
|
1096
1109
|
path,
|
|
1097
1110
|
url: ctx.request.href,
|
|
1098
1111
|
headers: convertHeaders(ctx.request.headers),
|
|
1099
|
-
size:
|
|
1112
|
+
size: ctx.request.length,
|
|
1100
1113
|
consumer: consumer == null ? void 0 : consumer.identifier,
|
|
1101
1114
|
body: convertBody(ctx.request.body, ctx.request.get("content-type"))
|
|
1102
1115
|
}, {
|
|
1103
1116
|
statusCode: statusCode || ctx.response.status,
|
|
1104
1117
|
responseTime: responseTime / 1e3,
|
|
1105
1118
|
headers: convertHeaders(ctx.response.headers),
|
|
1106
|
-
size:
|
|
1119
|
+
size: ctx.response.length,
|
|
1107
1120
|
body: convertBody(ctx.response.body, ctx.response.get("content-type"))
|
|
1108
|
-
});
|
|
1121
|
+
}, serverError);
|
|
1109
1122
|
}
|
|
1110
1123
|
}
|
|
1111
1124
|
};
|