Skip to main content

自定义数据接口

Bugly 提供了丰富的自定义数据上报和查询支持。允许在上报 Bugly 事件时,业务携带自定义的字段到 Bugly 数据中,按照业务的定义和需求进行查询和分析。

关于自定义字段的查询使用,可以参考数据分析-自定义数据

在 iOS SDK 中,设置自定义字段,主要有两种方式。一是通过业务主动调用设置相关字段,Bugly 在上报时携带其内容;二是 Bugly 在产生数据上报时,通过回调通知业务,业务在此时返回需要携带的字段给 Bugly。前者作用与全局,后者仅对当次上报有效。

下面就是相关接口进行详细介绍和使用。

主动调用接口

Bugly.h

Bugly.h 中相关接口属于全局接口,在未指定特殊类型的情况下,其对所有的数据上报均生效。

  1. 设置和获取全局的自定义字段,每次调用设置接口会覆盖前一次设置,因此可以获取已有字段后,进行局部更新;
/**
* 添加自定义上报的tag, SDK初始化前调用无效
* @param data 需要更新的自定义字段
*/
+ (void)updateCustomData:(BuglyCustomData *)data;

/**
* 获取当前自定标签的副本信息,若未设置,返回空
* @return 已设置的用户自定义字段
*/
+ (nullable BuglyCustomData *)currentCustomData;
  1. 按照事件类型设置和获取自定义字段,同全局设置会存在覆盖关系;其仅对对应事件的上报生效;
/**
* 添加自定义数据为特定的事件上报
* @param data 需要更新的自定义字段
* @param eventType 对应的事件类型
*/
+ (void)updateCustomData:(BuglyCustomData *)data forEvent:(BuglyEventTypeName)eventType;

/**
* 获取特定事件的当前自定义数据
* @param eventType 需要获取的事件类型
* @return 对应已设置的自定义字段
*/
+ (nullable BuglyCustomData *)currentCustomDataForEvent:(BuglyEventTypeName)eventType;

其中,BuglyCustomDataBuglyEventTypeName 事件类型的定义在 BuglyCustomData.h 中。

因对自定义字段的值有一定的限制规则,因此需要通过 BuglyCustomData 类进行管理,以实现校验和更新的机制。

重要提醒

需要注意的是,BuglyCustomData 虽然提供了使用 NSDictory 进行初始化和更新的接口,但是会对其中的 key 进行严格检查,对于不符合规则的 key 会全部过滤。因此不建议直接使用字典进行初始化和更新。

BuglyCustomData 提供了对应的增加、删除自定义字段的接口,但是限制了其 key,需要使用文件中声明的 BuglyCustomNumberDataKeyBuglyCustomStringDataKeyBuglyCustomArrayDataKey等常量作为 key,除此以外的 key 都将被过滤。

为了后台高效进行数据入库和查询,Bugly 对上报字段做了限制,因此会产生以上的规则。因此其可以作为“自定义维度”字段使用,实现高效的维度数据下钻分析。

这里给到一个简单的例子,展示 BuglyCustomData 的使用方法。

// 获取现有的自定义字段值
BuglyCustomData *customData = [Bugly currentCustomData];
// 更新新的字段值
[customData putStringParam:@"cust_string_value" forKey:BuglyCustomStringDataKey2];
// 更新全局值
[Bugly updateCustomData:customData];

上面例子为典型的一种更新方式,先获取现有值,更行其中的字段后,再整体更行;移除和其他操作也是类似,若只针对特殊类型的事件进行更新,只需要使用对应的 forEvent 方法即可。

BuglyCrashMonitorPlugin.h

BuglyCrashMonitorPlugin.h 中的接口为了满足 Crash 上报的需求,保留仅对 Crash 上报有效的接口。

这部分接口在 Bugly+Deprecated.h 文件中有相关的接口,在内部调用实现时一致的,仅保留用作 SDK 升级兼容使用。

  1. 设置 Crash 上报相关的自定义字段;
/**
* 设置关键数据,随崩溃信息上报
*
* @param value KEY
* @param key VALUE
*/
+ (void)setUserValue:(NSString *)value forKey:(NSString *)key;

/**
* 获取关键数据
*
* @return 关键数据
*/
+ (NSDictionary * _Nullable)allUserValues;

此处设置的内容没有对 key 和 value 做严格的限制检查,也因此其仅对 Crash 部分生效,且在 Bugly 平台无法支持指标下钻查询,仅在个例的“现场数据 - 自定义字段”中展示。

  1. 自定义异常上报,用来业务自己调用上报异常信息等;
/**
* 上报自定义Objective-C异常
*
* @param exception 异常信息
*/
+ (void)reportException:(NSException *)exception;

/**
* 上报错误
*
* @param error 错误信息
*/
+ (void)reportError:(NSError *)error;

/**
* @brief 上报自定义错误
*
* @param category 类型(Cocoa=3,CSharp=4,JS=5,Lua=6)
* @param aName 名称
* @param aReason 错误原因
* @param aStackArray 堆栈
* @param info 附加数据,需要 key、value 均为 NSString 类型
* @param terminate 上报后是否退出应用进程
*/
+ (void)reportExceptionWithCategory:(NSUInteger)category
name:(NSString *)aName
reason:(NSString *)aReason
callStack:(NSArray *)aStackArray
extraInfo:(NSDictionary <NSString *, NSString *> *)info
terminateApp:(BOOL)terminate;

