Ce produit n'est pas pris en charge par le site Datadog que vous avez sélectionné. ().
Présentation
Cette page décrit comment instrumenter votre application iOS ou tvOS avec le SDK Datadog Feature Flags. Les Datadog Feature Flags offrent un moyen unifié de contrôler à distance la disponibilité des fonctionnalités dans votre application, d’expérimenter en toute sécurité et de proposer de nouvelles expériences en toute confiance.
Ce guide explique comment installer et activer le SDK, créer et utiliser un FlagsClient, et configurer des options avancées.
Installation
Déclarez DatadogFlags comme dépendance dans votre projet. La méthode d’installation recommandée est Swift Package Manager (SPM).
Pour installer le SDK Datadog Feature Flags à l’aide de Swift Package Manager d’Apple, ajoutez ce qui suit en tant que dépendance à votre fichier Package.swift :
Dans votre projet, associez les bibliothèques suivantes :
DatadogCoreDatadogFlags
Pour installer le SDK Datadog Feature Flags avec CocoaPods, déclarez les pods suivants dans votre Podfile :
DatadogCoreDatadogFlags
Pour installer le SDK Datadog Feature Flags avec Carthage, ajoutez dd-sdk-ios à votre Cartfile :
github"DataDog/dd-sdk-ios"
Remarque : Datadog ne fournit pas de binaires Carthage préconstruits. Cela signifie que Carthage compile le SDK à partir de la source. Pour compiler et intégrer le SDK, exécutez :
Initialisez Datadog le plus tôt possible dans le cycle de vie de votre application, généralement dans application(_:didFinishLaunchingWithOptions:) (ou avec @UIApplicationDelegateAdaptor pour les applications SwiftUI). Cela garantit que toutes les évaluations de feature flags et la télémétrie sont capturées correctement. Pour créer un jeton client, consultez Jetons client.
Après avoir initialisé Datadog, activez Flags pour l’attacher à l’instance actuelle du SDK Datadog iOS et préparer la création du client ainsi que l’évaluation des flags :
importDatadogFlagsFlags.enable()
Vous pouvez également transmettre un objet de configuration ; consultez Configuration avancée.
Créer et récupérer un client
Créez un client une seule fois, généralement au démarrage de l’application :
FlagsClient.create()// Creates the default client
Récupérez le même client n’importe où dans votre application :
letflagsClient=FlagsClient.shared()// Retrieves the "default" client
Vous pouvez également créer et récupérer plusieurs clients en fournissant le paramètre name :
Si un client avec le nom donné existe déjà, l'instance existante est réutilisée.
Définir le contexte d’évaluation
Définissez à qui ou à quoi s’applique l’évaluation du flag en utilisant un FlagsEvaluationContext. Le contexte d’évaluation inclut des informations sur l’utilisateur ou la session utilisées pour déterminer quelles variantes d’indicateur doivent être renvoyées. Appelez cette méthode avant d’évaluer les flags pour garantir un ciblage approprié.
Datadog Feature Flags nécessite que les attributs du contexte d'évaluation soient des valeurs primitives plates : chaînes de caractères, nombres et booléens. Ne transmettez pas d'objets ou de tableaux imbriqués ; ils ne sont pas pris en charge et peuvent entraîner la perte des données d'exposition.
Cette méthode récupère les attributions de flags depuis le serveur de manière asynchrone. En fournissant un rappel de fin optionnel ou en utilisant la variante async/await, vous pouvez gérer le résultat de l’évaluation du contexte :
do{tryawaitflagsClient.setEvaluationContext(evaluationContext)// Context set successfully}catch{print("Failed to set context: \(error)")}
Évaluer les Feature Flags
Après avoir créé le FlagsClient et défini son contexte d’évaluation, vous pouvez commencer à lire les valeurs des flags dans toute votre application. L’évaluation des flags est locale et instantanée : le SDK utilise des données mises en cache localement, donc aucune requête réseau n’est effectuée lors de l’évaluation des flags. Cela permet d’effectuer les évaluations en toute sécurité sur le thread principal.
Chaque flag est identifié par une clé (une chaîne unique) et peut être évalué avec un getter typé qui renvoie une valeur du type attendu. Si le Feature Flag n’existe pas ou ne peut pas être évalué, le SDK renvoie la valeur par défaut fournie.
Feature Flags booléens
Utilisez getBooleanValue(key:defaultValue:) pour les flags qui représentent des conditions activé/désactivé ou vrai/faux. Exemple :
Pour les flags numériques, utilisez getIntegerValue(key:defaultValue:) ou getDoubleValue(key:defaultValue:). Ils sont appropriés lorsqu’une fonctionnalité dépend d’un paramètre numérique tel qu’une limite, un pourcentage ou un multiplicateur :
Pour les données structurées ou de type JSON, utilisez getObjectValue(key:defaultValue:). Cette méthode renvoie un AnyValue, qui peut représenter des primitives, des tableaux ou des dictionnaires. Les flags d’objet sont utiles pour les scénarios de configuration à distance où plusieurs propriétés doivent être fournies ensemble. Exemple :
Lorsque vous avez besoin de plus que la simple valeur du flag, utilisez les API get<Type>Details. Ces méthodes renvoient à la fois la valeur évaluée et les métadonnées expliquant l’évaluation :
letdetails=flagsClient.getStringDetails(key:"paywall.layout",defaultValue:"control")print(details.value)// Evaluated value (for example: "A", "B", or "control")print(details.variant)// Variant name, if applicableprint(details.reason)// Description of why this value was chosen (for example: "TARGETING_MATCH" or "DEFAULT")print(details.error)// The error that occurred during evaluation, if any
Les détails du flag peuvent vous aider à déboguer le comportement d’évaluation et à comprendre pourquoi un utilisateur a reçu une valeur donnée.
Observer les changements d’état
L'observation de l'état avec FlagsClient.state est disponible dans dd-sdk-ios 3.11.0 et versions ultérieures.
Utilisez flagsClient.state pour vérifier si un FlagsClient est prêt à évaluer les flags et pour réagir lorsque son état change. Les changements d’état se produisent lorsque vous appelez setEvaluationContext et que le SDK récupère les attributions de flags pour ce contexte.
finalclassFeatureFlagStateObserver:FlagsStateListener{funcflagsStateDidChange(_newState:FlagsClientState){switchnewState{case.notReady:// The client has not loaded assignments yet.breakcase.reconciling:// The client is fetching assignments for a context change.breakcase.ready:// Assignments are loaded and available for evaluation.breakcase.stale:// Cached assignments are available, but the latest fetch failed.breakcase.error:// No assignments are available for evaluation.break}}}letobserver=FeatureFlagStateObserver()flagsClient.state.addListener(observer)letcurrentState=flagsClient.state.currentState
Conservez une référence forte à l’écouteur aussi longtemps que vous souhaitez recevoir des mises à jour. L’écouteur reçoit l’état actuel lorsqu’il est enregistré, puis reçoit les changements d’état futurs.
Utilisation avec OpenFeature
Les exemples ci-dessus utilisent directement l’API FlagsClient de Datadog. Si vous préférez l’API standard OpenFeature, Datadog propose un fournisseur OpenFeature pour iOS qui encapsule FlagsClient et l’expose via OpenFeatureAPI.shared. Les mêmes données d’indicateur sont servies via l’une ou l’autre interface ; choisissez l’API qui convient à votre application.
Le pont OpenFeature pour iOS (dd-openfeature-provider-swift) est disponible en tant que package pré-1.0. Jusqu'à ce qu'il atteigne la version 1.0, les mises à jour de version peuvent inclure des changements incompatibles. Utilisez cette section pour effectuer l'intégration via OpenFeature ; utilisez FlagsClient directement pour l'interface API iOS la plus stable.
Installer le fournisseur OpenFeature
Ajoutez dd-openfeature-provider-swift à votre Package.swift :
Liez le produit DatadogOpenFeatureProvider à votre cible d’application. Le pont dépend du SDK OpenFeature Swift 0.3.0.
Initialisez OpenFeature
Initialisez Datadog et activez les flags comme indiqué dans Initialiser le SDK. Créez ensuite un DatadogProvider et enregistrez-le avec OpenFeatureAPI.shared :
setProviderAndWait est async et ne génère pas d’exception. Une fois qu’il a renvoyé une valeur, le fournisseur est prêt et les évaluations de flags utilisent les valeurs mises en cache.
Définissez le contexte d’évaluation
Le contexte d’évaluation identifie à qui ou à quoi s’applique l’évaluation du flag. Transmettez-le lors de l’enregistrement du fournisseur, comme indiqué ci-dessus, ou mettez-le à jour ultérieurement :
Les évaluations sont synchrones et peuvent être effectuées en toute sécurité sur le thread principal — elles lisent à partir du cache local du SDK et n’effectuent pas de requêtes réseau. Notez que getIntegerValue renvoie Int64 ; effectuez un cast vers Int sur le site d’appel si nécessaire.
Détails de l’évaluation du flag
Utilisez les méthodes get<Type>Details lorsque vous avez besoin de la raison, de la variante ou de toute erreur d’évaluation en plus de la valeur :
letdetails=client.getStringDetails(key:"paywall.layout",defaultValue:"control")print(details.value)// Evaluated valueprint(details.variant)// Variant name, if applicableprint(details.reason)// Reason (for example: "TARGETING_MATCH" or "DEFAULT")print(details.errorCode)// Error code, if evaluation failed
Observer les événements du fournisseur
L'observation des événements du fournisseur pour le fournisseur Datadog OpenFeature est disponible dans dd-openfeature-provider-swift 0.2.0 et versions ultérieures. La version 0.2.0 dépend de dd-sdk-ios 3.13.0 ou version ultérieure.
Utilisez OpenFeatureAPI.shared.observe() pour réagir aux événements du fournisseur OpenFeature. Le fournisseur Datadog OpenFeature émet .ready, .stale et .error en fonction de l’état FlagsClient sous-jacent. Le SDK OpenFeature peut également émettre des événements de cycle de vie tels que .reconciling et .contextChanged lorsque le contexte d’évaluation change.
importCombineimportOpenFeaturefinalclassFeatureFlagEventObserver{privatevarcancellable:AnyCancellable?funcstartObserving(){cancellable=OpenFeatureAPI.shared.observe().sink{eventinguardleteventelse{return}switchevent{case.ready:// The provider is ready to evaluate flags.breakcase.stale:// Cached assignments are available, but they may be out of date.breakcase.error(_,_):// The provider cannot evaluate flags.breakcase.reconciling:// The provider is reconciling after a context change.breakcase.contextChanged:// The context change completed.breakcase.configurationChanged:// The provider configuration changed.break}}}}
Configuration avancée
L’API Flags.enable() accepte une configuration optionnelle avec les options listées ci-dessous.
Lorsque true (par défaut), le SDK enregistre automatiquement un événement d’exposition lorsqu’un flag est évalué. Ces événements contiennent des métadonnées sur le flag accédé, la variante servie et le contexte utilisé. Ils sont envoyés à Datadog afin que vous puissiez analyser ultérieurement l’adoption des fonctionnalités. Si vous avez uniquement besoin d’une évaluation locale sans télémétrie, vous pouvez désactiver cette option.
rumIntegrationEnabled
Lorsque true (par défaut), les évaluations de flag sont suivies dans RUM, ce qui permet de les corréler avec les sessions utilisateur. Cela permet des analyses telles que « Les utilisateurs de la variante B rencontrent-ils plus d’erreurs ? ». Si votre application n’utilise pas RUM, ce flag n’a aucun effet et peut être laissé en toute sécurité à sa valeur par défaut.
gracefulModeEnabled
Contrôle la façon dont le SDK gère une utilisation incorrecte de l’API FlagsClient — par exemple, la création d’un client avant l’appel de Flags.enable(), la création d’un client en double avec le même nom, ou la récupération d’un client qui n’a pas encore été créé.
Le comportement exact du mode Graceful dépend de votre configuration de build :
Builds de release: Le SDK applique toujours le mode Graceful: toute utilisation incorrecte est uniquement consignée en interne si Datadog.verbosityLevel est configuré.
Builds de debug avec gracefulModeEnabled = true (par défaut): Le SDK consigne toujours des avertissements dans la console.
Builds de debug avec gracefulModeEnabled = false: Le SDK génère fatalError en cas d’utilisation incorrecte de l’API, appliquant une approche de fail-fast qui aide à détecter rapidement les erreurs de configuration.
Vous pouvez ajuster gracefulModeEnabled en fonction de votre phase de développement ou de QA.
customFlagsEndpoint
Configure une URL de serveur personnalisée pour récupérer les attributions d’indicateurs :
customExposureEndpoint
Configure une URL de serveur personnalisée pour envoyer les données d’exposition des indicateurs :
customEvaluationEndpoint
Configure une URL de serveur personnalisée pour envoyer la télémétrie d’évaluation des indicateurs :
customFlagsHeaders
Définit des en-têtes HTTP supplémentaires à joindre aux requêtes effectuées vers customFlagsEndpoint : Cela peut être utile pour l’authentification ou le routage lors de l’utilisation de votre propre service d’indicateurs.
Tests
Les exemples ci-dessus utilisent directement l’API FlagsClient de Datadog. Si vous utilisez le pont OpenFeature ou si vous écrivez des tests autour de l’API OpenFeature, remplacez-le par un fournisseur en mémoire pour les valeurs d’indicateurs contrôlées par le code.
Vous pouvez effectuer des tests sur un environnement de test Datadog dédié avec le DatadogProvider réel, ou le remplacer par un FeatureProvider en mémoire pour contrôler directement les valeurs des indicateurs dans le code de test. Cette section présente l’approche en mémoire, qui permet de garder les tests hermétiques et hors ligne. Le SDK OpenFeature pour Swift ne fournit pas de InMemoryProvider, les tests utilisent donc un petit FeatureProvider personnalisé à la place.
importCombineimportOpenFeatureimportXCTest@testableimportMyApp// Minimal in-memory provider for tests. Copy into your test target.finalclassInMemoryTestProvider:FeatureProvider{varhooks:[anyHook]=[]varmetadata:ProviderMetadata=Metadata(name:"in-memory-test")privateletsubject=CurrentValueSubject<ProviderEvent?,Never>(.ready)privateletbools:[String:Bool]privateletstrings:[String:String]init(bools:[String:Bool]=[:],strings:[String:String]=[:]){self.bools=boolsself.strings=strings}funcobserve()->AnyPublisher<ProviderEvent?,Never>{subject.eraseToAnyPublisher()}funcinitialize(initialContext:EvaluationContext?)asyncthrows{}funconContextSet(oldContext:EvaluationContext?,newContext:EvaluationContext)asyncthrows{}funcgetBooleanEvaluation(key:String,defaultValue:Bool,context:EvaluationContext?)throws->ProviderEvaluation<Bool>{ProviderEvaluation(value:bools[key]??defaultValue,variant:bools[key]==nil?"default":"static",reason:Reason.staticReason.rawValue)}funcgetStringEvaluation(key:String,defaultValue:String,context:EvaluationContext?)throws->ProviderEvaluation<String>{ProviderEvaluation(value:strings[key]??defaultValue,variant:strings[key]==nil?"default":"static",reason:Reason.staticReason.rawValue)}funcgetIntegerEvaluation(key:String,defaultValue:Int64,context:EvaluationContext?)throws->ProviderEvaluation<Int64>{ProviderEvaluation(value:defaultValue,variant:"default",reason:Reason.staticReason.rawValue)}funcgetDoubleEvaluation(key:String,defaultValue:Double,context:EvaluationContext?)throws->ProviderEvaluation<Double>{ProviderEvaluation(value:defaultValue,variant:"default",reason:Reason.staticReason.rawValue)}funcgetObjectEvaluation(key:String,defaultValue:Value,context:EvaluationContext?)throws->ProviderEvaluation<Value>{ProviderEvaluation(value:defaultValue,variant:"default",reason:Reason.staticReason.rawValue)}privatestructMetadata:ProviderMetadata{varname:String?}}finalclassCheckoutFlagTests:XCTestCase{overridefunctearDown(){OpenFeatureAPI.shared.clearProvider()}functestNewCheckoutEnabled()asyncthrows{letprovider=InMemoryTestProvider(bools:["new-checkout-flow":true])awaitOpenFeatureAPI.shared.setProviderAndWait(provider:provider)letclient=OpenFeatureAPI.shared.getClient()XCTAssertTrue(client.getBooleanValue(key:"new-checkout-flow",defaultValue:false))}}
OpenFeatureAPI.shared est un singleton global, donc appelez clearProvider() dans tearDown pour empêcher que les indicateurs d’un test ne se retrouvent dans un autre. setProviderAndWait(provider:) est async et ne génère pas d’exception, donc aucun try n’est requis.
Pour aller plus loin
Documentation, liens et articles supplémentaires utiles: