logger-sdk
v1.0.4
Published
日志系统 SDK - 客户端日志记录和上报工具
Maintainers
Readme
Logger SDK
一个轻量级的客户端日志记录和上报 SDK,支持 TypeScript。
特性
- 🚀 轻量级,无依赖(仅依赖必要的运行时库)
- 📝 支持多级别日志(DEBUG, INFO, WARN, ERROR, FATAL)
- 💾 本地存储日志(LocalStorage)
- 📤 日志上报(支持 ZIP 压缩)
- 🖼️ 支持附件上传(图片、视频、文件)
- 📸 支持截图功能
- 🪵 自动捕获全局错误
- 🌍 全局单例模式
- 💯 TypeScript 支持
- 🔄 自动重试 + 离线队列保障上报成功率
安装
npm install logger-sdk快速开始
import { Logger } from 'logger-sdk'
// 初始化配置
Logger.config({
appId: 'your-app-id',
serverUrl: 'https://your-api.com/api/reports',
apiKey: 'your-api-key'
})
// 记录日志
Logger.info('用户登录', { userId: '123' })
Logger.error('API 请求失败', { url: '/api/users', status: 500 })配置选项
Logger.config({
appId: string // 应用 ID
appVersion?: string // 应用版本(默认: '1.0.0')
userId?: string // 用户 ID
serverUrl?: string // 上报服务器地址(配置后启用上报)
apiKey?: string // API Key(上报时需要)
disableErrorCapture?: boolean // 是否禁用自动错误捕获(默认: false)
})API
日志方法
Logger.debug(message: string, data?: Record<string, any>)
Logger.info(message: string, data?: Record<string, any>)
Logger.warn(message: string, data?: Record<string, any>)
Logger.error(message: string, data?: Record<string, any>)
Logger.fatal(message: string, data?: Record<string, any>)其他方法
// 设置用户信息
Logger.setUserInfo(userId: string)
// 获取 Storage 实例
const storage = Logger.getStorage()
const logs = storage.getLogs()
// 获取 Reporter 实例(配置了 serverUrl 后可用)
const reporter = Logger.getReporter()
await reporter.report({
title: '问题标题',
type: 'bug',
description: '问题描述'
})日志上报
const reporter = Logger.getReporter()
// 上报日志(默认配置)
await reporter.report({
title: '问题标题',
type: 'bug', // 'bug' | 'feature' | 'experience' | 'other'
description: '详细描述',
days: 7 // 最近几天的日志
})
// 带选项的上报(重试、超时控制)
await reporter.report({
title: '问题标题',
type: 'bug',
description: '详细描述'
}, {
maxRetries: 3, // 最大重试次数(默认: 3)
retryDelay: 1000, // 重试延迟基数 ms(默认: 1000,指数退避)
timeout: 30000, // 请求超时时间 ms(默认: 30000)
enableOfflineQueue: true // 失败时加入离线队列(默认: true)
})
// 添加附件
await reporter.addImage(file)
await reporter.addVideo(file)
await reporter.addFile(file)
// 截图
await reporter.captureScreenshot()
// 清空附件
reporter.clearAttachments()可靠性保障
SDK 内置了多层机制确保上报成功:
- 自动重试 - 上报失败时自动重试(默认 3 次),使用指数退避策略
- 超时控制 - 使用 AbortController 防止请求长时间挂起
- 离线队列 - 失败的上报会存储在 localStorage 中,网络恢复时自动重试
- 响应验证 - 兼容多种后端响应格式,确保正确识别成功状态
// 查看离线队列状态
const status = reporter.getOfflineQueueStatus()
console.log(`待上报数量: ${status.size}`)
// 手动触发离线队列处理
await reporter.processOfflineQueue()
// 清空离线队列
reporter.clearOfflineQueue()服务端接口规范
如果你要接收 SDK 的上报数据,需要按照以下规范实现接口。
接口概览
| 属性 | 值 |
|------|-----|
| 请求方法 | POST |
| Content-Type | multipart/form-data |
| 认证方式 | Header: X-API-Key |
请求格式
Headers
Content-Type: multipart/form-data
X-API-Key: your-api-key-hereBody (multipart/form-data)
| 字段名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| appId | string | 是 | 应用标识 |
| appVersion | string | 是 | 应用版本号 |
| title | string | 是 | 上报标题 |
| type | string | 是 | 上报类型(bug/feature/experience/other) |
| description | string | 否 | 详细描述 |
| deviceId | string | 是 | 设备唯一标识 |
| deviceInfo | string | 是 | 设备信息(如:Windows / Chrome) |
| userAgent | string | 是 | 浏览器 User-Agent |
| url | string | 是 | 当前页面 URL |
| logs | File (.zip) | 是 | 日志压缩包(ZIP 格式) |
| attachments | File | 否 | 附件文件(可能有多个) |
响应格式
成功响应
{
"success": true,
"data": {
"reportId": "507f1f77bcf86cd799439011"
},
"message": "上报成功"
}或简化格式:
{
"success": true,
"reportId": "507f1f77bcf86cd799439011"
}SDK 会兼容以下响应格式:
success: true或code: 0或status: 'success'reportId可能在data.reportId、reportId、id或data.id中
错误响应
{
"success": false,
"message": "错误描述"
}HTTP 状态码建议:
200- 成功400- 请求参数错误401- API Key 无效413- 文件过大500- 服务器内部错误
后端实现示例
Node.js + formidable
import formidable from 'formidable'
export async function handler(req, res) {
// 1. 验证 API Key
const apiKey = req.headers['x-api-key']
if (apiKey !== process.env.API_KEY) {
return res.status(401).json({ success: false, message: 'Invalid API Key' })
}
// 2. 解析 multipart/form-data
const form = formidable({
maxFileSize: 50 * 1024 * 1024, // 50MB
multiples: true
})
const [fields, files] = await form.parse(req)
// 3. 提取字段
const appId = fields.appId?.[0]
const title = fields.title?.[0]
const type = fields.type?.[0]
const logsFile = files.logs?.[0]
// 4. 保存文件、存储到数据库...
// 5. 返回成功响应
return res.status(201).json({
success: true,
data: { reportId: '生成的上报ID' },
message: '上报成功'
})
}Express + multer
import multer from 'multer'
const upload = multer({
dest: 'uploads/',
limits: { fileSize: 50 * 1024 * 1024 }
})
app.post('/api/reports',
upload.fields([
{ name: 'logs', maxCount: 1 },
{ name: 'attachments', maxCount: 10 }
]),
(req, res) => {
const apiKey = req.headers['x-api-key']
const { appId, title, type } = req.body
const logsFile = req.files.logs?.[0]
const attachments = req.files.attachments || []
// ... 保存逻辑
res.json({
success: true,
data: { reportId: 'xxx' },
message: '上报成功'
})
}
)日志 ZIP 文件格式
ZIP 文件包含以下内容:
- 有日志时:包含一个或多个
logs.txt或logs_001.txt、logs_002.txt等文件 - 无日志时:包含
logs.txt,内容为No logs available
日志文件格式示例:
2025-02-19 10:30:45.123 INFO 用户登录 {"userId":"123"}
2025-02-19 10:30:50.456 ERROR API请求失败 {"url":"/api/users","status":500"}安全建议
- API Key 验证 - 务必验证
X-API-Key请求头 - 文件大小限制 - 限制单个文件大小(建议 50MB)
- 文件类型验证 - 检查文件扩展名和 MIME 类型
- 速率限制 - 防止滥发上报
- 文件清理 - 定期清理旧的日志文件
使用 cURL 测试
curl -X POST https://your-api.com/api/reports \
-H "X-API-Key: your-api-key" \
-F "appId=test-app" \
-F "appVersion=1.0.0" \
-F "title=测试上报" \
-F "type=bug" \
-F "description=测试描述" \
-F "deviceId=test-device-123" \
-F "deviceInfo=Windows / Chrome" \
-F "userAgent=Mozilla/5.0..." \
-F "url=https://example.com" \
-F "logs=@./test.zip"License
MIT
