@djangocfg/monitor 2.1.230 → 2.1.232
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 +16 -1
- package/dist/client.cjs +62 -44
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +3 -1
- package/dist/client.d.ts +3 -1
- package/dist/client.mjs +62 -44
- package/dist/client.mjs.map +1 -1
- package/dist/index.cjs +36 -32
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +36 -32
- package/dist/index.mjs.map +1 -1
- package/dist/server.cjs +36 -32
- package/dist/server.cjs.map +1 -1
- package/dist/server.mjs +36 -32
- package/dist/server.mjs.map +1 -1
- package/package.json +2 -2
- package/src/_api/generated/cfg_monitor/client.ts +39 -42
- package/src/client/hooks/useDebugMode.ts +21 -7
- package/src/client/index.ts +1 -1
- package/src/client/store/index.ts +2 -0
- package/src/client/utils/env.ts +3 -0
- package/src/client/window.ts +3 -0
package/README.md
CHANGED
|
@@ -76,6 +76,7 @@ const res = await monitoredFetch('/api/orders', { method: 'POST', body: JSON.str
|
|
|
76
76
|
|--------|------|---------|-------------|
|
|
77
77
|
| `project` | `string` | `''` | Project name sent with every event |
|
|
78
78
|
| `environment` | `string` | `''` | `production` / `staging` / `development` |
|
|
79
|
+
| `buildId` | `string` | `sdk:<version>` | Build identifier (e.g. Next.js `BUILD_ID` or git SHA). Stamped on every event as `build_id`. Auto-filled with SDK version if not set |
|
|
79
80
|
| `baseUrl` | `string` | same origin | Base URL of the django-cfg backend |
|
|
80
81
|
| `flushInterval` | `number` | `5000` | Buffer flush interval (ms) |
|
|
81
82
|
| `maxBufferSize` | `number` | `20` | Max events before immediate flush |
|
|
@@ -137,7 +138,21 @@ window.monitor.flush()
|
|
|
137
138
|
|
|
138
139
|
// Inspect current state
|
|
139
140
|
window.monitor.status()
|
|
140
|
-
// → logs config, buffer size, session_id
|
|
141
|
+
// → logs sdk version, build_id, config, buffer size, session_id
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## Debug Mode
|
|
145
|
+
|
|
146
|
+
`useDebugMode` hook controls whether the debug panel is unlocked:
|
|
147
|
+
|
|
148
|
+
- **development** — always `true`, no localStorage needed
|
|
149
|
+
- **production** — `?debug=1` in URL → persists to `localStorage.__debug_mode__`, panel unlocks
|
|
150
|
+
- **production** — `?debug=0` in URL → clears `localStorage.__debug_mode__`, panel locks
|
|
151
|
+
|
|
152
|
+
```typescript
|
|
153
|
+
import { useDebugMode } from '@djangocfg/monitor/client'
|
|
154
|
+
|
|
155
|
+
const isDebug = useDebugMode()
|
|
141
156
|
```
|
|
142
157
|
|
|
143
158
|
## Debug Panel Integration
|
package/dist/client.cjs
CHANGED
|
@@ -266,6 +266,7 @@ __export(client_exports, {
|
|
|
266
266
|
EventLevel: () => FrontendEventIngestRequestLevel,
|
|
267
267
|
EventType: () => FrontendEventIngestRequestEventType,
|
|
268
268
|
FrontendMonitor: () => FrontendMonitor,
|
|
269
|
+
MONITOR_VERSION: () => MONITOR_VERSION,
|
|
269
270
|
MonitorProvider: () => MonitorProvider,
|
|
270
271
|
getSessionId: () => getSessionId,
|
|
271
272
|
initWindowMonitor: () => initWindowMonitor,
|
|
@@ -994,43 +995,47 @@ var _APIClient = class _APIClient {
|
|
|
994
995
|
if (error instanceof APIError) {
|
|
995
996
|
throw error;
|
|
996
997
|
}
|
|
997
|
-
|
|
998
|
+
let possiblyCors = false;
|
|
999
|
+
if (error instanceof TypeError && typeof window !== "undefined") {
|
|
1000
|
+
try {
|
|
1001
|
+
const isCrossOrigin = (() => {
|
|
1002
|
+
try {
|
|
1003
|
+
return new URL(url).origin !== window.location.origin;
|
|
1004
|
+
} catch {
|
|
1005
|
+
return false;
|
|
1006
|
+
}
|
|
1007
|
+
})();
|
|
1008
|
+
if (isCrossOrigin) {
|
|
1009
|
+
const entries = performance.getEntriesByName(url, "resource");
|
|
1010
|
+
if (entries.length > 0) {
|
|
1011
|
+
const last = entries[entries.length - 1];
|
|
1012
|
+
possiblyCors = "responseStatus" in last && last.responseStatus === 0;
|
|
1013
|
+
}
|
|
1014
|
+
}
|
|
1015
|
+
} catch {
|
|
1016
|
+
}
|
|
1017
|
+
}
|
|
998
1018
|
if (this.logger) {
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
this.logger.error(` \u2192
|
|
1003
|
-
} else {
|
|
1004
|
-
this.logger.error(`\u26A0\uFE0F Network Error: ${method} ${url}`);
|
|
1005
|
-
this.logger.error(` \u2192 ${error instanceof Error ? error.message : String(error)}`);
|
|
1019
|
+
this.logger.error(`\u26A0\uFE0F Network Error: ${method} ${url}`);
|
|
1020
|
+
this.logger.error(` \u2192 ${error instanceof Error ? error.message : String(error)}`);
|
|
1021
|
+
if (possiblyCors) {
|
|
1022
|
+
this.logger.error(` \u2192 Possibly blocked by CORS policy (configure CORS on the server)`);
|
|
1006
1023
|
}
|
|
1007
1024
|
}
|
|
1008
1025
|
if (typeof window !== "undefined") {
|
|
1009
1026
|
try {
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
window.dispatchEvent(new CustomEvent("network-error", {
|
|
1023
|
-
detail: {
|
|
1024
|
-
url,
|
|
1025
|
-
method,
|
|
1026
|
-
error: error instanceof Error ? error.message : String(error),
|
|
1027
|
-
timestamp: /* @__PURE__ */ new Date()
|
|
1028
|
-
},
|
|
1029
|
-
bubbles: true,
|
|
1030
|
-
cancelable: false
|
|
1031
|
-
}));
|
|
1032
|
-
}
|
|
1033
|
-
} catch (eventError) {
|
|
1027
|
+
window.dispatchEvent(new CustomEvent("network-error", {
|
|
1028
|
+
detail: {
|
|
1029
|
+
url,
|
|
1030
|
+
method,
|
|
1031
|
+
error: error instanceof Error ? error.message : String(error),
|
|
1032
|
+
possibly_cors: possiblyCors,
|
|
1033
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
1034
|
+
},
|
|
1035
|
+
bubbles: true,
|
|
1036
|
+
cancelable: false
|
|
1037
|
+
}));
|
|
1038
|
+
} catch {
|
|
1034
1039
|
}
|
|
1035
1040
|
}
|
|
1036
1041
|
const networkError = error instanceof Error ? new NetworkError(error.message, url, error) : new NetworkError("Unknown error", url);
|
|
@@ -1356,6 +1361,11 @@ async function sendBatch(batch, useBeacon = false) {
|
|
|
1356
1361
|
}
|
|
1357
1362
|
__name(sendBatch, "sendBatch");
|
|
1358
1363
|
|
|
1364
|
+
// src/client/utils/env.ts
|
|
1365
|
+
var isDevelopment = true;
|
|
1366
|
+
var isProduction = false;
|
|
1367
|
+
var MONITOR_VERSION = "2.1.232";
|
|
1368
|
+
|
|
1359
1369
|
// src/client/store/index.ts
|
|
1360
1370
|
var CIRCUIT_BREAKER_THRESHOLD = 3;
|
|
1361
1371
|
var CIRCUIT_BREAKER_COOLDOWN_MS = 6e4;
|
|
@@ -1369,6 +1379,7 @@ var monitorStore = (0, import_vanilla.createStore)((set, get) => ({
|
|
|
1369
1379
|
const { config, buffer } = get();
|
|
1370
1380
|
const maxSize = config.maxBufferSize ?? 20;
|
|
1371
1381
|
const sanitized = {
|
|
1382
|
+
build_id: event.build_id ?? config.buildId ?? `sdk:${MONITOR_VERSION}`,
|
|
1372
1383
|
...event,
|
|
1373
1384
|
// Enforce field size limits before buffering (last-resort backstop)
|
|
1374
1385
|
message: event.message && event.message.length > 4997 ? event.message.slice(0, 4997) + "..." : event.message,
|
|
@@ -1730,6 +1741,8 @@ function initWindowMonitor() {
|
|
|
1730
1741
|
status() {
|
|
1731
1742
|
const state = monitorStore.getState();
|
|
1732
1743
|
console.group("[monitor] status");
|
|
1744
|
+
console.log("sdk version:", MONITOR_VERSION);
|
|
1745
|
+
console.log("build_id:", state.config.buildId ?? `sdk:${MONITOR_VERSION}`);
|
|
1733
1746
|
console.log("config:", state.config);
|
|
1734
1747
|
console.log("buffer size:", state.buffer.length);
|
|
1735
1748
|
console.log("initialized:", state.initialized);
|
|
@@ -1754,12 +1767,6 @@ __name(MonitorProvider, "MonitorProvider");
|
|
|
1754
1767
|
|
|
1755
1768
|
// src/client/hooks/useDebugMode.ts
|
|
1756
1769
|
var import_react2 = require("react");
|
|
1757
|
-
|
|
1758
|
-
// src/client/utils/env.ts
|
|
1759
|
-
var isDevelopment = true;
|
|
1760
|
-
var isProduction = false;
|
|
1761
|
-
|
|
1762
|
-
// src/client/hooks/useDebugMode.ts
|
|
1763
1770
|
var LS_KEY = "__debug_mode__";
|
|
1764
1771
|
function readFromStorage() {
|
|
1765
1772
|
try {
|
|
@@ -1776,16 +1783,27 @@ function persistToStorage() {
|
|
|
1776
1783
|
}
|
|
1777
1784
|
}
|
|
1778
1785
|
__name(persistToStorage, "persistToStorage");
|
|
1786
|
+
function clearFromStorage() {
|
|
1787
|
+
try {
|
|
1788
|
+
localStorage.removeItem(LS_KEY);
|
|
1789
|
+
} catch {
|
|
1790
|
+
}
|
|
1791
|
+
}
|
|
1792
|
+
__name(clearFromStorage, "clearFromStorage");
|
|
1779
1793
|
function consumeDebugParam() {
|
|
1780
|
-
if (typeof window === "undefined") return
|
|
1794
|
+
if (typeof window === "undefined") return null;
|
|
1781
1795
|
const params = new URLSearchParams(window.location.search);
|
|
1782
1796
|
const value = params.get("debug");
|
|
1783
|
-
if (
|
|
1784
|
-
|
|
1797
|
+
if (value === null) return null;
|
|
1798
|
+
if (value === "1") {
|
|
1799
|
+
persistToStorage();
|
|
1800
|
+
} else {
|
|
1801
|
+
clearFromStorage();
|
|
1802
|
+
}
|
|
1785
1803
|
params.delete("debug");
|
|
1786
1804
|
const newUrl = `${window.location.pathname}${params.toString() ? `?${params.toString()}` : ""}${window.location.hash}`;
|
|
1787
1805
|
window.history.replaceState(null, "", newUrl);
|
|
1788
|
-
return
|
|
1806
|
+
return value === "1";
|
|
1789
1807
|
}
|
|
1790
1808
|
__name(consumeDebugParam, "consumeDebugParam");
|
|
1791
1809
|
function useDebugMode() {
|
|
@@ -1793,8 +1811,8 @@ function useDebugMode() {
|
|
|
1793
1811
|
const [isDebug, setIsDebug] = (0, import_react2.useState)(false);
|
|
1794
1812
|
(0, import_react2.useEffect)(() => {
|
|
1795
1813
|
const fromUrl = consumeDebugParam();
|
|
1796
|
-
if (fromUrl) {
|
|
1797
|
-
setIsDebug(
|
|
1814
|
+
if (fromUrl !== null) {
|
|
1815
|
+
setIsDebug(fromUrl);
|
|
1798
1816
|
return;
|
|
1799
1817
|
}
|
|
1800
1818
|
setIsDebug(readFromStorage());
|