Skip to content

Commit bbfcceb

Browse files
committed
add testing environment indicator to the logger
1 parent d52dcd5 commit bbfcceb

File tree

1 file changed

+28
-35
lines changed

1 file changed

+28
-35
lines changed

_delphi_utils_python/delphi_utils/logger.py

+28-35
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,7 @@ def handle_exceptions(logger):
2323
"""Handle exceptions using the provided logger."""
2424

2525
def exception_handler(scope, etype, value, traceback):
26-
logger.exception("Top-level exception occurred",
27-
scope=scope, exc_info=(etype, value, traceback))
26+
logger.exception("Top-level exception occurred", scope=scope, exc_info=(etype, value, traceback))
2827

2928
def sys_exception_handler(etype, value, traceback):
3029
exception_handler("sys", etype, value, traceback)
@@ -33,21 +32,19 @@ def threading_exception_handler(args):
3332
if args.exc_type == SystemExit and args.exc_value.code == 0:
3433
# `sys.exit(0)` is considered "successful termination":
3534
# https://docs.python.org/3/library/sys.html#sys.exit
36-
logger.debug("normal thread exit", thread=args.thread,
37-
stack="".join(
38-
format_exception(
39-
args.exc_type, args.exc_value, args.exc_traceback)))
35+
logger.debug(
36+
"normal thread exit",
37+
thread=args.thread,
38+
stack="".join(format_exception(args.exc_type, args.exc_value, args.exc_traceback)),
39+
)
4040
else:
41-
exception_handler(f"thread: {args.thread}",
42-
args.exc_type, args.exc_value, args.exc_traceback)
41+
exception_handler(f"thread: {args.thread}", args.exc_type, args.exc_value, args.exc_traceback)
4342

4443
sys.excepthook = sys_exception_handler
4544
threading.excepthook = threading_exception_handler
4645

4746

48-
def get_structured_logger(name=__name__,
49-
filename=None,
50-
log_exceptions=True):
47+
def get_structured_logger(name=__name__, filename=None, log_exceptions=True, is_real=True):
5148
"""Create a new structlog logger.
5249
5350
Use the logger returned from this in indicator code using the standard
@@ -66,17 +63,17 @@ def get_structured_logger(name=__name__,
6663
name: Name to use for logger (included in log lines), __name__ from caller
6764
is a good choice.
6865
filename: An (optional) file to write log output.
66+
log_exceptions: should we log exceptions?
67+
is_real: is this logger *not* in a testing environment? Used to avoid
68+
setting features that interfere with testing the logging output
6969
"""
7070
# Set the underlying logging configuration
7171
if "LOG_DEBUG" in os.environ:
7272
log_level = logging.DEBUG
7373
else:
7474
log_level = logging.INFO
7575

76-
logging.basicConfig(
77-
format="%(message)s",
78-
level=log_level,
79-
handlers=[logging.StreamHandler()])
76+
logging.basicConfig(format="%(message)s", level=log_level, handlers=[logging.StreamHandler()])
8077

8178
def add_pid(_logger, _method_name, event_dict):
8279
"""Add current PID to the event dict."""
@@ -115,7 +112,7 @@ def add_pid(_logger, _method_name, event_dict):
115112
# Use a standard wrapper class for utilities like log.warning()
116113
wrapper_class=structlog.stdlib.BoundLogger,
117114
# Cache the logger
118-
cache_logger_on_first_use=True,
115+
cache_logger_on_first_use=is_real,
119116
)
120117

121118
# Create the underlying python logger and wrap it with structlog
@@ -131,7 +128,7 @@ def add_pid(_logger, _method_name, event_dict):
131128
return logger
132129

133130

134-
class LoggerThread():
131+
class LoggerThread:
135132
"""
136133
A construct to use a logger from multiprocessing workers/jobs.
137134
@@ -149,15 +146,15 @@ class LoggerThread():
149146
docs.python.org/3/howto/logging-cookbook.html#logging-to-a-single-file-from-multiple-processes
150147
"""
151148

152-
class SubLogger():
149+
class SubLogger:
153150
"""MP-safe logger-like interface to convey log messages to a listening LoggerThread."""
154151

155152
def __init__(self, queue):
156153
"""Create SubLogger with a bound queue."""
157154
self.queue = queue
158155

159156
def _log(self, level, *args, **kwargs):
160-
kwargs_plus = {'sub_pid': multiprocessing.current_process().pid}
157+
kwargs_plus = {"sub_pid": multiprocessing.current_process().pid}
161158
kwargs_plus.update(kwargs)
162159
self.queue.put([level, args, kwargs_plus])
163160

@@ -181,7 +178,6 @@ def critical(self, *args, **kwargs):
181178
"""Log a CRITICAL level message."""
182179
self._log(logging.CRITICAL, *args, **kwargs)
183180

184-
185181
def get_sublogger(self):
186182
"""Retrieve SubLogger for this LoggerThread."""
187183
return self.sublogger
@@ -195,25 +191,22 @@ def __init__(self, logger, q=None):
195191
self.msg_queue = multiprocessing.Queue()
196192

197193
def logger_thread_worker():
198-
logger.info('thread started')
194+
logger.info("thread started")
199195
while True:
200196
msg = self.msg_queue.get()
201-
if msg == 'STOP':
202-
logger.debug('received stop signal')
197+
if msg == "STOP":
198+
logger.debug("received stop signal")
203199
break
204200
level, args, kwargs = msg
205-
if level in [logging.DEBUG, logging.INFO, logging.WARNING,
206-
logging.ERROR, logging.CRITICAL]:
201+
if level in [logging.DEBUG, logging.INFO, logging.WARNING, logging.ERROR, logging.CRITICAL]:
207202
logger.log(level, *args, **kwargs)
208203
else:
209-
logger.error('received unknown logging level! exiting...',
210-
level=level, args_kwargs=(args, kwargs))
204+
logger.error("received unknown logging level! exiting...", level=level, args_kwargs=(args, kwargs))
211205
break
212-
logger.debug('stopping thread')
206+
logger.debug("stopping thread")
213207

214-
self.thread = threading.Thread(target=logger_thread_worker,
215-
name="LoggerThread__"+logger.name)
216-
logger.debug('starting thread')
208+
self.thread = threading.Thread(target=logger_thread_worker, name="LoggerThread__" + logger.name)
209+
logger.debug("starting thread")
217210
self.thread.start()
218211

219212
self.sublogger = LoggerThread.SubLogger(self.msg_queue)
@@ -222,13 +215,13 @@ def logger_thread_worker():
222215
def stop(self):
223216
"""Terminate this LoggerThread."""
224217
if not self.running:
225-
self.logger.warning('thread already stopped')
218+
self.logger.warning("thread already stopped")
226219
return
227-
self.logger.debug('sending stop signal')
228-
self.msg_queue.put('STOP')
220+
self.logger.debug("sending stop signal")
221+
self.msg_queue.put("STOP")
229222
self.thread.join()
230223
self.running = False
231-
self.logger.info('thread stopped')
224+
self.logger.info("thread stopped")
232225

233226

234227
@contextlib.contextmanager

0 commit comments

Comments
 (0)