log.py 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. # adapted from https://medium.com/@jonathonbao/python3-logging-with-multiprocessing-f51f460b8778
  2. import logging
  3. import threading
  4. import os
  5. import signal
  6. import queue
  7. import multiprocessing as mp
  8. from logging import handlers
  9. from setproctitle import setproctitle
  10. from collections import deque
  11. def listener_configurer():
  12. root = logging.getLogger()
  13. console_handler = logging.StreamHandler()
  14. formatter = logging.Formatter(
  15. "[%(asctime)s] %(name)-30s %(levelname)-8s: %(message)s", "%Y-%m-%d %H:%M:%S"
  16. )
  17. console_handler.setFormatter(formatter)
  18. root.addHandler(console_handler)
  19. root.setLevel(logging.INFO)
  20. def root_configurer(queue):
  21. h = handlers.QueueHandler(queue)
  22. root = logging.getLogger()
  23. root.addHandler(h)
  24. root.setLevel(logging.INFO)
  25. def log_process(log_queue):
  26. threading.current_thread().name = f"logger"
  27. setproctitle("frigate.logger")
  28. listener_configurer()
  29. while True:
  30. try:
  31. record = log_queue.get(timeout=5)
  32. except (queue.Empty, KeyboardInterrupt):
  33. continue
  34. logger = logging.getLogger(record.name)
  35. logger.handle(record)
  36. # based on https://codereview.stackexchange.com/a/17959
  37. class LogPipe(threading.Thread):
  38. def __init__(self, log_name, level):
  39. """Setup the object with a logger and a loglevel
  40. and start the thread
  41. """
  42. threading.Thread.__init__(self)
  43. self.daemon = False
  44. self.logger = logging.getLogger(log_name)
  45. self.level = level
  46. self.deque = deque(maxlen=100)
  47. self.fdRead, self.fdWrite = os.pipe()
  48. self.pipeReader = os.fdopen(self.fdRead)
  49. self.start()
  50. def fileno(self):
  51. """Return the write file descriptor of the pipe"""
  52. return self.fdWrite
  53. def run(self):
  54. """Run the thread, logging everything."""
  55. for line in iter(self.pipeReader.readline, ""):
  56. self.deque.append(line.strip("\n"))
  57. self.pipeReader.close()
  58. def dump(self):
  59. while len(self.deque) > 0:
  60. self.logger.log(self.level, self.deque.popleft())
  61. def close(self):
  62. """Close the write end of the pipe."""
  63. os.close(self.fdWrite)