From bd9f8fce13da4afe0d8e7603db13a9e403f1c2c1 Mon Sep 17 00:00:00 2001 From: Anthony Geay Date: Thu, 28 Dec 2023 14:51:29 +0100 Subject: [PATCH] [EDF29150] : Distinguish verbosity and verbosity_level --- bin/runSalomeCommon.py | 59 +----------- bin/salome_utils.py | 94 +++++++++++++++++-- idl/SALOME_Component.idl | 4 +- src/Basics/KernelBasis.i | 31 ++++++- src/Basics/libSALOMELog.cxx | 104 +++++++++++++++++++--- src/Basics/libSALOMELog.hxx | 9 ++ src/Container/Container_i.cxx | 19 ++-- src/Container/SALOME_Container.py | 6 +- src/Container/SALOME_ContainerManager.cxx | 2 +- src/Container/SALOME_Container_i.hxx | 4 +- src/Container/SALOME_PyNode.py | 1 - 11 files changed, 239 insertions(+), 94 deletions(-) diff --git a/bin/runSalomeCommon.py b/bin/runSalomeCommon.py index 632c7e03b..6466c9a3e 100755 --- a/bin/runSalomeCommon.py +++ b/bin/runSalomeCommon.py @@ -34,68 +34,13 @@ import subprocess from salomeContextUtils import ScriptAndArgsObjectEncoder import platform import logging +from salome_utils import positionVerbosityOfLogger -## Setting formatter in setVerbose() was commented because adding of handler -## breaks using of root logger in other modules and cause many double lines in logs. -#FORMAT = '%(levelname)s : %(asctime)s : [%(filename)s:%(funcName)s:%(lineno)s] : %(message)s' -#logging.basicConfig(format=FORMAT) logger = logging.getLogger() -class ColoredFormatter(logging.Formatter): - BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = range(30,38) - COLORS = { 'WARNING': YELLOW, 'INFO': WHITE, 'DEBUG': BLUE, 'CRITICAL': YELLOW, 'ERROR': RED } - def __init__(self, *args, **kwargs): - logging.Formatter.__init__(self, *args, **kwargs) - def format(self, record): - RESET_SEQ = "\033[0m" - COLOR_SEQ = "\033[1;%dm" - import inspect - frame = inspect.currentframe() - for i in range(8): - frame = frame.f_back - record.levelname = COLOR_SEQ % ColoredFormatter.COLORS[record.levelname] + record.levelname + RESET_SEQ - record.msg = "{} ( callsite is {} of file \"{}\" at line {} )".format(record.msg, frame.f_code.co_name,inspect.getsourcefile(frame),inspect.getlineno(frame) ) - return logging.Formatter.format(self, record) - -class BackTraceFormatter(logging.Formatter): - def __init__(self, *args, **kwargs): - logging.Formatter.__init__(self, *args, **kwargs) - def format(self, record): - import inspect - frame = inspect.currentframe() - # go upward with ( a limit of 10 steps ) of the stack to catch the effective callsite. Not very steady.... - # should be replaced by an analysis of frame.f_code - for i in range(10): - frame = frame.f_back - if inspect.getsourcefile(frame) != logging.__file__: - break - record.msg = "{} ( callsite is {} of file \"{}\" at line {} )".format(record.msg, frame.f_code.co_name,inspect.getsourcefile(frame),inspect.getlineno(frame) ) - return logging.Formatter.format(self, record) - def setVerbose(verbose): - from packaging import version - current_version = version.parse("{}.{}".format(sys.version_info.major,sys.version_info.minor)) - version_ref = version.parse("3.5.0") - global logger - formatter = None - if current_version >= version_ref: - formatter = BackTraceFormatter('%(levelname)s : %(asctime)s : %(message)s ',style='%') - else: - formatter = logging.Formatter('%(levelname)s : %(asctime)s : %(message)s ',style='%') - formatter.default_time_format = '%H:%M:%S' - formatter.default_msec_format = "%s.%03d" - stream_handler = logging.StreamHandler() - stream_handler.setFormatter(formatter) - logger.addHandler(stream_handler) - verbose_map = { "0": logging.WARNING, "1": logging.INFO, "2": logging.DEBUG} - if verbose in verbose_map: - logger.setLevel(verbose_map[verbose]) - -def positionVerbosityOfLogger(): - import KernelBasis - setVerbose( {False:"0",True:"2"}[KernelBasis.VerbosityActivated()] ) - + positionVerbosityOfLogger( verbose_map[verbose] ) # ----------------------------------------------------------------------------- # # Class definitions to launch CORBA Servers diff --git a/bin/salome_utils.py b/bin/salome_utils.py index 20af63b4b..c9bd502f7 100644 --- a/bin/salome_utils.py +++ b/bin/salome_utils.py @@ -34,10 +34,17 @@ import shutil import socket import sys import tempfile +import logging from contextlib import suppress import psutil +## Setting formatter in setVerbose() was commented because adding of handler +## breaks using of root logger in other modules and cause many double lines in logs. +#FORMAT = '%(levelname)s : %(asctime)s : [%(filename)s:%(funcName)s:%(lineno)s] : %(message)s' +#logging.basicConfig(format=FORMAT) +logger = logging.getLogger() + def _try_bool(arg): """ Convert given `arg` to a boolean value. @@ -384,6 +391,57 @@ def uniteFiles(src_file, dest_file): # -- +class ColoredFormatter(logging.Formatter): + BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = range(30,38) + COLORS = { 'WARNING': YELLOW, 'INFO': WHITE, 'DEBUG': BLUE, 'CRITICAL': YELLOW, 'ERROR': RED } + def __init__(self, *args, **kwargs): + logging.Formatter.__init__(self, *args, **kwargs) + def format(self, record): + RESET_SEQ = "\033[0m" + COLOR_SEQ = "\033[1;%dm" + import inspect + frame = inspect.currentframe() + for i in range(8): + frame = frame.f_back + record.levelname = COLOR_SEQ % ColoredFormatter.COLORS[record.levelname] + record.levelname + RESET_SEQ + record.msg = "{} ( callsite is {} of file \"{}\" at line {} )".format(record.msg, frame.f_code.co_name,inspect.getsourcefile(frame),inspect.getlineno(frame) ) + return logging.Formatter.format(self, record) + +class BackTraceFormatter(logging.Formatter): + def __init__(self, *args, **kwargs): + logging.Formatter.__init__(self, *args, **kwargs) + def format(self, record): + import inspect + frame = inspect.currentframe() + # go upward with ( a limit of 10 steps ) of the stack to catch the effective callsite. Not very steady.... + # should be replaced by an analysis of frame.f_code + for i in range(10): + frame = frame.f_back + if inspect.getsourcefile(frame) != logging.__file__: + break + record.msg = "{} ( callsite is {} of file \"{}\" at line {} )".format(record.msg, frame.f_code.co_name,inspect.getsourcefile(frame),inspect.getlineno(frame) ) + return logging.Formatter.format(self, record) + +def positionVerbosityOfLogger( verboseLevel ): + from packaging import version + current_version = version.parse("{}.{}".format(sys.version_info.major,sys.version_info.minor)) + version_ref = version.parse("3.5.0") + global logger + formatter = None + if current_version >= version_ref: + formatter = BackTraceFormatter('%(levelname)s : %(asctime)s : %(message)s ',style='%') + else: + formatter = logging.Formatter('%(levelname)s : %(asctime)s : %(message)s ',style='%') + formatter.default_time_format = '%H:%M:%S' + formatter.default_msec_format = "%s.%03d" + stream_handler = logging.StreamHandler() + stream_handler.setFormatter(formatter) + logger.addHandler(stream_handler) + logger.setLevel(verboseLevel) + +def positionVerbosityOfLoggerRegardingState(): + positionVerbosityOfLogger( verboseLevel() ) + def verbose(): """ Get current verbosity level. @@ -397,22 +455,40 @@ def verbose(): :return current verbosity level """ - if not hasattr(verbose, 'verbosity_level'): - verbose.verbosity_level = 0 # default value - with suppress(TypeError, ValueError): - # from SALOME_VERBOSE environment variable - verbose.verbosity_level = int(os.getenv('SALOME_VERBOSE', '0')) - return verbose.verbosity_level + import KernelBasis + return KernelBasis.VerbosityActivated() + +# -- + +def setVerbose(status): + """ + Change verbosity level. + The function `verbose()` can be used to get current verbosity level. + :param status : verbosity status + :type status: bool + """ + import KernelBasis + return KernelBasis.SetVerbosityActivated( status ) + # -- -def setVerbose(level): +KernelLogLevelToLogging = {"INFO":logging.INFO, "DEBUG":logging.DEBUG, "WARNING":logging.WARNING, "ERROR":logging.ERROR} + +LoggingToKernelLogLevel = {v: k for k, v in KernelLogLevelToLogging.items()} + +def verboseLevel(): + import KernelBasis + return KernelLogLevelToLogging[ KernelBasis.VerbosityLevel() ] + +def setVerboseLevel(level): """ Change verbosity level. The function `verbose()` can be used to get current verbosity level. :param level : verbosity level """ - with suppress(TypeError, ValueError): - verbose.verbosity_level = int(level) + import KernelBasis + KernelBasis.SetVerbosityLevel(LoggingToKernelLogLevel[ level ]) + # -- def killPid(pid, sig=9): diff --git a/idl/SALOME_Component.idl b/idl/SALOME_Component.idl index 7c3b0283b..fba9652e2 100644 --- a/idl/SALOME_Component.idl +++ b/idl/SALOME_Component.idl @@ -182,7 +182,9 @@ module Engines //! name of the %container log file attribute string locallogfilename ; - attribute long verboselevel; + void verbosity(out boolean activated, out string level); + + void setVerbosity(in boolean activated, in string level); //! Shutdown the Container process. void Shutdown(); diff --git a/src/Basics/KernelBasis.i b/src/Basics/KernelBasis.i index 45908234b..cf78f1d79 100644 --- a/src/Basics/KernelBasis.i +++ b/src/Basics/KernelBasis.i @@ -26,7 +26,24 @@ using namespace SALOME; %} -%include "std_string.i" +%include std_string.i +%include std_set.i +%include std_except.i + +%exception { + try + { + $action + } + catch(std::exception& e) + { + SWIG_exception(SWIG_SystemError, e.what() ); + } + catch(...) + { + SWIG_exception(SWIG_UnknownError, "Unknown exception"); + } +} %rename (HeatMarcel) HeatMarcelSwig; @@ -49,6 +66,8 @@ void WriteInStdout(const std::string& msg); void WriteInStderr(const std::string& msg); +%rename (SetVerbosityLevel) SetVerbosityLevelSwig; +%rename (VerbosityLevel) VerbosityLevelSwig; %inline { @@ -61,4 +80,14 @@ PyObject *HeatMarcelSwig(double timeAjustment, unsigned int nbThreads = 0) PyTuple_SetItem(ret,1,SWIG_From_double(timeInS)); return ret; } + +void SetVerbosityLevelSwig(const std::string& level) +{ + SetVerbosityLevelStr(level); +} + +std::string VerbosityLevelSwig() +{ + return VerbosityLevelStr(); +} } diff --git a/src/Basics/libSALOMELog.cxx b/src/Basics/libSALOMELog.cxx index b1d1332e6..4491791e4 100644 --- a/src/Basics/libSALOMELog.cxx +++ b/src/Basics/libSALOMELog.cxx @@ -26,6 +26,7 @@ #include #include +#include enum class VerbosityMode { undefined, nolog, withlog }; @@ -33,6 +34,64 @@ static VerbosityMode isActivated = VerbosityMode::undefined; namespace SALOME { + static constexpr char ERROR_LEVEL_VALUE = 0; + static constexpr char ERROR_LEVEL_VALUE_STR[] = "ERROR"; + static constexpr char WARNING_LEVEL_VALUE = 1; + static constexpr char WARNING_LEVEL_VALUE_STR[] = "wARNING"; + static constexpr char INFO_LEVEL_VALUE = 2; + static constexpr char INFO_LEVEL_VALUE_STR[] = "INFO"; + static constexpr char DEBUG_LEVEL_VALUE = 7; + static constexpr char DEBUG_LEVEL_VALUE_STR[] = "DEBUG"; + static constexpr char UNDEFINED_LEVEL_VALUE=99; + + enum class VerbosityLevelType { error_level=ERROR_LEVEL_VALUE, warning_level=WARNING_LEVEL_VALUE, info_level=INFO_LEVEL_VALUE, debug_level=DEBUG_LEVEL_VALUE, undefined_level=UNDEFINED_LEVEL_VALUE }; + static VerbosityLevelType verbosityLevel = VerbosityLevelType::undefined_level; + + static VerbosityLevelType FromIntToVerbosityLevel(char value) + { + switch(value) + { + case ERROR_LEVEL_VALUE: + return VerbosityLevelType::error_level; + case WARNING_LEVEL_VALUE: + return VerbosityLevelType::warning_level; + case INFO_LEVEL_VALUE: + return VerbosityLevelType::info_level; + case DEBUG_LEVEL_VALUE: + return VerbosityLevelType::debug_level; + } + throw std::range_error("FromIntToVerbosityLevel : Invalid value for verbosity level !"); + } + + static VerbosityLevelType FromStrToVerbosityLevel(const std::string& val) + { + if(val == ERROR_LEVEL_VALUE_STR) + return VerbosityLevelType::error_level; + if(val == WARNING_LEVEL_VALUE_STR) + return VerbosityLevelType::warning_level; + if(val == INFO_LEVEL_VALUE_STR) + return VerbosityLevelType::info_level; + if(val == DEBUG_LEVEL_VALUE_STR) + return VerbosityLevelType::debug_level; + throw std::range_error("FromStrToVerbosityLevel : Invalid str value for verbosity level !"); + } + + static std::string FromVerbosityLevelToStr(VerbosityLevelType level) + { + switch(level) + { + case VerbosityLevelType::error_level: + return std::string(ERROR_LEVEL_VALUE_STR); + case VerbosityLevelType::warning_level: + return std::string(WARNING_LEVEL_VALUE_STR); + case VerbosityLevelType::info_level: + return std::string(INFO_LEVEL_VALUE_STR); + case VerbosityLevelType::debug_level: + return std::string(DEBUG_LEVEL_VALUE_STR); + default: + throw std::range_error("FromVerbosityLevelToStr : not managed verbosity level !"); + } + } // ============================================================================ /*! @@ -49,19 +108,12 @@ namespace SALOME { auto isEnvVarSet = []() -> VerbosityMode { - const char* envVar = std::getenv("SALOME_VERBOSE"); + const char *envVar = std::getenv("SALOME_VERBOSE"); if (envVar && (envVar[0] != '\0')) { - try - { - const long long numValue = std::stoll(envVar); - return numValue > 0?VerbosityMode::withlog:VerbosityMode::nolog; - } - catch(const std::exception& e) - { - std::cerr << e.what() << '\n'; - } + const int numValue = std::stoi(envVar); + return numValue > 0?VerbosityMode::withlog:VerbosityMode::nolog; } return VerbosityMode::nolog; @@ -76,4 +128,36 @@ namespace SALOME { isActivated = flag ? VerbosityMode::withlog:VerbosityMode::nolog; } + + VerbosityLevelType VerbosityLevel() + { + auto isEnvVarSet = []() -> VerbosityLevelType + { + const char *envVar = std::getenv("SALOME_VERBOSE_LEVEL"); + if (envVar && (envVar[0] != '\0')) + { + const int numValue = std::stoi(envVar); + return FromIntToVerbosityLevel( static_cast(numValue) ); + } + return VerbosityLevelType::info_level; + }; + if(verbosityLevel == VerbosityLevelType::undefined_level) + verbosityLevel = isEnvVarSet(); + return verbosityLevel; + } + + void BASICS_EXPORT SetVerbosityLevel(VerbosityLevelType level) + { + verbosityLevel = level; + } + + void SetVerbosityLevelStr(const std::string& level) + { + verbosityLevel = FromStrToVerbosityLevel(level); + } + + std::string VerbosityLevelStr() + { + return FromVerbosityLevelToStr( VerbosityLevel() ); + } } diff --git a/src/Basics/libSALOMELog.hxx b/src/Basics/libSALOMELog.hxx index 7d4b70611..df2716ea9 100644 --- a/src/Basics/libSALOMELog.hxx +++ b/src/Basics/libSALOMELog.hxx @@ -26,8 +26,17 @@ #include "SALOME_Basics.hxx" +#include + namespace SALOME { + enum class VerbosityLevelType; + bool BASICS_EXPORT VerbosityActivated(); void BASICS_EXPORT SetVerbosityActivated(bool); + + void BASICS_EXPORT SetVerbosityLevel(VerbosityLevelType level); + void BASICS_EXPORT SetVerbosityLevelStr(const std::string& level); + VerbosityLevelType BASICS_EXPORT VerbosityLevel(); + std::string BASICS_EXPORT VerbosityLevelStr(); } diff --git a/src/Container/Container_i.cxx b/src/Container/Container_i.cxx index d43b269b8..429efb8b9 100644 --- a/src/Container/Container_i.cxx +++ b/src/Container/Container_i.cxx @@ -326,14 +326,20 @@ void Abstract_Engines_Container_i::locallogfilename(const char *name) _localfilename = name; } -void Abstract_Engines_Container_i::verboselevel(CORBA::Long vl) +void Abstract_Engines_Container_i::verbosity(bool& activated, CORBA::String_out level) { - SALOME::SetVerbosityActivated( vl ); - if( SALOME::VerbosityActivated() ) + activated = SALOME::VerbosityActivated(); + level = CORBA::string_dup( SALOME::VerbosityLevelStr().c_str() ); +} + +void Abstract_Engines_Container_i::setVerbosity(bool activated, const char *level) +{ + SALOME::SetVerbosityActivated( activated ); + SALOME::SetVerbosityLevelStr( level ); { AutoGIL gstate; PyObject *res = PyObject_CallMethod(_pyCont, - (char*)"propageVerbosityToLogging",NULL); + (char*)"positionVerbosityOfLogger",NULL); if(res==NULL) { //internal error @@ -346,11 +352,6 @@ void Abstract_Engines_Container_i::verboselevel(CORBA::Long vl) } } -CORBA::Long Abstract_Engines_Container_i::verboselevel() -{ - return (CORBA::Long)SALOME::VerbosityActivated(); -} - //============================================================================= //! Get container host name /*! diff --git a/src/Container/SALOME_Container.py b/src/Container/SALOME_Container.py index 14dff9176..8203c6b57 100644 --- a/src/Container/SALOME_Container.py +++ b/src/Container/SALOME_Container.py @@ -156,7 +156,7 @@ class SALOME_Container_i: l=traceback.format_exception(exc_typ,exc_val,exc_fr) return 1,"".join(l) - def propageVerbosityToLogging(self): + def positionVerbosityOfLogger(self): if VerbosityActivated(): - import runSalomeCommon - runSalomeCommon.positionVerbosityOfLogger() + import salome_utils + salome_utils.positionVerbosityOfLoggerRegardingState() diff --git a/src/Container/SALOME_ContainerManager.cxx b/src/Container/SALOME_ContainerManager.cxx index 964e7d186..40dbb2011 100644 --- a/src/Container/SALOME_ContainerManager.cxx +++ b/src/Container/SALOME_ContainerManager.cxx @@ -505,7 +505,7 @@ Engines::Container_ptr SALOME_ContainerManager::GiveContainer(const Engines::Con cont->override_environment_python( envCorba ); if( !_code_to_exe_on_startup.empty() ) cont->execute_python_code( _code_to_exe_on_startup.c_str() ); - cont->verboselevel( SALOME::VerbosityActivated()? 1 : 0 ); + cont->setVerbosity( SALOME::VerbosityActivated(), SALOME::VerbosityLevelStr().c_str() ); return cont._retn(); } else diff --git a/src/Container/SALOME_Container_i.hxx b/src/Container/SALOME_Container_i.hxx index 900ba01ce..94f427996 100644 --- a/src/Container/SALOME_Container_i.hxx +++ b/src/Container/SALOME_Container_i.hxx @@ -119,8 +119,8 @@ public: void logfilename(const char *name) override; char *locallogfilename() override; void locallogfilename(const char *name) override; - void verboselevel(CORBA::Long vl) override; - CORBA::Long verboselevel() override; + void verbosity(bool& activated, CORBA::String_out level) override; + void setVerbosity(bool activated, const char *level) override; virtual void Shutdown(); char *getHostName(); diff --git a/src/Container/SALOME_PyNode.py b/src/Container/SALOME_PyNode.py index eea4f4f0c..5c58e38e2 100644 --- a/src/Container/SALOME_PyNode.py +++ b/src/Container/SALOME_PyNode.py @@ -29,7 +29,6 @@ import pickle import Engines__POA import SALOME__POA import SALOME -from KernelBasis import VerbosityActivated MY_CONTAINER_ENTRY_IN_GLBS = "my_container" -- 2.39.2