跳转至

数据采集自定义规则

View

Activity

  • 需要先通过 FTRUMConfig.setEnableTraceUserView(true) 开启
FTSdk.initRUMWithConfig(new FTRUMConfig()
    .setViewActivityTrackingHandler(new FTViewActivityTrackingHandler() {
        @Override
        public HandlerView resolveHandlerView(Activity activity) {
            String activityName = activity.getClass().getSimpleName();

            // 根据 Activity 名称自定义视图名称
            if (activityName.startsWith("Main")) {
                return new HandlerView("自定义主页面");
            } else if (activityName.startsWith("Detail")) {
                HashMap<String, Object> properties = new HashMap<>();
                properties.put("extra_key", "extra_value");
                return new HandlerView("自定义详情页面", properties);
            }

            // 返回 null 跳过跟踪
            return null;
        }
    })
);
FTSdk.initRUMWithConfig(
    FTRUMConfig()
        .setViewActivityTrackingHandler(object : FTViewActivityTrackingHandler {
            override fun resolveHandlerView(activity: Activity): HandlerView? {
                val activityName = activity.javaClass.simpleName
                return when {
                    activityName.startsWith("Main") ->
                        HandlerView("自定义主页面")
                    activityName.startsWith("Detail") -> {
                        val properties = hashMapOf<String, Any>("extra_key" to "extra_value")
                        HandlerView("自定义详情页面", properties)
                    }
                    else -> null // 跳过跟踪
                }
            }
        })
)

Fragment

  • 需要同时开启 FTRUMConfig.setEnableTraceUserView(true)FTRUMConfig.setEnableTraceUserViewInFragment(true)
FTSdk.initRUMWithConfig(new FTRUMConfig()
    .setViewFragmentTrackingHandler(new FTViewFragmentTrackingHandler() {
        @Override
        public HandlerView resolveHandlerView(FragmentWrapper fragment) {
            String fragmentName = fragment.getSimpleClassName();

            // 根据 Fragment 名称自定义视图名称
            if (fragmentName.equals("HomeFragment")) {
                return new HandlerView("自定义首页片段");
            } else if (fragmentName.startsWith("Detail")) {
                HashMap<String, Object> properties = new HashMap<>();
                properties.put("extra_key", "extra_value");
                return new HandlerView("自定义详情片段", properties);
            }

            // 返回 null 跳过跟踪
            return null;
        }
    })
);
FTSdk.initRUMWithConfig(
    FTRUMConfig()
        .setViewFragmentTrackingHandler(object : FTViewFragmentTrackingHandler {
            override fun resolveHandlerView(fragment: FragmentWrapper): HandlerView? {
                val fragmentName = fragment.simpleClassName
                return when {
                    fragmentName == "HomeFragment" ->
                        HandlerView("自定义首页片段")
                    fragmentName.startsWith("Detail") -> {
                        val properties = hashMapOf<String, Any>("extra_key" to "extra_value")
                        HandlerView("自定义详情片段", properties)
                    }
                    else -> null // 跳过跟踪
                }
            }
        })
)

Action

  • 需要 FTRUMConfig.setEnableTraceUserAction(true) 开启状态
  • 用途:自定义 Action 名称、属性,或根据具体 View 过滤 Action 采集
FTSdk.initRUMWithConfig(new FTRUMConfig()
    .setActionTrackingHandler(new FTActionTrackingHandler() {
        @Override
        public HandlerAction resolveHandlerAction(ActionEventWrapper actionEventWrapper) {
            // 获取操作类型
            ActionSourceType actionType = actionEventWrapper.getSourceType();
            Object source = actionEventWrapper.getSource();

            // 过滤指定 View 的 Action
            if (source instanceof View) {
                View view = (View) source;
                if (view.getId() == R.id.ignore_action_view) {
                    return null;
                }
            }

            // 根据操作类型自定义跟踪
            if (actionType == ActionSourceType.CLICK_VIEW) {
                HashMap<String, Object> properties = new HashMap<>();
                properties.put("extra_key", "extra_value");
                return new HandlerAction("自定义按钮点击", properties);
            } else if (actionType == ActionSourceType.CLICK_LIST_ITEM) {
                return new HandlerAction("自定义列表项点击");
            }

            // 返回 null 跳过跟踪
            return null;
        }
    })
);
FTSdk.initRUMWithConfig(
    FTRUMConfig()
        .setActionTrackingHandler(object : FTActionTrackingHandler {
            override fun resolveHandlerAction(actionEventWrapper: ActionEventWrapper): HandlerAction? {
                val source = actionEventWrapper.source

                // 过滤指定 View 的 Action
                if (source is View && source.id == R.id.ignore_action_view) {
                    return null
                }

                return when (actionEventWrapper.sourceType) {
                    ActionSourceType.CLICK_VIEW -> {
                        val properties = hashMapOf<String, Any>("extra_key" to "extra_value")
                        HandlerAction("自定义按钮点击", properties)
                    }
                    ActionSourceType.CLICK_LIST_ITEM ->
                        HandlerAction("自定义列表项点击")
                    else -> null // 跳过跟踪
                }
            }
        })
)
注意

