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

Kotlin Multiplatform 로그 수집

원문 보기 위키 갱신

Datadog의 dd-sdk-kotlin-multiplatform-logs 클라이언트 측 로깅 라이브러리를 사용해 Android 또는 iOS 애플리케이션에서 Datadog로 로그를 보내고 다음 기능을 사용할 수 있어요:

  • JSON 형식으로 기본 제공되는 형태로 Datadog에 로그 기록.
  • 보내는 모든 로그에 context와 추가 사용자 정의 속성 추가.
  • Java 또는 Kotlin에서 잡은 예외 전달.
  • iOS 오류 전달.
  • 실제 클라이언트 IP 주소와 User-Agent 기록.
  • 자동 벌크 게시로 네트워크 사용량 최적화.

출처: 문서

본문

설정

  1. 모듈 레벨 build.gradle.kts 파일에서 라이브러리를 의존성으로 선언해 공통 소스 세트에 Gradle 의존성을 추가하세요. 다음 예시의 x.x.x를 dd-sdk-kotlin-multiplatform-logs의 최신 버전으로 바꾸세요.
kotlin {
  sourceSets {
    commonMain.dependencies {
      implementation("com.datadoghq:dd-sdk-kotlin-multiplatform-logs:x.x.x")
    }
  }
}

iOS용 네이티브 의존성을 추가하세요.

참고: iOS에서 크래시 추적이 활성화되어 있다면 Kotlin 2.0.20 이상이 필요해요. 그렇지 않으면 PLCrashReporter와의 호환성 때문에 크래시 추적이 활성화된 경우 애플리케이션이 중단될 수 있어요.

링킹 단계에 필요한 다음 Datadog iOS SDK 의존성을 추가하세요:

  • DatadogCore
  • DatadogLogs
  • DatadogCrashReporting

참고: 이 의존성의 버전은 Datadog Kotlin Multiplatform SDK 자체가 사용하는 버전과 맞춰야 해요. 각 Kotlin Multiplatform SDK 릴리스에 대한 iOS SDK 버전의 전체 매핑은 버전 호환성 가이드에서 찾을 수 있어요. Kotlin Multiplatform SDK 버전 1.3.0 이하를 사용한다면 DatadogCore와 DatadogLogs 대신 DatadogObjc 의존성을 추가하세요.

CocoaPods 플러그인으로 네이티브 iOS 의존성 추가하기

iOS 애플리케이션에서 Kotlin Multiplatform 라이브러리를 CocoaPods 의존성으로 사용한다면 다음과 같이 의존성을 추가할 수 있어요:

cocoapods {
    // ...

    framework {
        baseName = "sharedLib"
    }

    pod("DatadogCore") {
        linkOnly = true
        version = x.x.x
    }

    pod("DatadogLogs") {
        linkOnly = true
        version = x.x.x
    }

    pod("DatadogCrashReporting") {
        linkOnly = true
        version = x.x.x
    }
}

Xcode로 네이티브 iOS 의존성 추가하기

Kotlin Multiplatform 라이브러리를 Xcode 빌드의 일부로 embedAndSignAppleFrameworkForXcode Gradle 태스크와 함께 프레임워크로 통합한다면 Xcode에서 직접 필요한 의존성을 다음과 같이 추가할 수 있어요:

  1. Xcode에서 프로젝트를 클릭하고 Package Dependencies 탭으로 이동하세요.
  2. 패키지 URL로 https://github.com/DataDog/dd-sdk-ios.git을 추가해 iOS SDK 패키지 의존성을 추가하세요.
  3. 위 표의 버전을 선택하세요.
  4. 필요한 애플리케이션 타깃을 클릭하고 General 탭을 여세요.
  5. Frameworks, Libraries, and Embedded Content 섹션까지 스크롤해 위에서 언급한 의존성을 추가하세요.

애플리케이션 컨텍스트(Android 전용; iOS는 null일 수 있음), 추적 동의(tracking consent), Datadog 클라이언트 토큰으로 Datadog SDK를 초기화하세요. 보안상의 이유로 클라이언트 토큰을 사용해야 해요. Datadog API 키는 Android 애플리케이션 APK 바이트 코드에서 클라이언트 측에 노출되므로 Datadog SDK 구성에 사용할 수 없어요.

