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

Datadog API를 사용한 Android·Android TV 커스텀 계측 (Android and Android TV Custom Instrumentation using the Datadog API)

원문 보기 위키 갱신

Android 애플리케이션을 Datadog API로 직접 계측해 트레이스를 Datadog으로 보내는 방법이에요. dd-sdk-android-trace SDK를 사용해 커스텀 스팬을 만들 수 있어요.

출처: 문서

본문

Datadog의 dd-sdk-android-trace 클라이언트 SDK로 Android 애플리케이션에서 트레이스를 Datadog으로 보내고 다음 기능을 활용할 수 있어요.

  • 애플리케이션의 작업에 대한 커스텀 스팬 만들기.
  • 보내는 각 스팬에 context와 추가 커스텀 속성 추가하기.
  • 자동 일괄 전송(bulk posts)으로 네트워크 사용 최적화하기.

Datadog와 함께 OpenTelemetry를 언제 사용해야 할지 모르겠다면 OpenTelemetry API 커스텀 계측부터 시작해 알아보세요.

개요 (Overview)

OpenTelemetry API로 애플리케이션을 수동 계측해야 하는 이유는 몇 가지가 있어요.

  • Datadog 지원 라이브러리 계측을 사용하지 않는 경우.
  • ddtrace 라이브러리의 기능을 확장하고 싶은 경우.
  • 애플리케이션 계측을 더 세밀하게 제어해야 하는 경우.

ddtrace 라이브러리는 이러한 목표를 달성하는 데 도움이 되는 여러 기법을 제공해요. 다음 섹션은 Datadog에서 사용하기 위해 커스텀 계측에 OpenTelemetry API를 사용하는 방법을 보여줘요.

Datadog은 Android 애플리케이션에서 보낸 수집·인덱싱된 스팬에 대해 비용을 청구하지만, 기본 디바이스에는 청구하지 않아요. 자세한 내용은 APM 요금 문서를 읽어보세요.

Datadog Tracer는 OpenTelemetry 표준을 구현해요. Datadog은 벤더 중립적이고 많은 언어·프레임워크를 지원하며 트레이스·메트릭·로그를 하나의 표준으로 통합하므로, 이를 애플리케이션 트레이싱 인터페이스로 사용할 것을 권장해요. SDK와 OpenTelemetry 통합을 설정하는 지침을 참고하세요.

참고: OpenTelemetry 사양 라이브러리는 minSdk < 26인 프로젝트에서 desugaring을 활성화해야 해요. 프로젝트에서 desugaring을 활성화할 수 없다면 대신 Datadog API로 Trace 제품을 사용할 수 있어요.

참고: Datadog API 구현은 OpenTracing에서 OpenTelemetry로 전환하는 데 도움을 줘요.

설정 (Setup)

  1. build.gradle 파일에 라이브러리를 의존성으로 선언해 Gradle 의존성을 추가하세요.

    dependencies {
      implementation "com.datadoghq:dd-sdk-android-trace:x.x.x"
    }
    
  2. 애플리케이션 컨텍스트, 추적 동의, Datadog 클라이언트 토큰으로 Datadog SDK를 초기화하세요. 보안상의 이유로 클라이언트 토큰을 사용해야 해요. Datadog API 키는 Android 애플리케이션 APK 바이트 코드에 클라이언트 측으로 노출되므로 Datadog SDK 구성에 사용할 수 없어요. 클라이언트 토큰 설정에 대한 자세한 내용은 클라이언트 토큰 문서를 참고하세요.

app.datadoghq.com 사이트 사용자의 경우:

  • Kotlin:
class SampleApplication : Application() {
   override fun onCreate() {
       super.onCreate()
       val configuration = Configuration.Builder(
            clientToken = "<CLIENT_TOKEN>",
            env = "<ENV_NAME>",
            variant = "<APP_VARIANT_NAME>"
       ).build()

       Datadog.initialize(this, configuration, trackingConsent)
   }
}
  • Java:
