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.
Files changed (101) hide show
  1. package/README.md +43 -2
  2. package/dist/adonisjs/index.cjs +41 -0
  3. package/dist/adonisjs/index.cjs.map +1 -0
  4. package/dist/adonisjs/index.d.cts +14 -0
  5. package/dist/adonisjs/index.d.ts +14 -0
  6. package/dist/adonisjs/index.js +17 -0
  7. package/dist/adonisjs/index.js.map +1 -0
  8. package/dist/adonisjs/middleware.cjs +214 -0
  9. package/dist/adonisjs/middleware.cjs.map +1 -0
  10. package/dist/adonisjs/middleware.d.cts +21 -0
  11. package/dist/adonisjs/middleware.d.ts +21 -0
  12. package/dist/adonisjs/middleware.js +185 -0
  13. package/dist/adonisjs/middleware.js.map +1 -0
  14. package/dist/adonisjs/provider.cjs +1083 -0
  15. package/dist/adonisjs/provider.cjs.map +1 -0
  16. package/dist/adonisjs/provider.d.cts +28 -0
  17. package/dist/adonisjs/provider.d.ts +28 -0
  18. package/dist/adonisjs/provider.js +1057 -0
  19. package/dist/adonisjs/provider.js.map +1 -0
  20. package/dist/common/client.cjs +117 -106
  21. package/dist/common/client.cjs.map +1 -1
  22. package/dist/common/client.js +112 -101
  23. package/dist/common/client.js.map +1 -1
  24. package/dist/common/consumerRegistry.cjs.map +1 -1
  25. package/dist/common/consumerRegistry.js.map +1 -1
  26. package/dist/common/logging.cjs.map +1 -1
  27. package/dist/common/logging.js.map +1 -1
  28. package/dist/common/packageVersions.cjs.map +1 -1
  29. package/dist/common/packageVersions.js.map +1 -1
  30. package/dist/common/paramValidation.cjs.map +1 -1
  31. package/dist/common/paramValidation.js.map +1 -1
  32. package/dist/common/requestCounter.cjs.map +1 -1
  33. package/dist/common/requestCounter.js.map +1 -1
  34. package/dist/common/requestLogger.cjs +55 -2
  35. package/dist/common/requestLogger.cjs.map +1 -1
  36. package/dist/common/requestLogger.d.cts +2 -1
  37. package/dist/common/requestLogger.d.ts +2 -1
  38. package/dist/common/requestLogger.js +55 -2
  39. package/dist/common/requestLogger.js.map +1 -1
  40. package/dist/common/sentry.cjs +55 -0
  41. package/dist/common/sentry.cjs.map +1 -0
  42. package/dist/common/sentry.d.cts +6 -0
  43. package/dist/common/sentry.d.ts +6 -0
  44. package/dist/common/sentry.js +22 -0
  45. package/dist/common/sentry.js.map +1 -0
  46. package/dist/common/serverErrorCounter.cjs +58 -45
  47. package/dist/common/serverErrorCounter.cjs.map +1 -1
  48. package/dist/common/serverErrorCounter.d.cts +3 -6
  49. package/dist/common/serverErrorCounter.d.ts +3 -6
  50. package/dist/common/serverErrorCounter.js +53 -45
  51. package/dist/common/serverErrorCounter.js.map +1 -1
  52. package/dist/common/tempGzipFile.cjs.map +1 -1
  53. package/dist/common/tempGzipFile.js.map +1 -1
  54. package/dist/common/types.cjs.map +1 -1
  55. package/dist/common/utils.cjs +48 -0
  56. package/dist/common/utils.cjs.map +1 -0
  57. package/dist/common/utils.d.cts +5 -0
  58. package/dist/common/utils.d.ts +5 -0
  59. package/dist/common/utils.js +25 -0
  60. package/dist/common/utils.js.map +1 -0
  61. package/dist/common/validationErrorCounter.cjs.map +1 -1
  62. package/dist/common/validationErrorCounter.js.map +1 -1
  63. package/dist/express/index.cjs +143 -111
  64. package/dist/express/index.cjs.map +1 -1
  65. package/dist/express/index.js +138 -106
  66. package/dist/express/index.js.map +1 -1
  67. package/dist/express/middleware.cjs +143 -111
  68. package/dist/express/middleware.cjs.map +1 -1
  69. package/dist/express/middleware.js +138 -106
  70. package/dist/express/middleware.js.map +1 -1
  71. package/dist/express/utils.cjs.map +1 -1
  72. package/dist/express/utils.js.map +1 -1
  73. package/dist/fastify/index.cjs +139 -112
  74. package/dist/fastify/index.cjs.map +1 -1
  75. package/dist/fastify/index.js +134 -107
  76. package/dist/fastify/index.js.map +1 -1
  77. package/dist/fastify/plugin.cjs +139 -112
  78. package/dist/fastify/plugin.cjs.map +1 -1
  79. package/dist/fastify/plugin.js +134 -107
  80. package/dist/fastify/plugin.js.map +1 -1
  81. package/dist/hono/index.cjs +138 -108
  82. package/dist/hono/index.cjs.map +1 -1
  83. package/dist/hono/index.js +133 -103
  84. package/dist/hono/index.js.map +1 -1
  85. package/dist/hono/middleware.cjs +138 -108
  86. package/dist/hono/middleware.cjs.map +1 -1
  87. package/dist/hono/middleware.js +133 -103
  88. package/dist/hono/middleware.js.map +1 -1
  89. package/dist/koa/index.cjs +122 -109
  90. package/dist/koa/index.cjs.map +1 -1
  91. package/dist/koa/index.js +117 -104
  92. package/dist/koa/index.js.map +1 -1
  93. package/dist/koa/middleware.cjs +122 -109
  94. package/dist/koa/middleware.cjs.map +1 -1
  95. package/dist/koa/middleware.js +117 -104
  96. package/dist/koa/middleware.js.map +1 -1
  97. package/dist/nestjs/index.cjs +143 -111
  98. package/dist/nestjs/index.cjs.map +1 -1
  99. package/dist/nestjs/index.js +138 -106
  100. package/dist/nestjs/index.js.map +1 -1
  101. package/package.json +46 -1
@@ -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 hexadeciaml UUID format)`);
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: Number(ctx.request.headers["content-length"]),
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: Number(ctx.response.headers["content-length"]),
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
  };