frappy/secop/logging.py
Markus Zolliker 9109170752 logging as of 2022-02-01
Change-Id: I63c681bea9553cd822b214075b163ca6c42fe0cc
2022-02-02 09:54:54 +01:00

128 lines
4.2 KiB
Python

# -*- coding: utf-8 -*-
# *****************************************************************************
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# Module authors:
# Markus Zolliker <markus.zolliker@psi.ch>
#
# *****************************************************************************
import os
from os.path import dirname, join
import mlzlog
from secop.lib import getGeneralConfig
OFF = 99
LOG_LEVELS = dict(mlzlog.LOGLEVELS, off=OFF)
LEVEL_NAMES = {v: k for k, v in LOG_LEVELS.items()}
log = None
rootlogdir = None
def checkLevel(level):
try:
if isinstance(level, str):
return LOG_LEVELS[level.lower()]
if level in LEVEL_NAMES:
return level
except KeyError:
pass
raise ValueError('%r is not a valid level' % level)
def initLogging(loglevel='info'):
global log, rootlogdir # pylint: disable-global-statement
loglevel = checkLevel(loglevel)
genConfig = getGeneralConfig()
rootname = genConfig.get('rootname', 'secop')
logdir = genConfig.get('logdir')
rootlogdir = join(logdir, rootname)
mlzlog.initLogging(rootname, 'debug', logdir)
for hdl in mlzlog.log.handlers:
hdl.setLevel(loglevel)
return mlzlog.log
class ComlogHandler(mlzlog.LogfileHandler):
"""handler for logging communication
communication is
"""
def format(self, record):
return '%s %s' % (self.formatter.formatTime(record), record.getMessage())
def doRollover(self):
super().doRollover()
max_days = getGeneralConfig().get('comlog_days', 31)
# keep only the last max_days files
with os.scandir(dirname(self.baseFilename)) as it:
files = sorted(entry.path for entry in it if entry.name != 'current')
for filepath in files[-max_days:]:
os.remove(filepath)
def add_comlog_handler(modobj):
global rootlogdir # pylint: disable-global-statement
comlog = getGeneralConfig().get('comlog')
if comlog:
comlog = join(rootlogdir, comlog)
modobj.log.addHandler(ComlogHandler(comlog, modobj.name))
class RemoteLogHandler(mlzlog.Handler):
"""handler for remote logging"""
def __init__(self, modobj):
super().__init__()
self.subscriptions = {} # dict [conn] of level
self.modobj = modobj
self.modobj.log.addHandler(self)
self.used_by = set()
def handle(self, record, name=None):
result = False
for conn, lev in self.subscriptions.items():
if record.levelno >= lev:
msg = record.getMessage()
if self.modobj.DISPATCHER.send_log_msg(
conn, name or self.modobj.name, LEVEL_NAMES[record.levelno], msg):
result = True
if result:
return True
for master in self.used_by:
# this is an iodev, try to handle by one of our masters
if master.remoteLogHandler.handle(record, self.modobj.name):
return True
return False
def set_conn_level(self, conn, level):
level = checkLevel(level)
if level == mlzlog.DEBUG:
iodev = getattr(self.modobj, '_iodev', None)
if iodev:
# we want also to see debug messages of iodev
if iodev.remoteLogHandler is None:
iodev.remoteLogHandler = RemoteLogHandler(self)
iodev.remoteLogHandler.used_by.add(self.modobj)
level = checkLevel(level)
if level == OFF:
self.subscriptions.pop(conn, None)
else:
self.subscriptions[conn] = level