cwj_monitoring 0.0.24 → 0.0.26

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 CHANGED
@@ -91,22 +91,20 @@ interface TransportConfig {
91
91
  - **FP (First Paint)**: 首次绘制时间
92
92
  - **FCP (First Contentful Paint)**: 首次内容绘制时间
93
93
  - **LCP (Largest Contentful Paint)**: 最大内容绘制时间
94
- - **INP (Interaction to Next Paint)**: 交互到下一次绘制的延迟(关注交互响应性)
95
- - **Long Task**: 超过阈值的长任务(关注主线程阻塞)
94
+ - **LoAF (Long Animation Frame)**: 现代化的长任务监控,提供详尽的脚本级归因(Chrome 123+)
96
95
  - **Resource**: 仅监听 `fetch` 与 `xmlhttprequest` 的网络请求耗时
97
96
 
98
97
  **配置项:**
99
98
 
100
- - `longTaskThreshold`: 长任务阈值 (ms),默认 `100`
99
+ - `loafThreshold`: LoAF 阈值 (ms),默认 `50`
101
100
  - `resourceThreshold`: 资源加载阈值 (ms),默认 `1000`
102
- - `inpThreshold`: INP 阈值 (ms),默认 `200`
103
101
  - `filter`: 过滤函数,支持按类型过滤指标
104
102
 
105
103
  示例:
106
104
 
107
105
  ```typescript
108
106
  PerformancePlugin({
109
- longTaskThreshold: 200, // 仅记录超过 200ms 的长任务
107
+ loafThreshold: 150, // 仅记录超过 150ms 的 LoAF
110
108
  resourceThreshold: 2000, // 仅记录超过 2s 的请求
111
109
  });
112
110
  ```
package/dist/index.cjs CHANGED
@@ -105,13 +105,19 @@ function throttle(fn, delay) {
105
105
  }
106
106
  };
107
107
  }
108
+ const isIgnoredScriptSource = (sourceURL) => {
109
+ if (!sourceURL || typeof sourceURL !== "string")
110
+ return false;
111
+ if (/node_modules/.test(sourceURL))
112
+ return true;
113
+ return false;
114
+ };
108
115
 
109
116
  const MAX_CACHE_LEN = 5;
110
117
  const MAX_WAITING_TIME = 3e4;
111
118
  const UUID = "track_uuid";
112
- const DEFAULT_LONG_TASK_THRESHOLD = 100;
113
119
  const DEFAULT_RESOURCE_THRESHOLD = 1e3;
114
- const DEFAULT_INP_THRESHOLD = 200;
120
+ const DEFAULT_LOAF_THRESHOLD = 50;
115
121
 
116
122
  var __defProp$3 = Object.defineProperty;
117
123
  var __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
