fix(bugcollect): captureError 在 SDK 未就绪时暂存事件,就绪后自动 flush

- 添加 pendingErrors 队列,SDK 未初始化时 captureError 不再丢弃事件
- startCrashCapture 完成后自动 flush 暂存事件到上传队列
这个提交包含在:
XuqmGroup 2026-06-18 18:56:37 +08:00
父节点 d5ce5ffabb
当前提交 3ded960383

查看文件

@ -16,6 +16,9 @@ object BugCollect {
private val breadcrumbBuffer: LinkedList<Breadcrumb> = LinkedList() private val breadcrumbBuffer: LinkedList<Breadcrumb> = LinkedList()
private val breadcrumbLock = Any() private val breadcrumbLock = Any()
// SDK 未就绪时暂存的错误事件,就绪后自动 flush
private val pendingErrors = LinkedList<IssueEvent>()
private val pendingErrorsLock = Any()
private const val MAX_BREADCRUMBS = 50 private const val MAX_BREADCRUMBS = 50
private const val SDK_NAME = "bugcollect.android" private const val SDK_NAME = "bugcollect.android"
private const val SDK_VERSION = "1.1.0" private const val SDK_VERSION = "1.1.0"
@ -53,14 +56,13 @@ object BugCollect {
} }
fun captureError(error: Throwable, tags: Map<String, Any?> = emptyMap(), fingerprint: String? = null) { fun captureError(error: Throwable, tags: Map<String, Any?> = emptyMap(), fingerprint: String? = null) {
if (!isReady()) return
val crumbs = synchronized(breadcrumbLock) { breadcrumbBuffer.toList() } val crumbs = synchronized(breadcrumbLock) { breadcrumbBuffer.toList() }
val fp = fingerprint ?: Fingerprint.compute( val fp = fingerprint ?: Fingerprint.compute(
error.javaClass.simpleName, error.javaClass.simpleName,
error.message ?: error.javaClass.name, error.message ?: error.javaClass.name,
error.stackTraceToString(), error.stackTraceToString(),
) )
queue().push(IssueEvent( val event = IssueEvent(
level = "error", level = "error",
platform = "android", platform = "android",
fingerprint = fp, fingerprint = fp,
@ -77,7 +79,13 @@ object BugCollect {
user = IssueEvent.UserInfo(id = XuqmSDK.getUserId() ?: XuqmSDK.deviceId), user = IssueEvent.UserInfo(id = XuqmSDK.getUserId() ?: XuqmSDK.deviceId),
device = buildDeviceInfo(), device = buildDeviceInfo(),
tags = tags, tags = tags,
)) )
if (!isReady()) {
synchronized(pendingErrorsLock) { pendingErrors.add(event) }
return
}
flushPendingErrors()
queue().push(event)
} }
fun captureCrash(error: Throwable, tags: Map<String, Any?> = emptyMap()) { fun captureCrash(error: Throwable, tags: Map<String, Any?> = emptyMap()) {
@ -143,9 +151,21 @@ object BugCollect {
appKey = XuqmSDK.appKey, appKey = XuqmSDK.appKey,
getUserId = { XuqmSDK.getUserId() ?: XuqmSDK.deviceId }, getUserId = { XuqmSDK.getUserId() ?: XuqmSDK.deviceId },
) )
flushPendingErrors()
queue().uploadPendingCrashes() queue().uploadPendingCrashes()
} }
/** 将 SDK 未就绪时暂存的错误事件 flush 到队列。 */
private fun flushPendingErrors() {
val events = synchronized(pendingErrorsLock) {
if (pendingErrors.isEmpty()) return
val list = pendingErrors.toList()
pendingErrors.clear()
list
}
events.forEach { queue().push(it) }
}
/** 上传上次崩溃落盘的文件(远端配置就绪后由 BugCollectInitProvider 自动调用)。 */ /** 上传上次崩溃落盘的文件(远端配置就绪后由 BugCollectInitProvider 自动调用)。 */
fun uploadPendingCrashes() { fun uploadPendingCrashes() {
if (isReady()) queue().uploadPendingCrashes() if (isReady()) queue().uploadPendingCrashes()