Add log.add_log_file()

log.add_log_file(path) allows to pass a file path log messages will
be written into. Special characters (e.g. console color codes) will
be removed from the messages.

Signed-off-by: Jan Lindemann <jan@janware.com>
This commit is contained in:
Jan Lindemann 2022-12-08 16:41:27 +01:00
commit b7de950750

View file

@ -4,7 +4,7 @@ from __future__ import print_function
from typing import List, Tuple, Optional, Any from typing import List, Tuple, Optional, Any
import sys, re, io, syslog, inspect import sys, re, io, syslog, inspect, unicodedata
from os.path import basename from os.path import basename
from datetime import datetime from datetime import datetime
@ -29,6 +29,9 @@ _special_chars = {
_special_char_regex = re.compile("(%s)" % "|".join(map(re.escape, _special_chars.keys()))) _special_char_regex = re.compile("(%s)" % "|".join(map(re.escape, _special_chars.keys())))
_all_control_chars = ''.join(chr(c) for c in range(sys.maxunicode) if unicodedata.category(chr(c)) in {'Cc'})
_clean_str_regex = re.compile('(\033\[[0-9]*m|[%s])' % re.escape(_all_control_chars))
EMERG = int(syslog.LOG_EMERG) EMERG = int(syslog.LOG_EMERG)
ALERT = int(syslog.LOG_ALERT) ALERT = int(syslog.LOG_ALERT)
CRIT = int(syslog.LOG_CRIT) CRIT = int(syslog.LOG_CRIT)
@ -66,8 +69,10 @@ f_default = [ f_position, f_stderr, f_prio, f_color ]
_flags = set(f_default) _flags = set(f_default)
_log_prefix = '' _log_prefix = ''
_clean_log_prefix = ''
_file_name_len = 20 _file_name_len = 20
_module_name_len = 50 _module_name_len = 50
_log_file_streams = []
_short_prio_str = { _short_prio_str = {
EMERG : '<Y>', EMERG : '<Y>',
@ -178,20 +183,25 @@ def slog(prio: int, *args, only_printable: bool=False, **kwargs) -> None: # expo
if f_color in _flags: if f_color in _flags:
color_on, color_off = console_color_chars(prio) color_on, color_off = console_color_chars(prio)
msg += _log_prefix margs = ''
if len(args): if len(args):
margs = ''
for a in args: for a in args:
margs += ' ' + str(a) margs += ' ' + str(a)
if only_printable: if only_printable:
margs = _special_char_regex.sub(lambda mo: _special_chars[mo.string[mo.start():mo.end()]], margs) margs = _special_char_regex.sub(lambda mo: _special_chars[mo.string[mo.start():mo.end()]], margs)
margs = re.sub('[\x01-\x1f]', '.', margs) margs = re.sub('[\x01-\x1f]', '.', margs)
msg += color_on + margs + color_off
for file in _log_file_streams:
print(msg + _clean_log_prefix + margs, file=file)
msg += _log_prefix
if not len(msg): if not len(msg):
return return
if len(margs):
msg += color_on + margs + color_off
files = [] files = []
if 'capture' in kwargs: if 'capture' in kwargs:
files.append(kwargs['capture']) files.append(kwargs['capture'])
@ -285,17 +295,21 @@ def set_flags(flags: str|None) -> str: # export
def append_to_prefix(prefix: str) -> str: # export def append_to_prefix(prefix: str) -> str: # export
global _log_prefix global _log_prefix
global _clean_log_prefix
r = _log_prefix r = _log_prefix
if prefix: if prefix:
_log_prefix += prefix _log_prefix += prefix
_clean_log_prefix = _clean_str_regex.sub('', _log_prefix)
return r return r
def remove_from_prefix(count) -> str: # export def remove_from_prefix(count) -> str: # export
if isinstance(count, str): if isinstance(count, str):
count = len(count) count = len(count)
global _log_prefix global _log_prefix
global _clean_log_prefix
r = _log_prefix r = _log_prefix
_log_prefix = _log_prefix[:-count] _log_prefix = _log_prefix[:-count]
_clean_log_prefix = _clean_str_regex.sub('', _log_prefix)
return r return r
def set_filename_length(l: int) -> int: # export def set_filename_length(l: int) -> int: # export
@ -311,3 +325,8 @@ def set_module_name_length(l: int) -> int: # export
if l: if l:
_module_name_len = l _module_name_len = l
return r return r
def add_log_file(path: str) -> None: # export
global _log_file_streams
fd = open(path, 'w', buffering=1)
_log_file_streams.append(fd)