可以通过 ActionEventWrapper.getSource() 获取当前操作的来源对象。普通点击、列表项点击、Tab 点击等由 View 触发的 Action,source 通常为对应的 View。设置 setActionTrackingHandler 后,SDK 会以该处理器的返回结果作为 Action 采集依据。返回 null 的 Action 会被跳过;需要继续采集的 Action 应返回 HandlerAction

Resource

  • 需要 FTRUMConfig.setEnableTraceUserResource(true) 开启状态

根据 Url 采集过滤

FTSdk.initRUMWithConfig(new FTRUMConfig()
    .setResourceUrlHandler(new FTInTakeUrlHandler() {
        @Override
        public boolean isInTakeUrl(String url) {
            // 返回 true 表示不采集;返回 false 表示采集
            return url.startsWith("https://url.rule");
        }
    })
);
FTSdk.initRUMWithConfig(
    FTRUMConfig()
        .setResourceUrlHandler(object : FTInTakeUrlHandler {
            override fun isInTakeUrl(url: String): Boolean {
                // 返回 true 表示不采集;返回 false 表示采集
                return url.startsWith("https://url.rule")
            }
        })
)

添加自定义属性

可以通过 FTRUMConfig.setOkHttpResourceContentHandler(FTResourceInterceptor.ContentHandlerHelperEx)

new FTResourceInterceptor.ContentHandlerHelperEx() {
    @Override
    public void onRequest(Request request, HashMap<String, Object> extraData) {
        extraData.put("df_custom_key","custom_value");
    }

    @Override
    public void onResponse(Response response, HashMap<String, Object> extraData) throws IOException {
        extraData.put("df_custom_key","custom_value");
    }

    @Override
    public boolean onExceptionWithFilter(Exception e, HashMap<String, Object> extraData)  {
        extraData.put("df_custom_key","custom_value");
        return false;
    }
}
object : FTResourceInterceptor.ContentHandlerHelperEx() {

override fun onRequest(
    request: Request,
    extraData: HashMap<String, Any>
    ) {
        extraData["df_custom_key"] = "custom_value"
    }

    override fun onResponse(
        response: Response,
        extraData: HashMap<String, Any>
    ) {
        extraData["df_custom_key"] = "custom_value"
    }

    override fun onExceptionWithFilter(
        e: Exception,
        extraData: HashMap<String, Any>
    ): Boolean {
        extraData["df_custom_key"] = "custom_value"
        return false
    }
}   

过滤网络错误

可以针对本地网络 IOException 错误进行过滤。可以通过FTRUMConfig.setOkHttpResourceContentHandler(FTResourceInterceptor.ContentHandlerHelperEx) 进行设置,或自定义 Resource

new FTResourceInterceptor.ContentHandlerHelperEx() {
    //...

    /**
     * 返回网络链接过程中的异常
     *
     * @param e         请求发生的 IOException 数据
     * @param extraData 附加数据
     * @return 是否过滤本地网络  network_error 类型的错误。true,表示过滤不采集
     */
    @Override
    public boolean onExceptionWithFilter(Exception e, HashMap<String, Object> extraData) {
        if (e instanceof SocketTimeoutException) { //网络超时
            return true;
        }
        return super.onExceptionWithFilter(e, extraData);
    }
}
object : FTResourceInterceptor.ContentHandlerHelperEx() {
    //...

    /**
    * 返回网络链接过程中的异常
    *
    * @param e         请求发生的 IOException 数据
    * @param extraData 附加数据
    * @return 是否过滤本地网络 network_error 类型的错误。true,为覆盖不采集
    */
    override fun onExceptionWithFilter(e: Exception, extraData: HashMap<String, Any>): Boolean {
        return if (e is SocketTimeoutException) {
            true
        } else {
            super.onExceptionWithFilter(e, extraData)
        }
    }
}

自定义 TraceHeader

