Skip to content

Commit cd472e2

Browse files
committed
Fix evaluation reason logic: SPLIT precedence (ADR-004), DEFAULT for catch-all allocs, date window precludes STATIC (ADR-003)
1 parent 9aedff2 commit cd472e2

1 file changed

Lines changed: 20 additions & 4 deletions

File tree

  • products/feature-flagging/feature-flagging-api/src/main/java/datadog/trace/api/openfeature

products/feature-flagging/feature-flagging-api/src/main/java/datadog/trace/api/openfeature/DDEvaluator.java

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -386,10 +386,7 @@ private static <T> ProviderEvaluation<T> resolveVariant(
386386
final ProviderEvaluation<T> result =
387387
ProviderEvaluation.<T>builder()
388388
.value(mappedValue)
389-
.reason(
390-
!isEmpty(allocation.rules)
391-
? Reason.TARGETING_MATCH.name()
392-
: !isEmpty(split.shards) ? Reason.SPLIT.name() : Reason.STATIC.name())
389+
.reason(resolveReason(allocation, split, flag))
393390
.variant(variant.key)
394391
.flagMetadata(metadataBuilder.build())
395392
.build();
@@ -400,6 +397,25 @@ private static <T> ProviderEvaluation<T> resolveVariant(
400397
return result;
401398
}
402399

400+
private static String resolveReason(
401+
final Allocation allocation, final Split split, final Flag flag) {
402+
// ADR-004: SPLIT overrides TARGETING_MATCH when both rules and shard contributed
403+
if (!isEmpty(allocation.rules) && !isEmpty(split.shards)) {
404+
return Reason.SPLIT.name();
405+
}
406+
if (!isEmpty(allocation.rules)) {
407+
return Reason.TARGETING_MATCH.name();
408+
}
409+
if (!isEmpty(split.shards)) {
410+
return Reason.SPLIT.name();
411+
}
412+
// No rules, no shards (vacuous split). STATIC only when this is the sole allocation
413+
// with no date-window constraints (ADR-003: time-gated result is not permanently stable).
414+
final boolean hasDateWindow = allocation.startAt != null || allocation.endAt != null;
415+
final boolean isSoleStaticAlloc = flag.allocations.size() == 1 && !hasDateWindow;
416+
return isSoleStaticAlloc ? Reason.STATIC.name() : Reason.DEFAULT.name();
417+
}
418+
403419
private static Object resolveAttribute(final String name, final EvaluationContext context) {
404420
// Special handling for "id" attribute: if not explicitly provided, use targeting key
405421
if ("id".equals(name) && !context.keySet().contains(name)) {

0 commit comments

Comments
 (0)