public class SampleApplication extends Application {
   @Override
   public void onCreate() {
       super.onCreate();
       Configuration configuration = new Configuration.Builder("<CLIENT_TOKEN>", "<ENV_NAME>", "<APP_VARIANT_NAME>")
         .build();

       Datadog.initialize(this, configuration, trackingConsent);
   }
}

다른 사이트 사용자는 초기화 시 Configuration.Builder에 해당 사이트를 지정하면 됩니다. app.datadoghq.eu 사이트는 .useSite(DatadogSite.EU1), us3.datadoghq.com은 .useSite(DatadogSite.US3), us5.datadoghq.com은 .useSite(DatadogSite.US5), app.ddog-gov.com은 .useSite(DatadogSite.US1_FED), us2.ddog-gov.com은 .useSite(DatadogSite.US2_FED), ap1.datadoghq.com은 .useSite(DatadogSite.AP1), ap2.datadoghq.com은 .useSite(DatadogSite.AP2), uk1.datadoghq.com은 .useSite(DatadogSite.UK1)로 지정하면 돼요. Java에서는 각각 DatadogSite 열거형 값을 useSite()에 전달하면 됩니다.

GDPR 규정을 준수하기 위해 SDK는 초기화 시 추적 동의(tracking consent) 값을 요구해요. 값은 다음 중 하나일 수 있어요.

  • TrackingConsent.PENDING: SDK가 데이터 수집·배치를 시작하지만 데이터 수집 엔드포인트로 보내지는 않아요. SDK는 배치된 데이터를 어떻게 처리할지 결정하기 위해 새 추적 동의 값을 기다립니다.
  • TrackingConsent.GRANTED: SDK가 데이터 수집을 시작하고 데이터 수집 엔드포인트로 보내요.
  • TrackingConsent.NOT_GRANTED: SDK가 어떤 데이터도 수집하지 않아요. 로그·트레이스·RUM 이벤트를 수동으로 보낼 수 없어요.

SDK 초기화 후 추적 동의를 업데이트하려면 Datadog.setTrackingConsent(<NEW CONSENT>)를 호출하세요. SDK는 새 동의에 따라 동작을 바꿔요. 예를 들어 현재 추적 동의가 TrackingConsent.PENDING이고 다음으로 업데이트하면:

  • TrackingConsent.GRANTED: SDK가 현재·향후 배치 데이터를 데이터 수집 엔드포인트로 바로 보내요.
  • TrackingConsent.NOT_GRANTED: SDK가 모든 배치 데이터를 지우고 향후 데이터를 수집하지 않아요.

참고: 초기화에 필요한 자격 증명에는 애플리케이션 변형(variant) 이름도 필요하며, BuildConfig.FLAVOR 값(변형이 없으면 빈 문자열)을 사용해야 해요. 이것은 빌드 시 올바른 ProGuard mapping.txt 파일이 자동으로 업로드되어 난독화 해제된 RUM 오류 스택 트레이스를 볼 수 있게 하므로 중요해요. 자세한 내용은 Android 소스 매핑 파일 업로드 가이드를 참고하세요.

isInitialized 유틸리티 메서드를 사용해 SDK가 올바르게 초기화되었는지 확인하세요.

if (Datadog.isInitialized()) {
    // your code here
}

애플리케이션을 작성할 때 setVerbosity 메서드를 호출해 개발 로그를 활성화할 수 있어요. 제공된 레벨 이상의 우선순위를 가진 라이브러리의 모든 내부 메시지가 Android의 Logcat에 기록돼요.

Datadog.setVerbosity(Log.INFO)

Trace 기능을 구성·활성화하세요.

  • Kotlin:
val traceConfig = TraceConfiguration.Builder().build()
Trace.enable(traceConfig)
  • Java:
TraceConfiguration traceConfig = new TraceConfiguration.Builder().build();
Trace.enable(traceConfig);

DatadogTracer를 구성·등록하세요. 보통 애플리케이션의 onCreate() 메서드에서 한 번만 하면 돼요.

  • Kotlin:
