Advertisement
Uno-Dan

Logging Server

May 10th, 2019
224
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 7.80 KB | None | 0 0
  1.  
  2. from os import path, makedirs
  3. from logging import config, Filter, getLogger, INFO, DEBUG, WARNING, ERROR, CRITICAL, FATAL, NOTSET
  4. from multiprocessing import Process
  5. from socket import gethostname, gethostbyname
  6.  
  7. from zmq import Context
  8. from zmq.backend.cython.constants import SUB, SUBSCRIBE, PUSH, PULL
  9.  
  10. PATH_ABS = path.dirname(path.realpath(__file__))
  11. PATH_LOGS = path.join(PATH_ABS, '../logs')
  12. LOG_FORMAT = '%(levelname)s:%(asctime)s:%(process)d:%(name)s:%(filename)s:%(funcName)s:%(lineno)d:%(message)s'
  13.  
  14. _nameToLevel = {
  15.     'CRITICAL': CRITICAL,
  16.     'FATAL': FATAL,
  17.     'ERROR': ERROR,
  18.     'WARN': WARNING,
  19.     'WARNING': WARNING,
  20.     'INFO': INFO,
  21.     'DEBUG': DEBUG,
  22.     'NOTSET': NOTSET,
  23. }
  24.  
  25.  
  26. def spawn(task, *args):
  27.     process = Process(target=task, args=args)
  28.     process.daemon = True
  29.     process.start()
  30.     return process
  31.  
  32.  
  33. class Logger:
  34.     def __init__(self, name, frontend, backend):
  35.         super().__init__()
  36.  
  37.         logger = 'local'
  38.         self.ctx = None
  39.         self.name = name
  40.         self.backend = backend
  41.         self.frontend = frontend
  42.         self.processes = []
  43.         self.logger = getLogger(logger)
  44.         self.hostname = gethostname()
  45.         self.ipaddr = gethostbyname(self.hostname)
  46.  
  47.         _path = path.join(PATH_LOGS, logger)
  48.         if not path.exists(_path):
  49.             makedirs(_path)
  50.  
  51.         self.logger.setLevel(DEBUG)
  52.         config.dictConfig(log_config)
  53.  
  54.     def start(self, nbr_workers):
  55.         ctx = Context()
  56.  
  57.         # Clients connect to the frontend
  58.         frontend = ctx.socket(SUB)
  59.         frontend.setsockopt_string(SUBSCRIBE, '')
  60.         frontend.bind(self.frontend)
  61.  
  62.         # Workers connect to the backend
  63.         backend = ctx.socket(PUSH)
  64.         backend.bind(self.backend)
  65.  
  66.         for idx in range(nbr_workers):
  67.             process = spawn(self.worker, idx)
  68.             self.processes.append(process)
  69.  
  70.         while True:
  71.             request = frontend.recv_multipart()
  72.             backend.send_multipart(request)
  73.  
  74.     def worker(self, index):
  75.         socket = Context().socket(PULL)
  76.         socket.connect(self.backend)
  77.  
  78.         remote_logger = getLogger('remote')  # Handles logs for remote clients
  79.         remote_logger.setLevel(DEBUG)
  80.  
  81.         message = f'{self.hostname}:{self.ipaddr}:{self.name}-{index}:started'
  82.         self.logger.info(message)
  83.  
  84.         while True:
  85.             errorlevel, message = socket.recv_multipart()
  86.             message = message.decode('utf-8')
  87.             errorlevel = errorlevel.decode('utf-8')
  88.             remote_logger.log(_nameToLevel[errorlevel], message)
  89.  
  90.  
  91. class Equals(Filter):
  92.     def __init__(self, param):
  93.         super().__init__()
  94.         self.errorlevel = param if param else NOTSET
  95.  
  96.     def filter(self, record):
  97.         return True if record.levelno == self.errorlevel else False
  98.  
  99.  
  100. class LessThan(Filter):
  101.     def __init__(self, param):
  102.         super().__init__()
  103.         self.errorlevel = param if param else WARNING
  104.  
  105.     def filter(self, record):
  106.         return True if record.levelno < self.errorlevel else False
  107.  
  108.  
  109. class GreaterThan(Filter):
  110.     def __init__(self, param):
  111.         super().__init__()
  112.         self.errorlevel = param if param else INFO
  113.  
  114.     def filter(self, record):
  115.         return True if record.levelno > self.errorlevel else False
  116.  
  117.  
  118. log_config = {
  119.     'version': 1,
  120.     'formatters': {
  121.         'remote': {'format': ''},
  122.         'default': {'format': LOG_FORMAT}
  123.     },
  124.     'loggers': {
  125.         'local': {
  126.             'handlers': [
  127.                 'stdout',
  128.                 'stderr',
  129.                 'debug',
  130.                 'info',
  131.                 'warning',
  132.                 'error',
  133.                 'critical'
  134.             ]
  135.         },
  136.         'remote': {
  137.             'handlers': [
  138.                 'stdout2',
  139.                 'stderr2',
  140.                 'debug2',
  141.                 'info2',
  142.                 'warning2',
  143.                 'error2',
  144.                 'critical2'
  145.             ]
  146.         },
  147.     },
  148.     'filters': {
  149.         'stdout': {
  150.             '()': LessThan,
  151.             'param': WARNING
  152.         },
  153.         'stderr': {
  154.             '()': GreaterThan,
  155.             'param': INFO
  156.         },
  157.         'info': {
  158.             '()': Equals,
  159.             'param': INFO
  160.         },
  161.         'warning': {
  162.             '()': Equals,
  163.             'param': WARNING
  164.         },
  165.         'error': {
  166.             '()': Equals,
  167.             'param': ERROR
  168.         },
  169.         'critical': {
  170.             '()': Equals,
  171.             'param': CRITICAL
  172.         },
  173.     },
  174.     'handlers': {
  175.         'stdout': {
  176.             'class': 'logging.StreamHandler',
  177.             'level': DEBUG,
  178.             'stream': 'ext://sys.stdout',
  179.             'formatter': 'default',
  180.             'filters': ['stdout']
  181.         },
  182.         'stdout2': {
  183.             'class': 'logging.StreamHandler',
  184.             'level': DEBUG,
  185.             'stream': 'ext://sys.stdout',
  186.             'formatter': 'remote',
  187.             'filters': ['stdout']
  188.         },
  189.         'stderr': {
  190.             'class': 'logging.StreamHandler',
  191.             'level': WARNING,
  192.             'stream': 'ext://sys.stderr',
  193.             'formatter': 'default',
  194.             'filters': ['stderr']
  195.         },
  196.         'stderr2': {
  197.             'class': 'logging.StreamHandler',
  198.             'level': WARNING,
  199.             'stream': 'ext://sys.stderr',
  200.             'formatter': 'remote',
  201.             'filters': ['stderr']
  202.         },
  203.         'debug': {
  204.             'class': 'logging.FileHandler',
  205.             'filename': path.join(PATH_LOGS, 'local', 'debug.log'),
  206.             'level': DEBUG,
  207.             'formatter': 'default',
  208.         },
  209.         'debug2': {
  210.             'class': 'logging.handlers.RotatingFileHandler',
  211.             'filename': path.join(PATH_LOGS, 'debug.log'),
  212.             'level': DEBUG,
  213.             'formatter': 'remote',
  214.         },
  215.         'info': {
  216.             'class': 'logging.FileHandler',
  217.             'filename': path.join(PATH_LOGS, 'local', 'info.log'),
  218.             'level': INFO,
  219.             'formatter': 'default',
  220.             'filters': ['info'],
  221.         },
  222.         'info2': {
  223.             'class': 'logging.FileHandler',
  224.             'filename': path.join(PATH_LOGS, 'info.log'),
  225.             'level': INFO,
  226.             'formatter': 'remote',
  227.             'filters': ['info'],
  228.         },
  229.         'warning': {
  230.             'class': 'logging.FileHandler',
  231.             'filename': path.join(PATH_LOGS, 'local', 'warn.log'),
  232.             'level': WARNING,
  233.             'formatter': 'default',
  234.             'filters': ['warning'],
  235.         },
  236.         'warning2': {
  237.             'class': 'logging.FileHandler',
  238.             'filename': path.join(PATH_LOGS, 'warn.log'),
  239.             'level': WARNING,
  240.             'formatter': 'remote',
  241.             'filters': ['warning'],
  242.         },
  243.         'error': {
  244.             'class': 'logging.FileHandler',
  245.             'filename': path.join(PATH_LOGS, 'local', 'error.log'),
  246.             'level': ERROR,
  247.             'formatter': 'default',
  248.             'filters': ['error'],
  249.         },
  250.         'error2': {
  251.             'class': 'logging.FileHandler',
  252.             'filename': path.join(PATH_LOGS, 'error.log'),
  253.             'level': ERROR,
  254.             'formatter': 'remote',
  255.             'filters': ['error'],
  256.         },
  257.         'critical': {
  258.             'class': 'logging.FileHandler',
  259.             'filename': path.join(PATH_LOGS, 'local', 'critical.log'),
  260.             'level': CRITICAL,
  261.             'formatter': 'default',
  262.             'filters': ['critical'],
  263.         },
  264.         'critical2': {
  265.             'class': 'logging.FileHandler',
  266.             'filename': path.join(PATH_LOGS, 'critical.log'),
  267.             'level': CRITICAL,
  268.             'formatter': 'remote',
  269.             'filters': ['critical'],
  270.         },
  271.     },
  272. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement