Commit abfa4420 authored by Giuseppe Carboni's avatar Giuseppe Carboni Committed by aorlati
Browse files

Fix #222, done a little rework on `IRAPY/customlogging.py` module. (#224)

Added an internal method in the CustomLogger class that recursively replaces the `<` and `>` characters in exception strings with `{` and `}` respectively before logging them.
Also now the `logException` method logs the name of the calling method to the user correctly (before this fix the caller appeared to be `logException` with no further informations).
parent c3054faa
Loading
Loading
Loading
Loading
+33 −33
Original line number Original line Diff line number Diff line
"""
"""
This module is intended to replace the ACS Logging module in our python code. 
This module is intended to extend the ACS Logging module in our python code.
This is necessary as our logging events contain a key-value pair of extra data used to distinguish them 
from the ACS system log.
"""
"""
from Acspy.Common import Log
import logging
import logging
import ACSLog
import sys

from Acspy.Common import Log

from ACSLog import ACS_LOG_CRITICAL
"""
Key-Value pair distinguishing our custom logging.
"""
CUSTOM_ENV = dict(source="custom")
CUSTOM_DATA = dict(data=CUSTOM_ENV)
CUSTOM_EXTRA = dict(extra=CUSTOM_DATA)


class CustomLogger(Log.Logger):
class CustomLogger(Log.Logger):
    """This class replaces the standard logging functionalities by overloading the log method. 
    """
    Each log event now will have additional custom key-value data pairs.
    This class replaces the standard logging functionalities by overloading the
    `log` method and by defining a new `logException` method.
    """
    """
    def __init__(self, name):
    def __init__(self, name):
        self.isUserLogger=False
        self.isUserLogger=False
@@ -27,33 +19,41 @@ class CustomLogger(Log.Logger):
        return self._Logger__formatMessage(msg)
        return self._Logger__formatMessage(msg)


    def log(self, level, msg, *args, **kwargs):
    def log(self, level, msg, *args, **kwargs):
        """Add key-value custom data to the LogRecord structure
        # Replace some characters in order to avoid parsing errors
        """
        #if 'extra' in kwargs:
        #    if 'data' in kwargs['extra']:
        #        kwargs['extra']['data'].update(CUSTOM_ENV)
        #    else:
        #        kwargs['extra'].update(CUSTOM_DATA)
        #else:
        #    kwargs.update(CUSTOM_EXTRA)
        msg = msg.replace('[', '{')
        msg = msg.replace('[', '{')
        msg = msg.replace(']', '}')
        msg = msg.replace(']', '}')
        Log.Logger.log(self, level, msg, *args, **kwargs)
        Log.Logger.log(self, level, msg, *args, **kwargs)
        
        
    #This is another workaround to match c++ with buggy python behaviour.
    #It results into having a double entry in acs log
    #The LOG_CRITICAL level correspond in the ERROR level...other ACS bug!
    def logException(self, ex):
    def logException(self, ex):
        """This method is another workaround to match c++ with buggy python
        behaviour. It results into having a double entry in acs log. The
        LOG_CRITICAL level correspond in the ERROR level...other ACS bug!
        """
        ex.errorTrace = self._fix_error_trace(ex.errorTrace)
        if self.isUserLogger:
        if self.isUserLogger:
            self.logError(ex.shortDescription)
            # Get caller name first to log it correctly
        ex.log(self,ACSLog.ACS_LOG_CRITICAL)
            caller = sys._getframe(1).f_code.co_name
            self.log(logging.ERROR, '%s - %s' % (caller, ex.shortDescription))
        ex.log(self, ACS_LOG_CRITICAL)

    def _fix_error_trace(self, trace):
        """In order to avoid XML parsing errors in the CustomLogger component,
        fields errorTrace.file and errorTrace.routine must not have XML key
        characters `<` and `>`, therefore, we replace them with `{` and `}`."""
        trace.file = trace.file.replace('<', '{').replace('>', '}')
        trace.routine = trace.routine.replace('<', '{').replace('>', '}')
        for index in range(len(trace.previousError)):
            previousTrace = trace.previousError[index]
            previousTrace = self._fix_error_trace(previousTrace)
            trace.previousError[index] = previousTrace
        return trace



logging.setLoggerClass(CustomLogger)
logging.setLoggerClass(CustomLogger)
logging.root.setLevel(logging.NOTSET)
logging.root.setLevel(logging.NOTSET)


def getLogger(name=None):
def getLogger(name=None):
    """Get our custom logger form the system
    """Get our custom logger from the system."""
    """
    return logging.getLogger(str(name))
    return logging.getLogger(str(name))


if __name__ == '__main__':
if __name__ == '__main__':