Coverage for /Users/davegaeddert/Development/dropseed/plain/plain/plain/logs/loggers.py: 35%

1 import logging

2

3 app_logger = logging.getLogger("app")

4

5

6 class KVLogger:

7 def __init__(self, logger):

8 self.logger = logger

9 self.context = {} # A dict that will be output in every log message

10

11 def log(self, level, message, **kwargs):

12 msg_kwargs = {

13 **kwargs,

14 **self.context, # Put these last so they're at the end of the line

15 }

16 self.logger.log(level, f"{message} {self._format_kwargs(msg_kwargs)}")

17

18 def _format_kwargs(self, kwargs):

19 outputs = []

20

21 for k, v in kwargs.items():

22 self._validate_key(k)

23 formatted_value = self._format_value(v)

24 outputs.append(f"{k}={formatted_value}")

25

26 return " ".join(outputs)

27

28 def _validate_key(self, key):

29 if " " in key:

30 raise ValueError("Keys cannot have spaces")

31

32 if "=" in key:

33 raise ValueError("Keys cannot have equals signs")

34

35 if '"' in key or "'" in key:

36 raise ValueError("Keys cannot have quotes")

37

38 def _format_value(self, value):

39 if isinstance(value, str):

40 s = value

41 else:

42 s = str(value)

43

44 if '"' in s:

45 # Escape quotes and surround it

46 s = s.replace('"', '\\"')

47 s = f'"{s}"'

48 elif s == "":

49 # Quote empty strings instead of printing nothing

50 s = '""'

51 elif any(char in s for char in [" ", "/", "'", ":", "=", "."]):

52 # Surround these with quotes for parsers

53 s = f'"{s}"'

54

55 return s

56

57 def info(self, message, **kwargs):

58 self.log(logging.INFO, message, **kwargs)

59

60 def debug(self, message, **kwargs):

61 self.log(logging.DEBUG, message, **kwargs)

62

63 def warning(self, message, **kwargs):

64 self.log(logging.WARNING, message, **kwargs)

65

66 def error(self, message, **kwargs):

67 self.log(logging.ERROR, message, **kwargs)

68

69 def critical(self, message, **kwargs):

70 self.log(logging.CRITICAL, message, **kwargs)

71

72

73# Make this accessible from the app_logger

74 app_logger.kv = KVLogger(app_logger)