import com.datadog.android.trace.GlobalDatadogTracer
import com.datadog.android.trace.DatadogTracing

GlobalDatadogTracer.registerIfAbsent(
  DatadogTracing.newTracerBuilder()
    .build()
)
  • Java:
import com.datadog.android.trace.GlobalDatadogTracer;
import com.datadog.android.trace.DatadogTracing;

GlobalDatadogTracer.registerIfAbsent(
  DatadogTracing.newTracerBuilder(Datadog.getInstance()).build()
);

(선택) 애플리케이션이 생성하는 스팬 수에 따라 SDK 작업량을 최적화하도록 부분 플러시(partial flush) 임계값을 설정하세요. 라이브러리는 완료된 스팬 수가 임계값을 초과할 때까지 기다렸다가 디스크에 씁니다. 이 값을 1로 설정하면 각 스팬이 완료되는 즉시 써요.

  • Kotlin:
val tracer = DatadogTracing.newTracerBuilder()
  .withPartialFlushMinSpans(10)
  .build()
  • Java:
DatadogTracer tracer = DatadogTracing.newTracerBuilder(Datadog.getInstance())
  .withPartialFlushMinSpans(10)
  .build();

다음 메서드로 커스텀 스팬을 시작하세요.

  • Kotlin:
val tracer = GlobalDatadogTracer.get()
val span = tracer.buildSpan("<SPAN_NAME>").start()
// Do something ...
// ...
// Then when the span should be closed
span.finish()
  • Java:
DatadogTracer tracer = GlobalDatadogTracer.get();
DatadogSpan span = tracer.buildSpan("<SPAN_NAME>").start();
// Do something ...
// ...
// Then when the span should be closed
span.finish();

동기 호출에서 scope를 사용하려면:

  • Kotlin:
val span = tracer.buildSpan("<SPAN_NAME1>").start()
try {
  val scope = tracer.activateSpan(span)
  scope?.use {
    // Do something ...
    // ...
    // Start a new Scope
    val childSpan = tracer.buildSpan("<SPAN_NAME2>").start()
    try {
      val innerScope = tracer.activateSpan(childSpan).use { innerScope ->
        // Do something ...
      }
    } catch (e: Throwable) {
      childSpan.logThrowable(e)
    } finally {
      childSpan.finish()
    }
  }
} catch (e: Throwable) {
}
  • Java:
DatadogSpan span = tracer.buildSpan("<SPAN_NAME1>").start();
try {
  DatadogScope scope = tracer.activateSpan(span);
  try {
    // Do something ...
    // ...
    // Start a new Scope
    DatadogSpan childSpan = tracer.buildSpan("<SPAN_NAME2>").start();
    try {
      DatadogScope innerScope = tracer.activateSpan(childSpan);
      try {
        // Do something ...
      }
      finally {
        innerScope.close();
      }
    } catch (Throwable e) {
      childSpan.logThrowable(e);
    } finally {
      childSpan.finish();
    }
  }
  finally {
    scope.close();
  }
} catch (Throwable e){
}

비동기 호출에서 scope를 사용하려면:

  • Kotlin:
val span = tracer.buildSpan("<SPAN_NAME1>").start()
try {
  val scope = tracer.activateSpan(span)
  scope.use {
    // Do something ...
    Thread {
      // Step 2: reactivate the Span in the worker thread
      tracer.activateSpan(span).use {
        // Do something ...
      }
    }.start()
  }
} catch (e: Throwable) {
  span.logThrowable(e)
} finally {
  span.finish()
}
  • Java:
DatadogSpan span = tracer.buildSpan("<SPAN_NAME1>").start();
try {
    DatadogScope scope = tracer.activateSpan(span);
    try {
        // Do something ...
        new Thread(() ->{
            // Step 2: reactivate the Span in the worker thread
            DatadogScope scopeContinuation = tracer.activateSpan(span);
            try {
                // Do something
            } finally {
                scope.close();
            }
        }).start();

    } finally {
        scope.close();
    }
} catch (Throwable e) {
      span.logThrowable(e);
} finally {
      span.finish();
}

