Adjust: [logging] header/content debug log indended by space to be skipped by logwatch

This commit is contained in:
Peter Bieringer
2025-12-10 18:01:14 +01:00
parent bac608a37a
commit 183e556144
5 changed files with 26 additions and 12 deletions

View File

@@ -38,7 +38,7 @@ import zlib
from http import client from http import client
from typing import Iterable, List, Mapping, Tuple, Union from typing import Iterable, List, Mapping, Tuple, Union
from radicale import config, httputils, log, pathutils, types from radicale import config, httputils, log, pathutils, types, utils
from radicale.app.base import ApplicationBase from radicale.app.base import ApplicationBase
from radicale.app.delete import ApplicationPartDelete from radicale.app.delete import ApplicationPartDelete
from radicale.app.get import ApplicationPartGet from radicale.app.get import ApplicationPartGet
@@ -177,7 +177,7 @@ class Application(ApplicationPartDelete, ApplicationPartHead,
s = io.StringIO() s = io.StringIO()
stats = pstats.Stats(self.profiler_per_request_method[method], stream=s).sort_stats('cumulative') stats = pstats.Stats(self.profiler_per_request_method[method], stream=s).sort_stats('cumulative')
stats.print_stats(self._profiling_top_x_functions) # Print top X functions stats.print_stats(self._profiling_top_x_functions) # Print top X functions
logger.info("Profiling data per request method %s after %d seconds and %d requests: %s", method, profiler_timedelta_start, self.profiler_per_request_method_counter[method], s.getvalue()) logger.info("Profiling data per request method %s after %d seconds and %d requests: %s", method, profiler_timedelta_start, self.profiler_per_request_method_counter[method], utils.textwrap_str(s.getvalue(), -1))
else: else:
if shutdown: if shutdown:
logger.info("Profiling data per request method %s after %d seconds: (no request seen so far)", method, profiler_timedelta_start) logger.info("Profiling data per request method %s after %d seconds: (no request seen so far)", method, profiler_timedelta_start)
@@ -238,7 +238,7 @@ class Application(ApplicationPartDelete, ApplicationPartHead,
if answer is not None: if answer is not None:
if isinstance(answer, str): if isinstance(answer, str):
if self._response_content_on_debug: if self._response_content_on_debug:
logger.debug("Response content:\n%s", answer) logger.debug("Response content (nonXML):\n%s", utils.textwrap_str(answer))
else: else:
logger.debug("Response content: suppressed by config/option [logging] response_content_on_debug") logger.debug("Response content: suppressed by config/option [logging] response_content_on_debug")
headers["Content-Type"] += "; charset=%s" % self._encoding headers["Content-Type"] += "; charset=%s" % self._encoding
@@ -329,7 +329,7 @@ class Application(ApplicationPartDelete, ApplicationPartHead,
remote_host, remote_useragent, https_info) remote_host, remote_useragent, https_info)
if self._request_header_on_debug: if self._request_header_on_debug:
logger.debug("Request header:\n%s", logger.debug("Request header:\n%s",
pprint.pformat(self._scrub_headers(environ))) utils.textwrap_str(pprint.pformat(self._scrub_headers(environ))))
else: else:
logger.debug("Request header: suppressed by config/option [logging] request_header_on_debug") logger.debug("Request header: suppressed by config/option [logging] request_header_on_debug")

View File

@@ -23,7 +23,7 @@ import xml.etree.ElementTree as ET
from typing import Optional from typing import Optional
from radicale import (auth, config, hook, httputils, pathutils, rights, from radicale import (auth, config, hook, httputils, pathutils, rights,
storage, types, web, xmlutils) storage, types, utils, web, xmlutils)
from radicale.log import logger from radicale.log import logger
# HACK: https://github.com/tiran/defusedxml/issues/54 # HACK: https://github.com/tiran/defusedxml/issues/54
@@ -71,7 +71,7 @@ class ApplicationBase:
if logger.isEnabledFor(logging.DEBUG): if logger.isEnabledFor(logging.DEBUG):
if self._request_content_on_debug: if self._request_content_on_debug:
logger.debug("Request content (XML):\n%s", logger.debug("Request content (XML):\n%s",
xmlutils.pretty_xml(xml_content)) utils.textwrap_str(xmlutils.pretty_xml(xml_content)))
else: else:
logger.debug("Request content (XML): suppressed by config/option [logging] request_content_on_debug") logger.debug("Request content (XML): suppressed by config/option [logging] request_content_on_debug")
return xml_content return xml_content
@@ -80,7 +80,7 @@ class ApplicationBase:
if logger.isEnabledFor(logging.DEBUG): if logger.isEnabledFor(logging.DEBUG):
if self._response_content_on_debug: if self._response_content_on_debug:
logger.debug("Response content (XML):\n%s", logger.debug("Response content (XML):\n%s",
xmlutils.pretty_xml(xml_content)) utils.textwrap_str(xmlutils.pretty_xml(xml_content)))
else: else:
logger.debug("Response content (XML): suppressed by config/option [logging] response_content_on_debug") logger.debug("Response content (XML): suppressed by config/option [logging] response_content_on_debug")
f = io.BytesIO() f = io.BytesIO()

View File

@@ -99,7 +99,7 @@ def prepare(vobject_items: List[vobject.base.Component], path: str,
content = vobject_item content = vobject_item
else: else:
content = item._text content = item._text
logger.warning("Problem during prepare item with UID '%s' (content below): %s\n%s", item.uid, e, content) logger.warning("Problem during prepare item with UID '%s' (content below): %s\n%s", item.uid, e, utils.textwrap_str(content))
else: else:
logger.warning("Problem during prepare item with UID '%s' (content suppressed in this loglevel): %s", item.uid, e) logger.warning("Problem during prepare item with UID '%s' (content suppressed in this loglevel): %s", item.uid, e)
raise raise
@@ -117,7 +117,7 @@ def prepare(vobject_items: List[vobject.base.Component], path: str,
content = vobject_item content = vobject_item
else: else:
content = item._text content = item._text
logger.warning("Problem during prepare item with UID '%s' (content below): %s\n%s", item.uid, e, content) logger.warning("Problem during prepare item with UID '%s' (content below): %s\n%s", item.uid, e, utils.textwrap_str(content))
else: else:
logger.warning("Problem during prepare item with UID '%s' (content suppressed in this loglevel): %s", item.uid, e) logger.warning("Problem during prepare item with UID '%s' (content suppressed in this loglevel): %s", item.uid, e)
raise raise
@@ -180,7 +180,7 @@ class ApplicationPartPut(ApplicationBase):
logger.warning( logger.warning(
"Bad PUT request on %r (read_components): %s", path, e, exc_info=True) "Bad PUT request on %r (read_components): %s", path, e, exc_info=True)
if self._log_bad_put_request_content: if self._log_bad_put_request_content:
logger.warning("Bad PUT request content of %r:\n%s", path, content) logger.warning("Bad PUT request content of %r:\n%s", path, utils.textwrap_str(content))
else: else:
logger.debug("Bad PUT request content: suppressed by config/option [logging] bad_put_request_content") logger.debug("Bad PUT request content: suppressed by config/option [logging] bad_put_request_content")
return httputils.BAD_REQUEST return httputils.BAD_REQUEST

View File

@@ -31,7 +31,7 @@ import time
from http import client from http import client
from typing import List, Mapping, Union, cast from typing import List, Mapping, Union, cast
from radicale import config, pathutils, types from radicale import config, pathutils, types, utils
from radicale.log import logger from radicale.log import logger
if sys.version_info < (3, 9): if sys.version_info < (3, 9):
@@ -150,7 +150,7 @@ def read_request_body(configuration: "config.Configuration",
content = decode_request(configuration, environ, content = decode_request(configuration, environ,
read_raw_request_body(configuration, environ)) read_raw_request_body(configuration, environ))
if configuration.get("logging", "request_content_on_debug"): if configuration.get("logging", "request_content_on_debug"):
logger.debug("Request content:\n%s", content) logger.debug("Request content:\n%s", utils.textwrap_str(content))
else: else:
logger.debug("Request content: suppressed by config/option [logging] request_content_on_debug") logger.debug("Request content: suppressed by config/option [logging] request_content_on_debug")
return content return content

View File

@@ -21,6 +21,7 @@ import datetime
import os import os
import ssl import ssl
import sys import sys
import textwrap
from importlib import import_module, metadata from importlib import import_module, metadata
from typing import Callable, Sequence, Tuple, Type, TypeVar, Union from typing import Callable, Sequence, Tuple, Type, TypeVar, Union
@@ -291,3 +292,16 @@ def format_ut(unixtime: int) -> str:
dt = datetime.datetime.fromtimestamp(unixtime, datetime.UTC) dt = datetime.datetime.fromtimestamp(unixtime, datetime.UTC)
r = str(unixtime) + "(" + dt.strftime('%Y-%m-%dT%H:%M:%SZ') + ")" r = str(unixtime) + "(" + dt.strftime('%Y-%m-%dT%H:%M:%SZ') + ")"
return r return r
def limit_str(content: str, limit: int) -> str:
length = len(content)
if limit > 0 and length >= limit:
return content[:limit] + ("...(shortened because original length %d > limit %d)" % (length, limit))
else:
return content
def textwrap_str(content: str, limit: int = 2000) -> str:
# TODO: add support for config option and prefix
return textwrap.indent(limit_str(content, limit), " ", lambda line: True)