|
2 | 2 | import logging
|
3 | 3 | import pickle
|
4 | 4 |
|
5 |
| -from datetime import datetime |
| 5 | +from datetime import datetime, timedelta |
6 | 6 |
|
7 | 7 | import pytest
|
8 | 8 |
|
9 | 9 | from sentry_sdk import Hub, Client, add_breadcrumb, capture_message
|
| 10 | +from sentry_sdk.transport import _parse_rate_limits |
10 | 11 |
|
11 | 12 |
|
12 | 13 | @pytest.fixture(params=[True, False])
|
@@ -54,3 +55,115 @@ def test_transport_works(
|
54 | 55 | assert httpserver.requests
|
55 | 56 |
|
56 | 57 | assert any("Sending event" in record.msg for record in caplog.records) == debug
|
| 58 | + |
| 59 | + |
| 60 | +NOW = datetime(2014, 6, 2) |
| 61 | + |
| 62 | + |
| 63 | +@pytest.mark.parametrize( |
| 64 | + "input,expected", |
| 65 | + [ |
| 66 | + # Invalid rate limits |
| 67 | + ("", {}), |
| 68 | + ("invalid", {}), |
| 69 | + (",,,", {}), |
| 70 | + ( |
| 71 | + "42::organization, invalid, 4711:foobar;transaction;security:project", |
| 72 | + { |
| 73 | + None: NOW + timedelta(seconds=42), |
| 74 | + "transaction": NOW + timedelta(seconds=4711), |
| 75 | + "security": NOW + timedelta(seconds=4711), |
| 76 | + # Unknown data categories |
| 77 | + "foobar": NOW + timedelta(seconds=4711), |
| 78 | + }, |
| 79 | + ), |
| 80 | + ( |
| 81 | + "4711:foobar;;transaction:organization", |
| 82 | + { |
| 83 | + "transaction": NOW + timedelta(seconds=4711), |
| 84 | + # Unknown data categories |
| 85 | + "foobar": NOW + timedelta(seconds=4711), |
| 86 | + "": NOW + timedelta(seconds=4711), |
| 87 | + }, |
| 88 | + ), |
| 89 | + ], |
| 90 | +) |
| 91 | +def test_parse_rate_limits(input, expected): |
| 92 | + assert dict(_parse_rate_limits(input, now=NOW)) == expected |
| 93 | + |
| 94 | + |
| 95 | +def test_simple_rate_limits(httpserver, capsys, caplog): |
| 96 | + client = Client(dsn="http://foobar@{}/123".format(httpserver.url[len("http://") :])) |
| 97 | + httpserver.serve_content("no", 429, headers={"Retry-After": "4"}) |
| 98 | + |
| 99 | + client.capture_event({"type": "transaction"}) |
| 100 | + client.flush() |
| 101 | + |
| 102 | + assert len(httpserver.requests) == 1 |
| 103 | + del httpserver.requests[:] |
| 104 | + |
| 105 | + assert set(client.transport._disabled_until) == set([None]) |
| 106 | + |
| 107 | + client.capture_event({"type": "transaction"}) |
| 108 | + client.capture_event({"type": "event"}) |
| 109 | + client.flush() |
| 110 | + |
| 111 | + assert not httpserver.requests |
| 112 | + |
| 113 | + |
| 114 | +@pytest.mark.parametrize("response_code", [200, 429]) |
| 115 | +def test_data_category_limits(httpserver, capsys, caplog, response_code): |
| 116 | + client = Client( |
| 117 | + dict(dsn="http://foobar@{}/123".format(httpserver.url[len("http://") :])) |
| 118 | + ) |
| 119 | + httpserver.serve_content( |
| 120 | + "hm", |
| 121 | + response_code, |
| 122 | + headers={"X-Sentry-Rate-Limit": "4711:transaction:organization"}, |
| 123 | + ) |
| 124 | + |
| 125 | + client.capture_event({"type": "transaction"}) |
| 126 | + client.flush() |
| 127 | + |
| 128 | + assert len(httpserver.requests) == 1 |
| 129 | + del httpserver.requests[:] |
| 130 | + |
| 131 | + assert set(client.transport._disabled_until) == set(["transaction"]) |
| 132 | + |
| 133 | + client.transport.capture_event({"type": "transaction"}) |
| 134 | + client.transport.capture_event({"type": "transaction"}) |
| 135 | + client.flush() |
| 136 | + |
| 137 | + assert not httpserver.requests |
| 138 | + |
| 139 | + client.capture_event({"type": "event"}) |
| 140 | + client.flush() |
| 141 | + |
| 142 | + assert len(httpserver.requests) == 1 |
| 143 | + |
| 144 | + |
| 145 | +@pytest.mark.parametrize("response_code", [200, 429]) |
| 146 | +def test_complex_limits_without_data_category( |
| 147 | + httpserver, capsys, caplog, response_code |
| 148 | +): |
| 149 | + client = Client( |
| 150 | + dict(dsn="http://foobar@{}/123".format(httpserver.url[len("http://") :])) |
| 151 | + ) |
| 152 | + httpserver.serve_content( |
| 153 | + "hm", response_code, headers={"X-Sentry-Rate-Limit": "4711::organization"}, |
| 154 | + ) |
| 155 | + |
| 156 | + client.capture_event({"type": "transaction"}) |
| 157 | + client.flush() |
| 158 | + |
| 159 | + assert len(httpserver.requests) == 1 |
| 160 | + del httpserver.requests[:] |
| 161 | + |
| 162 | + assert set(client.transport._disabled_until) == set([None]) |
| 163 | + |
| 164 | + client.transport.capture_event({"type": "transaction"}) |
| 165 | + client.transport.capture_event({"type": "transaction"}) |
| 166 | + client.capture_event({"type": "event"}) |
| 167 | + client.flush() |
| 168 | + |
| 169 | + assert len(httpserver.requests) == 0 |
0 commit comments