Projet

Général

Profil

0001-logging-append-connector-response-to-ressource-log-3.patch

Nicolas Roche, 13 novembre 2019 18:34

Télécharger (7,01 ko)

Voir les différences:

Subject: [PATCH] logging: append connector response to ressource log (#31774)

 passerelle/base/models.py      | 18 ++++++++++--------
 passerelle/views.py            | 16 +++++++++++++++-
 tests/test_generic_endpoint.py | 21 +++++++++++++++++++++
 3 files changed, 46 insertions(+), 9 deletions(-)
passerelle/base/models.py
770 770

  
771 771
    def _log(self, levelname, message, *args, **kwargs):
772 772
        force = kwargs.pop('force', False)
773
        ressource_log = None
773 774
        if self.connector.down() and not force:
774 775
            # don't log if the connector is known to be down
775 776
            return
......
825 826
                (exc_type, exc_value, tb) = sys.exc_info()
826 827
                attr['extra']['error_summary'] = traceback.format_exception_only(exc_type, exc_value)
827 828

  
828
            ResourceLog.objects.create(**attr)
829
            ressource_log = ResourceLog.objects.create(**attr)
829 830

  
830 831
        admins = settings.ADMINS
831 832
        logging_parameters = self.connector.logging_parameters
......
833 834
            admins = [('', x) for x in logging_parameters.trace_emails.splitlines()]
834 835
        with override_settings(ADMINS=admins):
835 836
            getattr(self._logger, levelname.lower())(message, *args, **kwargs)
837
        return ressource_log
836 838

  
837 839
    def exception(self, message, *args, **kwargs):
838 840
        kwargs['exc_info'] = 1
839
        self._log('ERROR', message, *args, **kwargs)
841
        return self._log('ERROR', message, *args, **kwargs)
840 842

  
841 843
    def debug(self, message, *args, **kwargs):
842
        self._log('DEBUG', message, *args, **kwargs)
844
        return self._log('DEBUG', message, *args, **kwargs)
843 845

  
844 846
    def info(self, message, *args, **kwargs):
845
        self._log('INFO', message, *args, **kwargs)
847
        return self._log('INFO', message, *args, **kwargs)
846 848

  
847 849
    def warning(self, message, *args, **kwargs):
848
        self._log('WARNING', message, *args, **kwargs)
850
        return self._log('WARNING', message, *args, **kwargs)
849 851

  
850 852
    def critical(self, message, *args, **kwargs):
851
        self._log('CRITICAL', message, *args, **kwargs)
853
        return self._log('CRITICAL', message, *args, **kwargs)
852 854

  
853 855
    def error(self, message, *args, **kwargs):
854
        self._log('ERROR', message, *args, **kwargs)
856
        return self._log('ERROR', message, *args, **kwargs)
855 857

  
856 858
    def fatal(self, message, *args, **kwargs):
857
        self._log('FATAL', message, *args, **kwargs)
859
        return self._log('FATAL', message, *args, **kwargs)
858 860

  
859 861

  
860 862
class HTTPResource(models.Model):
passerelle/views.py
18 18
import hashlib
19 19
import inspect
20 20
import json
21
from exceptions import UnicodeDecodeError
21 22

  
22 23
from django.apps import apps
23 24
from django.conf.urls import url
......
421 422
            payload.decode('utf-8')
422 423
        except UnicodeDecodeError:
423 424
            payload = '<BINARY PAYLOAD>'
424
        connector.logger.info('endpoint %s %s (%r) ' %
425
        ressource_log = connector.logger.info('endpoint %s %s (%r) ' %
425 426
                              (request.method, url, payload),
426 427
                              extra={
427 428
                                  'request': request,
......
432 433
                                  'connector_payload': payload
433 434
                              })
434 435

  
436
        def log_connector_response(key, value):
437
            if not ressource_log:
438
                return
439
            response = str(value)[:connector.logging_parameters.responses_max_size]
440
            ressource_log.extra[key] = response
441
            try:
442
                with transaction.atomic():
443
                    ressource_log.save()
444
            except UnicodeDecodeError:
445
                pass
446

  
435 447
        params = self.get_params(request, *args, **kwargs)
436 448
        if request.method == 'GET' and self.endpoint.endpoint_info.cache_duration:
437 449
            cache_key = hashlib.md5(
438 450
                repr(self.get_object().slug) + repr(self.endpoint) + repr(params)).hexdigest()
439 451
            result = cache.get(cache_key)
440 452
            if result is not None:
453
                log_connector_response('connector_response_from_cache', result)
441 454
                return result
442 455

  
443 456
        result = self.endpoint(request, **params)
444 457
        if request.method == 'GET' and self.endpoint.endpoint_info.cache_duration:
445 458
            cache.set(cache_key, result, self.endpoint.endpoint_info.cache_duration)
459
        log_connector_response('connector_response', result)
446 460
        return result
447 461

  
448 462
    def get(self, request, *args, **kwargs):
tests/test_generic_endpoint.py
115 115
    assert log.extra['connector'] == 'arcgis'
116 116
    assert log.extra['connector_endpoint'] == 'district'
117 117
    assert log.extra['connector_endpoint_method'] == 'GET'
118
    assert "'text': u'HAUSSONVILLE / BLANDAN / MON DESERT / SAURUPT'" in log.extra['connector_response']
118 119
    assert '/arcgis/test/district?' in log.extra['connector_endpoint_url']
119 120

  
120 121
    # Resource Generic Logger
......
142 143
    assert ResourceLog.objects.last().message == 'first warning'
143 144
    assert ResourceLog.objects.last().levelno == 30
144 145

  
146
    # troncate connector response on Resource Custom DB Logger
147
    ResourceLog.objects.all().delete()
148
    parameters = arcgis.logging_parameters
149
    parameters.responses_max_size = 20
150
    parameters.save()
151
    app.get('/arcgis/test/district', params={'lon': 6.172122, 'lat': 48.673836}, status=200)
152
    assert ResourceLog.objects.count() == 1
153
    log = ResourceLog.objects.filter(appname='arcgis', slug='test').first()
154
    assert len(log.extra['connector_response']) == 20
155
    assert log.extra.get('connector_response_from_cache') == None
156

  
157
    # check connector response returned by cache
158
    ResourceLog.objects.all().delete()
159
    arcgis.district.endpoint_info.cache_duration = 5
160
    app.get('/arcgis/test/district', params={'lon': 6.172122, 'lat': 48.673836}, status=200)
161
    app.get('/arcgis/test/district', params={'lon': 6.172122, 'lat': 48.673836}, status=200)
162
    assert ResourceLog.objects.count() == 2
163
    log = ResourceLog.objects.filter(appname='arcgis', slug='test').all()[1]
164
    assert log.extra.get('connector_response') == None
165
    assert len(log.extra['connector_response_from_cache']) == 20
145 166

  
146 167
class FakeConnectorBase(object):
147 168
    slug = 'connector'
148
-