Add multiple verbosity levels
This commit is contained in:
parent
62701888c9
commit
dd1290e38e
@ -3,7 +3,6 @@ This module contains the argument manager class
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import logging
|
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
from typing import List, NamedTuple, Optional
|
from typing import List, NamedTuple, Optional
|
||||||
@ -64,11 +63,10 @@ class Arguments(object):
|
|||||||
"""
|
"""
|
||||||
self.parser.add_argument(
|
self.parser.add_argument(
|
||||||
'-v', '--verbose',
|
'-v', '--verbose',
|
||||||
help='be verbose',
|
help='verbose mode (-vv for more, -vvv to get all messages)',
|
||||||
action='store_const',
|
action='count',
|
||||||
dest='loglevel',
|
dest='loglevel',
|
||||||
const=logging.DEBUG,
|
default=0,
|
||||||
default=logging.INFO,
|
|
||||||
)
|
)
|
||||||
self.parser.add_argument(
|
self.parser.add_argument(
|
||||||
'--version',
|
'--version',
|
||||||
|
@ -12,10 +12,22 @@ from jsonschema import Draft4Validator, validate
|
|||||||
from jsonschema.exceptions import ValidationError, best_match
|
from jsonschema.exceptions import ValidationError, best_match
|
||||||
|
|
||||||
from freqtrade import OperationalException, constants
|
from freqtrade import OperationalException, constants
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def set_loggers(log_level: int = 0) -> None:
|
||||||
|
"""
|
||||||
|
Set the logger level for Third party libs
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
|
|
||||||
|
logging.getLogger('requests').setLevel(logging.INFO if log_level <= 1 else logging.DEBUG)
|
||||||
|
logging.getLogger("urllib3").setLevel(logging.INFO if log_level <= 1 else logging.DEBUG)
|
||||||
|
logging.getLogger('ccxt.base.exchange').setLevel(
|
||||||
|
logging.INFO if log_level <= 2 else logging.DEBUG)
|
||||||
|
logging.getLogger('telegram').setLevel(logging.INFO)
|
||||||
|
|
||||||
|
|
||||||
class Configuration(object):
|
class Configuration(object):
|
||||||
"""
|
"""
|
||||||
Class to read and init the bot configuration
|
Class to read and init the bot configuration
|
||||||
@ -79,12 +91,15 @@ class Configuration(object):
|
|||||||
|
|
||||||
# Log level
|
# Log level
|
||||||
if 'loglevel' in self.args and self.args.loglevel:
|
if 'loglevel' in self.args and self.args.loglevel:
|
||||||
config.update({'loglevel': self.args.loglevel})
|
config.update({'verbosity': self.args.loglevel})
|
||||||
|
else:
|
||||||
|
config.update({'verbosity': 0})
|
||||||
logging.basicConfig(
|
logging.basicConfig(
|
||||||
level=config['loglevel'],
|
level=logging.INFO if config['verbosity'] < 1 else logging.DEBUG,
|
||||||
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
|
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
|
||||||
)
|
)
|
||||||
logger.info('Log level set to %s', logging.getLevelName(config['loglevel']))
|
set_loggers(config['verbosity'])
|
||||||
|
logger.info('Verbosity set to %s', config['verbosity'])
|
||||||
|
|
||||||
# Add dynamic_whitelist if found
|
# Add dynamic_whitelist if found
|
||||||
if 'dynamic_whitelist' in self.args and self.args.dynamic_whitelist:
|
if 'dynamic_whitelist' in self.args and self.args.dynamic_whitelist:
|
||||||
|
@ -10,7 +10,7 @@ from typing import List
|
|||||||
|
|
||||||
from freqtrade import OperationalException
|
from freqtrade import OperationalException
|
||||||
from freqtrade.arguments import Arguments
|
from freqtrade.arguments import Arguments
|
||||||
from freqtrade.configuration import Configuration
|
from freqtrade.configuration import Configuration, set_loggers
|
||||||
from freqtrade.freqtradebot import FreqtradeBot
|
from freqtrade.freqtradebot import FreqtradeBot
|
||||||
from freqtrade.state import State
|
from freqtrade.state import State
|
||||||
from freqtrade.rpc import RPCMessageType
|
from freqtrade.rpc import RPCMessageType
|
||||||
@ -84,16 +84,6 @@ def reconfigure(freqtrade: FreqtradeBot, args: Namespace) -> FreqtradeBot:
|
|||||||
return freqtrade
|
return freqtrade
|
||||||
|
|
||||||
|
|
||||||
def set_loggers() -> None:
|
|
||||||
"""
|
|
||||||
Set the logger level for Third party libs
|
|
||||||
:return: None
|
|
||||||
"""
|
|
||||||
logging.getLogger('requests.packages.urllib3').setLevel(logging.INFO)
|
|
||||||
logging.getLogger('ccxt.base.exchange').setLevel(logging.INFO)
|
|
||||||
logging.getLogger('telegram').setLevel(logging.INFO)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
set_loggers()
|
set_loggers()
|
||||||
main(sys.argv[1:])
|
main(sys.argv[1:])
|
||||||
|
@ -5,7 +5,6 @@ Unit test file for arguments.py
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import logging
|
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
@ -35,7 +34,7 @@ def test_parse_args_defaults() -> None:
|
|||||||
args = Arguments([], '').get_parsed_arg()
|
args = Arguments([], '').get_parsed_arg()
|
||||||
assert args.config == 'config.json'
|
assert args.config == 'config.json'
|
||||||
assert args.dynamic_whitelist is None
|
assert args.dynamic_whitelist is None
|
||||||
assert args.loglevel == logging.INFO
|
assert args.loglevel == 0
|
||||||
|
|
||||||
|
|
||||||
def test_parse_args_config() -> None:
|
def test_parse_args_config() -> None:
|
||||||
@ -53,10 +52,10 @@ def test_parse_args_db_url() -> None:
|
|||||||
|
|
||||||
def test_parse_args_verbose() -> None:
|
def test_parse_args_verbose() -> None:
|
||||||
args = Arguments(['-v'], '').get_parsed_arg()
|
args = Arguments(['-v'], '').get_parsed_arg()
|
||||||
assert args.loglevel == logging.DEBUG
|
assert args.loglevel == 1
|
||||||
|
|
||||||
args = Arguments(['--verbose'], '').get_parsed_arg()
|
args = Arguments(['--verbose'], '').get_parsed_arg()
|
||||||
assert args.loglevel == logging.DEBUG
|
assert args.loglevel == 1
|
||||||
|
|
||||||
|
|
||||||
def test_scripts_options() -> None:
|
def test_scripts_options() -> None:
|
||||||
@ -153,7 +152,7 @@ def test_parse_args_backtesting_custom() -> None:
|
|||||||
call_args = Arguments(args, '').get_parsed_arg()
|
call_args = Arguments(args, '').get_parsed_arg()
|
||||||
assert call_args.config == 'test_conf.json'
|
assert call_args.config == 'test_conf.json'
|
||||||
assert call_args.live is True
|
assert call_args.live is True
|
||||||
assert call_args.loglevel == logging.INFO
|
assert call_args.loglevel == 0
|
||||||
assert call_args.subparser == 'backtesting'
|
assert call_args.subparser == 'backtesting'
|
||||||
assert call_args.func is not None
|
assert call_args.func is not None
|
||||||
assert call_args.ticker_interval == '1m'
|
assert call_args.ticker_interval == '1m'
|
||||||
@ -170,7 +169,7 @@ def test_parse_args_hyperopt_custom() -> None:
|
|||||||
call_args = Arguments(args, '').get_parsed_arg()
|
call_args = Arguments(args, '').get_parsed_arg()
|
||||||
assert call_args.config == 'test_conf.json'
|
assert call_args.config == 'test_conf.json'
|
||||||
assert call_args.epochs == 20
|
assert call_args.epochs == 20
|
||||||
assert call_args.loglevel == logging.INFO
|
assert call_args.loglevel == 0
|
||||||
assert call_args.subparser == 'hyperopt'
|
assert call_args.subparser == 'hyperopt'
|
||||||
assert call_args.spaces == ['buy']
|
assert call_args.spaces == ['buy']
|
||||||
assert call_args.func is not None
|
assert call_args.func is not None
|
||||||
|
@ -6,6 +6,7 @@ Unit test file for configuration.py
|
|||||||
import json
|
import json
|
||||||
from argparse import Namespace
|
from argparse import Namespace
|
||||||
from copy import deepcopy
|
from copy import deepcopy
|
||||||
|
import logging
|
||||||
from unittest.mock import MagicMock
|
from unittest.mock import MagicMock
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
@ -13,7 +14,7 @@ from jsonschema import ValidationError
|
|||||||
|
|
||||||
from freqtrade import OperationalException
|
from freqtrade import OperationalException
|
||||||
from freqtrade.arguments import Arguments
|
from freqtrade.arguments import Arguments
|
||||||
from freqtrade.configuration import Configuration
|
from freqtrade.configuration import Configuration, set_loggers
|
||||||
from freqtrade.constants import DEFAULT_DB_DRYRUN_URL, DEFAULT_DB_PROD_URL
|
from freqtrade.constants import DEFAULT_DB_DRYRUN_URL, DEFAULT_DB_PROD_URL
|
||||||
from freqtrade.tests.conftest import log_has
|
from freqtrade.tests.conftest import log_has
|
||||||
|
|
||||||
@ -406,3 +407,63 @@ def test_check_exchange(default_conf) -> None:
|
|||||||
match=r'.*Exchange "unknown_exchange" not supported.*'
|
match=r'.*Exchange "unknown_exchange" not supported.*'
|
||||||
):
|
):
|
||||||
configuration.check_exchange(conf)
|
configuration.check_exchange(conf)
|
||||||
|
|
||||||
|
|
||||||
|
def test_cli_verbose_with_params(default_conf, mocker, caplog) -> None:
|
||||||
|
"""
|
||||||
|
Test Configuration.load_config() with cli params used
|
||||||
|
"""
|
||||||
|
|
||||||
|
mocker.patch('freqtrade.configuration.open', mocker.mock_open(
|
||||||
|
read_data=json.dumps(default_conf)))
|
||||||
|
# Prevent setting loggers
|
||||||
|
mocker.patch('freqtrade.configuration.set_loggers', MagicMock)
|
||||||
|
arglist = ['-vvv']
|
||||||
|
args = Arguments(arglist, '').get_parsed_arg()
|
||||||
|
|
||||||
|
configuration = Configuration(args)
|
||||||
|
validated_conf = configuration.load_config()
|
||||||
|
|
||||||
|
assert validated_conf.get('verbosity') == 3
|
||||||
|
assert log_has('Verbosity set to 3', caplog.record_tuples)
|
||||||
|
|
||||||
|
|
||||||
|
def test_set_loggers() -> None:
|
||||||
|
"""
|
||||||
|
Test set_loggers() update the logger level for third-party libraries
|
||||||
|
"""
|
||||||
|
# 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(log_level=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
|
||||||
|
|
||||||
|
set_loggers(log_level=3)
|
||||||
|
|
||||||
|
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
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
Unit test file for main.py
|
Unit test file for main.py
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import logging
|
|
||||||
from copy import deepcopy
|
from copy import deepcopy
|
||||||
from unittest.mock import MagicMock
|
from unittest.mock import MagicMock
|
||||||
|
|
||||||
@ -11,7 +10,7 @@ import pytest
|
|||||||
from freqtrade import OperationalException
|
from freqtrade import OperationalException
|
||||||
from freqtrade.arguments import Arguments
|
from freqtrade.arguments import Arguments
|
||||||
from freqtrade.freqtradebot import FreqtradeBot
|
from freqtrade.freqtradebot import FreqtradeBot
|
||||||
from freqtrade.main import main, reconfigure, set_loggers
|
from freqtrade.main import main, reconfigure
|
||||||
from freqtrade.state import State
|
from freqtrade.state import State
|
||||||
from freqtrade.tests.conftest import log_has, patch_exchange
|
from freqtrade.tests.conftest import log_has, patch_exchange
|
||||||
|
|
||||||
@ -27,7 +26,7 @@ def test_parse_args_backtesting(mocker) -> None:
|
|||||||
call_args = backtesting_mock.call_args[0][0]
|
call_args = backtesting_mock.call_args[0][0]
|
||||||
assert call_args.config == 'config.json'
|
assert call_args.config == 'config.json'
|
||||||
assert call_args.live is False
|
assert call_args.live is False
|
||||||
assert call_args.loglevel == 20
|
assert call_args.loglevel == 0
|
||||||
assert call_args.subparser == 'backtesting'
|
assert call_args.subparser == 'backtesting'
|
||||||
assert call_args.func is not None
|
assert call_args.func is not None
|
||||||
assert call_args.ticker_interval is None
|
assert call_args.ticker_interval is None
|
||||||
@ -42,29 +41,11 @@ def test_main_start_hyperopt(mocker) -> None:
|
|||||||
assert hyperopt_mock.call_count == 1
|
assert hyperopt_mock.call_count == 1
|
||||||
call_args = hyperopt_mock.call_args[0][0]
|
call_args = hyperopt_mock.call_args[0][0]
|
||||||
assert call_args.config == 'config.json'
|
assert call_args.config == 'config.json'
|
||||||
assert call_args.loglevel == 20
|
assert call_args.loglevel == 0
|
||||||
assert call_args.subparser == 'hyperopt'
|
assert call_args.subparser == 'hyperopt'
|
||||||
assert call_args.func is not None
|
assert call_args.func is not None
|
||||||
|
|
||||||
|
|
||||||
def test_set_loggers() -> None:
|
|
||||||
"""
|
|
||||||
Test set_loggers() update the logger level for third-party libraries
|
|
||||||
"""
|
|
||||||
previous_value1 = logging.getLogger('requests.packages.urllib3').level
|
|
||||||
previous_value2 = logging.getLogger('telegram').level
|
|
||||||
|
|
||||||
set_loggers()
|
|
||||||
|
|
||||||
value1 = logging.getLogger('requests.packages.urllib3').level
|
|
||||||
assert previous_value1 is not value1
|
|
||||||
assert value1 is logging.INFO
|
|
||||||
|
|
||||||
value2 = logging.getLogger('telegram').level
|
|
||||||
assert previous_value2 is not value2
|
|
||||||
assert value2 is logging.INFO
|
|
||||||
|
|
||||||
|
|
||||||
def test_main_fatal_exception(mocker, default_conf, caplog) -> None:
|
def test_main_fatal_exception(mocker, default_conf, caplog) -> None:
|
||||||
"""
|
"""
|
||||||
Test main() function
|
Test main() function
|
||||||
|
Loading…
Reference in New Issue
Block a user