@@ -267,3 +267,75 @@ def record_lost_event(reason, data_category, quantity):
267267 assert len (lost_event_calls ) == 5
268268 for lost_event_call in lost_event_calls :
269269 assert lost_event_call == ("queue_overflow" , "trace_metric" , 1 )
270+
271+
272+ def test_metrics_sample_rate_basic (sentry_init , capture_envelopes ):
273+ sentry_init ()
274+ envelopes = capture_envelopes ()
275+
276+ sentry_sdk .metrics .count ("test.counter" , 1 , sample_rate = 0.5 )
277+ sentry_sdk .metrics .gauge ("test.gauge" , 42 , sample_rate = 0.8 )
278+ sentry_sdk .metrics .distribution ("test.distribution" , 200 , sample_rate = 1.0 )
279+
280+ get_client ().flush ()
281+ metrics = envelopes_to_metrics (envelopes )
282+
283+ assert len (metrics ) == 3
284+
285+ assert metrics [0 ]["name" ] == "test.counter"
286+ assert metrics [0 ]["attributes" ]["sentry.client_sample_rate" ] == 0.5
287+
288+ assert metrics [1 ]["name" ] == "test.gauge"
289+ assert metrics [1 ]["attributes" ]["sentry.client_sample_rate" ] == 0.8
290+
291+ assert metrics [2 ]["name" ] == "test.distribution"
292+ assert "sentry.client_sample_rate" not in metrics [2 ]["attributes" ]
293+
294+
295+ def test_metrics_sample_rate_normalization (sentry_init , capture_envelopes , monkeypatch ):
296+ sentry_init ()
297+ envelopes = capture_envelopes ()
298+ client = sentry_sdk .get_client ()
299+
300+ lost_event_calls = []
301+
302+ def record_lost_event (reason , data_category , quantity ):
303+ lost_event_calls .append ((reason , data_category , quantity ))
304+
305+ monkeypatch .setattr (client .transport , "record_lost_event" , record_lost_event )
306+
307+ sentry_sdk .metrics .count ("test.counter1" , 1 , sample_rate = 0.0 ) # <= 0
308+ sentry_sdk .metrics .count ("test.counter2" , 1 , sample_rate = - 0.5 ) # < 0
309+ sentry_sdk .metrics .count ("test.counter3" , 1 , sample_rate = 0.5 ) # > 0 but < 1.0
310+ sentry_sdk .metrics .count ("test.counter4" , 1 , sample_rate = 1.0 ) # = 1.0
311+ sentry_sdk .metrics .count ("test.counter4" , 1 , sample_rate = 1.5 ) # > 1.0
312+
313+ client .flush ()
314+ metrics = envelopes_to_metrics (envelopes )
315+
316+ assert len (metrics ) == 2
317+
318+ assert metrics [0 ]["attributes" ]["sentry.client_sample_rate" ] == 0.5
319+ assert (
320+ "sentry.client_sample_rate" not in metrics [1 ]["attributes" ]
321+ ) # 1.0 does not need a sample rate, it's implied to be 1.0
322+
323+ assert len (lost_event_calls ) == 3
324+ assert lost_event_calls [0 ] == ("invalid_sample_rate" , "trace_metric" , 1 )
325+ assert lost_event_calls [1 ] == ("invalid_sample_rate" , "trace_metric" , 1 )
326+ assert lost_event_calls [2 ] == ("invalid_sample_rate" , "trace_metric" , 1 )
327+
328+
329+ def test_metrics_no_sample_rate (sentry_init , capture_envelopes ):
330+ sentry_init ()
331+ envelopes = capture_envelopes ()
332+
333+ sentry_sdk .metrics .count ("test.counter" , 1 )
334+
335+ get_client ().flush ()
336+ metrics = envelopes_to_metrics (envelopes )
337+
338+ assert len (metrics ) == 1
339+
340+ # Should not have sample_rate attribute when not provided
341+ assert "sentry.client_sample_rate" not in metrics [0 ]["attributes" ]
0 commit comments