@@ -96,9 +96,17 @@ def test_no_groups_found(self, mock_seer_request: MagicMock, mock_metrics_incr:
96
96
tags = {"response_status" : 200 , "outcome" : "no_similar_groups" },
97
97
)
98
98
99
+ @mock .patch (
100
+ "sentry.seer.similarity.similar_issues.seer_similarity_circuit_breaker.record_error"
101
+ )
99
102
@mock .patch ("sentry.seer.similarity.similar_issues.metrics.incr" )
100
103
@mock .patch ("sentry.seer.similarity.similar_issues.seer_grouping_connection_pool.urlopen" )
101
- def test_bad_response_data (self , mock_seer_request : MagicMock , mock_metrics_incr : MagicMock ):
104
+ def test_bad_response_data (
105
+ self ,
106
+ mock_seer_request : MagicMock ,
107
+ mock_metrics_incr : MagicMock ,
108
+ mock_record_circuit_breaker_error : MagicMock ,
109
+ ):
102
110
cases : list [tuple [Any , str ]] = [
103
111
(None , "AttributeError" ),
104
112
([], "AttributeError" ),
@@ -139,14 +147,22 @@ def test_bad_response_data(self, mock_seer_request: MagicMock, mock_metrics_incr
139
147
sample_rate = SIMILARITY_REQUEST_METRIC_SAMPLE_RATE ,
140
148
tags = {"response_status" : 200 , "outcome" : "error" , "error" : expected_error },
141
149
)
150
+ assert mock_record_circuit_breaker_error .call_count == 0
142
151
143
152
mock_metrics_incr .reset_mock ()
144
153
154
+ @mock .patch (
155
+ "sentry.seer.similarity.similar_issues.seer_similarity_circuit_breaker.record_error"
156
+ )
145
157
@mock .patch ("sentry.seer.similarity.similar_issues.metrics.incr" )
146
158
@mock .patch ("sentry.seer.similarity.similar_issues.logger" )
147
159
@mock .patch ("sentry.seer.similarity.similar_issues.seer_grouping_connection_pool.urlopen" )
148
160
def test_redirect (
149
- self , mock_seer_request : MagicMock , mock_logger : MagicMock , mock_metrics_incr : MagicMock
161
+ self ,
162
+ mock_seer_request : MagicMock ,
163
+ mock_logger : MagicMock ,
164
+ mock_metrics_incr : MagicMock ,
165
+ mock_record_circuit_breaker_error : MagicMock ,
150
166
):
151
167
mock_seer_request .return_value = HTTPResponse (
152
168
status = 308 , headers = {"location" : "/new/and/improved/endpoint/" }
@@ -161,12 +177,20 @@ def test_redirect(
161
177
sample_rate = SIMILARITY_REQUEST_METRIC_SAMPLE_RATE ,
162
178
tags = {"response_status" : 308 , "outcome" : "error" , "error" : "Redirect" },
163
179
)
180
+ assert mock_record_circuit_breaker_error .call_count == 0
164
181
182
+ @mock .patch (
183
+ "sentry.seer.similarity.similar_issues.seer_similarity_circuit_breaker.record_error"
184
+ )
165
185
@mock .patch ("sentry.seer.similarity.similar_issues.metrics.incr" )
166
186
@mock .patch ("sentry.seer.similarity.similar_issues.logger" )
167
187
@mock .patch ("sentry.seer.similarity.similar_issues.seer_grouping_connection_pool.urlopen" )
168
188
def test_request_error (
169
- self , mock_seer_request : MagicMock , mock_logger : MagicMock , mock_metrics_incr : MagicMock
189
+ self ,
190
+ mock_seer_request : MagicMock ,
191
+ mock_logger : MagicMock ,
192
+ mock_metrics_incr : MagicMock ,
193
+ mock_record_circuit_breaker_error : MagicMock ,
170
194
):
171
195
for request_error , expected_error_tag in [
172
196
(TimeoutError , "TimeoutError" ),
@@ -192,25 +216,44 @@ def test_request_error(
192
216
sample_rate = SIMILARITY_REQUEST_METRIC_SAMPLE_RATE ,
193
217
tags = {"outcome" : "error" , "error" : expected_error_tag },
194
218
)
219
+ assert mock_record_circuit_breaker_error .call_count == 1
220
+
221
+ mock_logger .warning .reset_mock ()
222
+ mock_metrics_incr .reset_mock ()
223
+ mock_record_circuit_breaker_error .reset_mock ()
195
224
225
+ @mock .patch (
226
+ "sentry.seer.similarity.similar_issues.seer_similarity_circuit_breaker.record_error"
227
+ )
196
228
@mock .patch ("sentry.seer.similarity.similar_issues.metrics.incr" )
197
229
@mock .patch ("sentry.seer.similarity.similar_issues.logger" )
198
230
@mock .patch ("sentry.seer.similarity.similar_issues.seer_grouping_connection_pool.urlopen" )
199
231
def test_error_status (
200
- self , mock_seer_request : MagicMock , mock_logger : MagicMock , mock_metrics_incr : MagicMock
232
+ self ,
233
+ mock_seer_request : MagicMock ,
234
+ mock_logger : MagicMock ,
235
+ mock_metrics_incr : MagicMock ,
236
+ mock_record_circuit_breaker_error : MagicMock ,
201
237
):
202
- mock_seer_request .return_value = HTTPResponse ("No soup for you" , status = 403 )
238
+ for response , status , counts_for_circuit_breaker in [
239
+ ("No soup for you" , 403 , False ),
240
+ ("No soup, period" , 500 , True ),
241
+ ]:
242
+ mock_seer_request .return_value = HTTPResponse (response , status = status )
203
243
204
- assert get_similarity_data_from_seer (self .request_params ) == []
205
- mock_logger .error .assert_called_with (
206
- f"Received 403 when calling Seer endpoint { SEER_SIMILAR_ISSUES_URL } ." ,
207
- extra = {"response_data" : "No soup for you" },
208
- )
209
- mock_metrics_incr .assert_any_call (
210
- "seer.similar_issues_request" ,
211
- sample_rate = SIMILARITY_REQUEST_METRIC_SAMPLE_RATE ,
212
- tags = {"response_status" : 403 , "outcome" : "error" , "error" : "RequestError" },
213
- )
244
+ assert get_similarity_data_from_seer (self .request_params ) == []
245
+ mock_logger .error .assert_called_with (
246
+ f"Received { status } when calling Seer endpoint { SEER_SIMILAR_ISSUES_URL } ." ,
247
+ extra = {"response_data" : response },
248
+ )
249
+ mock_metrics_incr .assert_any_call (
250
+ "seer.similar_issues_request" ,
251
+ sample_rate = SIMILARITY_REQUEST_METRIC_SAMPLE_RATE ,
252
+ tags = {"response_status" : status , "outcome" : "error" , "error" : "RequestError" },
253
+ )
254
+ assert mock_record_circuit_breaker_error .call_count == (
255
+ 1 if counts_for_circuit_breaker else 0
256
+ )
214
257
215
258
@mock .patch ("sentry.seer.similarity.similar_issues.seer_grouping_connection_pool.urlopen" )
216
259
def test_returns_sorted_results (self , mock_seer_request : MagicMock ):
0 commit comments