mirror of
https://github.com/rbreu/beeref.git
synced 2026-03-11 08:54:28 +00:00
Add new loglevel TRACE
The debug log file still only logs DEBUG and above, so it's less verbose now. TRACE output will only show in the console if the loglevel is set accordingly.
This commit is contained in:
parent
2de388ec5f
commit
849de6197a
8 changed files with 132 additions and 69 deletions
|
|
@ -1,3 +1,12 @@
|
|||
0.2.0 - unreleased
|
||||
==================
|
||||
|
||||
Changed
|
||||
-------
|
||||
|
||||
* Make debug log file less verbose
|
||||
|
||||
|
||||
0.1.1 - 2021-07-18
|
||||
==================
|
||||
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import os.path
|
|||
from PyQt6 import QtCore
|
||||
|
||||
from beeref import constants
|
||||
from beeref.logging import qt_message_handler
|
||||
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
|
|
@ -161,7 +162,7 @@ logging_conf = {
|
|||
'level': CommandlineArgs().loglevel,
|
||||
},
|
||||
'file': {
|
||||
'class': 'beeref.utils.BeeRotatingFileHandler',
|
||||
'class': 'beeref.logging.BeeRotatingFileHandler',
|
||||
'formatter': 'verbose',
|
||||
'filename': logfile_name(),
|
||||
'maxBytes': 1024 * 1000, # 1MB
|
||||
|
|
@ -173,7 +174,7 @@ logging_conf = {
|
|||
'loggers': {
|
||||
'beeref': {
|
||||
'handlers': ['console', 'file'],
|
||||
'level': 'DEBUG',
|
||||
'level': 'TRACE',
|
||||
'propagate': False,
|
||||
},
|
||||
},
|
||||
|
|
@ -183,27 +184,7 @@ logging_conf = {
|
|||
},
|
||||
}
|
||||
|
||||
|
||||
logging.config.dictConfig(logging_conf)
|
||||
|
||||
|
||||
# Redirect Qt logging to Python logger:
|
||||
qtlogger = logging.getLogger('Qt')
|
||||
|
||||
|
||||
def qt_message_handler(mode, context, message):
|
||||
logfuncs = {
|
||||
QtCore.QtMsgType.QtDebugMsg: qtlogger.debug,
|
||||
QtCore.QtMsgType.QtInfoMsg: qtlogger.info,
|
||||
QtCore.QtMsgType.QtWarningMsg: qtlogger.warning,
|
||||
QtCore.QtMsgType.QtCriticalMsg: qtlogger.critical,
|
||||
QtCore.QtMsgType.QtFatalMsg: qtlogger.fatal,
|
||||
}
|
||||
if context and (context.file or context.line or context.function):
|
||||
message = (f'{message}: File {context.file}, line {context.line}, '
|
||||
f'in {context.function}')
|
||||
|
||||
logfuncs[mode](message)
|
||||
|
||||
|
||||
QtCore.qInstallMessageHandler(qt_message_handler)
|
||||
|
|
|
|||
62
beeref/logging.py
Normal file
62
beeref/logging.py
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
# This file is part of BeeRef.
|
||||
#
|
||||
# BeeRef is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# BeeRef is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with BeeRef. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import logging
|
||||
import logging.handlers
|
||||
import os.path
|
||||
|
||||
from PyQt6 import QtCore
|
||||
|
||||
|
||||
logging.TRACE = 5
|
||||
|
||||
|
||||
class BeeLogger(logging.Logger):
|
||||
|
||||
def __init__(self, name, level=logging.NOTSET):
|
||||
super().__init__(name, level)
|
||||
logging.addLevelName(logging.TRACE, 'TRACE')
|
||||
|
||||
def trace(self, msg, *args, **kwargs):
|
||||
self.log(logging.TRACE, msg, *args, **kwargs)
|
||||
|
||||
|
||||
logging.setLoggerClass(BeeLogger)
|
||||
|
||||
|
||||
class BeeRotatingFileHandler(logging.handlers.RotatingFileHandler):
|
||||
"""RotatingFileHandler that creates log directory if necessary."""
|
||||
|
||||
def __init__(self, filename, **kwargs):
|
||||
os.makedirs(os.path.dirname(filename), exist_ok=True)
|
||||
super().__init__(filename, **kwargs)
|
||||
|
||||
|
||||
qtlogger = logging.getLogger('Qt')
|
||||
|
||||
|
||||
def qt_message_handler(mode, context, message):
|
||||
logfuncs = {
|
||||
QtCore.QtMsgType.QtDebugMsg: qtlogger.debug,
|
||||
QtCore.QtMsgType.QtInfoMsg: qtlogger.info,
|
||||
QtCore.QtMsgType.QtWarningMsg: qtlogger.warning,
|
||||
QtCore.QtMsgType.QtCriticalMsg: qtlogger.critical,
|
||||
QtCore.QtMsgType.QtFatalMsg: qtlogger.fatal,
|
||||
}
|
||||
if context and (context.file or context.line or context.function):
|
||||
message = (f'{message}: File {context.file}, line {context.line}, '
|
||||
f'in {context.function}')
|
||||
|
||||
logfuncs[mode](message)
|
||||
|
|
@ -70,11 +70,3 @@ def round_to(number, base):
|
|||
"""
|
||||
|
||||
return base * round(number / base)
|
||||
|
||||
|
||||
class BeeRotatingFileHandler(logging.handlers.RotatingFileHandler):
|
||||
"""RotatingFileHandler that creates log directory if necessary."""
|
||||
|
||||
def __init__(self, filename, **kwargs):
|
||||
os.makedirs(os.path.dirname(filename), exist_ok=True)
|
||||
super().__init__(filename, **kwargs)
|
||||
|
|
|
|||
|
|
@ -471,7 +471,7 @@ class BeeGraphicsView(QtWidgets.QGraphicsView, ActionsMixin):
|
|||
|
||||
if self.previous_transform:
|
||||
return
|
||||
logger.debug('Recalculating scene rectangle...')
|
||||
logger.trace('Recalculating scene rectangle...')
|
||||
try:
|
||||
topleft = self.mapFromScene(
|
||||
self.scene.itemsBoundingRect().topLeft())
|
||||
|
|
@ -486,7 +486,7 @@ class BeeGraphicsView(QtWidgets.QGraphicsView, ActionsMixin):
|
|||
self.setSceneRect(QtCore.QRectF(topleft, bottomright))
|
||||
except OverflowError:
|
||||
logger.info('Maximum scene size reached')
|
||||
logger.debug('Done recalculating scene rectangle')
|
||||
logger.trace('Done recalculating scene rectangle')
|
||||
|
||||
def get_zoom_size(self, func):
|
||||
"""Calculates the size of all items' bounding box in the view's
|
||||
|
|
|
|||
|
|
@ -1,13 +1,10 @@
|
|||
import os.path
|
||||
import tempfile
|
||||
from types import SimpleNamespace
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
|
||||
from PyQt6 import QtCore
|
||||
|
||||
from beeref.config import CommandlineArgs, qt_message_handler
|
||||
from beeref.config import CommandlineArgs
|
||||
|
||||
|
||||
def test_command_line_args_singleton():
|
||||
|
|
@ -74,16 +71,3 @@ def test_settings_recent_files_update_respects_max_num(settings):
|
|||
assert len(recent) == 10
|
||||
assert recent[0] == os.path.abspath('14.bee')
|
||||
assert recent[-1] == os.path.abspath('5.bee')
|
||||
|
||||
|
||||
@patch('beeref.config.qtlogger.info')
|
||||
def test_qt_message_handler_without(log_mock, qapp):
|
||||
qt_message_handler(QtCore.QtMsgType.QtInfoMsg, None, 'foo')
|
||||
log_mock.assert_called_once_with('foo')
|
||||
|
||||
|
||||
@patch('beeref.config.qtlogger.warning')
|
||||
def test_qt_message_handler_with_context(log_mock, qapp):
|
||||
ctx = SimpleNamespace(file='bla.txt', line='1', function='myfunc')
|
||||
qt_message_handler(QtCore.QtMsgType.QtWarningMsg, ctx, 'foo')
|
||||
log_mock.assert_called_once_with('foo: File bla.txt, line 1, in myfunc')
|
||||
|
|
|
|||
55
tests/test_logging.py
Normal file
55
tests/test_logging.py
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
import logging
|
||||
import os.path
|
||||
from types import SimpleNamespace
|
||||
from unittest.mock import patch
|
||||
|
||||
from PyQt6 import QtCore
|
||||
|
||||
from beeref.logging import (
|
||||
BeeLogger,
|
||||
BeeRotatingFileHandler,
|
||||
qt_message_handler,
|
||||
)
|
||||
|
||||
|
||||
def test_sets_new_loglevel():
|
||||
assert logging.getLevelName(5) == 'TRACE'
|
||||
|
||||
|
||||
@patch('beeref.logging.BeeLogger.log')
|
||||
def test_beelogger(log_mock):
|
||||
logger = BeeLogger('mylogger', logging.TRACE)
|
||||
logger.trace('blah: %s', 'spam', extra={'foo': 'bar'})
|
||||
log_mock.assert_called_once_with(
|
||||
logging.TRACE, 'blah: %s', 'spam', extra={'foo': 'bar'})
|
||||
|
||||
|
||||
def test_rotating_file_handler_creates_new_dir(tmpdir):
|
||||
logfile = os.path.join(tmpdir, 'foo', 'bar.log')
|
||||
handler = BeeRotatingFileHandler(logfile)
|
||||
handler.emit(logging.LogRecord(
|
||||
'foo', logging.INFO, 'bar', 66, 'baz', [], None))
|
||||
handler.close()
|
||||
assert os.path.exists(logfile)
|
||||
|
||||
|
||||
def testrotating_file_handler_uses_existing_dir(tmpdir):
|
||||
logfile = os.path.join(tmpdir, 'bar.log')
|
||||
handler = BeeRotatingFileHandler(logfile)
|
||||
handler.emit(logging.LogRecord(
|
||||
'foo', logging.INFO, 'bar', 66, 'baz', [], None))
|
||||
handler.close()
|
||||
assert os.path.exists(logfile)
|
||||
|
||||
|
||||
@patch('beeref.logging.qtlogger.info')
|
||||
def test_qt_message_handler_without(log_mock, qapp):
|
||||
qt_message_handler(QtCore.QtMsgType.QtInfoMsg, None, 'foo')
|
||||
log_mock.assert_called_once_with('foo')
|
||||
|
||||
|
||||
@patch('beeref.logging.qtlogger.warning')
|
||||
def test_qt_message_handler_with_context(log_mock, qapp):
|
||||
ctx = SimpleNamespace(file='bla.txt', line='1', function='myfunc')
|
||||
qt_message_handler(QtCore.QtMsgType.QtWarningMsg, ctx, 'foo')
|
||||
log_mock.assert_called_once_with('foo: File bla.txt, line 1, in myfunc')
|
||||
|
|
@ -1,5 +1,3 @@
|
|||
import logging
|
||||
import os.path
|
||||
import pytest
|
||||
|
||||
from PyQt6 import QtCore, QtGui
|
||||
|
|
@ -65,21 +63,3 @@ def test_get_rect_from_points_given_topright_bottomleft():
|
|||
(3.1, 0.5, 3.0)])
|
||||
def test_round_to(number, base, expected):
|
||||
assert utils.round_to(number, base) == expected
|
||||
|
||||
|
||||
def test_rotating_file_handler_creates_new_dir(tmpdir):
|
||||
logfile = os.path.join(tmpdir, 'foo', 'bar.log')
|
||||
handler = utils.BeeRotatingFileHandler(logfile)
|
||||
handler.emit(logging.LogRecord(
|
||||
'foo', logging.INFO, 'bar', 66, 'baz', [], None))
|
||||
handler.close()
|
||||
assert os.path.exists(logfile)
|
||||
|
||||
|
||||
def testrotating_file_handler_uses_existing_dir(tmpdir):
|
||||
logfile = os.path.join(tmpdir, 'bar.log')
|
||||
handler = utils.BeeRotatingFileHandler(logfile)
|
||||
handler.emit(logging.LogRecord(
|
||||
'foo', logging.INFO, 'bar', 66, 'baz', [], None))
|
||||
handler.close()
|
||||
assert os.path.exists(logfile)
|
||||
|
|
|
|||
Loading…
Reference in a new issue