@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 +76 -15
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +3 -0
- package/dist/client.d.ts +3 -0
- package/dist/client.mjs +76 -15
- package/dist/client.mjs.map +1 -1
- package/dist/index.cjs +3 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.mjs +3 -2
- package/dist/index.mjs.map +1 -1
- package/dist/server.cjs +3 -2
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +1 -0
- package/dist/server.d.ts +1 -0
- package/dist/server.mjs +3 -2
- package/dist/server.mjs.map +1 -1
- package/package.json +2 -2
- package/src/_api/generated/cfg_monitor/_utils/schemas/FrontendEventIngestRequest.schema.ts +2 -1
- package/src/_api/generated/cfg_monitor/monitor/models.ts +1 -0
- package/src/_api/generated/cfg_monitor/schema.json +6 -1
- package/src/client/capture/console.ts +11 -5
- package/src/client/capture/js-errors.ts +48 -3
- package/src/client/capture/validation.ts +2 -1
- package/src/client/store/index.ts +18 -1
- package/src/types/config.ts +2 -0
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(
|
|
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
|
|
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
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
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
|
-
|
|
1511
|
+
s = JSON.stringify(a);
|
|
1457
1512
|
} catch {
|
|
1458
|
-
|
|
1513
|
+
s = String(a);
|
|
1459
1514
|
}
|
|
1460
|
-
}
|
|
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:
|
|
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,
|