StreamSight 是一个基于 TypeScript 的用户行为录制与回放系统,采用 Monorepo 架构,支持高效的事件采集、压缩存储和安全回放。
- Node.js >= 18.0.0
- pnpm >= 8.0.0
# 方式一:使用安装脚本(推荐)
./scripts/setup.sh
# 方式二:手动安装
pnpm install
pnpm build- 启动后端服务
pnpm backend
# 或者
pnpm --filter @streamsight/backend-api dev- 启动演示应用
pnpm demo
# 或者
pnpm --filter @streamsight/demo-app dev- 启动回放平台
pnpm replay
# 或者
pnpm --filter @streamsight/replay-platform dev- 一键启动所有服务
pnpm e2e- 打开演示应用:http://localhost:5174
- 在页面上进行各种操作(点击、输入、滚动等)
- 点击"停止录制"按钮
- 打开回放平台:http://localhost:3000
- 查看录制的会话并播放
- 在浏览器中打开
test-simple.html - 点击"开始录制"
- 进行各种操作(输入、点击等)
- 查看浏览器控制台的日志输出
- 后端会接收并存储录制数据
✅ 已完成功能:
- Monorepo 项目结构搭建
- 核心 SDK 基础框架
- 事件批次处理逻辑
- Web Worker 压缩桥接
- 后端 API 服务(支持本地文件和 MySQL 存储)
- 简单测试页面验证
- rrweb 类型定义冲突,暂时禁用了 DOM 增强插件
- 部分 TypeScript 类型需要进一步优化
- 回放平台需要完善 rrweb-player 集成
🔧 快速修复建议:
- 使用
test-simple.html验证基础录制功能 - 后续可以逐步完善 rrweb 集成
- 优化 TypeScript 类型定义
streamsight/
├── apps/
│ ├── replay-platform/ # Next.js 回放查看器
│ └── demo-app/ # 演示应用
├── packages/
│ ├── streamsight/ # 核心 SDK (streamsight)
│ ├── core-utils/ # 共享工具 (streamsight-core-utils)
│ └── backend-api/ # 后端 API (@streamsight/backend-api)
import { init, start, stop } from 'streamsight'
// 初始化
const recorder = init({
appId: 'my-app',
apiEndpoint: 'http://localhost:3001',
userId: 'user-123',
})
// 开始录制
await start()
// 停止录制
stop()import { init } from 'streamsight'
const recorder = init({
appId: 'my-app',
apiEndpoint: 'http://localhost:3001',
userId: 'user-123',
// 批次配置
batchSize: 80, // 每批事件数量
batchTimeout: 30000, // 批次超时时间(毫秒)
// 脱敏配置
privacy: {
maskSelectors: ['.oo-mask', '.sensitive'],
blockSelectors: ['.oo-block', '.private'],
maskAllInputs: false,
maskPasswords: true,
},
// 压缩配置
compression: {
type: 'gzip', // 'gzip' | 'zstd'
level: 6,
},
// 网络配置
network: {
retryCount: 3,
retryDelay: 1000,
},
})SDK 支持多种脱敏策略:
-
CSS 类名脱敏
<!-- 文本遮盖 --> <span class="oo-mask">敏感信息</span> <!-- 元素阻止 --> <div class="oo-block">私密内容</div>
-
自动模式识别
- 信用卡号:
4111-1111-1111-1111 - 邮箱地址:
user@example.com - 手机号码:
13812345678 - 身份证号:
110101199001011234
- 信用卡号:
-
表单输入脱敏
<!-- 密码输入默认遮盖 --> <input type="password" /> <!-- 自定义遮盖 --> <input class="oo-mask" type="text" />
// 初始化 SDK
init(config: StreamsightConfig): StreamsightRecorder
// 开始录制
start(): Promise<void>
// 停止录制
stop(): void
// 刷新当前批次
flush(): Promise<void>
// 设置用户信息
setUser(userId: string, meta?: Record<string, any>): void
// 添加遮盖选择器
addMaskSelector(selector: string): void
// 添加阻止选择器
addIgnoreSelector(selector: string): void默认使用本地文件存储,数据保存在 packages/backend-api/data/ 目录:
# 使用默认配置
pnpm backend- 准备 MySQL 数据库
CREATE DATABASE streamsight CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'streamsight'@'localhost' IDENTIFIED BY 'your_password';
GRANT ALL PRIVILEGES ON streamsight.* TO 'streamsight'@'localhost';
FLUSH PRIVILEGES;- 配置环境变量
# 编辑 packages/backend-api/.env
USE_MYSQL=true
MYSQL_HOST=localhost
MYSQL_PORT=3306
MYSQL_USER=streamsight
MYSQL_PASSWORD=your_password
MYSQL_DATABASE=streamsight- 启动服务
pnpm backend数据库表会自动创建,包括:
replay_metadata: 回放元数据replay_data: 回放二进制数据
默认使用 fflate 库进行 gzip 压缩:
// packages/core-utils/src/compression.ts
import { gzip, gunzip } from 'fflate'- 安装 zstd-wasm
pnpm add zstd-wasm- 更新压缩适配器
// packages/core-utils/src/compression.ts
import { compress as zstdCompress, decompress as zstdDecompress } from 'zstd-wasm'
// 在 CompressionAdapter 类中添加
private static async compressZstd(data: Uint8Array, level: number): Promise<ArrayBuffer> {
const compressed = await zstdCompress(data, level)
return compressed.buffer
}
private static async decompressZstd(data: Uint8Array): Promise<string> {
const decompressed = await zstdDecompress(data)
const decoder = new TextDecoder()
return decoder.decode(decompressed)
}- 更新支持检测
static isZstdSupported(): boolean {
try {
require('zstd-wasm')
return true
} catch {
return false
}
}| 压缩方案 | 压缩率 | 压缩速度 | 解压速度 | 浏览器支持 |
|---|---|---|---|---|
| gzip | 中等 | 快 | 快 | 优秀 |
| zstd | 优秀 | 很快 | 很快 | 需要 WASM |
- 默认遮盖密码输入
- 支持自定义遮盖规则
- 自动识别敏感信息模式
- 支持元素级别的阻止采集
- 移除所有
<script>标签的可执行内容 - 阻止回放时的真实页面跳转
- 使用 iframe sandbox 隔离回放环境
- 支持用户级别的访问控制
- 会话级别的数据隔离
- API 密钥认证(生产环境)
- 用户同意:在开始录制前获得用户明确同意
- 数据保留:设置合理的数据保留期限
- 访问审计:记录所有回放访问日志
- 数据加密:生产环境使用 HTTPS 和数据库加密
- 隐私政策:更新隐私政策说明数据收集用途
# 构建所有包
pnpm build
# 构建特定包
pnpm --filter streamsight build# 运行所有测试
pnpm test
# 运行特定包测试
pnpm --filter streamsight test# 运行 ESLint
pnpm lint
# 类型检查
pnpm type-check# 发布到 npm
pnpm publish-packages- ✅ 基于 rrweb 的 DOM 快照与增量事件
- ✅ MutationObserver 监听 DOM 变化
- ✅ 事件批次处理(默认 80 条/批)
- ✅ Web Worker 压缩处理
- ✅ 脱敏规则支持(
.oo-mask/.oo-block) - ✅ 相对 URL 转绝对 URL
- ✅ 脚本内容清理
- ✅ 表单输入值处理
- ✅ 网络重试与离线队列
- ✅ iframe sandbox 安全回放
- ⏳ ZSTD 压缩支持
- ⏳ Canvas 录制支持
- ⏳ 移动端适配
- ⏳ 实时流式传输
- ⏳ 高级权限控制
- ⏳ 数据库存储后端
- ⏳ 回放性能优化
- Fork 项目
- 创建特性分支:
git checkout -b feature/amazing-feature - 提交更改:
git commit -m 'Add amazing feature' - 推送分支:
git push origin feature/amazing-feature - 提交 Pull Request
MIT License - 详见 LICENSE 文件
注意:这是一个 MVP 版本,主要用于概念验证和快速原型开发。生产环境使用前请进行充分的安全评估和性能测试。