@djangocfg/monitor 2.1.226 → 2.1.228
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 +2 -6
- package/dist/client.cjs +48 -26
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +31 -33
- package/dist/client.d.ts +31 -33
- package/dist/client.mjs +48 -26
- package/dist/client.mjs.map +1 -1
- package/dist/index.cjs +9 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +29 -33
- package/dist/index.d.ts +29 -33
- package/dist/index.mjs +9 -10
- package/dist/index.mjs.map +1 -1
- package/dist/server.cjs +10 -11
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +29 -33
- package/dist/server.d.ts +29 -33
- package/dist/server.mjs +10 -11
- package/dist/server.mjs.map +1 -1
- package/package.json +2 -2
- package/src/_api/generated/cfg_monitor/_utils/schemas/FrontendEventIngestRequest.schema.ts +5 -6
- package/src/_api/generated/cfg_monitor/_utils/schemas/IngestBatchRequest.schema.ts +2 -2
- package/src/_api/generated/cfg_monitor/enums.ts +14 -16
- package/src/_api/generated/cfg_monitor/monitor/client.ts +2 -1
- package/src/_api/generated/cfg_monitor/monitor/models.ts +16 -18
- package/src/_api/generated/cfg_monitor/schema.json +19 -27
- package/src/client/capture/console.ts +3 -1
- package/src/client/capture/js-errors.ts +7 -0
- package/src/client/capture/network.ts +1 -1
- package/src/client/capture/validation.ts +1 -1
- package/src/client/constants.ts +7 -0
- package/src/client/index.ts +2 -1
- package/src/client/store/index.ts +28 -2
- package/src/client/transport/ingest.ts +5 -9
- package/src/client/window.ts +3 -3
- package/src/server/index.ts +1 -1
package/README.md
CHANGED
|
@@ -116,13 +116,9 @@ export const POST = withMonitor(async (req) => {
|
|
|
116
116
|
|
|
117
117
|
## Django Backend
|
|
118
118
|
|
|
119
|
-
|
|
120
|
-
# cfg.py
|
|
121
|
-
class Config(DjangoConfig):
|
|
122
|
-
installed_apps = [..., 'django_cfg.apps.system.monitor']
|
|
123
|
-
```
|
|
119
|
+
The monitor module is included automatically with `django-cfg` — no extra `installed_apps` entry needed.
|
|
124
120
|
|
|
125
|
-
Ingest endpoint: `POST /cfg/monitor/ingest/` — no auth required,
|
|
121
|
+
Ingest endpoint: `POST /cfg/monitor/ingest/` — no auth required, always mounted.
|
|
126
122
|
|
|
127
123
|
## Browser Console Testing
|
|
128
124
|
|
package/dist/client.cjs
CHANGED
|
@@ -263,6 +263,8 @@ var require_retry2 = __commonJS({
|
|
|
263
263
|
// src/client/index.ts
|
|
264
264
|
var client_exports = {};
|
|
265
265
|
__export(client_exports, {
|
|
266
|
+
EventLevel: () => FrontendEventIngestRequestLevel,
|
|
267
|
+
EventType: () => FrontendEventIngestRequestEventType,
|
|
266
268
|
FrontendMonitor: () => FrontendMonitor,
|
|
267
269
|
MonitorProvider: () => MonitorProvider,
|
|
268
270
|
getSessionId: () => getSessionId,
|
|
@@ -342,7 +344,8 @@ var _Monitor = class _Monitor {
|
|
|
342
344
|
/**
|
|
343
345
|
* Ingest browser events
|
|
344
346
|
*
|
|
345
|
-
* Accepts a batch of up to 50 frontend events. No authentication required
|
|
347
|
+
* Accepts a batch of up to 50 frontend events. No authentication required
|
|
348
|
+
* — anonymous visitors can send events.
|
|
346
349
|
*/
|
|
347
350
|
async ingestCreate(data) {
|
|
348
351
|
const response = await this.client.request("POST", "/cfg/monitor/ingest/", { body: data });
|
|
@@ -1120,19 +1123,18 @@ var MemoryStorageAdapter = _MemoryStorageAdapter;
|
|
|
1120
1123
|
|
|
1121
1124
|
// src/_api/generated/cfg_monitor/enums.ts
|
|
1122
1125
|
var FrontendEventIngestRequestEventType = /* @__PURE__ */ ((FrontendEventIngestRequestEventType2) => {
|
|
1126
|
+
FrontendEventIngestRequestEventType2["JS_ERROR"] = "JS_ERROR";
|
|
1127
|
+
FrontendEventIngestRequestEventType2["NETWORK_ERROR"] = "NETWORK_ERROR";
|
|
1123
1128
|
FrontendEventIngestRequestEventType2["ERROR"] = "ERROR";
|
|
1124
1129
|
FrontendEventIngestRequestEventType2["WARNING"] = "WARNING";
|
|
1125
|
-
FrontendEventIngestRequestEventType2["INFO"] = "INFO";
|
|
1126
1130
|
FrontendEventIngestRequestEventType2["PAGE_VIEW"] = "PAGE_VIEW";
|
|
1127
1131
|
FrontendEventIngestRequestEventType2["PERFORMANCE"] = "PERFORMANCE";
|
|
1128
|
-
FrontendEventIngestRequestEventType2["NETWORK_ERROR"] = "NETWORK_ERROR";
|
|
1129
|
-
FrontendEventIngestRequestEventType2["JS_ERROR"] = "JS_ERROR";
|
|
1130
1132
|
FrontendEventIngestRequestEventType2["CONSOLE"] = "CONSOLE";
|
|
1131
1133
|
return FrontendEventIngestRequestEventType2;
|
|
1132
1134
|
})(FrontendEventIngestRequestEventType || {});
|
|
1133
1135
|
var FrontendEventIngestRequestLevel = /* @__PURE__ */ ((FrontendEventIngestRequestLevel2) => {
|
|
1134
1136
|
FrontendEventIngestRequestLevel2["ERROR"] = "error";
|
|
1135
|
-
FrontendEventIngestRequestLevel2["
|
|
1137
|
+
FrontendEventIngestRequestLevel2["WARNING"] = "warning";
|
|
1136
1138
|
FrontendEventIngestRequestLevel2["INFO"] = "info";
|
|
1137
1139
|
FrontendEventIngestRequestLevel2["DEBUG"] = "debug";
|
|
1138
1140
|
return FrontendEventIngestRequestLevel2;
|
|
@@ -1150,13 +1152,12 @@ var FrontendEventIngestRequestSchema = import_zod.z.object({
|
|
|
1150
1152
|
http_status: import_zod.z.number().int().nullable().optional(),
|
|
1151
1153
|
http_method: import_zod.z.string().max(10).optional(),
|
|
1152
1154
|
http_url: import_zod.z.string().max(2e3).optional(),
|
|
1155
|
+
session_id: import_zod.z.string().max(64).optional(),
|
|
1153
1156
|
user_agent: import_zod.z.string().max(500).optional(),
|
|
1154
|
-
|
|
1155
|
-
browser_fingerprint: import_zod.z.string().max(64).optional(),
|
|
1156
|
-
extra: import_zod.z.record(import_zod.z.string(), import_zod.z.any()).optional(),
|
|
1157
|
-
project_name: import_zod.z.string().max(100).optional(),
|
|
1157
|
+
build_id: import_zod.z.string().max(100).optional(),
|
|
1158
1158
|
environment: import_zod.z.string().max(20).optional(),
|
|
1159
|
-
|
|
1159
|
+
extra: import_zod.z.record(import_zod.z.string(), import_zod.z.any()).optional(),
|
|
1160
|
+
project_name: import_zod.z.string().max(100).optional()
|
|
1160
1161
|
});
|
|
1161
1162
|
|
|
1162
1163
|
// src/_api/generated/cfg_monitor/_utils/schemas/IngestBatchRequest.schema.ts
|
|
@@ -1343,23 +1344,24 @@ function syncBeaconBaseUrl() {
|
|
|
1343
1344
|
__name(syncBeaconBaseUrl, "syncBeaconBaseUrl");
|
|
1344
1345
|
async function sendBatch(batch, useBeacon = false) {
|
|
1345
1346
|
if (batch.events.length === 0) return;
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
await monitorApi.monitor.ingestCreate(batch);
|
|
1352
|
-
}
|
|
1353
|
-
} catch {
|
|
1347
|
+
if (useBeacon) {
|
|
1348
|
+
syncBeaconBaseUrl();
|
|
1349
|
+
await monitorApiBeacon.monitor.ingestCreate(batch);
|
|
1350
|
+
} else {
|
|
1351
|
+
await monitorApi.monitor.ingestCreate(batch);
|
|
1354
1352
|
}
|
|
1355
1353
|
}
|
|
1356
1354
|
__name(sendBatch, "sendBatch");
|
|
1357
1355
|
|
|
1358
1356
|
// src/client/store/index.ts
|
|
1357
|
+
var CIRCUIT_BREAKER_THRESHOLD = 3;
|
|
1358
|
+
var CIRCUIT_BREAKER_COOLDOWN_MS = 6e4;
|
|
1359
1359
|
var monitorStore = (0, import_vanilla.createStore)((set, get) => ({
|
|
1360
1360
|
config: {},
|
|
1361
1361
|
buffer: [],
|
|
1362
1362
|
initialized: false,
|
|
1363
|
+
_consecutiveFailures: 0,
|
|
1364
|
+
_pausedUntil: 0,
|
|
1363
1365
|
push(event) {
|
|
1364
1366
|
const { config, buffer } = get();
|
|
1365
1367
|
const maxSize = config.maxBufferSize ?? 20;
|
|
@@ -1385,23 +1387,40 @@ var monitorStore = (0, import_vanilla.createStore)((set, get) => ({
|
|
|
1385
1387
|
}
|
|
1386
1388
|
},
|
|
1387
1389
|
flush(useBeacon = false) {
|
|
1388
|
-
const { buffer } = get();
|
|
1390
|
+
const { buffer, _pausedUntil } = get();
|
|
1389
1391
|
if (buffer.length === 0) return;
|
|
1392
|
+
if (Date.now() < _pausedUntil) return;
|
|
1390
1393
|
const batch = buffer.slice(0, 50);
|
|
1391
1394
|
set({ buffer: buffer.slice(50) });
|
|
1392
|
-
sendBatch({ events: batch }, useBeacon)
|
|
1395
|
+
sendBatch({ events: batch }, useBeacon).then(
|
|
1396
|
+
() => {
|
|
1397
|
+
set({ _consecutiveFailures: 0, _pausedUntil: 0 });
|
|
1398
|
+
},
|
|
1399
|
+
() => {
|
|
1400
|
+
const failures = get()._consecutiveFailures + 1;
|
|
1401
|
+
const pausedUntil = failures >= CIRCUIT_BREAKER_THRESHOLD ? Date.now() + CIRCUIT_BREAKER_COOLDOWN_MS : get()._pausedUntil;
|
|
1402
|
+
set({ _consecutiveFailures: failures, _pausedUntil: pausedUntil });
|
|
1403
|
+
}
|
|
1404
|
+
);
|
|
1393
1405
|
},
|
|
1394
1406
|
setConfig(config) {
|
|
1395
1407
|
set({ config, initialized: true });
|
|
1396
1408
|
}
|
|
1397
1409
|
}));
|
|
1398
1410
|
|
|
1411
|
+
// src/client/constants.ts
|
|
1412
|
+
var MONITOR_INGEST_PATTERN = /cfg\/monitor\/ingest/;
|
|
1413
|
+
|
|
1399
1414
|
// src/client/capture/js-errors.ts
|
|
1400
1415
|
var MSG_MAX = 2e3;
|
|
1401
1416
|
function truncate(s, max = MSG_MAX) {
|
|
1402
1417
|
return s.length > max ? s.slice(0, max - 1) + "\u2026" : s;
|
|
1403
1418
|
}
|
|
1404
1419
|
__name(truncate, "truncate");
|
|
1420
|
+
function isMonitorOwnError(msg, stack) {
|
|
1421
|
+
return MONITOR_INGEST_PATTERN.test(msg) || MONITOR_INGEST_PATTERN.test(stack ?? "");
|
|
1422
|
+
}
|
|
1423
|
+
__name(isMonitorOwnError, "isMonitorOwnError");
|
|
1405
1424
|
var HYDRATION_NOISE = [
|
|
1406
1425
|
/hydration failed/i,
|
|
1407
1426
|
/there was an error while hydrating/i,
|
|
@@ -1436,6 +1455,7 @@ function installJsErrorCapture() {
|
|
|
1436
1455
|
const msg = truncate(typeof message === "string" ? message : String(message));
|
|
1437
1456
|
if (isHydrationNoise(msg)) return;
|
|
1438
1457
|
const stack = error?.stack ?? `at ${source}:${lineno}:${colno}`;
|
|
1458
|
+
if (isMonitorOwnError(msg, stack)) return;
|
|
1439
1459
|
const url = window.location.href;
|
|
1440
1460
|
const fingerprint = await computeFingerprint(msg, stack, url);
|
|
1441
1461
|
if (isRecentlySent(fingerprint)) return;
|
|
@@ -1462,6 +1482,7 @@ function installJsErrorCapture() {
|
|
|
1462
1482
|
const msg = truncate(reason instanceof Error ? reason.message : typeof reason === "string" ? reason : "Unhandled promise rejection");
|
|
1463
1483
|
if (isHydrationNoise(msg)) return;
|
|
1464
1484
|
const stack = reason instanceof Error ? reason.stack ?? "" : "";
|
|
1485
|
+
if (isMonitorOwnError(msg, stack)) return;
|
|
1465
1486
|
const url = window.location.href;
|
|
1466
1487
|
const fingerprint = await computeFingerprint(msg, stack, url);
|
|
1467
1488
|
if (isRecentlySent(fingerprint)) return;
|
|
@@ -1494,7 +1515,7 @@ __name(installJsErrorCapture, "installJsErrorCapture");
|
|
|
1494
1515
|
|
|
1495
1516
|
// src/client/capture/console.ts
|
|
1496
1517
|
var levelMap = {
|
|
1497
|
-
warn: "
|
|
1518
|
+
warn: "warning" /* WARNING */,
|
|
1498
1519
|
error: "error" /* ERROR */
|
|
1499
1520
|
};
|
|
1500
1521
|
var typeMap = {
|
|
@@ -1523,6 +1544,7 @@ __name(stringify, "stringify");
|
|
|
1523
1544
|
async function captureConsoleEvent(level, args) {
|
|
1524
1545
|
try {
|
|
1525
1546
|
const message = stringify(args);
|
|
1547
|
+
if (MONITOR_INGEST_PATTERN.test(message)) return;
|
|
1526
1548
|
const url = typeof window !== "undefined" ? window.location.href : "";
|
|
1527
1549
|
const fingerprint = await computeFingerprint(message, "", url);
|
|
1528
1550
|
const { config } = monitorStore.getState();
|
|
@@ -1588,7 +1610,7 @@ function installValidationCapture() {
|
|
|
1588
1610
|
const rawMsg = `Zod validation error in ${detail.operation}: ${detail.error?.message ?? "unknown"}`;
|
|
1589
1611
|
monitorStore.getState().push({
|
|
1590
1612
|
event_type: "WARNING" /* WARNING */,
|
|
1591
|
-
level: "
|
|
1613
|
+
level: "warning" /* WARNING */,
|
|
1592
1614
|
message: rawMsg.length > 500 ? rawMsg.slice(0, 499) + "\u2026" : rawMsg,
|
|
1593
1615
|
url: window.location.href,
|
|
1594
1616
|
http_method: detail.method,
|
|
@@ -1617,7 +1639,7 @@ async function monitoredFetch(input, init) {
|
|
|
1617
1639
|
const { config } = monitorStore.getState();
|
|
1618
1640
|
monitorStore.getState().push({
|
|
1619
1641
|
event_type: "NETWORK_ERROR" /* NETWORK_ERROR */,
|
|
1620
|
-
level: response.status >= 500 ? "error" /* ERROR */ : "
|
|
1642
|
+
level: response.status >= 500 ? "error" /* ERROR */ : "warning" /* WARNING */,
|
|
1621
1643
|
message: `HTTP ${response.status} ${response.statusText} \u2014 ${method} ${url}`,
|
|
1622
1644
|
url: typeof window !== "undefined" ? window.location.href : "",
|
|
1623
1645
|
http_status: response.status,
|
|
@@ -1677,17 +1699,17 @@ function initWindowMonitor() {
|
|
|
1677
1699
|
console.log("[monitor] error captured \u2192", message);
|
|
1678
1700
|
},
|
|
1679
1701
|
warn(message, extra) {
|
|
1680
|
-
monitorStore.getState().push(makeEvent("WARNING" /* WARNING */, "
|
|
1702
|
+
monitorStore.getState().push(makeEvent("WARNING" /* WARNING */, "warning" /* WARNING */, message, extra));
|
|
1681
1703
|
console.log("[monitor] warn captured \u2192", message);
|
|
1682
1704
|
},
|
|
1683
1705
|
info(message, extra) {
|
|
1684
|
-
monitorStore.getState().push(makeEvent("
|
|
1706
|
+
monitorStore.getState().push(makeEvent("WARNING" /* WARNING */, "info" /* INFO */, message, extra));
|
|
1685
1707
|
console.log("[monitor] info captured \u2192", message);
|
|
1686
1708
|
},
|
|
1687
1709
|
network(status, method, url, extra) {
|
|
1688
1710
|
const event = makeEvent(
|
|
1689
1711
|
"NETWORK_ERROR" /* NETWORK_ERROR */,
|
|
1690
|
-
status >= 500 ? "error" /* ERROR */ : "
|
|
1712
|
+
status >= 500 ? "error" /* ERROR */ : "warning" /* WARNING */,
|
|
1691
1713
|
`${method} ${url} \u2192 ${status}`,
|
|
1692
1714
|
extra
|
|
1693
1715
|
);
|