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

iOS 애플리케이션 트레이싱 (Tracing iOS Applications)

원문 보기 위키 갱신

iOS 애플리케이션에서 Datadog으로 트레이스를 보내는 방법이에요. Datadog의 dd-sdk-ios 클라이언트 SDK를 사용해 커스텀 스팬을 만들고, 로그를 보내며, 네트워크 요청을 추적할 수 있어요.

출처: 문서

본문

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

  • 앱의 다양한 작업에 대한 커스텀 스팬 만들기.
  • 각 스팬에 대해 개별적으로 로그 보내기.
  • 각 스팬에 기본·커스텀 속성 사용하기.
  • 자동 일괄 전송(bulk posts)으로 네트워크 사용을 최적화하기.

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

설정 (Setup)

  1. 패키지 관리자에 따라 라이브러리를 의존성으로 선언하세요. Swift Package Manager(SPM)를 권장해요.

    • Swift Package Manager (SPM): Apple의 Swift Package Manager로 통합하려면 Package.swift에 다음을 의존성으로 추가하세요.
    .package(url: "https://github.com/Datadog/dd-sdk-ios.git", .upToNextMajor(from: "2.0.0"))
    

    프로젝트에서 다음 라이브러리를 링크하세요.

    DatadogCore
    DatadogTrace
    
    • CocoaPods: CocoaPods로 dd-sdk-ios를 설치할 수 있어요.
    pod 'DatadogCore'
    pod 'DatadogTrace'
    
    • Carthage: Carthage로 dd-sdk-ios를 설치할 수 있어요.
    github "DataDog/dd-sdk-ios"
    

Xcode에서 다음 프레임워크를 링크하세요.

DatadogInternal.xcframework
DatadogCore.xcframework
DatadogTrace.xcframework
  1. 애플리케이션 컨텍스트와 Datadog 클라이언트 토큰으로 라이브러리를 초기화하세요. 보안상의 이유로 클라이언트 토큰을 사용해야 해요. Datadog API 키는 iOS 애플리케이션 IPA 바이트 코드에 클라이언트 측으로 노출되므로 dd-sdk-ios 라이브러리 구성에 사용할 수 없어요.

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

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

  • Swift:
import DatadogCore

Datadog.initialize(
    with: Datadog.Configuration(
        clientToken: "<client token>",
        env: "<environment>",
        service: "<service name>"
    ),
    trackingConsent: trackingConsent
)
  • Objective-C:
DDConfiguration *configuration = [[DDConfiguration alloc] initWithClientToken:@"<client token>" env:@"<environment>"];
configuration.service = @"<service name>";

[DDDatadog initializeWithConfiguration:configuration
                        trackingConsent:trackingConsent];

app.datadoghq.eu 사이트 사용자의 경우 site: .eu1`` (해당 Swift/Objective-C)을 Datadog.Configuration에 지정하세요.

Datadog.initialize(
    with: Datadog.Configuration(
        clientToken: "<client token>",
        env: "<environment>",
        site: .eu1,
        service: "<service name>"
    ),
    trackingConsent: trackingConsent
)

다른 사이트 사용자도 초기화 시 site: 매개변수에 해당 사이트를 지정하면 됩니다. 지원되는 사이트 값은 다음과 같아요.

  • us3.datadoghq.com → .us3
  • us5.datadoghq.com → .us5
  • app.ddog-gov.com → .us1_fed
  • us2.ddog-gov.com → .us2_fed
  • ap1.datadoghq.com → .ap1
  • ap2.datadoghq.com → .ap2
  • uk1.datadoghq.com → .uk1

Objective-C에서는 [DDSite eu1], [DDSite us3] 등 해당 메서드로 사이트를 설정하세요.

GDPR 규정을 준수하기 위해 SDK는 초기화 시 trackingConsent 값을 요구해요. trackingConsent는 다음 값 중 하나일 수 있어요.

  • .pending: SDK가 데이터 수집·배치를 시작하지만 Datadog으로 보내지는 않아요. 배치된 데이터를 어떻게 처리할지 결정하려면 새 추적 동의 값을 기다립니다.
  • .granted: SDK가 데이터 수집을 시작하고 Datadog으로 보내요.
  • .notGranted: SDK가 어떤 데이터도 수집하지 않아요. 로그·트레이스·RUM 이벤트가 Datadog으로 보내지지 않아요.

SDK 초기화 후 추적 동의 값을 바꾸려면 Datadog.set(trackingConsent:) API 호출을 사용하세요.

SDK는 새 값에 따라 동작을 바꿔요. 예를 들어 현재 추적 동의가 .pending이라면:

  • .granted로 바꾸면 SDK가 현재·향후 모든 데이터를 Datadog으로 보내요.
  • .notGranted로 바꾸면 SDK가 현재 모든 데이터를 지우고 향후 데이터 수집을 중지해요.

데이터가 Datadog으로 업로드되기 전에 애플리케이션 샌드박스의 캐시 디렉터리(Library/Caches)에 평문으로 저장돼요. 캐시 디렉터리는 기기에 설치된 다른 어떤 앱도 읽을 수 없어요.

