Log to file instead of syslog via command-line "--log-file" flag (#233).
This commit is contained in:
commit
06f134cc71
4 changed files with 53 additions and 5 deletions
|
@ -149,6 +149,12 @@ def parse_arguments(*unparsed_arguments):
|
||||||
default=0,
|
default=0,
|
||||||
help='Display verbose progress to syslog (from none to lots: 0, 1, or 2). Ignored when console is interactive',
|
help='Display verbose progress to syslog (from none to lots: 0, 1, or 2). Ignored when console is interactive',
|
||||||
)
|
)
|
||||||
|
global_group.add_argument(
|
||||||
|
'--log-file',
|
||||||
|
type=str,
|
||||||
|
default=None,
|
||||||
|
help='Write log messages to this file instead of concole and syslog',
|
||||||
|
)
|
||||||
global_group.add_argument(
|
global_group.add_argument(
|
||||||
'--version',
|
'--version',
|
||||||
dest='version',
|
dest='version',
|
||||||
|
|
|
@ -487,6 +487,7 @@ def main(): # pragma: no cover
|
||||||
configure_logging(
|
configure_logging(
|
||||||
verbosity_to_log_level(global_arguments.verbosity),
|
verbosity_to_log_level(global_arguments.verbosity),
|
||||||
verbosity_to_log_level(global_arguments.syslog_verbosity),
|
verbosity_to_log_level(global_arguments.syslog_verbosity),
|
||||||
|
global_arguments.log_file,
|
||||||
)
|
)
|
||||||
|
|
||||||
logger.debug('Ensuring legacy configuration is upgraded')
|
logger.debug('Ensuring legacy configuration is upgraded')
|
||||||
|
|
|
@ -73,7 +73,7 @@ def color_text(color, message):
|
||||||
return '{}{}{}'.format(color, message, colorama.Style.RESET_ALL)
|
return '{}{}{}'.format(color, message, colorama.Style.RESET_ALL)
|
||||||
|
|
||||||
|
|
||||||
def configure_logging(console_log_level, syslog_log_level=None):
|
def configure_logging(console_log_level, syslog_log_level=None, log_file=None):
|
||||||
'''
|
'''
|
||||||
Configure logging to go to both the console and syslog. Use the given log levels, respectively.
|
Configure logging to go to both the console and syslog. Use the given log levels, respectively.
|
||||||
'''
|
'''
|
||||||
|
@ -85,16 +85,29 @@ def configure_logging(console_log_level, syslog_log_level=None):
|
||||||
console_handler.setLevel(console_log_level)
|
console_handler.setLevel(console_log_level)
|
||||||
|
|
||||||
syslog_path = None
|
syslog_path = None
|
||||||
if os.path.exists('/dev/log'):
|
if log_file is None:
|
||||||
syslog_path = '/dev/log'
|
if os.path.exists('/dev/log'):
|
||||||
elif os.path.exists('/var/run/syslog'):
|
syslog_path = '/dev/log'
|
||||||
syslog_path = '/var/run/syslog'
|
elif os.path.exists('/var/run/syslog'):
|
||||||
|
syslog_path = '/var/run/syslog'
|
||||||
|
|
||||||
if syslog_path and not interactive_console():
|
if syslog_path and not interactive_console():
|
||||||
syslog_handler = logging.handlers.SysLogHandler(address=syslog_path)
|
syslog_handler = logging.handlers.SysLogHandler(address=syslog_path)
|
||||||
syslog_handler.setFormatter(logging.Formatter('borgmatic: %(levelname)s %(message)s'))
|
syslog_handler.setFormatter(logging.Formatter('borgmatic: %(levelname)s %(message)s'))
|
||||||
syslog_handler.setLevel(syslog_log_level)
|
syslog_handler.setLevel(syslog_log_level)
|
||||||
handlers = (console_handler, syslog_handler)
|
handlers = (console_handler, syslog_handler)
|
||||||
|
elif log_file:
|
||||||
|
try:
|
||||||
|
file_handler = logging.FileHandler(log_file)
|
||||||
|
except FileNotFoundError:
|
||||||
|
print("ERROR: Path to log-file doesn't exist: {}".format(log_file))
|
||||||
|
sys.exit(1)
|
||||||
|
except PermissionError:
|
||||||
|
print("ERROR: No write access to log-file: {}".format(log_file))
|
||||||
|
sys.exit(1)
|
||||||
|
file_handler.setFormatter(logging.Formatter('[%(asctime)s] %(levelname)s: %(message)s'))
|
||||||
|
file_handler.setLevel(syslog_log_level)
|
||||||
|
handlers = (console_handler, file_handler)
|
||||||
else:
|
else:
|
||||||
handlers = (console_handler,)
|
handlers = (console_handler,)
|
||||||
|
|
||||||
|
|
|
@ -193,3 +193,31 @@ def test_configure_logging_skips_syslog_if_interactive_console():
|
||||||
flexmock(module.logging.handlers).should_receive('SysLogHandler').never()
|
flexmock(module.logging.handlers).should_receive('SysLogHandler').never()
|
||||||
|
|
||||||
module.configure_logging(console_log_level=logging.INFO)
|
module.configure_logging(console_log_level=logging.INFO)
|
||||||
|
|
||||||
|
|
||||||
|
def test_configure_logging_to_logfile_instead_syslog():
|
||||||
|
# syslog skipped in non-interactive console if --log-file argument provided
|
||||||
|
flexmock(module).should_receive('interactive_console').and_return(False)
|
||||||
|
flexmock(module.logging).should_receive('basicConfig').with_args(
|
||||||
|
level=logging.INFO, handlers=tuple
|
||||||
|
)
|
||||||
|
flexmock(module.os.path).should_receive('exists').with_args('/dev/log').and_return(True)
|
||||||
|
flexmock(module.logging.handlers).should_receive('SysLogHandler').never()
|
||||||
|
file_handler = logging.FileHandler('/tmp/logfile')
|
||||||
|
flexmock(module.logging).should_receive('FileHandler').with_args('/tmp/logfile').and_return(
|
||||||
|
file_handler
|
||||||
|
).once()
|
||||||
|
|
||||||
|
module.configure_logging(console_log_level=logging.INFO, log_file='/tmp/logfile')
|
||||||
|
|
||||||
|
|
||||||
|
def test_configure_logging_skips_logfile_if_argument_is_none():
|
||||||
|
# No FileHandler added if argument --log-file is None
|
||||||
|
flexmock(module).should_receive('interactive_console').and_return(False)
|
||||||
|
flexmock(module.logging).should_receive('basicConfig').with_args(
|
||||||
|
level=logging.INFO, handlers=tuple
|
||||||
|
)
|
||||||
|
flexmock(module.os.path).should_receive('exists').and_return(False)
|
||||||
|
flexmock(module.logging).should_receive('FileHandler').never()
|
||||||
|
|
||||||
|
module.configure_logging(console_log_level=logging.INFO, log_file=None)
|
||||||
|
|
Loading…
Reference in a new issue