Skip to content

Commit 0dcdb9c

Browse files
committed
fix(logging-filter): add some changes for discussion
1 parent 2164442 commit 0dcdb9c

File tree

4 files changed

+90
-43
lines changed

4 files changed

+90
-43
lines changed

anonip.py

+46-26
Original file line numberDiff line numberDiff line change
@@ -304,46 +304,66 @@ def truncate_address(self, ip):
304304
return ip.supernet(new_prefix=self._prefixes[ip.version])[0]
305305

306306

307-
class AnonipFilter:
308-
def __init__(self, args=None, extra=None, anonip=None):
307+
class AnonipFilter(logging.Filter):
308+
def __init__(self, name="", args=None, extra=None, anonip=None):
309309
"""
310310
An implementation of Python logging.Filter using anonip.
311311
312+
:param name: str
312313
:param args: list of log message args to filter. Defaults to []
313314
:param extra: list of LogRecord attributes to filter. Defaults to []
314315
:param anonip: dict of parameters for Anonip instance
315316
"""
317+
super(AnonipFilter, self).__init__(name)
316318
self.args = [] if args is None else args
317319
self.extra = [] if extra is None else extra
318320
self.anonip = Anonip(**(anonip or {}))
319321

322+
def _set_args_attr(self, args, key):
323+
value = args[key]
324+
if not isinstance(value, str):
325+
return args
326+
327+
orig_type = type(args)
328+
temp_type = list
329+
if isinstance(args, abc.Mapping):
330+
temp_type = dict
331+
has_setitem = hasattr(args, "__setitem__")
332+
if not has_setitem:
333+
args = temp_type(args)
334+
ip = self.anonip.extract_ip(value)[1]
335+
args[key] = str(self.anonip.process_ip(ip))
336+
if not has_setitem:
337+
args = orig_type(args)
338+
return args
339+
320340
def filter(self, record):
321341
"""
322-
See logging.Filter.filter()
342+
Apply anonip IP masking.
343+
344+
:param record: logging.LogRecord
345+
:return: bool
323346
"""
324-
if record.name != "anonip":
325-
for key in self.args:
326-
if isinstance(record.args, abc.Mapping):
327-
if key in record.args:
328-
value = record.args[key]
329-
if isinstance(value, str):
330-
record.args[key] = self.anonip.process_line(value)
331-
elif isinstance(record.args, abc.Sequence):
332-
if key < len(record.args):
333-
value = record.args[key]
334-
if isinstance(value, str):
335-
is_tuple = isinstance(record.args, tuple)
336-
if is_tuple:
337-
record.args = list(record.args)
338-
record.args[key] = self.anonip.process_line(value)
339-
if is_tuple:
340-
record.args = tuple(record.args)
341-
342-
for key in self.extra:
343-
if hasattr(record, key):
344-
value = getattr(record, key)
345-
if (isinstance(value, str)):
346-
setattr(record, key, self.anonip.process_line(value))
347+
if not super(AnonipFilter, self).filter(record):
348+
return False
349+
350+
for key in self.args:
351+
if isinstance(record.args, abc.Mapping):
352+
if key in record.args:
353+
record.args = self._set_args_attr(record.args, key)
354+
elif isinstance(record.args, abc.Sequence):
355+
if isinstance(key, int) and key < len(record.args):
356+
record.args = self._set_args_attr(record.args, key)
357+
358+
for key in self.extra:
359+
if hasattr(record, key):
360+
value = getattr(record, key)
361+
if isinstance(value, str):
362+
ip = self.anonip.extract_ip(value)[1]
363+
setattr(record, key, str(self.anonip.process_ip(ip)))
364+
365+
if not self.args and not self.extra:
366+
record.msg = self.anonip.process_line(record.msg)
347367

348368
return True
349369

conftest.py

+9
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import logging
12
import sys
23

34
import pytest
@@ -8,3 +9,11 @@ def backup_and_restore_sys_argv():
89
old_sys_argv = sys.argv
910
yield
1011
sys.argv = old_sys_argv
12+
13+
14+
@pytest.fixture()
15+
def enable_logging():
16+
logging.disable(logging.NOTSET)
17+
logging.getLogger("anonip").setLevel(logging.CRITICAL)
18+
yield
19+
logging.disable(logging.CRITICAL)

tests.py

+34-17
Original file line numberDiff line numberDiff line change
@@ -432,27 +432,44 @@ def test_logging_filter_defaults(caplog):
432432
logging.disable(logging.CRITICAL)
433433

434434

435-
def test_logging_filter_args(caplog):
436-
logging.disable(logging.NOTSET)
437-
logging.getLogger("anonip").setLevel(logging.CRITICAL)
438-
435+
@pytest.mark.parametrize(
436+
"string,args,filter_attr,expected",
437+
[
438+
("%(ip)s string", {"ip": "192.168.100.200"}, "ip", "192.168.96.0 string"),
439+
("%s string", "192.168.100.200", 0, "192.168.96.0 string"),
440+
(
441+
"%(ip)s string",
442+
{"ip": "2001:0db8:85a3:0000:0000:8a2e:0370:7334"},
443+
"ip",
444+
"2001:db8:85a0:: string",
445+
),
446+
("string", None, "ip", "string"),
447+
("string", {"ip": ["in a list"]}, "ip", "string"),
448+
("", "", "", ""),
449+
],
450+
)
451+
def test_logging_filter_args(
452+
string, args, filter_attr, expected, mocker, caplog, enable_logging
453+
):
439454
logger = logging.getLogger("filter_args")
440-
logger.addFilter(anonip.AnonipFilter(args=["ip", "non-existing-attr"], extra=[]))
455+
logger.addFilter(
456+
anonip.AnonipFilter(args=[filter_attr, "non-existing-attr"], extra=[])
457+
)
441458
logger.setLevel(logging.INFO)
442459

443-
logger.info("%(ip)s string", {"ip": "192.168.100.200"})
444-
logger.info("string %(ip)s", {"ip": "1.2.3.4"})
445-
logger.info("%(ip)s string", {"ip": "2001:0db8:85a3:0000:0000:8a2e:0370:7334"})
446-
logger.info("string")
447-
448-
assert caplog.record_tuples == [
449-
("filter_args", logging.INFO, "192.168.96.0 string"),
450-
("filter_args", logging.INFO, "string 1.2.0.0"),
451-
("filter_args", logging.INFO, "2001:db8:85a0:: string"),
452-
("filter_args", logging.INFO, "string"),
453-
]
460+
log_args = [string]
461+
if args:
462+
log_args.append(args)
454463

455-
logging.disable(logging.CRITICAL)
464+
if string == args == filter_attr == expected == "":
465+
mocker.patch.object(logging.Filter, "filter", return_value=False)
466+
logger.info(*log_args)
467+
assert len(caplog.record_tuples) == 0
468+
else:
469+
logger.info(*log_args)
470+
assert caplog.record_tuples == [
471+
("filter_args", logging.INFO, expected),
472+
]
456473

457474

458475
def test_logging_filter_extra(caplog):

tox.ini

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ envlist = py{27,36,37,38,39,310}, pypy3, flake8, black
1313
deps=
1414
pytest
1515
pytest-cov
16+
pytest-mock
1617
commands=pytest -r a -vv tests.py anonip.py
1718

1819
[testenv:flake8]

0 commit comments

Comments
 (0)