애플리케이션을 작성할 때 개발 로그를 활성화해 SDK의 모든 내부 메시지를 제공된 레벨 이상의 우선순위로 콘솔에 기록할 수 있어요.

  • Swift: Datadog.verbosityLevel = .debug
  • Objective-C: DDDatadog.verbosityLevel = DDSDKVerbosityLevelDebug;
  1. Datadog SDK는 OpenTracing과 OpenTelemetry 표준을 모두 구현해요. 공유 OpenTracing Tracer를 Tracer.shared()로 구성·활성화하세요.
  • Swift:
import DatadogTrace

Trace.enable(
    with: Trace.Configuration(
        networkInfoEnabled: true
    )
)

let tracer = Tracer.shared()
  • Objective-C:
DDTraceConfiguration *configuration = [[DDTraceConfiguration alloc] init];
configuration.networkInfoEnabled = YES;

[DDTrace enableWith:configuration];

DDTracer *tracer = [Tracer shared];
  1. 다음 방법으로 코드를 계측하세요.
  • Swift:
let span = tracer.startSpan(operationName: "<span_name>")
// 측정하려는 것을 수행하세요 ...
// ... 그런 다음 작업이 끝나면:
span.finish()
  • Objective-C:
id<OTSpan> span = [tracer startSpan:@"<span_name>"];
// 측정하려는 것을 수행하세요 ...
// ... 그런 다음 작업이 끝나면:
[span finish];
  1. (선택) 스팬 사이의 자식-부모 관계를 설정하세요.
  • Swift:
let responseDecodingSpan = tracer.startSpan(
    operationName: "response decoding",
    childOf: networkRequestSpan.context // make it a child of `networkRequestSpan`
)
// ... HTTP 응답 데이터 디코딩 ...
responseDecodingSpan.finish()
  • Objective-C:
id<OTSpan> responseDecodingSpan = [tracer startSpan:@"response decoding"
                                                            childOf:networkRequestSpan.context];
// ... HTTP 응답 데이터 디코딩 ...
[responseDecodingSpan finish];
  1. (선택) 스팬에 추가 태그를 제공하세요.
  • Swift: span.setTag(key: "http.url", value: url)
  • Objective-C: [span setTag:@"http.url" value:url];
  1. (선택) 표준 Open Tracing 로그 필드를 사용해 오류 정보를 기록해 스팬에 오류를 첨부하세요.
  • Swift:
span.log(
    fields: [
        OTLogFields.event: "error",
        OTLogFields.errorKind: "I/O Exception",
        OTLogFields.message: "File not found",
        OTLogFields.stack: "FileReader.swift:42",
    ]
)
  • Objective-C:
[span log:@{
    @"event": @"error",
    @"error.kind": @"I/O Exception",
    @"message": @"File not found",
    @"stack": @"FileReader.swift:42",
}];
  1. (선택) 트레이스를 유지하거나 드롭하도록 강제해 샘플링 결정을 재정의하세요. 예를 들어 중요한 트랜잭션의 트레이스는 항상 유지하고, 불필요한 반복 트레이스는 항상 드롭할 수 있어요.

트레이스를 수동으로 유지하려면:

  • Swift: span.keepTrace()
  • Objective-C: [span keepTrace];

트레이스를 수동으로 드롭하려면:

  • Swift: span.dropTrace()
  • Objective-C: [span dropTrace];

항상 자식 스팬이 생성되거나 컨텍스트 전파가 일어나기 전에 루트 스팬에서 keepTrace() 또는 dropTrace()를 호출하세요. 그렇지 않으면 시스템이 일관성을 보장할 수 없어 부분적인 트레이스만 수집될 수 있어요.

  1. (선택) 프론트엔드에서 백엔드로처럼 환경 간에 트레이스를 분산하려면 수동으로 하거나 자동 계측을 사용할 수 있어요. 두 경우 모두 모든 요청 또는 샘플링된 요청에만 트레이스 컨텍스트를 주입하도록 선택할 수 있어요. 기본적으로 100% 샘플링이 적용돼요.

* 트레이스를 수동으로 전파하려면 URLRequest 헤더에 스팬 컨텍스트를 주입하세요.

  • Swift:
var request: URLRequest = ... // your API에 대한 요청

let span = tracer.startSpan(operationName: "network request")
let traceContextInjection = ... // `.all` 또는 `.sampled`

let headersWriter = HTTPHeadersWriter(traceContextInjection: traceContextInjection)
tracer.inject(spanContext: span.context, writer: headersWriter)

for (headerField, value) in headersWriter.traceHeaderFields {
    request.addValue(value, forHTTPHeaderField: headerField)
}
  • Objective-C:
id<OTSpan> span = [tracer startSpan:@"network request"];
DDTraceContextInjection traceContextInjection = ...; // `DDTraceContextInjectionAll` 또는 `DDTraceContextInjectionSampled`
DDHTTPHeadersWriter *headersWriter = [[DDHTTPHeadersWriter alloc] initWithTraceContextInjection:traceContextInjection];

