2017-10-25 10:06:29 +02:00
|
|
|
from __future__ import print_function
|
2017-07-30 18:51:19 +02:00
|
|
|
import syslog
|
2017-10-25 10:06:29 +02:00
|
|
|
import sys
|
|
|
|
|
import inspect
|
2020-05-16 15:33:13 +00:00
|
|
|
import re
|
2017-10-25 10:06:29 +02:00
|
|
|
from os.path import basename
|
2019-12-21 19:08:51 +00:00
|
|
|
from datetime import datetime
|
2024-12-15 15:35:29 +01:00
|
|
|
from typing import List, Tuple, Optional, Any
|
2019-03-10 16:38:59 +01:00
|
|
|
from . import misc
|
|
|
|
|
|
|
|
|
|
# --- python 2 / 3 compatibility stuff
|
|
|
|
|
try:
|
2024-06-02 12:05:44 +02:00
|
|
|
basestring # type: ignore
|
2019-03-10 16:38:59 +01:00
|
|
|
except NameError:
|
|
|
|
|
basestring = str
|
2017-07-30 18:51:19 +02:00
|
|
|
|
2020-05-16 15:33:13 +00:00
|
|
|
_special_chars = {
|
|
|
|
|
'\a' : '\\a',
|
|
|
|
|
'\b' : '\\b',
|
|
|
|
|
'\t' : '\\t',
|
|
|
|
|
'\n' : '\\n',
|
|
|
|
|
'\v' : '\\v',
|
|
|
|
|
'\f' : '\\f',
|
|
|
|
|
'\r' : '\\r',
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_special_char_regex = re.compile("(%s)" % "|".join(map(re.escape, _special_chars.keys())))
|
|
|
|
|
|
2022-10-04 13:11:44 +02:00
|
|
|
EMERG = int(syslog.LOG_EMERG)
|
|
|
|
|
ALERT = int(syslog.LOG_ALERT)
|
|
|
|
|
CRIT = int(syslog.LOG_CRIT)
|
|
|
|
|
ERR = int(syslog.LOG_ERR)
|
|
|
|
|
WARNING = int(syslog.LOG_WARNING)
|
|
|
|
|
NOTICE = int(syslog.LOG_NOTICE)
|
|
|
|
|
INFO = int(syslog.LOG_INFO)
|
|
|
|
|
DEBUG = int(syslog.LOG_DEBUG)
|
|
|
|
|
DEVEL = int(syslog.LOG_DEBUG + 1)
|
2019-10-28 10:59:20 +01:00
|
|
|
OFF = DEVEL + 1
|
|
|
|
|
|
|
|
|
|
_level = NOTICE
|
2017-07-30 18:51:19 +02:00
|
|
|
|
2017-10-25 10:06:29 +02:00
|
|
|
CONSOLE_FONT_BOLD = '\033[1m'
|
|
|
|
|
CONSOLE_FONT_RED = '\033[31m'
|
|
|
|
|
CONSOLE_FONT_GREEN = '\033[32m'
|
|
|
|
|
CONSOLE_FONT_YELLOW = '\033[33m'
|
|
|
|
|
CONSOLE_FONT_BLUE = '\033[34m'
|
|
|
|
|
|
|
|
|
|
CONSOLE_FONT_MAGENTA = '\033[35m'
|
|
|
|
|
CONSOLE_FONT_CYAN = '\033[36m'
|
|
|
|
|
CONSOLE_FONT_WHITE = '\033[37m'
|
|
|
|
|
|
|
|
|
|
CONSOLE_FONT_BLINK = '\033[5m'
|
|
|
|
|
CONSOLE_FONT_OFF = '\033[m'
|
|
|
|
|
|
2019-10-28 10:59:20 +01:00
|
|
|
f_position = 'position'
|
2019-12-21 19:08:51 +00:00
|
|
|
f_date = 'date'
|
2019-10-28 10:59:20 +01:00
|
|
|
f_stderr = 'stderr'
|
|
|
|
|
f_stdout = 'stdout'
|
|
|
|
|
f_prio = 'prio'
|
|
|
|
|
f_color = 'color'
|
|
|
|
|
f_default = [ f_position, f_stderr, f_prio, f_color ]
|
|
|
|
|
|
|
|
|
|
_flags = set(f_default)
|
2019-10-30 15:46:26 +01:00
|
|
|
_log_prefix = ''
|
|
|
|
|
_file_name_len = 20
|
2019-10-28 10:59:20 +01:00
|
|
|
|
|
|
|
|
_short_prio_str = {
|
|
|
|
|
EMERG : '<Y>',
|
|
|
|
|
ALERT : '<A>',
|
|
|
|
|
CRIT : '<C>',
|
|
|
|
|
ERR : '<E>',
|
|
|
|
|
WARNING : '<W>',
|
|
|
|
|
NOTICE : '<N>',
|
|
|
|
|
INFO : '<I>',
|
|
|
|
|
DEBUG : '<D>',
|
|
|
|
|
DEVEL : '<V>',
|
2017-10-25 10:06:29 +02:00
|
|
|
}
|
|
|
|
|
|
2019-10-28 10:59:20 +01:00
|
|
|
_prio_colors = {
|
|
|
|
|
DEVEL : [ "", "" ],
|
|
|
|
|
DEBUG : [ "", "" ],
|
|
|
|
|
INFO : [ CONSOLE_FONT_BLUE, CONSOLE_FONT_OFF ],
|
|
|
|
|
NOTICE : [ CONSOLE_FONT_GREEN, CONSOLE_FONT_OFF ],
|
|
|
|
|
WARNING : [ CONSOLE_FONT_YELLOW, CONSOLE_FONT_OFF ],
|
|
|
|
|
ERR : [ CONSOLE_FONT_BOLD + CONSOLE_FONT_RED, CONSOLE_FONT_OFF ],
|
|
|
|
|
CRIT : [ CONSOLE_FONT_BOLD + CONSOLE_FONT_MAGENTA, CONSOLE_FONT_OFF ],
|
|
|
|
|
ALERT : [ CONSOLE_FONT_BOLD + CONSOLE_FONT_MAGENTA, CONSOLE_FONT_OFF ],
|
|
|
|
|
EMERG : [ CONSOLE_FONT_BOLD + CONSOLE_FONT_MAGENTA, CONSOLE_FONT_OFF ],
|
2017-10-25 10:06:29 +02:00
|
|
|
}
|
|
|
|
|
|
2025-01-18 16:42:33 +01:00
|
|
|
def prio_gets_logged(prio: int) -> bool: # export
|
|
|
|
|
if prio > _level:
|
|
|
|
|
return False
|
|
|
|
|
return True
|
|
|
|
|
|
2025-01-29 16:51:07 +01:00
|
|
|
def log_level(s: Optional[str]=None) -> int: # export
|
2025-01-28 10:17:17 +01:00
|
|
|
if s is None:
|
|
|
|
|
return _level
|
2025-01-29 16:51:07 +01:00
|
|
|
return parse_log_prio_str(s)
|
2025-01-28 10:17:17 +01:00
|
|
|
|
2024-12-15 15:35:29 +01:00
|
|
|
def get_caller_pos(up: int = 1, kwargs: Optional[dict[str, Any]] = None) -> Tuple[str, int]:
|
2020-04-11 10:56:30 +02:00
|
|
|
if kwargs and 'caller' in kwargs:
|
|
|
|
|
r = kwargs['caller']
|
|
|
|
|
del kwargs['caller']
|
|
|
|
|
return r
|
2019-12-30 17:46:20 +01:00
|
|
|
caller = inspect.stack()[up+1]
|
|
|
|
|
return (basename(caller.filename), caller.lineno)
|
2017-10-27 18:58:53 +02:00
|
|
|
|
2020-04-10 17:55:36 +02:00
|
|
|
def slog_m(prio: int, *args, **kwargs) -> None: # export
|
2019-10-28 12:50:17 +01:00
|
|
|
if prio > _level:
|
|
|
|
|
return
|
|
|
|
|
if len(args):
|
|
|
|
|
margs = ''
|
|
|
|
|
for a in args:
|
2019-10-30 15:46:26 +01:00
|
|
|
if isinstance(a, list):
|
|
|
|
|
margs += '\n'.join([str(elem) for elem in a])
|
|
|
|
|
continue
|
2019-10-28 12:50:17 +01:00
|
|
|
margs += ' ' + str(a)
|
2020-04-04 11:12:11 +02:00
|
|
|
if 'caller' not in kwargs:
|
|
|
|
|
caller = get_caller_pos(1)
|
|
|
|
|
else:
|
|
|
|
|
caller = kwargs['caller']
|
|
|
|
|
del kwargs['caller']
|
2019-10-28 12:50:17 +01:00
|
|
|
for line in margs[1:].split('\n'):
|
|
|
|
|
slog(prio, line, **kwargs, caller=caller)
|
|
|
|
|
|
2024-12-15 15:35:29 +01:00
|
|
|
def slog(prio: int, *args, only_printable: bool=False, **kwargs) -> None: # export
|
2017-10-25 10:06:29 +02:00
|
|
|
|
2019-10-28 10:59:20 +01:00
|
|
|
if prio > _level:
|
2017-08-07 18:05:53 +02:00
|
|
|
return
|
2017-10-25 10:06:29 +02:00
|
|
|
|
2017-10-16 12:22:49 +02:00
|
|
|
msg = ''
|
2017-10-25 10:06:29 +02:00
|
|
|
color_on = ''
|
|
|
|
|
color_off = ''
|
|
|
|
|
|
2019-12-21 19:08:51 +00:00
|
|
|
if f_date in _flags:
|
|
|
|
|
msg += datetime.now().strftime("%b %d %H:%M:%S.%f ")
|
|
|
|
|
|
2019-10-28 10:59:20 +01:00
|
|
|
if f_prio in _flags:
|
|
|
|
|
msg += _short_prio_str[prio] + ' '
|
2017-10-25 10:06:29 +02:00
|
|
|
|
2019-10-28 10:59:20 +01:00
|
|
|
if f_position in _flags:
|
2017-10-27 18:58:53 +02:00
|
|
|
if 'caller' in kwargs:
|
|
|
|
|
name, line = kwargs['caller']
|
|
|
|
|
else:
|
|
|
|
|
name, line = get_caller_pos(1)
|
2019-10-30 15:46:26 +01:00
|
|
|
msg += misc.pad(name, _file_name_len) + '[' + misc.pad(str(line), 4, True) + ']'
|
2017-10-25 10:06:29 +02:00
|
|
|
|
2019-10-28 10:59:20 +01:00
|
|
|
if f_color in _flags:
|
2019-12-23 18:01:53 +01:00
|
|
|
color_on, color_off = console_color_chars(prio)
|
2017-10-25 10:06:29 +02:00
|
|
|
|
2019-10-30 15:46:26 +01:00
|
|
|
msg += _log_prefix
|
|
|
|
|
|
2017-10-25 10:06:29 +02:00
|
|
|
if len(args):
|
|
|
|
|
margs = ''
|
|
|
|
|
for a in args:
|
|
|
|
|
margs += ' ' + str(a)
|
2020-05-16 15:33:13 +00:00
|
|
|
if only_printable:
|
|
|
|
|
margs = _special_char_regex.sub(lambda mo: _special_chars[mo.string[mo.start():mo.end()]], margs)
|
|
|
|
|
margs = re.sub('[\x01-\x1f]', '.', margs)
|
2017-10-25 10:06:29 +02:00
|
|
|
msg += color_on + margs + color_off
|
|
|
|
|
|
2019-10-28 12:50:17 +01:00
|
|
|
if not len(msg):
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
files = []
|
2019-10-28 10:59:20 +01:00
|
|
|
if f_stdout in _flags:
|
2019-10-28 12:50:17 +01:00
|
|
|
files.append(sys.stdout)
|
2017-10-25 10:06:29 +02:00
|
|
|
|
2019-10-28 10:59:20 +01:00
|
|
|
if f_stderr in _flags:
|
2019-10-28 12:50:17 +01:00
|
|
|
files.append(sys.stderr)
|
|
|
|
|
|
|
|
|
|
if not len(files):
|
|
|
|
|
files = [ sys.stdout ]
|
2017-10-25 10:06:29 +02:00
|
|
|
|
2019-10-28 12:50:17 +01:00
|
|
|
for file in files:
|
2017-10-25 10:06:29 +02:00
|
|
|
print(msg, file=file)
|
2017-08-07 18:05:53 +02:00
|
|
|
|
2025-01-28 10:17:27 +01:00
|
|
|
def throw(*args, prio=ERR, caller=None, **kwargs) -> None:
|
|
|
|
|
if caller is None:
|
|
|
|
|
caller = get_caller_pos(1)
|
|
|
|
|
msg = ' '.join([str(arg) for arg in args])
|
|
|
|
|
slog(prio, msg, caller=caller)
|
|
|
|
|
raise Exception(msg)
|
|
|
|
|
|
2020-04-10 17:55:36 +02:00
|
|
|
def parse_log_prio_str(prio: str) -> int: # export
|
2017-08-07 18:05:53 +02:00
|
|
|
try:
|
|
|
|
|
r = int(prio)
|
|
|
|
|
if r < 0 or r > DEVEL:
|
2020-04-10 17:55:36 +02:00
|
|
|
raise Exception("Invalid log priority ", prio)
|
2017-08-07 18:05:53 +02:00
|
|
|
except ValueError:
|
|
|
|
|
map_prio_str_to_val = {
|
2019-10-28 10:59:20 +01:00
|
|
|
"EMERG" : EMERG,
|
|
|
|
|
"emerg" : EMERG,
|
|
|
|
|
"ALERT" : ALERT,
|
|
|
|
|
"alert" : ALERT,
|
|
|
|
|
"CRIT" : CRIT,
|
|
|
|
|
"crit" : CRIT,
|
|
|
|
|
"ERR" : ERR,
|
|
|
|
|
"err" : ERR,
|
|
|
|
|
"WARNING" : WARNING,
|
|
|
|
|
"warning" : WARNING,
|
|
|
|
|
"NOTICE" : NOTICE,
|
|
|
|
|
"notice" : NOTICE,
|
|
|
|
|
"INFO" : INFO,
|
|
|
|
|
"info" : INFO,
|
|
|
|
|
"DEBUG" : DEBUG,
|
|
|
|
|
"debug" : DEBUG,
|
|
|
|
|
"DEVEL" : DEVEL,
|
|
|
|
|
"devel" : DEVEL,
|
|
|
|
|
"OFF" : OFF,
|
|
|
|
|
"off" : OFF,
|
2017-08-07 18:05:53 +02:00
|
|
|
}
|
|
|
|
|
if prio in map_prio_str_to_val:
|
|
|
|
|
return map_prio_str_to_val[prio]
|
|
|
|
|
raise Exception("Unknown priority string \"", prio, "\"")
|
|
|
|
|
|
2020-04-10 17:55:36 +02:00
|
|
|
def console_color_chars(prio: int) -> List[str]: # export
|
2019-12-23 18:01:53 +01:00
|
|
|
if not sys.stdout.isatty():
|
|
|
|
|
return [ '', '' ]
|
|
|
|
|
return _prio_colors[prio]
|
2019-10-28 10:59:20 +01:00
|
|
|
|
2020-04-10 17:55:36 +02:00
|
|
|
def set_level(level_: str) -> None: # export
|
2019-10-28 10:59:20 +01:00
|
|
|
global _level
|
2017-08-07 18:05:53 +02:00
|
|
|
if isinstance(level_, basestring):
|
2019-10-28 10:59:20 +01:00
|
|
|
_level = parse_log_prio_str(level_)
|
2017-08-07 18:05:53 +02:00
|
|
|
return
|
2019-10-28 10:59:20 +01:00
|
|
|
_level = level_
|
2017-10-25 10:06:29 +02:00
|
|
|
|
2020-04-10 17:55:36 +02:00
|
|
|
def set_flags(flags_: str) -> None: # export
|
2019-10-28 10:59:20 +01:00
|
|
|
global _flags
|
|
|
|
|
_flags = set(flags_.split(','))
|
2017-10-25 10:06:29 +02:00
|
|
|
|
|
|
|
|
#syslog
|
|
|
|
|
#console
|
|
|
|
|
#color
|
|
|
|
|
#prio
|
|
|
|
|
#position
|
|
|
|
|
#ide
|
|
|
|
|
#trace_rename_thread_to_shorter
|
|
|
|
|
#trace_rename_thread_to_longer
|
|
|
|
|
#trace_inout
|
|
|
|
|
#skip_openlog
|
|
|
|
|
#id
|
|
|
|
|
#date
|
|
|
|
|
#pid
|
|
|
|
|
#highlight_first_error
|
2019-10-30 15:46:26 +01:00
|
|
|
|
2020-04-10 17:55:36 +02:00
|
|
|
def append_to_prefix(prefix: str) -> str: # export
|
2019-10-30 15:46:26 +01:00
|
|
|
global _log_prefix
|
|
|
|
|
r = _log_prefix
|
|
|
|
|
if prefix:
|
|
|
|
|
_log_prefix += prefix
|
|
|
|
|
return r
|
|
|
|
|
|
2020-04-23 10:32:05 +02:00
|
|
|
def remove_from_prefix(count) -> str: # export
|
|
|
|
|
if isinstance(count, str):
|
|
|
|
|
count = len(count)
|
2019-10-30 15:46:26 +01:00
|
|
|
global _log_prefix
|
|
|
|
|
r = _log_prefix
|
|
|
|
|
_log_prefix = _log_prefix[:-count]
|
|
|
|
|
return r
|
|
|
|
|
|
2020-04-10 17:55:36 +02:00
|
|
|
def set_filename_length(l: int) -> int: # export
|
2019-10-30 15:46:26 +01:00
|
|
|
global _file_name_len
|
|
|
|
|
r = _file_name_len
|
|
|
|
|
if l:
|
|
|
|
|
_file_name_len = l
|
|
|
|
|
return r
|