Repository navigation
feat: Mark evaluation events as override-affected - #366
Merged
Merged
Conversation
kinyoklion
force-pushed
the
rlamb/overrides-dotnet-events-internal
branch
from
September 28, 2026 20:39
9387b50 to
3aacd97
Compare
kinyoklion
force-pushed
the
rlamb/overrides-dotnet-events
branch
from
September 28, 2026 20:39
86caaa5 to
9ddeb28
Compare
kinyoklion
force-pushed
the
rlamb/overrides-dotnet-events-internal
branch
from
October 1, 2026 23:43
3aacd97 to
471a60c
Compare
kinyoklion
force-pushed
the
rlamb/overrides-dotnet-events
branch
from
October 1, 2026 23:44
9ddeb28 to
75135db
Compare
kinyoklion
force-pushed
the
rlamb/overrides-dotnet-events-internal
branch
from
October 3, 2026 01:34
471a60c to
a750428
Compare
kinyoklion
force-pushed
the
rlamb/overrides-dotnet-events
branch
from
October 3, 2026 01:34
75135db to
89329c5
Compare
Member
Author
|
bugbot review |
kinyoklion
force-pushed
the
rlamb/overrides-dotnet-events-internal
branch
from
October 3, 2026 01:52
a750428 to
c9ce308
Compare
kinyoklion
force-pushed
the
rlamb/overrides-dotnet-events
branch
from
October 3, 2026 01:52
89329c5 to
403d56e
Compare
kinyoklion
force-pushed
the
rlamb/overrides-dotnet-events-internal
branch
from
October 5, 2026 21:55
c9ce308 to
18760a7
Compare
kinyoklion
force-pushed
the
rlamb/overrides-dotnet-events
branch
from
October 5, 2026 21:55
403d56e to
b085719
Compare
kinyoklion
force-pushed
the
rlamb/overrides-dotnet-events-internal
branch
from
October 5, 2026 22:12
18760a7 to
3941b93
Compare
kinyoklion
force-pushed
the
rlamb/overrides-dotnet-events
branch
from
October 5, 2026 22:12
b085719 to
2b54c3e
Compare
kinyoklion
force-pushed
the
rlamb/overrides-dotnet-events-internal
branch
from
October 5, 2026 22:28
3941b93 to
17cf04b
Compare
kinyoklion
force-pushed
the
rlamb/overrides-dotnet-events
branch
from
October 5, 2026 22:28
2b54c3e to
4ec85dc
Compare
kinyoklion
force-pushed
the
rlamb/overrides-dotnet-events-internal
branch
from
October 5, 2026 23:56
17cf04b to
fb8c7ac
Compare
kinyoklion
force-pushed
the
rlamb/overrides-dotnet-events
branch
from
October 5, 2026 23:56
4ec85dc to
368f8fa
Compare
kinyoklion
force-pushed
the
rlamb/overrides-dotnet-events-internal
branch
from
October 13, 2026 21:03
fb8c7ac to
e0080d0
Compare
kinyoklion
force-pushed
the
rlamb/overrides-dotnet-events
branch
from
October 13, 2026 21:03
368f8fa to
f12a5f6
Compare
kinyoklion
force-pushed
the
rlamb/overrides-dotnet-events-internal
branch
from
October 13, 2026 22:13
e0080d0 to
3469298
Compare
kinyoklion
force-pushed
the
rlamb/overrides-dotnet-events
branch
from
October 13, 2026 22:13
f12a5f6 to
6d2b453
Compare
kinyoklion
force-pushed
the
rlamb/overrides-dotnet-events-internal
branch
from
October 16, 2026 21:21
3469298 to
1531cd9
Compare
kinyoklion
force-pushed
the
rlamb/overrides-dotnet-events
branch
from
October 16, 2026 21:21
6d2b453 to
4e21dce
Compare
kinyoklion
force-pushed
the
rlamb/overrides-dotnet-events-internal
branch
from
October 23, 2026 23:50
1531cd9 to
ac67f94
Compare
kinyoklion
force-pushed
the
rlamb/overrides-dotnet-events
branch
from
October 23, 2026 23:50
4e21dce to
28e15b9
Compare
kinyoklion
force-pushed
the
rlamb/overrides-dotnet-events-internal
branch
from
October 26, 2026 22:46
ac67f94 to
e4a339c
Compare
kinyoklion
force-pushed
the
rlamb/overrides-dotnet-events
branch
from
October 26, 2026 22:46
28e15b9 to
8bd83fe
Compare
kinyoklion
force-pushed
the
rlamb/overrides-dotnet-events-internal
branch
from
October 26, 2026 23:13
e4a339c to
e6beb28
Compare
kinyoklion
force-pushed
the
rlamb/overrides-dotnet-events
branch
from
October 26, 2026 23:13
8bd83fe to
d116173
Compare
kinyoklion
force-pushed
the
rlamb/overrides-dotnet-events-internal
branch
from
October 28, 2026 20:38
693bae7 to
0da3d0f
Compare
kinyoklion
force-pushed
the
rlamb/overrides-dotnet-events
branch
from
October 28, 2026 20:38
511c88a to
6735a14
Compare
kinyoklion
force-pushed
the
rlamb/overrides-dotnet-events-internal
branch
from
October 28, 2026 21:04
0da3d0f to
917b778
Compare
kinyoklion
force-pushed
the
rlamb/overrides-dotnet-events
branch
from
October 28, 2026 21:04
6735a14 to
73a926e
Compare
kinyoklion
force-pushed
the
rlamb/overrides-dotnet-events-internal
branch
from
October 28, 2026 21:23
917b778 to
96a4008
Compare
kinyoklion
force-pushed
the
rlamb/overrides-dotnet-events
branch
from
October 28, 2026 21:23
73a926e to
9de4329
Compare
kinyoklion
force-pushed
the
rlamb/overrides-dotnet-events-internal
branch
from
October 28, 2026 21:53
96a4008 to
521a20b
Compare
kinyoklion
force-pushed
the
rlamb/overrides-dotnet-events
branch
from
October 28, 2026 21:53
9de4329 to
e148541
Compare
kinyoklion
force-pushed
the
rlamb/overrides-dotnet-events-internal
branch
from
October 28, 2026 22:02
521a20b to
f7eafb9
Compare
kinyoklion
force-pushed
the
rlamb/overrides-dotnet-events
branch
from
October 28, 2026 22:02
e148541 to
69a4fcf
Compare
kinyoklion
force-pushed
the
rlamb/overrides-dotnet-events-internal
branch
from
October 28, 2026 22:35
f7eafb9 to
52b82ae
Compare
kinyoklion
force-pushed
the
rlamb/overrides-dotnet-events
branch
from
October 28, 2026 22:35
69a4fcf to
9d0b734
Compare
kinyoklion
force-pushed
the
rlamb/overrides-dotnet-events-internal
branch
from
October 29, 2026 16:45
52b82ae to
56e48ec
Compare
kinyoklion
force-pushed
the
rlamb/overrides-dotnet-events
branch
from
October 29, 2026 16:45
9d0b734 to
9259cff
Compare
keelerm84
approved these changes
Oct 29, 2026
kinyoklion
force-pushed
the
rlamb/overrides-dotnet-events
branch
from
October 29, 2026 20:23
9259cff to
19628f5
Compare
Base automatically changed from
rlamb/overrides-dotnet-events-internal
to
dotnet-server-sdk-v9
October 29, 2026 20:36
kinyoklion
force-pushed
the
rlamb/overrides-dotnet-events
branch
from
October 29, 2026 20:39
19628f5 to
7f9e390
Compare
EventProcessorTypes.EvaluationEvent gains an OverrideAffected property. The event factory sets it from the evaluation result for every evaluation event and prerequisite record, whether or not the caller asked for reasons, and the event processor wrapper passes it through, so a marked evaluation produces no individual feature or debug event and is counted under a separate summary counter. A wrong-type result keeps the marking on its reason and its event. The OVERRIDE specification's test vectors now also assert the per-evaluation summary contribution.
The server uses the override-affected event marking that InternalSdk 3.12.0-alpha adds.
kinyoklion
force-pushed
the
rlamb/overrides-dotnet-events
branch
from
October 29, 2026 20:53
7f9e390 to
2b8016e
Compare
Member
Author
|
bugbot review |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 2b8016e. Configure here.
kinyoklion
added a commit
that referenced
this pull request
Oct 29, 2026
<!-- TERMAG_PR_BODY_BEGIN --> ## Summary Adds the file-based override source, as defined by the OVERRIDE specification, on top of the shared file loading code and the override layer from the earlier changes in this series. The series targets `dotnet-server-sdk-v9`, the branch that prepares the next major version. The existing file data source keeps its current behavior: it does not use the shared code, and nothing in this change touches it. Configuration: `FileOverrides.Source()` returns a `FileOverrideSourceBuilder` that is passed to `DataSystemBuilder.Overrides(...)`. Its options are `FilePaths` (one or more files, in precedence order, required), `DuplicateKeysHandling` (`Fail`, the default, or `Ignore`, which keeps the first configured file's entry), `ChangeDetection` (`Polling`, the default, or `Watching`), `PollInterval` (one second by default and at minimum; a lower value is raised to the minimum with a warning), and `Parser`, which registers a parsing function for a file extension, for formats other than JSON such as YAML. Building a source with no file paths, with an option outside its enumeration, or with a YAML file for which no parser is registered, throws, so the client constructor fails the same way it does for other invalid component configuration. A path listed more than once is logged at Warn and the repeats are ignored; the first occurrence keeps its place in the order. Every public member carries the note that flag overrides are currently experimental and subject to change. Behavior: the files use the file data document format (`flags`, `flagValues`, `segments`); a `flagValues` entry expands to a flag that is on and serves its single value by fallthrough, so it evaluates with the `FALLTHROUGH` reason. The parser for a file is chosen by its extension, and a file whose extension has no registered parser is parsed as JSON. A flag or segment is listed under its key; a `key` property in the definition is optional and must be equal to it, and a `version` property is optional. The initial load runs inside the client constructor. Change detection is in place before the initial load, so a change made between the two is not missed. In watching mode a configured path that is a link to a file in another directory is detected only through the periodic directory check; polling, the default, follows the link directly. A configured file that does not exist contributes no overrides and produces no error log; creating it later adds its overrides and deleting it removes them. A file that exists but cannot be read or parsed, or a duplicate key under `Fail`, fails that whole reload: the previously loaded overrides stay in effect, the failure is logged, and the source retries after a bounded delay and on the next change. Every applied change is logged at Info level with the overrides in effect and what each configured file supplied (for example `Flag overrides in effect: 2 flags, 1 segment (/etc/ld/a.json: 2 flags, 1 segment; /etc/ld/b.json: absent)`). Polling examines the files' modification time, size, and existence once per interval; watching uses file system notifications on each file's directory. YAML: the SDK does not bundle a YAML parser, following the existing file data source, so YAML files require the application to register a parser for the `.yaml` or `.yml` extension through the `Parser` option. A YAML file configured without one is reported when the client is created, not on every reload. The specification allows the application to supply the parser. Tests cover the builder validation and defaults, including the YAML check, every file behavior above in both change detection modes, the Info log lines, and client end-to-end scenarios in which an operator adds, changes, and removes an override on a running client that never obtains LaunchDarkly data, and in which a YAML override file is read with the registered parser. It depends on the server events change, #366, which is merged into `dotnet-server-sdk-v9`. [SDK-3248](https://launchdarkly.atlassian.net/browse/SDK-3248) [SDK-3248]: https://launchdarkly.atlassian.net/browse/SDK-3248?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Overview** > Adds the **built-in file override integration** so operators can force flag/segment values from local files via `DataSystemBuilder.Overrides(FileOverrides.Source()...)`, without restarting the client. > > The public surface is `FileOverrides`, `FileOverrideSourceBuilder`, and `FileOverrideTypes` (duplicate-key policy, polling vs watching, poll interval, optional per-extension parsers for YAML). The internal `FileOverrideSource` merges multiple paths in order, loads synchronously on startup, hot-reloads through shared file-loading helpers, pushes full snapshots to the override layer, and logs what is in effect per file. Failed reloads keep the last good snapshot; missing files are ignored until they appear. > > Docs on `DataSystemBuilder.Overrides` and `IOverrideSource` now point at `FileOverrides`. Tests cover builder validation, reload/merge/error behavior, and end-to-end `LdClient` evaluation (including `OverrideAffected` and client-side `AllFlagsState` rules). > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit feaf592. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> <!-- TERMAG_PR_BODY_END --> <!-- termag: box=i-0575d1c54853058d7 project=projects --> <sub>Opened from termag</sub>
kinyoklion
pushed a commit
that referenced
this pull request
Oct 29, 2026
…ha.1 (#382) 🤖 I have created a release *beep* *boop* --- ## [9.0.0-alpha.1](LaunchDarkly.ServerSdk-v9.0.0-alpha.0...LaunchDarkly.ServerSdk-v9.0.0-alpha.1) (2026-10-29) ### Features * Add a shared file data reloader, poller, and watcher ([#361](#361)) ([4eed241](4eed241)) * Add the file-based override source ([#367](#367)) ([b834131](b834131)) * Add the override marker to the flag and segment models and mark evaluations ([#363](#363)) ([21f666a](21f666a)) * Add the override store, overlay, source interfaces, and data system wiring ([#364](#364)) ([e1748a1](e1748a1)) * Mark evaluation events as override-affected ([#366](#366)) ([7c873a0](7c873a0)) * Split summary counters by overrideAffected and suppress individual events for marked evaluations ([#365](#365)) ([c9b327b](c9b327b)) * Support the flag-overrides capability in the contract test service ([#368](#368)) ([b80d6aa](b80d6aa)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Overview** > This is a **Release Please** cut that publishes **LaunchDarkly.ServerSdk `9.0.0-alpha.1`**. The diff only updates release metadata: `.release-please-manifest.json`, `LaunchDarkly.ServerSdk.csproj` `<Version>`, `PROVENANCE.md` verification example, and a new **`9.0.0-alpha.1`** section in `CHANGELOG.md`. > > The changelog entry documents what ships in this alpha (already merged elsewhere): **local flag overrides** via override store/overlay/source wiring and a **file-based override source** with shared file reloader/poller/watcher; **override markers** on flag/segment models and evaluations; **analytics** changes that mark override-affected evaluations, split summary counters by `overrideAffected`, and suppress individual events when appropriate; plus **contract-test** support for the flag-overrides capability. > > Reviewers can treat this as a **versioning and release-notes sanity check**—no application logic changes appear in the diff itself. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 81f0588. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Makes the server SDK hand the override-affected marking to the event processor, as defined by the OVERRIDE specification.
EventProcessorTypes.EvaluationEventgains anOverrideAffectedproperty,EventFactorysets it from the evaluation result for every evaluation event and every prerequisite record, andDefaultEventProcessorWrapperpasses it to the InternalSdk event processor, which then suppresses individual feature and debug events for the marked evaluation and counts it under a separate summary counter that carries the marker. The marking is carried whether or not the caller asked for reasons.A wrong-type result keeps the marking: the replacement error reason and the event for that evaluation both report it, because the evaluation read the same definitions. The specification's test vectors now also assert the per-evaluation summary contribution, and new client tests cover the marked evaluation record, the prerequisite tree in which only one leaf is overridden, and the event output of a full flush, in which only the unaffected sibling prerequisite produces a feature event while all four flags have tracking on.
It depends on the InternalSdk events change, #365, released as
LaunchDarkly.InternalSdk3.12.0-alpha, which the server now references.SDK-3248
Note
Overview
The server SDK now passes override-affected marking from evaluations into analytics:
EvaluationEventgainsOverrideAffected,EventFactorysets it from the evaluation reason (including prerequisite and wrong-type default-value events), andDefaultEventProcessorWrapperforwards it to InternalSdk so marked evaluations skip individual feature/debug events and appear in summary counters with the marker—even when the caller did not request reasons.The package reference bumps to
LaunchDarkly.InternalSdk3.12.0-alpha (depends on the InternalSdk events change). Override vector tests assertsummaryOverrideAffected, and newLdClientOverrideEventsTestcoverage exercises marking, prerequisite trees, wrong-type paths, flush output, and the default event processor wrapper.Reviewed by Cursor Bugbot for commit 2b8016e. Bugbot is set up for automated code reviews on this repo. Configure here.
Opened from termag