Skip to content

Commit 34a6241

Browse files
Add Config Version to Exposure Metadata (#365)
kong test: statsig-io/kong#2842
1 parent 1a92749 commit 34a6241

File tree

5 files changed

+34
-5
lines changed

5 files changed

+34
-5
lines changed

statsig/config_evaluation.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ def __init__(self,
77
boolean_value=False,
88
json_value=None,
99
rule_id="",
10+
version=None,
1011
secondary_exposures=None,
1112
allocated_experiment=None,
1213
explicit_parameters=None,
@@ -41,3 +42,4 @@ def __init__(self,
4142
self.sample_rate = sample_rate
4243
self.user = user
4344
self.forward_all_exposures = forward_all_exposures
45+
self.version = version

statsig/dynamic_config.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
class DynamicConfig:
88
def __init__(self, data, name, rule, user: Optional[StatsigUser] = None, group_name=None,
99
evaluation_details: Optional[EvaluationDetails] = None,
10-
secondary_exposures=None):
10+
secondary_exposures=None, passed_rule=None, version=None):
1111
if data is None:
1212
data = {}
1313
self.value = data
@@ -25,6 +25,8 @@ def __init__(self, data, name, rule, user: Optional[StatsigUser] = None, group_n
2525
secondary_exposures = []
2626
self.secondary_exposures = secondary_exposures
2727
self.user = user
28+
self.passed_rule = passed_rule
29+
self.version = version
2830

2931
def get(self, key, default=None):
3032
"""Returns the value of the config at the given key

statsig/evaluator.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ def check_gate(self, user, gate, end_result=None, is_nested=False):
203203
globals.logger.debug(f"Gate {gate} not found in the store. Are you sure the gate name is correct?")
204204
return self.unsupported_or_unrecognized(gate)
205205
if end_result is None:
206-
end_result = _ConfigEvaluation()
206+
end_result = _ConfigEvaluation(version=eval_gate.get("version", None))
207207
self.__eval_config(user, eval_gate, end_result, is_nested)
208208
return end_result
209209

@@ -222,7 +222,7 @@ def get_config(self, user, config_name, is_exp=False):
222222
f"{'Config' if is_exp else 'Experiment'} {config_name} not found in the store. Are you sure the config name is correct?"
223223
)
224224
return self.unsupported_or_unrecognized(config_name)
225-
result = _ConfigEvaluation()
225+
result = _ConfigEvaluation(version=eval_config.get("version", None))
226226
self.__eval_config(user, eval_config, result)
227227
return result
228228

@@ -239,7 +239,7 @@ def get_layer(self, user, layer_name):
239239
if eval_layer is None:
240240
globals.logger.debug(f"Layer {layer_name} not found in the store. Are you sure the layer name is correct?")
241241
return self.unsupported_or_unrecognized(layer_name)
242-
result = _ConfigEvaluation()
242+
result = _ConfigEvaluation(version=eval_layer.get("version", None))
243243
self.__eval_config(user, eval_layer, result)
244244
return result
245245

statsig/statsig_logger.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ def log_gate_exposure(
8080
gate,
8181
value,
8282
rule_id,
83+
version,
8384
secondary_exposures,
8485
evaluation_details: EvaluationDetails,
8586
is_manual_exposure=False,
@@ -93,6 +94,9 @@ def log_gate_exposure(
9394
"gateValue": "true" if value else "false",
9495
"ruleID": rule_id,
9596
}
97+
98+
if version is not None:
99+
event.metadata["configVersion"] = version
96100
event.statsigMetadata = {}
97101
if not self._is_unique_exposure(user, _GATE_EXPOSURE_EVENT, event.metadata):
98102
return
@@ -118,6 +122,8 @@ def log_config_exposure(
118122
user,
119123
config,
120124
rule_id,
125+
passed_rule,
126+
version,
121127
secondary_exposures,
122128
evaluation_details: EvaluationDetails,
123129
is_manual_exposure=False,
@@ -129,7 +135,10 @@ def log_config_exposure(
129135
event.metadata = {
130136
"config": config,
131137
"ruleID": rule_id,
138+
"rulePassed": "true" if passed_rule else "false",
132139
}
140+
if version is not None:
141+
event.metadata["configVersion"] = version
133142
event.statsigMetadata = {}
134143

135144
if not self._is_unique_exposure(user, _CONFIG_EXPOSURE_EVENT, event.metadata):
@@ -177,6 +186,8 @@ def log_layer_exposure(
177186
"parameterName": parameter_name,
178187
"isExplicitParameter": "true" if is_explicit else "false",
179188
}
189+
if config_evaluation.version is not None:
190+
metadata["configVersion"] = config_evaluation.version
180191
if not self._is_unique_exposure(user, _LAYER_EXPOSURE_EVENT, metadata):
181192
return
182193
event.metadata = metadata

statsig/statsig_server.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,7 @@ def manually_log_gate_exposure(self, user: StatsigUser, gate_name: str):
234234
gate_name,
235235
result.boolean_value,
236236
result.rule_id,
237+
result.version,
237238
result.secondary_exposures,
238239
result.evaluation_details,
239240
is_manual_exposure=True,
@@ -255,7 +256,9 @@ def task():
255256
result.user,
256257
group_name=result.group_name,
257258
evaluation_details=result.evaluation_details,
258-
secondary_exposures=result.secondary_exposures
259+
secondary_exposures=result.secondary_exposures,
260+
passed_rule=result.boolean_value,
261+
version=result.version,
259262
)
260263
self.safe_eval_callback(dynamicConfig)
261264
return dynamicConfig
@@ -274,6 +277,8 @@ def manually_log_config_exposure(self, user: StatsigUser, config_name: str):
274277
user,
275278
config_name,
276279
result.rule_id,
280+
result.boolean_value,
281+
result.version,
277282
result.secondary_exposures,
278283
result.evaluation_details,
279284
is_manual_exposure=True,
@@ -285,6 +290,8 @@ def log_exposure_for_config(self, config_eval: DynamicConfig):
285290
user,
286291
config_eval.name,
287292
config_eval.rule_id,
293+
config_eval.passed_rule,
294+
config_eval.version,
288295
config_eval.secondary_exposures,
289296
config_eval.evaluation_details,
290297
is_manual_exposure=True,
@@ -308,6 +315,8 @@ def task():
308315
group_name=result.group_name,
309316
evaluation_details=result.evaluation_details,
310317
secondary_exposures=result.secondary_exposures,
318+
passed_rule=result.boolean_value,
319+
version=result.version,
311320
)
312321
self.safe_eval_callback(dynamicConfig)
313322
return dynamicConfig
@@ -326,6 +335,8 @@ def manually_log_experiment_exposure(self, user: StatsigUser, experiment_name: s
326335
user,
327336
experiment_name,
328337
result.rule_id,
338+
result.boolean_value,
339+
result.version,
329340
result.secondary_exposures,
330341
result.evaluation_details,
331342
is_manual_exposure=True,
@@ -569,6 +580,7 @@ def __check_gate(self, user: StatsigUser, gate_name: str, log_exposure=True):
569580
gate_name,
570581
result.boolean_value,
571582
result.rule_id,
583+
result.version,
572584
result.secondary_exposures,
573585
result.evaluation_details,
574586
sampling_rate=logged_sampling_rate,
@@ -590,6 +602,8 @@ def __get_config(self, user: StatsigUser, config_name: str, log_exposure=True):
590602
user,
591603
config_name,
592604
result.rule_id,
605+
result.boolean_value,
606+
result.version,
593607
result.secondary_exposures,
594608
result.evaluation_details,
595609
sampling_rate=logged_sampling_rate,

0 commit comments

Comments
 (0)