@@ -108,28 +108,34 @@ export function evaluateFeatures(
108108 const segmentOverride = segmentOverrides [ feature . feature_key ] ;
109109 const finalFeature = segmentOverride ? segmentOverride . feature : feature ;
110110 const hasOverride = ! ! segmentOverride ;
111- const reason = getTargetingMatchReason ( segmentOverride ) ;
111+
112+ const { value : evaluatedValue , reason : evaluatedReason } = hasOverride
113+ ? { value : finalFeature . value , reason : undefined }
114+ : evaluateFeatureValue ( finalFeature , context . identity ?. key ) ;
112115
113116 flags . push ( {
114117 feature_key : finalFeature . feature_key ,
115118 name : finalFeature . name ,
116119 enabled : finalFeature . enabled ,
117- value : hasOverride
118- ? finalFeature . value
119- : evaluateFeatureValue ( finalFeature , context . identity ?. key ) ,
120- reason
120+ value : evaluatedValue ,
121+ reason :
122+ evaluatedReason ??
123+ getTargetingMatchReason ( { type : 'SEGMENT' , override : segmentOverride } )
121124 } ) ;
122125 }
123126
124127 return flags ;
125128}
126129
127- function evaluateFeatureValue ( feature : FeatureContext , identityKey ?: string ) : any {
130+ function evaluateFeatureValue (
131+ feature : FeatureContext ,
132+ identityKey ?: string
133+ ) : { value : any ; reason ?: string } {
128134 if ( ! ! feature . variants && feature . variants . length > 0 && ! ! identityKey ) {
129135 return getMultivariateFeatureValue ( feature , identityKey ) ;
130136 }
131137
132- return feature . value ;
138+ return { value : feature . value , reason : undefined } ;
133139}
134140
135141/**
@@ -142,19 +148,25 @@ function evaluateFeatureValue(feature: FeatureContext, identityKey?: string): an
142148 * @param identityKey - The identity key used for deterministic variant selection
143149 * @returns The variant value if the identity falls within a variant's range, otherwise the default feature value
144150 */
145- function getMultivariateFeatureValue ( feature : FeatureContext , identityKey ?: string ) : any {
151+ function getMultivariateFeatureValue (
152+ feature : FeatureContext ,
153+ identityKey ?: string
154+ ) : { value : any ; reason ?: string } {
146155 const percentageValue = getHashedPercentageForObjIds ( [ feature . key , identityKey ] ) ;
147156
148157 let startPercentage = 0 ;
149158 for ( const variant of feature ?. variants || [ ] ) {
150159 const limit = startPercentage + variant . weight ;
151160
152161 if ( startPercentage <= percentageValue && percentageValue < limit ) {
153- return variant . value ;
162+ return {
163+ value : variant . value ,
164+ reason : getTargetingMatchReason ( { type : 'SPLIT' , weight : variant . weight } )
165+ } ;
154166 }
155167 startPercentage = limit ;
156168 }
157- return feature . value ;
169+ return { value : feature . value , reason : undefined } ;
158170}
159171
160172export function shouldApplyOverride (
@@ -174,8 +186,28 @@ export function isHigherPriority(
174186 return ( priorityA ?? Infinity ) < ( priorityB ?? Infinity ) ;
175187}
176188
177- const getTargetingMatchReason = ( segmentOverride : SegmentOverride ) => {
178- return segmentOverride
179- ? `${ TARGETING_REASONS . TARGETING_MATCH } ; segment=${ segmentOverride . segmentName } `
180- : TARGETING_REASONS . DEFAULT ;
189+ export type TargetingMatchReason =
190+ | {
191+ type : 'SEGMENT' ;
192+ override : SegmentOverride ;
193+ }
194+ | {
195+ type : 'SPLIT' ;
196+ weight : number ;
197+ } ;
198+
199+ const getTargetingMatchReason = ( matchObject : TargetingMatchReason ) => {
200+ const { type } = matchObject ;
201+
202+ if ( type === 'SEGMENT' ) {
203+ return matchObject . override
204+ ? `${ TARGETING_REASONS . TARGETING_MATCH } ; segment=${ matchObject . override . segmentName } `
205+ : TARGETING_REASONS . DEFAULT ;
206+ }
207+
208+ if ( type === 'SPLIT' ) {
209+ return `${ TARGETING_REASONS . SPLIT } ; weight=${ matchObject . weight } ` ;
210+ }
211+
212+ return TARGETING_REASONS . DEFAULT ;
181213} ;
0 commit comments