forked from Tribler/tribler
-
Notifications
You must be signed in to change notification settings - Fork 0
/
logger.py
83 lines (65 loc) · 3.24 KB
/
logger.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
import logging
import logging.config
import sys
from pathlib import Path
import yaml
LOG_CONFIG_FILENAME = 'logger.yaml'
logger = logging.getLogger(__name__)
# note: this class is used by logger.yaml
class StdoutFilter(logging.Filter):
def filter(self, record):
return record.levelno < logging.ERROR
def load_logger_config(app_mode, log_dir, current_process_is_primary=True):
"""
Loads tribler-gui module logger configuration. Note that this function should be called explicitly to
enable GUI logs dump to a file in the log directory (default: inside state directory).
"""
if current_process_is_primary:
# Set up logging to files for primary process only, as logging module does not support
# writing to the same log file from multiple Python processes
logger_config_path = get_logger_config_path()
setup_logging(app_mode, Path(log_dir), logger_config_path)
else:
logger.info('Skip the initialization of a normal file-based logging as the current process is non-primary.\n'
'Continue using the basic logging config from the boot logger initialization.\n'
'Only primary Tribler process can write to Tribler log files, as logging module does not support\n'
'writing to files from multiple Python processes.')
def get_logger_config_path():
if not hasattr(sys, '_MEIPASS'):
dirname = Path(__file__).absolute().parent
else:
dirname = Path(getattr(sys, '_MEIPASS')) / "tribler_source/tribler/core/logger"
return dirname / LOG_CONFIG_FILENAME
def setup_logging(app_mode, log_dir: Path, config_path: Path):
"""
Setup logging configuration with the given YAML file.
"""
logger.info(f'Load logger config: app_mode={app_mode}, config_path={config_path}, dir={log_dir}')
if not config_path.exists():
print(f'Logger config not found in {config_path}. Using default configs.', file=sys.stderr)
logging.basicConfig(level=logging.INFO, stream=sys.stdout)
return
try:
# Update the log file paths in the config
module_info_log_file = log_dir.joinpath(f"{app_mode}-info.log")
module_error_log_file = log_dir.joinpath(f"{app_mode}-error.log")
with config_path.open() as f:
config_text = f.read()
config_text = config_text.replace('TRIBLER_INFO_LOG_FILE', str(module_info_log_file))
config_text = config_text.replace('TRIBLER_ERROR_LOG_FILE', str(module_error_log_file))
# Create log directory if it does not exist
if not log_dir.exists():
log_dir.mkdir(parents=True)
config = yaml.safe_load(config_text)
logging.config.dictConfig(config)
logger.info(f'Config loaded for app_mode={app_mode}')
except Exception as e: # pylint: disable=broad-except
error_description = format_error_description(e)
print('Error in loading logger config. Using default configs. ', error_description, file=sys.stderr)
logging.basicConfig(level=logging.INFO, stream=sys.stdout)
def format_error_description(e: Exception):
result = f'{e.__class__.__name__}: {e}'
cause = e.__cause__
if cause:
result += f'. Cause: {cause.__class__.__name__}: {cause}'
return result