@be-link/cls-logger 1.0.1-beta.20 → 1.0.1-beta.22

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/web.esm.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import * as tencentcloudClsSdkJsWeb from 'tencentcloud-cls-sdk-js-web';
2
+ import { onFCP, onLCP, onCLS, onINP, onTTFB } from 'web-vitals';
2
3
 
3
4
  function isPlainObject(value) {
4
5
  return Object.prototype.toString.call(value) === '[object Object]';
@@ -1433,14 +1434,10 @@ function getPagePath() {
1433
1434
  return '';
1434
1435
  }
1435
1436
  }
1436
- function reportMetric(report, reportType, metric, value, extra = {}) {
1437
- report(reportType, {
1438
- pagePath: getPagePath(),
1439
- metric,
1440
- value,
1441
- ...extra,
1442
- });
1443
- }
1437
+ /**
1438
+ * 安装浏览器性能监控
1439
+ * 使用 Google web-vitals 库实现 Core Web Vitals 指标采集
1440
+ */
1444
1441
  function installBrowserPerformanceMonitor(report, options) {
1445
1442
  if (typeof window === 'undefined')
1446
1443
  return;
@@ -1449,145 +1446,100 @@ function installBrowserPerformanceMonitor(report, options) {
1449
1446
  return;
1450
1447
  w.__beLinkClsLoggerPerfInstalled__ = true;
1451
1448
  const ignoreUrls = [...DEFAULT_IGNORE, ...(options.ignoreUrls ?? [])];
1452
- // Navigation timing: TTFB
1453
- if (options.navigationTiming) {
1449
+ // Web Vitals: 使用 Google web-vitals 库
1450
+ // 这个库会自动处理:
1451
+ // - LCP 在用户交互后停止观察
1452
+ // - firstHiddenTime 过滤(页面隐藏后的数据不计入)
1453
+ // - CLS 5秒会话窗口算法
1454
+ // - BFCache 恢复时自动重置指标
1455
+ if (options.webVitals) {
1456
+ // FCP
1454
1457
  try {
1455
- const navEntries = performance.getEntriesByType?.('navigation');
1456
- const nav = Array.isArray(navEntries) ? navEntries[0] : undefined;
1457
- if (nav && typeof nav === 'object') {
1458
- const ttfb = typeof nav.responseStart === 'number' && typeof nav.requestStart === 'number'
1459
- ? nav.responseStart - nav.requestStart
1460
- : -1;
1461
- if (ttfb >= 0 && sampleHit(options.sampleRate))
1462
- reportMetric(report, options.reportType, 'TTFB', ttfb, { unit: 'ms' });
1463
- }
1458
+ onFCP((metric) => {
1459
+ report(options.reportType, {
1460
+ pagePath: getPagePath(),
1461
+ metric: 'FCP',
1462
+ value: metric.value,
1463
+ unit: 'ms',
1464
+ rating: metric.rating,
1465
+ id: metric.id,
1466
+ navigationType: metric.navigationType,
1467
+ });
1468
+ });
1464
1469
  }
1465
1470
  catch {
1466
1471
  // ignore
1467
1472
  }
1468
- }
1469
- // Web Vitals: FCP/LCP/CLS/FID
1470
- if (options.webVitals && typeof globalThis.PerformanceObserver === 'function') {
1471
- // FCP
1473
+ // LCP(自动处理用户交互后停止)
1472
1474
  try {
1473
- const po = new PerformanceObserver((list) => {
1474
- try {
1475
- if (!sampleHit(options.sampleRate))
1476
- return;
1477
- for (const entry of list.getEntries()) {
1478
- if (entry?.name === 'first-contentful-paint' && typeof entry.startTime === 'number') {
1479
- reportMetric(report, options.reportType, 'FCP', entry.startTime, { unit: 'ms' });
1480
- }
1481
- }
1482
- }
1483
- catch {
1484
- // ignore
1485
- }
1475
+ onLCP((metric) => {
1476
+ report(options.reportType, {
1477
+ pagePath: getPagePath(),
1478
+ metric: 'LCP',
1479
+ value: metric.value,
1480
+ unit: 'ms',
1481
+ rating: metric.rating,
1482
+ id: metric.id,
1483
+ navigationType: metric.navigationType,
1484
+ });
1486
1485
  });
1487
- po.observe({ type: 'paint', buffered: true });
1488
1486
  }
1489
1487
  catch {
1490
1488
  // ignore
1491
1489
  }
1492
- // LCP(最后一次为准)
1493
- let lastLcp = null;
1490
+ // CLS(自动处理会话窗口)
1494
1491
  try {
1495
- const po = new PerformanceObserver((list) => {
1496
- try {
1497
- const entries = list.getEntries();
1498
- if (entries && entries.length)
1499
- lastLcp = entries[entries.length - 1];
1500
- }
1501
- catch {
1502
- // ignore
1503
- }
1492
+ onCLS((metric) => {
1493
+ report(options.reportType, {
1494
+ pagePath: getPagePath(),
1495
+ metric: 'CLS',
1496
+ value: metric.value,
1497
+ unit: 'score',
1498
+ rating: metric.rating,
1499
+ id: metric.id,
1500
+ navigationType: metric.navigationType,
1501
+ });
1504
1502
  });
1505
- po.observe({ type: 'largest-contentful-paint', buffered: true });
1506
- const flushLcp = () => {
1507
- try {
1508
- if (!lastLcp)
1509
- return;
1510
- if (!sampleHit(options.sampleRate))
1511
- return;
1512
- if (typeof lastLcp.startTime === 'number')
1513
- reportMetric(report, options.reportType, 'LCP', lastLcp.startTime, { unit: 'ms' });
1514
- lastLcp = null;
1515
- }
1516
- catch {
1517
- // ignore
1518
- }
1519
- };
1520
- window.addEventListener('pagehide', flushLcp, { once: true });
1521
- document.addEventListener('visibilitychange', () => {
1522
- if (document.visibilityState === 'hidden')
1523
- flushLcp();
1524
- }, { once: true });
1525
1503
  }
1526
1504
  catch {
1527
1505
  // ignore
1528
1506
  }
1529
- // CLS
1507
+ // INP(替代 FID,2024年3月起成为核心指标)
1530
1508
  try {
1531
- let clsValue = 0;
1532
- const po = new PerformanceObserver((list) => {
1533
- try {
1534
- for (const entry of list.getEntries()) {
1535
- if (entry && entry.hadRecentInput)
1536
- continue;
1537
- if (typeof entry.value === 'number')
1538
- clsValue += entry.value;
1539
- }
1540
- }
1541
- catch {
1542
- // ignore
1543
- }
1509
+ onINP((metric) => {
1510
+ report(options.reportType, {
1511
+ pagePath: getPagePath(),
1512
+ metric: 'INP',
1513
+ value: metric.value,
1514
+ unit: 'ms',
1515
+ rating: metric.rating,
1516
+ id: metric.id,
1517
+ navigationType: metric.navigationType,
1518
+ });
1544
1519
  });
1545
- po.observe({ type: 'layout-shift', buffered: true });
1546
- const flushCls = () => {
1547
- try {
1548
- if (!sampleHit(options.sampleRate))
1549
- return;
1550
- reportMetric(report, options.reportType, 'CLS', clsValue, { unit: 'score' });
1551
- }
1552
- catch {
1553
- // ignore
1554
- }
1555
- };
1556
- window.addEventListener('pagehide', flushCls, { once: true });
1557
- document.addEventListener('visibilitychange', () => {
1558
- if (document.visibilityState === 'hidden')
1559
- flushCls();
1560
- }, { once: true });
1561
1520
  }
1562
1521
  catch {
1563
1522
  // ignore
1564
1523
  }
1565
- // FID
1524
+ // TTFB
1566
1525
  try {
1567
- const po = new PerformanceObserver((list) => {
1568
- try {
1569
- if (!sampleHit(options.sampleRate))
1570
- return;
1571
- for (const entry of list.getEntries()) {
1572
- const startTime = typeof entry.startTime === 'number' ? entry.startTime : -1;
1573
- const processingStart = typeof entry.processingStart === 'number' ? entry.processingStart : -1;
1574
- if (startTime >= 0 && processingStart >= 0) {
1575
- reportMetric(report, options.reportType, 'FID', processingStart - startTime, { unit: 'ms' });
1576
- break;
1577
- }
1578
- }
1579
- }
1580
- catch {
1581
- // ignore
1582
- }
1526
+ onTTFB((metric) => {
1527
+ report(options.reportType, {
1528
+ pagePath: getPagePath(),
1529
+ metric: 'TTFB',
1530
+ value: metric.value,
1531
+ unit: 'ms',
1532
+ rating: metric.rating,
1533
+ id: metric.id,
1534
+ navigationType: metric.navigationType,
1535
+ });
1583
1536
  });
1584
- po.observe({ type: 'first-input', buffered: true });
1585
1537
  }
1586
1538
  catch {
1587
1539
  // ignore
1588
1540
  }
1589
1541
  }
1590
- // Resource timing:资源加载耗时
1542
+ // Resource timing:资源加载耗时(web-vitals 不包含此功能,保留原有实现)
1591
1543
  if (options.resourceTiming && typeof globalThis.PerformanceObserver === 'function') {
1592
1544
  try {
1593
1545
  const po = new PerformanceObserver((list) => {
@@ -1599,9 +1551,25 @@ function installBrowserPerformanceMonitor(report, options) {
1599
1551
  if (!name || shouldIgnoreUrl(name, ignoreUrls))
1600
1552
  continue;
1601
1553
  const initiatorType = String(entry?.initiatorType ?? '');
1602
- // 对齐文档:关注 fetch/xhr/img/script(同时允许 css/other 但不强制)
1554
+ // 关注 fetch/xhr/img/script(同时允许 css/other 但不强制)
1603
1555
  if (!['xmlhttprequest', 'fetch', 'img', 'script', 'css'].includes(initiatorType))
1604
1556
  continue;
1557
+ // 时序分解(便于定位慢在哪个阶段)
1558
+ const domainLookupStart = entry.domainLookupStart ?? 0;
1559
+ const domainLookupEnd = entry.domainLookupEnd ?? 0;
1560
+ const connectStart = entry.connectStart ?? 0;
1561
+ const connectEnd = entry.connectEnd ?? 0;
1562
+ const requestStart = entry.requestStart ?? 0;
1563
+ const responseStart = entry.responseStart ?? 0;
1564
+ const responseEnd = entry.responseEnd ?? 0;
1565
+ const dns = domainLookupEnd - domainLookupStart;
1566
+ const tcp = connectEnd - connectStart;
1567
+ const ttfb = responseStart - requestStart;
1568
+ const download = responseEnd - responseStart;
1569
+ // 缓存检测:transferSize=0 且 decodedBodySize>0 表示缓存命中
1570
+ const transferSize = entry.transferSize ?? 0;
1571
+ const decodedBodySize = entry.decodedBodySize ?? 0;
1572
+ const cached = transferSize === 0 && decodedBodySize > 0;
1605
1573
  const payload = {
1606
1574
  pagePath: getPagePath(),
1607
1575
  metric: 'resource',
@@ -1609,16 +1577,26 @@ function installBrowserPerformanceMonitor(report, options) {
1609
1577
  url: truncate$1(name, options.maxTextLength),
1610
1578
  startTime: typeof entry?.startTime === 'number' ? entry.startTime : undefined,
1611
1579
  duration: typeof entry?.duration === 'number' ? entry.duration : undefined,
1580
+ // 时序分解(跨域资源可能为 0)
1581
+ dns: dns > 0 ? Math.round(dns) : undefined,
1582
+ tcp: tcp > 0 ? Math.round(tcp) : undefined,
1583
+ ttfb: ttfb > 0 ? Math.round(ttfb) : undefined,
1584
+ download: download > 0 ? Math.round(download) : undefined,
1585
+ // 缓存标记
1586
+ cached,
1612
1587
  };
1613
- // 兼容字段(部分浏览器支持)
1614
- if (typeof entry?.transferSize === 'number')
1615
- payload.transferSize = entry.transferSize;
1616
- if (typeof entry?.encodedBodySize === 'number')
1588
+ // 尺寸字段(跨域资源可能为 0)
1589
+ if (transferSize > 0)
1590
+ payload.transferSize = transferSize;
1591
+ if (typeof entry?.encodedBodySize === 'number' && entry.encodedBodySize > 0) {
1617
1592
  payload.encodedBodySize = entry.encodedBodySize;
1618
- if (typeof entry?.decodedBodySize === 'number')
1619
- payload.decodedBodySize = entry.decodedBodySize;
1620
- if (typeof entry?.nextHopProtocol === 'string')
1593
+ }
1594
+ if (decodedBodySize > 0)
1595
+ payload.decodedBodySize = decodedBodySize;
1596
+ // 协议和状态
1597
+ if (typeof entry?.nextHopProtocol === 'string' && entry.nextHopProtocol) {
1621
1598
  payload.nextHopProtocol = entry.nextHopProtocol;
1599
+ }
1622
1600
  if (typeof entry?.responseStatus === 'number')
1623
1601
  payload.status = entry.responseStatus;
1624
1602
  report(options.reportType, payload);
@@ -1646,7 +1624,6 @@ function installWebPerformanceMonitor(report, opts = {}) {
1646
1624
  sampleRate: raw.sampleRate ?? 1,
1647
1625
  ignoreUrls: raw.ignoreUrls ?? [],
1648
1626
  webVitals: raw.webVitals ?? true,
1649
- navigationTiming: raw.navigationTiming ?? true,
1650
1627
  resourceTiming: raw.resourceTiming ?? true,
1651
1628
  maxTextLength: raw.maxTextLength ?? 2000,
1652
1629
  };
package/dist/web.js CHANGED
@@ -3,6 +3,7 @@
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var tencentcloudClsSdkJsWeb = require('tencentcloud-cls-sdk-js-web');
6
+ var webVitals = require('web-vitals');
6
7
 
7
8
  function _interopNamespaceDefault(e) {
8
9
  var n = Object.create(null);
@@ -1456,14 +1457,10 @@ function getPagePath() {
1456
1457
  return '';
1457
1458
  }
1458
1459
  }
1459
- function reportMetric(report, reportType, metric, value, extra = {}) {
1460
- report(reportType, {
1461
- pagePath: getPagePath(),
1462
- metric,
1463
- value,
1464
- ...extra,
1465
- });
1466
- }
1460
+ /**
1461
+ * 安装浏览器性能监控
1462
+ * 使用 Google web-vitals 库实现 Core Web Vitals 指标采集
1463
+ */
1467
1464
  function installBrowserPerformanceMonitor(report, options) {
1468
1465
  if (typeof window === 'undefined')
1469
1466
  return;
@@ -1472,145 +1469,100 @@ function installBrowserPerformanceMonitor(report, options) {
1472
1469
  return;
1473
1470
  w.__beLinkClsLoggerPerfInstalled__ = true;
1474
1471
  const ignoreUrls = [...DEFAULT_IGNORE, ...(options.ignoreUrls ?? [])];
1475
- // Navigation timing: TTFB
1476
- if (options.navigationTiming) {
1472
+ // Web Vitals: 使用 Google web-vitals 库
1473
+ // 这个库会自动处理:
1474
+ // - LCP 在用户交互后停止观察
1475
+ // - firstHiddenTime 过滤(页面隐藏后的数据不计入)
1476
+ // - CLS 5秒会话窗口算法
1477
+ // - BFCache 恢复时自动重置指标
1478
+ if (options.webVitals) {
1479
+ // FCP
1477
1480
  try {
1478
- const navEntries = performance.getEntriesByType?.('navigation');
1479
- const nav = Array.isArray(navEntries) ? navEntries[0] : undefined;
1480
- if (nav && typeof nav === 'object') {
1481
- const ttfb = typeof nav.responseStart === 'number' && typeof nav.requestStart === 'number'
1482
- ? nav.responseStart - nav.requestStart
1483
- : -1;
1484
- if (ttfb >= 0 && sampleHit(options.sampleRate))
1485
- reportMetric(report, options.reportType, 'TTFB', ttfb, { unit: 'ms' });
1486
- }
1481
+ webVitals.onFCP((metric) => {
1482
+ report(options.reportType, {
1483
+ pagePath: getPagePath(),
1484
+ metric: 'FCP',
1485
+ value: metric.value,
1486
+ unit: 'ms',
1487
+ rating: metric.rating,
1488
+ id: metric.id,
1489
+ navigationType: metric.navigationType,
1490
+ });
1491
+ });
1487
1492
  }
1488
1493
  catch {
1489
1494
  // ignore
1490
1495
  }
1491
- }
1492
- // Web Vitals: FCP/LCP/CLS/FID
1493
- if (options.webVitals && typeof globalThis.PerformanceObserver === 'function') {
1494
- // FCP
1496
+ // LCP(自动处理用户交互后停止)
1495
1497
  try {
1496
- const po = new PerformanceObserver((list) => {
1497
- try {
1498
- if (!sampleHit(options.sampleRate))
1499
- return;
1500
- for (const entry of list.getEntries()) {
1501
- if (entry?.name === 'first-contentful-paint' && typeof entry.startTime === 'number') {
1502
- reportMetric(report, options.reportType, 'FCP', entry.startTime, { unit: 'ms' });
1503
- }
1504
- }
1505
- }
1506
- catch {
1507
- // ignore
1508
- }
1498
+ webVitals.onLCP((metric) => {
1499
+ report(options.reportType, {
1500
+ pagePath: getPagePath(),
1501
+ metric: 'LCP',
1502
+ value: metric.value,
1503
+ unit: 'ms',
1504
+ rating: metric.rating,
1505
+ id: metric.id,
1506
+ navigationType: metric.navigationType,
1507
+ });
1509
1508
  });
1510
- po.observe({ type: 'paint', buffered: true });
1511
1509
  }
1512
1510
  catch {
1513
1511
  // ignore
1514
1512
  }
1515
- // LCP(最后一次为准)
1516
- let lastLcp = null;
1513
+ // CLS(自动处理会话窗口)
1517
1514
  try {
1518
- const po = new PerformanceObserver((list) => {
1519
- try {
1520
- const entries = list.getEntries();
1521
- if (entries && entries.length)
1522
- lastLcp = entries[entries.length - 1];
1523
- }
1524
- catch {
1525
- // ignore
1526
- }
1515
+ webVitals.onCLS((metric) => {
1516
+ report(options.reportType, {
1517
+ pagePath: getPagePath(),
1518
+ metric: 'CLS',
1519
+ value: metric.value,
1520
+ unit: 'score',
1521
+ rating: metric.rating,
1522
+ id: metric.id,
1523
+ navigationType: metric.navigationType,
1524
+ });
1527
1525
  });
1528
- po.observe({ type: 'largest-contentful-paint', buffered: true });
1529
- const flushLcp = () => {
1530
- try {
1531
- if (!lastLcp)
1532
- return;
1533
- if (!sampleHit(options.sampleRate))
1534
- return;
1535
- if (typeof lastLcp.startTime === 'number')
1536
- reportMetric(report, options.reportType, 'LCP', lastLcp.startTime, { unit: 'ms' });
1537
- lastLcp = null;
1538
- }
1539
- catch {
1540
- // ignore
1541
- }
1542
- };
1543
- window.addEventListener('pagehide', flushLcp, { once: true });
1544
- document.addEventListener('visibilitychange', () => {
1545
- if (document.visibilityState === 'hidden')
1546
- flushLcp();
1547
- }, { once: true });
1548
1526
  }
1549
1527
  catch {
1550
1528
  // ignore
1551
1529
  }
1552
- // CLS
1530
+ // INP(替代 FID,2024年3月起成为核心指标)
1553
1531
  try {
1554
- let clsValue = 0;
1555
- const po = new PerformanceObserver((list) => {
1556
- try {
1557
- for (const entry of list.getEntries()) {
1558
- if (entry && entry.hadRecentInput)
1559
- continue;
1560
- if (typeof entry.value === 'number')
1561
- clsValue += entry.value;
1562
- }
1563
- }
1564
- catch {
1565
- // ignore
1566
- }
1532
+ webVitals.onINP((metric) => {
1533
+ report(options.reportType, {
1534
+ pagePath: getPagePath(),
1535
+ metric: 'INP',
1536
+ value: metric.value,
1537
+ unit: 'ms',
1538
+ rating: metric.rating,
1539
+ id: metric.id,
1540
+ navigationType: metric.navigationType,
1541
+ });
1567
1542
  });
1568
- po.observe({ type: 'layout-shift', buffered: true });
1569
- const flushCls = () => {
1570
- try {
1571
- if (!sampleHit(options.sampleRate))
1572
- return;
1573
- reportMetric(report, options.reportType, 'CLS', clsValue, { unit: 'score' });
1574
- }
1575
- catch {
1576
- // ignore
1577
- }
1578
- };
1579
- window.addEventListener('pagehide', flushCls, { once: true });
1580
- document.addEventListener('visibilitychange', () => {
1581
- if (document.visibilityState === 'hidden')
1582
- flushCls();
1583
- }, { once: true });
1584
1543
  }
1585
1544
  catch {
1586
1545
  // ignore
1587
1546
  }
1588
- // FID
1547
+ // TTFB
1589
1548
  try {
1590
- const po = new PerformanceObserver((list) => {
1591
- try {
1592
- if (!sampleHit(options.sampleRate))
1593
- return;
1594
- for (const entry of list.getEntries()) {
1595
- const startTime = typeof entry.startTime === 'number' ? entry.startTime : -1;
1596
- const processingStart = typeof entry.processingStart === 'number' ? entry.processingStart : -1;
1597
- if (startTime >= 0 && processingStart >= 0) {
1598
- reportMetric(report, options.reportType, 'FID', processingStart - startTime, { unit: 'ms' });
1599
- break;
1600
- }
1601
- }
1602
- }
1603
- catch {
1604
- // ignore
1605
- }
1549
+ webVitals.onTTFB((metric) => {
1550
+ report(options.reportType, {
1551
+ pagePath: getPagePath(),
1552
+ metric: 'TTFB',
1553
+ value: metric.value,
1554
+ unit: 'ms',
1555
+ rating: metric.rating,
1556
+ id: metric.id,
1557
+ navigationType: metric.navigationType,
1558
+ });
1606
1559
  });
1607
- po.observe({ type: 'first-input', buffered: true });
1608
1560
  }
1609
1561
  catch {
1610
1562
  // ignore
1611
1563
  }
1612
1564
  }
1613
- // Resource timing:资源加载耗时
1565
+ // Resource timing:资源加载耗时(web-vitals 不包含此功能,保留原有实现)
1614
1566
  if (options.resourceTiming && typeof globalThis.PerformanceObserver === 'function') {
1615
1567
  try {
1616
1568
  const po = new PerformanceObserver((list) => {
@@ -1622,9 +1574,25 @@ function installBrowserPerformanceMonitor(report, options) {
1622
1574
  if (!name || shouldIgnoreUrl(name, ignoreUrls))
1623
1575
  continue;
1624
1576
  const initiatorType = String(entry?.initiatorType ?? '');
1625
- // 对齐文档:关注 fetch/xhr/img/script(同时允许 css/other 但不强制)
1577
+ // 关注 fetch/xhr/img/script(同时允许 css/other 但不强制)
1626
1578
  if (!['xmlhttprequest', 'fetch', 'img', 'script', 'css'].includes(initiatorType))
1627
1579
  continue;
1580
+ // 时序分解(便于定位慢在哪个阶段)
1581
+ const domainLookupStart = entry.domainLookupStart ?? 0;
1582
+ const domainLookupEnd = entry.domainLookupEnd ?? 0;
1583
+ const connectStart = entry.connectStart ?? 0;
1584
+ const connectEnd = entry.connectEnd ?? 0;
1585
+ const requestStart = entry.requestStart ?? 0;
1586
+ const responseStart = entry.responseStart ?? 0;
1587
+ const responseEnd = entry.responseEnd ?? 0;
1588
+ const dns = domainLookupEnd - domainLookupStart;
1589
+ const tcp = connectEnd - connectStart;
1590
+ const ttfb = responseStart - requestStart;
1591
+ const download = responseEnd - responseStart;
1592
+ // 缓存检测:transferSize=0 且 decodedBodySize>0 表示缓存命中
1593
+ const transferSize = entry.transferSize ?? 0;
1594
+ const decodedBodySize = entry.decodedBodySize ?? 0;
1595
+ const cached = transferSize === 0 && decodedBodySize > 0;
1628
1596
  const payload = {
1629
1597
  pagePath: getPagePath(),
1630
1598
  metric: 'resource',
@@ -1632,16 +1600,26 @@ function installBrowserPerformanceMonitor(report, options) {
1632
1600
  url: truncate$1(name, options.maxTextLength),
1633
1601
  startTime: typeof entry?.startTime === 'number' ? entry.startTime : undefined,
1634
1602
  duration: typeof entry?.duration === 'number' ? entry.duration : undefined,
1603
+ // 时序分解(跨域资源可能为 0)
1604
+ dns: dns > 0 ? Math.round(dns) : undefined,
1605
+ tcp: tcp > 0 ? Math.round(tcp) : undefined,
1606
+ ttfb: ttfb > 0 ? Math.round(ttfb) : undefined,
1607
+ download: download > 0 ? Math.round(download) : undefined,
1608
+ // 缓存标记
1609
+ cached,
1635
1610
  };
1636
- // 兼容字段(部分浏览器支持)
1637
- if (typeof entry?.transferSize === 'number')
1638
- payload.transferSize = entry.transferSize;
1639
- if (typeof entry?.encodedBodySize === 'number')
1611
+ // 尺寸字段(跨域资源可能为 0)
1612
+ if (transferSize > 0)
1613
+ payload.transferSize = transferSize;
1614
+ if (typeof entry?.encodedBodySize === 'number' && entry.encodedBodySize > 0) {
1640
1615
  payload.encodedBodySize = entry.encodedBodySize;
1641
- if (typeof entry?.decodedBodySize === 'number')
1642
- payload.decodedBodySize = entry.decodedBodySize;
1643
- if (typeof entry?.nextHopProtocol === 'string')
1616
+ }
1617
+ if (decodedBodySize > 0)
1618
+ payload.decodedBodySize = decodedBodySize;
1619
+ // 协议和状态
1620
+ if (typeof entry?.nextHopProtocol === 'string' && entry.nextHopProtocol) {
1644
1621
  payload.nextHopProtocol = entry.nextHopProtocol;
1622
+ }
1645
1623
  if (typeof entry?.responseStatus === 'number')
1646
1624
  payload.status = entry.responseStatus;
1647
1625
  report(options.reportType, payload);
@@ -1669,7 +1647,6 @@ function installWebPerformanceMonitor(report, opts = {}) {
1669
1647
  sampleRate: raw.sampleRate ?? 1,
1670
1648
  ignoreUrls: raw.ignoreUrls ?? [],
1671
1649
  webVitals: raw.webVitals ?? true,
1672
- navigationTiming: raw.navigationTiming ?? true,
1673
1650
  resourceTiming: raw.resourceTiming ?? true,
1674
1651
  maxTextLength: raw.maxTextLength ?? 2000,
1675
1652
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@be-link/cls-logger",
3
- "version": "1.0.1-beta.20",
3
+ "version": "1.0.1-beta.22",
4
4
  "description": "@be-link cls-logger - 腾讯云 CLS 日志上报封装",
5
5
  "homepage": "https://github.com/snowmountain-top/be-link",
6
6
  "author": "zhuiyi",
@@ -45,7 +45,8 @@
45
45
  ],
46
46
  "dependencies": {
47
47
  "tencentcloud-cls-sdk-js-web": "^1.0.11",
48
- "tencentcloud-cls-sdk-js-mini": "^1.0.3"
48
+ "tencentcloud-cls-sdk-js-mini": "^1.0.3",
49
+ "web-vitals": "^5.1.0"
49
50
  },
50
51
  "devDependencies": {
51
52
  "rimraf": "^5.0.0",