본문 바로가기
WIKI 기술 지식 베이스

Java OpenTracing 계측

원문 보기 위키 갱신

{% alert level="info" %} OpenTracing 지원은 더 이상 사용되지 않는(deprecated) 사양을 기반으로 해요. 오픈 스펙으로 코드를 계측하려면 OpenTelemetry를 사용하세요. Datadog SDK에서 OpenTelemetry 계측 데이터를 처리하는 방법을 시도해 보세요. {% /alert %}

Datadog는 OpenTracing API와 통합돼요.

출처: 문서

본문

설정

Maven의 경우 pom.xml에 다음을 추가하세요:

<!-- OpenTracing API -->
<dependency>
    <groupId>io.opentracing</groupId>
    <artifactId>opentracing-api</artifactId>
    <version>0.32.0</version>
</dependency>

<dependency>
    <groupId>io.opentracing</groupId>
    <artifactId>opentracing-util</artifactId>
    <version>0.32.0</version>
</dependency>

<!-- Datadog API -->
<dependency>
    <groupId>com.datadoghq</groupId>
    <artifactId>dd-trace-api</artifactId>
    <version>${dd-trace-java.version}</version>
</dependency>

<!-- Datadog OpenTracing bridge (only needed if you do not use dd-java-agent for autoinstrumentation) -->
<dependency>
    <groupId>com.datadoghq</groupId>
    <artifactId>dd-trace-ot</artifactId>
    <version>${dd-trace-java.version}</version>
</dependency>

Gradle의 경우 다음을 추가하세요:

compile group: 'io.opentracing', name: 'opentracing-api', version: "0.32.0"
compile group: 'io.opentracing', name: 'opentracing-util', version: "0.32.0"
compile group: 'com.datadoghq', name: 'dd-trace-api', version: "${dd-trace-java.version}"
// Datadog OpenTracing bridge (only needed if you do not use dd-java-agent for autoinstrumentation)
compile group: 'com.datadoghq', name: 'dd-trace-ot', version: "${dd-trace-java.version}"

환경 변수나 시스템 속성을 사용해 애플리케이션을 구성하세요. 자세한 내용은 설정 섹션을 참고하세요.

자동 계측을 사용하지 않는다면 구성된 트레이서를 GlobalTracer에 등록해야 해요. 이를 위해 애플리케이션 시작 초반(예: main 메서드)에 GlobalTracer.register(DDTracer.builder().build())를 호출하세요.

import datadog.opentracing.DDTracer;
import io.opentracing.Tracer;
import io.opentracing.util.GlobalTracer;

public class Application {
    public static void main(String[] args) {
        DDTracer tracer = DDTracer.builder().build();
        GlobalTracer.register(tracer);
        // register the same tracer with the Datadog API
        datadog.trace.api.GlobalTracer.registerIfAbsent(tracer);
    }
}

환경 변수와 시스템 속성 외에도 DDTracer.Builder 인터페이스의 일부로 추가 설정 옵션이 있어요. 전체 목록은 Javadoc을 참고하세요.

참고: dd-java-agent를 classpath에 절대 추가하지 마세요. 추가하면 예상하지 못한 동작이 발생할 수 있어요.

비동기 트레이스

비동기 트레이스는 한 스레드에서 span을 시작하고 다른 스레드에서 끝내는 것이에요. 이 동작을 계측하려면 span이 활성화된 각 스레드에서 새 scope를 사용해야 해요.

// Step 1: start the Scope/Span on the work submission thread
final Tracer tracer = GlobalTracer.get();
final Span span = tracer.buildSpan("ServicehandlerSpan").start();

try (final Scope scope = tracer.activateSpan(span)) {
    // submission thread impl...

    submitAsyncTask(new Runnable() {
        @Override
        public void run() {
            // Step 2: reactivate the Span in the worker thread
            try (final Scope scope = tracer.activateSpan(span)) {
              // worker thread impl
            } finally {
              // Step 3: Finish Span when work is complete
              span.finish();
            }
       }
    });
}

분산 트레이싱을 위한 컨텍스트 주입과 추출

OpenTracing으로 수동 계측을 사용해 분산 트레이스를 만드세요:

// Step 1: Inject the Datadog headers in the client code
Span span = tracer.buildSpan("httpClientSpan").start();
try (Scope scope = tracer.activate(span)) {
    HttpRequest request = /* your code here */;

    tracer.inject(span.context(),
                  Format.Builtin.HTTP_HEADERS,
                  new MyHttpHeadersInjectAdapter(request));

    // http request impl...
} finally {
    span.finish();
}

public static class MyHttpHeadersInjectAdapter implements TextMap {
    private final HttpRequest httpRequest;

    public HttpHeadersInjectAdapter(final HttpRequest httpRequest) {
        this.httpRequest = httpRequest;
    }

    @Override
    public void put(final String key, final String value) {
        httpRequest.addHeader(key, value);
    }

    @Override
    public Iterator<Map.Entry<String, String>> iterator() {
        throw new UnsupportedOperationException("This class should be used only with tracer#inject()");
    }
}

// Step 2: Extract the Datadog headers in the server code
HttpRequest request = /* your code here */;

final SpanContext extractedContext =
  GlobalTracer.get().extract(Format.Builtin.HTTP_HEADERS,
                             new MyHttpRequestExtractAdapter(request));

// is a child of http client span in step 1
Span span = tracer.buildSpan("httpServerSpan").asChildOf(extractedContext).start();
try (Scope scope = tracer.activateSpan(span)) {
    // http server impl...
} finally {
    span.finish();
}

public class MyHttpRequestExtractAdapter implements TextMap {
    private final HttpRequest request;

    public HttpRequestExtractAdapter(final HttpRequest request) {
        this.request = request;
    }

    @Override
    public Iterator<Map.Entry<String, String>> iterator() {
        return request.headers().iterator();
    }

    @Override
    public void put(final String key, final String value) {
        throw new UnsupportedOperationException("This class should be used only with Tracer.extract()!");
    }
}

위 예제는 OpenTracing 클래스만 사용한다는 점에 주의하세요. 자세한 내용과 정보는 OpenTracing API를 참고하세요.

더 알아보기 (Learn more)

추가로 도움이 되는 문서, 링크, 아티클: