add RemoteLogHandler independent of MainLogger

installing a custom logger was not possible, since the RemoteLogHandler
was not installed.
Additionally, search for the RemoteLogHandler recursively upwards, since
not all loggers copy their Hanlders to their children.

Change-Id: If3e19966d9289cacd926648582e9718b7eab279c
Reviewed-on: https://forge.frm2.tum.de/review/c/secop/frappy/+/34288
Reviewed-by: Alexander Zaft <a.zaft@fz-juelich.de>
Tested-by: Jenkins Automated Tests <pedersen+jenkins@frm2.tum.de>
This commit is contained in:
Alexander Zaft 2024-08-01 08:56:33 +02:00 committed by Markus Zolliker
parent 1f5bba5575
commit 6f465be567
5 changed files with 36 additions and 12 deletions

View File

@ -51,6 +51,7 @@ def check_level(level):
class RemoteLogHandler(mlzlog.Handler): class RemoteLogHandler(mlzlog.Handler):
"""handler for remote logging""" """handler for remote logging"""
def __init__(self): def __init__(self):
super().__init__() super().__init__()
self.subscriptions = {} # dict[modname] of tuple(mobobj, dict [conn] of level) self.subscriptions = {} # dict[modname] of tuple(mobobj, dict [conn] of level)
@ -131,7 +132,6 @@ class HasComlog:
directory = join(logger.logdir, logger.rootname, 'comlog', self.secNode.name) directory = join(logger.logdir, logger.rootname, 'comlog', self.secNode.name)
self._comLog.addHandler(ComLogfileHandler( self._comLog.addHandler(ComLogfileHandler(
directory, self.name, max_days=generalConfig.getint('comlog_days', 7))) directory, self.name, max_days=generalConfig.getint('comlog_days', 7)))
return
def comLog(self, msg, *args, **kwds): def comLog(self, msg, *args, **kwds):
self.log.log(COMLOG, msg, *args, **kwds) self.log.log(COMLOG, msg, *args, **kwds)
@ -139,6 +139,11 @@ class HasComlog:
self._comLog.info(msg, *args) self._comLog.info(msg, *args)
def init_remote_logging(log):
'''Install RemoteLogHandler to the given logger.'''
log.addHandler(RemoteLogHandler())
class MainLogger: class MainLogger:
def __init__(self): def __init__(self):
self.log = None self.log = None
@ -164,8 +169,6 @@ class MainLogger:
logfile_handler = LogfileHandler(self.logdir, self.rootname, max_days=logfile_days) logfile_handler = LogfileHandler(self.logdir, self.rootname, max_days=logfile_days)
logfile_handler.setLevel(LOG_LEVELS[generalConfig.get('logfile_level', 'info')]) logfile_handler.setLevel(LOG_LEVELS[generalConfig.get('logfile_level', 'info')])
self.log.addHandler(logfile_handler) self.log.addHandler(logfile_handler)
self.log.addHandler(RemoteLogHandler())
self.log.handlers[0].setLevel(LOG_LEVELS[console_level]) self.log.handlers[0].setLevel(LOG_LEVELS[console_level])

View File

@ -523,6 +523,7 @@ class Module(HasAccessibles):
value = pobj.datatype(value) value = pobj.datatype(value)
except Exception as e: except Exception as e:
err = e err = e
changed = False
else: else:
changed = pobj.value != value or pobj.readerror changed = pobj.value != value or pobj.readerror
# store the value even in case of error # store the value even in case of error
@ -797,11 +798,20 @@ class Module(HasAccessibles):
def setRemoteLogging(self, conn, level, send_log): def setRemoteLogging(self, conn, level, send_log):
if self.remoteLogHandler is None: if self.remoteLogHandler is None:
for handler in self.log.handlers: # for non-mlzlog loggers: search parents for remoteloghandler
log = self.log
while log is not None:
for handler in log.handlers:
if isinstance(handler, RemoteLogHandler): if isinstance(handler, RemoteLogHandler):
handler.send_log = send_log handler.send_log = send_log
self.remoteLogHandler = handler self.remoteLogHandler = handler
break break
if self.remoteLogHandler is None:
# if the log message does not propagate, we would not get it in
# the handler anyway, so we can stop searching and fail
log = log.parent if log.propagate else None
else:
break
else: else:
raise ValueError('remote handler not found') raise ValueError('remote handler not found')
self.remoteLogHandler.set_conn_level(self.name, conn, level) self.remoteLogHandler.set_conn_level(self.name, conn, level)

View File

@ -31,6 +31,7 @@ from frappy.config import load_config
from frappy.errors import ConfigError from frappy.errors import ConfigError
from frappy.lib import formatException, generalConfig, get_class, mkthread from frappy.lib import formatException, generalConfig, get_class, mkthread
from frappy.lib.multievent import MultiEvent from frappy.lib.multievent import MultiEvent
from frappy.logging import init_remote_logging
from frappy.params import PREDEFINED_ACCESSIBLES from frappy.params import PREDEFINED_ACCESSIBLES
from frappy.secnode import SecNode from frappy.secnode import SecNode
@ -62,7 +63,8 @@ class Server:
Arguments: Arguments:
- name: the node name - name: the node name
- parent_logger: the logger to inherit from - parent_logger: the logger to inherit from. a handler is installed by
the server to provide remote logging
- cfgfiles: if not given, defaults to name - cfgfiles: if not given, defaults to name
may be a comma separated list of cfg files may be a comma separated list of cfg files
items ending with .cfg are taken as paths, else .cfg is appended and items ending with .cfg are taken as paths, else .cfg is appended and
@ -93,6 +95,7 @@ class Server:
# sanitize name (in case it is a cfgfile) # sanitize name (in case it is a cfgfile)
name = os.path.splitext(os.path.basename(name))[0] name = os.path.splitext(os.path.basename(name))[0]
self.log = parent_logger.getChild(name, True) self.log = parent_logger.getChild(name, True)
init_remote_logging(self.log)
merged_cfg = load_config(cfgfiles, self.log) merged_cfg = load_config(cfgfiles, self.log)
self.node_cfg = merged_cfg.pop('node') self.node_cfg = merged_cfg.pop('node')

View File

@ -19,13 +19,15 @@
# #
# ***************************************************************************** # *****************************************************************************
import pytest
import mlzlog import mlzlog
import pytest
import frappy.logging
from frappy.logging import HasComlog, generalConfig, init_remote_logging, \
logger
from frappy.modules import Module from frappy.modules import Module
from frappy.protocol.dispatcher import Dispatcher from frappy.protocol.dispatcher import Dispatcher
from frappy.protocol.interface import encode_msg_frame, decode_msg from frappy.protocol.interface import decode_msg, encode_msg_frame
import frappy.logging
from frappy.logging import logger, generalConfig, HasComlog
class SecNodeStub: class SecNodeStub:
@ -127,6 +129,7 @@ def init_(monkeypatch):
generalConfig.testinit(logger_root='frappy', comlog=comlog) generalConfig.testinit(logger_root='frappy', comlog=comlog)
logger.init(console_level) logger.init(console_level)
init_remote_logging(logger.log)
self.srv = ServerStub() self.srv = ServerStub()
self.conn1 = Connection('conn1', self.srv.dispatcher, self.result_dict['conn1']) self.conn1 = Connection('conn1', self.srv.dispatcher, self.result_dict['conn1'])

View File

@ -37,6 +37,11 @@ class LoggerStub:
def getChild(self, *args): def getChild(self, *args):
return self return self
def addHandler(self, *args):
pass
info = warning = exception = error = debug info = warning = exception = error = debug
handlers = [] handlers = []