跳转至

数据采集自定义规则

View

需要开启配置 FTRUMConfig.enableTraceUserView = YES

rumConfig.viewTrackingHandler = [CustomViewTracker new];

#import "FTDefaultUIKitViewTrackingHandler.h"

// 协议实现方式示例
@interface CustomViewTracker : NSObject <FTUIKitViewTrackingHandler>
// 仅在需要 SDK 默认的 view 采集规则时添加
@property (nonatomic, strong) FTDefaultUIKitViewTrackingHandler defaultHandler;
@end

@implementation CustomViewTracker

// 仅在需要 SDK 默认的 view 采集规则时添加
-(FTDefaultUIKitViewTrackingHandler *)defaultHandler{
    if (!_defaultHandler) {
        _defaultHandler = [FTDefaultUIKitViewTrackingHandler new];
    }
    return _defaultHandler;
}

- (FTRUMView *)rumViewForViewController:(UIViewController *)viewController {
    // 通过类名精确匹配
    if ([viewController isKindOfClass:[HomeViewController class]]) {
        return [[FTRUMView alloc] initWithViewName:@"main_home" property:@{@"page_type": @"home"}];
    }
    // 通过前缀过滤
    else if ([NSStringFromClass([viewController class]) hasPrefix:@"FT"]) {
        return [[FTRUMView alloc] initWithViewName:[NSString stringWithFormat:@"ft_%@", NSStringFromClass([viewController class])] property:nil];
    }
    // 通过 accessibilityLabel 设置
    else if (viewController.view.accessibilityLabel) {
        return [[FTRUMView alloc] initWithViewName:viewController.view.accessibilityLabel property:nil];
    }
    // 自定义部分页面后,剩余页面使用 SDK 默认采集规则(返回默认处理器的处理结果)
    return [self.defaultHandler rumViewForViewController:viewController];

    // 若需要跳过追踪,直接返回 nil 即可
    return nil;
}
@end
rumConfig.viewTrackingHandler = CustomViewTracker()

class CustomViewTracker: NSObject, FTUIKitViewTrackingHandler {

    // 仅在需要 SDK 默认 view 采集规则时保留该属性
    lazy var defaultHandler: FTDefaultUIKitViewTrackingHandler = {
        FTDefaultUIKitViewTrackingHandler() 
    }()

    func rumView(for viewController: UIViewController) -> FTRUMView? {
        // 通过类名精确匹配
        if viewController is HomeViewController {
            let properties: [String: Any] = ["page_type": "home"]
            return FTRUMView(viewName: "main_home", property: properties)
        }

        // 通过类名前缀过滤
        let vcClassName = String(describing: type(of: viewController))
        if vcClassName.hasPrefix("FT") {
            let viewName = "ft_\(vcClassName)"
            return FTRUMView(viewName: viewName, property: nil)
        }

        // 通过 accessibilityLabel 设置
        if let accessibilityLabel = viewController.view.accessibilityLabel, !accessibilityLabel.isEmpty {
            return FTRUMView(viewName: accessibilityLabel, property: nil)
        }

        // 自定义部分页面后,剩余页面使用 SDK 默认采集规则(返回默认处理器的处理结果)
        return defaultHandler.rumView(for: viewController)

        // 若需要跳过追踪,直接返回 nil 即可
        return nil
    }
}

Action

需要开启配置 FTRUMConfig.enableTraceUserAction = YES

rumConfig.actionTrackingHandler = [CustomActionTracker new];

#import "FTDefaultActionTrackingHandler.h"

// 协议实现方式示例
// 在 iOS 环境需遵循 `FTUIPressRUMActionsHandler` 协议
// 在 tvOS 环境 ,需遵循 `FTUITouchRUMActionsHandler` 协议。
@interface CustomActionTracker : NSObject <FTUIPressRUMActionsHandler,FTUITouchRUMActionsHandler>
// 仅在需要 SDK 默认的 Action 采集规则时添加
@property (nonatomic, strong) FTDefaultActionTrackingHandler defaultHandler;
@end
@implementation CustomActionTracker

// 仅在需要 SDK 默认的 Action 采集规则时添加
-(FTDefaultActionTrackingHandler *)defaultHandler{
    if (!_defaultHandler) {
        _defaultHandler = [FTDefaultActionTrackingHandler new];
    }
    return _defaultHandler;
}