(선택) 예를 들어 프론트엔드에서 백엔드로 환경 간에 트레이스를 수동으로 분산하려면:

  1. 클라이언트 요청에 트레이서 컨텍스트를 주입하세요.

    • Kotlin:
    val tracer = GlobalDatadogTracer.get()
    val span = tracer.buildSpan("<SPAN_NAME>").start()
    val tracedRequestBuilder = Request.Builder()
    tracer.propagate().inject<Request.Builder?>(
      span.context(),
      tracedRequestBuilder
    ) { builder, key, value ->
      builder?.addHeader(key, value)
    }
    val request = tracedRequestBuilder.build()
    // Dispatch the request and finish the span after.
    
    • Java:
    DatadogTracer tracer = GlobalDatadogTracer.get();
    DatadogSpan span = tracer.buildSpan("<SPAN_NAME>").start();
    Request.Builder tracedRequestBuilder = new Request.Builder();
    tracer.propagate().inject(
      span.context(),
      tracedRequestBuilder,
      new Function3<Request.Builder,String,String,Unit>(){
        @Override
        public Unit invoke(Request.Builder builder, String key, String value) {
          builder.addHeader(key, value);
          return Unit.INSTANCE;
        }
      });
    Request request = tracedRequestBuilder.build();
    // Dispatch the request and finish the span after.
    
  2. 서버 코드에서 헤더로부터 클라이언트 트레이서 컨텍스트를 추출하세요.

    • Kotlin:
    val tracer = GlobalDatadogTracer.get()
    val extractedContext = tracer.propagate()
      .extract(request) { carrier, classifier ->
        val headers = carrier.headers.toMultimap()
          .map { it.key to it.value.joinToString(";") }
          .toMap()
    
        for ((key, value) in headers) classifier(key, value)
      }
    
    val serverSpan = tracer.buildSpan("<SERVER_SPAN_NAME>").withParentContext(extractedContext).start()
    
    • Java:
    DatadogTracer tracer = GlobalDatadogTracer.get();
    DatadogSpanContext extractedContext = tracer.propagate()
      .extract(request,
        new Function2<Request, Function2<? super String, ? super String, Boolean>, Unit>() {
          @Override
          public Unit invoke(
            Request carrier,
            Function2<? super String, ? super String, Boolean> classifier
          ) {
            request.headers().forEach(pair -> {
              String key = pair.component1();
              String value = pair.component2();
    
              classifier.invoke(key, value);
            });
    
            return Unit.INSTANCE;
          }
        });
    DatadogSpan serverSpan = tracer.buildSpan("<SERVER_SPAN_NAME>").withParentContext(extractedContext).start();
    

참고: OkHttp 클라이언트를 사용하는 코드베이스에는 Datadog이 아래 구현을 제공해요.

(선택) 스팬에 추가 태그를 제공하려면:

span.setTag("http.url", url)

(선택) 스팬에 오류가 있다고 표시하려면 해당 메서드로 기록하세요.

span.logThrowable(throwable)
span.logErrorMessage(message)

배치하기 전에 Span 이벤트의 일부 속성을 수정해야 한다면 Trace 기능을 활성화할 때 SpanEventMapper 구현을 제공하면 돼요.

  • Kotlin:
val traceConfig = TraceConfiguration.Builder()
  // ...
  .setEventMapper(spanEventMapper)
  .build()
  • Java:
TraceConfiguration config = new TraceConfiguration.Builder()
  // ...
  .setEventMapper(spanEventMapper)
  .build();

Kotlin 확장 (Kotlin Extensions)

Span 안에서 람다 실행하기 (Running a lambda within a Span)

주어진 람다의 성능을 모니터링하려면 withinSpan() 메서드를 사용할 수 있어요. 기본적으로 스팬에 대한 scope가 생성되지만, activate 매개변수를 false로 설정해 이 동작을 비활성화할 수 있어요.

import com.datadog.android.trace.withinSpan
import com.datadog.android.trace.api.span.DatadogSpan

