From ca935a31f9caca6001bffeb7bfd6adfafff7b755 Mon Sep 17 00:00:00 2001 From: "Matthew M. Keeler" Date: Thu, 13 Jun 2024 13:41:02 -0400 Subject: [PATCH] feat!: Add exclude from summary field to flag (#18) --- src/eval.rs | 2 ++ src/flag.rs | 46 ++++++++++++++++++++++++++++++++++++---------- src/lib.rs | 16 ++++++++-------- src/rule.rs | 2 +- src/segment.rs | 2 +- src/test_common.rs | 3 ++- src/variation.rs | 2 +- 7 files changed, 51 insertions(+), 22 deletions(-) diff --git a/src/eval.rs b/src/eval.rs index 84e246b..c750eb6 100644 --- a/src/eval.rs +++ b/src/eval.rs @@ -604,10 +604,12 @@ mod tests { let event = &recorder.events.borrow()[0]; assert_eq!("flagWithSatisfiedPrereq", event.target_flag_key); assert_eq!("prereq", event.prerequisite_flag.key); + assert!(event.prerequisite_flag.exclude_from_summaries); let event = &recorder.events.borrow()[1]; assert_eq!("flagWithNestedPrereq", event.target_flag_key); assert_eq!("flagWithSatisfiedPrereq", event.prerequisite_flag.key); + assert!(!event.prerequisite_flag.exclude_from_summaries); } #[test] diff --git a/src/flag.rs b/src/flag.rs index 8970c44..646541a 100644 --- a/src/flag.rs +++ b/src/flag.rs @@ -83,16 +83,27 @@ pub struct Flag { /// Contains migration-related flag parameters. If this flag is for migration purposes, this /// property is guaranteed to be set. - #[serde(default, skip_serializing_if = "is_default_migration_settings")] + #[serde( + default, + rename = "migration", + skip_serializing_if = "is_default_migration_settings" + )] pub migration_settings: Option, /// Controls the rate at which feature and debug events are emitted from the SDK for this /// particular flag. If this value is not defined, it is assumed to be 1. /// - /// LaunchDarkly may affect this flag to prevent poorly performing applications from adversely + /// LaunchDarkly may modify this value to prevent poorly performing applications from adversely /// affecting upstream service health. #[serde(default, skip_serializing_if = "is_default_ratio")] - pub sampling_ratio: Option, + pub sampling_ratio: Option, + + /// Determines whether or not this flag will be excluded from the event summarization process. + /// + /// LaunchDarkly may change this value to prevent poorly performing applications from adversely + /// affecting upstream service health. + #[serde(default, skip_serializing_if = "std::ops::Not::not")] + pub exclude_from_summaries: bool, } impl Versioned for Flag { @@ -102,7 +113,7 @@ impl Versioned for Flag { } // Used strictly for serialization to determine if a ratio should be included in the JSON. -fn is_default_ratio(sampling_ratio: &Option) -> bool { +fn is_default_ratio(sampling_ratio: &Option) -> bool { sampling_ratio.unwrap_or(1) == 1 } @@ -122,7 +133,7 @@ pub struct MigrationFlagParameters { /// read or write operation. This value can be controlled through the LaunchDarkly UI and /// propagated downstream to the SDKs. #[serde(skip_serializing_if = "is_default_ratio")] - pub check_ratio: Option, + pub check_ratio: Option, } impl MigrationFlagParameters { @@ -361,6 +372,7 @@ impl Flag { context_targets: vec![], migration_settings: None, sampling_ratio: None, + exclude_from_summaries: false, } } } @@ -597,7 +609,7 @@ mod tests { asserting!("true for rule if rule.trackEvents is true") .that(&flag.is_experimentation_enabled(&RuleMatch { rule_index: 0, - rule_id: flag.rules.get(0).unwrap().id.clone(), + rule_id: flag.rules.first().unwrap().id.clone(), in_experiment: false, })) .is_true(); @@ -648,6 +660,20 @@ mod tests { assert!(!with_no_ratio.contains("\"samplingRatio\"")); } + #[test] + fn exclude_from_summaries_is_ignored_appropriately() { + let store = TestStore::new(); + let mut flag = store.flag("flag").unwrap(); + + flag.exclude_from_summaries = true; + let with_exclude = serde_json::to_string_pretty(&flag).unwrap(); + assert!(with_exclude.contains("\"excludeFromSummaries\": true")); + + flag.exclude_from_summaries = false; + let without_exclude = serde_json::to_string_pretty(&flag).unwrap(); + assert!(!without_exclude.contains("\"excludeFromSummaries\"")); + } + #[test] fn migration_settings_included_appropriately() { let store = TestStore::new(); @@ -655,23 +681,23 @@ mod tests { flag.migration_settings = None; let without_migration_settings = serde_json::to_string_pretty(&flag).unwrap(); - assert!(!without_migration_settings.contains("\"migrationSettings\"")); + assert!(!without_migration_settings.contains("\"migration\"")); flag.migration_settings = Some(MigrationFlagParameters { check_ratio: None }); let without_empty_migration_settings = serde_json::to_string_pretty(&flag).unwrap(); - assert!(!without_empty_migration_settings.contains("\"migrationSettings\"")); + assert!(!without_empty_migration_settings.contains("\"migration\"")); flag.migration_settings = Some(MigrationFlagParameters { check_ratio: Some(1), }); let with_default_ratio = serde_json::to_string_pretty(&flag).unwrap(); - assert!(!with_default_ratio.contains("\"migrationSettings\"")); + assert!(!with_default_ratio.contains("\"migration\"")); flag.migration_settings = Some(MigrationFlagParameters { check_ratio: Some(42), }); let with_specific_ratio = serde_json::to_string_pretty(&flag).unwrap(); - assert!(with_specific_ratio.contains("\"migrationSettings\": {")); + assert!(with_specific_ratio.contains("\"migration\": {")); assert!(with_specific_ratio.contains("\"checkRatio\": 42")); } } diff --git a/src/lib.rs b/src/lib.rs index 263a141..cea4a2f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -31,14 +31,6 @@ pub use segment::*; pub use store::*; pub use variation::*; -#[cfg(test)] -pub(crate) mod proptest_generators { - pub(crate) use crate::contexts::attribute_reference::proptest_generators::*; - pub(crate) use crate::contexts::context::proptest_generators::*; - pub(crate) use crate::rule::proptest_generators::*; - pub(crate) use crate::variation::proptest_generators::*; -} - /// Trait indicating that the item is versioned. pub trait Versioned { /// Retrieve the version for this item instance. @@ -50,3 +42,11 @@ pub trait Versioned { self.version() >= version } } + +#[cfg(test)] +pub(crate) mod proptest_generators { + pub(crate) use crate::contexts::attribute_reference::proptest_generators::*; + pub(crate) use crate::contexts::context::proptest_generators::*; + pub(crate) use crate::rule::proptest_generators::*; + pub(crate) use crate::variation::proptest_generators::*; +} diff --git a/src/rule.rs b/src/rule.rs index 46997db..8eb5315 100644 --- a/src/rule.rs +++ b/src/rule.rs @@ -1324,7 +1324,7 @@ mod tests { proptest! { #[test] fn arbitrary_clause_serialization_rountrip(clause in any_clause()) { - let json = serde_json::to_value(&clause).expect("a clause should serialize"); + let json = serde_json::to_value(clause).expect("a clause should serialize"); let parsed: Clause = serde_json::from_value(json.clone()).expect("a clause should parse"); assert_json_eq!(json, parsed); } diff --git a/src/segment.rs b/src/segment.rs index 1310cf2..4145f9d 100644 --- a/src/segment.rs +++ b/src/segment.rs @@ -519,7 +519,7 @@ mod tests { proptest! { #[test] fn arbitrary_segment_rule_serialization_roundtrip(rule in any_segment_rule()) { - let json = serde_json::to_value(&rule).expect("an arbitrary segment rule should serialize"); + let json = serde_json::to_value(rule).expect("an arbitrary segment rule should serialize"); let parsed: SegmentRule = serde_json::from_value(json.clone()).expect("an arbitrary segment rule should parse"); assert_json_eq!(json, parsed); } diff --git a/src/test_common.rs b/src/test_common.rs index db53b80..e9e0090 100644 --- a/src/test_common.rs +++ b/src/test_common.rs @@ -531,7 +531,8 @@ impl TestStore { "usingEnvironmentId": true, "usingMobileKey": true }, - "salt": "salty" + "salt": "salty", + "excludeFromSummaries": true }"#).unwrap(), "offPrereq".to_string() => serde_json::from_str(r#"{ "key": "offPrereq", diff --git a/src/variation.rs b/src/variation.rs index d1248a8..22c1005 100644 --- a/src/variation.rs +++ b/src/variation.rs @@ -752,7 +752,7 @@ mod tests { proptest! { #[test] fn arbitrary_rollout_serialization_roundtrip(rollout in any_rollout()) { - let json = serde_json::to_value(&rollout).expect("a rollout should serialize"); + let json = serde_json::to_value(rollout).expect("a rollout should serialize"); let parsed: Rollout = serde_json::from_value(json.clone()).expect("a rollout should parse"); assert_json_eq!(json, parsed); }