// iOS 与 tvOS 都需要实现的协议方法
- (nullable FTRUMAction *)rumLaunchActionWithLaunchType:(FTLaunchType)type {
    if(type == FTLaunchCold){
      return [[FTRUMAction alloc]initWithActionName:@"cold"];
    }
    // 返回 nil 跳过跟踪
    return nil;
}

// iOS 环境需实现的协议方法
-(nullable FTRUMAction *)rumActionWithTargetView:(UIView *)targetView{
    if (view.accessibilityIdentifier){
       return [[FTRUMAction alloc] initWithActionName:view.accessibilityIdentifier];
    }

     // 自定义部分 Action 后,剩余使用 SDK 默认采集规则(返回默认处理器的处理结果)
    return [self.defaultHandler rumActionWithTargetView:targetView];

    // 返回 nil 跳过跟踪
    return nil;
}
// tvOS 环境需实现的协议方法
- (nullable FTRUMAction *)rumActionWithPressType:(UIPressType)type targetView:(UIView *)targetView{
    if (type == UIPressTypeSelect && view.accessibilityIdentifier){
       return [[FTRUMAction alloc] initWithActionName:view.accessibilityIdentifier];
    }

    // 自定义部分 Action 后,剩余使用 SDK 默认采集规则(返回默认处理器的处理结果)
    return [self.defaultHandler rumActionWithPressType:type targetView:targetView];

        // 返回 nil 跳过跟踪
    return nil;
}
@end
rumConfig.actionTrackingHandler = CustomActionTracker()

// 协议实现方式示例
// 在 iOS 环境需遵循 `FTUIPressRUMActionsHandler` 协议
// 在 tvOS 环境 ,需遵循 `FTUITouchRUMActionsHandler` 协议。
class CustomActionTracker: NSObject, FTUIPressRUMActionsHandler, FTUITouchRUMActionsHandler {

    // 仅在需要 SDK 默认的 Action 采集规则时添加
    lazy var defaultHandler: FTDefaultActionTrackingHandler = {
        FTDefaultActionTrackingHandler()
    }()

    // iOS 与 tvOS 都需要实现的协议方法
    func rumLaunchAction(with type: FTLaunchType) -> FTRUMAction? {
        if type == .cold {
            return FTRUMAction(actionName: "cold")
        }
        // 返回 nil 跳过跟踪
        return nil
    }

    // iOS 环境需实现的协议方法
    func rumAction(withTargetView targetView: UIView) -> FTRUMAction? {
        if let identifier = targetView.accessibilityIdentifier {
            return FTRUMAction(actionName: identifier)
        }

        // 自定义部分 Action 后,剩余使用 SDK 默认采集规则(返回默认处理器的处理结果)
        return defaultHandler.rumAction(withTargetView: targetView)

        // 返回 nil 跳过跟踪
        return nil 
    }

    // tvOS 环境需实现的协议方法
    func rumAction(with pressType: UIPress.PressType, targetView: UIView) -> FTRUMAction? {
        if pressType == .select, let identifier = targetView.accessibilityIdentifier {
            return FTRUMAction(actionName: identifier)
        }

        // 自定义部分 Action 后,剩余使用 SDK 默认采集规则(返回默认处理器的处理结果)        
        return defaultHandler.rumAction(with: pressType, targetView: targetView)

        // 返回 nil 跳过跟踪
        return nil
    }
}

Resource

需要开启配置 FTRUMConfig.enableTraceUserResource = YES通过转发 URLSession Delegate 自定义采集 Network

根据 Url 采集过滤

rumConfig.resourceUrlHandler = ^(NSURL *url){
        // 返回 YES 表示不采集;返回 NO 表示采集
        if ([url.host isEqualToString:@"example.com"]) {
            return YES;
        }
        return NO;
};
rumConfig.resourceUrlHandler = { url in 
     // 返回 true 表示不采集;返回 false 表示采集
     return url.host == "example.com"
}

添加自定义属性

通过设置属性提供程序闭包,您可以返回要附加到 RUM Resoucre 的其他属性。

例如,您可能希望向 RUM Resource 添加 HTTP 请求 body:

