Instrumentación personalizada de iOS y tvOS con la API de OpenTelemetry

Unsure when to use OpenTelemetry with Datadog? Start with Custom Instrumentation with the OpenTelemetry API to learn more.

Overview

There are a few reasons to manually instrument your applications with the OpenTelemetry API:

  • You are not using Datadog supported library instrumentation.
  • You want to extend the ddtrace library’s functionality.
  • You need finer control over instrumenting your applications.

The ddtrace library provides several techniques to help you achieve these goals. The following sections demonstrate how to use the OpenTelemetry API for custom instrumentation to use with Datadog.

Requisitos y limitaciones

  • DatadogTrace para iOS y tvOS versión 2.12.0+.

Rastreo de aplicaciones iOS con OpenTelemetry

  1. Declara la biblioteca como una dependencia en función de tu gestor de paquetes:

Puedes utilizar CocoaPods para instalar dd-sdk-ios:

pod 'DatadogCore'
pod 'DatadogTrace'

Para integrar con Swift Package Manager de Apple, añade lo siguiente como una dependencia a tu Package.swift:

.package(url: "https://github.com/Datadog/dd-sdk-ios.git", .upToNextMajor(from: "2.0.0"))

En tu proyecto, vincula las siguientes bibliotecas:

DatadogCore
DatadogTrace

Puedes utilizar Cartago para instalar dd-sdk-ios:

github "DataDog/dd-sdk-ios"

En Xcode, vincula los siguientes marcos:

OpenTelemetryApi.xcframework
DatadogInternal.xcframework
DatadogCore.xcframework
DatadogTrace.xcframework
  1. Inicializa la biblioteca con el contexto de tu aplicación y tu token de cliente de Datadog. Por razones de seguridad, debes utilizar un token de cliente: no puedes utilizar claves de API de Datadog para configurar la biblioteca dd-sdk-ios, ya que estarían expuestas del lado del cliente en el código de bytes IPA de la aplicación iOS.

Para más información sobre cómo configurar un token de cliente, consulta la documentación sobre tokens de cliente.

import DatadogCore

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

import DatadogCore

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

import DatadogCore

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

import DatadogCore

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

import DatadogCore

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

import DatadogCore

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

Para cumplir con la normativa GDPR, el SDK requiere el valor trackingConsent en la inicialización. El valor trackingConsent puede ser uno de los siguientes:

  • .pending: el SDK comienza a recopilar y procesar los datos por lotes, pero no los envía a Datadog. El SDK espera al nuevo valor de consentimiento de rastreo para decidir qué hacer con los datos procesados por lotes.
  • .granted: el SDK comienza a recopilar los datos y los envía a Datadog.
  • .notGranted: el SDK no recopila ningún dato: los logs, trazas (traces) y eventos RUM no se envían a Datadog.

Para cambiar el valor del consentimiento de rastreo una vez inicializado el SDK, utiliza la llamada a la API Datadog.set(trackingConsent:).

El SDK cambia su comportamiento según el nuevo valor. Por ejemplo, si el consentimiento de rastreo actual es .pending:

  • Si se cambia a .granted, el SDK envía todos los datos actuales y futuros a Datadog;
  • Si se cambia a .notGranted, el SDK borra todos los datos actuales y deja de recopilar datos futuros.

Antes de que los datos se carguen en Datadog, se almacenan en texto simple en el directorio de caché (Library/Caches) de tu entorno de pruebas de aplicaciones. El directorio de caché no puede ser leído por ninguna otra aplicación instalada en el dispositivo.

Al redactar tu aplicación, habilita los logs de desarrollo para registrar en consola todos los mensajes internos del SDK con una prioridad igual o superior al nivel proporcionado.

Datadog.verbosityLevel = .debug
  1. El rastreador de Datadog implementa el estándar de OpenTelemetry. Habilita el rastreador de Datadog, registra el proveedor del rastreador y obtén la instancia del rastreador:
import DatadogTrace
import OpenTelemetryApi

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

OpenTelemetry.registerTracerProvider(
    tracerProvider: OTelTracerProvider()
)

let tracer = OpenTelemetry
    .instance
    .tracerProvider
    .get(instrumentationName: "", instrumentationVersion: nil)
  1. Instrumenta tu código con la API de OpenTelemetry:
let span = tracer.spanBuilder(spanName: "<span_name>").startSpan()
// haz algo que deseas medir...
// ... luego, cuando termina la operación:
span.end()
  1. (opcional) Establece la relación principal-secundario entre tus tramos:
let responseDecodingSpan = tracer.spanBuilder(spanName: "response decoding")
    .setParent(networkRequestSpan) // haz que sea tramo secundario de `networkRequestSpan`
    .startSpan()

// ... decodifica los datos de respuesta HTTP ...
responseDecodingSpan.end()
  1. (Opcional) Proporciona atributos adicionales junto a tu tramo:
span.setAttribute(key: "http.url", value: url)
  1. (Opcional) Adjunta un error a un tramo:
span.status = .error(description: "Failed to decode response")
  1. (Opcional) Añade enlaces de tramo a tu tramo:
let linkedSpan = tracer.spanBuilder(spanName: "linked span").startSpan()
linkedSpan.end()

let spanWithLinks = tracer.spanBuilder(spanName: "span with links")
    .addLink(spanContext: linkedSpan.context)
    .startSpan()
spanWithLinks.end()