Skip to content

feat(analytics): add variantSource alongside fallbackReason (SDK-79) - #87

Closed
tylerjroach wants to merge 1 commit into
feature-flags-supportfrom
fix/sdk-79-variant-source-fallback-reason
Closed

feat(analytics): add variantSource alongside fallbackReason (SDK-79)#87
tylerjroach wants to merge 1 commit into
feature-flags-supportfrom
fix/sdk-79-variant-source-fallback-reason

Conversation

@tylerjroach

Copy link
Copy Markdown
Contributor

Summary

  • MixpanelSelectedVariant->variantSource (always set): local | remote | fallback. New SOURCE_* constants on the class.
  • MixpanelSelectedVariant->fallbackReason (existing field, semantics tightened): one of FLAG_NOT_FOUND | MISSING_CONTEXT_KEY | NO_ROLLOUT_MATCH | BACKEND_ERROR | NOT_READY. Only set when variantSource === SOURCE_FALLBACK.
  • withFallbackReason() now sets both variantSource = SOURCE_FALLBACK and fallbackReason. New withSource() clears fallbackReason.
  • MixpanelLocalFlags tags matched returns with SOURCE_LOCAL. MixpanelRemoteFlags tags network successes with SOURCE_REMOTE.

Why

The base feature-flag work in #86 already introduced fallbackReason to distinguish the various fallback paths. Adding variantSource alongside completes the picture: callers (especially a future OpenFeature wrapper, and exposure analytics) can answer both "where did this value come from?" and "if it's a fallback, why?".

Constants and field naming align with the design being applied to the other Mixpanel SDKs (Python / Ruby / Java / Go / Node / Android / Swift / JS-web), tracked at Linear SDK-79.

Stacked on #86

This PR is based on feature-flags-support (PR #86's branch). Once #86 merges to master, GitHub auto-rebases this onto master.

Test plan

  • 36 tests / 104 assertions pass (vendor/bin/phpunit test/FeatureFlags/)
  • Existing fallbackReason tests still pass; assertions augmented to also check variantSource
  • New assertions confirm variantSource is SOURCE_LOCAL / SOURCE_REMOTE on successful eval, and SOURCE_FALLBACK (plus the right fallbackReason) on every fallback path

🤖 Generated with Claude Code

SelectedVariant now carries two source fields: `variant_source`
(local | remote | fallback) and `fallback_reason` (FLAG_NOT_FOUND |
MISSING_CONTEXT_KEY | NO_ROLLOUT_MATCH | BACKEND_ERROR | NOT_READY,
set only when source is fallback).

Three behaviorally distinct outcomes — flag-not-found, no-rollout-match,
and missing-context-key — previously all returned the bare fallback. The
OpenFeature wrapper collapsed them to FLAG_NOT_FOUND, sending callers
chasing the flag name when the real cause was usually a rule miss or
absent context.

The wrapper now dispatches on fallback_reason and maps each to the
spec-correct OpenFeature response. Most notably, NO_ROLLOUT_MATCH
becomes `reason: DEFAULT` with no error code instead of FLAG_NOT_FOUND.

Constant names align with mixpanel-php for consistency across SDKs.

Linear: SDK-79

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@linear-code

linear-code Bot commented Jun 29, 2026

Copy link
Copy Markdown
@tylerjroach tylerjroach changed the title fix(flags): add variantSource alongside fallbackReason (SDK-79) Jun 29, 2026
@tylerjroach
tylerjroach deleted the fix/sdk-79-variant-source-fallback-reason branch June 29, 2026 16:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

1 participant