diff --git a/DOCUMENTATION.md b/DOCUMENTATION.md index b929b442e..382e1e031 100644 --- a/DOCUMENTATION.md +++ b/DOCUMENTATION.md @@ -910,6 +910,12 @@ Log bad PUT request content (for further diagnostics) Default: `False' +##### backtrace_on_debug + +Log backtrace on level=debug + +Default: `True' + #### headers In this section additional HTTP headers that are sent to clients can be diff --git a/config b/config index f195d2609..4a2e2f29c 100644 --- a/config +++ b/config @@ -123,6 +123,9 @@ # Log bad PUT request content #bad_put_request_content = False +# Log backtrace on level=debug +# backtrace_on_debug = True + [headers] diff --git a/radicale/__init__.py b/radicale/__init__.py index 4df3e989c..2ce5d4b72 100644 --- a/radicale/__init__.py +++ b/radicale/__init__.py @@ -52,7 +52,7 @@ def _get_application_instance(config_path: str, wsgi_errors: types.ErrorStream configuration = config.load(config.parse_compound_paths( config.DEFAULT_CONFIG_PATH, config_path)) - log.set_level(cast(str, configuration.get("logging", "level"))) + log.set_level(cast(str, configuration.get("logging", "level")), configuration.get("logging", "backtrace_on_debug")) # Log configuration after logger is configured default_config_active = True for source, miss in configuration.sources(): diff --git a/radicale/__main__.py b/radicale/__main__.py index e71663b4b..f2f157b9f 100644 --- a/radicale/__main__.py +++ b/radicale/__main__.py @@ -142,7 +142,7 @@ def exit_signal_handler(signal_number: int, # Preliminary configure logging with contextlib.suppress(ValueError): log.set_level(config.DEFAULT_CONFIG_SCHEMA["logging"]["level"]["type"]( - vars(args_ns).get("c:logging:level", ""))) + vars(args_ns).get("c:logging:level", "")), True) # Update Radicale configuration according to arguments arguments_config: types.MUTABLE_CONFIG = {} @@ -165,7 +165,7 @@ def exit_signal_handler(signal_number: int, sys.exit(1) # Configure logging - log.set_level(cast(str, configuration.get("logging", "level"))) + log.set_level(cast(str, configuration.get("logging", "level")), configuration.get("logging", "backtrace_on_debug")) # Log configuration after logger is configured default_config_active = True diff --git a/radicale/config.py b/radicale/config.py index 6961c4601..27352bdc0 100644 --- a/radicale/config.py +++ b/radicale/config.py @@ -252,6 +252,10 @@ def _convert_to_bool(value: Any) -> bool: "value": "False", "help": "log bad PUT request content", "type": bool}), + ("backtrace_on_debug", { + "value": "True", + "help": "log backtrace on level=debug", + "type": bool}), ("mask_passwords", { "value": "True", "help": "mask passwords in logs", diff --git a/radicale/log.py b/radicale/log.py index 8d54a1b0a..59473644c 100644 --- a/radicale/log.py +++ b/radicale/log.py @@ -215,17 +215,23 @@ def setup() -> None: register_stream = handler.register_stream log_record_factory = IdentLogRecordFactory(logging.getLogRecordFactory()) logging.setLogRecordFactory(log_record_factory) - set_level(logging.WARNING) + set_level(logging.INFO, True) if format_name != sane_format_name: logger.error("Invalid RADICALE_LOG_FORMAT: %r", format_name) -def set_level(level: Union[int, str]) -> None: +def set_level(level: Union[int, str], backtrace_on_debug: bool) -> None: """Set logging level for global logger.""" if isinstance(level, str): level = getattr(logging, level.upper()) assert isinstance(level, int) logger.setLevel(level) - logger.removeFilter(REMOVE_TRACEBACK_FILTER) if level > logging.DEBUG: + logger.info("Logging of backtrace is disabled in this loglevel") logger.addFilter(REMOVE_TRACEBACK_FILTER) + else: + if not backtrace_on_debug: + logger.debug("Logging of backtrace is disabled by option in this loglevel") + logger.addFilter(REMOVE_TRACEBACK_FILTER) + else: + logger.removeFilter(REMOVE_TRACEBACK_FILTER)