클라이언트 토큰 설정에 대한 자세한 내용은 클라이언트 토큰 문서를 참고하세요.

// in common source set
fun initializeDatadog(context: Any? = null) {
    // context should be application context on Android and can be null on iOS
    val appClientToken = <CLIENT_TOKEN>
    val appEnvironment = <ENV_NAME>
    val appVariantName = <APP_VARIANT_NAME>

    val configuration = Configuration.Builder(
            clientToken = appClientToken,
            env = appEnvironment,
            variant = appVariantName
    )<YOUR_KOTLIN_MULTIPLATFORM_SITE_CONFIG>
        .build()

    Datadog.initialize(context, configuration, trackingConsent)
}
GDPR을 준수하기 위해 SDK는 초기화 시 추적 동의 값을 요구해요.
추적 동의는 다음 값 중 하나가 될 수 있어요:

- `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가 배칭된 모든 데이터를 지우고 향후 데이터도 수집하지 않아요.

isInitialized 유틸리티 메서드를 사용해 SDK가 제대로 초기화됐는지 확인하세요:

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

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

Datadog.setVerbosity(SdkLogVerbosity.INFO)

Logs 기능을 구성하고 활성화하세요:

val logsConfig = LogsConfiguration.Builder().build()
Logs.enable(logsConfig)

로거를 구성하세요:

val logger = Logger.Builder()
    .setNetworkInfoEnabled(true)
    .setPrintLogsToConsole(true)
    .setRemoteSampleRate(100f)
    .setBundleWithRumEnabled(true)
    .setName("<LOGGER_NAME>")
    .build()

다음 함수 중 하나로 사용자 정의 로그 항목을 Datadog로 직접 보내세요:

logger.debug("A debug message.")
logger.info("Some relevant information?")
logger.warn("An important warning...")
logger.error("An error was met!")
logger.critical("What a Terrible Failure!")

잡은 예외는 메시지와 함께 보낼 수 있어요:

try { 
    doSomething() 
} catch (e: IOException) {
     logger.error("Error while doing something", e) 
}

참고: 모든 로깅 메서드에는 Throwable(또는 iOS 소스 세트에서 호출될 때 NSError)을 붙일 수 있어요.

(선택 사항) 로그 메시지와 함께 맵을 제공해 생성되는 로그에 속성을 추가하세요. 맵의 각 항목이 속성으로 추가돼요.

logger.info("onPageStarted", attributes = mapOf("http.url" to url))

배칭 전에 Log 이벤트의 일부 속성을 수정해야 한다면 Logs 기능을 초기화할 때 EventMapper<LogEvent> 구현을 제공해 처리할 수 있어요:

val logsConfig = LogsConfiguration.Builder()
            // ...
            .setEventMapper(logEventMapper)
            .build()

참고: EventMapper<LogEvent> 구현에서 null이나 다른 인스턴스를 반환하면 이벤트는 삭제돼요.

고급 로깅

로거 초기화

Datadog로 로그를 보내도록 로거를 초기화할 때 Logger.Builder의 다음 메서드를 사용할 수 있어요:

메서드 설명
setNetworkInfoEnabled(true) 모든 로그에 network.client.connectivity 속성을 추가해요.Android: 기본으로 기록되는 데이터는:\n - connectivity\n - Wifi, 3G, 4G 등\n - carrier_name - Android API 레벨 28+에서만 사용 가능\n - AT&T - US\n. iOS: 기본으로 기록되는 데이터는:\n - reachability\n - yes, no, maybe\n - available_interfaces\n - wifi, cellular 등\n - sim_carrier.name\n - 예: AT&T - US\n - sim_carrier.technology\n - 3G, LTE 등\n - sim_carrier.iso_country\n - 예: US
setService(<SERVICE_NAME>) Datadog로 보내는 모든 로그에 붙는 service 표준 속성 값으로 <SERVICE_NAME>을 설정해요.
setPrintLogsToConsole(true) true로 설정하면 Logcat을 로거로 사용(Android)하거나 Xcode의 디버거 콘솔에 로그를 출력(iOS)해요.
setBundleWithTraceEnabled(true) true(기본값)로 설정하면 로그를 애플리케이션의 활성 트레이스와 묶어요. 이 파라미터를 사용하면 Datadog 대시보드로 특정 트레이스 동안 보낸 모든 로그를 표시할 수 있어요.
setBundleWithRumEnabled(true) true(기본값)로 설정하면 로그를 애플리케이션의 현재 RUM 컨텍스트와 묶어요. 이 파라미터를 사용하면 Datadog RUM Explorer로 특정 View가 활성 상태인 동안 보낸 모든 로그를 표시할 수 있어요.
setName(<LOGGER_NAME>) Datadog로 보내는 모든 로그에 붙는 logger.name 속성 값으로 <LOGGER_NAME>을 설정해요.
setRemoteSampleRate(<SAMPLE_RATE>) 이 로거의 샘플링 비율을 설정해요. 로거 인스턴스가 생성하는 모든 로그는 제공된 샘플링 비율(기본값 1.0 = 모든 로그)에 따라 무작위로 샘플링돼요. 참고: 콘솔 로그는 샘플링되지 않아요.
setRemoteLogThreshold(LogLevel) Datadog 서버로 보낼 로그의 최소 임계값(우선순위)을 설정해요. 로그 우선순위가 그보다 낮으면 보내지지 않아요(기본값은 모두 허용). 참고: 콘솔 로그는 샘플링되지 않아요.
build() 모든 옵션을 설정한 새 로거 인스턴스를 빌드해요.

글로벌 구성

다음 함수를 사용해 지정된 로거가 보내는 모든 로그에 태그·속성을 추가하거나 제거하세요.

글로벌 태그
태그 추가

addTag("<TAG_KEY>", "<TAG_VALUE>") 함수를 사용해 특정 로거가 보내는 모든 로그에 태그를 추가하세요:

// This adds a tag "build_type:debug" or "build_type:release" accordingly
logger.addTag("build_type", BuildConfig.BUILD_TYPE)

// This adds a tag "device:android"
logger.addTag("device", "android")

<TAG_VALUE>는 String이어야 해요.

태그 제거

removeTagsWithKey("<TAG_KEY>") 함수를 사용해 특정 로거가 보내는 모든 로그에서 태그를 제거하세요:

// This removes any tag starting with "build_type"
logger.removeTagsWithKey("build_type")

자세한 내용은 태그 시작하기를 참고하세요.

글로벌 속성
속성 추가

기본적으로 로거가 보내는 모든 로그에 다음 속성이 추가돼요:

  • http.useragent와 여기서 추출한 device, OS 속성
  • network.client.ip와 여기서 추출한 지리적 속성(country, city)

addAttribute("<ATTRIBUTE_KEY>", "<ATTRIBUTE_VALUE>") 함수를 사용해 특정 로거가 보내는 모든 로그에 사용자 정의 속성을 추가하세요:

// This adds an attribute "version_code" with an integer value
logger.addAttribute("version_code", BuildConfig.VERSION_CODE)

// This adds an attribute "version_name" with a String value
logger.addAttribute("version_name", BuildConfig.VERSION_NAME)

<ATTRIBUTE_VALUE>는 어떤 프리미티브, String, Date가 될 수 있어요.

속성 제거

removeAttribute("<ATTRIBUTE_KEY>", "<ATTRIBUTE_VALUE>") 함수를 사용해 특정 로거가 보내는 모든 로그에서 사용자 정의 속성을 제거하세요:

// This removes the attribute "version_code" from all further log send.
logger.removeAttribute("version_code")

// This removes the attribute "version_name" from all further log send.
logger.removeAttribute("version_name")

배치 수집

모든 로그는 먼저 로컬 디바이스에 배치로 저장돼요. 각 배치는 수집 규격을 따르며, 네트워크가 사용 가능하고 배터리가 충분해 Datadog SDK가 최종 사용자 경험에 영향을 주지 않을 때 보내져요. 애플리케이션이 포그라운드에 있을 때 네트워크를 사용할 수 없거나 데이터 업로드가 실패하면, 배치는 성공적으로 보낼 수 있을 때까지 유지돼요.

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

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

데이터가 Datadog로 업로드되기 전에는 애플리케이션의 캐시 디렉터리에 일반 텍스트로 저장돼요.

더 알아보기 (Learn more)