Skip to content
This repository was archived by the owner on May 23, 2023. It is now read-only.

Commit 4bad915

Browse files
committed
Fix logging annoyance
1 parent a31fc79 commit 4bad915

File tree

3 files changed

+67
-14
lines changed

3 files changed

+67
-14
lines changed

ethereum/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
import os.path
55
import subprocess
66
import re
7+
# Import slogging to patch logging as soon as possible
8+
import slogging # noqa
79

810

911
GIT_DESCRIBE_RE = re.compile('^(?P<version>v\d+\.\d+\.\d+)-(?P<git>\d+-g[a-fA-F0-9]+(?:-dirty)?)$')

ethereum/slogging.py

Lines changed: 45 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import logging
22
import json
3+
import textwrap
34
from logging import StreamHandler, Formatter, FileHandler
45
from ethereum.utils import bcolors, isnumeric
56

@@ -18,15 +19,54 @@
1819
log_listeners = []
1920

2021

21-
# add level trace into logging
22-
def _trace(self, msg, *args, **kwargs):
23-
if self.isEnabledFor(TRACE):
24-
self._log(TRACE, msg, args, **kwargs)
25-
logging.Logger.trace = _trace
22+
def _inject_into_logger(name, code, namespace=None):
23+
# This is a hack to fool the logging module into reporting correct source files.
24+
# It determines the actual source of a logging call by inspecting the stack frame's
25+
# source file. So we use this `eval(compile())` construct to "inject" our additional
26+
# methods into the logging module.
27+
if namespace is None:
28+
namespace = {}
29+
eval(
30+
compile(
31+
code,
32+
logging._srcfile,
33+
'exec'
34+
),
35+
namespace
36+
)
37+
setattr(logging.Logger, name, namespace[name])
38+
39+
40+
# Add `trace()` level to Logger
41+
_inject_into_logger(
42+
'trace',
43+
textwrap.dedent(
44+
"""\
45+
def trace(self, msg, *args, **kwargs):
46+
if self.isEnabledFor(TRACE):
47+
self._log(TRACE, msg, args, **kwargs)
48+
"""
49+
),
50+
{'TRACE': TRACE}
51+
)
2652
logging.TRACE = TRACE
2753
logging.addLevelName(TRACE, "TRACE")
2854

2955

56+
# Add `DEV()` shortcut to loggers
57+
_inject_into_logger(
58+
'DEV',
59+
textwrap.dedent(
60+
"""\
61+
def DEV(self, msg, *args, **kwargs):
62+
'''Shortcut to output highlighted log text'''
63+
kwargs['highlight'] = True
64+
self.critical(msg, *args, **kwargs)
65+
"""
66+
)
67+
)
68+
69+
3070
class LogRecorder(object):
3171

3272
"""
@@ -166,11 +206,6 @@ def _log(self, level, msg, args, **kwargs):
166206
msg = self.format_message(msg, kwargs, highlight, level)
167207
super(SLogger, self)._log(level, msg, args, exc_info, extra)
168208

169-
def DEV(self, msg, *args, **kwargs):
170-
"""Shortcut to output highlighted log text"""
171-
kwargs['highlight'] = True
172-
self.critical(msg, *args, **kwargs)
173-
174209

175210
class RootLogger(SLogger):
176211

ethereum/tests/test_logging.py

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ def test_jsonconfig(caplog):
4949
slogging.configure(log_json=True)
5050
log = slogging.get_logger('prefix')
5151
log.warn('abc', a=1)
52-
assert json.loads(caplog.records()[0].msg) == dict(event='prefix.abc', a=1, level='WARNING')
52+
assert json.loads(caplog.records[0].msg) == dict(event='prefix.abc', a=1, level='WARNING')
5353

5454

5555
def test_configuration():
@@ -271,14 +271,14 @@ def test_bound_logger_isolation(caplog):
271271
bound_log_1 = real_log.bind(key1="value1")
272272
with caplog.at_level(slogging.TRACE):
273273
bound_log_1.info("test1")
274-
records = caplog.records()
274+
records = caplog.records
275275
assert len(records) == 1
276276
assert "test1" in records[0].msg
277277
assert 'key1=value1' in records[0].msg
278278

279279
with caplog.at_level(slogging.TRACE):
280280
real_log.info("test2")
281-
records = caplog.records()
281+
records = caplog.records
282282
assert len(records) == 2
283283
assert "test2" in records[1].msg
284284
assert 'key1=value1' not in records[1].msg
@@ -289,7 +289,7 @@ def test_highlight(caplog):
289289
log = slogging.getLogger()
290290

291291
log.DEV('testmessage')
292-
assert "\033[91mtestmessage \033[0m" in caplog.records()[0].msg
292+
assert "\033[91mtestmessage \033[0m" in caplog.records[0].msg
293293

294294

295295
def test_shortcut_dev_logger(capsys):
@@ -336,3 +336,19 @@ def test_logging_reconfigure_levels(config, logger, level):
336336
def test_set_level():
337337
slogging.set_level('test', 'CRITICAL')
338338
assert slogging.getLogger('test').level == logging.CRITICAL
339+
340+
341+
@pytest.mark.parametrize(
342+
('log_method', ), (
343+
('DEV', ),
344+
('trace', ),
345+
('info', ),
346+
))
347+
def test_logging_source_file(caplog, log_method):
348+
slogging.configure(":trace")
349+
logger = slogging.getLogger("test")
350+
getattr(logger, log_method)("testmessage")
351+
352+
v = caplog.records[0]
353+
print(v.pathname, v.module, v.name)
354+
assert caplog.records[0].module == "test_logging"

0 commit comments

Comments
 (0)