/**
* @brief 上报自定义 crash 的堆栈
* 1. 该上报接口会 dump 全部线程信息,解析 stackArr 中堆栈作为 crash 线程的堆栈上报到后台
* 2. 调用该接口后,会关闭 crash 的监控,但不会主动杀进程,因此业务应该主动杀进程以规避异常。
* 3. 和“reportException”、“reportError”、“reportExceptionWithCategory”方法不同,该方法会生成一条crash 上报,并算在用户的 crash 率
* 因此该方法适合一些信息不全的crash上报,例如 “Kotlin Exception”
* 4. 为了能够识别堆栈地址并上报,stackArr 应该为 "[index] [image name] [address] [others]" 的结构,中间用空格或者tab键隔开
* 例如 "0 RMonitorExample 0x102b38347 ThrowArrayIndexOutOfBoundsException + 159",
* 5. 该接口仅在 bugly sdk 初始化结束后生效
*/
+ (void)reportUnhandledCrash:(BuglyUnhandledCrash)type
name:(NSString *)name
reason:(NSString *)reason
callStack:(NSArray<NSString *> *)stackArr;
重要提醒

需要注意的是调用频率问题,对于部分频繁发生的异常(通常是业务通过 try-catch 捕获),大量上报可能造成大量无用数据,增加 Bugly 后台负担或导致大量占用事件量。

回调接口

回调接口指 Bugly 通过 BuglyDelegate(定义在 BuglyDelegate.h 文件中)接口回调的情况。使用时,业务方需要提供一个实现该接口的实例给到 Bugly 中,例如:

BuglyConfig *config = [[BuglyConfig alloc] initWithAppId:@"appid" appKey:@"appkey"];
config.delegate = self; // self 指实现了 BuglyDelegate 的实例

需要格外强调的是,Bugly 不会强引用该实例对线,业务方需要确保其生命周期符合预期。

BuglyDelegate 中提供两个主回调方法:

1. 通用回调接口:

/// 允许业务带附件到个例上报中
/// @param eventType 个例事件类型
/// @param customData 业务自定义字段
/// @param eventInfo 个例信息,暂为空
- (NSDictionary<NSString *, NSString *> *)attachmentForEvent:(NSString *)eventType
customData:(BuglyCustomData *)customData
eventInfo:(NSDictionary *)eventInfo;

该方法回调会对所有的上报生效,其参数和返回值的定义如下:

  1. 参数 eventType 来区分不同的事件类型,eventType 的取值与前述中的 BuglyEventTypeName 一致;

  2. 参数 customData 为对应上报事件已携带的自定义字段的内容,若需要增加或者更新字段,可以直接对 customData 对象进行操作,完成更新。需要说明的是此处的更新仅针对这一次上报生效,若要对全局生效,参考前述中的主动接口;

  3. 参数 eventInfo 为对应事件的附加字段,这个内容因事件不同而携带的内容会有差异,内容仅提供给业务使用,不会通过 Bugly 上报;

  4. 返回值,业务在处理完事件后,需要返回一个字典,其中的内容为需要 Bugly 上的自定义字段内容,与 customData 中的内容不同的是,这部分字段的值仅提供展示筛选,无法在 Bugly 平台进行指标的分析下钻。返回内容都会进行校验,字典中的 key 和 value 必须都是 NSString 类型,且 key 长度不能超过 50 个字符,value 的长度不超过 1024 字符,字典大小不超过 20 个元素,所有超过部分会被截断。

2. 异常事件回调接口:

/**
* 发生异常时回调
* @param exception 异常信息
* @return 返回需上报记录,随异常上报一起上报
*/
- (NSString * __nullable)attachmentForException:(NSException * __nullable)exception;

上报异常时会回调该接口,其中 exception 为发生的异常信息。对于 cpp exception,signal 等异常信息,同样会转为 NSException 对象进行处理。

业务需要注意的是,此接口可能是二次启动时回调,不一定在异常发生的时刻。

重要提醒

回调接口会阻塞 Bugly 内部的上报逻辑,因此对 Bugly 事件上报成功率同样存在影响。业务在回调接口中的操作需要尽可能的简单高效,避免因为回调的异常导致 Bugly 上报事件丢失。

实时回调接口

在 2.8.0 版本中,新增了部分监控数据实时回调接口,SDK 会将监控到的部分指标/异常数据实时回调给业务使用。

1. 注册回调事件

在 Bugly 中,提供如下接口(Bugly.h):

+ (void)setBuglyMonitorCallback:(nullable BuglyMonitorCallback)callback
forEvent:(BuglyMonitorCallbackEvent)event;

用于注册需要的业务对应的回调接口,其中 BuglyMonitorCallback, BuglyMonitorCallbackEvent 的定义在 BuglyMonitorCallback.h 中。

BuglyMonitorCallbackEvent 仅可使用枚举中定义的类型,其他类型设置无效。同一类型再次设置会覆盖之前的设置结果,置为 nil 时则为清空对应的设置。

2. 回调接口说明

typedef void (^BuglyMonitorCallback)(BuglyMonitorCallbackEvent event, NSDictionary *eventInfo);

该回调接口拥有两个参数,第一个是 BuglyMonitorCallbackEvent 枚举类型,第二个为对应事件的具体信息。

事件信息为 NSDictionary, 其内容由具体的事件决定。

例如目前支持的 BuglyMonitorCallbackEvent_FPS 其中的内容为

@{@"fps": @(realTimeFPS)}

3. 回调频率

实时回调接口调用线程不定,应不同类型会有区别。业务在使用时应注意是否存在线程安全等问题。

其次回调可能存在延迟和滞后,这是限于各类指标收集和统计的局限所致。例如 FPS 每秒回调,其结果为上一秒的帧率。限于指标收集的局限,无法提供当前时刻的帧率信息。

重要提醒

需要特别注意的是,由于接口是高频率调用,因此业务在回调中需要快速处理,不要阻塞回调线程。长时间阻塞可能导致数据积压,对监控逻辑造成不良影响。