跳转至

Trace 配置

Trace 初始化配置

FTSdk.initTraceWithConfig(new FTTraceConfig()
    .setSamplingRate(0.8f)
    .setEnableAutoTrace(true)
    .setEnableLinkRUMData(true));
FTSdk.initTraceWithConfig(
    FTTraceConfig()
        .setSamplingRate(0.8f)
        .setEnableAutoTrace(true)
        .setEnableLinkRUMData(true)
)
方法名 类型 必须 含义
setSamplingRate Float 设置采集率,取值范围 [0,1],0 表示不采集,1 表示全采集,默认值为 1
setTraceType TraceType 设置链路追踪的类型,默认为 DDTrace,目前支持 ZipkinJaegerDDTraceSkywalking (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、traceIdspanId,示例参考自定义 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、traceIdspanId,推荐优先使用此方式。

推荐方式:使用 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

new Request.Builder()
    .tag(ResourceID.class, new ResourceID());
Request.Builder()
    .tag(ResourceID::class.java, ResourceID())

文档评价

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