Trace 설정¶
Trace 초기화 설정¶
| 메서드명 | 유형 | 필수 | 설명 |
|---|---|---|---|
| setSamplingRate | Float | 아니요 | 수집률 설정. 값 범위는 [0,1]이며, 0은 수집 안 함, 1은 전체 수집을 의미합니다. 기본값은 1입니다. |
| setTraceType | TraceType | 아니요 | 분산 추적 유형 설정. 기본값은 DDTrace이며, 현재 Zipkin, Jaeger, DDTrace, Skywalking (8.0+), TraceParent (W3C)를 지원합니다. OpenTelemetry를 연동할 때 해당 링크 유형을 선택하는 경우, 지원 유형 및 에이전트 관련 설정을 확인하시기 바랍니다. |
| 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가 자동으로 추가됩니다.