Este producto no es compatible con el sitio Datadog seleccionado. ().
Descripción general
Esta página describe cómo instrumentar su aplicación Android o Android TV con el SDK de Feature Flags de Datadog. Las Feature Flags de Datadog proporcionan una forma unificada de controlar de forma remota la disponibilidad de funciones en su aplicación, experimentar de forma segura y ofrecer nuevas experiencias con confianza.
El SDK de Feature Flags de Datadog para Android está construido sobre OpenFeature, un estándar abierto para la gestión de Feature Flags. Esta guía explica cómo instalar el SDK, configurar el proveedor de Datadog y evaluar Feature Flags en su aplicación.
Para la mayoría de las aplicaciones, la API de OpenFeature es el enfoque recomendado. Si necesita múltiples contextos de evaluación independientes en la misma aplicación, consulte Integración directa de FlagsClient.
Primeros pasos
Aquí tiene un ejemplo mínimo para que los Feature Flags funcionen en su aplicación Android:
// 1. Add dependencies (see Installation section)
// 2. Initialize the Datadog Android SDK (in Application.onCreate)
valconfiguration=Configuration.Builder(clientToken="<CLIENT_TOKEN>",env="<ENV_NAME>",variant="<APP_VARIANT_NAME>").useSite(DatadogSite.).build()Datadog.initialize(this,configuration,TrackingConsent.GRANTED)// 3. Enable Feature Flags with a bounded initialization timeout
Flags.enable(FlagsConfiguration.Builder().initializationTimeout(2_000L).build())// 4. Create and set up the OpenFeature provider
valprovider=FlagsClient.Builder().build().asOpenFeatureProvider()OpenFeatureAPI.setProviderAndWait(provider)// 5. Set evaluation context (who is the user)
OpenFeatureAPI.setEvaluationContext(ImmutableContext(targetingKey="user-123",attributes=mapOf("tier"toValue.String("premium"))))// 6. Evaluate flags anywhere in your app
valclient=OpenFeatureAPI.getClient()valisEnabled=client.getBooleanValue("my-feature",false)
El resto de esta guía explica cada paso en detalle.
Instalación
Agregue el SDK de Feature Flags de Datadog y el proveedor de OpenFeature como dependencias de Gradle en el archivo build.gradle de su módulo de aplicación:
build.gradle
dependencies{implementation"com.datadoghq:dd-sdk-android-flags:<latest-version>"implementation"com.datadoghq:dd-sdk-android-flags-openfeature:<latest-version>"// Recommended: RUM integration drives analysis and enriches RUM session data
implementation"com.datadoghq:dd-sdk-android-rum:<latest-version>"}
Inicializar el SDK
Inicialice Datadog lo antes posible en el ciclo de vida de su aplicación, normalmente en el método onCreate() de su clase Application. Esto ayuda a garantizar que todas las evaluaciones de Feature Flags y la telemetría se capturen correctamente. Para crear un token de cliente, consulte Client tokens.
Después de inicializar Datadog, habilite Flags para adjuntarlo a la instancia actual del SDK de Datadog para Android y prepararse para la creación del proveedor y la evaluación de Feature Flags:
Cree un FlagsClient y conviértalo en un proveedor de OpenFeature utilizando la extensión asOpenFeatureProvider(). Haga esto una vez durante el inicio de la aplicación:
importcom.datadog.android.flags.FlagsClientimportcom.datadog.android.flags.openfeature.asOpenFeatureProviderimportdev.openfeature.kotlin.sdk.OpenFeatureAPI// Create and configure the provider
valprovider=FlagsClient.Builder().build().asOpenFeatureProvider()// Set it as the OpenFeature provider
OpenFeatureAPI.setProviderAndWait(provider)
El proveedor de OpenFeature envuelve un Datadog FlagsClient internamente. Este es un detalle de implementación: una vez configurado, usted interactúa exclusivamente a través de la API estándar de OpenFeature.
El SDK de OpenFeature para Kotlin utiliza un único proveedor global y un contexto de evaluación. Si necesita múltiples contextos de evaluación independientes en la misma aplicación (por ejemplo, para diferentes usuarios en una aplicación multiusuario), consulte Integración directa de FlagsClient.
Establezca el contexto de evaluación
Defina a quién o a qué se aplica la evaluación de Feature Flags mediante un ImmutableContext. El contexto de evaluación incluye información del usuario o de la sesión utilizada para determinar qué variaciones de los marcadores deben devolverse. Establezca esto antes de evaluar los Feature Flags para ayudar a garantizar una segmentación adecuada.
Datadog Feature Flags requiere que los atributos del contexto de evaluación sean valores primitivos planos: cadenas, números y booleanos. No pase objetos o arreglos anidados; no son compatibles y pueden causar que los datos de exposición se descarten.
Los atributos de OpenFeature deben usar planos Value primitivos como Value.String(), Value.Integer(), Value.Double(), o Value.Boolean(). La clave de segmentación debe ser consistente para el mismo usuario para ayudar a garantizar una evaluación de Feature Flags consistente entre sesiones. Para usuarios anónimos, utilice un UUID persistente almacenado, por ejemplo, en SharedPreferences.
Evalúe marcadores
Después de configurar su proveedor y contexto de evaluación, puede leer los valores de los Feature Flags en toda su aplicación. La evaluación de marcadores es local e instantánea: el SDK utiliza datos almacenados en caché localmente, por lo que no se producen solicitudes de red al evaluar marcadores. Esto hace que las evaluaciones sean seguras para realizarse en el hilo principal.
Cada Feature Flag se identifica mediante una clave (una cadena única) y se puede evaluar con un método tipado que devuelve un valor del tipo esperado. Si el marcador no existe o no se puede evaluar, el SDK devuelve el valor predeterminado proporcionado.
Los Feature Flags estructurados son útiles para escenarios de configuración remota donde se deben proporcionar múltiples propiedades juntas como datos tipo JSON:
Cuando necesite más que el valor de un Feature Flag, puede obtener metadatos de evaluación detallados, incluyendo el valor evaluado, el nombre de la variante, el motivo y cualquier código de error:
valdetails=client.getStringDetails(key="paywall.layout",defaultValue="control")print(details.value)// Evaluated value (for example: "A", "B", or "control")
print(details.variant)// Variant name, if applicable
print(details.reason)// Reason for this value (for example: "TARGETING_MATCH" or "DEFAULT")
print(details.errorCode)// Error code, if any
Existen métodos de detalle similares para otros tipos: getBooleanDetails(), getIntegerDetails(), getDoubleDetails() y getObjectDetails().
Los detalles del marcador le ayudan a depurar el comportamiento de evaluación y a entender por qué un usuario recibió un valor determinado.
Observe eventos del proveedor
La observación de eventos del proveedor está disponible en dd-sdk-android-flags-openfeature 3.6.0 y versiones posteriores. Utilice la misma versión para dd-sdk-android-flags.
Utilice OpenFeatureAPI.observe() para reaccionar a los cambios de estado del proveedor. El proveedor OpenFeature de Datadog emite ProviderReady, ProviderStale y ProviderError según el estado del FlagsClient subyacente.
importdev.openfeature.kotlin.sdk.OpenFeatureAPIimportdev.openfeature.kotlin.sdk.events.OpenFeatureProviderEventsimportkotlinx.coroutines.flow.catchimportkotlinx.coroutines.launchvalstateJob=lifecycleScope.launch{OpenFeatureAPI.observe<OpenFeatureProviderEvents>().catch{// Handle Flow collection errors.
}.collect{event->when(event){isOpenFeatureProviderEvents.ProviderReady->{// The provider is ready to evaluate flags.
}isOpenFeatureProviderEvents.ProviderStale->{// Cached assignments are available, but they may be out of date.
}isOpenFeatureProviderEvents.ProviderError->{// The provider cannot evaluate flags.
}isOpenFeatureProviderEvents.ProviderConfigurationChanged->{// The provider configuration changed.
}else->{// Handle other OpenFeature provider events as needed.
}}}}
Cancele el trabajo de recolección cuando el componente de observación se detenga. Por ejemplo, recolecte desde lifecycleScope en un Activity o Fragment de Android, o desde viewModelScope en un ViewModel.
Configuración avanzada
Configuración global
La API Flags.enable() acepta una configuración opcional con las opciones enumeradas a continuación. Estos ajustes se aplican globalmente a todos los proveedores:
valconfig=FlagsConfiguration.Builder().initializationTimeout(2_000L)// configure additional options here
.build()Flags.enable(config)
initializationTimeout(timeoutMs)
Tiempo máximo, en milisegundos, para esperar a que el primer contexto de evaluación esté listo. El tiempo de espera cubre la carga de datos en caché, la obtención de asignaciones, la lectura y decodificación de la respuesta, el almacenamiento de asignaciones y la publicación del estado de listo. No cambia el tiempo de espera del cliente HTTP. La operación de asignación continúa después del tiempo de espera y puede mover al cliente a Ready cuando se completa.
El tiempo de espera se aplica solo a la primera llamada setEvaluationContext. Esa llamada consume el tiempo de espera incluso si la operación falla o nunca comienza. Las llamadas posteriores no tienen temporizador de inicialización. El valor predeterminado es 5_000 milisegundos. Establézcalo en cero o en un valor negativo para desactivar el tiempo de espera. Cuando el tiempo de espera expira, el cliente se vuelve Stale si hay asignaciones almacenadas en caché disponibles. De lo contrario, se vuelve Error.
initializationTimeout está disponible en dd-sdk-android-flags 3.14.0 y versiones posteriores.
trackExposures()
Cuando true (predeterminado), el SDK registra automáticamente un evento de exposición cuando se evalúa un marcador. Estos eventos contienen metadatos sobre qué marcador se accedió, qué variante se entregó y bajo qué contexto. Se envían a Datadog para que el usuario pueda analizar posteriormente la adopción de funciones. Si solo necesita una evaluación local sin telemetría, puede desactivarla con : trackExposures(false).
rumIntegrationEnabled()
Cuando true (predeterminado), las evaluaciones de marcadores se rastrean en RUM, lo que permite correlacionarlos con las sesiones de usuario. Esto permite análisis como “¿Los usuarios en la variante B experimentan más errores?”. Si su aplicación no utiliza RUM, este marcador no tiene efecto y puede dejarse de forma segura en su valor predeterminado. Use rumIntegrationEnabled(false) para desactivar la integración de RUM.
gracefulModeEnabled()
Controla cómo el SDK maneja el uso incorrecto de la API, por ejemplo, crear un cliente antes de llamar a Flags.enable(), crear un cliente duplicado con el mismo nombre o recuperar un cliente que aún no se ha creado.
El comportamiento exacto del Graceful Mode depende de su configuración de compilación:
Compilaciones de lanzamiento: El SDK siempre aplica Graceful Mode: cualquier uso indebido solo se registra internamente si Datadog.setVerbosity() está configurado.
Compilaciones de depuración con gracefulModeEnabled = true (predeterminado): El SDK siempre registra advertencias en la consola.
Compilaciones de depuración con gracefulModeEnabled = false: El SDK genera IllegalStateException por el uso incorrecto de la API, lo que aplica un enfoque de falla rápida que ayuda a detectar errores de configuración a tiempo.
Puede ajustar gracefulModeEnabled() según su fase de desarrollo o control de calidad.
Configuración por proveedor
Puede configurar proveedores individuales con endpoints personalizados antes de crearlos:
Para la mayoría de las aplicaciones, la API de OpenFeature descrita anteriormente es el enfoque recomendado. Sin embargo, puede usar el FlagsClient de Datadog directamente si tiene requisitos específicos que la abstracción de OpenFeature no admite.
Utilice FlagsClient directamente solo si usted:
Requiere múltiples contextos de evaluación independientes en la misma aplicación (por ejemplo, diferentes contextos para diferentes usuarios en una aplicación multiusuario)
Desea trabajar con tipos nativos de Kotlin directamente (JSONObject en lugar de Value.Structure)
Necesita control detallado sobre el ciclo de vida del cliente y la configuración por instancia
Instalación (FlagsClient)
Si solo necesita la API directa, puede omitir la dependencia de OpenFeature:
build.gradle
dependencies{implementation"com.datadoghq:dd-sdk-android-flags:<latest-version>"// Recommended: RUM integration drives analysis and enriches RUM session data
implementation"com.datadoghq:dd-sdk-android-rum:<latest-version>"}
Cree y recupere un cliente (FlagsClient)
Cree un cliente una vez, normalmente durante el inicio de la aplicación:
FlagsClient.Builder().build()// Creates the default client
Recupere el mismo cliente en cualquier parte de su aplicación:
valflagsClient=FlagsClient.get()// Retrieves the "default" client
También puede crear y recuperar múltiples clientes proporcionando el parámetro name:
Este método obtiene las asignaciones de los Feature Flags del servidor de forma asíncrona, en segundo plano. La operación no es bloqueante y es segura para subprocesos. Las actualizaciones de los Feature Flags están disponibles para evaluaciones posteriores después de que se complete la operación en segundo plano.
Observar cambios en el estado del cliente directo
Observación directa del estado del cliente con flagsClient.state está disponible en dd-sdk-android-flags 3.4.0 y versiones posteriores.
Utilice flagsClient.state para verificar el estado actual del cliente directo o registrar un oyente para los cambios de estado:
importcom.datadog.android.flags.FlagsStateListenerimportcom.datadog.android.flags.model.FlagsClientStatevallistener=object: FlagsStateListener{overridefunonStateChanged(newState:FlagsClientState){when(newState){FlagsClientState.NotReady->{// The client has not loaded assignments yet.
}FlagsClientState.Reconciling->{// The client is fetching assignments for a context change.
}FlagsClientState.Ready->{// Assignments are loaded and available for evaluation.
}FlagsClientState.Stale->{// Cached assignments are available, but the latest fetch failed.
}isFlagsClientState.Error->{// No assignments are available for evaluation.
}}}}flagsClient.state.addListener(listener)valcurrentState=flagsClient.state.getCurrentState()
El oyente recibe el estado actual cuando se registra, y luego recibe los cambios de estado futuros. Mantenga la devolución de llamada rápida y envíe el trabajo de larga duración a otro subproceso. Llame a flagsClient.state.removeListener(listener) cuando el componente de observación se detenga.
valdetails=flagsClient.resolve(flagKey="paywall.layout",defaultValue="control")print(details.value)// Evaluated value (for example: "A", "B", or "control")
print(details.variant)// Variant name, if applicable
print(details.reason)// Description of why this value was chosen
print(details.errorCode)// The error that occurred during evaluation, if any
Comparación de API
Esta tabla destaca las diferencias clave entre las API de OpenFeature y FlagsClient para ayudarle a elegir la integración que se ajuste a sus requisitos.
Característica
OpenFeature
FlagsClient
Estándar de API
OpenFeature (neutral respecto al proveedor)
Específico de Datadog
Contexto de evaluación
Global/estático
Por instancia de cliente
Feature Flags estructurados
Value.Structure
JSONObject
Seguridad de tipos
Tipos de ValueOpenFeature
Tipos nativos de Kotlin
Dependencia del proveedor
Baja (neutral respecto al proveedor)
Más alta (específica de Datadog)
Gestión de estado
Observación basada en flujo
Registro manual de oyentes
Pruebas
Puede realizar pruebas en un entorno de prueba de Datadog dedicado con el proveedor real de Datadog, o cambiarlo por un FeatureProvider en memoria para controlar directamente los valores de los marcadores en el código de prueba. Esta sección muestra el enfoque en memoria, que mantiene las pruebas herméticas y sin conexión. El SDK de Kotlin de OpenFeature upstream no incluye un InMemoryProvider, por lo que las pruebas utilizan un pequeño FeatureProvider personalizado. El siguiente ejemplo reemplaza el proveedor de OpenFeatureAPI: si su código de producción utiliza el wrapper FlagsClient de Datadog directamente, su prueba debe realizar aserciones a través del mismo cliente OpenFeatureAPI que utiliza el wrapper, no FlagsClient.
Agregue kotlinx-coroutines-test a su configuración de prueba (el initialize del SDK es una función suspend):
importdev.openfeature.kotlin.sdk.*importdev.openfeature.kotlin.sdk.events.OpenFeatureProviderEventsimportkotlinx.coroutines.flow.Flowimportkotlinx.coroutines.flow.MutableSharedFlowimportkotlinx.coroutines.test.runTestimportorg.junit.Beforeimportorg.junit.Testimportkotlin.test.assertTrueclassFakeProvider(privatevalflags:Map<String,Any>):FeatureProvider{overridevalhooks=emptyList<Hook<*>>()overridevalmetadata=object: ProviderMetadata{overridevalname="fake"}privatevalevents=MutableSharedFlow<OpenFeatureProviderEvents>(replay=1)overridesuspendfuninitialize(initialContext:EvaluationContext?){// No-op. The SDK emits ProviderReady after initialize returns.
}overridefunshutdown(){}overridesuspendfunonContextSet(old:EvaluationContext?,new:EvaluationContext){}overridefungetBooleanEvaluation(key:String,defaultValue:Boolean,context:EvaluationContext?)=ProviderEvaluation(value=(flags[key]as?Boolean)?:defaultValue)overridefungetStringEvaluation(key:String,defaultValue:String,context:EvaluationContext?)=ProviderEvaluation(value=(flags[key]as?String)?:defaultValue)overridefungetIntegerEvaluation(key:String,defaultValue:Int,context:EvaluationContext?)=ProviderEvaluation(value=(flags[key]as?Int)?:defaultValue)overridefungetDoubleEvaluation(key:String,defaultValue:Double,context:EvaluationContext?)=ProviderEvaluation(value=(flags[key]as?Double)?:defaultValue)overridefungetObjectEvaluation(key:String,defaultValue:Value,context:EvaluationContext?)=ProviderEvaluation(value=(flags[key]as?Value)?:defaultValue)overridefunobserve():Flow<OpenFeatureProviderEvents>=events}classCheckoutFlagsTest{privatelateinitvarclient:Client@BeforefunsetUp()=runTest{OpenFeatureAPI.setProviderAndWait(FakeProvider(mapOf("new-checkout-flow"totrue)))client=OpenFeatureAPI.getClient()}@TestfunnewCheckoutEnabled(){assertTrue(client.getBooleanValue("new-checkout-flow",false))}}
OpenFeatureAPI es un singleton de todo el proceso, así que reinícielo entre clases de prueba si las pruebas comparten una JVM. Envuelva setProviderAndWait en runTest { ... }: no se puede llamar desde un método @Before simple porque es suspend.
Lecturas adicionales
Documentación, enlaces y artículos útiles adicionales: