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

SDK-79

@tylerjroach tylerjroach changed the title fix(flags): add variantSource alongside fallbackReason (SDK-79) feat(analytics): 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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant