Data Collection Custom Rules¶
View¶
Activity¶
- First, enable it via
FTRUMConfig.setEnableTraceUserView(true)
FTSdk.initRUMWithConfig(new FTRUMConfig()
.setViewActivityTrackingHandler(new FTViewActivityTrackingHandler() {
@Override
public HandlerView resolveHandlerView(Activity activity) {
String activityName = activity.getClass().getSimpleName();
// Customize view name based on Activity name
if (activityName.startsWith("Main")) {
return new HandlerView("Custom Main Page");
} else if (activityName.startsWith("Detail")) {
HashMap<String, Object> properties = new HashMap<>();
properties.put("extra_key", "extra_value");
return new HandlerView("Custom Detail Page", properties);
}
// Return null to skip tracking
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("Custom Main Page")
activityName.startsWith("Detail") -> {
val properties = hashMapOf<String, Any>("extra_key" to "extra_value")
HandlerView("Custom Detail Page", properties)
}
else -> null // Skip tracking
}
}
})
)
Fragment¶
- Requires enabling both
FTRUMConfig.setEnableTraceUserView(true)andFTRUMConfig.setEnableTraceUserViewInFragment(true)
FTSdk.initRUMWithConfig(new FTRUMConfig()
.setViewFragmentTrackingHandler(new FTViewFragmentTrackingHandler() {
@Override
public HandlerView resolveHandlerView(FragmentWrapper fragment) {
String fragmentName = fragment.getSimpleClassName();
// Customize view name based on Fragment name
if (fragmentName.equals("HomeFragment")) {
return new HandlerView("Custom Home Fragment");
} else if (fragmentName.startsWith("Detail")) {
HashMap<String, Object> properties = new HashMap<>();
properties.put("extra_key", "extra_value");
return new HandlerView("Custom Detail Fragment", properties);
}
// Return null to skip tracking
return null;
}
})
);
FTSdk.initRUMWithConfig(
FTRUMConfig()
.setViewFragmentTrackingHandler(object : FTViewFragmentTrackingHandler {
override fun resolveHandlerView(fragment: FragmentWrapper): HandlerView? {
val fragmentName = fragment.simpleClassName
return when {
fragmentName == "HomeFragment" ->
HandlerView("Custom Home Fragment")
fragmentName.startsWith("Detail") -> {
val properties = hashMapOf<String, Any>("extra_key" to "extra_value")
HandlerView("Custom Detail Fragment", properties)
}
else -> null // Skip tracking
}
}
})
)
Action¶
- Requires
FTRUMConfig.setEnableTraceUserAction(true)to be enabled - Purpose: Customize Action name, properties, or filter Action collection based on specific Views
FTSdk.initRUMWithConfig(new FTRUMConfig()
.setActionTrackingHandler(new FTActionTrackingHandler() {
@Override
public HandlerAction resolveHandlerAction(ActionEventWrapper actionEventWrapper) {
// Get operation type
ActionSourceType actionType = actionEventWrapper.getSourceType();
Object source = actionEventWrapper.getSource();
// Filter Actions for specified Views
if (source instanceof View) {
View view = (View) source;
if (view.getId() == R.id.ignore_action_view) {
return null;
}
}
// Customize tracking based on operation type
if (actionType == ActionSourceType.CLICK_VIEW) {
HashMap<String, Object> properties = new HashMap<>();
properties.put("extra_key", "extra_value");
return new HandlerAction("Custom Button Click", properties);
} else if (actionType == ActionSourceType.CLICK_LIST_ITEM) {
return new HandlerAction("Custom List Item Click");
}
// Return null to skip tracking
return null;
}
})
);
FTSdk.initRUMWithConfig(
FTRUMConfig()
.setActionTrackingHandler(object : FTActionTrackingHandler {
override fun resolveHandlerAction(actionEventWrapper: ActionEventWrapper): HandlerAction? {
val source = actionEventWrapper.source
// Filter Actions for specified Views
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("Custom Button Click", properties)
}
ActionSourceType.CLICK_LIST_ITEM ->
HandlerAction("Custom List Item Click")
else -> null // Skip tracking
}
}
})
)
Note
You can get the source object of the current operation via ActionEventWrapper.getSource(). For Actions triggered by Views, such as normal clicks, list item clicks, Tab clicks, etc., the source is usually the corresponding View. After setting setActionTrackingHandler, the SDK will use the handler's return result as the basis for Action collection. Actions returning null will be skipped; Actions that need to continue collection should return a HandlerAction.
Resource¶
- Requires
FTRUMConfig.setEnableTraceUserResource(true)to be enabled
Collection Filtering Based on URL¶
Add Custom Properties¶
Can be done via 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
}
}
Filter Network Errors¶
You can filter local network IOException errors. Can be set via FTRUMConfig.setOkHttpResourceContentHandler(FTResourceInterceptor.ContentHandlerHelperEx), or Custom Resource
new FTResourceInterceptor.ContentHandlerHelperEx() {
//...
/**
* Returns exceptions during network connection
*
* @param e IOException data from the request
* @param extraData Additional data
* @return Whether to filter local network errors of type `network_error`. true means filter and do not collect
*/
@Override
public boolean onExceptionWithFilter(Exception e, HashMap<String, Object> extraData) {
if (e instanceof SocketTimeoutException) { //Network timeout
return true;
}
return super.onExceptionWithFilter(e, extraData);
}
}
object : FTResourceInterceptor.ContentHandlerHelperEx() {
//...
/**
* Returns exceptions during network connection
*
* @param e IOException data from the request
* @param extraData Additional data
* @return Whether to filter local network errors of type `network_error`. true means override and do not collect
*/
override fun onExceptionWithFilter(e: Exception, extraData: HashMap<String, Any>): Boolean {
return if (e is SocketTimeoutException) {
true
} else {
super.onExceptionWithFilter(e, extraData)
}
}
}
Custom TraceHeader¶
Can be set via FTTraceConfig.setOkHttpTraceHeaderHandler(FTTraceInterceptor.HeaderHandler), or Custom Trace. The following uses w3c-traceContext as an example.
new FTTraceInterceptor.HeaderHandler() {
private String[] splits;
@Override
public HashMap<String, String> getTraceHeader(Request request) {
HashMap<String, String> map = new HashMap<>();
//Get custom trace_id from header
String replaceTrace = request.header(CUSTOM_TRACE_HEADER);
String headerString = FTTraceManager.get().
getTraceHeader(request.url().toString())
// Get propagation header from 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>()
// Get custom trace_id from header
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)
}
}