Introduce an internal log level for debug to simplify Script logging

This commit is contained in:
Jeremy Stretch 2024-02-05 16:37:39 -05:00
parent a6f5e7260b
commit d7bcf3d4cc
3 changed files with 58 additions and 33 deletions

View File

@ -1,3 +1,5 @@
import logging
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from utilities.choices import ButtonColorChoices, ChoiceSet from utilities.choices import ButtonColorChoices, ChoiceSet
@ -164,6 +166,7 @@ class JournalEntryKindChoices(ChoiceSet):
class LogLevelChoices(ChoiceSet): class LogLevelChoices(ChoiceSet):
LOG_DEBUG = 'debug'
LOG_DEFAULT = 'default' LOG_DEFAULT = 'default'
LOG_SUCCESS = 'success' LOG_SUCCESS = 'success'
LOG_INFO = 'info' LOG_INFO = 'info'
@ -171,6 +174,7 @@ class LogLevelChoices(ChoiceSet):
LOG_FAILURE = 'failure' LOG_FAILURE = 'failure'
CHOICES = ( CHOICES = (
(LOG_DEBUG, _('Debug'), 'teal'),
(LOG_DEFAULT, _('Default'), 'gray'), (LOG_DEFAULT, _('Default'), 'gray'),
(LOG_SUCCESS, _('Success'), 'green'), (LOG_SUCCESS, _('Success'), 'green'),
(LOG_INFO, _('Info'), 'cyan'), (LOG_INFO, _('Info'), 'cyan'),
@ -178,6 +182,15 @@ class LogLevelChoices(ChoiceSet):
(LOG_FAILURE, _('Failure'), 'red'), (LOG_FAILURE, _('Failure'), 'red'),
) )
SYSTEM_LEVELS = {
LOG_DEBUG: logging.DEBUG,
LOG_DEFAULT: logging.INFO,
LOG_SUCCESS: logging.INFO,
LOG_INFO: logging.INFO,
LOG_WARNING: logging.WARNING,
LOG_FAILURE: logging.ERROR,
}
class DurationChoices(ChoiceSet): class DurationChoices(ChoiceSet):

View File

@ -1,3 +1,4 @@
from .choices import LogLevelChoices
from .scripts import BaseScript from .scripts import BaseScript
__all__ = ( __all__ = (
@ -6,6 +7,15 @@ __all__ = (
class Report(BaseScript): class Report(BaseScript):
#
# Legacy logging methods for Reports
#
# There is no generic log() equivalent on BaseScript
def log(self, message):
self._log(message, None, level=LogLevelChoices.LOG_DEFAULT)
def log_success(self, obj=None, message=None): def log_success(self, obj=None, message=None):
super().log_success(message, obj) super().log_success(message, obj)
@ -17,3 +27,7 @@ class Report(BaseScript):
def log_failure(self, obj=None, message=None): def log_failure(self, obj=None, message=None):
super().log_failure(message, obj) super().log_failure(message, obj)
# Added in v4.0 to avoid confusion with the log_debug() method provided by BaseScript
def log_debug(self, obj=None, message=None):
super().log_debug(message, obj)

View File

@ -286,10 +286,10 @@ class BaseScript:
# Compile test methods and initialize results skeleton # Compile test methods and initialize results skeleton
self._logs[''] = { self._logs[''] = {
'success': 0, LogLevelChoices.LOG_SUCCESS: 0,
'info': 0, LogLevelChoices.LOG_INFO: 0,
'warning': 0, LogLevelChoices.LOG_WARNING: 0,
'failure': 0, LogLevelChoices.LOG_FAILURE: 0,
'log': [], 'log': [],
} }
test_methods = [] test_methods = []
@ -297,10 +297,10 @@ class BaseScript:
if method.startswith('test_') and callable(getattr(self, method)): if method.startswith('test_') and callable(getattr(self, method)):
test_methods.append(method) test_methods.append(method)
self._logs[method] = { self._logs[method] = {
'success': 0, LogLevelChoices.LOG_SUCCESS: 0,
'info': 0, LogLevelChoices.LOG_INFO: 0,
'warning': 0, LogLevelChoices.LOG_WARNING: 0,
'failure': 0, LogLevelChoices.LOG_FAILURE: 0,
'log': [], 'log': [],
} }
self.test_methods = test_methods self.test_methods = test_methods
@ -437,53 +437,51 @@ class BaseScript:
# Logging # Logging
def _log(self, message, obj=None, log_level=LogLevelChoices.LOG_DEFAULT, level=logging.INFO): def _log(self, message, obj=None, level=LogLevelChoices.LOG_DEFAULT):
""" """
Log a message from a test method. Do not call this method directly; use one of the log_* wrappers below. Log a message. Do not call this method directly; use one of the log_* wrappers below.
""" """
if log_level not in LogLevelChoices.values(): if level not in LogLevelChoices.values():
raise Exception(f"Unknown logging level: {log_level}") raise ValueError(f"Invalid logging level: {level}")
if message: if message:
# Record to the script's log
self._logs[self._current_method]['log'].append(( self._logs[self._current_method]['log'].append((
timezone.now().isoformat(), timezone.now().isoformat(),
log_level, level,
str(obj) if obj else None, str(obj) if obj else None,
obj.get_absolute_url() if hasattr(obj, 'get_absolute_url') else None, obj.get_absolute_url() if hasattr(obj, 'get_absolute_url') else None,
message, str(message),
)) ))
if log_level != LogLevelChoices.LOG_DEFAULT: # Record to the system log
self._logs[self._current_method][log_level] += 1
if self._current_method != '':
self._logs[''][log_level] += 1
if obj: if obj:
self.logger.log(level, f"{log_level.capitalize()} | {obj}: {message}") message = f"{obj}: {message}"
else: self.logger.log(LogLevelChoices.SYSTEM_LEVELS[level], message)
self.logger.log(level, message) # No syslog equivalent for SUCCESS
def log(self, message): # Increment the event counter for this level if applicable
""" if level in self._logs[self._current_method]:
Log a message which is not associated with a particular object. self._logs[self._current_method][level] += 1
"""
self._log(str(message), None, log_level=LogLevelChoices.LOG_DEFAULT, level=logging.INFO) # For individual test methods, increment the global counter as well
if self._current_method:
self._logs[''][level] += 1
def log_debug(self, message, obj=None): def log_debug(self, message, obj=None):
self._log(str(message), obj, log_level=LogLevelChoices.LOG_DEFAULT, level=logging.DEBUG) self._log(message, obj, level=LogLevelChoices.LOG_DEBUG)
def log_success(self, message, obj=None): def log_success(self, message, obj=None):
self._log(str(message), obj, log_level=LogLevelChoices.LOG_SUCCESS, level=logging.INFO) self._log(message, obj, level=LogLevelChoices.LOG_SUCCESS)
def log_info(self, message, obj=None): def log_info(self, message, obj=None):
self._log(str(message), obj, log_level=LogLevelChoices.LOG_INFO, level=logging.INFO) self._log(message, obj, level=LogLevelChoices.LOG_INFO)
def log_warning(self, message, obj=None): def log_warning(self, message, obj=None):
self._log(str(message), obj, log_level=LogLevelChoices.LOG_WARNING, level=logging.WARNING) self._log(message, obj, level=LogLevelChoices.LOG_WARNING)
def log_failure(self, message, obj=None): def log_failure(self, message, obj=None):
self._log(str(message), obj, log_level=LogLevelChoices.LOG_FAILURE, level=logging.ERROR) self._log(message, obj, level=LogLevelChoices.LOG_FAILURE)
self._failed = True self._failed = True
# Convenience functions # Convenience functions