PyBitmessage/src/debug.py

138 lines
4.2 KiB
Python
Raw Normal View History

# -*- coding: utf-8 -*-
2018-04-08 15:28:08 +00:00
"""
Logging and debuging facility
=============================
Levels:
2018-04-08 15:28:08 +00:00
DEBUG Detailed information, typically of interest only when
diagnosing problems.
INFO Confirmation that things are working as expected.
2018-04-08 15:28:08 +00:00
WARNING An indication that something unexpected happened, or indicative
of some problem in the near future (e.g. disk space low).
The software is still working as expected.
ERROR Due to a more serious problem, the software has not been able
to perform some function.
CRITICAL A serious error, indicating that the program itself may be
unable to continue running.
There are three loggers: `console_only`, `file_only` and `both`.
2018-04-08 15:28:08 +00:00
Use: `from debug import logger` to import this facility into whatever module
you wish to log messages from. Logging is thread-safe so you don't have
to worry about locks, just import and log.
"""
import logging
import logging.config
import os
import sys
2014-10-13 05:59:16 +00:00
import helper_startup
import state
2018-04-08 15:28:08 +00:00
2014-10-13 05:59:16 +00:00
helper_startup.loadConfig()
2018-04-08 15:28:08 +00:00
# Now can be overriden from a config file, which uses standard python
# logging.config.fileConfig interface
# examples are here:
# https://bitmessage.org/forum/index.php/topic,4820.msg11163.html#msg11163
log_level = 'WARNING'
2018-04-08 15:28:08 +00:00
def log_uncaught_exceptions(ex_cls, ex, tb):
logging.critical('Unhandled exception', exc_info=(ex_cls, ex, tb))
2018-04-08 15:28:08 +00:00
2013-07-15 19:45:03 +00:00
def configureLogging():
have_logging = False
try:
2018-04-08 15:28:08 +00:00
logging.config.fileConfig(os.path.join(state.appdata, 'logging.dat'))
have_logging = True
2018-04-08 15:28:08 +00:00
print(
'Loaded logger configuration from %s' %
os.path.join(state.appdata, 'logging.dat'))
except:
if os.path.isfile(os.path.join(state.appdata, 'logging.dat')):
2018-04-08 15:28:08 +00:00
print(
'Failed to load logger configuration from %s, using default'
' logging config\n%s' %
(os.path.join(state.appdata, 'logging.dat'), sys.exc_info()))
else:
2018-04-08 15:28:08 +00:00
# no need to confuse the user if the logger config
# is missing entirely
print('Using default logger configuration')
sys.excepthook = log_uncaught_exceptions
if have_logging:
return False
2013-07-15 19:45:03 +00:00
logging.config.dictConfig({
'version': 1,
'formatters': {
'default': {
'format': u'%(asctime)s - %(levelname)s - %(message)s',
2013-07-15 19:45:03 +00:00
},
},
2013-07-15 19:45:03 +00:00
'handlers': {
'console': {
'class': 'logging.StreamHandler',
'formatter': 'default',
'level': log_level,
'stream': 'ext://sys.stderr'
2013-07-15 19:45:03 +00:00
},
'file': {
'class': 'logging.handlers.RotatingFileHandler',
'formatter': 'default',
'level': log_level,
'filename': state.appdata + 'debug.log',
2018-04-08 15:28:08 +00:00
'maxBytes': 2097152, # 2 MiB
2013-07-15 19:45:03 +00:00
'backupCount': 1,
'encoding': 'UTF-8',
2013-07-15 19:45:03 +00:00
}
},
'loggers': {
'console_only': {
'handlers': ['console'],
2018-04-08 15:28:08 +00:00
'propagate': 0
2013-07-15 19:45:03 +00:00
},
'file_only': {
'handlers': ['file'],
2018-04-08 15:28:08 +00:00
'propagate': 0
2013-07-15 19:45:03 +00:00
},
'both': {
'handlers': ['console', 'file'],
2018-04-08 15:28:08 +00:00
'propagate': 0
2013-07-15 19:45:03 +00:00
},
},
2013-07-15 19:45:03 +00:00
'root': {
'level': log_level,
'handlers': ['console'],
},
2013-07-15 19:45:03 +00:00
})
return True
2018-04-08 15:28:08 +00:00
# TODO (xj9): Get from a config file.
2018-04-08 15:28:08 +00:00
# logger = logging.getLogger('console_only')
if configureLogging():
if '-c' in sys.argv:
logger = logging.getLogger('file_only')
else:
logger = logging.getLogger('both')
else:
logger = logging.getLogger('default')
2013-07-15 19:45:03 +00:00
2018-04-08 15:28:08 +00:00
2013-07-15 19:45:03 +00:00
def restartLoggingInUpdatedAppdataLocation():
global logger
for i in list(logger.handlers):
logger.removeHandler(i)
i.flush()
i.close()
if configureLogging():
if '-c' in sys.argv:
logger = logging.getLogger('file_only')
else:
logger = logging.getLogger('both')
else:
logger = logging.getLogger('default')