1438 行
40 KiB
Markdown
1438 行
40 KiB
Markdown
|
|
# BugCollect API v1 规范
|
|||
|
|
|
|||
|
|
> **版本**:1.1.0
|
|||
|
|
> **日期**:2026-06-17
|
|||
|
|
> **状态**:Draft
|
|||
|
|
> **设计参考**:[Sentry Event Payloads](https://develop.sentry.dev/sdk/event-payloads/)
|
|||
|
|
> **服务端模块**:`xuqm-bugcollect-service`
|
|||
|
|
> **基础路径**:`/bugcollect/v1`
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 目录
|
|||
|
|
|
|||
|
|
1. [概述](#1-概述)
|
|||
|
|
2. [术语表](#2-术语表)
|
|||
|
|
3. [认证与安全](#3-认证与安全)
|
|||
|
|
4. [数据上报端点](#4-数据上报端点)
|
|||
|
|
- 4.1 [Issue 批量上报](#41-issue-批量上报)
|
|||
|
|
- 4.2 [Event 批量上报](#42-event-批量上报)
|
|||
|
|
- 4.3 [SourceMap / 符号文件上传](#43-sourcemap--符号文件上传)
|
|||
|
|
- 4.4 [Session 上报](#44-session-上报)
|
|||
|
|
5. [数据模型](#5-数据模型)
|
|||
|
|
- 5.1 [批量信封 Envelope](#51-批量信封-envelope)
|
|||
|
|
- 5.2 [IssueEvent](#52-issueevent)
|
|||
|
|
- 5.3 [LogEvent](#53-logevent)
|
|||
|
|
- 5.4 [Breadcrumb](#54-breadcrumb)
|
|||
|
|
- 5.5 [枚举定义](#55-枚举定义)
|
|||
|
|
6. [查询端点](#6-查询端点)
|
|||
|
|
- 6.1 [Issue 列表](#61-issue-列表)
|
|||
|
|
- 6.2 [Issue 详情](#62-issue-详情)
|
|||
|
|
- 6.3 [Issue 事件列表](#63-issue-事件列表)
|
|||
|
|
- 6.4 [Issue 趋势](#64-issue-趋势)
|
|||
|
|
- 6.5 [Event 列表](#65-event-列表)
|
|||
|
|
- 6.6 [概览统计](#66-概览统计)
|
|||
|
|
- 6.7 [频率排行](#67-频率排行)
|
|||
|
|
- 6.8 [风险排行](#68-风险排行)
|
|||
|
|
- 6.9 [漏斗分析](#69-漏斗分析)
|
|||
|
|
7. [Issue 管理端点](#7-issue-管理端点)
|
|||
|
|
- 7.1 [解决 Issue](#71-解决-issue)
|
|||
|
|
- 7.2 [忽略 Issue](#72-忽略-issue)
|
|||
|
|
- 7.3 [分配责任人](#73-分配责任人)
|
|||
|
|
- 7.4 [批量操作](#74-批量操作)
|
|||
|
|
8. [Webhook](#8-webhook)
|
|||
|
|
9. [错误码](#9-错误码)
|
|||
|
|
10. [Fingerprint 去重机制](#10-fingerprint-去重机制)
|
|||
|
|
11. [SDK 集成指南](#11-sdk-集成指南)
|
|||
|
|
12. [数据库 Schema](#12-数据库-schema)
|
|||
|
|
13. [变更日志](#13-变更日志)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 1. 概述
|
|||
|
|
|
|||
|
|
BugCollect 是一个轻量级错误收集与分析服务,设计目标对齐 [Sentry](https://sentry.io) 核心能力,为 XuqmGroup 全平台 SDK(Android、iOS、HarmonyOS、React Native、Web)提供统一的错误上报、聚合、查询和告警能力。
|
|||
|
|
|
|||
|
|
### 核心能力
|
|||
|
|
|
|||
|
|
| 能力 | 说明 |
|
|||
|
|
|------|------|
|
|||
|
|
| **Issue 聚合** | 按 fingerprint 自动去重,将同类错误聚合为 Issue |
|
|||
|
|
| **Event 追踪** | 每次错误发生记录独立 Event,保留完整上下文和面包屑 |
|
|||
|
|
| **Analytics 事件** | 自定义业务事件上报,支持漏斗分析 |
|
|||
|
|
| **Session 追踪** | 会话生命周期上报,支持 crash-free session rate 计算 |
|
|||
|
|
| **符号化** | 上传 SourceMap / ProGuard mapping / dSYM,支持多平台堆栈还原 |
|
|||
|
|
| **Webhook 告警** | 新 Issue、fatal 级别、阈值超限等事件触发 Webhook 通知 |
|
|||
|
|
| **Issue 管理** | 解决、忽略、分配、批量操作 |
|
|||
|
|
| **多平台** | 统一 API,平台差异由 `platform` 字段区分 |
|
|||
|
|
|
|||
|
|
### 设计原则
|
|||
|
|
|
|||
|
|
1. **Sentry 对齐**:字段命名和结构参考 Sentry,降低学习成本
|
|||
|
|
2. **批量优先**:上报端点均为批量接口,减少网络请求
|
|||
|
|
3. **信封封装**:请求体使用信封(Envelope)结构,支持携带 SDK 元信息
|
|||
|
|
4. **幂等安全**:每条 Event 携带 `eventId`,服务端按此去重
|
|||
|
|
5. **向前兼容**:未知字段忽略不报错,新字段可选添加
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 2. 术语表
|
|||
|
|
|
|||
|
|
| 术语 | 说明 |
|
|||
|
|
|------|------|
|
|||
|
|
| **Issue** | 一类错误的聚合,由 fingerprint 唯一标识。一个 Issue 对应多次 Event |
|
|||
|
|
| **Event** | 一次具体的错误发生记录,包含完整的堆栈、面包屑、设备、用户等上下文 |
|
|||
|
|
| **Analytics Event** | 自定义业务事件(如页面访问、按钮点击),用于漏斗分析 |
|
|||
|
|
| **Session** | 一次应用使用过程,从前台打开到退出/崩溃,用于计算 crash-free rate |
|
|||
|
|
| **Breadcrumb** | 崩溃前的操作轨迹,如导航、网络请求、用户操作,自动附带在 Event 中 |
|
|||
|
|
| **Fingerprint** | 错误指纹,SHA-256 哈希值,用于 Issue 去重分组 |
|
|||
|
|
| **Level** | 错误严重级别:`fatal` > `error` > `warning` > `info` > `debug` |
|
|||
|
|
| **Status** | Issue 状态:`open`(未处理)/ `resolved`(已解决)/ `ignored`(已忽略) |
|
|||
|
|
| **Release** | 应用版本号,对应 `appVersion` |
|
|||
|
|
| **Environment** | 运行环境:`production` / `staging` / `development` / `integration` |
|
|||
|
|
| **Envelope** | 批量请求的信封结构,包含 `sentAt`、`sdk`、`events` |
|
|||
|
|
| **AppKey** | 应用唯一标识,由平台分配 |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 3. 认证与安全
|
|||
|
|
|
|||
|
|
### 上报端点(SDK → 服务端)
|
|||
|
|
|
|||
|
|
SDK 通过 `config.xuqm` 完成初始化认证,`appKey` 由 SDK 自动从配置文件读取并附带在请求体中,**开发者无需手动处理认证逻辑**。
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
appKey 来源:assets/xuqm/config.xuqm(加密文件,由租户平台下发)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
认证链路:
|
|||
|
|
|
|||
|
|
1. 开发者从租户平台下载 `config.xuqm`,内含 `appKey` 和可选的 `serverUrl`
|
|||
|
|
2. `config.xuqm` 已加密存储,且绑定包名(SDK 启动时校验包名与文件中记录的一致性)
|
|||
|
|
3. SDK 初始化时从平台拉取配置,验证 BugCollect 服务已开通(`t_feature_service.enabled = true`);未开通时 `captureError` 为空操作,不发送任何请求
|
|||
|
|
4. 服务端收到上报后,验证 `appKey` 有效且对应 BugCollect 服务已激活,否则拒绝写入
|
|||
|
|
|
|||
|
|
> **服务激活即权限边界**:BugCollect 服务开通状态由租户在平台管理,未开通的 `appKey` 的上报请求会被服务端拒绝,无需额外 Token。
|
|||
|
|
|
|||
|
|
建议 SDK 端通过 **HTTPS** 传输,防止 appKey 被中间人截获。
|
|||
|
|
|
|||
|
|
### 查询端点 / 管理端点(Web → 服务端)
|
|||
|
|
|
|||
|
|
- 通过 API 网关统一鉴权(租户 Token)
|
|||
|
|
- 查询参数中的 `appKey` 必须与鉴权租户匹配
|
|||
|
|
|
|||
|
|
### 速率限制
|
|||
|
|
|
|||
|
|
| 端点类型 | 限制 | 超限行为 |
|
|||
|
|
|---------|------|---------|
|
|||
|
|
| Issue / Event 上报 | 1000 次/分钟/appKey | HTTP 429,SDK 将事件重新入队,下次重试 |
|
|||
|
|
| Session 上报 | 5000 次/分钟/appKey | HTTP 429,SDK 丢弃(会话数据可接受损失) |
|
|||
|
|
| SourceMap 上传 | 20 次/小时/appKey | HTTP 429 |
|
|||
|
|
| 查询端点 | 100 次/分钟/租户 | HTTP 429 |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 4. 数据上报端点
|
|||
|
|
|
|||
|
|
### 4.1 Issue 批量上报
|
|||
|
|
|
|||
|
|
捕获的错误、未捕获的崩溃统一通过此端点上报。
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
POST /bugcollect/v1/issues/batch
|
|||
|
|
Content-Type: application/json
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 请求体
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"sentAt": "2026-06-17T10:30:00Z",
|
|||
|
|
"sdk": {
|
|||
|
|
"name": "bugcollect.android",
|
|||
|
|
"version": "1.0.0"
|
|||
|
|
},
|
|||
|
|
"events": [
|
|||
|
|
{
|
|||
|
|
"eventId": "550e8400-e29b-41d4-a716-446655440000",
|
|||
|
|
"appKey": "2000111111110002",
|
|||
|
|
"level": "error",
|
|||
|
|
"platform": "android",
|
|||
|
|
"release": "7.2.13",
|
|||
|
|
"environment": "production",
|
|||
|
|
"timestamp": 1718620200000,
|
|||
|
|
"fingerprint": "a1b2c3d4e5f6789012345678901234567890abcdef1234567890abcdef123456",
|
|||
|
|
"exception": {
|
|||
|
|
"type": "IllegalStateException",
|
|||
|
|
"value": "更新服务未开通 (code=40404)",
|
|||
|
|
"stacktrace": "java.lang.IllegalStateException: 更新服务未开通\n\tat com.szyx.app.MainActivity.onCreate(MainActivity.kt:178)\n\tat android.app.Activity.performCreate(Activity.java:8000)"
|
|||
|
|
},
|
|||
|
|
"breadcrumbs": [
|
|||
|
|
{
|
|||
|
|
"timestamp": 1718620195000,
|
|||
|
|
"category": "navigation",
|
|||
|
|
"message": "进入首页",
|
|||
|
|
"level": "info"
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"timestamp": 1718620199000,
|
|||
|
|
"category": "network",
|
|||
|
|
"message": "GET /api/update → 404",
|
|||
|
|
"level": "warning",
|
|||
|
|
"data": { "url": "https://update.dev.xuqinmin.com/", "statusCode": 404 }
|
|||
|
|
}
|
|||
|
|
],
|
|||
|
|
"user": {
|
|||
|
|
"id": "user-123"
|
|||
|
|
},
|
|||
|
|
"device": {
|
|||
|
|
"name": "Pixel 7",
|
|||
|
|
"model": "Pixel 7",
|
|||
|
|
"manufacturer": "Google",
|
|||
|
|
"osName": "Android",
|
|||
|
|
"osVersion": "14",
|
|||
|
|
"locale": "zh_CN",
|
|||
|
|
"timezone": "Asia/Shanghai",
|
|||
|
|
"network": "wifi",
|
|||
|
|
"isEmulator": false,
|
|||
|
|
"freeMemoryMb": 512,
|
|||
|
|
"buildType": "release"
|
|||
|
|
},
|
|||
|
|
"tags": {
|
|||
|
|
"context": "checkAppUpdate"
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
]
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 响应
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"code": 200,
|
|||
|
|
"message": "success",
|
|||
|
|
"data": null
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
> **幂等说明**:服务端按 `eventId` 去重。相同 `appKey` + `eventId` 的二次提交直接返回 200,不重复写入。
|
|||
|
|
|
|||
|
|
#### cURL 示例
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
curl -X POST https://bugcollect.xuqinmin.com/bugcollect/v1/issues/batch \
|
|||
|
|
-H "Content-Type: application/json" \
|
|||
|
|
-d '{
|
|||
|
|
"sentAt": "2026-06-17T10:30:00Z",
|
|||
|
|
"sdk": { "name": "bugcollect.android", "version": "1.0.0" },
|
|||
|
|
"events": [{
|
|||
|
|
"eventId": "550e8400-e29b-41d4-a716-446655440000",
|
|||
|
|
"appKey": "2000111111110002",
|
|||
|
|
"level": "error",
|
|||
|
|
"platform": "android",
|
|||
|
|
"release": "7.2.13",
|
|||
|
|
"environment": "production",
|
|||
|
|
"timestamp": 1718620200000,
|
|||
|
|
"fingerprint": "abc123...",
|
|||
|
|
"exception": {
|
|||
|
|
"type": "NullPointerException",
|
|||
|
|
"value": "Attempt to invoke virtual method on a null reference",
|
|||
|
|
"stacktrace": "java.lang.NullPointerException: ...\n\tat ..."
|
|||
|
|
}
|
|||
|
|
}]
|
|||
|
|
}'
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### 4.2 Event 批量上报
|
|||
|
|
|
|||
|
|
自定义业务事件(页面访问、功能使用、漏斗步骤等)通过此端点上报。
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
POST /bugcollect/v1/events/batch
|
|||
|
|
Content-Type: application/json
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 请求体
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"sentAt": "2026-06-17T10:30:00Z",
|
|||
|
|
"sdk": {
|
|||
|
|
"name": "bugcollect.android",
|
|||
|
|
"version": "1.0.0"
|
|||
|
|
},
|
|||
|
|
"events": [
|
|||
|
|
{
|
|||
|
|
"eventId": "660e8400-e29b-41d4-a716-446655440001",
|
|||
|
|
"appKey": "2000111111110002",
|
|||
|
|
"name": "page_view",
|
|||
|
|
"properties": {
|
|||
|
|
"page": "/home",
|
|||
|
|
"referrer": "/login"
|
|||
|
|
},
|
|||
|
|
"platform": "android",
|
|||
|
|
"release": "7.2.13",
|
|||
|
|
"environment": "production",
|
|||
|
|
"timestamp": 1718620200000,
|
|||
|
|
"user": {
|
|||
|
|
"id": "user-123"
|
|||
|
|
},
|
|||
|
|
"device": {
|
|||
|
|
"osName": "Android",
|
|||
|
|
"osVersion": "14",
|
|||
|
|
"isEmulator": false
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
]
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 响应
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"code": 200,
|
|||
|
|
"message": "success",
|
|||
|
|
"data": null
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### 4.3 SourceMap / 符号文件上传
|
|||
|
|
|
|||
|
|
上传符号文件,用于堆栈还原。各平台文件格式不同:
|
|||
|
|
|
|||
|
|
| 平台 | 文件类型 | 说明 |
|
|||
|
|
|------|----------|------|
|
|||
|
|
| `web` / `react-native` | `.map` | JavaScript SourceMap |
|
|||
|
|
| `android` | `.txt` | ProGuard / R8 mapping 文件 |
|
|||
|
|
| `ios` | `.zip` | dSYM 压缩包(含 DWARF 调试信息) |
|
|||
|
|
| `harmonyos` | `.map` | 类 SourceMap 格式 |
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
POST /bugcollect/v1/sourcemaps/upload
|
|||
|
|
Content-Type: multipart/form-data
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 请求参数
|
|||
|
|
|
|||
|
|
| 参数 | 类型 | 必填 | 说明 |
|
|||
|
|
|------|------|------|------|
|
|||
|
|
| `appKey` | string | ✅ | 应用标识 |
|
|||
|
|
| `platform` | string | ✅ | 平台:`web` / `react-native` / `android` / `ios` / `harmonyos` |
|
|||
|
|
| `appVersion` | string | ✅ | 应用版本,对应 `release` 字段 |
|
|||
|
|
| `bundleName` | string | | JS Bundle 名称,默认 `index`(web/rn 专用) |
|
|||
|
|
| `file` | file | ✅ | 符号文件 |
|
|||
|
|
|
|||
|
|
#### cURL 示例
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
# React Native SourceMap
|
|||
|
|
curl -X POST https://bugcollect.xuqinmin.com/bugcollect/v1/sourcemaps/upload \
|
|||
|
|
-F "appKey=2000111111110002" \
|
|||
|
|
-F "platform=react-native" \
|
|||
|
|
-F "appVersion=7.2.13" \
|
|||
|
|
-F "bundleName=index" \
|
|||
|
|
-F "file=@./index.bundle.map"
|
|||
|
|
|
|||
|
|
# Android ProGuard mapping
|
|||
|
|
curl -X POST https://bugcollect.xuqinmin.com/bugcollect/v1/sourcemaps/upload \
|
|||
|
|
-F "appKey=2000111111110002" \
|
|||
|
|
-F "platform=android" \
|
|||
|
|
-F "appVersion=7.2.13" \
|
|||
|
|
-F "file=@./mapping.txt"
|
|||
|
|
|
|||
|
|
# iOS dSYM
|
|||
|
|
curl -X POST https://bugcollect.xuqinmin.com/bugcollect/v1/sourcemaps/upload \
|
|||
|
|
-F "appKey=2000111111110002" \
|
|||
|
|
-F "platform=ios" \
|
|||
|
|
-F "appVersion=7.2.13" \
|
|||
|
|
-F "file=@./YwxApp.app.dSYM.zip"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 响应
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"code": 200,
|
|||
|
|
"message": "success",
|
|||
|
|
"data": {
|
|||
|
|
"id": 1,
|
|||
|
|
"appKey": "2000111111110002",
|
|||
|
|
"platform": "android",
|
|||
|
|
"appVersion": "7.2.13",
|
|||
|
|
"uploadedAt": "2026-06-17T10:30:00"
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### 4.4 Session 上报
|
|||
|
|
|
|||
|
|
上报会话生命周期,用于计算 crash-free session rate。
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
POST /bugcollect/v1/sessions/batch
|
|||
|
|
Content-Type: application/json
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 请求体
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"sentAt": "2026-06-17T10:30:00Z",
|
|||
|
|
"sdk": { "name": "bugcollect.android", "version": "1.0.0" },
|
|||
|
|
"sessions": [
|
|||
|
|
{
|
|||
|
|
"sessionId": "sess-abc-123",
|
|||
|
|
"appKey": "2000111111110002",
|
|||
|
|
"status": "exited",
|
|||
|
|
"platform": "android",
|
|||
|
|
"release": "7.2.13",
|
|||
|
|
"environment": "production",
|
|||
|
|
"startedAt": 1718620100000,
|
|||
|
|
"duration": 95000,
|
|||
|
|
"user": { "id": "user-123" },
|
|||
|
|
"errors": 0
|
|||
|
|
}
|
|||
|
|
]
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### Session 状态
|
|||
|
|
|
|||
|
|
| `status` | 说明 |
|
|||
|
|
|---------|------|
|
|||
|
|
| `ok` | 进行中(心跳上报) |
|
|||
|
|
| `exited` | 正常退出(用户主动离开或 App 进入后台超时) |
|
|||
|
|
| `crashed` | 因未捕获异常终止 |
|
|||
|
|
| `abnormal` | 进程被系统杀死(ANR、OOM、后台清理) |
|
|||
|
|
|
|||
|
|
#### 字段说明
|
|||
|
|
|
|||
|
|
| 字段 | 类型 | 必填 | 说明 |
|
|||
|
|
|------|------|------|------|
|
|||
|
|
| `sessionId` | string | ✅ | 会话唯一 ID(UUID) |
|
|||
|
|
| `appKey` | string | ✅ | 应用标识 |
|
|||
|
|
| `status` | string | ✅ | 会话状态,见上表 |
|
|||
|
|
| `platform` | string | ✅ | 平台 |
|
|||
|
|
| `release` | string | | 应用版本 |
|
|||
|
|
| `environment` | string | | 运行环境 |
|
|||
|
|
| `startedAt` | long | ✅ | 会话开始时间戳(毫秒) |
|
|||
|
|
| `duration` | long | | 会话时长(毫秒) |
|
|||
|
|
| `user.id` | string | | 用户 ID |
|
|||
|
|
| `errors` | int | | 会话内捕获的 error 数量 |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 5. 数据模型
|
|||
|
|
|
|||
|
|
### 5.1 批量信封 Envelope
|
|||
|
|
|
|||
|
|
所有批量上报端点共享统一的信封结构。信封层的 `sdk` 字段作为默认值,事件层不再重复携带。
|
|||
|
|
|
|||
|
|
| 字段 | 类型 | 必填 | 说明 |
|
|||
|
|
|------|------|------|------|
|
|||
|
|
| `sentAt` | string (ISO 8601) | | 客户端发送时间,用于时钟偏差校正 |
|
|||
|
|
| `sdk` | object | | SDK 信息 |
|
|||
|
|
| `sdk.name` | string | | SDK 标识,如 `bugcollect.android`、`bugcollect.ios`、`bugcollect.harmonyos`、`bugcollect.rn`、`bugcollect.web` |
|
|||
|
|
| `sdk.version` | string | | SDK 版本号 |
|
|||
|
|
| `events` | array | ✅ | 事件数组,不能为空 |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### 5.2 IssueEvent
|
|||
|
|
|
|||
|
|
错误事件数据模型,用于 `captureError()` 和 `captureCrash()`。
|
|||
|
|
|
|||
|
|
| 字段 | 类型 | 必填 | 说明 |
|
|||
|
|
|------|------|------|------|
|
|||
|
|
| `eventId` | string (UUID) | ✅ | 客户端生成的唯一事件 ID,服务端按此去重 |
|
|||
|
|
| `appKey` | string | ✅ | 应用标识 |
|
|||
|
|
| `level` | string | ✅ | 严重级别,见 [Level 枚举](#551-level) |
|
|||
|
|
| `platform` | string | ✅ | 平台,见 [Platform 枚举](#552-platform) |
|
|||
|
|
| `fingerprint` | string | ✅ | 错误指纹,64 字符 SHA-256 哈希 |
|
|||
|
|
| `timestamp` | long | ✅ | 事件时间戳(毫秒) |
|
|||
|
|
| `exception` | object | | 异常信息 |
|
|||
|
|
| `exception.type` | string | | 异常类名,如 `NullPointerException` |
|
|||
|
|
| `exception.value` | string | | 异常消息 |
|
|||
|
|
| `exception.stacktrace` | string | | 完整堆栈文本 |
|
|||
|
|
| `breadcrumbs` | array | | 崩溃前操作轨迹,见 [Breadcrumb](#54-breadcrumb),最多 50 条 |
|
|||
|
|
| `release` | string | | 应用版本号 |
|
|||
|
|
| `environment` | string | | 运行环境,默认 `production` |
|
|||
|
|
| `user` | object | | 用户信息 |
|
|||
|
|
| `user.id` | string | | 用户 ID |
|
|||
|
|
| `device` | object | | 设备信息,见下表 |
|
|||
|
|
| `tags` | object | | 自定义标签,key-value 均为 string |
|
|||
|
|
|
|||
|
|
#### device 字段
|
|||
|
|
|
|||
|
|
| 字段 | 类型 | 说明 |
|
|||
|
|
|------|------|------|
|
|||
|
|
| `name` | string | 设备名称,如 `Pixel 7` |
|
|||
|
|
| `model` | string | 设备型号 |
|
|||
|
|
| `manufacturer` | string | 制造商 |
|
|||
|
|
| `osName` | string | 操作系统名称 |
|
|||
|
|
| `osVersion` | string | 操作系统版本 |
|
|||
|
|
| `locale` | string | 语言区域,如 `zh_CN` |
|
|||
|
|
| `timezone` | string | 时区,如 `Asia/Shanghai` |
|
|||
|
|
| `network` | string | 网络类型:`wifi` / `cellular` / `none` / `unknown` |
|
|||
|
|
| `isEmulator` | boolean | 是否模拟器(过滤开发噪声) |
|
|||
|
|
| `freeMemoryMb` | int | 可用内存(MB) |
|
|||
|
|
| `buildType` | string | 构建类型:`debug` / `release` |
|
|||
|
|
|
|||
|
|
#### 最小上报示例
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"eventId": "550e8400-e29b-41d4-a716-446655440000",
|
|||
|
|
"appKey": "2000111111110002",
|
|||
|
|
"level": "error",
|
|||
|
|
"platform": "android",
|
|||
|
|
"fingerprint": "abc123...",
|
|||
|
|
"timestamp": 1718620200000,
|
|||
|
|
"exception": {
|
|||
|
|
"type": "Exception",
|
|||
|
|
"value": "something went wrong",
|
|||
|
|
"stacktrace": "..."
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### 5.3 LogEvent
|
|||
|
|
|
|||
|
|
自定义业务事件数据模型,用于 `event()` 方法。
|
|||
|
|
|
|||
|
|
| 字段 | 类型 | 必填 | 说明 |
|
|||
|
|
|------|------|------|------|
|
|||
|
|
| `eventId` | string (UUID) | ✅ | 客户端生成的唯一事件 ID,服务端按此去重 |
|
|||
|
|
| `appKey` | string | ✅ | 应用标识 |
|
|||
|
|
| `name` | string | ✅ | 事件名称,如 `page_view`、`button_click` |
|
|||
|
|
| `timestamp` | long | ✅ | 事件时间戳(毫秒) |
|
|||
|
|
| `properties` | object | | 事件属性,任意 key-value |
|
|||
|
|
| `platform` | string | | 平台 |
|
|||
|
|
| `release` | string | | 应用版本号 |
|
|||
|
|
| `environment` | string | | 运行环境 |
|
|||
|
|
| `user` | object | | 用户信息 |
|
|||
|
|
| `user.id` | string | | 用户 ID |
|
|||
|
|
| `device` | object | | 设备信息(同 IssueEvent.device) |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### 5.4 Breadcrumb
|
|||
|
|
|
|||
|
|
崩溃前的操作轨迹条目,自动附带在 IssueEvent 的 `breadcrumbs` 数组中,最多保留最近 50 条。
|
|||
|
|
|
|||
|
|
| 字段 | 类型 | 必填 | 说明 |
|
|||
|
|
|------|------|------|------|
|
|||
|
|
| `timestamp` | long | ✅ | 轨迹时间戳(毫秒) |
|
|||
|
|
| `category` | string | ✅ | 分类,见下表 |
|
|||
|
|
| `message` | string | ✅ | 描述文本 |
|
|||
|
|
| `level` | string | | `info` / `warning` / `error`,默认 `info` |
|
|||
|
|
| `data` | object | | 额外键值对,如 `url`、`statusCode`、`method` |
|
|||
|
|
|
|||
|
|
#### 标准 Category
|
|||
|
|
|
|||
|
|
| category | 说明 | 典型 data 字段 |
|
|||
|
|
|----------|------|---------------|
|
|||
|
|
| `navigation` | 页面/路由切换 | `from`, `to` |
|
|||
|
|
| `network` | HTTP 请求 | `url`, `method`, `statusCode`, `durationMs` |
|
|||
|
|
| `ui` | 用户交互 | `action`(tap/swipe),`target` |
|
|||
|
|
| `lifecycle` | App / Activity 生命周期 | `event`(foreground/background) |
|
|||
|
|
| `console` | 手动打点日志 | — |
|
|||
|
|
| `error` | SDK 内部捕获的非致命错误 | — |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### 5.5 枚举定义
|
|||
|
|
|
|||
|
|
#### 5.5.1 Level
|
|||
|
|
|
|||
|
|
错误严重级别,从高到低排列。
|
|||
|
|
|
|||
|
|
| 值 | 含义 | 对应 SDK 方法 | Web 展示颜色 |
|
|||
|
|
|----|------|--------------|-------------|
|
|||
|
|
| `fatal` | 未捕获崩溃,应用即将终止 | `captureCrash()` | 🔴 深红 |
|
|||
|
|
| `error` | 捕获的错误,不影响应用存活 | `captureError()` | 🔴 红 |
|
|||
|
|
| `warning` | 警告,潜在问题 | `warn()` | 🟡 黄 |
|
|||
|
|
| `info` | 信息性记录 | `info()` | 🔵 蓝 |
|
|||
|
|
| `debug` | 调试信息 | `debug()` | ⚪ 灰 |
|
|||
|
|
|
|||
|
|
**服务端存储策略**:
|
|||
|
|
|
|||
|
|
- `fatal` / `error` → 写入 `log_issues` 表参与 Issue 聚合,同时写入 `log_issue_events` 表记录明细
|
|||
|
|
- `warning` / `info` / `debug` → **仅写入** `log_issue_events` 表,不创建或更新 Issue,不触发告警
|
|||
|
|
|
|||
|
|
#### 5.5.2 Platform
|
|||
|
|
|
|||
|
|
| 值 | 说明 |
|
|||
|
|
|----|------|
|
|||
|
|
| `android` | Android 原生 |
|
|||
|
|
| `ios` | iOS 原生 |
|
|||
|
|
| `harmonyos` | HarmonyOS 原生 |
|
|||
|
|
| `react-native` | React Native 跨平台 |
|
|||
|
|
| `web` | Web 浏览器 |
|
|||
|
|
| `java-server` | Java 服务端 |
|
|||
|
|
| `python-server` | Python 服务端 |
|
|||
|
|
| `go-server` | Go 服务端 |
|
|||
|
|
|
|||
|
|
#### 5.5.3 Environment
|
|||
|
|
|
|||
|
|
| 值 | 说明 |
|
|||
|
|
|----|------|
|
|||
|
|
| `production` | 生产环境(默认) |
|
|||
|
|
| `staging` | 预发布环境 |
|
|||
|
|
| `integration` | 集成测试环境 |
|
|||
|
|
| `development` | 开发环境 |
|
|||
|
|
|
|||
|
|
#### 5.5.4 Issue Status
|
|||
|
|
|
|||
|
|
| 值 | 说明 |
|
|||
|
|
|----|------|
|
|||
|
|
| `open` | 未处理(默认) |
|
|||
|
|
| `resolved` | 已解决 |
|
|||
|
|
| `ignored` | 已忽略,不再告警 |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 6. 查询端点
|
|||
|
|
|
|||
|
|
> 以下端点均为 `GET` 请求,返回数据格式统一为 `ApiResponse<T>`。
|
|||
|
|
|
|||
|
|
### 通用响应格式
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"code": 200,
|
|||
|
|
"message": "success",
|
|||
|
|
"data": { ... }
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 通用分页格式
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"items": [],
|
|||
|
|
"page": 1,
|
|||
|
|
"size": 20,
|
|||
|
|
"total": 100
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### 6.1 Issue 列表
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
GET /bugcollect/v1/issues
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 查询参数
|
|||
|
|
|
|||
|
|
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|
|||
|
|
|------|------|------|--------|------|
|
|||
|
|
| `appKey` | string | ✅ | | 应用标识 |
|
|||
|
|
| `level` | string | | | 级别筛选:`fatal` / `error` / `warning` |
|
|||
|
|
| `status` | string | | `open` | 状态筛选:`open` / `resolved` / `ignored` |
|
|||
|
|
| `platform` | string | | | 平台筛选 |
|
|||
|
|
| `release` | string | | | 版本筛选 |
|
|||
|
|
| `q` | string | | | 按 Issue 标题全文搜索 |
|
|||
|
|
| `from` | string | | | 起始日期 `YYYY-MM-DD` |
|
|||
|
|
| `to` | string | | | 结束日期 `YYYY-MM-DD` |
|
|||
|
|
| `page` | int | | 1 | 页码(从 1 开始) |
|
|||
|
|
| `size` | int | | 20 | 每页条数 |
|
|||
|
|
|
|||
|
|
#### 响应
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"code": 200,
|
|||
|
|
"message": "success",
|
|||
|
|
"data": {
|
|||
|
|
"items": [
|
|||
|
|
{
|
|||
|
|
"id": 1,
|
|||
|
|
"appKey": "2000111111110002",
|
|||
|
|
"fingerprint": "abc123...",
|
|||
|
|
"level": "error",
|
|||
|
|
"status": "open",
|
|||
|
|
"title": "IllegalStateException: 更新服务未开通",
|
|||
|
|
"firstSeenAt": "2026-06-17T10:00:00",
|
|||
|
|
"lastSeenAt": "2026-06-17T12:00:00",
|
|||
|
|
"count": 15,
|
|||
|
|
"affectedUsers": 8,
|
|||
|
|
"platform": "android",
|
|||
|
|
"release": "7.2.13"
|
|||
|
|
}
|
|||
|
|
],
|
|||
|
|
"page": 1,
|
|||
|
|
"size": 20,
|
|||
|
|
"total": 1
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### 6.2 Issue 详情
|
|||
|
|
|
|||
|
|
仅返回 Issue 元数据。事件明细通过 [6.3 Issue 事件列表](#63-issue-事件列表) 分页获取。
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
GET /bugcollect/v1/issues/{id}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 路径参数
|
|||
|
|
|
|||
|
|
| 参数 | 类型 | 说明 |
|
|||
|
|
|------|------|------|
|
|||
|
|
| `id` | long | Issue ID |
|
|||
|
|
|
|||
|
|
#### 响应
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"code": 200,
|
|||
|
|
"message": "success",
|
|||
|
|
"data": {
|
|||
|
|
"id": 1,
|
|||
|
|
"appKey": "2000111111110002",
|
|||
|
|
"fingerprint": "abc123...",
|
|||
|
|
"level": "error",
|
|||
|
|
"status": "open",
|
|||
|
|
"title": "IllegalStateException: 更新服务未开通",
|
|||
|
|
"firstSeenAt": "2026-06-17T10:00:00",
|
|||
|
|
"lastSeenAt": "2026-06-17T12:00:00",
|
|||
|
|
"count": 15,
|
|||
|
|
"affectedUsers": 8,
|
|||
|
|
"platform": "android",
|
|||
|
|
"release": "7.2.13",
|
|||
|
|
"assignee": null
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### 6.3 Issue 事件列表
|
|||
|
|
|
|||
|
|
分页获取某个 Issue 下的所有事件明细,含完整堆栈、面包屑、设备信息。
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
GET /bugcollect/v1/issues/{id}/events
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 查询参数
|
|||
|
|
|
|||
|
|
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|
|||
|
|
|------|------|------|--------|------|
|
|||
|
|
| `id` | long | ✅(路径) | | Issue ID |
|
|||
|
|
| `from` | string | | | 起始日期 |
|
|||
|
|
| `to` | string | | | 结束日期 |
|
|||
|
|
| `page` | int | | 1 | 页码 |
|
|||
|
|
| `size` | int | | 20 | 每页条数 |
|
|||
|
|
|
|||
|
|
#### 响应
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"code": 200,
|
|||
|
|
"message": "success",
|
|||
|
|
"data": {
|
|||
|
|
"items": [
|
|||
|
|
{
|
|||
|
|
"id": 101,
|
|||
|
|
"issueId": 1,
|
|||
|
|
"eventId": "550e8400-e29b-41d4-a716-446655440000",
|
|||
|
|
"appKey": "2000111111110002",
|
|||
|
|
"level": "error",
|
|||
|
|
"userId": "user-123",
|
|||
|
|
"sessionId": "sess-abc",
|
|||
|
|
"exception": {
|
|||
|
|
"type": "IllegalStateException",
|
|||
|
|
"value": "更新服务未开通",
|
|||
|
|
"stacktrace": "java.lang.IllegalStateException: ...",
|
|||
|
|
"stackSymbolicated": null
|
|||
|
|
},
|
|||
|
|
"breadcrumbs": [
|
|||
|
|
{
|
|||
|
|
"timestamp": 1718620195000,
|
|||
|
|
"category": "navigation",
|
|||
|
|
"message": "进入首页",
|
|||
|
|
"level": "info"
|
|||
|
|
}
|
|||
|
|
],
|
|||
|
|
"tags": { "context": "checkAppUpdate" },
|
|||
|
|
"device": {
|
|||
|
|
"osName": "Android",
|
|||
|
|
"osVersion": "14",
|
|||
|
|
"isEmulator": false,
|
|||
|
|
"network": "wifi"
|
|||
|
|
},
|
|||
|
|
"platform": "android",
|
|||
|
|
"release": "7.2.13",
|
|||
|
|
"environment": "production",
|
|||
|
|
"sdkName": "bugcollect.android",
|
|||
|
|
"sdkVersion": "1.0.0",
|
|||
|
|
"createdAt": "2026-06-17T10:30:00"
|
|||
|
|
}
|
|||
|
|
],
|
|||
|
|
"page": 1,
|
|||
|
|
"size": 20,
|
|||
|
|
"total": 15
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### 6.4 Issue 趋势
|
|||
|
|
|
|||
|
|
获取某个 Issue 在指定时间范围内的每日发生次数趋势,用于判断问题是在收敛还是扩散。
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
GET /bugcollect/v1/issues/{id}/trend
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 查询参数
|
|||
|
|
|
|||
|
|
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|
|||
|
|
|------|------|------|--------|------|
|
|||
|
|
| `from` | string | | 近 14 天 | 起始日期 `YYYY-MM-DD` |
|
|||
|
|
| `to` | string | | 今天 | 结束日期 `YYYY-MM-DD` |
|
|||
|
|
|
|||
|
|
#### 响应
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"code": 200,
|
|||
|
|
"message": "success",
|
|||
|
|
"data": {
|
|||
|
|
"issueId": 1,
|
|||
|
|
"points": [
|
|||
|
|
{ "date": "2026-06-11", "count": 2, "affectedUsers": 1 },
|
|||
|
|
{ "date": "2026-06-12", "count": 5, "affectedUsers": 3 },
|
|||
|
|
{ "date": "2026-06-17", "count": 8, "affectedUsers": 5 }
|
|||
|
|
]
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### 6.5 Event 列表
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
GET /bugcollect/v1/events
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 查询参数
|
|||
|
|
|
|||
|
|
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|
|||
|
|
|------|------|------|--------|------|
|
|||
|
|
| `appKey` | string | ✅ | | 应用标识 |
|
|||
|
|
| `name` | string | | | 事件名称筛选 |
|
|||
|
|
| `userId` | string | | | 用户 ID 筛选 |
|
|||
|
|
| `from` | string | | | 起始日期 |
|
|||
|
|
| `to` | string | | | 结束日期 |
|
|||
|
|
| `page` | int | | 1 | 页码 |
|
|||
|
|
| `size` | int | | 20 | 每页条数 |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### 6.6 概览统计
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
GET /bugcollect/v1/overview?appKey={appKey}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 查询参数
|
|||
|
|
|
|||
|
|
| 参数 | 类型 | 必填 | 说明 |
|
|||
|
|
|------|------|------|------|
|
|||
|
|
| `appKey` | string | ✅ | 应用标识 |
|
|||
|
|
| `from` | string | | 起始日期 |
|
|||
|
|
| `to` | string | | 结束日期 |
|
|||
|
|
|
|||
|
|
#### 响应
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"code": 200,
|
|||
|
|
"message": "success",
|
|||
|
|
"data": {
|
|||
|
|
"totalIssues": 42,
|
|||
|
|
"openIssues": 35,
|
|||
|
|
"todayNewIssues": 3,
|
|||
|
|
"affectedUsers": 128,
|
|||
|
|
"crashFreeSessionRate": 0.9971,
|
|||
|
|
"crashRate": 0.05,
|
|||
|
|
"crashRateTrend": [
|
|||
|
|
{ "date": "2026-06-11", "count": 5, "rate": 0.03 },
|
|||
|
|
{ "date": "2026-06-12", "count": 8, "rate": 0.05 }
|
|||
|
|
],
|
|||
|
|
"topIssues": [
|
|||
|
|
{
|
|||
|
|
"id": 1,
|
|||
|
|
"title": "NullPointerException: ...",
|
|||
|
|
"level": "error",
|
|||
|
|
"count": 15,
|
|||
|
|
"affectedUsers": 8
|
|||
|
|
}
|
|||
|
|
]
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
> **crashFreeSessionRate**:`1 - (crashed_sessions / total_sessions)`,行业标准指标,需 [Session 上报](#44-session-上报) 数据支撑。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### 6.7 频率排行
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
GET /bugcollect/v1/issues/rankings/frequency
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 查询参数
|
|||
|
|
|
|||
|
|
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|
|||
|
|
|------|------|------|--------|------|
|
|||
|
|
| `appKey` | string | ✅ | | 应用标识 |
|
|||
|
|
| `from` | string | | | 起始日期 |
|
|||
|
|
| `to` | string | | | 结束日期 |
|
|||
|
|
| `limit` | int | | 20 | 返回条数 |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### 6.8 风险排行
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
GET /bugcollect/v1/issues/rankings/risk
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
风险分 = `count × level_weight × recency_weight`,`fatal` 权重最高。
|
|||
|
|
|
|||
|
|
#### 查询参数
|
|||
|
|
|
|||
|
|
同 [频率排行](#67-频率排行)。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### 6.9 漏斗分析
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
GET /bugcollect/v1/events/funnel
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 查询参数
|
|||
|
|
|
|||
|
|
| 参数 | 类型 | 必填 | 说明 |
|
|||
|
|
|------|------|------|------|
|
|||
|
|
| `appKey` | string | ✅ | 应用标识 |
|
|||
|
|
| `steps` | string | ✅ | 逗号分隔的步骤名,如 `page_view,click_submit,order_created` |
|
|||
|
|
| `from` | string | | 起始日期 |
|
|||
|
|
| `to` | string | | 结束日期 |
|
|||
|
|
|
|||
|
|
#### 响应
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"code": 200,
|
|||
|
|
"message": "success",
|
|||
|
|
"data": {
|
|||
|
|
"steps": ["page_view", "click_submit", "order_created"],
|
|||
|
|
"counts": [1000, 600, 300],
|
|||
|
|
"rates": [100.0, 60.0, 30.0]
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 7. Issue 管理端点
|
|||
|
|
|
|||
|
|
> 以下端点均需租户 Token 鉴权(Web 端调用)。
|
|||
|
|
|
|||
|
|
### 7.1 解决 Issue
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
PUT /bugcollect/v1/issues/{id}/resolve
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
将 Issue 状态置为 `resolved`。若该 Issue 后续有新 Event 上报,状态自动回滚到 `open` 并触发 `issue.regressed` Webhook。
|
|||
|
|
|
|||
|
|
#### 响应
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{ "code": 200, "message": "success", "data": null }
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### 7.2 忽略 Issue
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
PUT /bugcollect/v1/issues/{id}/ignore
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
将 Issue 状态置为 `ignored`。忽略后不再触发告警,不影响数据记录。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### 7.3 分配责任人
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
PUT /bugcollect/v1/issues/{id}/assign
|
|||
|
|
Content-Type: application/json
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 请求体
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{ "assignee": "user@example.com" }
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
传 `null` 取消分配。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### 7.4 批量操作
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
POST /bugcollect/v1/issues/bulk
|
|||
|
|
Content-Type: application/json
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 请求体
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"ids": [1, 2, 3],
|
|||
|
|
"action": "resolve"
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### action 枚举
|
|||
|
|
|
|||
|
|
| 值 | 说明 |
|
|||
|
|
|----|------|
|
|||
|
|
| `resolve` | 批量解决 |
|
|||
|
|
| `ignore` | 批量忽略 |
|
|||
|
|
| `reopen` | 批量重新打开 |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 8. Webhook
|
|||
|
|
|
|||
|
|
### 8.1 查询 Webhook 列表
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
GET /bugcollect/v1/webhooks?appKey={appKey}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 8.2 创建 Webhook
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
POST /bugcollect/v1/webhooks
|
|||
|
|
Content-Type: application/json
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 请求体
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"appKey": "2000111111110002",
|
|||
|
|
"url": "https://hooks.example.com/notify",
|
|||
|
|
"events": ["issue.created", "issue.fatal"],
|
|||
|
|
"secret": "webhook-secret-key"
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 8.3 更新 Webhook
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
PUT /bugcollect/v1/webhooks/{id}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 8.4 删除 Webhook
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
DELETE /bugcollect/v1/webhooks/{id}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Webhook 事件类型
|
|||
|
|
|
|||
|
|
| 事件 | 触发时机 |
|
|||
|
|
|------|---------|
|
|||
|
|
| `issue.created` | 新 Issue 首次出现 |
|
|||
|
|
| `issue.fatal` | `fatal` 级别事件上报时立即触发(不等去重) |
|
|||
|
|
| `issue.threshold` | Issue 发生次数超过配置阈值(默认 100 次) |
|
|||
|
|
| `issue.regressed` | 已解决的 Issue 重新出现 |
|
|||
|
|
| `issue.resolved` | Issue 被标记为已解决(用于 CI/CD 集成) |
|
|||
|
|
|
|||
|
|
### Webhook 回调体
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"event": "issue.created",
|
|||
|
|
"timestamp": "2026-06-17T10:30:00Z",
|
|||
|
|
"issue": {
|
|||
|
|
"id": 1,
|
|||
|
|
"appKey": "2000111111110002",
|
|||
|
|
"level": "error",
|
|||
|
|
"status": "open",
|
|||
|
|
"title": "IllegalStateException: 更新服务未开通",
|
|||
|
|
"platform": "android",
|
|||
|
|
"count": 1,
|
|||
|
|
"affectedUsers": 1,
|
|||
|
|
"firstSeenAt": "2026-06-17T10:30:00"
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
> **签名验证**:Webhook 请求携带 `X-BugCollect-Signature: sha256=<hmac>` 请求头,接收方用 `secret` 验证请求合法性。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 9. 错误码
|
|||
|
|
|
|||
|
|
| HTTP 状态码 | code | 说明 |
|
|||
|
|
|------------|------|------|
|
|||
|
|
| 200 | 200 | 成功 |
|
|||
|
|
| 400 | 400 | 请求参数校验失败 |
|
|||
|
|
| 400 | 40001 | `appKey` 不能为空 |
|
|||
|
|
| 400 | 40002 | `events` / `sessions` 数组为空 |
|
|||
|
|
| 400 | 40003 | `fingerprint` 格式非法(非 64 字符十六进制) |
|
|||
|
|
| 400 | 40004 | `level` 不在枚举范围内 |
|
|||
|
|
| 400 | 40005 | `platform` 不在枚举范围内 |
|
|||
|
|
| 403 | 40301 | `appKey` 对应的 BugCollect 服务未开通 |
|
|||
|
|
| 404 | 40401 | Issue 不存在 |
|
|||
|
|
| 429 | 42901 | 请求频率超限 |
|
|||
|
|
| 500 | 500 | 服务端内部错误 |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 10. Fingerprint 去重机制
|
|||
|
|
|
|||
|
|
### 默认算法
|
|||
|
|
|
|||
|
|
SDK 端默认使用以下公式生成 fingerprint(注意:不含 `level`,同一错误不同严重程度归为同一 Issue):
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
SHA-256( normalize(exception.type + ":" + exception.value) + ":" + top_3_stack_lines )
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
- `normalize` — 移除数字字面量、UUID、URL、内存地址等易变内容
|
|||
|
|
- `top_3_stack_lines` — 取堆栈中前 3 行(跳过 SDK 内部框架层)
|
|||
|
|
|
|||
|
|
### 自定义 Fingerprint
|
|||
|
|
|
|||
|
|
SDK 端可传入自定义 fingerprint,覆盖默认算法:
|
|||
|
|
|
|||
|
|
```kotlin
|
|||
|
|
BugCollect.captureError(exception, tags = mapOf("context" to "checkAppUpdate"), fingerprint = "custom-group-key")
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 分组优先级
|
|||
|
|
|
|||
|
|
1. **自定义 fingerprint** — 如果 SDK 传入,完全按此分组
|
|||
|
|
2. **堆栈分组** — 按 `exception.type` + 归一化堆栈前 3 行
|
|||
|
|
3. **消息分组** — 无堆栈时按 `exception.type` + `exception.value` 分组
|
|||
|
|
|
|||
|
|
### 混淆代码处理
|
|||
|
|
|
|||
|
|
Android Release 包经 ProGuard / R8 混淆后,堆栈行类名如 `a.b.c.d` 无法直接分组。建议:
|
|||
|
|
|
|||
|
|
1. 上传 [ProGuard mapping 文件](#43-sourcemap--符号文件上传)
|
|||
|
|
2. 服务端符号化后将还原堆栈写入 `stack_symbolicated`
|
|||
|
|
3. 对已符号化的堆栈重新计算 fingerprint(服务端异步任务)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 11. SDK 集成指南
|
|||
|
|
|
|||
|
|
### 11.1 Android SDK
|
|||
|
|
|
|||
|
|
#### 初始化
|
|||
|
|
|
|||
|
|
SDK 通过 `config.xuqm` 自动初始化,无需手动调用初始化代码。DSN Token 已内含于配置文件。
|
|||
|
|
|
|||
|
|
```kotlin
|
|||
|
|
// 无需手动初始化,ContentProvider 自动完成
|
|||
|
|
// 若需手动初始化:
|
|||
|
|
XuqmSDK.initialize(context, appKey = "2000111111110002")
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 设置用户
|
|||
|
|
|
|||
|
|
通过 `XuqmSDK` 统一管理用户信息,BugCollect 自动跟随:
|
|||
|
|
|
|||
|
|
```kotlin
|
|||
|
|
XuqmSDK.setUserInfo(XuqmUserInfo(userId = "user-123"))
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 捕获错误
|
|||
|
|
|
|||
|
|
```kotlin
|
|||
|
|
try {
|
|||
|
|
// 业务代码
|
|||
|
|
} catch (e: Exception) {
|
|||
|
|
BugCollect.captureError(e, tags = mapOf("context" to "checkAppUpdate"))
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 记录面包屑
|
|||
|
|
|
|||
|
|
```kotlin
|
|||
|
|
BugCollect.addBreadcrumb(category = "navigation", message = "进入首页")
|
|||
|
|
BugCollect.addBreadcrumb(
|
|||
|
|
category = "network",
|
|||
|
|
message = "GET /api/update → 404",
|
|||
|
|
level = "warning",
|
|||
|
|
data = mapOf("url" to url, "statusCode" to 404)
|
|||
|
|
)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 记录事件
|
|||
|
|
|
|||
|
|
```kotlin
|
|||
|
|
BugCollect.event("page_view", properties = mapOf("page" to "/home"))
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 设置环境
|
|||
|
|
|
|||
|
|
```kotlin
|
|||
|
|
BugCollect.setEnvironment("staging")
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 11.2 React Native SDK
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
import { BugCollect } from '@xuqm/rn-bugcollect';
|
|||
|
|
|
|||
|
|
// 捕获错误
|
|||
|
|
try { ... } catch (e) {
|
|||
|
|
BugCollect.captureError(e, { tags: { context: 'checkAppUpdate' } });
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 记录面包屑
|
|||
|
|
BugCollect.addBreadcrumb({ category: 'navigation', message: '进入首页' });
|
|||
|
|
|
|||
|
|
// 记录事件
|
|||
|
|
BugCollect.event('page_view', { page: '/home' });
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 11.3 Web SDK
|
|||
|
|
|
|||
|
|
```javascript
|
|||
|
|
import { BugCollect } from '@xuqm/bugcollect-web';
|
|||
|
|
|
|||
|
|
BugCollect.init({ appKey: '2000111111110002' });
|
|||
|
|
|
|||
|
|
// 自动捕获未处理异常(window.onerror / unhandledrejection)
|
|||
|
|
// 手动捕获
|
|||
|
|
try { ... } catch (e) {
|
|||
|
|
BugCollect.captureError(e);
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 11.4 批量上报策略
|
|||
|
|
|
|||
|
|
SDK 内部自动管理队列,开发者无需关心。
|
|||
|
|
|
|||
|
|
| 参数 | 值 | 说明 |
|
|||
|
|
|------|------|------|
|
|||
|
|
| 批量大小 | 30 条 | 积攒 30 条后立即发送 |
|
|||
|
|
| 定时刷新 | 10 秒 | 未满 30 条时每 10 秒发送一次 |
|
|||
|
|
| 最大队列 | 500 条 | 超出后丢弃最旧的 |
|
|||
|
|
| 持久化范围 | `fatal` / `error` | 发送失败写入磁盘,下次启动补发;`warning` 及以下仅内存队列 |
|
|||
|
|
| 重试 | 1 次 | 发送失败重试 1 次,失败后重新入队 |
|
|||
|
|
| 幂等保障 | `eventId` | 每条 Event 携带 UUID,服务端按此去重,重试不会产生重复数据 |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 12. 数据库 Schema
|
|||
|
|
|
|||
|
|
### log_issues — Issue 聚合表
|
|||
|
|
|
|||
|
|
```sql
|
|||
|
|
CREATE TABLE log_issues (
|
|||
|
|
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
|||
|
|
app_key VARCHAR(64) NOT NULL,
|
|||
|
|
fingerprint VARCHAR(128) NOT NULL,
|
|||
|
|
level VARCHAR(20) NOT NULL DEFAULT 'error',
|
|||
|
|
status VARCHAR(20) NOT NULL DEFAULT 'open', -- open | resolved | ignored
|
|||
|
|
assignee VARCHAR(200),
|
|||
|
|
title VARCHAR(500),
|
|||
|
|
first_seen_at DATETIME NOT NULL,
|
|||
|
|
last_seen_at DATETIME NOT NULL,
|
|||
|
|
count INT NOT NULL DEFAULT 1,
|
|||
|
|
affected_users INT NOT NULL DEFAULT 0,
|
|||
|
|
platform VARCHAR(30),
|
|||
|
|
release VARCHAR(50),
|
|||
|
|
UNIQUE KEY uk_app_fingerprint (app_key, fingerprint),
|
|||
|
|
INDEX idx_app_key_last_seen (app_key, status, last_seen_at),
|
|||
|
|
INDEX idx_app_key_level (app_key, level, last_seen_at)
|
|||
|
|
);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### log_issue_events — Issue 事件明细表
|
|||
|
|
|
|||
|
|
```sql
|
|||
|
|
CREATE TABLE log_issue_events (
|
|||
|
|
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
|||
|
|
issue_id BIGINT NOT NULL,
|
|||
|
|
event_id VARCHAR(64) NOT NULL, -- 客户端幂等 ID
|
|||
|
|
app_key VARCHAR(64) NOT NULL,
|
|||
|
|
level VARCHAR(20) NOT NULL DEFAULT 'error',
|
|||
|
|
user_id VARCHAR(128),
|
|||
|
|
session_id VARCHAR(128),
|
|||
|
|
exception_type VARCHAR(200),
|
|||
|
|
exception_value TEXT,
|
|||
|
|
stack LONGTEXT,
|
|||
|
|
stack_symbolicated LONGTEXT,
|
|||
|
|
breadcrumbs JSON,
|
|||
|
|
tags JSON,
|
|||
|
|
device JSON,
|
|||
|
|
platform VARCHAR(30),
|
|||
|
|
release VARCHAR(50),
|
|||
|
|
environment VARCHAR(50) DEFAULT 'production',
|
|||
|
|
sdk_name VARCHAR(100),
|
|||
|
|
sdk_version VARCHAR(20),
|
|||
|
|
created_at DATETIME NOT NULL,
|
|||
|
|
UNIQUE KEY uk_event_id (app_key, event_id),
|
|||
|
|
INDEX idx_issue_created (issue_id, created_at),
|
|||
|
|
INDEX idx_app_key (app_key)
|
|||
|
|
);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### log_events — 自定义事件表
|
|||
|
|
|
|||
|
|
```sql
|
|||
|
|
CREATE TABLE log_events (
|
|||
|
|
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
|||
|
|
event_id VARCHAR(64) NOT NULL, -- 客户端幂等 ID
|
|||
|
|
app_key VARCHAR(64) NOT NULL,
|
|||
|
|
name VARCHAR(200) NOT NULL,
|
|||
|
|
user_id VARCHAR(128),
|
|||
|
|
session_id VARCHAR(128),
|
|||
|
|
properties JSON,
|
|||
|
|
platform VARCHAR(30),
|
|||
|
|
release VARCHAR(50),
|
|||
|
|
environment VARCHAR(50) DEFAULT 'production',
|
|||
|
|
device JSON,
|
|||
|
|
sdk_name VARCHAR(100),
|
|||
|
|
sdk_version VARCHAR(20),
|
|||
|
|
created_at DATETIME NOT NULL,
|
|||
|
|
UNIQUE KEY uk_event_id (app_key, event_id),
|
|||
|
|
INDEX idx_app_key_name (app_key, name),
|
|||
|
|
INDEX idx_app_key_user (app_key, user_id),
|
|||
|
|
INDEX idx_app_key_created (app_key, created_at)
|
|||
|
|
);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### log_sessions — Session 表
|
|||
|
|
|
|||
|
|
```sql
|
|||
|
|
CREATE TABLE log_sessions (
|
|||
|
|
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
|||
|
|
session_id VARCHAR(64) NOT NULL,
|
|||
|
|
app_key VARCHAR(64) NOT NULL,
|
|||
|
|
status VARCHAR(20) NOT NULL, -- ok | exited | crashed | abnormal
|
|||
|
|
user_id VARCHAR(128),
|
|||
|
|
platform VARCHAR(30),
|
|||
|
|
release VARCHAR(50),
|
|||
|
|
environment VARCHAR(50) DEFAULT 'production',
|
|||
|
|
started_at DATETIME NOT NULL,
|
|||
|
|
duration_ms BIGINT,
|
|||
|
|
errors INT NOT NULL DEFAULT 0,
|
|||
|
|
created_at DATETIME NOT NULL,
|
|||
|
|
UNIQUE KEY uk_session_id (app_key, session_id),
|
|||
|
|
INDEX idx_app_key_started (app_key, started_at),
|
|||
|
|
INDEX idx_app_key_status (app_key, status, started_at)
|
|||
|
|
);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### sourcemaps — 符号文件表
|
|||
|
|
|
|||
|
|
```sql
|
|||
|
|
CREATE TABLE sourcemaps (
|
|||
|
|
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
|||
|
|
app_key VARCHAR(64) NOT NULL,
|
|||
|
|
platform VARCHAR(30) NOT NULL,
|
|||
|
|
app_version VARCHAR(50) NOT NULL,
|
|||
|
|
bundle_name VARCHAR(100) DEFAULT 'index',
|
|||
|
|
file_path VARCHAR(500) NOT NULL,
|
|||
|
|
uploaded_at DATETIME NOT NULL,
|
|||
|
|
UNIQUE KEY uk_app_version_bundle (app_key, platform, app_version, bundle_name)
|
|||
|
|
);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 13. 变更日志
|
|||
|
|
|
|||
|
|
### v1.1.0(2026-06-17)
|
|||
|
|
|
|||
|
|
**New Features:**
|
|||
|
|
|
|||
|
|
- 上报认证:明确认证链路,`appKey` 由 SDK 从 `config.xuqm` 自动读取;服务端新增 BugCollect 服务激活校验(`t_feature_service.enabled`),未开通的 appKey 请求返回 `403 / 40301`
|
|||
|
|
- 幂等保障:IssueEvent / LogEvent 新增必填 `eventId`(UUID),服务端按此去重
|
|||
|
|
- Breadcrumbs:IssueEvent 新增 `breadcrumbs` 数组,携带崩溃前最近 50 条操作轨迹
|
|||
|
|
- device 字段扩充:新增 `locale`、`timezone`、`network`、`isEmulator`、`freeMemoryMb`、`buildType`
|
|||
|
|
- Session 上报:新增 `POST /bugcollect/v1/sessions/batch`,支持 crash-free session rate 计算
|
|||
|
|
- 符号化扩展:SourceMap 上传新增 `android`(ProGuard mapping)、`ios`(dSYM)平台支持
|
|||
|
|
- Issue 管理端点:新增 resolve / ignore / assign / bulk 操作
|
|||
|
|
- Issue 状态:`isResolved: boolean` 替换为 `status: open | resolved | ignored`,新增 `affectedUsers` 字段
|
|||
|
|
- Issue 详情拆分:`GET /issues/{id}` 不再内嵌 Event 列表,新增 `GET /issues/{id}/events` 分页接口
|
|||
|
|
- Issue 趋势:新增 `GET /issues/{id}/trend`
|
|||
|
|
- Webhook 事件扩充:新增 `issue.fatal`、`issue.threshold`、`issue.resolved`;回调体新增签名校验头
|
|||
|
|
- 概览统计:新增 `crashFreeSessionRate`、`openIssues`、`affectedUsers`
|
|||
|
|
- 全文搜索:Issue 列表新增 `q` 参数
|
|||
|
|
- 版本筛选:Issue 列表新增 `release` 参数
|
|||
|
|
- Environment:新增 `integration` 枚举值
|
|||
|
|
- 数据库:新增 `log_sessions` 表;`log_issues` 新增 `status`/`affected_users`/`assignee` 列;`log_issue_events` 新增 `event_id`/`breadcrumbs` 列;补全缺失索引
|
|||
|
|
|
|||
|
|
**Breaking Changes:**
|
|||
|
|
|
|||
|
|
- `isResolved` 字段已移除,改用 `status`(`isResolved: false` → `status: "open"`,`isResolved: true` → `status: "resolved"`)
|
|||
|
|
- Issue 详情响应不再包含 `events` 数组,需改用 `GET /issues/{id}/events`
|
|||
|
|
- 每条 Event 现在必须携带 `eventId`;缺失时返回 `400 / 40006`
|
|||
|
|
- BugCollect 服务未激活的 appKey 上报请求返回 `403 / 40301`
|
|||
|
|
|
|||
|
|
**Bug Fixes:**
|
|||
|
|
|
|||
|
|
- 修复 Fingerprint 算法中包含 `level` 字段的问题:相同堆栈的 `error` 和 `warning` 现在归为同一 Issue
|
|||
|
|
- 修复 Issue 列表查询参数使用废弃的 `type` 字段问题,统一改为 `level`
|
|||
|
|
- 修复 SDK 集成指南中 `BugCollect.setUser()` 错误引用,统一改为 `XuqmSDK.setUserInfo()`
|
|||
|
|
- 修复 Issue 详情示例响应中 `metadata` 字段未同步改名为 `tags` 的问题
|
|||
|
|
|
|||
|
|
### v1.0.0(2026-06-17)
|
|||
|
|
|
|||
|
|
**Breaking Changes:**
|
|||
|
|
|
|||
|
|
- 上报端点路径从 `/log/v1/` 统一为 `/bugcollect/v1/`
|
|||
|
|
- Issue 上报请求体从裸 JSON 数组改为信封格式 `{ "sentAt", "sdk", "events" }`
|
|||
|
|
- Issue 事件中 `type` 字段(`android_error` / `native_crash`)替换为 `level` 字段(`fatal` / `error` / `warning` / `info` / `debug`)
|
|||
|
|
- Issue 事件中 `message` + `stack` 平铺字段归入 `exception` 对象(`exception.type` / `exception.value` / `exception.stacktrace`)
|
|||
|
|
- Issue 事件中 `metadata` 重命名为 `tags`
|
|||
|
|
- Issue 事件中 `appVersion` 重命名为 `release`
|
|||
|
|
- Analytics 事件请求体同步改为信封格式
|
|||
|
|
|
|||
|
|
**New Features:**
|
|||
|
|
|
|||
|
|
- Issue 事件新增 `user`(用户信息)、`device`(设备信息)、`sdk`(SDK 自标识)字段
|
|||
|
|
- Issue 事件新增 `environment` 字段(`production` / `staging` / `development`)
|
|||
|
|
- Analytics 事件新增 `user`、`device`、`sdk`、`environment` 字段
|
|||
|
|
- 信封层新增 `sentAt`(时钟偏差校正)和 `sdk`(SDK 版本追踪)
|
|||
|
|
- 查询端点新增 `level` 筛选参数
|