feat(bugcollect): 更新 API 端点并改进数据结构
- 将 Android SDK 的 mapping 上传端点从 /log/v1/sourcemaps/upload 更改为 /bugcollect/v1/sourcemaps/upload - 将 RN SDK 的 API 端点从 /log/v1/ 统一更改为 /bugcollect/v1/ - 在 LogQueue.ts 的请求体中添加 sentAt 时间戳和 SDK 信息 - 重构 BugCollect.ts 中的事件结构,将 appVersion 重命名为 release,添加 environment 和 sdk 字段 - 将 JS 错误上报的类型从 js_error 改为 issue,并调整错误级别分类 - 为 warn 和 info 方法添加完整的 issue 事件结构 - 在 types.ts 中添加新的数据类型定义,包括 Level、Platform、SdkInfo、ExceptionInfo 等 - 为 IssueEvent 添加详细的异常信息结构,包括类型、值和堆栈跟踪 - 添加完整的错误收集 API v1 规范审阅报告文档 - 在数据库迁移脚本中为日志表添加新字段,包括级别、环境、设备信息、SDK 信息等
这个提交包含在:
父节点
639e9bcc26
当前提交
76099d897e
@ -22,7 +22,7 @@ function withBugCollect(metroConfig) {
|
|||||||
// TODO: 补全 SourceMap 上传逻辑
|
// TODO: 补全 SourceMap 上传逻辑
|
||||||
// 1. 读取 .xuqmconfig 或 xuqm.config.js 获取 bugCollectApiUrl
|
// 1. 读取 .xuqmconfig 或 xuqm.config.js 获取 bugCollectApiUrl
|
||||||
// 2. 读取 sourceMapUrl 对应的 .map 文件
|
// 2. 读取 sourceMapUrl 对应的 .map 文件
|
||||||
// 3. 上传到 bugCollectApiUrl/log/v1/sourcemaps/upload
|
// 3. 上传到 bugCollectApiUrl/bugcollect/v1/sourcemaps/upload
|
||||||
}
|
}
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|||||||
@ -66,13 +66,15 @@ export const BugCollect = {
|
|||||||
const event: LogEvent = {
|
const event: LogEvent = {
|
||||||
type: 'event',
|
type: 'event',
|
||||||
name,
|
name,
|
||||||
properties: properties ? { ...properties, environment: _environment } : { environment: _environment },
|
properties,
|
||||||
timestamp: Date.now(),
|
timestamp: Date.now(),
|
||||||
userId: getUserId() ?? undefined,
|
userId: getUserId() ?? undefined,
|
||||||
sessionId: _sessionId,
|
sessionId: _sessionId,
|
||||||
appKey: getConfig().appKey,
|
appKey: getConfig().appKey,
|
||||||
platform: _getPlatform(),
|
platform: _getPlatform(),
|
||||||
appVersion: _getAppVersion(),
|
release: _getAppVersion(),
|
||||||
|
environment: _environment,
|
||||||
|
sdk: { name: 'bugcollect.rn', version: '0.2.0' },
|
||||||
}
|
}
|
||||||
_enqueue(event)
|
_enqueue(event)
|
||||||
FunnelTracker.track(name, properties)
|
FunnelTracker.track(name, properties)
|
||||||
@ -83,17 +85,23 @@ export const BugCollect = {
|
|||||||
if (!isInitialized()) return
|
if (!isInitialized()) return
|
||||||
const err = error instanceof Error ? error : new Error(String(error))
|
const err = error instanceof Error ? error : new Error(String(error))
|
||||||
const issue: IssueEvent = {
|
const issue: IssueEvent = {
|
||||||
type: 'js_error',
|
type: 'issue',
|
||||||
message: err.message,
|
level: 'error',
|
||||||
stack: err.stack,
|
platform: _getPlatform(),
|
||||||
fingerprint: computeFingerprint('js_error', err.message, err.stack),
|
fingerprint: computeFingerprint('error', err.message, err.stack),
|
||||||
timestamp: Date.now(),
|
timestamp: Date.now(),
|
||||||
|
appKey: getConfig().appKey,
|
||||||
|
release: _getAppVersion(),
|
||||||
|
environment: _environment,
|
||||||
|
exception: {
|
||||||
|
type: err.name ?? 'Error',
|
||||||
|
value: err.message,
|
||||||
|
stacktrace: err.stack,
|
||||||
|
},
|
||||||
userId: getUserId() ?? undefined,
|
userId: getUserId() ?? undefined,
|
||||||
sessionId: _sessionId,
|
sessionId: _sessionId,
|
||||||
appKey: getConfig().appKey,
|
tags: metadata,
|
||||||
platform: _getPlatform(),
|
sdk: { name: 'bugcollect.rn', version: '0.2.0' },
|
||||||
appVersion: _getAppVersion(),
|
|
||||||
metadata: metadata ? { ...metadata, environment: _environment } : { environment: _environment },
|
|
||||||
}
|
}
|
||||||
_enqueue(issue)
|
_enqueue(issue)
|
||||||
},
|
},
|
||||||
@ -101,13 +109,51 @@ export const BugCollect = {
|
|||||||
/** Log a warning (if log level allows). */
|
/** Log a warning (if log level allows). */
|
||||||
warn(message: string, metadata?: Record<string, unknown>): void {
|
warn(message: string, metadata?: Record<string, unknown>): void {
|
||||||
if (_levelNum(_logLevel) > _levelNum('warn')) return
|
if (_levelNum(_logLevel) > _levelNum('warn')) return
|
||||||
BugCollect.captureError(new Error(message), { ...metadata, level: 'warn' })
|
if (!isInitialized()) return
|
||||||
|
const issue: IssueEvent = {
|
||||||
|
type: 'issue',
|
||||||
|
level: 'warning',
|
||||||
|
platform: _getPlatform(),
|
||||||
|
fingerprint: computeFingerprint('warning', message),
|
||||||
|
timestamp: Date.now(),
|
||||||
|
appKey: getConfig().appKey,
|
||||||
|
release: _getAppVersion(),
|
||||||
|
environment: _environment,
|
||||||
|
exception: {
|
||||||
|
type: 'Warning',
|
||||||
|
value: message,
|
||||||
|
},
|
||||||
|
userId: getUserId() ?? undefined,
|
||||||
|
sessionId: _sessionId,
|
||||||
|
tags: metadata,
|
||||||
|
sdk: { name: 'bugcollect.rn', version: '0.2.0' },
|
||||||
|
}
|
||||||
|
_enqueue(issue)
|
||||||
},
|
},
|
||||||
|
|
||||||
/** Log an informational event (if log level allows). */
|
/** Log an informational event (if log level allows). */
|
||||||
info(message: string, metadata?: Record<string, unknown>): void {
|
info(message: string, metadata?: Record<string, unknown>): void {
|
||||||
if (_levelNum(_logLevel) > _levelNum('info')) return
|
if (_levelNum(_logLevel) > _levelNum('info')) return
|
||||||
BugCollect.event('__log_info', { message, ...metadata })
|
if (!isInitialized()) return
|
||||||
|
const issue: IssueEvent = {
|
||||||
|
type: 'issue',
|
||||||
|
level: 'info',
|
||||||
|
platform: _getPlatform(),
|
||||||
|
fingerprint: computeFingerprint('info', message),
|
||||||
|
timestamp: Date.now(),
|
||||||
|
appKey: getConfig().appKey,
|
||||||
|
release: _getAppVersion(),
|
||||||
|
environment: _environment,
|
||||||
|
exception: {
|
||||||
|
type: 'Info',
|
||||||
|
value: message,
|
||||||
|
},
|
||||||
|
userId: getUserId() ?? undefined,
|
||||||
|
sessionId: _sessionId,
|
||||||
|
tags: metadata,
|
||||||
|
sdk: { name: 'bugcollect.rn', version: '0.2.0' },
|
||||||
|
}
|
||||||
|
_enqueue(issue)
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -35,8 +35,8 @@ export class LogQueue {
|
|||||||
const events = batch.filter(e => e.type === 'event')
|
const events = batch.filter(e => e.type === 'event')
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (issues.length > 0) await this._post('/log/v1/issues/batch', issues)
|
if (issues.length > 0) await this._post('/bugcollect/v1/issues/batch', issues)
|
||||||
if (events.length > 0) await this._post('/log/v1/events/batch', events)
|
if (events.length > 0) await this._post('/bugcollect/v1/events/batch', events)
|
||||||
this.retryCount = 0
|
this.retryCount = 0
|
||||||
} catch {
|
} catch {
|
||||||
this.retryCount++
|
this.retryCount++
|
||||||
@ -56,7 +56,7 @@ export class LogQueue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async _post(path: string, data: BugCollectEvent[]): Promise<void> {
|
private async _post(path: string, data: BugCollectEvent[]): Promise<void> {
|
||||||
const body = JSON.stringify({ events: data })
|
const body = JSON.stringify({ sentAt: new Date().toISOString(), sdk: { name: 'bugcollect.rn', version: '0.2.0' }, events: data })
|
||||||
const res = await fetch(`${this.cfg.bugCollectApiUrl}${path}`, {
|
const res = await fetch(`${this.cfg.bugCollectApiUrl}${path}`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
|
|||||||
@ -1,5 +1,30 @@
|
|||||||
export type LogLevel = 'debug' | 'info' | 'warn' | 'error'
|
export type LogLevel = 'debug' | 'info' | 'warn' | 'error'
|
||||||
export type Environment = 'development' | 'staging' | 'production'
|
export type Environment = 'development' | 'staging' | 'production'
|
||||||
|
export type Level = 'fatal' | 'error' | 'warning' | 'info' | 'debug'
|
||||||
|
export type Platform = 'ios' | 'android' | 'harmonyos' | 'web' | 'react-native'
|
||||||
|
|
||||||
|
export interface SdkInfo {
|
||||||
|
name: string
|
||||||
|
version: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ExceptionInfo {
|
||||||
|
type: string
|
||||||
|
value: string
|
||||||
|
stacktrace?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UserInfo {
|
||||||
|
id?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DeviceInfo {
|
||||||
|
name?: string
|
||||||
|
model?: string
|
||||||
|
manufacturer?: string
|
||||||
|
osName?: string
|
||||||
|
osVersion?: string
|
||||||
|
}
|
||||||
|
|
||||||
export interface LogEvent {
|
export interface LogEvent {
|
||||||
type: 'event'
|
type: 'event'
|
||||||
@ -9,24 +34,37 @@ export interface LogEvent {
|
|||||||
userId?: string
|
userId?: string
|
||||||
sessionId: string
|
sessionId: string
|
||||||
appKey: string
|
appKey: string
|
||||||
platform: 'ios' | 'android'
|
platform: Platform
|
||||||
appVersion: string
|
release: string
|
||||||
fingerprint?: string
|
environment?: Environment
|
||||||
|
user?: UserInfo
|
||||||
|
device?: DeviceInfo
|
||||||
|
sdk?: SdkInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IssueEvent {
|
export interface IssueEvent {
|
||||||
type: 'js_error' | 'native_crash' | 'api_error' | 'warning'
|
type: 'issue'
|
||||||
message: string
|
level: Level
|
||||||
stack?: string
|
platform: Platform
|
||||||
fingerprint: string
|
fingerprint: string
|
||||||
count?: number
|
|
||||||
timestamp: number
|
timestamp: number
|
||||||
userId?: string
|
|
||||||
sessionId: string
|
|
||||||
appKey: string
|
appKey: string
|
||||||
platform: 'ios' | 'android'
|
release: string
|
||||||
appVersion: string
|
environment?: Environment
|
||||||
metadata?: Record<string, unknown>
|
exception?: ExceptionInfo
|
||||||
|
userId?: string
|
||||||
|
sessionId?: string
|
||||||
|
user?: UserInfo
|
||||||
|
device?: DeviceInfo
|
||||||
|
tags?: Record<string, unknown>
|
||||||
|
sdk?: SdkInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
export type BugCollectEvent = LogEvent | IssueEvent
|
export type BugCollectEvent = LogEvent | IssueEvent
|
||||||
|
|
||||||
|
/** Envelope sent in the POST body */
|
||||||
|
export interface BugCollectEnvelope {
|
||||||
|
sentAt?: string
|
||||||
|
sdk?: SdkInfo
|
||||||
|
events: BugCollectEvent[]
|
||||||
|
}
|
||||||
|
|||||||
正在加载...
在新工单中引用
屏蔽一个用户