withinSpan("<SPAN_NAME>", parentSpan, activate) {
  // Your code here
}

SQLite 트랜잭션 트레이싱 (Tracing SQLite transaction)

SQLiteDatabase를 사용해 데이터를 로컬에 영속화한다면 다음 메서드로 데이터베이스 트랜잭션을 트레이싱할 수 있어요.

import com.datadog.android.trace.sqlite.transactionTraced
import android.database.sqlite.SQLiteDatabase

sqliteDatabase.transactionTraced("<SPAN_NAME>", isExclusive) { database ->
  // Your queries here
  database.insert("<TABLE_NAME>", null, contentValues)

  // Decorate the Span
  setTag("<TAG_KEY>", "<TAG_VALUE>")
}

이것은 core-ktx AndroidX 패키지에서 제공하는 SQLiteDatabase.transaction 메서드처럼 동작하며 스팬 작업 이름만 필요해요.

통합 (Integrations)

수동 트레이싱 외에도 Datadog SDK는 다음 통합을 제공해요.

OkHttp

OkHttp 요청을 트레이싱하려면 제공된 Interceptor(dd-sdk-android-okhttp 라이브러리에서 찾을 수 있음)를 다음과 같이 추가할 수 있어요.

  1. 모듈 수준 build.gradle 파일에 dd-sdk-android-okhttp 라이브러리의 Gradle 의존성을 추가하세요.

    dependencies {
        implementation "com.datadoghq:dd-sdk-android-okhttp:x.x.x"
    }
    
  2. DatadogInterceptor를 OkHttpClient에 추가하세요.

    • Kotlin:
    val tracedHosts = listOf("example.com", "example.eu")
    val okHttpClient = OkHttpClient.Builder()
      .addInterceptor(
        DatadogInterceptor.Builder(tracedHosts)
          .setTraceSampleRate(20f)
          .build()
      )
      .build()
    
    • Java:
    List<String> tracedHosts = Arrays.asList("example.com", "example.eu");
    OkHttpClient okHttpClient = new OkHttpClient.Builder()
      .addInterceptor(
        new DatadogInterceptor.Builder(tracedHosts)
          .setTraceSampleRate(20f)
          .build()
      )
      .build();
    

이것은 제공된 호스트와 일치하는 OkHttpClient가 처리하는 각 요청 주위에 스팬을 만들고, 관련 정보(URL, 메서드, 상태 코드, 오류)를 자동으로 채우며, 트레이싱 정보를 백엔드로 전파해 Datadog 내에서 통합된 트레이스를 얻을 수 있게 해요.

네트워크 트레이스는 조절 가능한 샘플링 비율로 샘플링돼요. 기본적으로 100% 샘플링이 적용돼요.

인터셉터는 애플리케이션 수준에서 요청을 추적해요. 리다이렉션을 따를 때처럼 더 자세한 정보가 필요하면 네트워크 수준에서 TracingInterceptor를 추가할 수도 있어요.

  • Kotlin:
val tracedHosts = listOf("example.com", "example.eu")
val okHttpClient = OkHttpClient.Builder()
  .addInterceptor(
    DatadogInterceptor.Builder(tracedHosts)
      .setTraceSampleRate(20f)
      .build()
  )
  .addNetworkInterceptor(
    TracingInterceptor.Builder(tracedHosts)
      .setTraceSampleRate(100f)
      .build()
  )
  .build()
  • Java:
List<String> tracedHosts = Arrays.asList("example.com", "example.eu");
OkHttpClient okHttpClient = new OkHttpClient.Builder()
  .addInterceptor(
    new DatadogInterceptor.Builder(tracedHosts)
      .setTraceSampleRate(20f)
      .build()
  )
  .addNetworkInterceptor(
    new TracingInterceptor.Builder(tracedHosts)
      .setTraceSampleRate(20f)
      .build()
  )
  .build();

이 경우 특정 요청에 대해 업스트림 인터셉터가 내린 트레이스 샘플링 결정은 다운스트림 인터셉터에서 존중돼요.

