Merge branch 'develop' into pr/hippocritical/8369

This commit is contained in:
Matthias
2023-06-09 07:03:25 +02:00
6 changed files with 167 additions and 153 deletions
+1 -1
View File
@@ -1,4 +1,4 @@
FROM python:3.10.11-slim-bullseye as base FROM python:3.11.4-slim-bullseye as base
# Setup env # Setup env
ENV LANG C.UTF-8 ENV LANG C.UTF-8
+2 -24
View File
@@ -5,6 +5,7 @@ from logging.handlers import RotatingFileHandler, SysLogHandler
from freqtrade.constants import Config from freqtrade.constants import Config
from freqtrade.exceptions import OperationalException from freqtrade.exceptions import OperationalException
from freqtrade.loggers.buffering_handler import FTBufferingHandler from freqtrade.loggers.buffering_handler import FTBufferingHandler
from freqtrade.loggers.set_log_levels import set_loggers
from freqtrade.loggers.std_err_stream_handler import FTStdErrStreamHandler from freqtrade.loggers.std_err_stream_handler import FTStdErrStreamHandler
@@ -16,29 +17,6 @@ bufferHandler = FTBufferingHandler(1000)
bufferHandler.setFormatter(Formatter(LOGFORMAT)) bufferHandler.setFormatter(Formatter(LOGFORMAT))
def _set_loggers(verbosity: int = 0, api_verbosity: str = 'info') -> None:
"""
Set the logging level for third party libraries
:return: None
"""
logging.getLogger('requests').setLevel(
logging.INFO if verbosity <= 1 else logging.DEBUG
)
logging.getLogger("urllib3").setLevel(
logging.INFO if verbosity <= 1 else logging.DEBUG
)
logging.getLogger('ccxt.base.exchange').setLevel(
logging.INFO if verbosity <= 2 else logging.DEBUG
)
logging.getLogger('telegram').setLevel(logging.INFO)
logging.getLogger('httpx').setLevel(logging.WARNING)
logging.getLogger('werkzeug').setLevel(
logging.ERROR if api_verbosity == 'error' else logging.INFO
)
def get_existing_handlers(handlertype): def get_existing_handlers(handlertype):
""" """
Returns Existing handler or None (if the handler has not yet been added to the root handlers). Returns Existing handler or None (if the handler has not yet been added to the root handlers).
@@ -115,6 +93,6 @@ def setup_logging(config: Config) -> None:
logging.root.addHandler(handler_rf) logging.root.addHandler(handler_rf)
logging.root.setLevel(logging.INFO if verbosity < 1 else logging.DEBUG) logging.root.setLevel(logging.INFO if verbosity < 1 else logging.DEBUG)
_set_loggers(verbosity, config.get('api_server', {}).get('verbosity', 'info')) set_loggers(verbosity, config.get('api_server', {}).get('verbosity', 'info'))
logger.info('Verbosity set to %s', verbosity) logger.info('Verbosity set to %s', verbosity)
+25
View File
@@ -0,0 +1,25 @@
import logging
def set_loggers(verbosity: int = 0, api_verbosity: str = 'info') -> None:
"""
Set the logging level for third party libraries
:return: None
"""
logging.getLogger('requests').setLevel(
logging.INFO if verbosity <= 1 else logging.DEBUG
)
logging.getLogger("urllib3").setLevel(
logging.INFO if verbosity <= 1 else logging.DEBUG
)
logging.getLogger('ccxt.base.exchange').setLevel(
logging.INFO if verbosity <= 2 else logging.DEBUG
)
logging.getLogger('telegram').setLevel(logging.INFO)
logging.getLogger('httpx').setLevel(logging.WARNING)
logging.getLogger('werkzeug').setLevel(
logging.ERROR if api_verbosity == 'error' else logging.INFO
)
+8 -2
View File
@@ -1114,7 +1114,9 @@ class Telegram(RPCHandler):
async def _force_exit_action(self, trade_id): async def _force_exit_action(self, trade_id):
if trade_id != 'cancel': if trade_id != 'cancel':
try: try:
self._rpc._rpc_force_exit(trade_id) loop = asyncio.get_running_loop()
# Workaround to avoid nested loops
await loop.run_in_executor(None, self._rpc._rpc_force_exit, trade_id)
except RPCException as e: except RPCException as e:
await self._send_msg(str(e)) await self._send_msg(str(e))
@@ -1140,7 +1142,11 @@ class Telegram(RPCHandler):
async def _force_enter_action(self, pair, price: Optional[float], order_side: SignalDirection): async def _force_enter_action(self, pair, price: Optional[float], order_side: SignalDirection):
if pair != 'cancel': if pair != 'cancel':
try: try:
self._rpc._rpc_force_entry(pair, price, order_side=order_side) def _force_enter():
self._rpc._rpc_force_entry(pair, price, order_side=order_side)
loop = asyncio.get_running_loop()
# Workaround to avoid nested loops
await loop.run_in_executor(None, _force_enter)
except RPCException as e: except RPCException as e:
logger.exception("Forcebuy error!") logger.exception("Forcebuy error!")
await self._send_msg(str(e), ParseMode.HTML) await self._send_msg(str(e), ParseMode.HTML)
+1 -126
View File
@@ -1,7 +1,5 @@
# pragma pylint: disable=missing-docstring, protected-access, invalid-name # pragma pylint: disable=missing-docstring, protected-access, invalid-name
import json import json
import logging
import sys
import warnings import warnings
from copy import deepcopy from copy import deepcopy
from pathlib import Path from pathlib import Path
@@ -23,8 +21,6 @@ from freqtrade.configuration.load_config import (load_config_file, load_file, lo
from freqtrade.constants import DEFAULT_DB_DRYRUN_URL, DEFAULT_DB_PROD_URL, ENV_VAR_PREFIX from freqtrade.constants import DEFAULT_DB_DRYRUN_URL, DEFAULT_DB_PROD_URL, ENV_VAR_PREFIX
from freqtrade.enums import RunMode from freqtrade.enums import RunMode
from freqtrade.exceptions import OperationalException from freqtrade.exceptions import OperationalException
from freqtrade.loggers import (FTBufferingHandler, FTStdErrStreamHandler, _set_loggers,
setup_logging, setup_logging_pre)
from tests.conftest import (CURRENT_TEST_STRATEGY, log_has, log_has_re, from tests.conftest import (CURRENT_TEST_STRATEGY, log_has, log_has_re,
patched_configuration_load_config_file) patched_configuration_load_config_file)
@@ -594,7 +590,7 @@ def test_cli_verbose_with_params(default_conf, mocker, caplog) -> None:
patched_configuration_load_config_file(mocker, default_conf) patched_configuration_load_config_file(mocker, default_conf)
# Prevent setting loggers # Prevent setting loggers
mocker.patch('freqtrade.loggers._set_loggers', MagicMock) mocker.patch('freqtrade.loggers.set_loggers', MagicMock)
arglist = ['trade', '-vvv'] arglist = ['trade', '-vvv']
args = Arguments(arglist).get_parsed_arg() args = Arguments(arglist).get_parsed_arg()
@@ -605,127 +601,6 @@ def test_cli_verbose_with_params(default_conf, mocker, caplog) -> None:
assert log_has('Verbosity set to 3', caplog) assert log_has('Verbosity set to 3', caplog)
def test_set_loggers() -> None:
# Reset Logging to Debug, otherwise this fails randomly as it's set globally
logging.getLogger('requests').setLevel(logging.DEBUG)
logging.getLogger("urllib3").setLevel(logging.DEBUG)
logging.getLogger('ccxt.base.exchange').setLevel(logging.DEBUG)
logging.getLogger('telegram').setLevel(logging.DEBUG)
previous_value1 = logging.getLogger('requests').level
previous_value2 = logging.getLogger('ccxt.base.exchange').level
previous_value3 = logging.getLogger('telegram').level
_set_loggers()
value1 = logging.getLogger('requests').level
assert previous_value1 is not value1
assert value1 is logging.INFO
value2 = logging.getLogger('ccxt.base.exchange').level
assert previous_value2 is not value2
assert value2 is logging.INFO
value3 = logging.getLogger('telegram').level
assert previous_value3 is not value3
assert value3 is logging.INFO
_set_loggers(verbosity=2)
assert logging.getLogger('requests').level is logging.DEBUG
assert logging.getLogger('ccxt.base.exchange').level is logging.INFO
assert logging.getLogger('telegram').level is logging.INFO
assert logging.getLogger('werkzeug').level is logging.INFO
_set_loggers(verbosity=3, api_verbosity='error')
assert logging.getLogger('requests').level is logging.DEBUG
assert logging.getLogger('ccxt.base.exchange').level is logging.DEBUG
assert logging.getLogger('telegram').level is logging.INFO
assert logging.getLogger('werkzeug').level is logging.ERROR
@pytest.mark.skipif(sys.platform == "win32", reason="does not run on windows")
def test_set_loggers_syslog():
logger = logging.getLogger()
orig_handlers = logger.handlers
logger.handlers = []
config = {'verbosity': 2,
'logfile': 'syslog:/dev/log',
}
setup_logging_pre()
setup_logging(config)
assert len(logger.handlers) == 3
assert [x for x in logger.handlers if type(x) == logging.handlers.SysLogHandler]
assert [x for x in logger.handlers if type(x) == FTStdErrStreamHandler]
assert [x for x in logger.handlers if type(x) == FTBufferingHandler]
# setting up logging again should NOT cause the loggers to be added a second time.
setup_logging(config)
assert len(logger.handlers) == 3
# reset handlers to not break pytest
logger.handlers = orig_handlers
@pytest.mark.skipif(sys.platform == "win32", reason="does not run on windows")
def test_set_loggers_Filehandler(tmpdir):
logger = logging.getLogger()
orig_handlers = logger.handlers
logger.handlers = []
logfile = Path(tmpdir) / 'ft_logfile.log'
config = {'verbosity': 2,
'logfile': str(logfile),
}
setup_logging_pre()
setup_logging(config)
assert len(logger.handlers) == 3
assert [x for x in logger.handlers if type(x) == logging.handlers.RotatingFileHandler]
assert [x for x in logger.handlers if type(x) == FTStdErrStreamHandler]
assert [x for x in logger.handlers if type(x) == FTBufferingHandler]
# setting up logging again should NOT cause the loggers to be added a second time.
setup_logging(config)
assert len(logger.handlers) == 3
# reset handlers to not break pytest
if logfile.exists:
logfile.unlink()
logger.handlers = orig_handlers
@pytest.mark.skip(reason="systemd is not installed on every system, so we're not testing this.")
def test_set_loggers_journald(mocker):
logger = logging.getLogger()
orig_handlers = logger.handlers
logger.handlers = []
config = {'verbosity': 2,
'logfile': 'journald',
}
setup_logging_pre()
setup_logging(config)
assert len(logger.handlers) == 3
assert [x for x in logger.handlers if type(x).__name__ == "JournaldLogHandler"]
assert [x for x in logger.handlers if type(x) == FTStdErrStreamHandler]
# reset handlers to not break pytest
logger.handlers = orig_handlers
def test_set_loggers_journald_importerror(import_fails):
logger = logging.getLogger()
orig_handlers = logger.handlers
logger.handlers = []
config = {'verbosity': 2,
'logfile': 'journald',
}
with pytest.raises(OperationalException,
match=r'You need the cysystemd python package.*'):
setup_logging(config)
logger.handlers = orig_handlers
def test_set_logfile(default_conf, mocker, tmpdir): def test_set_logfile(default_conf, mocker, tmpdir):
patched_configuration_load_config_file(mocker, default_conf) patched_configuration_load_config_file(mocker, default_conf)
f = Path(tmpdir / "test_file.log") f = Path(tmpdir / "test_file.log")
+130
View File
@@ -0,0 +1,130 @@
import logging
import sys
from pathlib import Path
import pytest
from freqtrade.exceptions import OperationalException
from freqtrade.loggers import (FTBufferingHandler, FTStdErrStreamHandler, set_loggers,
setup_logging, setup_logging_pre)
def test_set_loggers() -> None:
# Reset Logging to Debug, otherwise this fails randomly as it's set globally
logging.getLogger('requests').setLevel(logging.DEBUG)
logging.getLogger("urllib3").setLevel(logging.DEBUG)
logging.getLogger('ccxt.base.exchange').setLevel(logging.DEBUG)
logging.getLogger('telegram').setLevel(logging.DEBUG)
previous_value1 = logging.getLogger('requests').level
previous_value2 = logging.getLogger('ccxt.base.exchange').level
previous_value3 = logging.getLogger('telegram').level
set_loggers()
value1 = logging.getLogger('requests').level
assert previous_value1 is not value1
assert value1 is logging.INFO
value2 = logging.getLogger('ccxt.base.exchange').level
assert previous_value2 is not value2
assert value2 is logging.INFO
value3 = logging.getLogger('telegram').level
assert previous_value3 is not value3
assert value3 is logging.INFO
set_loggers(verbosity=2)
assert logging.getLogger('requests').level is logging.DEBUG
assert logging.getLogger('ccxt.base.exchange').level is logging.INFO
assert logging.getLogger('telegram').level is logging.INFO
assert logging.getLogger('werkzeug').level is logging.INFO
set_loggers(verbosity=3, api_verbosity='error')
assert logging.getLogger('requests').level is logging.DEBUG
assert logging.getLogger('ccxt.base.exchange').level is logging.DEBUG
assert logging.getLogger('telegram').level is logging.INFO
assert logging.getLogger('werkzeug').level is logging.ERROR
@pytest.mark.skipif(sys.platform == "win32", reason="does not run on windows")
def test_set_loggers_syslog():
logger = logging.getLogger()
orig_handlers = logger.handlers
logger.handlers = []
config = {'verbosity': 2,
'logfile': 'syslog:/dev/log',
}
setup_logging_pre()
setup_logging(config)
assert len(logger.handlers) == 3
assert [x for x in logger.handlers if type(x) == logging.handlers.SysLogHandler]
assert [x for x in logger.handlers if type(x) == FTStdErrStreamHandler]
assert [x for x in logger.handlers if type(x) == FTBufferingHandler]
# setting up logging again should NOT cause the loggers to be added a second time.
setup_logging(config)
assert len(logger.handlers) == 3
# reset handlers to not break pytest
logger.handlers = orig_handlers
@pytest.mark.skipif(sys.platform == "win32", reason="does not run on windows")
def test_set_loggers_Filehandler(tmpdir):
logger = logging.getLogger()
orig_handlers = logger.handlers
logger.handlers = []
logfile = Path(tmpdir) / 'ft_logfile.log'
config = {'verbosity': 2,
'logfile': str(logfile),
}
setup_logging_pre()
setup_logging(config)
assert len(logger.handlers) == 3
assert [x for x in logger.handlers if type(x) == logging.handlers.RotatingFileHandler]
assert [x for x in logger.handlers if type(x) == FTStdErrStreamHandler]
assert [x for x in logger.handlers if type(x) == FTBufferingHandler]
# setting up logging again should NOT cause the loggers to be added a second time.
setup_logging(config)
assert len(logger.handlers) == 3
# reset handlers to not break pytest
if logfile.exists:
logfile.unlink()
logger.handlers = orig_handlers
@pytest.mark.skip(reason="systemd is not installed on every system, so we're not testing this.")
def test_set_loggers_journald(mocker):
logger = logging.getLogger()
orig_handlers = logger.handlers
logger.handlers = []
config = {'verbosity': 2,
'logfile': 'journald',
}
setup_logging_pre()
setup_logging(config)
assert len(logger.handlers) == 3
assert [x for x in logger.handlers if type(x).__name__ == "JournaldLogHandler"]
assert [x for x in logger.handlers if type(x) == FTStdErrStreamHandler]
# reset handlers to not break pytest
logger.handlers = orig_handlers
def test_set_loggers_journald_importerror(import_fails):
logger = logging.getLogger()
orig_handlers = logger.handlers
logger.handlers = []
config = {'verbosity': 2,
'logfile': 'journald',
}
with pytest.raises(OperationalException,
match=r'You need the cysystemd python package.*'):
setup_logging(config)
logger.handlers = orig_handlers