forked from Mirror/pmbootstrap
When this parameter is set, `args.logfd` (the log file descriptor) gets set to `sys.stdout`, so all logging gets directly sent to the active pmbootstrap session, and not to a log file. This will be used for Travis jobs, because they get killed after 10 minutes without any output (and builds may take longer).
103 lines
3.2 KiB
Python
103 lines
3.2 KiB
Python
"""
|
|
Copyright 2017 Oliver Smith
|
|
|
|
This file is part of pmbootstrap.
|
|
|
|
pmbootstrap is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
pmbootstrap is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with pmbootstrap. If not, see <http://www.gnu.org/licenses/>.
|
|
"""
|
|
import logging
|
|
import os
|
|
import sys
|
|
|
|
|
|
class log_handler(logging.StreamHandler):
|
|
"""
|
|
Write to stdout and to the already opened log file.
|
|
"""
|
|
_args = None
|
|
|
|
def emit(self, record):
|
|
try:
|
|
msg = self.format(record)
|
|
|
|
# INFO or higher: Write to stdout
|
|
if (not self._args.details_to_stdout and
|
|
not self._args.quiet and
|
|
record.levelno >= logging.INFO):
|
|
stream = self.stream
|
|
stream.write(msg)
|
|
stream.write(self.terminator)
|
|
self.flush()
|
|
|
|
# Everything: Write to logfd
|
|
msg = "(" + str(os.getpid()).zfill(6) + ") " + msg
|
|
self._args.logfd.write(msg + "\n")
|
|
self._args.logfd.flush()
|
|
|
|
except (KeyboardInterrupt, SystemExit):
|
|
raise
|
|
except BaseException:
|
|
self.handleError(record)
|
|
|
|
|
|
def add_verbose_log_level():
|
|
"""
|
|
Add a new log level "verbose", which is below "debug". Also monkeypatch
|
|
logging, so it can be used with logging.verbose().
|
|
|
|
This function is based on work by Voitek Zylinski and sleepycal:
|
|
https://stackoverflow.com/a/20602183
|
|
All stackoverflow user contributions are licensed as CC-BY-SA:
|
|
https://creativecommons.org/licenses/by-sa/3.0/
|
|
"""
|
|
logging.VERBOSE = 5
|
|
logging.addLevelName(logging.VERBOSE, "VERBOSE")
|
|
logging.Logger.verbose = lambda inst, msg, * \
|
|
args, **kwargs: inst.log(logging.VERBOSE, msg, *args, **kwargs)
|
|
logging.verbose = lambda msg, *args, **kwargs: logging.log(logging.VERBOSE, msg,
|
|
*args, **kwargs)
|
|
|
|
|
|
def init(args):
|
|
"""
|
|
Set log format and add the log file descriptor to args.logfd, add the
|
|
verbose log level.
|
|
"""
|
|
# Create work folder (because usually the log file is in there)
|
|
if not os.path.exists(args.work):
|
|
os.makedirs(args.work)
|
|
|
|
# Open logfile
|
|
if args.details_to_stdout:
|
|
setattr(args, "logfd", sys.stdout)
|
|
else:
|
|
setattr(args, "logfd", open(args.log, "a+"))
|
|
|
|
# Set log format
|
|
root_logger = logging.getLogger()
|
|
root_logger.handlers = []
|
|
formatter = logging.Formatter("[%(asctime)s] %(message)s",
|
|
datefmt="%H:%M:%S")
|
|
|
|
# Set log level
|
|
add_verbose_log_level()
|
|
root_logger.setLevel(logging.DEBUG)
|
|
if args.verbose:
|
|
root_logger.setLevel(logging.VERBOSE)
|
|
|
|
# Add a custom log handler
|
|
handler = log_handler()
|
|
log_handler._args = args
|
|
handler.setFormatter(formatter)
|
|
root_logger.addHandler(handler)
|