Projet

Général

Profil

0001-logging-add-LOGGED_REQUEST_MAX_SIZE-settings.patch

Nicolas Roche, 26 septembre 2019 19:09

Télécharger (5,92 ko)

Voir les différences:

Subject: [PATCH] logging: add LOGGED_REQUEST_MAX_SIZE settings

 passerelle/settings.py           |  3 +++
 passerelle/utils/__init__.py     |  2 +-
 passerelle/utils/jsonresponse.py |  2 +-
 passerelle/views.py              |  2 +-
 tests/test_api_access.py         | 28 +++++++++++++++++++++++++++-
 tests/test_requests.py           | 17 +++++++++++++++++
 6 files changed, 50 insertions(+), 4 deletions(-)
passerelle/settings.py
211 211
# Max size of the response to log
212 212
LOGGED_RESPONSES_MAX_SIZE = 4096
213 213

  
214
# Max size of the request to log
215
LOGGED_REQUEST_MAX_SIZE = 5000
216

  
214 217
# Number of days to keep logs
215 218
LOG_RETENTION_DAYS = 7
216 219

  
passerelle/utils/__init__.py
158 158
    if logger.level == 10:  # DEBUG
159 159
        extra['request_headers'] = dict(request.headers.items())
160 160
        if request.body:
161
            extra['request_payload'] = repr(request.body[:5000])
161
            extra['request_payload'] = repr(request.body[:settings.LOGGED_REQUEST_MAX_SIZE])
162 162
    if response is not None:
163 163
        message = message + ' (=> %s)' % response.status_code
164 164
        extra['response_status'] = response.status_code
passerelle/utils/jsonresponse.py
132 132
        except Exception as e:
133 133
            extras = {'method': req.method, 'exception': exception_to_text(e), 'request': req}
134 134
            if req.method == 'POST':
135
                extras.update({'body': repr(req.body[:5000])})
135
                extras.update({'body': repr(req.body[:settings.LOGGED_REQUEST_MAX_SIZE])})
136 136
            if (not isinstance(e, (Http404, PermissionDenied, ObjectDoesNotExist, RequestException))
137 137
                    and getattr(e, 'log_error', True)):
138 138
                logger.exception("Error occurred while processing request", extra=extras)
passerelle/views.py
394 394
        connector_name, endpoint_name = kwargs['connector'], kwargs['endpoint']
395 395
        connector = self.get_object()
396 396
        url = request.get_full_path()
397
        payload = request.body[:5000]
397
        payload = request.body[:settings.LOGGED_REQUEST_MAX_SIZE]
398 398
        try:
399 399
            payload.decode('utf-8')
400 400
        except UnicodeDecodeError:
tests/test_api_access.py
7 7

  
8 8
import pytest
9 9

  
10
from django.test import override_settings
11

  
10 12
from passerelle.base import signature
11
from passerelle.base.models import ApiUser, AccessRight
13
from passerelle.base.models import ApiUser, AccessRight, ResourceLog
12 14
from passerelle.apps.oxyd.models import OxydSMSGateway
13 15

  
14 16
pytestmark = pytest.mark.django_db
......
181 183
                         extra_environ={'REMOTE_ADDR': authorized_ip})
182 184
    assert resp.json['err'] == 1
183 185
    assert resp.json['err_desc'] == 'Payload error: missing "message" in JSON payload'
186

  
187
def test_logged_request_max_size(app, oxyd):
188
    endpoint_url = reverse('generic-endpoint',
189
            kwargs={'connector': 'oxyd', 'slug': oxyd.slug, 'endpoint': 'send'})
190
    api = ApiUser.objects.create(username='public',
191
                    fullname='public',
192
                    description='access for all',
193
                    keytype='', key='')
194
    obj_type = ContentType.objects.get_for_model(OxydSMSGateway)
195
    AccessRight.objects.create(codename='can_send_messages',
196
                    apiuser=api,
197
                    resource_type=obj_type,
198
                    resource_pk=oxyd.pk,
199
    )
200
    resp = app.post_json(endpoint_url, params={'foo': 'bar'})
201
    assert ResourceLog.objects.all()[0].message[-9:] == '"bar"}\') '
202

  
203
    # for empty payload the connector returns an APIError with
204
    assert 'Error occurred' in ResourceLog.objects.all()[1].message
205

  
206
    # troncate logs
207
    with override_settings(LOGGED_REQUEST_MAX_SIZE=6):
208
        resp = app.post_json(endpoint_url, params={'foo': 'bar'})
209
        assert ResourceLog.objects.all()[2].message[-8:] == '"foo"\') '
tests/test_requests.py
105 105
            assert not hasattr(record, 'response_content')
106 106
            assert not hasattr(record, 'response_headers')
107 107

  
108
def test_log_error_request_max_size(caplog, log_level):
109
    url = 'https://httperror.org/plop'
110

  
111
    logger = logging.getLogger('requests')
112
    logger.setLevel(log_level)
113

  
114
    with override_settings(LOGGED_REQUEST_MAX_SIZE=8):
115
        with HTTMock(http400_mock):
116
            requests = Request(logger=logger)
117
            response = requests.post(url, json={'name':'josh'})
118

  
119
    print logger.level
120
    if logger.level == 10:  # DEBUG
121
        records = [record for record in caplog.records if record.name == 'requests']
122
        assert records[0].request_payload == '\'{"name":\''
123

  
124

  
108 125
@pytest.fixture(params=['xml', 'whatever', 'jpeg', 'pdf'])
109 126
def endpoint_response(request):
110 127
    response_request = mock.Mock(
111
-