fluffy-log-trace-browser-sdk
v0.3.1
Published
Dependency-free browser logging SDK for Fluffy Log Trace.
Readme
fluffy-log-trace-browser-sdk
Fluffy Log Trace 的无运行时依赖浏览器日志 SDK。它将日志批量发送到 Fluffy Log Trace 的采集 API,适合以 ESM 方式接入 Vite、Vue、React、Angular 或原生前端项目。
安装
npm install fluffy-log-trace-browser-sdk也可使用 Yarn:
yarn add fluffy-log-trace-browser-sdkScript Tag 接入(无需构建工具)
无需模块打包工具,在 HTML 中嵌入以下代码即可:
<script>
(function(w,d,s,o){
w[s]=w[s]||function(){(w[s].q=w[s].q||[]).push(arguments)};
var t=d.createElement('script');t.async=1;t.src=o;
var y=d.getElementsByTagName('script')[0];y.parentNode.insertBefore(t,y);
})(window,document,'FluffyLog','/api/v1/sdk/fluffy-log.min.js');
</script>将 o 参数(最后一个)替换为 fluffy-log.min.js 的实际托管地址。随后在任何脚本中使用:
// 这些调用在 SDK 加载完成前会被排队,加载后自动回放
FluffyLog('init', {
appId: 'app_xxx',
apiBaseUrl: 'https://logs.example.com/api/v1',
credential: 'flt_pub_xxx',
environment: 'production',
});
FluffyLog('info', 'SDK injected', { version: '0.3.0' });
FluffyLog('warn', 'A warning message');
FluffyLog('error', new Error('something broke'));与 ESM 的区别:Script Tag 模式下通过 FluffyLog('methodName', ...args) 函数调用代替 FluffyLog.methodName(...args),两种方式在加载完成后完全等价。SDK 的 dist/fluffy-log.min.js 文件随 npm 包一并发布,可自行托管到 CDN 或静态目录。
快速接入
在应用入口尽早初始化,例如 main.ts、main.tsx:
import { FluffyLog } from 'fluffy-log-trace-browser-sdk';
FluffyLog.init({
appId: 'app_xxx',
apiBaseUrl: 'https://logs.example.com/api/v1',
credential: 'flt_pub_xxx',
environment: 'production',
});记录日志:
FluffyLog.debug('Loaded settings', { section: 'profile' });
FluffyLog.info('User signed in', { userId: 'user_123' });
FluffyLog.warn('Slow API response', { durationMs: 1800 });
FluffyLog.error(new Error('Payment request failed'), { orderId: 'order_123' });
FluffyLog.fatal('Application cannot continue', { reason: 'missing configuration' });需要在应用退出、测试或 SPA 生命周期节点等待当前日志发送完成时:
const result = await FluffyLog.flush();
await FluffyLog.shutdown();shutdown() 会先执行一次 flush(),随后停止当前 SDK 实例。重新初始化前必须先调用它。
本地前端直连生产 API
SDK 从 npm 安装不会改变浏览器请求的 Origin。假设本地前端运行在 http://localhost:3000,生产采集 API 为 https://logs.example.com/api/v1,初始化如下:
FluffyLog.init({
appId: 'app_xxx',
apiBaseUrl: 'https://logs.example.com/api/v1',
credential: 'flt_pub_local_test_xxx',
environment: 'development',
});生产服务端必须同时允许该 Origin:
- API 环境变量
CORS_ALLOWED_ORIGINS包含http://localhost:3000; - 此
browser_publishable凭据的allowedOrigins包含http://localhost:3000。
Origin 必须精确匹配协议、域名和端口。例如 http://localhost:3000、http://localhost:5173 与 http://127.0.0.1:3000 是不同 Origin。建议为本地联调创建单独凭据,并在测试完成后吊销。
配置
| 字段 | 必需 | 默认值 | 说明 |
| --- | --- | --- | --- |
| appId | 是 | — | Fluffy Log Trace 应用 ID。 |
| apiBaseUrl | 是 | — | 绝对 API URL,路径必须恰好为 /api/v1。 |
| credential | 是 | — | 对应应用的 browser_publishable 凭据。仅通过 Authorization 请求头发送。 |
| environment | 是 | — | 例如 development、staging、production。 |
| level | 否 | debug | 最低记录等级:debug、info、warn、error、fatal。 |
| bufferSize | 否 | 100 | 内存缓冲记录数,范围 1–500。满时丢弃最旧记录并触发发送。 |
| flushMaxBytes | 否 | 262144 | 单批未压缩字节上限,范围 1024–262144。 |
| timeout | 否 | 10000 | 单次请求超时毫秒数,范围 1–60000。 |
| autoCapture | 否 | none | 自动捕获模式:none(关闭)、error(自动捕获 error + warn 及未捕获异常)、full(全量捕获所有 console 日志及异常)。 |
| flushInterval | 否 | 5000 | 调度器自动刷出间隔毫秒数,范围 1000–30000。依赖 requestIdleCallback,不支持时降级为 MessageChannel。 |
| maxRetries | 否 | 3 | 单批失败后的额外重试次数,范围 0–10;超过后静默丢弃该批。 |
| retry.initialDelay | 否 | 1000 | 首次自动重试延迟毫秒数,范围 0–30000。 |
| retry.backoffFactor | 否 | 2 | 指数退避倍数,范围 1–10。 |
| retry.maxDelay | 否 | 30000 | 单次重试最大等待毫秒数,范围 0–120000。 |
| browserContext.enabled | 否 | true | 是否在 flush 时附加浏览器上下文。 |
| browserContext.includeUrl、includeUserAgent、includeScreen、includeViewport、includeLanguage、includeNetwork | 否 | true | 默认采集的浏览器字段。viewport 为 CSS 视口宽高;network 包含在线状态及浏览器支持时的粗粒度网络指标。 |
| browserContext.includeReferrer、includeTimezone | 否 | false | 默认关闭的可选浏览器字段。 |
| sanitize.deniedKeys | 否 | password、secret、token、authorization、cookie | 不区分大小写的 context 字段过滤列表。 |
| sanitize.stripQueryString | 否 | false | 移除 URL、异常 stack 和 context 中绝对 HTTP(S) URL 的查询参数。 |
| beforeSend | 否 | — | 每条记录发送前的转换钩子;返回 null 可丢弃该记录。核心元数据会被 SDK 保持。 |
完整示例:
FluffyLog.init({
appId: 'app_xxx',
apiBaseUrl: 'https://logs.example.com/api/v1',
credential: 'flt_pub_xxx',
environment: 'production',
level: 'info',
bufferSize: 100,
flushMaxBytes: 256 * 1024,
timeout: 10_000,
autoCapture: 'error', // 自动捕获 error + warn 级别及未捕获异常
flushInterval: 5000, // 每 5 秒调度一次自动刷出
sanitize: {
deniedKeys: ['password', 'accessToken', 'refreshToken'],
},
beforeSend(record) {
if (record.message.includes('health check')) return null;
return record;
},
});API
FluffyLog.log(level, message, context?);
FluffyLog.debug(message, context?);
FluffyLog.info(message, context?);
FluffyLog.warn(message, context?);
FluffyLog.error(message, context?);
FluffyLog.fatal(message, context?);
FluffyLog.flush();
FluffyLog.shutdown();message可以是字符串、Error或任意可序列化值;Error的 message 和 stack 会被提取。context是结构化对象。循环引用会替换为[Circular],最大递归深度为 4,最大大小为 4 KiB。- 单条 message 与 stack 最多保留 4096 个字符。
- SDK 产生的异常不会抛回宿主应用。
发送行为与安全边界
- 日志使用 NDJSON、UTF-8 和 Base64URL 构建 protocol v1 批次。
- v1 固定
encoding: 'none'、encryption: 'none',生产环境必须使用 HTTPS。 - 请求使用浏览器原生
fetch,带Authorization: Bearer <credential>和credentials: 'omit';凭据不会放入 URL、payload 或调试输出。 - error 与 fatal 在写入后立即请求异步上报;debug、info、warn 继续按缓冲上限、空闲调度及生命周期事件发送。立即上报不会并发或中断已有 fetch:已有请求完成后,高优先级批次优先获得下一个发送槽,并可越过正在退避的普通批次。
- HTTP
202表示服务端已接收批次;普通4xx立即丢弃,429、网络失败、超时和5xx会自动重试。高优先级与普通批次各自复用同一batchId,按指数退避加随机抖动调度;429优先采用受上限约束的Retry-After。 pagehide与visibilitychange(hidden)会优先对 keepalive 预算内的高优先级批次做一次携带 Authorization 的fetch(..., { keepalive: true })尝试;超预算或失败会静默放弃,不使用 sendBeacon、同步 XHR、URL token 或无认证降级。- 浏览器上下文在构建批次时附加到每条日志的
context.browser,默认包含 URL、UA、屏幕、CSS 视口、语言和在线状态;浏览器支持 Network Information API 时还会附加effectiveType、downlink、rtt、saveData。自动采集来源仍保留在顶层context.capture等字段,重试不会重新采集上下文。 - URL/referrer、UA、屏幕/视口、语言、timezone 与网络质量可能形成指纹;可通过
browserContext各字段开关关闭。SDK 不采集 IP、地理位置、运营商或网络事件历史。 - 内存缓冲不保证页面关闭、崩溃或刷新后的送达。
当前未提供的能力
以下能力仍在后续版本规划中,当前版本不可依赖:
globalThis.$log全局快捷方式;- gzip 压缩;
- protocol v2 应用层加密。
开发与发布
yarn workspace fluffy-log-trace-browser-sdk build
yarn workspace fluffy-log-trace-browser-sdk typecheck
yarn workspace fluffy-log-trace-browser-sdk test