NSError *error = nil;
[tracer inject:span.context
        format:OT.formatTextMap
    carrier:headersWriter
        error:&error];

for (NSString *key in headersWriter.traceHeaderFields) {
    NSString *value = headersWriter.traceHeaderFields[key];
    [request addValue:value forHTTPHeaderField:key];
}

이렇게 하면 요청에 추가 트레이싱 헤더가 설정되므로 백엔드가 요청을 추출해 분산 트레이싱을 계속할 수 있어요. 요청이 끝나면 완료 핸들러 안에서 span.finish()를 호출하세요. 백엔드도 Datadog APM & Distributed Tracing으로 계측되어 있다면 전체 프론트-백 트레이스가 Datadog 대시보드에 나타나요.

* 주어진 호스트에 대한 모든 네트워크 요청을 자동으로 트레이싱하려면 Trace 구성에서 urlSessionTracking과 함께 firstPartyHosts 배열을 지정하세요. 각 항목은 일반 호스트 이름(예: "example.com")이나 단일 *가 있는 와일드카드 패턴(예: "*.example.com")을 허용해요.

  • Swift:
import DatadogTrace

Trace.enable(
    with: Trace.Configuration(
        urlSessionTracking: Trace.Configuration.URLSessionTracking(
            firstPartyHostsTracing: .trace(hosts: ["example.com", "api.yourdomain.com", "*.api.yourdomain.com"])
        )
    )
)
  • Objective-C:
@import DatadogObjc;

DDTraceFirstPartyHostsTracing *firstPartyHosts = [DDTraceFirstPartyHostsTracing alloc] initWithHosts:@[@"example.com", @"api.yourdomain.com"]
                                                                                            sampleRate: 20];

DDTraceURLSessionTracking *urlSessionTracking = [DDTraceURLSessionTracking alloc] initWithFirstPartyHostsTracing:firstPartyHosts];
DDTraceConfiguration *configuration = [[DDTraceConfiguration] alloc] init];
[configuration setURLSessionTracking:urlSessionTracking];

[DDTrace enableWith:configuration];

이렇게 하면 example.com과 api.yourdomain.com 호스트에 대한 모든 요청(예: https://api.yourdomain.com/v2/users 또는 https://subdomain.example.com/image.png)이 자동으로 트레이싱돼요.

(선택) 더 정확한 트레이스 타이밍을 위해 델리게이트 타입에 URLSessionInstrumentation을 활성화하세요.

  • Swift:
URLSessionInstrumentation.enableDurationBreakdown(
    with: .init(
        delegateClass: <YourSessionDelegate>.self
    )
)

let session = URLSession(
    configuration: .default,
    delegate: <YourSessionDelegate>(),
    delegateQueue: nil
)
  • Objective-C:
DDURLSessionInstrumentationConfiguration *config = [[DDURLSessionInstrumentationConfiguration alloc] initWithDelegateClass:[<YourSessionDelegate> class]];
[DDURLSessionInstrumentation enableDurationBreakdownWithConfiguration:config];

NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]
                                                        delegate:[[<YourSessionDelegate> alloc] init]
                                                    delegateQueue:nil];

참고:

  • 트레이싱 자동 계측은 URLSession 스위즐링을 사용하며 옵트인 방식이에요. urlSessionTracking과 firstPartyHosts 구성을 지정하지 않으면 스위즐링이 적용되지 않아요.
  • URLSessionInstrumentation 없이도 트레이싱은 자동으로 동작하지만, 활성화하면 트레이스 타이밍이 더 정확해져요.

배치 수집 (Batch collection)

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

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

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

초기화 (Initialization)

Trace.Configuration에서 Tracer를 만들 때 사용할 수 있는 속성은 다음과 같아요.

메서드 설명
bundleWithRumEnabled true로 설정하면 스팬이 현재 RUM View 정보로 강화돼요. 이렇게 하면 특정 View 수명 동안 생성된 모든 스팬을 RUM Explorer에서 볼 수 있어요.
customEndpoint 커스텀 서버로 트레이스를 보낼 URL을 설정해요.
eventMapper 스팬 이벤트를 보내기 전에 수정할 매퍼를 설정해요.
networkInfoEnabled true로 설정하면 트레이스를 네트워크 연결 정보(도달성 상태, 연결 유형, 이동통신사 이름 등)로 강화해요.
sampleRate 수집할 트레이스의 비율을 정의하는 0-100 값을 설정해요.
service service 값을 설정해요.
tags Tracer가 만든 스팬에 추가할 <KEY>:<VALUE> 태그 쌍을 설정해요.
urlSessionTracking 네트워크 요청의 자동 트레이싱을 구성하도록 설정해요. 퍼스트파티 호스트와 샘플 비율, 트레이스 컨텍스트 주입 전략을 정의해요. RUM 같은 다른 기능이 이미 구성했다면 설정하지 마세요.

더 알아보기 (Learn more)

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