Trace 配置¶
Trace 初始化配置¶
| 方法名 | 类型 | 必须 | 含义 |
|---|---|---|---|
| setSamplingRate | Float | 否 | 设置采集率,取值范围 [0,1],0 表示不采集,1 表示全采集,默认值为 1 |
| setTraceType | TraceType | 否 | 设置链路追踪的类型,默认为 DDTrace,目前支持 Zipkin、Jaeger、DDTrace、Skywalking (8.0+)、TraceParent (W3C),如果接入 OpenTelemetry 选择对应链路类型时,请注意查阅支持类型及 agent 相关配置 |
| setEnableLinkRUMData | Boolean | 否 | 是否与 RUM 数据关联,默认为 false |
| setEnableAutoTrace | Boolean | 否 | 设置是否开启自动 HTTP Trace,该配置依赖 ft-plugin,目前只支持 OkHttp 的自动追踪,默认为 false |
| setOkHttpTraceHeaderHandler | Callback | 否 | ASM 设置全局 FTTraceInterceptor.HeaderHandler,默认不设置,ft-sdk 1.6.8 以上支持。ft-sdk 1.6.17 起,优先支持重写 getTraceContext(Request),可一次性返回 Header、traceId 和 spanId,示例参考自定义 Trace |
Tracer 网络链路追踪¶
FTTraceConfig 配置开启 enableAutoTrace 自动添加链路数据,或手动使用 FTTraceManager 在 HTTP 请求中添加 Propagation Header,示例如下。
String url = "https://request.url";
String uuid = "uuid";
// 获取链路头参数
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();
// 在请求中,添加链路头参数
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"
// 获取链路头参数
val headers = FTTraceManager.get().getTraceHeader(uuid, url)
val client: OkHttpClient = OkHttpClient.Builder().addInterceptor { chain ->
val original = chain.request()
val requestBuilder = original.newBuilder()
// 在请求中,添加链路头参数
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()
通过 OKHttp Interceptor 自定义 Resource 和 TraceHeader¶
Resource¶
FTRUMConfig.setEnableTraceUserResource(true) 或 FTRUMConfig.setOkHttpResourceContentHandler(...) 开启时,OkHttp 中自定义 Interceptor 会优先加载。
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)) {
// 复制读取部分 body,避免大数据处理消耗
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) {
// 复制部分响应体以避免大数据消耗
val body = response.peekBody(33554432)
extraData["df_response_body"] = body.string()
}
}
override fun onException(e: Exception, extraData: HashMap<String, Any>) {
// 处理异常情况
}
}))
.eventListenerFactory(FTResourceEventListener.FTFactory())
.build()
TraceHeader¶
FTTraceConfig.setEnableAutoTrace(true) 或 FTTraceConfig.setOkHttpTraceHeaderHandler(...) 开启时,OkHttp 中自定义 Interceptor 会优先加载。以下以 W3C Trace Context 为例。
ft-sdk < 1.4.1 时,需要关闭
FTTraceConfig.setEnableAutoTrace(false)。 ft-sdk > 1.6.7 支持自定义 Trace Header 与 RUM 数据关联。 ft-sdk >= 1.6.17 新增getTraceContext(Request),可一次性返回请求 Header、traceId和spanId,推荐优先使用此方式。
推荐方式:使用 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()
兼容旧方式:分别实现 getTraceHeader / getTraceID / getSpanID¶
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())
// 从 header 中获取 propagation 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())
// 从 header 中获取 propagation 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()
OKHttp 添加 ResourceID¶
对 OkHttp Request 添加 uuid。如果有相同请求高频并发场景建议开启。ft-plugin 1.3.5 以上版本、ft-sdk 1.6.10 以上版本开启 FTSDKConfig.setEnableOkhttpRequestTag(true) 后,可以自动在 Request 中添加 ResourceID。