Trace Configuration¶
Trace Initialization Configuration¶
| Method Name | Type | Required | Description |
|---|---|---|---|
| setSamplingRate | Float | No | Sets the sampling rate, range [0,1]. 0 means no sampling, 1 means full sampling. Default is 1. |
| setTraceType | TraceType | No | Sets the type of APM. Default is DDTrace. Currently supports Zipkin, Jaeger, DDTrace, Skywalking (8.0+), TraceParent (W3C). If integrating OpenTelemetry, please check the supported types and agent configurations when selecting the corresponding APM type. |
| setEnableLinkRUMData | Boolean | No | Whether to correlate with RUM data. Default is false. |
| setEnableAutoTrace | Boolean | No | Sets whether to enable automatic HTTP Trace. This configuration depends on ft-plugin. Currently only supports automatic tracing for OkHttp. Default is false. |
| setOkHttpTraceHeaderHandler | Callback | No | ASM sets the global FTTraceInterceptor.HeaderHandler. Not set by default. Supported from ft-sdk 1.6.8 onwards. Starting from ft-sdk 1.6.17, priority support for overriding getTraceContext(Request), which can return Header, traceId, and spanId at once. Example reference Custom Trace. |
Tracer Network APM¶
The FTTraceConfig configuration enables enableAutoTrace to automatically add APM data, or manually use FTTraceManager to add Propagation Header in HTTP requests, as shown in the following example.
String url = "https://request.url";
String uuid = "uuid";
// Get APM header parameters
Map<String, String> headers = FTTraceManager.get().getTraceHeader(uuid, url);
OkHttpClient client = new OkHttpClient.Builder().addInterceptor(chain -> {
Request original = chain.request();
Request.Builder requestBuilder = original.newBuilder();
// Add APM header parameters to the request
for (String key : headers.keySet()) {
requestBuilder.header(key, headers.get(key));
}
Request request = requestBuilder.build();
Response response = chain.proceed(request);
if (response != null) {
Map<String, String> requestHeaderMap = new HashMap<>();
Map<String, String> responseHeaderMap = new HashMap<>();
for (Pair<String, String> header : response.request().headers()) {
requestHeaderMap.put(header.first, header.second);
}
for (Pair<String, String> header : response.headers()) {
responseHeaderMap.put(header.first, header.second);
}
}
return response;
}).build();
Request.Builder builder = new Request.Builder().url(url).method(RequestMethod.GET.name(), null);
client.newCall(builder.build()).execute();
val url = "https://request.url"
val uuid = "uuid"
// Get APM header parameters
val headers = FTTraceManager.get().getTraceHeader(uuid, url)
val client: OkHttpClient = OkHttpClient.Builder().addInterceptor { chain ->
val original = chain.request()
val requestBuilder = original.newBuilder()
// Add APM header parameters to the request
for (key in headers.keys) {
requestBuilder.header(key!!, headers[key]!!)
}
val request = requestBuilder.build()
val response = chain.proceed(request)
if (response != null) {
val requestHeaderMap = HashMap<String, String>()
val responseHeaderMap = HashMap<String, String>()
request.headers.forEach {
requestHeaderMap[it.first] = it.second
}
response.headers.forEach {
responseHeaderMap[it.first] = it.second
}
}
response
}.build()
val builder: Request.Builder = Request.Builder().url(url).method(RequestMethod.GET.name, null)
client.newCall(builder.build()).execute()
Customizing Resource and TraceHeader via OkHttp Interceptor¶
Resource¶
When FTRUMConfig.setEnableTraceUserResource(true) or FTRUMConfig.setOkHttpResourceContentHandler(...) is enabled, the custom Interceptor in OkHttp will be loaded first.
new OkHttpClient.Builder()
.addInterceptor(new FTTraceInterceptor())
.addInterceptor(new FTResourceInterceptor(new FTResourceInterceptor.ContentHandlerHelper() {
@Override
public void onRequest(Request request, HashMap<String, Object> extraData) {
String contentType = request.header("Content-Type");
extraData.put("df_request_header", request.headers().toString());
if ("application/json".equals(contentType) ||
"application/x-www-form-urlencoded".equals(contentType) ||
"application/xml".equals(contentType)) {
extraData.put("df_request_body", request.body());
}
}
@Override
public void onResponse(Response response, HashMap<String, Object> extraData) throws IOException {
String contentType = response.header("Content-Type");
extraData.put("df_response_header", response.headers().toString());
if ("application/json".equals(contentType) ||
"application/xml".equals(contentType)) {
// Copy and read part of the body to avoid consumption from large data processing
ResponseBody body = response.peekBody(33554432);
extraData.put("df_response_body", body.string());
}
}
@Override
public void onException(Exception e, HashMap<String, Object> extraData) {
}
}))
.eventListenerFactory(new FTResourceEventListener.FTFactory())
.build();
OkHttpClient.Builder()
.addInterceptor(FTTraceInterceptor())
.addInterceptor(FTResourceInterceptor(object : FTResourceInterceptor.ContentHandlerHelper {
override fun onRequest(request: Request, extraData: HashMap<String, Any>) {
val contentType = request.header("Content-Type")
extraData["df_request_header"] = request.headers().toString()
if ("application/json" == contentType ||
"application/x-www-form-urlencoded" == contentType ||
"application/xml" == contentType) {
extraData["df_request_body"] = request.body()
}
}
override fun onResponse(response: Response, extraData: HashMap<String, Any>) {
val contentType = response.header("Content-Type")
extraData["df_response_header"] = response.headers().toString()
if ("application/json" == contentType ||
"application/xml" == contentType) {
// Copy part of the response body to avoid large data consumption
val body = response.peekBody(33554432)
extraData["df_response_body"] = body.string()
}
}
override fun onException(e: Exception, extraData: HashMap<String, Any>) {
// Handle exception cases
}
}))
.eventListenerFactory(FTResourceEventListener.FTFactory())
.build()
TraceHeader¶
When FTTraceConfig.setEnableAutoTrace(true) or FTTraceConfig.setOkHttpTraceHeaderHandler(...) is enabled, the custom Interceptor in OkHttp will be loaded first. The following example uses W3C Trace Context.
When ft-sdk < 1.4.1, you need to disable
FTTraceConfig.setEnableAutoTrace(false). ft-sdk > 1.6.7 supports custom Trace Header correlation with RUM data. ft-sdk >= 1.6.17 addsgetTraceContext(Request), which can return request Header,traceId, andspanIdat once. It is recommended to use this method first.
Recommended Method: Using getTraceContext(Request)¶
new OkHttpClient.Builder()
.addInterceptor(new FTTraceInterceptor(new FTTraceInterceptor.HeaderHandler() {
@Override
public TraceContext getTraceContext(Request request) {
HashMap<String, String> headers = FTTraceManager.get()
.getTraceHeader(request.url().toString());
return TraceContext.Simple.fromTraceType(headers);
}
}))
.addInterceptor(new FTResourceInterceptor())
.eventListenerFactory(new FTResourceEventListener.FTFactory())
.build();
OkHttpClient.Builder()
.addInterceptor(
FTTraceInterceptor(object : FTTraceInterceptor.HeaderHandler() {
override fun getTraceContext(request: Request): TraceContext? {
val headers = FTTraceManager.get().getTraceHeader(request.url.toString())
return TraceContext.Simple.fromTraceType(headers)
}
})
)
.addInterceptor(FTResourceInterceptor())
.eventListenerFactory(FTResourceEventListener.FTFactory())
.build()
Compatible Old Method: Implementing getTraceHeader / getTraceID / getSpanID Separately¶
new OkHttpClient.Builder()
.addInterceptor(new FTTraceInterceptor(new FTTraceInterceptor.HeaderHandler() {
private String[] splits;
@Override
public HashMap<String, String> getTraceHeader(Request request) {
HashMap<String, String> map = new HashMap<>();
String headerString = FTTraceManager.get()
.getTraceHeader(request.url().toString())
// Get propagation header from header
.get(FTTraceHandler.W3C_TRACEPARENT_KEY);
splits = headerString.split("-");
map.put(W3C_TRACEPARENT_KEY, headerString);
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;
}
}))
.addInterceptor(new FTResourceInterceptor())
.eventListenerFactory(new FTResourceEventListener.FTFactory())
.build();
OkHttpClient.Builder()
.addInterceptor(
FTTraceInterceptor(object : FTTraceInterceptor.HeaderHandler {
private var splits: Array<String>? = null
override fun getTraceHeader(request: Request): HashMap<String, String> {
val map = HashMap<String, String>()
val headerString = FTTraceManager.get()
.getTraceHeader(request.url.toString())
// Get propagation header from header
.get(FTTraceHandler.W3C_TRACEPARENT_KEY)
splits = headerString?.split("-")?.toTypedArray()
headerString?.let {
map[W3C_TRACEPARENT_KEY] = it
}
return map
}
override fun getSpanID(): String? {
return splits?.getOrNull(2)
}
override fun getTraceID(): String? {
return splits?.getOrNull(1)
}
})
)
.addInterceptor(FTResourceInterceptor())
.eventListenerFactory(FTResourceEventListener.FTFactory())
.build()
Adding ResourceID to OkHttp¶
Add uuid to OkHttp Request. It is recommended to enable this for high-frequency concurrent scenarios with the same request. For ft-plugin version 1.3.5 and above, ft-sdk version 1.6.10 and above, after enabling FTSDKConfig.setEnableOkhttpRequestTag(true), ResourceID can be automatically added to Request.