Log to file instead of syslog via command-line "--log-file" flag (#233).

This commit is contained in:
Dan Helfman 2019-11-02 17:43:39 +00:00 committed by Gitea
commit 06f134cc71
4 changed files with 53 additions and 5 deletions

View file

@ -149,6 +149,12 @@ def parse_arguments(*unparsed_arguments):
default=0,
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(
'--version',
dest='version',

View file

@ -487,6 +487,7 @@ def main(): # pragma: no cover
configure_logging(
verbosity_to_log_level(global_arguments.verbosity),
verbosity_to_log_level(global_arguments.syslog_verbosity),
global_arguments.log_file,
)
logger.debug('Ensuring legacy configuration is upgraded')

View file

@ -73,7 +73,7 @@ def color_text(color, message):
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.
'''
@ -85,6 +85,7 @@ def configure_logging(console_log_level, syslog_log_level=None):
console_handler.setLevel(console_log_level)
syslog_path = None
if log_file is None:
if os.path.exists('/dev/log'):
syslog_path = '/dev/log'
elif os.path.exists('/var/run/syslog'):
@ -95,6 +96,18 @@ def configure_logging(console_log_level, syslog_log_level=None):
syslog_handler.setFormatter(logging.Formatter('borgmatic: %(levelname)s %(message)s'))
syslog_handler.setLevel(syslog_log_level)
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:
handlers = (console_handler,)

View file

@ -193,3 +193,31 @@ def test_configure_logging_skips_syslog_if_interactive_console():
flexmock(module.logging.handlers).should_receive('SysLogHandler').never()
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)