@be-link/cls-logger
v1.0.13
Published
@be-link cls-logger - 腾讯云 CLS 日志上报封装
Readme
@be-link/cls-logger
腾讯云 CLS(tencentcloud-cls-sdk-js-web / tencentcloud-cls-sdk-js-mini)日志上报封装,支持 Web、H5 和小程序环境,提供统一的调用方式。
特性
- 自动环境适配(Web / H5 / 小程序)
- 内存队列批量上报,减少网络请求
- 页面关闭时
sendBeacon保证日志不丢失 - 支持浏览器空闲时上报(
requestIdleCallback) - 错误即时上报,信息日志批量上报
- 自动采集:请求监控、性能监控、错误监控、行为埋点
- 失败重试 + 本地缓存兜底
安装
pnpm add @be-link/cls-logger依赖说明
| 入口 | 依赖 | 说明 |
| -------------------------- | -------------------------------------------- | ----------------------------------- |
| @be-link/cls-logger | tencentcloud-cls-sdk-js-web | 统一入口,自动适配环境 |
| @be-link/cls-logger/web | tencentcloud-cls-sdk-js-web + web-vitals | Web/H5 专用,含 Web Vitals 性能监控 |
| @be-link/cls-logger/mini | tencentcloud-cls-sdk-js-mini | 小程序专用 |
注意:所有依赖已内置,无需手动安装。
快速开始
1. 统一引入方式(推荐快速接入)
import clsLogger from '@be-link/cls-logger';
clsLogger.init({
projectId: 'my-project',
appId: 'my-app-id',
source: 'my-source',
});2. 分环境引入方式(推荐生产环境)
Web / H5:
import { clsLogger } from '@be-link/cls-logger/web';
clsLogger.init({
projectId: 'my-web-project',
source: 'web-source',
});小程序:
import { clsLogger } from '@be-link/cls-logger/mini';
clsLogger.init({
projectId: 'my-mini-project',
appId: 'wx123456789',
source: 'mini-source',
});API
日志方法
// 信息日志(走批量队列)
clsLogger.info('应用启动', { startUpTime: 120 });
// 警告日志(走批量队列)
clsLogger.warn('资源加载慢', { duration: 3000 });
// 错误日志(默认即时上报)
clsLogger.error('支付失败', { orderId: '123' });
// Error 对象(自动解析堆栈)
try {
doSomething();
} catch (err) {
clsLogger.error(err, { module: 'payment' });
}即时上报选项
// info/warn 强制即时上报
clsLogger.info('重要事件', { data: 1 }, { immediate: true });
// error 走批量队列(默认是即时上报)
clsLogger.error('非关键错误', { data: 1 }, { immediate: false });自定义埋点
clsLogger.track('click_event', {
button: 'submit',
page: '/home',
});统计埋点
clsLogger.stat({
pageName: '首页',
scene: '入口',
subScene: '活动弹窗',
data: 1,
});配置项
完整配置示例
clsLogger.init({
// 基础配置
enabled: true, // 是否启用,默认 true
projectId: 'my-project', // 项目标识
appId: 'wx123456789', // 应用 ID(小程序必填)
appVersion: '1.0.0', // 应用版本
source: 'my-source', // CLS source
// 腾讯云 CLS 配置
tencentCloud: {
endpoint: 'https://ap-shanghai.cls.tencentcs.com',
topicID: 'your-topic-id',
retry_times: 3,
},
// 批量上报配置
batch: {
maxSize: 50, // 队列达到此数量立即发送,默认 20
intervalMs: 1000, // 定时批量发送间隔,默认 500ms
startupDelayMs: 3000, // 启动合并窗口,默认 0(不启用)
startupMaxSize: 500, // 启动窗口内的队列阈值,默认 maxSize*10(至少200)
useIdleCallback: true, // 使用浏览器空闲时间上报,默认 false
idleTimeout: 3000, // 空闲回调超时时间,默认 3000ms
},
// 请求监控配置
requestMonitor: {
enabled: true, // 是否开启,默认 true
sampleRate: 1, // 采样率 0~1,默认 1
ignoreUrls: [/localhost/], // 忽略的 URL
includeMethod: true, // 是否携带 method,默认 true
includeQuery: true, // 是否携带 query,默认 true
includeBody: true, // 是否携带 body,默认 true
maxParamLength: 2000, // 参数最大长度,默认 2000
},
// 错误监控配置
errorMonitor: {
enabled: true, // 是否开启,默认 true
sampleRate: 1, // 采样率 0~1,默认 1
captureResourceError: true, // 是否采集资源加载错误,默认 true
maxTextLength: 4000, // stack/message 最大长度,默认 4000
dedupeWindowMs: 3000, // 错误去重窗口,默认 3000ms
dedupeMaxKeys: 200, // 去重缓存最大 key 数,默认 200
ignoreMessages: [
// 忽略的错误信息(默认值)
'Script error.',
'Script error',
/^ResizeObserver loop/,
'Permission was denied',
],
},
// 性能监控配置
performanceMonitor: {
enabled: true, // 是否开启,默认 true
sampleRate: 1, // 采样率 0~1,默认 1
webVitals: true, // 是否采集 Web Vitals(含 TTFB),默认 true
resourceTiming: true, // 是否采集资源加载耗时,默认 true
ignoreUrls: [/localhost/], // 忽略的资源 URL
maxTextLength: 2000, // 性能指标文本最大长度,默认 2000
},
// 行为埋点配置
behaviorMonitor: {
enabled: true, // 是否开启,默认 true
pv: true, // PV 是否开启,默认 true
uv: true, // UV 是否开启,默认 true
click: true, // 点击是否开启,默认 true
sampleRate: 1, // 采样率 0~1,默认 1
uvExpireDays: 30, // UV 标识过期天数,默认 30
clickTrackIdAttr: 'data-track-id', // 点击元素埋点标识属性名
clickMaxTextLength: 120, // 点击文本最大长度,默认 120
},
// 设备信息配置
deviceInfo: {
enabled: true, // 是否开启,默认 true
includeUserAgent: true, // 是否包含 UA,默认 true
includeNetwork: true, // 是否包含网络信息,默认 true
},
// 自定义基础字段
generateBaseFields: () => ({
userId: getUserId(),
userName: getUserName(),
environment: 'production',
}),
});常见场景配置
场景 1:首屏请求过多
页面首次加载时日志请求过多,影响其他请求:
clsLogger.init({
batch: {
startupDelayMs: 3000, // 启动 3 秒内的日志合并发送
startupMaxSize: 500, // 启动窗口内允许更多日志积累(防止 maxSize 打断合并)
maxSize: 100, // 正常运行时的队列阈值
intervalMs: 2000, // 延长批量间隔
useIdleCallback: true, // 等待延迟后在浏览器空闲时上报
},
performanceMonitor: {
resourceTiming: false, // 关闭资源监控(首屏资源多时可大幅减少日志量)
},
});说明:
startupMaxSize确保启动窗口内不会因为maxSize被频繁触发而打断日志合并。
场景 2:减少资源监控日志
开发环境资源过多,或生产环境不需要全量资源监控:
clsLogger.init({
performanceMonitor: {
resourceTiming: false, // 关闭资源监控
// 或者采样
// sampleRate: 0.1, // 10% 采样
// 或者过滤
// ignoreUrls: [/localhost/, /node_modules/],
},
});场景 3:过滤无意义的错误
过滤第三方 SDK 的跨域错误:
clsLogger.init({
errorMonitor: {
ignoreMessages: [
// 默认规则
'Script error.',
'Script error',
/^ResizeObserver loop/,
'Permission was denied',
// 自定义规则
/火山SDK/,
/VolcEngine/,
/network error/i,
],
},
});场景 4:高并发场景(直播间)
clsLogger.init({
batch: {
startupDelayMs: 3000, // 启动合并窗口
startupMaxSize: 500, // 启动窗口内的队列阈值
maxSize: 100, // 正常运行时的队列阈值
intervalMs: 2000, // 延长批量间隔
useIdleCallback: true, // 空闲时上报,不阻塞主线程
},
performanceMonitor: {
resourceTiming: false, // 关闭资源监控
},
requestMonitor: {
sampleRate: 0.1, // 请求监控采样 10%
ignoreUrls: [
/heartbeat/i, // 忽略心跳请求
/polling/i, // 忽略轮询请求
/danmaku|barrage/i, // 忽略弹幕请求
],
},
});最佳实践
1. 批量配置的正确姿势
useIdleCallback 工作原理
当 useIdleCallback: true 时,SDK 的上报流程为:
日志产生 → 等待 intervalMs/startupDelayMs → 等待浏览器空闲 → 发送
↑ 最小等待时间 ↑ 在 idleTimeout 内空闲就发送关键点:
intervalMs/startupDelayMs是最小等待时间,保证不会过早发送idleTimeout是空闲等待的最大时间,防止浏览器一直繁忙导致日志积压
startupMaxSize 的作用
启动阶段(startupDelayMs 窗口内)日志量通常很大(性能指标、资源加载等),如果 maxSize 设置过小,会频繁触发队列满而打断合并:
// ❌ 错误配置:startupDelayMs 会被 maxSize 打断
batch: {
startupDelayMs: 3000,
maxSize: 20, // 启动期间可能产生 200+ 条日志,会触发 10+ 次发送
}
// ✅ 正确配置:使用 startupMaxSize 保护启动窗口
batch: {
startupDelayMs: 3000,
maxSize: 20,
startupMaxSize: 500, // 启动期间允许更多日志积累
}2. 推荐配置模板
普通 H5 页面
clsLogger.init({
batch: {
startupDelayMs: 2000,
startupMaxSize: 300,
maxSize: 50,
intervalMs: 1000,
useIdleCallback: true,
idleTimeout: 3000,
},
});首屏性能敏感(电商、活动页)
clsLogger.init({
batch: {
startupDelayMs: 5000, // 更长的启动窗口
startupMaxSize: 500,
maxSize: 100,
intervalMs: 2000,
useIdleCallback: true,
idleTimeout: 5000,
},
performanceMonitor: {
sampleRate: 0.3, // 性能监控采样
},
});高频交互页面(直播间、游戏)
clsLogger.init({
batch: {
startupDelayMs: 3000,
startupMaxSize: 500,
maxSize: 100,
intervalMs: 3000, // 更长的间隔
useIdleCallback: true,
idleTimeout: 5000,
},
performanceMonitor: {
resourceTiming: false, // 关闭资源监控
},
requestMonitor: {
sampleRate: 0.1, // 请求监控采样
ignoreUrls: [/heartbeat/, /polling/, /danmaku/],
},
});3. 日志量优化技巧
| 优化项 | 配置 | 效果 |
| ------------ | ------------------------------------------ | ------------------------- |
| 关闭资源监控 | performanceMonitor.resourceTiming: false | 减少 80%+ 的 perf 日志 |
| 性能采样 | performanceMonitor.sampleRate: 0.1 | 只采集 10% 用户的性能数据 |
| 请求采样 | requestMonitor.sampleRate: 0.1 | 只采集 10% 的请求日志 |
| 忽略高频请求 | requestMonitor.ignoreUrls: [/heartbeat/] | 过滤心跳等高频请求 |
| 错误去重 | errorMonitor.dedupeWindowMs: 5000 | 5秒内相同错误只上报一次 |
4. 常见问题排查
问题:首屏请求过多
现象:页面加载时发出 10+ 个日志请求
排查步骤:
- 检查
startupDelayMs是否配置 - 检查
startupMaxSize是否足够大(建议 300-500) - 检查
resourceTiming是否需要开启(这是日志量最大的来源)
问题:日志延迟过高
现象:日志上报明显滞后
排查步骤:
- 检查
useIdleCallback+idleTimeout配置 - 检查
intervalMs是否设置过大 - 考虑关闭
useIdleCallback或减小idleTimeout
问题:页面关闭丢日志
现象:用户快速关闭页面时日志丢失
说明:SDK 已通过 sendBeacon 处理此场景,如仍有丢失:
- 检查日志是否在
memoryQueue中(可能还未触发 flush) - 考虑对关键日志使用
{ immediate: true }
功能说明
1. 批量上报机制
SDK 使用内存队列批量上报日志:
| 触发条件 | 说明 |
| -------- | ------------------------------------------------------- |
| 队列满 | 达到 maxSize(启动窗口内为 startupMaxSize)立即发送 |
| 定时器 | 每 intervalMs 毫秒发送一次 |
| 页面关闭 | visibilitychange + pagehide 触发 sendBeacon 发送 |
| 启动合并 | startupDelayMs 窗口内的日志尽量合并 |
| 空闲上报 | useIdleCallback 开启时,等待浏览器空闲后发送 |
2. 即时上报 vs 批量上报
| 方法 | 默认行为 | 说明 |
| --------- | -------- | -------------------------------------------------------- |
| error() | 即时上报 | 错误需要及时发现,可通过 { immediate: false } 改为批量 |
| info() | 批量上报 | 可通过 { immediate: true } 改为即时 |
| warn() | 批量上报 | 可通过 { immediate: true } 改为即时 |
| track() | 批量上报 | - |
3. 页面关闭保障
页面关闭时(visibilitychange / pagehide),SDK 会:
- 使用
navigator.sendBeacon同步发送队列中的日志 - 如果
sendBeacon不可用,将日志缓存到本地存储 - 下次启动时自动重试发送缓存的日志
4. 失败重试机制
- 上报失败后使用指数退避算法重试
- 多次重试仍失败,日志落盘到本地缓存
- 下次应用启动时自动尝试重新上报
- 本地缓存最多保留 200 条(可配置
failedCacheMax)
5. 自动采集内容
请求监控
- Web: 拦截
fetch/XMLHttpRequest - 小程序: 拦截
wx.request/wx.cloud.callFunction
性能监控
- Web: 使用 Google web-vitals 库实现
- FCP (First Contentful Paint): 首次内容渲染
- LCP (Largest Contentful Paint): 最大内容渲染(用户交互后自动停止)
- CLS (Cumulative Layout Shift): 累积布局偏移(5秒会话窗口算法)
- INP (Interaction to Next Paint): 交互到绘制延迟(替代 FID)
- TTFB (Time to First Byte): 首字节时间
- 资源加载耗时: PerformanceResourceTiming
- 自动处理 BFCache 恢复时的指标重置
- 上报数据包含
rating字段:'good'|'needs-improvement'|'poor'
- 小程序: 首屏渲染、路由切换、启动耗时
错误监控
- Web:
window.onerror,unhandledrejection, 资源加载错误 - 小程序:
wx.onError,wx.onUnhandledRejection,App.onError
行为埋点
- PV: 页面访问
- UV: 用户访问(自动生成持久化 ID)
- 点击: 带
data-track-id属性的元素点击
手动注入 SDK
在某些特殊构建环境下,可以手动注入 SDK:
import { clsLogger } from '@be-link/cls-logger/mini';
import * as MiniSdk from 'tencentcloud-cls-sdk-js-mini';
clsLogger.init({
tencentCloud: { topicID: 'xxx', endpoint: 'xxx' },
sdk: MiniSdk,
});类型定义
import type {
ClsLoggerInitOptions,
BatchOptions,
ReportOptions,
RequestMonitorOptions,
ErrorMonitorOptions,
PerformanceMonitorOptions,
BehaviorMonitorOptions,
DeviceInfoOptions,
} from '@be-link/cls-logger';License
MIT