rumConfig.resourcePropertyProvider = ^NSDictionary *_Nullable(NSURLRequest *request, NSURLResponse *response,NSData *data, NSError *error) {
     NSString *body = @"";
     if (request.HTTPBody) {
        body = [[NSString alloc] initWithData:httpBody encoding:NSUTF8StringEncoding] ?: @"";
     }
     return @{@"request_body": body};
 }
rumConfig.resourcePropertyProvider = { request, response, data, error in
   let body = request.httpBody.flatMap { String(data: $0, encoding: .utf8) } ?? ""
   return ["request_body": body]
  }

过滤网络错误

网络请求发生错误时,RUM 中会生成一条类型为 network_error 的 Error 数据,一些 URLSeesion 的本地错误比如 task.cancel 是用户程序中的正常逻辑,并非是错误数据,此时可以通过 sessionTaskErrorFilter 回调进行拦截过滤。确认拦截返回 YES,不拦截返回 NO,拦截后 RUM-Error 不采集该条错误。

rumConfig.sessionTaskErrorFilter = ^BOOL(NSError * _Nonnull error){
    return error.code == NSURLErrorCancelled;
}; 
rumConfig.sessionTaskErrorFilter = { error in
   return (error as? URLError)?.code == .cancelled
}

自定义 TraceHeader

可以通过 FTTraceConfig.traceInterceptor 进行全局设置,或 URLSession 级自定义 Trace,以下为 w3c-traceContext 为例

FTTraceConfig *traceConfig = [[FTTraceConfig alloc]init];
   traceConfig.traceInterceptor = ^FTTraceContext * _Nullable(NSURLRequest *request) {
    // 1. 获取业务自定义的 traceId
    NSString *replaceTrace = [request.allHTTPHeaderFields valueForKey:CUSTOM_TRACE_HEADER];

    // 2. 获取 SDK 标准 W3C traceparent 请求头
    NSDictionary *traceHeaders = [[FTExternalDataManager sharedManager] getTraceHeaderWithUrl:request.URL];
    NSString *traceParentStr = traceHeaders[FT_NETWORK_TRACEPARENT_KEY];

    // 3. 解析 W3C traceparent 格式并替换索引 1 的 traceId
    NSArray *traceComponents = [traceParentStr componentsSeparatedByString:@"-"];
    if (traceComponents.count != 4) {
        return nil;
    }
    NSMutableArray *newComponents = [traceComponents mutableCopy];
    newComponents[1] = replaceTrace;
    NSString *newTraceParent = [newComponents componentsJoinedByString:@"-"];

    // 4. 组装并返回自定义追踪上下文
    FTTraceContext *context = [FTTraceContext new];
    context.traceHeader = @{FT_NETWORK_TRACEPARENT_KEY:newTraceParent};
    context.traceId = replaceTrace;
    // 保留 SDK 生成的 spanId(索引 2 固定位置)
    context.spanId = newComponents[2];
    return context;
};
let traceConfig = FTTraceConfig()
traceConfig.traceInterceptor = { (request: URLRequest) -> FTTraceContext? in
        // 1. 获取业务自定义的 traceId
        guard let replaceTrace = request.allHTTPHeaderFields?[CUSTOM_TRACE_HEADER] else {
            return nil
        }

        // 2. 获取 SDK 标准 W3C traceparent 请求头
        guard let traceHeaders = FTExternalDataManager.shared().getTraceHeader(with: request.url!), let traceParentStr = traceHeaders[FT_NETWORK_TRACEPARENT_KEY] as? String else {
            return nil
        }

        // 3. 解析 W3C traceparent 格式并替换索引 1 的 traceId
        let traceComponents = traceParentStr.components(separatedBy: "-")
        guard traceComponents.count == 4 else {
            return nil
        }
        var newComponents = traceComponents
        newComponents[1] = replaceTrace
        let newTraceParent = newComponents.joined(separator: "-")

        // 4. 组装并返回自定义追踪上下文
        let context = FTTraceContext()
        context.traceHeader = [FT_NETWORK_TRACEPARENT_KEY: newTraceParent]
        context.traceId = replaceTrace
        // 保留 SDK 生成的 spanId(索引 2 固定位置)
        context.spanId = newComponents[2]
        return context
    }

文档评价

文档内容是否对您有帮助? ×