Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 37 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,55 @@
# Rust Confidence SDK

Rust implementation of the [Confidence](https://confidence.spotify.com/).
This repo contains the [Confidence](https://confidence.spotify.com/) Rust SDK and the Confidence OpenFeature provider. We recommend using the OpenFeature Rust SDK to access Confidence feature flags. Use it to consume feature flags from Confidence.

To learn more about the basic concepts (flags, targeting key, evaluation contexts), the [OpenFeature reference documentation](https://openfeature.dev/docs/reference/intro/) can be a useful resource.


## Usage

### Instantiating the Confidence
### Instantiating the ConfidenceProvider and connecting it to OpenFeature

first, we need to setup the api config which contains a `api_key` and a `region`:
You setup the Confidence Provider once in your app and connect it to OpenFeature .

```rust
// first, we need to setup the api config which contains a `api_key` and a `region`
let api_config = APIConfig { api_key: "YOUR_API_KEY".to_string(), region: YOUR_REGION };

// we can then create a confidence provider using a confidence instance.
let confidence = Confidence::new(api_config)
let provider = ConfidenceProvider::new(confidence);

let mut api = OpenFeature::singleton_mut().await;

// the provider can be set on the open feature api
api.set_provider(provider).await;
```

after this initial setup we can start accessing the flags.
### Resolving feature flags

After this initial setup we can start accessing the flags using an OpenFeature `client`.
Every time any of flags are asked, the sdk fetches them from the network and resolve the asked property.

```rust
let client = api.create_client();

let context = EvaluationContext::default()
.with_custom_field("visitor_id", visitor_id)
.with_custom_field("user_id", user_id);
let details_string = client.get_string_details("my-flag.property", Some(&context), None).await;

match details_string {
Ok(details) => {
println!("Successfully retrieved flag value: {:?}", details.value);
println!("Flag details: {:?}", details);
}
Err(error) => {
println!("Error retrieving flag: {:?}", error);
println!("This is expected if the flag 'hawkflag.message' doesn't exist in your Confidence project");
}
}
```

The schema of the property plays a crucial role in resolving the property, if the schema type matches the asked type, the value will be returned otherwise
we expect an `MismatchType` error from the `EvaluationError`.

Expand All @@ -25,9 +58,3 @@ we expect an `MismatchType` error from the `EvaluationError`.
let details_string = confidence.get_flag("hawkflag.message", "default".to_string()).await;
println!("details string -> {:?}", details_string);
```
### Send custom Events
we can send custom events to the confidence sdk like following:

```rust
confidence.track("[EVENT-NAME]", HashMap::new());
```
3 changes: 2 additions & 1 deletion demo_open_feature/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@ path = "../confidence"
[dependencies]
tokio = {version = "1.33.0", features = ["full"] }
async-trait = "0.1.74"
open-feature = "0.2.3"
open-feature = "0.2.5"
rand = "0.8"
30 changes: 19 additions & 11 deletions demo_open_feature/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
use std::collections::HashMap;
use open_feature::{EvaluationContext, OpenFeature};

use spotify_confidence_sdk::{APIConfig, Confidence, Region};
use spotify_confidence_openfeature_provider::ConfidenceProvider;

Expand All @@ -14,18 +12,28 @@ let api_config = APIConfig {
let confidence = Confidence::new(api_config);
let provider = ConfidenceProvider::new(confidence);

let context = EvaluationContext {
targeting_key: Some("TARGETING_KEY".to_string()),
custom_fields: HashMap::new()
};

let mut api = OpenFeature::singleton_mut().await;

api.set_provider(provider).await;

// wrong type, should return error
let details_string = api
.create_client().get_string_details("hawkflag.message", Some(&context), None).await;
let client = api.create_client();

let random_number = rand::random::<u64>();
let visitor_id = random_number.to_string();

println!("details string -> {:?}", details_string.unwrap().value);
let context = EvaluationContext::default()
.with_custom_field("visitor_id", visitor_id)
.with_custom_field("user_id", "1111111111");
let details_string = client.get_string_details("hawkflag.message", Some(&context), None).await;

match details_string {
Ok(details) => {
println!("Successfully retrieved flag value: {:?}", details.value);
println!("Flag details: {:?}", details);
}
Err(error) => {
println!("Error retrieving flag: {:?}", error);
println!("This is expected if the flag 'hawkflag.message' doesn't exist in your Confidence project");
}
}
}
2 changes: 1 addition & 1 deletion provider/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ path = "../confidence"
version = "0.1.1"

[dependencies]
open-feature = "0.2.3"
open-feature = "0.2.5"
async-trait = "0.1.74"
typed-builder = "0.18.2"
mockall = "0.12.0"
Expand Down
Loading