OkHttp Request가 실행되는 방식(Thread pool 사용) 때문에 요청 스팬은 요청을 트리거한 스팬과 자동으로 연결되지 않아요. OkHttp Request.Builder의 Request.Builder.parentSpan 확장 메서드를 사용해 수동으로 부모 스팬을 제공할 수 있어요.

  • Kotlin:
val request = Request.Builder()
  .url(requestUrl)
  .parentSpan(parentSpan)
  .build()
  • Java:
Request.Builder requestBuilder = new Request.Builder()
  .url(requestUrl);
Request request = OkHttpRequestExtKt
  .parentSpan(requestBuilder, parentSpan)
  .build();

참고:

  • 여러 Interceptor를 사용한다면 이 인터셉터가 먼저 호출되어야 해요.
  • Datadog 구성에서 커스텀 트레이싱 헤더 타입을 정의하고 GlobalDatadogTracer로 등록된 SDK를 사용한다면, 사용 중인 트레이서에도 동일한 트레이싱 헤더 타입이 설정되어 있는지 확인하세요.

Cronet

OkHttp 대신 Cronet을 사용한다면 CronetEngine을 분산 트레이싱용으로 계측할 수 있어요.

  1. 모듈 수준 build.gradle 파일에 Gradle 의존성을 추가하세요.

    dependencies {
        implementation "com.datadoghq:dd-sdk-android-cronet:x.x.x"
    }
    
  2. CronetEngine.Builder를 계측하세요.

    • Kotlin:
    val cronetEngine = CronetEngine.Builder(context)
      .configureDatadogInstrumentation(
        apmInstrumentationConfiguration = ApmNetworkInstrumentationConfiguration(
          tracedHosts = listOf("example.com", "example.eu")
        )
      )
      .build()
    
    • Java:
    CronetEngine.Builder builder = new CronetEngine.Builder(context);
    CronetEngine cronetEngine = CronetIntegrationPluginKt
      .configureDatadogInstrumentation(
        builder,
        null,
        new ApmNetworkInstrumentationConfiguration(
          Arrays.asList("example.com", "example.eu")
        )
      )
      .build();
    

이것은 제공된 호스트와 일치하는 CronetEngine이 처리하는 각 요청 주위에 스팬을 만들어요. 관련 정보(URL, 메서드, 상태 코드, 오류)가 자동으로 채워지고 트레이싱 정보가 백엔드로 전파돼요.

리다이렉트 트레이싱 (Tracing redirects)

기본적으로 트레이싱은 애플리케이션 수준에서 적용돼요. 리다이렉트된 요청도 트레이싱하려면 트레이스 범위를 ALL로 설정하세요.

  • Kotlin:
val cronetEngine = CronetEngine.Builder(context)
  .configureDatadogInstrumentation(
    apmInstrumentationConfiguration = ApmNetworkInstrumentationConfiguration(
      tracedHosts = listOf("example.com", "example.eu"),
    )
    .setTraceScope(ApmNetworkTracingScope.ALL)
  )
  .build()
  • Java:
CronetEngine.Builder builder = new CronetEngine.Builder(context);
CronetEngine cronetEngine = CronetIntegrationPluginKt
  .configureDatadogInstrumentation(
    builder,
    null,
    new ApmNetworkInstrumentationConfiguration(
      Arrays.asList("example.com", "example.eu")
    ).setTraceScope(ApmNetworkTracingScope.ALL)
  )
  .build();

헤더 전파 전용 (Header propagation only)

로컬 스팬을 만들지 않고 트레이싱 헤더를 전파하려면 헤더 전파 전용 모드를 사용하세요.

참고: 이 모드는 리소스 추적을 RUM 계측이 처리하므로 RUM이 활성화되어 있어야 해요. configureDatadogInstrumentation 호출에서 RumNetworkInstrumentationConfiguration을 제공해야 해요.

  • Kotlin:
