@djangocfg/monitor 2.1.236 → 2.1.238

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
@@ -1364,11 +1364,32 @@ __name(sendBatch, "sendBatch");
1364
1364
  // src/client/utils/env.ts
1365
1365
  var isDevelopment = process.env.NODE_ENV === "development";
1366
1366
  var isProduction = !isDevelopment;
1367
- var MONITOR_VERSION = "2.1.236";
1367
+ var MONITOR_VERSION = "2.1.238";
1368
1368
 
1369
1369
  // src/client/store/index.ts
1370
1370
  var CIRCUIT_BREAKER_THRESHOLD = 3;
1371
1371
  var CIRCUIT_BREAKER_COOLDOWN_MS = 6e4;
1372
+ var STORE_DEDUP_TTL = 5e3;
1373
+ var STORE_DEDUP_MAX = 200;
1374
+ var _recentPushKeys = /* @__PURE__ */ new Map();
1375
+ function _pushDedupeKey(event) {
1376
+ const msg = (event.message ?? "").slice(0, 100);
1377
+ return `${event.event_type}:${event.level}:${msg}:${event.http_url ?? event.url ?? ""}`;
1378
+ }
1379
+ __name(_pushDedupeKey, "_pushDedupeKey");
1380
+ function _isRecentPush(key) {
1381
+ const now = Date.now();
1382
+ const last = _recentPushKeys.get(key);
1383
+ if (last !== void 0 && now - last < STORE_DEDUP_TTL) return true;
1384
+ _recentPushKeys.set(key, now);
1385
+ if (_recentPushKeys.size > STORE_DEDUP_MAX) {
1386
+ for (const [k, ts] of _recentPushKeys) {
1387
+ if (now - ts > STORE_DEDUP_TTL) _recentPushKeys.delete(k);
1388
+ }
1389
+ }
1390
+ return false;
1391
+ }
1392
+ __name(_isRecentPush, "_isRecentPush");
1372
1393
  var monitorStore = (0, import_vanilla.createStore)((set, get) => ({
1373
1394
  config: {},
1374
1395
  buffer: [],
@@ -1376,6 +1397,8 @@ var monitorStore = (0, import_vanilla.createStore)((set, get) => ({
1376
1397
  _consecutiveFailures: 0,
1377
1398
  _pausedUntil: 0,
1378
1399
  push(event) {
1400
+ const dedupeKey = _pushDedupeKey(event);
1401
+ if (_isRecentPush(dedupeKey)) return;
1379
1402
  const { config, buffer } = get();
1380
1403
  const maxSize = config.maxBufferSize ?? 20;
1381
1404
  const sanitized = {
@@ -1537,6 +1560,20 @@ var typeMap = {
1537
1560
  error: "ERROR" /* ERROR */
1538
1561
  };
1539
1562
  var ARG_MAX = 500;
1563
+ var CONSOLE_DEDUP_TTL = 5 * 60 * 1e3;
1564
+ var recentConsoleFingerprints = /* @__PURE__ */ new Map();
1565
+ function isRecentConsole(fingerprint) {
1566
+ const now = Date.now();
1567
+ const last = recentConsoleFingerprints.get(fingerprint);
1568
+ if (last !== void 0 && now - last < CONSOLE_DEDUP_TTL) return true;
1569
+ recentConsoleFingerprints.set(fingerprint, now);
1570
+ if (recentConsoleFingerprints.size > 100) {
1571
+ const oldest = [...recentConsoleFingerprints.entries()].sort((a, b) => a[1] - b[1])[0];
1572
+ recentConsoleFingerprints.delete(oldest[0]);
1573
+ }
1574
+ return false;
1575
+ }
1576
+ __name(isRecentConsole, "isRecentConsole");
1540
1577
  function stringifyArg(a) {
1541
1578
  let s;
1542
1579
  if (typeof a === "string") s = a;
@@ -1561,6 +1598,7 @@ async function captureConsoleEvent(level, args) {
1561
1598
  if (MONITOR_INGEST_PATTERN.test(message)) return;
1562
1599
  const url = typeof window !== "undefined" ? window.location.href : "";
1563
1600
  const fingerprint = await computeFingerprint(message, "", url);
1601
+ if (isRecentConsole(fingerprint)) return;
1564
1602
  const { config } = monitorStore.getState();
1565
1603
  monitorStore.getState().push({
1566
1604
  event_type: typeMap[level],
@@ -1613,6 +1651,21 @@ function installConsoleCapture() {
1613
1651
  __name(installConsoleCapture, "installConsoleCapture");
1614
1652
 
1615
1653
  // src/client/capture/validation.ts
1654
+ var VALIDATION_DEDUP_TTL = 1e4;
1655
+ var recentValidations = /* @__PURE__ */ new Map();
1656
+ function isRecentValidation(key) {
1657
+ const now = Date.now();
1658
+ const last = recentValidations.get(key);
1659
+ if (last !== void 0 && now - last < VALIDATION_DEDUP_TTL) return true;
1660
+ recentValidations.set(key, now);
1661
+ if (recentValidations.size > 50) {
1662
+ for (const [k, ts] of recentValidations) {
1663
+ if (now - ts > VALIDATION_DEDUP_TTL) recentValidations.delete(k);
1664
+ }
1665
+ }
1666
+ return false;
1667
+ }
1668
+ __name(isRecentValidation, "isRecentValidation");
1616
1669
  function installValidationCapture() {
1617
1670
  if (typeof window === "undefined") return () => {
1618
1671
  };
@@ -1620,6 +1673,8 @@ function installValidationCapture() {
1620
1673
  if (!(event instanceof CustomEvent)) return;
1621
1674
  try {
1622
1675
  const detail = event.detail;
1676
+ const dedupeKey = `${detail.operation}:${detail.path}:${detail.method}`;
1677
+ if (isRecentValidation(dedupeKey)) return;
1623
1678
  const { config } = monitorStore.getState();
1624
1679
  const rawMsg = `Zod validation error in ${detail.operation}: ${detail.error?.message ?? "unknown"}`;
1625
1680
  monitorStore.getState().push({
@@ -1644,12 +1699,29 @@ function installValidationCapture() {
1644
1699
  __name(installValidationCapture, "installValidationCapture");
1645
1700
 
1646
1701
  // src/client/capture/network.ts
1702
+ var NETWORK_DEDUP_TTL = 5e3;
1703
+ var recentNetworkErrors = /* @__PURE__ */ new Map();
1704
+ function isRecentNetwork(key) {
1705
+ const now = Date.now();
1706
+ const last = recentNetworkErrors.get(key);
1707
+ if (last !== void 0 && now - last < NETWORK_DEDUP_TTL) return true;
1708
+ recentNetworkErrors.set(key, now);
1709
+ if (recentNetworkErrors.size > 100) {
1710
+ for (const [k, ts] of recentNetworkErrors) {
1711
+ if (now - ts > NETWORK_DEDUP_TTL) recentNetworkErrors.delete(k);
1712
+ }
1713
+ }
1714
+ return false;
1715
+ }
1716
+ __name(isRecentNetwork, "isRecentNetwork");
1647
1717
  async function monitoredFetch(input, init) {
1648
1718
  const url = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
1649
1719
  const method = (init?.method ?? "GET").toUpperCase();
1650
1720
  try {
1651
1721
  const response = await fetch(input, init);
1652
1722
  if (!response.ok) {
1723
+ const netKey = `${response.status}:${method}:${url}`;
1724
+ if (isRecentNetwork(netKey)) return response;
1653
1725
  const { config } = monitorStore.getState();
1654
1726
  monitorStore.getState().push({
1655
1727
  event_type: "NETWORK_ERROR" /* NETWORK_ERROR */,
@@ -1667,19 +1739,23 @@ async function monitoredFetch(input, init) {
1667
1739
  }
1668
1740
  return response;
1669
1741
  } catch (err) {
1670
- const { config } = monitorStore.getState();
1671
- monitorStore.getState().push({
1672
- event_type: "NETWORK_ERROR" /* NETWORK_ERROR */,
1673
- level: "error" /* ERROR */,
1674
- message: err instanceof Error ? err.message : `Network error \u2014 ${method} ${url}`,
1675
- url: typeof window !== "undefined" ? window.location.href : "",
1676
- http_method: method,
1677
- http_url: url,
1678
- session_id: getSessionId(),
1679
- user_agent: typeof navigator !== "undefined" ? navigator.userAgent : "",
1680
- project_name: config.project,
1681
- environment: config.environment
1682
- });
1742
+ const errMsg = err instanceof Error ? err.message : "network-error";
1743
+ const netKey = `err:${errMsg.slice(0, 50)}:${method}:${url}`;
1744
+ if (!isRecentNetwork(netKey)) {
1745
+ const { config } = monitorStore.getState();
1746
+ monitorStore.getState().push({
1747
+ event_type: "NETWORK_ERROR" /* NETWORK_ERROR */,
1748
+ level: "error" /* ERROR */,
1749
+ message: err instanceof Error ? err.message : `Network error \u2014 ${method} ${url}`,
1750
+ url: typeof window !== "undefined" ? window.location.href : "",
1751
+ http_method: method,
1752
+ http_url: url,
1753
+ session_id: getSessionId(),
1754
+ user_agent: typeof navigator !== "undefined" ? navigator.userAgent : "",
1755
+ project_name: config.project,
1756
+ environment: config.environment
1757
+ });
1758
+ }
1683
1759
  throw err;
1684
1760
  }
1685
1761
  }