可通过FTTraceConfig.setOkHttpTraceHeaderHandler(FTTraceInterceptor.HeaderHandler)进行设置,或自定义 Trace,以下为 w3c-traceContext 为例

 new FTTraceInterceptor.HeaderHandler() {
        private String[] splits;

        @Override
        public HashMap<String, String> getTraceHeader(Request request) {
            HashMap<String, String> map = new HashMap<>();
            //从 header 中获取自定义 trace_id
            String replaceTrace = request.header(CUSTOM_TRACE_HEADER);
            String headerString = FTTraceManager.get().
                    getTraceHeader(request.url().toString())
                    // 从 header 中获取 propagation header
                    .get(FTTraceHandler.W3C_TRACEPARENT_KEY); 
            splits = headerString.split("-");
            String originTraceId = splits[1];
            splits[1] = replaceTrace;
            map.put(FTTraceHandler.W3C_TRACEPARENT_KEY, headerString.replace(originTraceId, replaceTrace));
            return map;
        }

        @Override
        public String getSpanID() {
            if (splits != null) {
                return splits[2];
            }
            return null;
        }

        @Override
        public String getTraceID() {
            if (splits != null) {
                return splits[1];
            }
            return null;
        }
};
object : FTTraceInterceptor.HeaderHandler() {
    private var splits: List<String>? = null
    override fun getTraceHeader(request: Request): HashMap<String, String> {
        val map = HashMap<String, String>()

        // 从 header 中获取自定义 trace_id
        val replaceTrace = request.header(CUSTOM_TRACE_HEADER)
        val headerString = FTTraceManager.get()
            .getTraceHeader(request.url().toString())
            .get(FTTraceHandler.W3C_TRACEPARENT_KEY)

        splits = headerString?.split("-")
        val originTraceId = splits?.getOrNull(1)

        if (headerString != null && originTraceId != null && replaceTrace != null) {
            map[FTTraceHandler.W3C_TRACEPARENT_KEY] = 
                headerString.replace(originTraceId, replaceTrace)
        }

        return map
    }

    override fun getSpanID(): String? {
        return splits?.getOrNull(2)
    }

    override fun getTraceID(): String? {
        return splits?.getOrNull(1)
    }
}

使用自定义 trace_id 关联 RUM Resource

如果应用侧已有自定义 trace_id,例如请求头 key 为 custom_trace_id,可以在 SDK 生成的 traceparent 基础上更新 trace_id,并通过 TraceContext.Simple 指定 RUM Resource 关联使用的 trace_id。

new FTTraceInterceptor.HeaderHandler() {
    @Override
    public TraceContext getTraceContext(Request request) {
        HashMap<String, String> headers = FTTraceManager.get()
                .getTraceHeader(request.url().toString());

        // 从请求 header 中获取自定义 trace_id,例如 custom_trace_id
        String customTraceId = request.header(CUSTOM_TRACE_HEADER);

        TraceContext.Simple sdkContext = TraceContext.Simple.fromTraceType(headers);
        if (customTraceId == null
                || customTraceId.length() == 0
                || sdkContext == null
                || sdkContext.getTraceId() == null) {
            return sdkContext;
        }

        String traceparent = headers.get(FTTraceHandler.W3C_TRACEPARENT_KEY);
        if (traceparent == null) {
            return sdkContext;
        }

        String newTraceparent = traceparent.replace(
                sdkContext.getTraceId(),
                customTraceId
        );

        // 更新注入到请求中的 W3C trace header
        headers.put(FTTraceHandler.W3C_TRACEPARENT_KEY, newTraceparent);

        // 可选:保留自定义业务 header
        headers.put(CUSTOM_TRACE_HEADER, customTraceId);

        // RUM Resource 关联使用 customTraceId,spanId 继续使用 SDK 生成的 spanId
        return new TraceContext.Simple(headers, customTraceId, sdkContext.getSpanId());
    }
};
object : FTTraceInterceptor.HeaderHandler() {
    override fun getTraceContext(request: Request): TraceContext? {
        val headers = FTTraceManager.get()
            .getTraceHeader(request.url().toString())

        // 从请求 header 中获取自定义 trace_id
        val customTraceId = request.header(CUSTOM_TRACE_HEADER)

        val sdkContext = TraceContext.Simple.fromTraceType(headers)
        val sdkTraceId = sdkContext?.traceId
        val sdkSpanId = sdkContext?.spanId
        if (customTraceId.isNullOrEmpty() || sdkTraceId.isNullOrEmpty()) {
            return sdkContext
        }

        val traceparent = headers[FTTraceHandler.W3C_TRACEPARENT_KEY] ?: return sdkContext
        val newTraceparent = traceparent.replace(sdkTraceId, customTraceId)

        // 更新注入到请求中的 W3C trace header
        headers[FTTraceHandler.W3C_TRACEPARENT_KEY] = newTraceparent

        // 可选:保留自定义业务 header
        headers[CUSTOM_TRACE_HEADER] = customTraceId

        // RUM Resource 关联使用 customTraceId,spanId 继续使用 SDK 生成的 spanId
        return TraceContext.Simple(headers, customTraceId, sdkSpanId)
    }
}

注意:W3C trace_id 需要为 32 位十六进制字符串,且不能全部为 0

文档评价

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