val cronetEngine = CronetEngine.Builder(context)
  .configureDatadogInstrumentation(
    rumInstrumentationConfiguration = RumNetworkInstrumentationConfiguration(),
    apmInstrumentationConfiguration = ApmNetworkInstrumentationConfiguration(
      tracedHosts = listOf("example.com", "example.eu")
    ).setHeaderPropagationOnly()
  )
  .build()
  • Java:
CronetEngine.Builder builder = new CronetEngine.Builder(context);
CronetEngine cronetEngine = CronetIntegrationPluginKt
  .configureDatadogInstrumentation(
    builder,
    new RumNetworkInstrumentationConfiguration(),
    new ApmNetworkInstrumentationConfiguration(
      Arrays.asList("example.com", "example.eu")
    ).setHeaderPropagationOnly()
  )
  .build();

샘플링 비율 (Sampling rate)

트레이스 샘플링 비율을 구성하려면:

  • Kotlin:
val cronetEngine = CronetEngine.Builder(context)
  .configureDatadogInstrumentation(
    apmInstrumentationConfiguration = ApmNetworkInstrumentationConfiguration(
      tracedHosts = listOf("example.com", "example.eu")
    ).setTraceSampleRate(20f)
  )
  .build()
  • Java:
CronetEngine.Builder builder = new CronetEngine.Builder(context);
CronetEngine cronetEngine = CronetIntegrationPluginKt
  .configureDatadogInstrumentation(
    builder,
    null,
    new ApmNetworkInstrumentationConfiguration(
      Arrays.asList("example.com", "example.eu")
    ).setTraceSampleRate(20f)
  )
  .build();

알려진 제한 사항:

  • Cronet API 제한으로 리다이렉트된 요청에는 트레이싱 헤더가 전파되지 않아요.
  • 재시도는 계측할 수 없어요.

배치 수집 (Batch collection)

모든 스팬은 먼저 로컬 디바이스에 배치로 저장돼요. 각 배치는 수집 사양을 따릅니다. 네트워크를 사용할 수 있고 배터리가 충분히 높아 Datadog SDK가 최종 사용자 경험에 영향을 주지 않을 때 전송돼요. 애플리케이션이 포그라운드에 있는 동안 네트워크를 사용할 수 없거나 데이터 업로드가 실패하면, 성공적으로 보낼 수 있을 때까지 배치가 유지돼요.

즉 사용자가 오프라인 상태로 애플리케이션을 열어도 데이터가 손실되지 않아요.

SDK가 디스크 공간을 너무 많이 사용하지 않도록 데이터가 너무 오래되면 디스크의 데이터는 자동으로 폐기돼요.

초기화 (Initialization)

DatadogTracer를 초기화할 때 DatadogTracerBuilder에서 다음 메서드를 사용할 수 있어요.

메서드 설명
withServiceName(<SERVICE_NAME>) service 값을 설정해요.
withPartialFlushMinSpans(<INT>) 이 임계값에 도달하면(닫힌 <INT> 개수의 스팬이 대기 중) 플러시 메커니즘이 트리거되어 보류 중인 모든 닫힌 스팬이 처리·수집 전송돼요.
withTag(<KEY>, <VALUE>) Tracer가 만든 스팬에 추가할 <KEY>:<VALUE> 태그 쌍을 설정해요.
setBundleWithRumEnabled(true) true로 설정하면 스팬이 현재 RUM View 정보로 강화돼요. 이렇게 하면 특정 View 수명 동안 생성된 모든 스팬을 RUM Explorer에서 볼 수 있어요.
withSampleRate(<FLOAT>) 수집할 트레이스의 비율을 정의하는 0-100 값을 설정해요.
withTracingHeadersTypes(Set<TracingHeaderType>) Tracer가 주입할 수 있는 트레이싱 헤더 스타일을 설정해요.
setTraceRateLimit(<INT>) 트레이스 비율 제한을 설정해요. 초당 허용되는 최대 트레이스 수예요.

더 알아보기 (Learn more)

도움이 되는 추가 문서, 링크, 글: