- 필수 기능
- 시작하기
- Glossary
- 표준 속성
- Guides
- Agent
- 통합
- 개방형텔레메트리
- 개발자
- API
- Datadog Mobile App
- CoScreen
- Cloudcraft
- 앱 내
- 서비스 관리
- 인프라스트럭처
- 애플리케이션 성능
- APM
- Continuous Profiler
- 스팬 시각화
- 데이터 스트림 모니터링
- 데이터 작업 모니터링
- 디지털 경험
- 소프트웨어 제공
- 보안
- AI Observability
- 로그 관리
- 관리
다음의 경우 OpenTelemetry API를 사용해 애플리케이션을 수동으로 계측해야 합니다.
ddtrace
라이브러리의 기능을 확장하고 싶습니다.ddtrace
라이브러리는 이러한 목표를 달성하는 데 도움이 됩니다. 다음 섹션에서는 커스텀 계측을 위해 Datadog과 OpenTelemetry API를 함께 사용하는 방법을 다룹니다.
build.gradle
file:android {
//(...)
}
dependencies {
implementation "com.datadoghq:dd-sdk-android-trace:x.x.x"
implementation "com.datadoghq:dd-sdk-android-trace-otel:x.x.x"
//(...)
}
Note: If you are targeting Android API level lower than 24, enable desugaring by adding the following lines to your build.gradle
file:
android {
compileOptions {
isCoreLibraryDesugaringEnabled = true
// ...
}
dependencies {
coreLibraryDesugaring "com.android.tools:desugar_jdk_libs:[latest_version]"
// ...
}
}
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)
}
}
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);
}
}
class SampleApplication : Application() {
override fun onCreate() {
super.onCreate()
val configuration = Configuration.Builder(
clientToken = <CLIENT_TOKEN>,
env = <ENV_NAME>,
variant = <APP_VARIANT_NAME>
)
.useSite(DatadogSite.EU1)
.build()
Datadog.initialize(this, configuration, trackingConsent)
}
}
public class SampleApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
Configuration configuration =
new Configuration.Builder(<CLIENT_TOKEN>, <ENV_NAME>, <APP_VARIANT_NAME>)
.useSite(DatadogSite.EU1)
.build();
Datadog.initialize(this, configuration, trackingConsent);
}
}
class SampleApplication : Application() {
override fun onCreate() {
super.onCreate()
val configuration = Configuration.Builder(
clientToken = <CLIENT_TOKEN>,
env = <ENV_NAME>,
variant = <APP_VARIANT_NAME>
)
.useSite(DatadogSite.US3)
.build()
Datadog.initialize(this, configuration, trackingConsent)
}
}
public class SampleApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
Configuration configuration =
new Configuration.Builder(<CLIENT_TOKEN>, <ENV_NAME>, <APP_VARIANT_NAME>)
.useSite(DatadogSite.US3)
.build();
Datadog.initialize(this, configuration, trackingConsent);
}
}
class SampleApplication : Application() {
override fun onCreate() {
super.onCreate()
val configuration = Configuration.Builder(
clientToken = <CLIENT_TOKEN>,
env = <ENV_NAME>,
variant = <APP_VARIANT_NAME>
)
.useSite(DatadogSite.US5)
.build()
Datadog.initialize(this, configuration, trackingConsent)
}
}
public class SampleApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
Configuration configuration =
new Configuration.Builder(<CLIENT_TOKEN>, <ENV_NAME>, <APP_VARIANT_NAME>)
.useSite(DatadogSite.US5)
.build();
Datadog.initialize(this, configuration, trackingConsent);
}
}
class SampleApplication : Application() {
override fun onCreate() {
super.onCreate()
val configuration = Configuration.Builder(
clientToken = <CLIENT_TOKEN>,
env = <ENV_NAME>,
variant = <APP_VARIANT_NAME>
)
.useSite(DatadogSite.US1_FED)
.build()
Datadog.initialize(this, configuration, trackingConsent)
}
}
public class SampleApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
Configuration configuration =
new Configuration.Builder(<CLIENT_TOKEN>, <ENV_NAME>, <APP_VARIANT_NAME>)
.useSite(DatadogSite.US1_FED)
.build();
Datadog.initialize(this, configuration, trackingConsent);
}
}
class SampleApplication : Application() {
override fun onCreate() {
super.onCreate()
val configuration = Configuration.Builder(
clientToken = <CLIENT_TOKEN>,
env = <ENV_NAME>,
variant = <APP_VARIANT_NAME>
)
.useSite(DatadogSite.AP1)
.build()
Datadog.initialize(this, configuration, trackingConsent)
}
}
public class SampleApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
Configuration configuration =
new Configuration.Builder(<CLIENT_TOKEN>, <ENV_NAME>, <APP_VARIANT_NAME>)
.useSite(DatadogSite.AP1)
.build();
Datadog.initialize(this, configuration, trackingConsent);
}
}
To be GDPR compliant, the SDK requires the tracking consent value at initialization. The tracking consent can be one of the following values see Tracking Consent:
TrackingConsent.PENDING
: The SDK starts collecting and batching the data but does not send it to the data
collection endpoint. The SDK waits for the new tracking consent value to decide what to do with the batched data.TrackingConsent.GRANTED
: The SDK starts collecting the data and sends it to the data collection endpoint.TrackingConsent.NOT_GRANTED
: The SDK does not collect any data. You will not be able to manually send any logs, traces, or
RUM events.To update the tracking consent after the SDK is initialized, call: Datadog.setTrackingConsent(<NEW CONSENT>)
.
The SDK changes its behavior according to the new consent. For example, if the current tracking consent is TrackingConsent.PENDING
and you update it to:
TrackingConsent.GRANTED
: The SDK sends all current batched data and future data directly to the data collection endpoint.TrackingConsent.NOT_GRANTED
: The SDK wipes all batched data and does not collect any future data.Use the utility method isInitialized
to check if the SDK is properly initialized:
if (Datadog.isInitialized()) {
// your code here
}
When writing your application, you can enable development logs by calling the setVerbosity
method. All internal messages in the library with a priority equal to or higher than the provided level are then logged to Android’s Logcat:
Datadog.setVerbosity(Log.INFO)
val traceConfig = TraceConfiguration.Builder().build()
Trace.enable(traceConfig)
final TraceConfiguration traceConfig = TraceConfiguration.Builder().build();
Trace.enable(traceConfig);
OtelTracerProvider
and register OpenTelemetrySdk
in GlobalOpenTelemetry
in your onCreate()
method:GlobalOpenTelemetry.set(object : OpenTelemetry {
private val tracerProvider = OtelTracerProvider.Builder()
.setService([BuildConfig.APPLICATION_ID])
.build()
override fun getTracerProvider(): TracerProvider {
return tracerProvider
}
override fun getPropagators(): ContextPropagators {
return ContextPropagators.noop()
}
})
// and later on if you want to access the tracer provider
val tracerProvider = GlobalOpenTelemetry.get().getTracer(instrumentationName = "<instrumentation_name>")
GlobalOpenTelemetry.set(new OpenTelemetry() {
private final TracerProvider tracerProvider = new OtelTracerProvider.Builder()
.setService(BuildConfig.APPLICATION_ID)
.build();
@Override
public TracerProvider getTracerProvider() {
return tracerProvider;
}
@Override
public ContextPropagators getPropagators() {
return ContextPropagators.noop();
}
};
// and later on if you want to access the tracer provider
final TracerProvider tracerProvider = GlobalOpenTelemetry.get().getTracer("<instrumentation_name>");
Note: Ensure GlobalOpenTelemetry.set
API is only called once per process. Otherwise, you can create a TracerProvider
and use it as a singleton in your project.
Note: The setService
method is used to set the service name for the tracer provider. The service name is used to identify the application in the Datadog UI. You can either use the GlobalOpenTelemetry
to hold a single instance of the TracerProvider
or create your own instance and use it in your application code as needed.
val span = tracer.spanBuilder(spanName = "<span_name>").startSpan()
// do something you want to measure ...
// ... then, when the operation is finished:
span.end()
final Span span = tracer.spanBuilder("<span_name>").startSpan();
// do something you want to measure ...
// ... then, when the operation is finished:
span.end();
let childSpan = tracer.spanBuilder(spanName = "response decoding")
.setParent(Context.current().with(parentSpan)) // make it child of parent span
.startSpan()
// ... do your logic here ...
childSpan.end()
final Span childSpan = tracer.spanBuilder("<span_name>")
.setParent(Context.current().with(parentSpan)) // make it child of parent span
.startSpan();
// ... do your logic here ...
childSpan.end();
tracer.spanBuilder(spanName = "<span_name>").setAttribute(key = "<key_name>", value = <key_value>).startSpan()
tracer.spanBuilder("<span_name>").setAttribute("<key_name>", <key_value>).startSpan();
span.setStatus(StatusCode.ERROR, description = "<error_description>")
// or if you want to set an exception
span.recordException(exception)
span.setStatus(StatusCode.ERROR, "<error_description>")
// or if you want to set an exception
span.recordException(exception)
val linkedSpan = tracer.spanBuilder(spanName = "linked span").startSpan()
linkedSpan.end()
val spanWithLinks = tracer.spanBuilder(spanName = "span with links")
.addLink(spanContext = linkedSpan.spanContext)
.startSpan()
spanWithLinks.end()
final Span linkedSpan = tracer.spanBuilder("linked span").startSpan();
linkedSpan.end();
final Span spanWithLinks = tracer.spanBuilder("span with links")
.addLink(linkedSpan.getSpanContext())
.startSpan();
spanWithLinks.end();
First, you need to add the OpenTelemetry OkHttp extension module to your project dependencies:
android {
//(...)
}
dependencies {
implementation "com.datadoghq:dd-sdk-android-okhttp:x.x.x"
implementation "com.datadoghq:dd-sdk-android-okhttp-otel:x.x.x"
//(...)
}
After you create an OkHttp
Request
, you can attach a parent span to the request:
val parentSpan = tracer.spanBuilder(spanName = "parent span").startSpan()
parentSpan.end()
val request = Request.Builder()
.url("<URL>")
.addParentSpan(parentSpan)
.build()
final Span parentSpan = tracer.spanBuilder("parent span").startSpan();
parentSpan.end()
final Request:request = new Request.Builder()
.url("<URL>")
.addParentSpan(parentSpan)
.build();