Skip to content
This repository has been archived by the owner on Nov 8, 2024. It is now read-only.

Commit

Permalink
fix: add timezone to timestamps
Browse files Browse the repository at this point in the history
  • Loading branch information
rasendubi committed Aug 21, 2024
1 parent 70595d1 commit a021dc2
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 2 deletions.
8 changes: 6 additions & 2 deletions eppo_client/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ def get_assignment_detail(
"featureFlag": flag_key,
"variation": result.variation.key if result and result.variation else None,
"subject": subject_key,
"timestamp": datetime.datetime.utcnow().isoformat(),
"timestamp": _utcnow().isoformat(),
"subjectAttributes": subject_attributes,
"metaData": {"sdkLanguage": "python", "sdkVersion": __version__},
}
Expand Down Expand Up @@ -370,7 +370,7 @@ def evaluate_bandit_action(
"modelVersion": (
bandit_data.bandit_model_version if evaluation else None
),
"timestamp": datetime.datetime.utcnow().isoformat(),
"timestamp": _utcnow().isoformat(),
"subjectNumericAttributes": (
subject_context_attributes.numeric_attributes
if evaluation.subject_attributes
Expand Down Expand Up @@ -492,3 +492,7 @@ def convert_actions_to_action_contexts(
actions: Union[ActionContexts, ActionAttributes]
) -> ActionContexts:
return {k: convert_attributes_to_context_attributes(v) for k, v in actions.items()}


def _utcnow() -> datetime.datetime:
return datetime.datetime.now(datetime.timezone.utc)
32 changes: 32 additions & 0 deletions test/client_bandit_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# making client_test.py too long.


import datetime
import json
import os
from time import sleep
Expand Down Expand Up @@ -156,6 +157,37 @@ def test_get_bandit_action_bandit_error(mock_bandit_evaluator):
assert len(mock_assignment_logger.bandit_events) == 0


def test_bandit_event_has_utc_timestamp():
# tests that allocation filtering based on subject attributes works correctly
client = get_instance()
actions = {
"adidas": ContextAttributes(
numeric_attributes={"discount": 0.1},
categorical_attributes={"from": "germany"},
),
"nike": ContextAttributes(
numeric_attributes={"discount": 0.2}, categorical_attributes={"from": "usa"}
),
}
client.get_bandit_action(
"banner_bandit_flag_uk_only",
"alice",
DEFAULT_SUBJECT_ATTRIBUTES,
actions,
"default_variation",
)

# testing assignment logger
assignment_event = mock_assignment_logger.assignment_events[-1]
timestamp = datetime.datetime.fromisoformat(assignment_event["timestamp"])
assert timestamp.tzinfo == datetime.timezone.utc

# testing bandit logger
bandit_event = mock_assignment_logger.bandit_events[-1]
timestamp = datetime.datetime.fromisoformat(bandit_event["timestamp"])
assert timestamp.tzinfo == datetime.timezone.utc


def test_get_bandit_action_with_subject_attributes():
# tests that allocation filtering based on subject attributes works correctly
client = get_instance()
Expand Down
35 changes: 35 additions & 0 deletions test/client_test.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import json
import datetime
import os
from time import sleep
from unittest.mock import patch
Expand Down Expand Up @@ -113,6 +114,40 @@ def test_log_assignment(mock_config_requestor, mock_logger):
assert mock_logger.log_assignment.call_count == 1


@patch("eppo_client.assignment_logger.AssignmentLogger")
@patch("eppo_client.configuration_requestor.ExperimentConfigurationRequestor")
def test_assignment_event_has_utc_timestamp(mock_config_requestor, mock_logger):
flag = Flag(
key="flag-key",
enabled=True,
variation_type=VariationType.STRING,
variations={"control": Variation(key="control", value="control")},
allocations=[
Allocation(
key="allocation",
splits=[
Split(
variation_key="control",
shards=[Shard(salt="salt", ranges=[Range(start=0, end=10000)])],
)
],
do_log=True,
)
],
total_shards=10_000,
)

mock_config_requestor.get_configuration.return_value = flag
client = EppoClient(
config_requestor=mock_config_requestor, assignment_logger=mock_logger
)
client.get_string_assignment("falg-key", "user-1", {}, "default value")

event = mock_logger.log_assignment.call_args.args[0]
timestamp = datetime.datetime.fromisoformat(event["timestamp"])
assert timestamp.tzinfo == datetime.timezone.utc


@patch("eppo_client.assignment_logger.AssignmentLogger")
@patch("eppo_client.configuration_requestor.ExperimentConfigurationRequestor")
def test_get_assignment_handles_logging_exception(mock_config_requestor, mock_logger):
Expand Down

0 comments on commit a021dc2

Please sign in to comment.