fix(analytics): surface dropped exposure when distinct_id missing from context (SDK-84)#90
Open
tylerjroach wants to merge 2 commits into
Open
fix(analytics): surface dropped exposure when distinct_id missing from context (SDK-84)#90tylerjroach wants to merge 2 commits into
tylerjroach wants to merge 2 commits into
Conversation
…m context When a flag uses a non-default Variant Assignment Key (e.g. device_id), local evaluation succeeds via that key independently of whether distinct_id is present. Exposure tracking, however, requires distinct_id to attribute the event to the user. Previously the SDK silently returned from track_exposure_event with no signal to the caller — the flag value came back correctly but analytics were silently dropped. Surface the drop through the configured error_handler so callers can see they need to include distinct_id in the context alongside the bucketing key. Behavior when distinct_id IS present is unchanged. Linear: SDK-84 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Contributor
Author
Switch the dropped-exposure warning from string concatenation to a
parameterized template so the flag key is only formatted when the
WARNING level is actually enabled.
The corresponding test set the LocalFlagsProvider logger level to
Level.ALL outside the try block and never restored it in finally,
leaking that level to any test that ran afterward in the same JVM.
Capture the original level and restore it. Also switch the log
assertion to format the LogRecord via SimpleFormatter — with
parameterized logging LogRecord.getMessage() returns the raw
"{0}" template, not the interpolated string.
Contributor
Author
|
Pushed P2 — parameterized JUL logging ( P2 — logger level not restored ( All 54 |
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
When a flag uses a non-default Variant Assignment Key (e.g.
device_id) and the evaluation context doesn't includedistinct_id, local eval succeeds — flag definitions are cached, bucketing only needs the configured key — buttrackLocalExposurethen silentlyreturns because it can only attribute the exposure event to adistinct_id. Caller gets the right flag value with no signal that analytics were dropped.Add a
Level.WARNINGlog so the drop becomes visible.Context
Linear: SDK-84. Only
JavaandRubyare actually affected of the five SDKs the audit listed — Python / Go / Node already log when this happens.This bug only affects local evaluation. Remote eval requires
distinct_idat the eval step itself, so it errors out before reaching exposure tracking.Behavior when
distinct_idIS present (alongside the bucketing key) is unchanged — exposure still fires correctly attributed to the user.Test plan
LocalFlagsProviderTesttests pass (mvn test)testWarnsWhenExposureDroppedDueToMissingDistinctIdexercises adevice_id-bucketed flag with a context that hasdevice_idbut nodistinct_id: asserts the variant value is returned, no exposure event is sent, AND aWARNINGlog is emitted🤖 Generated with Claude Code