Skip to content

Commit f124824

Browse files
authored
Emiel/add support for opt in metric properties (#31)
Add support for `include_experiment_computation` parameter
1 parent 91f994e commit f124824

File tree

11 files changed

+70
-7
lines changed

11 files changed

+70
-7
lines changed

LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
MIT License
22

3-
Copyright (c) 2023-2024 Eppo
3+
Copyright (c) 2023-2025 Eppo
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,14 @@ pip install -r requirements.txt
104104
pytest tests
105105
```
106106

107+
### Running the package
108+
109+
```bash
110+
export EPPO_API_KEY="your-api-key"
111+
export EPPO_SYNC_TAG="your-sync-tag"
112+
python -m eppo_metrics_sync path/to/yaml/directory
113+
```
114+
107115
### Building and Publishing
108116

109117
For package maintainers:

eppo_metrics_sync/eppo_metrics_sync.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
unique_names,
88
valid_fact_references,
99
metric_aggregation_is_valid,
10-
valid_guardrail_cutoff_signs
10+
valid_guardrail_cutoff_signs,
11+
valid_experiment_computation
1112
)
1213

1314
from eppo_metrics_sync.dbt_model_parser import DbtModelParser
@@ -112,6 +113,7 @@ def validate(self):
112113
valid_fact_references(self)
113114
metric_aggregation_is_valid(self)
114115
valid_guardrail_cutoff_signs(self)
116+
valid_experiment_computation(self)
115117

116118
if self.validation_errors:
117119
error_count = len(self.validation_errors)

eppo_metrics_sync/schema/eppo_metric_schema.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@
6565
},
6666
"column": {
6767
"description": "The column that contains this fact (if not specified, will use each record)",
68-
"type": ["string", "null"]
68+
"type": ["string", "null"]
6969
},
7070
"description": {
7171
"description": "User-friendly description of the fact",
@@ -97,6 +97,10 @@
9797
"description": {
9898
"description": "User-friendly description of the fact property",
9999
"type": "string"
100+
},
101+
"include_experiment_computation": {
102+
"description": "If true, this fact property will be used in experiment result computation",
103+
"type": "boolean"
100104
}
101105
}
102106
}

eppo_metrics_sync/validation.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,15 @@ def valid_fact_references(payload):
6969
str(', '.join(fact_references.difference(fact_names)))
7070
)
7171

72+
def valid_experiment_computation(payload):
73+
for fact_source in payload.fact_sources:
74+
if 'properties' in fact_source:
75+
for property in fact_source['properties']:
76+
if 'include_experiment_computation' in property:
77+
if not isinstance(property['include_experiment_computation'], bool):
78+
payload.validation_errors.append(
79+
f"Invalid include_experiment_computation value. It must be a boolean value for property: {property['name']}"
80+
)
7281

7382
def metric_aggregation_is_valid(payload):
7483
for m in payload.metrics:

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "eppo_metrics_sync"
7-
version = "0.1.5"
7+
version = "0.1.6"
88
description = "Sync metrics to Eppo"
99
readme = "README.md"
1010
requires-python = ">=3.7"

tests/test_validation.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,9 @@ def test_valid_guardrail_cutoff_signs():
5050

5151

5252
"""def test_unique_fact_property_names():
53-
5453
eppo_metrics_sync = EppoMetricsSync(directory = None)
55-
eppo_metrics_sync.load_yaml(
54+
eppo_metrics_sync.load_eppo_yaml(
5655
path = test_yaml_dir + "/duplicated_fact_property_names.yaml")
57-
5856
with pytest.raises(ValueError, match = "Fact property names are not unique: device"):
5957
eppo_metrics_sync.validate()"""
6058

@@ -66,6 +64,12 @@ def test_invalid_fact_reference():
6664
with pytest.raises(ValueError, match=re.escape("Invalid fact reference(s): revenue")):
6765
eppo_metrics_sync.validate()
6866

67+
def test_invalid_experiment_computation():
68+
eppo_metrics_sync = EppoMetricsSync(directory=None)
69+
eppo_metrics_sync.load_eppo_yaml(
70+
path=test_yaml_dir + "/invalid_experiment_computation.yaml")
71+
with pytest.raises(ValueError, match=re.escape("Invalid include_experiment_computation value. It must be a boolean value for property: Traffic Source")):
72+
eppo_metrics_sync.validate()
6973

7074
def test_invalid_winsorization_operation():
7175
test_agg = {
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
fact_sources:
2+
- name: Purchase
3+
sql: |
4+
SELECT
5+
events.*
6+
FROM customer_db.onboarding.events as events
7+
WHERE event_type = 'Revenue'
8+
timestamp_column: TS
9+
entities:
10+
- entity_name: User
11+
column: USER_ID
12+
facts:
13+
- name: Purchase # facts without column specified reflect "EACH RECORD"
14+
- name: Purchase Revenue
15+
column: EVENT_VALUE
16+
properties:
17+
- name: Traffic Source
18+
column: TRAFFIC_SOURCE
19+
include_experiment_computation: 0
20+
- name: Country
21+
column: COUNTRY
22+
include_experiment_computation: true
23+
- name: Browser
24+
column: BROWSER
25+
include_experiment_computation: true
26+
reference_url: https://github.com/Eppo-exp/eppo-metrics-sync
27+
metrics:
28+
- name: Unique Purchase by User
29+
entity: User # it would be nice if this was optional if there is exactly 1 entity defined above
30+
is_guardrail: true
31+
numerator:
32+
fact_name: Purchase
33+
operation: distinct_entity
File renamed without changes.
File renamed without changes.

0 commit comments

Comments
 (0)