1212use Sentry \HttpClient \HttpClientInterface ;
1313use Sentry \HttpClient \Response ;
1414use Sentry \Options ;
15+ use Sentry \Profiling \Profile ;
1516use Sentry \Serializer \PayloadSerializerInterface ;
1617use Sentry \Transport \HttpTransport ;
1718use Sentry \Transport \ResultStatus ;
@@ -25,7 +26,7 @@ final class HttpTransportTest extends TestCase
2526 private $ logger ;
2627
2728 /**
28- * @var MockObject&HttpAsyncClientInterface
29+ * @var MockObject&HttpClientInterface
2930 */
3031 private $ httpClient ;
3132
@@ -180,7 +181,7 @@ public function testSendFailsDueToHttpClientException(): void
180181 $ this ->assertSame (ResultStatus::failed (), $ result ->getStatus ());
181182 }
182183
183- public function testSendFailsDueToCulrError (): void
184+ public function testSendFailsDueToCurlError (): void
184185 {
185186 $ event = Event::createEvent ();
186187
@@ -263,6 +264,105 @@ public function testSendFailsDueToExceedingRateLimits(): void
263264 $ this ->assertSame (ResultStatus::rateLimit (), $ result ->getStatus ());
264265 }
265266
267+ /**
268+ * @group time-sensitive
269+ */
270+ public function testDropsProfileAndSendsTransactionWhenProfileRateLimited (): void
271+ {
272+ ClockMock::withClockMock (1644105600 );
273+
274+ $ transport = new HttpTransport (
275+ new Options ([
'dsn ' =>
'http://[email protected] /1 ' ]),
276+ $ this ->httpClient ,
277+ $ this ->payloadSerializer ,
278+ $ this ->logger
279+ );
280+
281+ $ event = Event::createTransaction ();
282+ $ event ->setSdkMetadata ('profile ' , new Profile ());
283+
284+ $ this ->payloadSerializer ->expects ($ this ->exactly (2 ))
285+ ->method ('serialize ' )
286+ ->willReturn ('{"foo":"bar"} ' );
287+
288+ $ this ->httpClient ->expects ($ this ->exactly (2 ))
289+ ->method ('sendRequest ' )
290+ ->willReturnOnConsecutiveCalls (
291+ new Response (429 , ['X-Sentry-Rate-Limits ' => ['60:profile:key ' ]], '' ),
292+ new Response (200 , [], '' )
293+ );
294+
295+ // First request is rate limited because of profiles
296+ $ result = $ transport ->send ($ event );
297+
298+ $ this ->assertEquals (ResultStatus::rateLimit (), $ result ->getStatus ());
299+
300+ // profile information is still present
301+ $ this ->assertNotNull ($ event ->getSdkMetadata ('profile ' ));
302+
303+ $ event = Event::createTransaction ();
304+ $ event ->setSdkMetadata ('profile ' , new Profile ());
305+
306+ $ this ->logger ->expects ($ this ->once ())
307+ ->method ('warning ' )
308+ ->with (
309+ $ this ->stringContains ('Rate limit exceeded for sending requests of type "profile". ' ),
310+ ['event ' => $ event ]
311+ );
312+
313+ $ result = $ transport ->send ($ event );
314+
315+ // Sending transaction is successful because only profiles are rate limited
316+ $ this ->assertEquals (ResultStatus::success (), $ result ->getStatus ());
317+
318+ // profile information is removed because it was rate limited
319+ $ this ->assertNull ($ event ->getSdkMetadata ('profile ' ));
320+ }
321+
322+ /**
323+ * @group time-sensitive
324+ */
325+ public function testCheckInsAreRateLimited (): void
326+ {
327+ ClockMock::withClockMock (1644105600 );
328+
329+ $ transport = new HttpTransport (
330+ new Options ([
'dsn ' =>
'http://[email protected] /1 ' ]),
331+ $ this ->httpClient ,
332+ $ this ->payloadSerializer ,
333+ $ this ->logger
334+ );
335+
336+ $ event = Event::createCheckIn ();
337+
338+ $ this ->payloadSerializer ->expects ($ this ->exactly (1 ))
339+ ->method ('serialize ' )
340+ ->willReturn ('{"foo":"bar"} ' );
341+
342+ $ this ->httpClient ->expects ($ this ->exactly (1 ))
343+ ->method ('sendRequest ' )
344+ ->willReturn (
345+ new Response (429 , ['X-Sentry-Rate-Limits ' => ['60:monitor:key ' ]], '' )
346+ );
347+
348+ $ result = $ transport ->send ($ event );
349+
350+ $ this ->assertEquals (ResultStatus::rateLimit (), $ result ->getStatus ());
351+
352+ $ event = Event::createCheckIn ();
353+
354+ $ this ->logger ->expects ($ this ->once ())
355+ ->method ('warning ' )
356+ ->with (
357+ $ this ->stringContains ('Rate limit exceeded for sending requests of type "check_in". ' ),
358+ ['event ' => $ event ]
359+ );
360+
361+ $ result = $ transport ->send ($ event );
362+
363+ $ this ->assertEquals (ResultStatus::rateLimit (), $ result ->getStatus ());
364+ }
365+
266366 public function testClose (): void
267367 {
268368 $ transport = new HttpTransport (
0 commit comments