@@ -317,6 +323,7 @@ var EMIT_TYPE = /* @__PURE__ */ ((EMIT_TYPE2) => {
317
323
  EMIT_TYPE2["PERFORMANCE_INP"] = "performance_inp";
318
324
  EMIT_TYPE2["PERFORMANCE_LONGTASK"] = "performance_longtask";
319
325
  EMIT_TYPE2["PERFORMANCE_RESOURCE"] = "performance_resource";
326
+ EMIT_TYPE2["PERFORMANCE_LOAF"] = "performance_loaf";
320
327
  EMIT_TYPE2["XHR"] = "xhr";
321
328
  EMIT_TYPE2["FETCH"] = "fetch";
322
329
  EMIT_TYPE2["CUSTOM"] = "custom";
@@ -610,10 +617,8 @@ const PerformancePlugin = (options = {}) => {
610
617
  let context;
611
618
  let paintObserver = null;
612
619
  let lcpObserver = null;
613
- let inpObserver = null;
614
- let longTaskObserver = null;
615
620
  let resourceObserver = null;
616
- const interactionMap = /* @__PURE__ */ new Map();
621
+ let loafObserver = null;
617
622
  const monitorPaintMetrics = () => {
618
623
  const entryHandler = (list) => {
619
624
  for (const entry of list.getEntries()) {
@@ -657,63 +662,56 @@ const PerformancePlugin = (options = {}) => {
657
662
  console.warn("[CWJ Monitor] LCP observation not supported:", e);
658
663
  }
659
664
  };
660
- const monitorINP = () => {
665
+ const monitorLoAF = () => {
661
666
  const entryHandler = (list) => {
662
667
  for (const entry of list.getEntries()) {
663
- if (!entry.interactionId)
668
+ if (options.filter && !options.filter(EMIT_TYPE.PERFORMANCE_LOAF, entry)) {
664
669
  continue;
665
- const existing = interactionMap.get(entry.interactionId);
666
- if (existing) {
667
- clearTimeout(existing.timeoutId);
668
670
  }
669
- const maxEntry = existing && existing.entry.duration > entry.duration ? existing.entry : entry;
670
- const timeoutId = setTimeout(() => {
671
- interactionMap.delete(maxEntry.interactionId);
672
- if (options.filter && !options.filter(EMIT_TYPE.PERFORMANCE_INP, maxEntry)) {
673
- return;
671
+ const threshold = options.loafThreshold ?? DEFAULT_LOAF_THRESHOLD;
672
+ if (entry.duration > threshold) {
673
+ const scripts = Array.isArray(entry.scripts) ? entry.scripts : [];
674
+ let isUserTriggered = false;
675
+ let allIgnored = true;
676
+ for (let i = 0; i < scripts.length; i++) {
677
+ const s = scripts[i];
678
+ if (!s)
679
+ continue;
680
+ if (!isUserTriggered && s.invokerType === "user-callback")
681
+ isUserTriggered = true;
682
+ if (allIgnored && !isIgnoredScriptSource(s.sourceURL)) {
683
+ allIgnored = false;
684
+ }
685
+ if (isUserTriggered && !allIgnored)
686
+ break;
674
687
  }
675
- const threshold = options.inpThreshold ?? DEFAULT_INP_THRESHOLD;
676
- if (maxEntry.duration > threshold) {
677
- context?.emit(EMIT_TYPE.PERFORMANCE_INP, {
678
- value: maxEntry.duration,
679
- startTime: maxEntry.startTime,
680
- name: maxEntry.name,
681
- interactionId: maxEntry.interactionId
688
+ if (isUserTriggered && !allIgnored) {
689
+ context?.emit(EMIT_TYPE.PERFORMANCE_LOAF, {
690
+ duration: entry.duration,
691
+ startTime: entry.startTime,
692
+ renderStart: entry.renderStart,
693
+ styleAndLayoutStart: entry.styleAndLayoutStart,
694
+ hadRecentInput: entry.hadRecentInput,
695
+ scripts: entry.scripts.map((s) => ({
696
+ duration: s.duration,
697
+ invoker: s.invoker,
698
+ invokerType: s.invokerType,
699
+ sourceURL: s.sourceURL,
700
+ functionName: s.functionName,
701
+ sourceFunctionName: s.sourceFunctionName,
702
+ sourceCharPosition: s.sourceCharPosition,
703
+ startTime: s.startTime
704
+ }))
682
705
  });
683
706
  }
684
- }, 200);
685
- interactionMap.set(entry.interactionId, { entry: maxEntry, timeoutId });
686
- }
687
- };
688
- try {
689
- inpObserver = new PerformanceObserver(entryHandler);
690
- inpObserver.observe({ type: "event", buffered: true });
691
- } catch (e) {
692
- console.warn("[CWJ Monitor] INP observation not supported:", e);
693
- }
694
- };
695
- const monitorLongTask = () => {
696
- const entryHandler = (list) => {
697
- for (const entry of list.getEntries()) {
698
- if (options.filter && !options.filter(EMIT_TYPE.PERFORMANCE_LONGTASK, entry)) {
699
- continue;
700
- }
701
- const threshold = options.longTaskThreshold ?? DEFAULT_LONG_TASK_THRESHOLD;
702
- if (entry.duration > threshold) {
703
- context?.emit(EMIT_TYPE.PERFORMANCE_LONGTASK, {
704
- startTime: entry.startTime,
705
- duration: entry.duration,
706
- name: entry.name,
707
- attribution: entry.attribution
708
- });
709
707
  }
710
708
  }
711
709
  };
712
710
  try {
713
- longTaskObserver = new PerformanceObserver(entryHandler);
714
- longTaskObserver.observe({ type: "longtask", buffered: true });
711
+ loafObserver = new PerformanceObserver(entryHandler);
712
+ loafObserver.observe({ type: "long-animation-frame", buffered: true });
715
713
  } catch (e) {
716
- console.warn("[CWJ Monitor] Long Task observation not supported:", e);
714
+ console.warn("[CWJ Monitor] LoAF observation not supported:", e);
717
715
  }
718
716
  };
719
717
  const monitorResource = () => {
@@ -753,18 +751,14 @@ const PerformancePlugin = (options = {}) => {
753
751
  context = ctx;
754
752
  monitorPaintMetrics();
755
753
  monitorLCP();
756
- monitorINP();
757
- monitorLongTask();
758
754
  monitorResource();
755
+ monitorLoAF();
759
756
  },
760
757
  uninstall: () => {
761
758
  paintObserver?.disconnect();
762
759
  lcpObserver?.disconnect();
763
- inpObserver?.disconnect();
764
- longTaskObserver?.disconnect();
765
760
  resourceObserver?.disconnect();
766
- interactionMap.forEach((value) => clearTimeout(value.timeoutId));
767
- interactionMap.clear();
761
+ loafObserver?.disconnect();
768
762
  }
769
763
  };
770
764
  };