1010
1111from mock_clock import MockClock
1212
13- from amazon .opentelemetry .distro .sampler .aws_xray_remote_sampler import AwsXRayRemoteSampler
13+ from amazon .opentelemetry .distro .sampler .aws_xray_remote_sampler import AwsXRayRemoteSampler , _AwsXRayRemoteSampler
1414from opentelemetry .sdk .resources import Resource
15+ from opentelemetry .sdk .trace import Tracer , TracerProvider
1516from opentelemetry .sdk .trace .sampling import Decision
1617
1718TEST_DIR = os .path .dirname (os .path .realpath (__file__ ))
@@ -55,27 +56,31 @@ def setUp(self):
5556 def tearDown (self ):
5657 # Clean up timers
5758 if self .rs is not None :
58- self .rs ._rules_timer .cancel ()
59- self .rs ._targets_timer .cancel ()
59+ self .rs ._root . _root . _rules_timer .cancel ()
60+ self .rs ._root . _root . _targets_timer .cancel ()
6061
6162 def test_create_remote_sampler_with_empty_resource (self ):
6263 self .rs = AwsXRayRemoteSampler (resource = Resource .get_empty ())
63- self .assertIsNotNone (self .rs ._rules_timer )
64- self .assertEqual (self .rs ._AwsXRayRemoteSampler__polling_interval , 300 )
65- self .assertIsNotNone (self .rs ._AwsXRayRemoteSampler__xray_client )
66- self .assertIsNotNone (self .rs ._AwsXRayRemoteSampler__resource )
67- self .assertTrue (len (self .rs ._AwsXRayRemoteSampler__client_id ), 24 )
64+ self .assertIsNotNone (self .rs ._root . _root . _rules_timer )
65+ self .assertEqual (self .rs ._root . _root . _AwsXRayRemoteSampler__polling_interval , 300 )
66+ self .assertIsNotNone (self .rs ._root . _root . _AwsXRayRemoteSampler__xray_client )
67+ self .assertIsNotNone (self .rs ._root . _root . _AwsXRayRemoteSampler__resource )
68+ self .assertTrue (len (self .rs ._root . _root . _AwsXRayRemoteSampler__client_id ), 24 )
6869
6970 def test_create_remote_sampler_with_populated_resource (self ):
7071 self .rs = AwsXRayRemoteSampler (
7172 resource = Resource .create ({"service.name" : "test-service-name" , "cloud.platform" : "test-cloud-platform" })
7273 )
73- self .assertIsNotNone (self .rs ._rules_timer )
74- self .assertEqual (self .rs ._AwsXRayRemoteSampler__polling_interval , 300 )
75- self .assertIsNotNone (self .rs ._AwsXRayRemoteSampler__xray_client )
76- self .assertIsNotNone (self .rs ._AwsXRayRemoteSampler__resource )
77- self .assertEqual (self .rs ._AwsXRayRemoteSampler__resource .attributes ["service.name" ], "test-service-name" )
78- self .assertEqual (self .rs ._AwsXRayRemoteSampler__resource .attributes ["cloud.platform" ], "test-cloud-platform" )
74+ self .assertIsNotNone (self .rs ._root ._root ._rules_timer )
75+ self .assertEqual (self .rs ._root ._root ._AwsXRayRemoteSampler__polling_interval , 300 )
76+ self .assertIsNotNone (self .rs ._root ._root ._AwsXRayRemoteSampler__xray_client )
77+ self .assertIsNotNone (self .rs ._root ._root ._AwsXRayRemoteSampler__resource )
78+ self .assertEqual (
79+ self .rs ._root ._root ._AwsXRayRemoteSampler__resource .attributes ["service.name" ], "test-service-name"
80+ )
81+ self .assertEqual (
82+ self .rs ._root ._root ._AwsXRayRemoteSampler__resource .attributes ["cloud.platform" ], "test-cloud-platform"
83+ )
7984
8085 def test_create_remote_sampler_with_all_fields_populated (self ):
8186 self .rs = AwsXRayRemoteSampler (
@@ -84,35 +89,39 @@ def test_create_remote_sampler_with_all_fields_populated(self):
8489 polling_interval = 120 ,
8590 log_level = DEBUG ,
8691 )
87- self .assertIsNotNone (self .rs ._rules_timer )
88- self .assertEqual (self .rs ._AwsXRayRemoteSampler__polling_interval , 120 )
89- self .assertIsNotNone (self .rs ._AwsXRayRemoteSampler__xray_client )
90- self .assertIsNotNone (self .rs ._AwsXRayRemoteSampler__resource )
92+ self .assertIsNotNone (self .rs ._root . _root . _rules_timer )
93+ self .assertEqual (self .rs ._root . _root . _AwsXRayRemoteSampler__polling_interval , 120 )
94+ self .assertIsNotNone (self .rs ._root . _root . _AwsXRayRemoteSampler__xray_client )
95+ self .assertIsNotNone (self .rs ._root . _root . _AwsXRayRemoteSampler__resource )
9196 self .assertEqual (
92- self .rs ._AwsXRayRemoteSampler__xray_client ._AwsXRaySamplingClient__get_sampling_rules_endpoint ,
97+ self .rs ._root . _root . _AwsXRayRemoteSampler__xray_client ._AwsXRaySamplingClient__get_sampling_rules_endpoint ,
9398 "http://abc.com/GetSamplingRules" ,
9499 )
95- self .assertEqual (self .rs ._AwsXRayRemoteSampler__resource .attributes ["service.name" ], "test-service-name" )
96- self .assertEqual (self .rs ._AwsXRayRemoteSampler__resource .attributes ["cloud.platform" ], "test-cloud-platform" )
100+ self .assertEqual (
101+ self .rs ._root ._root ._AwsXRayRemoteSampler__resource .attributes ["service.name" ], "test-service-name"
102+ )
103+ self .assertEqual (
104+ self .rs ._root ._root ._AwsXRayRemoteSampler__resource .attributes ["cloud.platform" ], "test-cloud-platform"
105+ )
97106
98107 @patch ("requests.Session.post" , side_effect = mocked_requests_get )
99108 @patch ("amazon.opentelemetry.distro.sampler.aws_xray_remote_sampler.DEFAULT_TARGET_POLLING_INTERVAL_SECONDS" , 2 )
100109 def test_update_sampling_rules_and_targets_with_pollers_and_should_sample (self , mock_post = None ):
101110 self .rs = AwsXRayRemoteSampler (
102111 resource = Resource .create ({"service.name" : "test-service-name" , "cloud.platform" : "test-cloud-platform" })
103112 )
104- self .assertEqual (self .rs ._AwsXRayRemoteSampler__target_polling_interval , 2 )
113+ self .assertEqual (self .rs ._root . _root . _AwsXRayRemoteSampler__target_polling_interval , 2 )
105114
106115 time .sleep (1.0 )
107116 self .assertEqual (
108- self .rs ._AwsXRayRemoteSampler__rule_cache ._RuleCache__rule_appliers [0 ].sampling_rule .RuleName ,
117+ self .rs ._root . _root . _AwsXRayRemoteSampler__rule_cache ._RuleCache__rule_appliers [0 ].sampling_rule .RuleName ,
109118 "test" ,
110119 )
111120 self .assertEqual (self .rs .should_sample (None , 0 , "name" , attributes = {"abc" : "1234" }).decision , Decision .DROP )
112121
113122 # wait 2 more seconds since targets polling was patched to 2 seconds (rather than 10s)
114123 time .sleep (2.0 )
115- self .assertEqual (self .rs ._AwsXRayRemoteSampler__target_polling_interval , 1000 )
124+ self .assertEqual (self .rs ._root . _root . _AwsXRayRemoteSampler__target_polling_interval , 1000 )
116125 self .assertEqual (
117126 self .rs .should_sample (None , 0 , "name" , attributes = {"abc" : "1234" }).decision ,
118127 Decision .RECORD_AND_SAMPLE ,
@@ -162,9 +171,9 @@ def test_multithreading_with_large_reservoir_with_otel_sdk(self, mock_post=None)
162171 threads [idx ].join ()
163172 sum_sampled += sampled_array [idx ]
164173
165- test_rule_applier = self .rs ._AwsXRayRemoteSampler__rule_cache ._RuleCache__rule_appliers [0 ]
174+ test_rule_applier = self .rs ._root . _root . _AwsXRayRemoteSampler__rule_cache ._RuleCache__rule_appliers [0 ]
166175 self .assertEqual (
167- test_rule_applier ._SamplingRuleApplier__reservoir_sampler ._root . _RateLimitingSampler__reservoir ._quota ,
176+ test_rule_applier ._SamplingRuleApplier__reservoir_sampler ._RateLimitingSampler__reservoir ._quota ,
168177 100000 ,
169178 )
170179 self .assertEqual (sum_sampled , 100000 )
@@ -183,19 +192,19 @@ def test_multithreading_with_some_reservoir_with_otel_sdk(self, mock_post=None):
183192 # which will eat up more than 1 second of reservoir. Using MockClock we can freeze time
184193 # and pretend all thread jobs start and end at the exact same time,
185194 # assume and test exactly 1 second of reservoir (100 quota) only
186- mock_clock : MockClock = self .rs ._clock
195+ mock_clock : MockClock = self .rs ._root . _root . _clock
187196
188197 time .sleep (1.0 )
189198 mock_clock .add_time (1.0 )
190- self .assertEqual (mock_clock .now (), self .rs ._clock .now ())
199+ self .assertEqual (mock_clock .now (), self .rs ._root . _root . _clock .now ())
191200 self .assertEqual (
192201 self .rs .should_sample (None , 0 , "name" , attributes = attributes ).decision , Decision .RECORD_AND_SAMPLE
193202 )
194203
195204 # wait 2 more seconds since targets polling was patched to 2 seconds (rather than 10s)
196205 time .sleep (2.0 )
197206 mock_clock .add_time (2.0 )
198- self .assertEqual (mock_clock .now (), self .rs ._clock .now ())
207+ self .assertEqual (mock_clock .now (), self .rs ._root . _root . _clock .now ())
199208
200209 number_of_spans = 100
201210 thread_count = 1000
@@ -219,9 +228,79 @@ def test_multithreading_with_some_reservoir_with_otel_sdk(self, mock_post=None):
219228 threads [idx ].join ()
220229 sum_sampled += sampled_array [idx ]
221230
222- default_rule_applier = self .rs ._AwsXRayRemoteSampler__rule_cache ._RuleCache__rule_appliers [1 ]
231+ default_rule_applier = self .rs ._root . _root . _AwsXRayRemoteSampler__rule_cache ._RuleCache__rule_appliers [1 ]
223232 self .assertEqual (
224- default_rule_applier ._SamplingRuleApplier__reservoir_sampler ._root . _RateLimitingSampler__reservoir ._quota ,
233+ default_rule_applier ._SamplingRuleApplier__reservoir_sampler ._RateLimitingSampler__reservoir ._quota ,
225234 100 ,
226235 )
227236 self .assertEqual (sum_sampled , 100 )
237+
238+ def test_get_description (self ) -> str :
239+ self .rs : AwsXRayRemoteSampler = AwsXRayRemoteSampler (resource = Resource .create ({"service.name" : "dummy_name" }))
240+ self .assertEqual (
241+ self .rs .get_description (),
242+ "AwsXRayRemoteSampler{root:ParentBased{root:_AwsXRayRemoteSampler{remote sampling with AWS X-Ray},remoteParentSampled:AlwaysOnSampler,remoteParentNotSampled:AlwaysOffSampler,localParentSampled:AlwaysOnSampler,localParentNotSampled:AlwaysOffSampler}}" , # noqa: E501
243+ )
244+
245+ @patch ("requests.Session.post" , side_effect = mocked_requests_get )
246+ def test_parent_based_xray_sampler_creates_updates_statistics_once_for_one_parent_span_with_two_children (
247+ self , mock_post = None
248+ ):
249+ self .rs : AwsXRayRemoteSampler = AwsXRayRemoteSampler (
250+ resource = Resource .create ({"service.name" : "use-default-sample-all-rule" })
251+ )
252+ time .sleep (1.0 )
253+
254+ provider = TracerProvider (sampler = self .rs )
255+ tracer : Tracer = provider .get_tracer ("test_tracer_1" )
256+
257+ # child1 and child2 are child spans of root parent0
258+ # For AwsXRayRemoteSampler (ParentBased), expect only parent0 to update statistics
259+ with tracer .start_as_current_span ("parent0" ) as _ :
260+ with tracer .start_as_current_span ("child1" ) as _ :
261+ pass
262+ with tracer .start_as_current_span ("child2" ) as _ :
263+ pass
264+ default_rule_applier = self .rs ._root ._root ._AwsXRayRemoteSampler__rule_cache ._RuleCache__rule_appliers [1 ]
265+ self .assertEqual (
266+ default_rule_applier ._SamplingRuleApplier__statistics .RequestCount ,
267+ 1 ,
268+ )
269+ self .assertEqual (
270+ default_rule_applier ._SamplingRuleApplier__statistics .SampleCount ,
271+ 1 ,
272+ )
273+
274+ @patch ("requests.Session.post" , side_effect = mocked_requests_get )
275+ def test_non_parent_based_xray_sampler_creates_updates_statistics_thrice_for_one_parent_span_with_two_children (
276+ self , mock_post = None
277+ ):
278+ non_parent_based_xray_sampler : _AwsXRayRemoteSampler = _AwsXRayRemoteSampler (
279+ resource = Resource .create ({"service.name" : "use-default-sample-all-rule" })
280+ )
281+ time .sleep (1.0 )
282+
283+ provider = TracerProvider (sampler = non_parent_based_xray_sampler )
284+ tracer : Tracer = provider .get_tracer ("test_tracer_2" )
285+
286+ # child1 and child2 are child spans of root parent0
287+ # For _AwsXRayRemoteSampler (Non-ParentBased), expect all 3 spans to update statistics
288+ with tracer .start_as_current_span ("parent0" ) as _ :
289+ with tracer .start_as_current_span ("child1" ) as _ :
290+ pass
291+ with tracer .start_as_current_span ("child2" ) as _ :
292+ pass
293+ default_rule_applier = (
294+ non_parent_based_xray_sampler ._AwsXRayRemoteSampler__rule_cache ._RuleCache__rule_appliers [1 ]
295+ )
296+ self .assertEqual (
297+ default_rule_applier ._SamplingRuleApplier__statistics .RequestCount ,
298+ 3 ,
299+ )
300+ self .assertEqual (
301+ default_rule_applier ._SamplingRuleApplier__statistics .SampleCount ,
302+ 3 ,
303+ )
304+
305+ non_parent_based_xray_sampler ._rules_timer .cancel ()
306+ non_parent_based_xray_sampler ._targets_timer .cancel ()
0 commit comments