Projet

Général

Profil

0001-add-a-RequestFilter-to-augment-logs-with-contextual-.patch

Benjamin Dauvergne, 27 mars 2017 12:55

Télécharger (6,2 ko)

Voir les différences:

Subject: [PATCH 1/2] add a RequestFilter to augment logs with contextual
 informations (#10411)

Fields added are:
- ip
- path
- user_id
- user_name
- user_email
- user_display_name
- user_uuid
- session_id (md5 of the real session id)
- request_id ( id(request) )
- tenant
 tests/test_logs.py      | 58 +++++++++++++++++++++++++++++++++++++++++++++++++
 wcs/qommon/logger.py    | 40 ++++++++++++++++++++++++++--------
 wcs/qommon/publisher.py |  3 ++-
 3 files changed, 91 insertions(+), 10 deletions(-)
 create mode 100644 tests/test_logs.py
tests/test_logs.py
1
from utilities import create_temporary_pub
2

  
3
from wcs.qommon.http_request import HTTPRequest
4
from qommon import get_logger
5
from quixote import get_session
6
from wcs.qommon.sessions import Session
7

  
8

  
9
def test_request_filter(caplog):
10
    pub = create_temporary_pub(sql_mode=False)
11
    pub.cfg['debug'] = {'logger': True}
12
    pub.write_cfg()
13

  
14
    user = pub.user_class()
15
    user.name = 'coucou'
16
    user.email = 'foo@localhost'
17
    user.name_identifiers = ['1234']
18
    user.store()
19

  
20
    req = HTTPRequest(None, {
21
        'SERVER_NAME': 'example.net',
22
        'SCRIPT_NAME': '/coin',
23
        'REMOTE_ADDR': '10.0.0.0',
24
    })
25
    pub._set_request(req)
26
    pub.set_config(req)
27
    session = Session(id='1')
28
    session.store()
29
    req.session = session
30
    logger = get_logger()
31

  
32
    logger.info('coucou')
33
    record = caplog.records[0]
34
    assert record.ip == '10.0.0.0'
35
    assert record.tenant == 'example.net'
36
    assert record.path == '/coin'
37
    assert record.request_id
38
    assert record.user_id == 'unlogged'
39
    assert record.user_email == '-'
40
    assert record.user_display_name == '-'
41
    assert record.user_uuid == '-'
42
    assert record.session_id != '[nosession]'
43

  
44
    req._user = ()
45
    get_session().set_user(user.id)
46
    get_session().store()
47
    assert get_session().get_session_id()
48
    logger.info('coucou')
49
    record = caplog.records[1]
50
    assert record.ip == '10.0.0.0'
51
    assert record.tenant == 'example.net'
52
    assert record.path == '/coin'
53
    assert record.request_id
54
    assert record.user_id == '1'
55
    assert record.user_email == 'foo@localhost'
56
    assert record.user_display_name == 'coucou'
57
    assert record.user_uuid == '1234'
58
    assert record.session_id != '[nosession]'
wcs/qommon/logger.py
16 16

  
17 17
import logging
18 18
import os
19
import hashlib
19 20

  
20 21
from quixote import get_publisher, get_session, get_request
21 22

  
......
40 41
        return False
41 42

  
42 43

  
43
class Formatter(logging.Formatter):
44
    def format(self, record):
44
class RequestFilter(logging.Filter):
45
    def filter(self, record):
45 46
        request = get_request()
47

  
48
        record.application = 'wcs'
49
        record.tenant = '-'
50
        record.ip = '-'
51
        record.path = '-'
52
        record.request_id = '-'
53
        record.user_id = 'unlogged'
54
        record.user_email = '-'
55
        record.user_display_name = '-'
56
        record.user_uuid = '-'
57
        record.session_id = '[nosession]'
46 58
        if request:
47
            record.address = request.get_environ('REMOTE_ADDR', '-')
59
            record.tenant = request.get_server()
60
            record.ip = request.get_environ('REMOTE_ADDR', '-')
48 61
            record.path = request.get_path()
62
            record.request_id = id(request)
49 63

  
50 64
            user = request.user
51 65
            if user:
......
53 67
                    user_id = user
54 68
                else:
55 69
                    user_id = user.id
70
                    record.user_display_name = user.name or '-'
71
                    record.user_email = user.email or '-'
72
                    uuid = None
73
                    if user.name_identifiers:
74
                        uuid = record.user_uuid = user.name_identifiers[0]
75
                    record.user = user.email or uuid or user_id
56 76
                    if type(user_id) is str and user_id.startswith('anonymous-'):
57 77
                        user_id = 'anonymous'
58 78
            else:
59 79
                user_id = 'unlogged'
60 80
                if BotFilter.is_bot():
61 81
                    user_id = 'bot'
82
                    record.user = 'bot'
62 83
            record.user_id = user_id
63
        else:
64
            record.address = '-'
65
            record.path = '-'
66
            record.user_id = 'unlogged'
67
        record.session_id = (get_request() and get_session() and \
68
                get_session().get_session_id()) or '[nosession]'
84
            if get_session() and get_session().get_session_id():
85
                # do not disseminate the real session_id
86
                record.session_id = hashlib.md5(str(get_session().get_session_id())).hexdigest()
87
        return True
69 88

  
89

  
90
class Formatter(logging.Formatter):
91
    def format(self, record):
70 92
        return logging.Formatter.format(self, record) \
71 93
                .replace('\n', '\n ')
72 94

  
wcs/qommon/publisher.py
949 949
        self._app_logger = logging.getLogger(self.APP_NAME + self.app_dir)
950 950
        if not self._app_logger.filters:
951 951
            self._app_logger.addFilter(logger.BotFilter())
952
            self._app_logger.addFilter(logger.RequestFilter())
952 953
        logfile = self.get_app_logger_filename()
953 954

  
954 955
        if not self._app_logger.handlers:
955 956
            hdlr = logging.handlers.RotatingFileHandler(logfile, 'a', 2**20, 100)
956 957
                # max size = 1M
957 958
            formatter = logger.Formatter(
958
                    '%(asctime)s %(levelname)s %(address)s '\
959
                    '%(asctime)s %(levelname)s %(ip)s '\
959 960
                    '%(session_id)s %(path)s %(user_id)s - %(message)s')
960 961
            hdlr.setFormatter(formatter)
961 962
            self._app_logger.addHandler(hdlr)
962
-