# function for collecting and writing messages i.e. logging and calculate the return-code # ------------------------------------------------------------------------ """ there are two types of logging: * log everything relevant to document the test-run in relation of the test-system and the test-effort should be logged in order to archive these logfiles * debug everything to know how this automatism is running should log into a debug-file. This file can be removed after a few days the logging is parametrized by the log-level (fatal ... trace). Especially the debug- and trace-message can be switched on/of en detail in the functions and over special settings (parameter tool, component: these debugs should be switched on) there are three types of functions: * setFatal|Error|...() it logs, sets the top-message and return-code * logFatal|Error|...() it logs without any effect for the program-result * log()|debug(int) it logs depending on the special level-setting at the end of a program there are some results: * for each component there is a return-code, a top-message for documentation in the parameter-file, and a list of collected messages + for the main-program the result (return-code, top-message) will be summarized (the most relevant message will used) """ import basic.program import os import math from datetime import datetime import utils.path_tool import utils.i18n_tool import basic.text_const as T LIMIT_FATAL = 0 LIMIT_ERROR = 4 LIMIT_WARN = 8 LIMIT_MSG = 12 LIMIT_INFO = 16 LIMIT_DEBUG = 20 LIMIT_TRACE = 24 RC_OFFSET = 4 RC_FATAL = 8 RC_ERROR = 6 RC_WARN = 5 RC_MSG = 4 RC_INFO = 3 RC_DEBUG = 2 RC_TRACE = 1 class Message: """ Ausgaben erfolgen prioritaeten-gesteuert anhand * Typ (fatal..trace) * Einstellung (a) ueber Parameter ODER (b) in Funktion Im Funktionskopf wird Einstellung gesetzt, z.B. verify=job.getDebugLevel (ggf keine Debug-Ausgabe) bzw. verify=job.getDebugLevel-1 (eingeschaltete Debug-Ausgabe) "fatal": "4", # Abbruchfehlker, wird immer in debug und log ausgegeben, setzt RC "error": "8", # Fehler, wird immer in debug und log ausgegeben, setzt RC "warn": "12", # Warnung, wird immer in debug und log ausgegeben, setzt RC "msg": "16", # Ergebnis, wird immer in debug und log ausgegeben, setzt RC "info": "20", # Info, wird ggf. in debug und log ausgegeben, setzt RC "debug": "24", # wird nur in debug ausgegeben, wenn log-level hoechstens auf eingestelltem job-level steht "trace": "28", # wird nur in debug ausgegeben, wenn log-level hoechstens auf eingestelltem job-level steht """ def __init__(self, job, level, logTime, componente): # (self, componente, out, level): self.job = job self.componente = componente # dezantrales Logsystem verify = LIMIT_DEBUG self.initErrorTyp() self.rc = RC_INFO if (level == 0): self.level = LIMIT_DEBUG else: self.level = level # init debugfile - except for each component if componente is not None: # use general debugfile self.debugfile = job.m.debugfile self.debug(verify, "> > > debugfile uebernommen zu " + str(componente)) else: debugpath = job.conf.confs["paths"]["debugs"] + "/debug_" + logTime[0:-4] + "00.txt" print ("debugpathx "+debugpath) if os.path.exists(debugpath): self.debugfile = open(debugpath, "a") else: self.debugfile = open(debugpath, "w") self.debug(verify, "> > > debugfile geoeffnet zu " + job.program + " mit " + debugpath) # init logfile - except for components or unittest self.logDebug("logfile " + str(componente) + ", " + str(job.par.basedir)) if componente is not None: # self.logfile = self.debugfile elif job.program == "unit": self.logfile = self.debugfile else: self.setLogdir(job, logTime) self.topmessage = "" self.messages = [] print("message initialisiert mit level " + str(self.level)) def setLogdir(self, job, logTime): basedir = job.par.basedir basedir = basedir.replace("base", "log") # basedir = utils.path_tool.composePath(basedir, None) basedir = utils.path_tool.composePath(basedir, None) os.makedirs(basedir, exist_ok=True) logpath = os.path.join(basedir , job.program + "_" + logTime + ".txt") self.logDebug("logfile " + logpath) self.logfile = open(logpath, "w") def initErrorTyp(self): self.CONST_ERRTYP = { "fatal": "4", # wird immer in debug und log ausgegeben, setzt RC "error": "8", # wird immer in debug und log ausgegeben, setzt RC "warn": "12", # wird immer in debug und log ausgegeben, setzt RC "msg": "16", # wird immer in debug und log ausgegeben, setzt RC "info": "20", # wird immer in debug und log ausgegeben, setzt RC "debug": "24", # wird nur in debug ausgegeben, wenn log-level hoechstens auf eingestelltem job-level steht "trace": "28", # wird nur in debug ausgegeben, wenn log-level hoechstens auf eingestelltem job-level steht "rc1": "fatal", "rc2": "error", "rc3": "warn", "rc4": "info", "rc5": "debug", "rc6": "trace", "1": "fatal", "2": "error", "3": "warn", "4": "info", "5": "debug", "6": "trace" } def getErrortyp(self, prio): if prio <= LIMIT_FATAL: return "FATAL" elif prio <= LIMIT_ERROR: return "ERROR" elif prio <= LIMIT_WARN: return "WARN" elif prio <= LIMIT_MSG: return "MESSAGE" elif prio <= LIMIT_INFO: return "INFO" elif prio <= LIMIT_DEBUG: return "DEBUG" elif prio <= LIMIT_TRACE: return "TRACE" else: return "NDEF" def closeMessage(self) : self.debug(LIMIT_INFO, "closeMessage ------------------------------------------- \n") self.logfile.close() self.debugfile.close() def setRc(self, rc, text): job = self.job #basic.program.Job.getInstance() verify = -0+LIMIT_DEBUG self.debug(verify, "setRc " + str(rc) + " " + str(self.rc)+ "\n") if (int(rc) > self.rc): self.rc = rc self.topmessage = self.CONST_ERRTYP["rc"+str(rc)].upper() + ": " + text elif (int(rc) == self.rc): self.topmessage = self.CONST_ERRTYP["rc"+str(rc)].upper() + ": " + text def isRc(self, rc): rcId = int(int(self.CONST_ERRTYP[rc]) / 4 - RC_OFFSET) print("< < < isRc " + str(self.rc) + " <=? " + str(rcId)) if self.rc <= int(rcId): print("return True") return True else: print("return False") return False def getFinalRc(self): if (self.rc <= RC_OFFSET): return 0 else: return int(int(self.rc) - RC_OFFSET) def setFatal(self, text): """ Routine zum Setzen des RC und gleichzeitigem Schreiben des Logs """ self.setRc(RC_FATAL, text) self.logFatal(text) def setError(self, text): """ Routine zum Setzen des RC und gleichzeitigem Schreiben des Logs """ self.setRc(RC_ERROR, text) self.logError(text) def setWarn(self, text): """ Routine zum Setzen des RC und gleichzeitigem Schreiben des Logs """ self.setRc(RC_WARN, text) self.logWarn(text) def setMsg(self, text): """ Routine zum Setzen des RC und gleichzeitigem Schreiben des Logs """ self.setRc(RC_MSG, text) self.logInfo(text) def getMessageText(self, text, args): out = "" constName = "" for i in range(0, len(T.LIST_EXP_TEXT)): if text == T.LIST_EXP_TEXT[i]: constName = T.LIST_EXP_CONST[i] txt = utils.i18n_tool.I18n.getInstance().getMessage(self.job, constName, args) out = txt.format(args) return out def logFatal(self, text): self.log(LIMIT_FATAL, "FATAL: " + text) self.debug(LIMIT_FATAL, "FATAL: " + text) def logError(self, text): self.log(LIMIT_ERROR, "ERROR: " + text) self.debug(LIMIT_ERROR, "ERROR: " + text) def logWarn(self, text): self.log(LIMIT_WARN, "WARN: " + text) def logMsg(self, text): self.log(LIMIT_MSG, text) self.log(LIMIT_MSG, "MSG: " + text) def logInfo(self, text): self.log(LIMIT_INFO, text) def logDebug(self, text): self.debug(LIMIT_DEBUG, text) def logTrace(self, text): self.debug(LIMIT_TRACE, text) def log(self, prio, text): """ eigentliche Schreibroutine: hierin wird debug-Level beruecksichtgigt""" if (int(prio) <= int(self.level)) and (self.componente is None): # and self.logfile.closed == False: self.logfile.write(text + "\n") elif (int(prio) <= int(self.level)): self.messages.append(text) else: self.debug(prio, self.getErrortyp(prio) + ": " + text) def debug(self, prio, text): """ eigentliche Schreibroutine: hierin wird debug-Level beruecksichtgigt""" if (int(prio) < int(self.level)+1) : #and self.debugfile.closed == False: self.debugfile.write(text + "\n") def resetLog(self): self.messages = [] def merge(self, submsg): self.setRc(submsg.getFinalRc(), submsg.topmessage) text = "\n".join(submsg.messages) self.logInfo("\n"+text+"\n")