From 3aacd9746cadd9af693f8e1c295f8fdafdbbe3ca Mon Sep 17 00:00:00 2001 From: Ryan Lamb <4955475+kinyoklion@users.noreply.github.com> Date: Fri, 25 Sep 2026 15:39:39 -0700 Subject: [PATCH] feat: Split summary counters by overrideAffected and suppress individual events for marked evaluations EventTypes.EvaluationEvent gains an OverrideAffected field. A marked evaluation produces no individual feature event and no debug event, whatever the flag requests, and is counted under a separate summary counter whose key includes the marker. The summary output writes "overrideAffected": true on such a counter and omits the property otherwise, as defined by the OVERRIDE specification. --- .../src/Events/AggregatedEventSummarizer.cs | 6 +- .../shared/internal/src/Events/EventOutput.cs | 1 + .../src/Events/EventProcessorInternal.cs | 8 +- .../internal/src/Events/EventSummarizer.cs | 25 +++-- pkgs/shared/internal/src/Events/EventTypes.cs | 4 + .../internal/src/Events/IEventSummarizer.cs | 6 +- .../src/Events/PerContextEventSummarizer.cs | 6 +- .../Events/AggregatedEventSummarizerTest.cs | 6 +- .../internal/test/Events/EventOutputTest.cs | 12 +- .../test/Events/EventProcessorTest.cs | 104 +++++++++++++++++- .../test/Events/EventSummarizerTest.cs | 50 +++++++-- .../Events/PerContextEventSummarizerTest.cs | 22 ++-- .../internal/test/Events/TestProperties.cs | 1 + 13 files changed, 204 insertions(+), 47 deletions(-) diff --git a/pkgs/shared/internal/src/Events/AggregatedEventSummarizer.cs b/pkgs/shared/internal/src/Events/AggregatedEventSummarizer.cs index e398183b..a500e86c 100644 --- a/pkgs/shared/internal/src/Events/AggregatedEventSummarizer.cs +++ b/pkgs/shared/internal/src/Events/AggregatedEventSummarizer.cs @@ -21,9 +21,11 @@ public void SummarizeEvent( int? variation, in LdValue value, in LdValue defaultValue, - in Context context + in Context context, + bool overrideAffected ) => - _summarizer.SummarizeEvent(timestamp, flagKey, flagVersion, variation, value, defaultValue, context); + _summarizer.SummarizeEvent(timestamp, flagKey, flagVersion, variation, value, defaultValue, context, + overrideAffected); public IReadOnlyList GetSummariesAndReset() { diff --git a/pkgs/shared/internal/src/Events/EventOutput.cs b/pkgs/shared/internal/src/Events/EventOutput.cs index cbcb1c65..7311c670 100644 --- a/pkgs/shared/internal/src/Events/EventOutput.cs +++ b/pkgs/shared/internal/src/Events/EventOutput.cs @@ -160,6 +160,7 @@ public void WriteSummaryEvent(EventSummary summary, Utf8JsonWriter w) JsonConverterHelpers.WriteLdValue(w, "value", counter.Value.FlagValue); JsonConverterHelpers.WriteIntIfNotNull(w, "version", counter.Key.Version); JsonConverterHelpers.WriteBooleanIfTrue(w, "unknown", !counter.Key.Version.HasValue); + JsonConverterHelpers.WriteBooleanIfTrue(w, "overrideAffected", counter.Key.OverrideAffected); w.WriteNumber("count", counter.Value.Count); w.WriteEndObject(); diff --git a/pkgs/shared/internal/src/Events/EventProcessorInternal.cs b/pkgs/shared/internal/src/Events/EventProcessorInternal.cs index bbcbacd1..50ed0cf5 100644 --- a/pkgs/shared/internal/src/Events/EventProcessorInternal.cs +++ b/pkgs/shared/internal/src/Events/EventProcessorInternal.cs @@ -145,7 +145,7 @@ internal void AddEvent(object e) internal void AddToSummary(EvaluationEvent ee) => _summarizer.SummarizeEvent(ee.Timestamp, ee.FlagKey, ee.FlagVersion, ee.Variation, ee.Value, ee.Default, - ee.Context); + ee.Context, ee.OverrideAffected); internal FlushPayload GetPayload() => new FlushPayload { Events = _events.ToArray(), Summaries = _summarizer.GetSummariesAndReset() }; @@ -312,8 +312,10 @@ private void ProcessEvent(object e, EventBuffer buffer) timestamp = ee.Timestamp; context = ee.Context; var samplingRatio = ee.SamplingRatio ?? 1; - willAddFullEvent = ee.TrackEvents && Sampler.Sample(samplingRatio); - if (ShouldDebugEvent(ee) && Sampler.Sample(samplingRatio)) + // An override-affected evaluation appears only in the summary counters. It produces + // no individual feature event and no debug event, whatever the flag requests. + willAddFullEvent = ee.TrackEvents && !ee.OverrideAffected && Sampler.Sample(samplingRatio); + if (!ee.OverrideAffected && ShouldDebugEvent(ee) && Sampler.Sample(samplingRatio)) { debugEvent = new DebugEvent { FromEvent = ee }; } diff --git a/pkgs/shared/internal/src/Events/EventSummarizer.cs b/pkgs/shared/internal/src/Events/EventSummarizer.cs index 684e0a4a..a45cd0e6 100644 --- a/pkgs/shared/internal/src/Events/EventSummarizer.cs +++ b/pkgs/shared/internal/src/Events/EventSummarizer.cs @@ -27,10 +27,11 @@ public void SummarizeEvent( int? variation, in LdValue value, in LdValue defaultValue, - in Context context + in Context context, + bool overrideAffected ) { - _eventsState.IncrementCounter(flagKey, variation, flagVersion, value, defaultValue, context); + _eventsState.IncrementCounter(flagKey, variation, flagVersion, value, defaultValue, context, overrideAffected); _eventsState.NoteTimestamp(timestamp); } @@ -71,7 +72,13 @@ public EventSummary(Context context) Context = context; } - public void IncrementCounter(string key, int? variation, int? version, LdValue flagValue, LdValue defaultVal, in Context context) + public void IncrementCounter(string key, int? variation, int? version, LdValue flagValue, LdValue defaultVal, in Context context) => + IncrementCounter(key, variation, version, flagValue, defaultVal, context, false); + + // The override-affected marker is part of the counter key. Override-affected and other + // evaluations of the same flag key, variation, and version accumulate into separate counters. + public void IncrementCounter(string key, int? variation, int? version, LdValue flagValue, LdValue defaultVal, + in Context context, bool overrideAffected) { if (!Flags.TryGetValue(key, out var flagSummary)) { @@ -92,7 +99,7 @@ public void IncrementCounter(string key, int? variation, int? version, LdValue f contextKinds.Add(context.Kind.Value); } - EventsCounterKey counterKey = new EventsCounterKey(version, variation); + EventsCounterKey counterKey = new EventsCounterKey(version, variation, overrideAffected); if (flagSummary.Counters.TryGetValue(counterKey, out EventsCounterValue value)) { value.Increment(); @@ -135,11 +142,15 @@ internal sealed class EventsCounterKey { public readonly int? Version; public readonly int? Variation; + public readonly bool OverrideAffected; + + public EventsCounterKey(int? version, int? variation) : this(version, variation, false) { } - public EventsCounterKey(int? version, int? variation) + public EventsCounterKey(int? version, int? variation, bool overrideAffected) { Version = version; Variation = variation; + OverrideAffected = overrideAffected; } // Required because we use this class as a dictionary key @@ -147,14 +158,14 @@ public override bool Equals(object obj) { if (obj is EventsCounterKey o) { - return Variation == o.Variation && Version == o.Version; + return Variation == o.Variation && Version == o.Version && OverrideAffected == o.OverrideAffected; } return false; } // Required because we use this class as a dictionary key public override int GetHashCode() => - (Variation ?? -1) * 17 + (Version ?? -1); + ((Variation ?? -1) * 17 + (Version ?? -1)) * 2 + (OverrideAffected ? 1 : 0); } internal sealed class EventsCounterValue diff --git a/pkgs/shared/internal/src/Events/EventTypes.cs b/pkgs/shared/internal/src/Events/EventTypes.cs index be776455..a9897198 100644 --- a/pkgs/shared/internal/src/Events/EventTypes.cs +++ b/pkgs/shared/internal/src/Events/EventTypes.cs @@ -53,6 +53,10 @@ public struct EvaluationEvent // disabling events. public long? SamplingRatio; public bool ExcludeFromSummaries; + // True when a flag override affected the evaluation, directly or transitively. A marked + // evaluation produces no individual feature or debug event, whatever the flag requests, and + // is counted under a separate summary counter that carries the marker. + public bool OverrideAffected; } /// diff --git a/pkgs/shared/internal/src/Events/IEventSummarizer.cs b/pkgs/shared/internal/src/Events/IEventSummarizer.cs index 4b9c30d6..0997ff30 100644 --- a/pkgs/shared/internal/src/Events/IEventSummarizer.cs +++ b/pkgs/shared/internal/src/Events/IEventSummarizer.cs @@ -19,7 +19,8 @@ namespace LaunchDarkly.Sdk.Internal.Events /// internal interface IEventSummarizer { - // Adds information about an evaluation to the summary. + // Adds information about an evaluation to the summary. An override-affected evaluation is + // counted under a separate counter that carries the marker. void SummarizeEvent( UnixMillisecondTime timestamp, string flagKey, @@ -27,7 +28,8 @@ void SummarizeEvent( int? variation, in LdValue value, in LdValue defaultValue, - in Context context + in Context context, + bool overrideAffected ); // Returns the current summary data and resets the state to empty. The aggregated diff --git a/pkgs/shared/internal/src/Events/PerContextEventSummarizer.cs b/pkgs/shared/internal/src/Events/PerContextEventSummarizer.cs index 19f5afc1..486a53fb 100644 --- a/pkgs/shared/internal/src/Events/PerContextEventSummarizer.cs +++ b/pkgs/shared/internal/src/Events/PerContextEventSummarizer.cs @@ -29,7 +29,8 @@ public void SummarizeEvent( int? variation, in LdValue value, in LdValue defaultValue, - in Context context + in Context context, + bool overrideAffected ) { if (!_summarizersByContext.TryGetValue(context, out var summarizer)) @@ -37,7 +38,8 @@ in Context context summarizer = new EventSummarizer(context); _summarizersByContext[context] = summarizer; } - summarizer.SummarizeEvent(timestamp, flagKey, flagVersion, variation, value, defaultValue, context); + summarizer.SummarizeEvent(timestamp, flagKey, flagVersion, variation, value, defaultValue, context, + overrideAffected); } public IReadOnlyList GetSummariesAndReset() diff --git a/pkgs/shared/internal/test/Events/AggregatedEventSummarizerTest.cs b/pkgs/shared/internal/test/Events/AggregatedEventSummarizerTest.cs index 3e5038aa..5810d21c 100644 --- a/pkgs/shared/internal/test/Events/AggregatedEventSummarizerTest.cs +++ b/pkgs/shared/internal/test/Events/AggregatedEventSummarizerTest.cs @@ -19,8 +19,8 @@ public void EmptySummarizerReturnsNoSummaries() public void AllContextsAreAggregatedIntoASingleContextlessSummary() { var summarizer = new AggregatedEventSummarizer(); - summarizer.SummarizeEvent(Time, "flag", 1, 0, LdValue.Of("a"), LdValue.Null, ContextA); - summarizer.SummarizeEvent(Time, "flag", 1, 0, LdValue.Of("b"), LdValue.Null, ContextB); + summarizer.SummarizeEvent(Time, "flag", 1, 0, LdValue.Of("a"), LdValue.Null, ContextA, false); + summarizer.SummarizeEvent(Time, "flag", 1, 0, LdValue.Of("b"), LdValue.Null, ContextB, false); var summaries = summarizer.GetSummariesAndReset(); @@ -35,7 +35,7 @@ public void AllContextsAreAggregatedIntoASingleContextlessSummary() public void GetSummariesAndResetClearsState() { var summarizer = new AggregatedEventSummarizer(); - summarizer.SummarizeEvent(Time, "flag", 1, 0, LdValue.Of("a"), LdValue.Null, ContextA); + summarizer.SummarizeEvent(Time, "flag", 1, 0, LdValue.Of("a"), LdValue.Null, ContextA, false); Assert.Single(summarizer.GetSummariesAndReset()); Assert.Empty(summarizer.GetSummariesAndReset()); diff --git a/pkgs/shared/internal/test/Events/EventOutputTest.cs b/pkgs/shared/internal/test/Events/EventOutputTest.cs index 10ed382f..1dc45036 100644 --- a/pkgs/shared/internal/test/Events/EventOutputTest.cs +++ b/pkgs/shared/internal/test/Events/EventOutputTest.cs @@ -201,6 +201,9 @@ public void SummaryEventIsSerialized() summary.IncrementCounter("third", null, null, LdValue.Of("default3"), LdValue.Of("default3"), context2); // flag doesn't exist (no version) + summary.IncrementCounter("fourth", 1, 41, LdValue.Of("value4"), LdValue.Of("default4"), context1, true); + summary.IncrementCounter("fourth", 1, 41, LdValue.Of("value4"), LdValue.Of("default4"), context1, false); + summary.NoteTimestamp(UnixMillisecondTime.OfMillis(1000)); summary.NoteTimestamp(UnixMillisecondTime.OfMillis(1002)); @@ -217,7 +220,7 @@ public void SummaryEventIsSerialized() Assert.Equal(LdValue.Null, outputEvent.Get("context")); var featuresJson = outputEvent.Get("features"); - Assert.Equal(3, featuresJson.Count); + Assert.Equal(4, featuresJson.Count); var firstJson = featuresJson.Get("first"); Assert.Equal("default1", firstJson.Get("default").AsString); @@ -242,6 +245,13 @@ public void SummaryEventIsSerialized() thirdJson.Get("contextKinds")); // we evaluated this flag with only context2 TestUtil.AssertContainsInAnyOrder(thirdJson.Get("counters").AsList(LdValue.Convert.Json), LdValue.Parse(@"{""unknown"":true,""value"":""default3"",""count"":1}")); + + // An override-affected counter carries the marker. The counter for the same flag, + // variation, and version without the marker stays separate and omits the property. + var fourthJson = featuresJson.Get("fourth"); + TestUtil.AssertContainsInAnyOrder(fourthJson.Get("counters").List, + LdValue.Parse(@"{""value"":""value4"",""variation"":1,""version"":41,""overrideAffected"":true,""count"":1}"), + LdValue.Parse(@"{""value"":""value4"",""variation"":1,""version"":41,""count"":1}")); } [Fact] diff --git a/pkgs/shared/internal/test/Events/EventProcessorTest.cs b/pkgs/shared/internal/test/Events/EventProcessorTest.cs index 905d7371..69dfbf80 100644 --- a/pkgs/shared/internal/test/Events/EventProcessorTest.cs +++ b/pkgs/shared/internal/test/Events/EventProcessorTest.cs @@ -109,7 +109,8 @@ private void RecordEval(EventProcessor ep, TestFlagProperties f, TestEvalPropert Reason = e.Reason, PrereqOf = e.PrereqOf, TrackEvents = f.TrackEvents, - DebugEventsUntilDate = f.DebugEventsUntilDate + DebugEventsUntilDate = f.DebugEventsUntilDate, + OverrideAffected = e.OverrideAffected }); } @@ -189,6 +190,95 @@ public void IndividualFeatureEventIsQueuedWithIndexEvent() } } + [Fact] + public void OverrideAffectedEvaluationProducesNoFeatureEvent() + { + var mockSender = MakeMockSender(); + var captured = EventCapture.From(mockSender); + + using (var ep = MakeProcessor(_config, mockSender)) + { + var eval = BasicEval; + eval.OverrideAffected = true; + RecordEval(ep, BasicFlagWithTracking, eval); + FlushAndWait(ep, captured); + + // The flag requests individual events, but the marking alone decides: only the index + // event and the summary appear. + Assert.Collection(captured.Events, + item => CheckIndexEvent(item, BasicEval.Timestamp, _contextJson), + item => CheckSummaryEventDetails(item, BasicEval.Timestamp, BasicEval.Timestamp, + MustHaveFlagSummary(BasicFlag.Key, LdValue.Null, + MustHaveFlagSummaryCounter(BasicEval.Value, BasicEval.Variation, BasicFlag.Version, 1, true)))); + } + } + + [Fact] + public void OverrideAffectedPrerequisiteRecordProducesNoFeatureEvent() + { + var mockSender = MakeMockSender(); + var captured = EventCapture.From(mockSender); + + using (var ep = MakeProcessor(_config, mockSender)) + { + var eval = BasicEval; + eval.OverrideAffected = true; + eval.PrereqOf = "parent-flag"; + RecordEval(ep, BasicFlagWithTracking, eval); + FlushAndWait(ep, captured); + + Assert.Collection(captured.Events, + item => CheckIndexEvent(item, BasicEval.Timestamp, _contextJson), + item => CheckSummaryEvent(item)); + } + } + + [Fact] + public void OverrideAffectedEvaluationProducesNoDebugEvent() + { + var mockSender = MakeMockSender(); + var captured = EventCapture.From(mockSender); + + using (var ep = MakeProcessor(_config, mockSender)) + { + var flag = BasicFlagWithTracking; + flag.DebugEventsUntilDate = UnixMillisecondTime.Now.PlusMillis(1000000); + var eval = BasicEval; + eval.OverrideAffected = true; + RecordEval(ep, flag, eval); + FlushAndWait(ep, captured); + + Assert.Collection(captured.Events, + item => CheckIndexEvent(item, BasicEval.Timestamp, _contextJson), + item => CheckSummaryEvent(item)); + } + } + + [Fact] + public void OverrideAffectedEvaluationsAreCountedSeparatelyFromOthers() + { + var mockSender = MakeMockSender(); + var captured = EventCapture.From(mockSender); + + using (var ep = MakeProcessor(_config, mockSender)) + { + var plainEval = BasicEval; + var markedEval = BasicEval; + markedEval.OverrideAffected = true; + RecordEval(ep, BasicFlag, markedEval); + RecordEval(ep, BasicFlag, markedEval); + RecordEval(ep, BasicFlag, plainEval); + FlushAndWait(ep, captured); + + Assert.Collection(captured.Events, + item => CheckIndexEvent(item, BasicEval.Timestamp, _contextJson), + item => CheckSummaryEventDetails(item, BasicEval.Timestamp, BasicEval.Timestamp, + MustHaveFlagSummary(BasicFlag.Key, LdValue.Null, + MustHaveFlagSummaryCounter(BasicEval.Value, BasicEval.Variation, BasicFlag.Version, 2, true), + MustHaveFlagSummaryCounter(BasicEval.Value, BasicEval.Variation, BasicFlag.Version, 1, false)))); + } + } + [Fact] public void ItDoesNotQueueAFeatureEventWithSamplingRatioOfZero() { @@ -965,7 +1055,12 @@ private Action MustHaveFlagSummary(string flagKey, LdValue defaultVal, }; } - private Action MustHaveFlagSummaryCounter(LdValue value, int? variation, int? version, int count) + private Action MustHaveFlagSummaryCounter(LdValue value, int? variation, int? version, int count) => + MustHaveFlagSummaryCounter(value, variation, version, count, false); + + // An override-affected counter carries "overrideAffected": true. Any other counter omits the property. + private Action MustHaveFlagSummaryCounter(LdValue value, int? variation, int? version, int count, + bool overrideAffected) { return (flagKey, items) => { @@ -974,11 +1069,12 @@ private Action MustHaveFlagSummaryCounter(LdValue value, int? v return o.Get("value").Equals(value) && o.Get("version").Equals(version.HasValue ? LdValue.Of(version.Value) : LdValue.Null) && o.Get("variation").Equals(variation.HasValue ? LdValue.Of(variation.Value) : LdValue.Null) - && o.Get("count").Equals(LdValue.Of(count)); + && o.Get("count").Equals(LdValue.Of(count)) + && o.Get("overrideAffected").Equals(overrideAffected ? LdValue.Of(true) : LdValue.Null); })) { Assert.True(false, "could not find counter for (" + value + ", " + version + ", " + variation + ", " + count - + ") in: " + items.ToString() + " for flag " + flagKey); + + ", overrideAffected=" + overrideAffected + ") in: " + items.ToString() + " for flag " + flagKey); } }; } diff --git a/pkgs/shared/internal/test/Events/EventSummarizerTest.cs b/pkgs/shared/internal/test/Events/EventSummarizerTest.cs index e8f76cc0..10250879 100644 --- a/pkgs/shared/internal/test/Events/EventSummarizerTest.cs +++ b/pkgs/shared/internal/test/Events/EventSummarizerTest.cs @@ -14,9 +14,9 @@ public void SummarizeEventSetsStartAndEndDates() var time2 = UnixMillisecondTime.OfMillis(2000); var time3 = UnixMillisecondTime.OfMillis(3000); EventSummarizer es = new EventSummarizer(); - es.SummarizeEvent(time2, "flag", null, null, LdValue.Null, LdValue.Null, _context); - es.SummarizeEvent(time1, "flag", null, null, LdValue.Null, LdValue.Null, _context); - es.SummarizeEvent(time3, "flag", null, null, LdValue.Null, LdValue.Null, _context); + es.SummarizeEvent(time2, "flag", null, null, LdValue.Null, LdValue.Null, _context, false); + es.SummarizeEvent(time1, "flag", null, null, LdValue.Null, LdValue.Null, _context, false); + es.SummarizeEvent(time3, "flag", null, null, LdValue.Null, LdValue.Null, _context, false); EventSummary data = es.GetSummaryAndReset(); Assert.Equal(time1, data.StartDate); @@ -35,11 +35,11 @@ public void SummarizeEventIncrementsCounters() default1 = LdValue.Of("default1"), default2 = LdValue.Of("default2"), default3 = LdValue.Of("default3"); EventSummarizer es = new EventSummarizer(); - es.SummarizeEvent(time, flag1Key, flag1Version, variation1, value1, default1, _context); - es.SummarizeEvent(time, flag1Key, flag1Version, variation2, value2, default1, _context); - es.SummarizeEvent(time, flag2Key, flag2Version, variation1, value99, default2, _context); - es.SummarizeEvent(time, flag1Key, flag1Version, variation1, value1, default1, _context); - es.SummarizeEvent(time, unknownFlagKey, null, null, default3, default3, _context); + es.SummarizeEvent(time, flag1Key, flag1Version, variation1, value1, default1, _context, false); + es.SummarizeEvent(time, flag1Key, flag1Version, variation2, value2, default1, _context, false); + es.SummarizeEvent(time, flag2Key, flag2Version, variation1, value99, default2, _context, false); + es.SummarizeEvent(time, flag1Key, flag1Version, variation1, value1, default1, _context, false); + es.SummarizeEvent(time, unknownFlagKey, null, null, default3, default3, _context, false); EventSummary data = es.GetSummaryAndReset(); Dictionary expected = new Dictionary(); @@ -53,6 +53,32 @@ public void SummarizeEventIncrementsCounters() data.Flags[unknownFlagKey].Counters[new EventsCounterKey(null, null)]); } + [Fact] + public void OverrideAffectedEvaluationsAreCountedSeparately() + { + var time = UnixMillisecondTime.OfMillis(1000); + var value = LdValue.Of("value"); + var defaultValue = LdValue.Of("default"); + EventSummarizer es = new EventSummarizer(); + es.SummarizeEvent(time, "flag", 11, 1, value, defaultValue, _context, false); + es.SummarizeEvent(time, "flag", 11, 1, value, defaultValue, _context, true); + es.SummarizeEvent(time, "flag", 11, 1, value, defaultValue, _context, true); + EventSummary data = es.GetSummaryAndReset(); + + var counters = data.Flags["flag"].Counters; + Assert.Equal(2, counters.Count); + Assert.Equal(new EventsCounterValue(1, value), counters[new EventsCounterKey(11, 1, false)]); + Assert.Equal(new EventsCounterValue(2, value), counters[new EventsCounterKey(11, 1, true)]); + } + + [Fact] + public void CounterKeyEqualityIncludesTheOverrideAffectedMarker() + { + Assert.Equal(new EventsCounterKey(11, 1), new EventsCounterKey(11, 1, false)); + Assert.NotEqual(new EventsCounterKey(11, 1, false), new EventsCounterKey(11, 1, true)); + Assert.NotEqual(new EventsCounterKey(11, 1, false).GetHashCode(), new EventsCounterKey(11, 1, true).GetHashCode()); + } + [Fact] public void SummarizeEventRemembersContextKinds() { @@ -68,10 +94,10 @@ public void SummarizeEventRemembersContextKinds() EventSummarizer es = new EventSummarizer(); // flag1 gets only kind1; flag2 gets kind1 and kind2; flag3 gets kind1, kind2, and kind3 - es.SummarizeEvent(time, flag1Key, version, variation, value, value, c1); - es.SummarizeEvent(time, flag2Key, version, variation, value, value, c1); - es.SummarizeEvent(time, flag2Key, version, variation, value, value, c2); - es.SummarizeEvent(time, flag3Key, version, variation, value, value, multi); + es.SummarizeEvent(time, flag1Key, version, variation, value, value, c1, false); + es.SummarizeEvent(time, flag2Key, version, variation, value, value, c1, false); + es.SummarizeEvent(time, flag2Key, version, variation, value, value, c2, false); + es.SummarizeEvent(time, flag3Key, version, variation, value, value, multi, false); EventSummary data = es.GetSummaryAndReset(); Assert.Equal(new HashSet { "kind1" }, data.Flags[flag1Key].ContextKinds); diff --git a/pkgs/shared/internal/test/Events/PerContextEventSummarizerTest.cs b/pkgs/shared/internal/test/Events/PerContextEventSummarizerTest.cs index 8583b2df..dad327b9 100644 --- a/pkgs/shared/internal/test/Events/PerContextEventSummarizerTest.cs +++ b/pkgs/shared/internal/test/Events/PerContextEventSummarizerTest.cs @@ -24,8 +24,8 @@ public void EmptySummarizerReturnsNoSummaries() public void EachContextGetsItsOwnSummaryWithTheContextAttached() { var summarizer = new PerContextEventSummarizer(); - summarizer.SummarizeEvent(Time, "flag", 1, 0, LdValue.Of("a"), LdValue.Null, ContextA); - summarizer.SummarizeEvent(Time, "flag", 1, 0, LdValue.Of("b"), LdValue.Null, ContextB); + summarizer.SummarizeEvent(Time, "flag", 1, 0, LdValue.Of("a"), LdValue.Null, ContextA, false); + summarizer.SummarizeEvent(Time, "flag", 1, 0, LdValue.Of("b"), LdValue.Null, ContextB, false); var summaries = summarizer.GetSummariesAndReset(); @@ -42,8 +42,8 @@ public void EvaluationsForEqualContextsAreMergedIntoOneSummary() var contextA2 = Context.New(ContextKind.Of("user"), "a"); var summarizer = new PerContextEventSummarizer(); - summarizer.SummarizeEvent(Time, "flag", 1, 0, LdValue.Of("v"), LdValue.Null, contextA1); - summarizer.SummarizeEvent(Time, "flag", 1, 0, LdValue.Of("v"), LdValue.Null, contextA2); + summarizer.SummarizeEvent(Time, "flag", 1, 0, LdValue.Of("v"), LdValue.Null, contextA1, false); + summarizer.SummarizeEvent(Time, "flag", 1, 0, LdValue.Of("v"), LdValue.Null, contextA2, false); var summaries = summarizer.GetSummariesAndReset(); @@ -60,8 +60,8 @@ public void ContextsDifferingByAttributeAreTrackedSeparately() var withName = Context.Builder("a").Kind("user").Name("Pat").Build(); var summarizer = new PerContextEventSummarizer(); - summarizer.SummarizeEvent(Time, "flag", 1, 0, LdValue.Of("v"), LdValue.Null, plain); - summarizer.SummarizeEvent(Time, "flag", 1, 0, LdValue.Of("v"), LdValue.Null, withName); + summarizer.SummarizeEvent(Time, "flag", 1, 0, LdValue.Of("v"), LdValue.Null, plain, false); + summarizer.SummarizeEvent(Time, "flag", 1, 0, LdValue.Of("v"), LdValue.Null, withName, false); var summaries = summarizer.GetSummariesAndReset(); @@ -72,9 +72,9 @@ public void ContextsDifferingByAttributeAreTrackedSeparately() public void CountersAreAccumulatedPerContext() { var summarizer = new PerContextEventSummarizer(); - summarizer.SummarizeEvent(Time, "flag", 1, 0, LdValue.Of("a"), LdValue.Null, ContextA); - summarizer.SummarizeEvent(Time, "flag", 1, 0, LdValue.Of("a"), LdValue.Null, ContextA); - summarizer.SummarizeEvent(Time, "flag", 1, 0, LdValue.Of("b"), LdValue.Null, ContextB); + summarizer.SummarizeEvent(Time, "flag", 1, 0, LdValue.Of("a"), LdValue.Null, ContextA, false); + summarizer.SummarizeEvent(Time, "flag", 1, 0, LdValue.Of("a"), LdValue.Null, ContextA, false); + summarizer.SummarizeEvent(Time, "flag", 1, 0, LdValue.Of("b"), LdValue.Null, ContextB, false); var summaries = summarizer.GetSummariesAndReset(); @@ -86,7 +86,7 @@ public void CountersAreAccumulatedPerContext() public void GetSummariesAndResetClearsState() { var summarizer = new PerContextEventSummarizer(); - summarizer.SummarizeEvent(Time, "flag", 1, 0, LdValue.Of("a"), LdValue.Null, ContextA); + summarizer.SummarizeEvent(Time, "flag", 1, 0, LdValue.Of("a"), LdValue.Null, ContextA, false); Assert.Single(summarizer.GetSummariesAndReset()); Assert.Empty(summarizer.GetSummariesAndReset()); @@ -96,7 +96,7 @@ public void GetSummariesAndResetClearsState() public void ClearDiscardsAccumulatedData() { var summarizer = new PerContextEventSummarizer(); - summarizer.SummarizeEvent(Time, "flag", 1, 0, LdValue.Of("a"), LdValue.Null, ContextA); + summarizer.SummarizeEvent(Time, "flag", 1, 0, LdValue.Of("a"), LdValue.Null, ContextA, false); summarizer.Clear(); diff --git a/pkgs/shared/internal/test/Events/TestProperties.cs b/pkgs/shared/internal/test/Events/TestProperties.cs index 9c00cba3..53e203ac 100644 --- a/pkgs/shared/internal/test/Events/TestProperties.cs +++ b/pkgs/shared/internal/test/Events/TestProperties.cs @@ -19,6 +19,7 @@ public struct TestEvalProperties public LdValue DefaultValue; public EvaluationReason? Reason; public string PrereqOf; + public bool OverrideAffected; } public struct TestCustomEventProperties