fix(mobile/telemetry): buffer pre-init events instead of dropping them
Root cause: TelemetryService.initialize() is async (device info collection,
SharedPreferences I/O, remote config sync), taking several hundred ms to
complete. RouteObserver page_view events and auth events fire synchronously
during the initial navigation before initialization finishes, causing the
"TelemetryService not initialized, event ignored" drops seen in logs.
Fix: add _preInitBuffer (max 50 events). logEvent() now enqueues events
instead of dropping when _isInitialized=false. After initialization
completes, all buffered events are replayed in order via logEvent(),
ensuring no startup events are lost.
The network errors ("Failed host lookup: api.gogenex.com") are unrelated —
they are expected in offline test environments and handled gracefully.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
9bcb1f864d
commit
918489e4e5
|
|
@ -45,6 +45,16 @@ class TelemetryService {
|
|||
bool _isInitialized = false;
|
||||
bool get isInitialized => _isInitialized;
|
||||
|
||||
/// 初始化完成前的事件缓冲队列
|
||||
///
|
||||
/// 解决启动时序问题:initialize() 是异步的(需要收集设备信息、
|
||||
/// 加载配置等),而 RouteObserver/auth 事件可能在初始化完成前
|
||||
/// 就已触发。将这些事件缓存,初始化完成后统一 replay,确保不丢失。
|
||||
///
|
||||
/// 上限 50 条,防止极端情况下内存积累。
|
||||
final List<_PendingEvent> _preInitBuffer = [];
|
||||
static const int _maxPreInitBuffer = 50;
|
||||
|
||||
/// 会话管理器
|
||||
late SessionManager _sessionManager;
|
||||
|
||||
|
|
@ -135,6 +145,16 @@ class TelemetryService {
|
|||
debugPrint('📊 TelemetryService initialized');
|
||||
debugPrint(' InstallId: $_installId');
|
||||
debugPrint(' UserId: $_userId');
|
||||
|
||||
// Replay 初始化前缓冲的事件(如 page_view、session 启动事件等)
|
||||
if (_preInitBuffer.isNotEmpty) {
|
||||
debugPrint('📊 [Telemetry] Replaying ${_preInitBuffer.length} buffered pre-init events');
|
||||
final buffered = List<_PendingEvent>.from(_preInitBuffer);
|
||||
_preInitBuffer.clear();
|
||||
for (final e in buffered) {
|
||||
logEvent(e.eventName, type: e.type, level: e.level, properties: e.properties);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 初始化 installId
|
||||
|
|
@ -167,7 +187,15 @@ class TelemetryService {
|
|||
Map<String, dynamic>? properties,
|
||||
}) {
|
||||
if (!_isInitialized) {
|
||||
debugPrint('⚠️ TelemetryService not initialized, event ignored');
|
||||
// 缓冲事件,等初始化完成后 replay,不丢弃
|
||||
if (_preInitBuffer.length < _maxPreInitBuffer) {
|
||||
_preInitBuffer.add(_PendingEvent(
|
||||
eventName: eventName,
|
||||
type: type,
|
||||
level: level,
|
||||
properties: properties,
|
||||
));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -394,3 +422,18 @@ class TelemetryService {
|
|||
_instance = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// 初始化前缓冲的待处理事件(内部使用)
|
||||
class _PendingEvent {
|
||||
final String eventName;
|
||||
final EventType type;
|
||||
final EventLevel level;
|
||||
final Map<String, dynamic>? properties;
|
||||
|
||||
const _PendingEvent({
|
||||
required this.eventName,
|
||||
required this.type,
|
||||
required this.level,
|
||||
this.properties,
|
||||
});
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue