@@ -6822,6 +6822,161 @@ def test_error_upsampling_with_partial_allowlist(self):
6822
6822
# Expect upsampling since any project is allowlisted (both events upsampled: 10 + 10 = 20)
6823
6823
assert response .data ["data" ][0 ]["count()" ] == 20
6824
6824
6825
+ def test_sample_count_with_allowlisted_project (self ):
6826
+ """Test that sample_count() returns raw sample count (not upsampled) for allowlisted projects."""
6827
+ # Set up allowlisted project
6828
+ with self .options ({"issues.client_error_sampling.project_allowlist" : [self .project .id ]}):
6829
+ # Store error event with error_sampling context
6830
+ self .store_event (
6831
+ data = {
6832
+ "event_id" : "a" * 32 ,
6833
+ "message" : "Error event for sample_count" ,
6834
+ "type" : "error" ,
6835
+ "exception" : [{"type" : "ValueError" , "value" : "Something went wrong" }],
6836
+ "timestamp" : self .ten_mins_ago_iso ,
6837
+ "fingerprint" : ["group1" ],
6838
+ "contexts" : {"error_sampling" : {"client_sample_rate" : 0.1 }},
6839
+ },
6840
+ project_id = self .project .id ,
6841
+ )
6842
+
6843
+ # Store error event without error_sampling context (sample_weight = null should count as 1)
6844
+ self .store_event (
6845
+ data = {
6846
+ "event_id" : "a1" * 16 ,
6847
+ "message" : "Error event without sampling" ,
6848
+ "type" : "error" ,
6849
+ "exception" : [{"type" : "ValueError" , "value" : "Something else went wrong" }],
6850
+ "timestamp" : self .ten_mins_ago_iso ,
6851
+ "fingerprint" : ["group1_no_sampling" ],
6852
+ },
6853
+ project_id = self .project .id ,
6854
+ )
6855
+
6856
+ # Test with errors dataset - sample_count() should return raw count, not upsampled
6857
+ query = {
6858
+ "field" : ["sample_count()" ],
6859
+ "statsPeriod" : "2h" ,
6860
+ "query" : "event.type:error" ,
6861
+ "dataset" : "errors" ,
6862
+ }
6863
+ response = self .do_request (query )
6864
+ assert response .status_code == 200 , response .content
6865
+ # Expect sample_count to return raw count: 2 events (not upsampled 11)
6866
+ assert response .data ["data" ][0 ]["sample_count()" ] == 2
6867
+
6868
+ # Check meta information
6869
+ meta = response .data ["meta" ]
6870
+ assert "fields" in meta
6871
+ assert "sample_count()" in meta ["fields" ]
6872
+ assert meta ["fields" ]["sample_count()" ] == "integer"
6873
+
6874
+ def test_sample_eps_with_allowlisted_project (self ):
6875
+ """Test that sample_eps() returns raw sample rate (not upsampled) for allowlisted projects."""
6876
+ # Set up allowlisted project
6877
+ with self .options ({"issues.client_error_sampling.project_allowlist" : [self .project .id ]}):
6878
+ # Store error event with error_sampling context
6879
+ self .store_event (
6880
+ data = {
6881
+ "event_id" : "b" * 32 ,
6882
+ "message" : "Error event for sample_eps" ,
6883
+ "type" : "error" ,
6884
+ "exception" : [{"type" : "ValueError" , "value" : "Something went wrong" }],
6885
+ "timestamp" : self .ten_mins_ago_iso ,
6886
+ "fingerprint" : ["group2" ],
6887
+ "contexts" : {"error_sampling" : {"client_sample_rate" : 0.1 }},
6888
+ },
6889
+ project_id = self .project .id ,
6890
+ )
6891
+
6892
+ # Store error event without error_sampling context (sample_weight = null should count as 1)
6893
+ self .store_event (
6894
+ data = {
6895
+ "event_id" : "b1" * 16 ,
6896
+ "message" : "Error event without sampling for sample_eps" ,
6897
+ "type" : "error" ,
6898
+ "exception" : [{"type" : "ValueError" , "value" : "Something else went wrong" }],
6899
+ "timestamp" : self .ten_mins_ago_iso ,
6900
+ "fingerprint" : ["group2_no_sampling" ],
6901
+ },
6902
+ project_id = self .project .id ,
6903
+ )
6904
+
6905
+ # Test with errors dataset - sample_eps() should return raw rate, not upsampled
6906
+ query = {
6907
+ "field" : ["sample_eps()" ],
6908
+ "statsPeriod" : "2h" ,
6909
+ "query" : "event.type:error" ,
6910
+ "dataset" : "errors" ,
6911
+ }
6912
+ response = self .do_request (query )
6913
+ assert response .status_code == 200 , response .content
6914
+ # Expect sample_eps to return raw rate: 2 events / 7200 seconds = 2/7200
6915
+ expected_sample_eps = 2 / 7200
6916
+ actual_sample_eps = response .data ["data" ][0 ]["sample_eps()" ]
6917
+ assert (
6918
+ abs (actual_sample_eps - expected_sample_eps ) < 0.0001
6919
+ ) # Allow small rounding differences
6920
+
6921
+ # Check meta information
6922
+ meta = response .data ["meta" ]
6923
+ assert "fields" in meta
6924
+ assert "sample_eps()" in meta ["fields" ]
6925
+ assert meta ["fields" ]["sample_eps()" ] == "rate"
6926
+
6927
+ def test_sample_epm_with_allowlisted_project (self ):
6928
+ """Test that sample_epm() returns raw sample rate (not upsampled) for allowlisted projects."""
6929
+ # Set up allowlisted project
6930
+ with self .options ({"issues.client_error_sampling.project_allowlist" : [self .project .id ]}):
6931
+ # Store error event with error_sampling context
6932
+ self .store_event (
6933
+ data = {
6934
+ "event_id" : "c" * 32 ,
6935
+ "message" : "Error event for sample_epm" ,
6936
+ "type" : "error" ,
6937
+ "exception" : [{"type" : "ValueError" , "value" : "Something went wrong" }],
6938
+ "timestamp" : self .ten_mins_ago_iso ,
6939
+ "fingerprint" : ["group3" ],
6940
+ "contexts" : {"error_sampling" : {"client_sample_rate" : 0.1 }},
6941
+ },
6942
+ project_id = self .project .id ,
6943
+ )
6944
+
6945
+ # Store error event without error_sampling context (sample_weight = null should count as 1)
6946
+ self .store_event (
6947
+ data = {
6948
+ "event_id" : "c1" * 16 ,
6949
+ "message" : "Error event without sampling for sample_epm" ,
6950
+ "type" : "error" ,
6951
+ "exception" : [{"type" : "ValueError" , "value" : "Something else went wrong" }],
6952
+ "timestamp" : self .ten_mins_ago_iso ,
6953
+ "fingerprint" : ["group3_no_sampling" ],
6954
+ },
6955
+ project_id = self .project .id ,
6956
+ )
6957
+
6958
+ # Test with errors dataset - sample_epm() should return raw rate, not upsampled
6959
+ query = {
6960
+ "field" : ["sample_epm()" ],
6961
+ "statsPeriod" : "2h" ,
6962
+ "query" : "event.type:error" ,
6963
+ "dataset" : "errors" ,
6964
+ }
6965
+ response = self .do_request (query )
6966
+ assert response .status_code == 200 , response .content
6967
+ # Expect sample_epm to return raw rate: 2 events / 120 minutes = 2/120
6968
+ expected_sample_epm = 2 / 120
6969
+ actual_sample_epm = response .data ["data" ][0 ]["sample_epm()" ]
6970
+ assert (
6971
+ abs (actual_sample_epm - expected_sample_epm ) < 0.001
6972
+ ) # Allow small rounding differences
6973
+
6974
+ # Check meta information
6975
+ meta = response .data ["meta" ]
6976
+ assert "fields" in meta
6977
+ assert "sample_epm()" in meta ["fields" ]
6978
+ assert meta ["fields" ]["sample_epm()" ] == "rate"
6979
+
6825
6980
def test_is_status (self ):
6826
6981
self .store_event (
6827
6982
data = {
0 commit comments