diff --git a/README.md b/README.md index de249601..38af1637 100644 --- a/README.md +++ b/README.md @@ -12,11 +12,6 @@ Functionalities: - Automatic data collection about which flags have been accessed by the application - Event tracking for instrumenting your application -### Swift 6 support: strict concurrency - -If your app is using some of the features of Swift 6, we recommend setting the **Strict Concurrency Checking** to -**Minimal**. - ## Dependency Setup ### Swift Package Manager @@ -41,23 +36,26 @@ First, ensure you have your GitHub account added as an option (+ > Add Source Co 1. Add as a remote repository * Search for `git@github.com:spotify/confidence-sdk-swift.git` and click "Add Package" -2. Clone the repository locally +2. Clone the repository locally (only recommended if you are making changes to the SDK) * Clone locally using your preferred method * Use the "Add Local..." button to select the local folder -**Note:** Option 2 is only recommended if you are making changes to the SDK. If working with the OpenFeature Provider, you will also need to add -the relevant OpenFeature SDK dependency manually. +### Swift 6 support + +If your app is using some of the features of Swift 6, we recommend setting the **Strict Concurrency Checking** to +**Minimal**. ### Creating the Confidence instance ```swift import Confidence -let confidence = Confidence.Builder(clientSecret: "mysecret").build() +let confidence = Confidence.Builder(clientSecret: "mysecret", loggerLevel: .NONE).build() await confidence.fetchAndActivate() ``` -The client secret for your application can be generated in the Confidence portal. +- The `clientSecret` for your application can be generated in the Confidence portal. +- The `loggerLevel` sets the verbosity level for logging to console. This can be useful while testing your integration with the Confidence SDK. _Note: the Confidence SDK has been intended to work as a single instance in your Application. Creating multiple instances in the same runtime could lead to unexpected behaviours._ @@ -65,7 +63,7 @@ Creating multiple instances in the same runtime could lead to unexpected behavio ### Initialization strategy `confidence.activateAndFetch()` is an async function that fetches the flags from the Confidence backend, -stores the result on disk, and make the same data ready for theApplication to be consumed. +stores the result on disk, and make the same data ready for the Application to be consumed. The alternative option is to call `confidence.activate()`: this loads previously fetched flags data from storage and makes that available for the Application to consume right away. @@ -77,19 +75,19 @@ The context is a key-value map used for sampling and for targeting, when flag ar It is also appended to the tracked events, making it a great way to create dimensions for metrics in Confidence. ```swift -confidence.putContext(context: ["key": ConfidenceValue(string: "value")]) // this will mutate the context of the current Confidence instance +confidence.putContext(context: ["key": ConfidenceValue(string: "value")]) ``` Note that a `ConfidenceValue` is accepted a map values, which has a constructor for all the value types supported by Confidence. ### Resolving feature flags -Once the flags are **activated**, you can access their value using the `getValue` method or the `getEvaluation` method. -Both methods use generics to return a type defined by the default value type. +Once the Confidence instance is **activated**, you can access the flag values using the +`getValue` method or the `getEvaluation` functions. +Both functions use generics to return a type defined by the default value type. The method `getEvaluation` returns an `Evaluation` object that contains the `value` of the flag, the `reason` -for the value returned, and the `variant` selected. - +for the value returned and the `variant` selected. The method `getValue` will simply return the assigned value or the default. In the case of an error, the default value will be returned and the `Evaluation` contains information about the error. @@ -113,19 +111,11 @@ The SDK takes care of storing events in case of offline and retries in case of t Note that the data struct can't contain the key `context`, as that is reserved for entries set via `putContext` (see below): violating this rule will cause the track function to throw an error. -To set context data to be appended to all tracked events, here as example: +To set context data to be appended to all tracked events, here is an example: ```swift confidence.putContext(context: ["os_version": ConfidenceValue(string: "17.0")]) ``` -### Logging -By default, the Confidence SDK will log errors and warnings locally to the console. You can change the preferred log level by passing a `loggerLevel` to the `Confidence.Builder` constructor. - -To turn off logging completely, you can pass `LoggingLevel.NONE` to the `Confidence.Builder`. - # OpenFeature Provider -If you want to use OpenFeature, an OpenFeature Provider for the [OpenFeature SDK](https://github.com/open-feature/kotlin-swift) is also available. - -## Usage - +If you want to use OpenFeature, an OpenFeature Provider for the [OpenFeature SDK](https://github.com/open-feature/kotlin-sdk) is also available. See the [dedicated Provider Readme](https://github.com/spotify/confidence-sdk-swift/tree/main/Sources/ConfidenceProvider). diff --git a/Sources/ConfidenceProvider/README.md b/Sources/ConfidenceProvider/README.md index fb6cc4af..83f74f82 100644 --- a/Sources/ConfidenceProvider/README.md +++ b/Sources/ConfidenceProvider/README.md @@ -1,5 +1,5 @@ # OpenFeature Provider -If you want to use OpenFeature, an OpenFeature Provider for the [OpenFeature SDK](https://github.com/open-feature/kotlin-swift) is also available. +If you want to use OpenFeature, an OpenFeature Provider for the [OpenFeature SDK](https://github.com/open-feature/kotlin-sdk) is also available. ## Usage @@ -27,7 +27,7 @@ import Confidence import ConfidenceProvider import OpenFeature -let confidence = Confidence.Builder(clientSecret: "mysecret").build() +let confidence = Confidence.Builder(clientSecret: "mysecret", loggerLevel: .NONE).build() let provider = ConfidenceFeatureProvider(confidence: confidence) let ctx = MutableContext(targetingKey: "myTargetingKey", structure: MutableStructure()) OpenFeatureAPI.shared.setProvider(provider: provider, initialContext: ctx) @@ -42,7 +42,7 @@ There is also an `async/await` compatible API available for waiting the Provider await OpenFeatureAPI.shared.setProviderAndWait(provider: provider) ``` -A utility function is available on the provider to check if the current storage has any values stored - this can be used to determine the best initialization strategy. +A utility function is available on the provider to check if the current storage has any stored values - this can be used to determine the best initialization strategy. ```swift // If we have no cache, then do a fetch first. var initializationStrategy: InitializationStrategy = .activateAndFetchAsync @@ -64,7 +64,7 @@ OpenFeatureAPI.shared.observe().sink { event in } ``` -**Note:** if you do attempt to resolve a flag before the READY event is emitted, you may receive the default value with reason `STALE`. +**Note:** if you do attempt to resolve a flag before the READY event is emitted, you may receive the default value with the reason `STALE`. There are other events that are emitted by the provider, see [Provider Events](https://openfeature.dev/specification/types#provider-events) in the Open Feature specification for more details. @@ -78,11 +78,13 @@ OpenFeatureAPI.shared.setEvaluationContext(evaluationContext: ctx) `setEvaluationContext()` is a synchronous function similar to `setProvider()`. It calls the Confidence backend to fetch the flag evaluations according to the new evaluation context; if the call is successful, it replaces the cache with the new flag data. -**Note:** the initialization strategy is not taken into consideration when calling `setEvaluationContext()`, so it's required to wait for READY before resuming to resolve flags. +**Notes:** -**Note:** if you do attempt to resolve a flag before the READY event is emitted, you may receive the old value with reason `STALE`. +- The initialization strategy is not taken into consideration when calling `setEvaluationContext()`, so it's required to wait for READY before resuming to resolve flags. -**Note:** a "targeting key" in the evaluation context is expected by the OpenFeature APIs, but a different custom field inside the `structure` value can also be configured as randomization unit in the Confidence portal. In this case, it's ok to leave `targetingKey` empty. +- If you do attempt to resolve a flag before the READY event is emitted, you may receive the old value with the reason `STALE`. + +- A "targeting key" in the evaluation context is expected by the OpenFeature APIs, but a different custom field inside the `structure` value can also be configured as the randomization unit in the Confidence portal. In this case, it's okay to leave `targetingKey` empty. ### Handling Provider Errors @@ -107,10 +109,9 @@ let client = OpenFeatureAPI.shared.getClient() let result = client.getBooleanValue(key: "my-flag.my-boolean", defaultValue: false) ``` -Confidence allows each flag value to be a complex data structure including multiple properties of different type. To access a specific flag's property, the dot notation in the example above is used. The full data structure for a flag can be always fetched via: +In Confidence each flag value is a complex data structure including one or more properties of different types. To access a specific flag's property, the dot notation in the example above is used. The full data structure for a flag can always be fetched via: ```swift let result = client.getObjectValue(key: "my-flag", defaultValue: Value.null) ``` **Note:** if a flag can't be resolved from the local cache, the provider doesn't automatically resort to calling remote. Refreshing the cache from remote only happens when setting a new provider and/or evaluation context in the global OpenFeatureAPI. -