0001-add-a-RequestFilter-to-augment-logs-with-contextual-.patch
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(): |
|
85 |
# do not disseminate the real session_id |
|
86 |
record.session_id = hashlib.md5(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 |
- |