11import json
2- import logging
32import threading
43import time
54from time import sleep
65from typing import Any , Dict
76
87from .config import RemoteEvaluationConfig
8+ from .fetch_options import FetchOptions
99from ..connection_pool import HTTPConnectionPool
1010from ..exception import FetchException
1111from ..user import User
@@ -32,26 +32,24 @@ def __init__(self, api_key, config=None):
3232 raise ValueError ("Experiment API key is empty" )
3333 self .api_key = api_key
3434 self .config = config or RemoteEvaluationConfig ()
35- self .logger = logging .getLogger ("Amplitude" )
36- self .logger .addHandler (logging .StreamHandler ())
37- if self .config .debug :
38- self .logger .setLevel (logging .DEBUG )
35+ self .logger = self .config .logger
3936 self .__setup_connection_pool ()
4037
41- def fetch_v2 (self , user : User ):
38+ def fetch_v2 (self , user : User , fetch_options : FetchOptions = None ):
4239 """
4340 Fetch all variants for a user synchronously. This method will automatically retry if configured, and throw if
4441 all retries fail. This function differs from fetch as it will return a default variant object if the flag
4542 was evaluated but the user was not assigned (i.e. off).
4643
4744 Parameters:
4845 user (User): The Experiment User to fetch variants for.
46+ fetch_options (FetchOptions): The Fetch Options
4947
5048 Returns:
5149 Variants Dictionary.
5250 """
5351 try :
54- return self .__fetch_internal (user )
52+ return self .__fetch_internal (user , fetch_options )
5553 except Exception as e :
5654 self .logger .error (f"[Experiment] Failed to fetch variants: { e } " )
5755 raise e
@@ -67,17 +65,18 @@ def fetch_async_v2(self, user: User, callback=None):
6765 thread .start ()
6866
6967 @deprecated ("Use fetch_v2" )
70- def fetch (self , user : User ):
68+ def fetch (self , user : User , fetch_options : FetchOptions = None ):
7169 """
7270 Fetch all variants for a user synchronous. This method will automatically retry if configured.
7371 Parameters:
7472 user (User): The Experiment User
73+ fetch_options (FetchOptions): The Fetch Options
7574
7675 Returns:
7776 Variants Dictionary.
7877 """
7978 try :
80- variants = self .fetch_v2 (user )
79+ variants = self .fetch_v2 (user , fetch_options )
8180 return self .__filter_default_variants (variants )
8281 except Exception :
8382 return {}
@@ -107,16 +106,16 @@ def __fetch_async_internal(self, user, callback):
107106 callback (user , {}, e )
108107 return {}
109108
110- def __fetch_internal (self , user ):
109+ def __fetch_internal (self , user , fetch_options : FetchOptions = None ):
111110 self .logger .debug (f"[Experiment] Fetching variants for user: { user } " )
112111 try :
113- return self .__do_fetch (user )
112+ return self .__do_fetch (user , fetch_options )
114113 except Exception as e :
115114 self .logger .error (f"[Experiment] Fetch failed: { e } " )
116115 if self .__should_retry_fetch (e ):
117- return self .__retry_fetch (user )
116+ return self .__retry_fetch (user , fetch_options )
118117
119- def __retry_fetch (self , user ):
118+ def __retry_fetch (self , user , fetch_options : FetchOptions = None ):
120119 if self .config .fetch_retries == 0 :
121120 return {}
122121 self .logger .debug ("[Experiment] Retrying fetch" )
@@ -125,21 +124,26 @@ def __retry_fetch(self, user):
125124 for i in range (self .config .fetch_retries ):
126125 sleep (delay_millis / 1000.0 )
127126 try :
128- return self .__do_fetch (user )
127+ return self .__do_fetch (user , fetch_options )
129128 except Exception as e :
130129 self .logger .error (f"[Experiment] Retry failed: { e } " )
131130 err = e
132131 delay_millis = min (delay_millis * self .config .fetch_retry_backoff_scalar ,
133132 self .config .fetch_retry_backoff_max_millis )
134133 raise err
135134
136- def __do_fetch (self , user ):
135+ def __do_fetch (self , user , fetch_options : FetchOptions = None ):
137136 start = time .time ()
138137 user_context = self .__add_context (user )
139138 headers = {
140139 'Authorization' : f"Api-Key { self .api_key } " ,
141140 'Content-Type' : 'application/json;charset=utf-8'
142141 }
142+ if fetch_options and fetch_options .tracksAssignment is not None :
143+ headers ['X-Amp-Exp-Track' ] = "track" if fetch_options .tracksAssignment else "no-track"
144+ if fetch_options and fetch_options .tracksExposure is not None :
145+ headers ['X-Amp-Exp-Exposure-Track' ] = "track" if fetch_options .tracksExposure else "no-track"
146+
143147 conn = self ._connection_pool .acquire ()
144148 body = user_context .to_json ().encode ('utf8' )
145149 if len (body ) > 8000 :
0 commit comments