Skip to content

Commit 232da69

Browse files
fix: correctly count metrics when a flag with dependencies has disabled parents (#304)
# Description This PR fixes a bug where we didn't count metrics correctly: if the dependencies were not satisfied during a `get_variant` call, we wouldn't track any metrics for the flag at all. During an `is_enabled` call, we'd track the result of the child flag's evaluation without taking into account the dependencies. Note that the **behavior** was still correct. This is only about metrics. The root cause is related to how we check dependencies and act on that result: the Unleash client checks dependencies as part of its `is_enabled` and `get_variant` calls, but the metrics are tracked in the individual `Feature` objects. The current implementation was the quickest way I could fix the issue. I think we should restructure it (probably; either now or later) to avoid calling internal methods of the Feature object. However, it serves as a nice way to show what's wrong and how we can fix it. (Maybe just make that `_count_variant` method non-internal?) Due to the way the code is organized already, it might make sense to move the dependencies check into the Feature class instead of performing it in the Unleash Client. However, that would require us to have some way to access those dependencies from the dependent feature. This probably means more restructuring. I'm not sure that's worth it. Maybe it's better to leave as is? I'll take any input on it 🙋🏼 ## Type of change Please delete options that are not relevant. - [x] Bug fix (non-breaking change which fixes an issue) # How Has This Been Tested? Please describe the tests that you ran to verify your changes. - [x] Unit tests # Checklist: - [x] My code follows the style guidelines of this project - [x] I have performed a self-review of my own code - [ ] I have commented my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation - [ ] My changes generate no new warnings - [x] I have added tests that prove my fix is effective or that my feature works - [ ] New and existing unit tests pass locally with my changes - [x] Any dependent changes have been merged and published in downstream modules
1 parent 31c33eb commit 232da69

File tree

2 files changed

+43
-4
lines changed

2 files changed

+43
-4
lines changed

UnleashClient/__init__.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -364,9 +364,15 @@ def is_enabled(
364364
if self.unleash_bootstrapped or self.is_initialized:
365365
try:
366366
feature = self.features[feature_name]
367-
feature_check = feature.is_enabled(
368-
context
369-
) and self._dependencies_are_satisfied(feature_name, context)
367+
dependency_check = self._dependencies_are_satisfied(
368+
feature_name, context
369+
)
370+
371+
if dependency_check:
372+
feature_check = feature.is_enabled(context)
373+
else:
374+
feature.increment_stats(False)
375+
feature_check = False
370376

371377
if feature.only_for_metrics:
372378
return self._get_fallback_value(
@@ -449,6 +455,8 @@ def get_variant(self, feature_name: str, context: Optional[dict] = None) -> dict
449455
feature = self.features[feature_name]
450456

451457
if not self._dependencies_are_satisfied(feature_name, context):
458+
feature.increment_stats(False)
459+
feature._count_variant("disabled")
452460
return DISABLED_VARIATION
453461

454462
variant_check = feature.get_variant(context)

tests/unit_tests/test_client.py

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -572,6 +572,7 @@ def test_uc_doesnt_count_metrics_for_dependency_parents(unleash_client):
572572
time.sleep(1)
573573

574574
child = "ChildWithVariant"
575+
parent = "Parent"
575576
# Check a flag that depends on a parent
576577
unleash_client.is_enabled(child)
577578
unleash_client.get_variant(child)
@@ -581,7 +582,37 @@ def test_uc_doesnt_count_metrics_for_dependency_parents(unleash_client):
581582
request = json.loads(responses.calls[-1].request.body)
582583
assert request["bucket"]["toggles"][child]["yes"] == 2
583584
assert request["bucket"]["toggles"][child]["variants"]["childVariant"] == 1
584-
assert "Parent" not in request["bucket"]["toggles"]
585+
assert parent not in request["bucket"]["toggles"]
586+
587+
588+
@responses.activate
589+
def test_uc_counts_metrics_for_child_even_if_parent_is_disabled(unleash_client):
590+
# Set up API
591+
responses.add(responses.POST, URL + REGISTER_URL, json={}, status=202)
592+
responses.add(
593+
responses.GET,
594+
URL + FEATURES_URL,
595+
json=MOCK_FEATURE_WITH_DEPENDENCIES_RESPONSE,
596+
status=200,
597+
)
598+
responses.add(responses.POST, URL + METRICS_URL, json={}, status=202)
599+
600+
# Create Unleash client and check initial load
601+
unleash_client.initialize_client()
602+
time.sleep(1)
603+
604+
child = "WithDisabledDependency"
605+
parent = "Disabled"
606+
# Check a flag that depends on a disabled parent
607+
unleash_client.is_enabled(child)
608+
unleash_client.get_variant(child)
609+
610+
# Verify that the parent doesn't have any metrics registered
611+
time.sleep(12)
612+
request = json.loads(responses.calls[-1].request.body)
613+
assert request["bucket"]["toggles"][child]["no"] == 2
614+
assert request["bucket"]["toggles"][child]["variants"]["disabled"] == 1
615+
assert parent not in request["bucket"]["toggles"]
585616

586617

587618
@responses.activate

0 commit comments

Comments
 (0)