diff --git a/src/octoprint/__init__.py b/src/octoprint/__init__.py index dbd06e7d..6d5dad46 100644 --- a/src/octoprint/__init__.py +++ b/src/octoprint/__init__.py @@ -5,7 +5,7 @@ from octoprint.server import Server class Main(Daemon): - def __init__(self, pidfile, configfile, basedir, host, port, debug, allowRoot): + def __init__(self, pidfile, configfile, basedir, host, port, debug, allowRoot, logConf): Daemon.__init__(self, pidfile) self._configfile = configfile @@ -14,6 +14,7 @@ class Main(Daemon): self._port = port self._debug = debug self._allowRoot = allowRoot + self._logConf = logConf def run(self): octoprint = Server(self._configfile, self._basedir, self._host, self._port, self._debug, self._allowRoot) @@ -36,6 +37,8 @@ def main(): help="Specify the config file to use. OctoPrint needs to have write access for the settings dialog to work. Defaults to ~/.octoprint/config.yaml") parser.add_argument("-b", "--basedir", action="store", dest="basedir", help="Specify the basedir to use for uploads, timelapses etc. OctoPrint needs to have write access. Defaults to ~/.octoprint") + parser.add_argument("--logging", action="store", dest="logConf", + help="Specify the config file to use for configuring logging. Defaults to ~/.octoprint/logging.yaml") parser.add_argument("--daemon", action="store", type=str, choices=["start", "stop", "restart"], help="Daemonize/control daemonized OctoPrint instance (only supported under Linux right now)") @@ -52,7 +55,7 @@ def main(): print >> sys.stderr, "Sorry, daemon mode is only supported under Linux right now" sys.exit(2) - daemon = Main(args.pidfile, args.config, args.basedir, args.host, args.port, args.debug, args.allowRoot) + daemon = Main(args.pidfile, args.config, args.basedir, args.host, args.port, args.debug, args.allowRoot, args.logConf) if "start" == args.daemon: daemon.start() elif "stop" == args.daemon: @@ -60,7 +63,7 @@ def main(): elif "restart" == args.daemon: daemon.restart() else: - octoprint = Server(args.config, args.basedir, args.host, args.port, args.debug, args.allowRoot) + octoprint = Server(args.config, args.basedir, args.host, args.port, args.debug, args.allowRoot, args.logConf) octoprint.run() if __name__ == "__main__": diff --git a/src/octoprint/server/__init__.py b/src/octoprint/server/__init__.py index cc1eb51f..9e0416d2 100644 --- a/src/octoprint/server/__init__.py +++ b/src/octoprint/server/__init__.py @@ -102,13 +102,14 @@ def load_user(id): class Server(): - def __init__(self, configfile=None, basedir=None, host="0.0.0.0", port=5000, debug=False, allowRoot=False): + def __init__(self, configfile=None, basedir=None, host="0.0.0.0", port=5000, debug=False, allowRoot=False, logConf=None): self._configfile = configfile self._basedir = basedir self._host = host self._port = port self._debug = debug self._allowRoot = allowRoot + self._logConf = logConf def run(self): @@ -133,7 +134,7 @@ class Server(): self._initSettings(self._configfile, self._basedir) # then initialize logging - self._initLogging(self._debug) + self._initLogging(self._debug, self._logConf) logger = logging.getLogger(__name__) eventManager = events.eventManager() @@ -229,8 +230,8 @@ class Server(): def _initSettings(self, configfile, basedir): settings(init=True, basedir=basedir, configfile=configfile) - def _initLogging(self, debug): - config = { + def _initLogging(self, debug, logConf=None): + defaultConfig = { "version": 1, "formatters": { "simple": { @@ -261,12 +262,6 @@ class Server(): } }, "loggers": { - #"octoprint.timelapse": { - # "level": "DEBUG" - #}, - #"octoprint.events": { - # "level": "DEBUG" - #}, "SERIAL": { "level": "CRITICAL", "handlers": ["serialFile"], @@ -280,8 +275,18 @@ class Server(): } if debug: - config["root"]["level"] = "DEBUG" + defaultConfig["root"]["level"] = "DEBUG" + if logConf is None: + logConf = os.path.join(settings().settings_dir, "logging.yaml") + + configFromFile = {} + if os.path.exists(logConf) and os.path.isfile(logConf): + import yaml + with open(logConf, "r") as f: + configFromFile = yaml.safe_load(f) + + config = util.dict_merge(defaultConfig, configFromFile) logging.config.dictConfig(config) if settings().getBoolean(["serial", "log"]): diff --git a/src/octoprint/util/__init__.py b/src/octoprint/util/__init__.py index ae4bbe73..ce01b87c 100644 --- a/src/octoprint/util/__init__.py +++ b/src/octoprint/util/__init__.py @@ -225,3 +225,22 @@ def getJsonCommandFromRequest(request, valid_commands): return command, data, None + +def dict_merge(a, b): + '''recursively merges dict's. not just simple a['key'] = b['key'], if + both a and bhave a key who's value is a dict then dict_merge is called + on both values and the result stored in the returned dictionary. + + Taken from https://www.xormedia.com/recursively-merge-dictionaries-in-python/''' + + from copy import deepcopy + + if not isinstance(b, dict): + return b + result = deepcopy(a) + for k, v in b.iteritems(): + if k in result and isinstance(result[k], dict): + result[k] = dict_merge(result[k], v) + else: + result[k] = deepcopy(v) + return result