@djangocfg/monitor 2.1.224 → 2.1.226

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/dist/client.cjs CHANGED
@@ -1144,7 +1144,7 @@ var FrontendEventIngestRequestSchema = import_zod.z.object({
1144
1144
  event_type: import_zod.z.nativeEnum(FrontendEventIngestRequestEventType),
1145
1145
  message: import_zod.z.string().min(1).max(5e3),
1146
1146
  level: import_zod.z.nativeEnum(FrontendEventIngestRequestLevel).optional(),
1147
- stack_trace: import_zod.z.string().max(2e4).optional(),
1147
+ stack_trace: import_zod.z.string().max(1e4).optional(),
1148
1148
  url: import_zod.z.string().max(2e3).optional(),
1149
1149
  fingerprint: import_zod.z.string().max(64).optional(),
1150
1150
  http_status: import_zod.z.number().int().nullable().optional(),
@@ -1155,7 +1155,8 @@ var FrontendEventIngestRequestSchema = import_zod.z.object({
1155
1155
  browser_fingerprint: import_zod.z.string().max(64).optional(),
1156
1156
  extra: import_zod.z.record(import_zod.z.string(), import_zod.z.any()).optional(),
1157
1157
  project_name: import_zod.z.string().max(100).optional(),
1158
- environment: import_zod.z.string().max(20).optional()
1158
+ environment: import_zod.z.string().max(20).optional(),
1159
+ build_id: import_zod.z.string().max(100).optional()
1159
1160
  });
1160
1161
 
1161
1162
  // src/_api/generated/cfg_monitor/_utils/schemas/IngestBatchRequest.schema.ts
@@ -1362,7 +1363,22 @@ var monitorStore = (0, import_vanilla.createStore)((set, get) => ({
1362
1363
  push(event) {
1363
1364
  const { config, buffer } = get();
1364
1365
  const maxSize = config.maxBufferSize ?? 20;
1365
- const next = [...buffer, event];
1366
+ const sanitized = {
1367
+ ...event,
1368
+ // Enforce field size limits before buffering (last-resort backstop)
1369
+ message: event.message && event.message.length > 4997 ? event.message.slice(0, 4997) + "..." : event.message,
1370
+ stack_trace: event.stack_trace && event.stack_trace.length > 1e4 ? event.stack_trace.slice(0, 9997) + "..." : event.stack_trace,
1371
+ // Cap extra payload — drop entirely if serialized size exceeds 32KB
1372
+ extra: (() => {
1373
+ if (!event.extra) return event.extra;
1374
+ try {
1375
+ return JSON.stringify(event.extra).length > 32768 ? {} : event.extra;
1376
+ } catch {
1377
+ return {};
1378
+ }
1379
+ })()
1380
+ };
1381
+ const next = [...buffer, sanitized];
1366
1382
  set({ buffer: next });
1367
1383
  if (next.length >= maxSize || event.level === "error") {
1368
1384
  get().flush();
@@ -1381,15 +1397,48 @@ var monitorStore = (0, import_vanilla.createStore)((set, get) => ({
1381
1397
  }));
1382
1398
 
1383
1399
  // src/client/capture/js-errors.ts
1400
+ var MSG_MAX = 2e3;
1401
+ function truncate(s, max = MSG_MAX) {
1402
+ return s.length > max ? s.slice(0, max - 1) + "\u2026" : s;
1403
+ }
1404
+ __name(truncate, "truncate");
1405
+ var HYDRATION_NOISE = [
1406
+ /hydration failed/i,
1407
+ /there was an error while hydrating/i,
1408
+ /minified react error #418/i,
1409
+ /minified react error #423/i,
1410
+ /minified react error #425/i,
1411
+ /text content does not match server-rendered html/i
1412
+ ];
1413
+ function isHydrationNoise(msg) {
1414
+ return HYDRATION_NOISE.some((p) => p.test(msg));
1415
+ }
1416
+ __name(isHydrationNoise, "isHydrationNoise");
1417
+ var CLIENT_DEDUP_TTL = 5 * 60 * 1e3;
1418
+ var recentFingerprints = /* @__PURE__ */ new Map();
1419
+ function isRecentlySent(fingerprint) {
1420
+ const now = Date.now();
1421
+ const last = recentFingerprints.get(fingerprint);
1422
+ if (last !== void 0 && now - last < CLIENT_DEDUP_TTL) return true;
1423
+ recentFingerprints.set(fingerprint, now);
1424
+ if (recentFingerprints.size > 100) {
1425
+ const oldest = [...recentFingerprints.entries()].sort((a, b) => a[1] - b[1])[0];
1426
+ recentFingerprints.delete(oldest[0]);
1427
+ }
1428
+ return false;
1429
+ }
1430
+ __name(isRecentlySent, "isRecentlySent");
1384
1431
  function installJsErrorCapture() {
1385
1432
  if (typeof window === "undefined") return () => {
1386
1433
  };
1387
1434
  const onError = /* @__PURE__ */ __name(async (message, source, lineno, colno, error) => {
1388
1435
  try {
1389
- const msg = typeof message === "string" ? message : String(message);
1436
+ const msg = truncate(typeof message === "string" ? message : String(message));
1437
+ if (isHydrationNoise(msg)) return;
1390
1438
  const stack = error?.stack ?? `at ${source}:${lineno}:${colno}`;
1391
1439
  const url = window.location.href;
1392
1440
  const fingerprint = await computeFingerprint(msg, stack, url);
1441
+ if (isRecentlySent(fingerprint)) return;
1393
1442
  const { config } = monitorStore.getState();
1394
1443
  monitorStore.getState().push({
1395
1444
  event_type: "JS_ERROR" /* JS_ERROR */,
@@ -1401,7 +1450,8 @@ function installJsErrorCapture() {
1401
1450
  session_id: getSessionId(),
1402
1451
  user_agent: navigator.userAgent,
1403
1452
  project_name: config.project,
1404
- environment: config.environment
1453
+ environment: config.environment,
1454
+ build_id: config.buildId ?? ""
1405
1455
  });
1406
1456
  } catch {
1407
1457
  }
@@ -1409,10 +1459,12 @@ function installJsErrorCapture() {
1409
1459
  const onUnhandledRejection = /* @__PURE__ */ __name(async (e) => {
1410
1460
  try {
1411
1461
  const reason = e.reason;
1412
- const msg = reason instanceof Error ? reason.message : typeof reason === "string" ? reason : "Unhandled promise rejection";
1462
+ const msg = truncate(reason instanceof Error ? reason.message : typeof reason === "string" ? reason : "Unhandled promise rejection");
1463
+ if (isHydrationNoise(msg)) return;
1413
1464
  const stack = reason instanceof Error ? reason.stack ?? "" : "";
1414
1465
  const url = window.location.href;
1415
1466
  const fingerprint = await computeFingerprint(msg, stack, url);
1467
+ if (isRecentlySent(fingerprint)) return;
1416
1468
  const { config } = monitorStore.getState();
1417
1469
  monitorStore.getState().push({
1418
1470
  event_type: "JS_ERROR" /* JS_ERROR */,
@@ -1424,7 +1476,8 @@ function installJsErrorCapture() {
1424
1476
  session_id: getSessionId(),
1425
1477
  user_agent: navigator.userAgent,
1426
1478
  project_name: config.project,
1427
- environment: config.environment
1479
+ environment: config.environment,
1480
+ build_id: config.buildId ?? ""
1428
1481
  });
1429
1482
  } catch {
1430
1483
  }
@@ -1448,16 +1501,23 @@ var typeMap = {
1448
1501
  warn: "WARNING" /* WARNING */,
1449
1502
  error: "ERROR" /* ERROR */
1450
1503
  };
1451
- function stringify(args) {
1452
- return args.map((a) => {
1453
- if (typeof a === "string") return a;
1454
- if (a instanceof Error) return a.message;
1504
+ var ARG_MAX = 500;
1505
+ function stringifyArg(a) {
1506
+ let s;
1507
+ if (typeof a === "string") s = a;
1508
+ else if (a instanceof Error) s = a.message;
1509
+ else {
1455
1510
  try {
1456
- return JSON.stringify(a);
1511
+ s = JSON.stringify(a);
1457
1512
  } catch {
1458
- return String(a);
1513
+ s = String(a);
1459
1514
  }
1460
- }).join(" ");
1515
+ }
1516
+ return s.length > ARG_MAX ? s.slice(0, ARG_MAX - 1) + "\u2026" : s;
1517
+ }
1518
+ __name(stringifyArg, "stringifyArg");
1519
+ function stringify(args) {
1520
+ return args.map(stringifyArg).join(" ");
1461
1521
  }
1462
1522
  __name(stringify, "stringify");
1463
1523
  async function captureConsoleEvent(level, args) {
@@ -1525,10 +1585,11 @@ function installValidationCapture() {
1525
1585
  try {
1526
1586
  const detail = event.detail;
1527
1587
  const { config } = monitorStore.getState();
1588
+ const rawMsg = `Zod validation error in ${detail.operation}: ${detail.error?.message ?? "unknown"}`;
1528
1589
  monitorStore.getState().push({
1529
1590
  event_type: "WARNING" /* WARNING */,
1530
1591
  level: "warn" /* WARN */,
1531
- message: `Zod validation error in ${detail.operation}: ${detail.error?.message ?? "unknown"}`,
1592
+ message: rawMsg.length > 500 ? rawMsg.slice(0, 499) + "\u2026" : rawMsg,
1532
1593
  url: window.location.href,
1533
1594
  http_method: detail.method,
1534
1595
  http_url: detail.path,