Salome HOME
[EDF29852] : Mecanism of fault tolerant in SALOME_Container to resist against emitted...
[modules/kernel.git] / src / Basics / libSALOMELog.cxx
1 // Copyright (C) 2007-2024  CEA, EDF, OPEN CASCADE
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 //  Author : Konstantin Leontev (OpenCascade)
21 //  Module : KERNEL
22 //  $Header$
23 //
24
25 #include "libSALOMELog.hxx"
26
27 #include <string>
28 #include <iostream>
29 #include <stdexcept>
30
31 #include <chrono>
32 #include <iomanip>
33 #include <ctime>
34
35 enum class VerbosityMode { undefined, nolog, withlog };
36
37 static VerbosityMode isActivated = VerbosityMode::undefined;
38
39 namespace SALOME
40 {
41   static constexpr char ERROR_LEVEL_VALUE = 0;
42   static constexpr char ERROR_LEVEL_VALUE_STR[] = "ERROR";
43   static constexpr char WARNING_LEVEL_VALUE = 1;
44   static constexpr char WARNING_LEVEL_VALUE_STR[] = "WARNING";
45   static constexpr char INFO_LEVEL_VALUE = 2;
46   static constexpr char INFO_LEVEL_VALUE_STR[] = "INFO";
47   static constexpr char DEBUG_LEVEL_VALUE = 7;
48   static constexpr char DEBUG_LEVEL_VALUE_STR[] = "DEBUG";
49   static constexpr char UNDEFINED_LEVEL_VALUE=99;
50
51   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 };
52   static VerbosityLevelType verbosityLevel = VerbosityLevelType::undefined_level;
53
54   static VerbosityLevelType FromIntToVerbosityLevel(char value)
55   {
56     switch(value)
57     {
58       case ERROR_LEVEL_VALUE:
59         return VerbosityLevelType::error_level;
60       case WARNING_LEVEL_VALUE:
61         return VerbosityLevelType::warning_level;
62       case INFO_LEVEL_VALUE:
63         return VerbosityLevelType::info_level;
64       case DEBUG_LEVEL_VALUE:
65         return VerbosityLevelType::debug_level;
66     }
67     throw std::range_error("FromIntToVerbosityLevel : Invalid value for verbosity level !");
68   }
69
70   static VerbosityLevelType FromStrToVerbosityLevel(const std::string& val)
71   {
72     if(val == ERROR_LEVEL_VALUE_STR)
73       return VerbosityLevelType::error_level;
74     if(val == WARNING_LEVEL_VALUE_STR)
75       return VerbosityLevelType::warning_level;
76     if(val == INFO_LEVEL_VALUE_STR)
77       return VerbosityLevelType::info_level;
78     if(val == DEBUG_LEVEL_VALUE_STR)
79       return VerbosityLevelType::debug_level;
80     throw std::range_error("FromStrToVerbosityLevel : Invalid str value for verbosity level !");
81   }
82
83   static std::string FromVerbosityLevelToStr(VerbosityLevelType level)
84   {
85     switch(level)
86     {
87       case VerbosityLevelType::error_level:
88         return std::string(ERROR_LEVEL_VALUE_STR);
89       case VerbosityLevelType::warning_level:
90         return std::string(WARNING_LEVEL_VALUE_STR);
91       case VerbosityLevelType::info_level:
92         return std::string(INFO_LEVEL_VALUE_STR);
93       case VerbosityLevelType::debug_level:
94         return std::string(DEBUG_LEVEL_VALUE_STR);
95       default:
96         throw std::range_error("FromVerbosityLevelToStr : not managed verbosity level !");
97     }
98   }
99
100 // ============================================================================
101 /*!
102  *  Called by any log message macros to decide about log output in Release and
103  *  Debug mode dynamically rely on SALOME_VERBOSE environment variable.
104  *  Checks SALOME_VERBOSE only on the very first call and returns cached result
105  *  for all followed calls.
106  *  Returns true if SALOME_VERBOSE is positioned and not empty and if its
107  *  numeric value greater than 0.
108  */
109 // ============================================================================
110
111   bool VerbosityActivated()
112   {
113     auto isEnvVarSet = []() -> VerbosityMode
114     {
115       const char *envVar = std::getenv("SALOME_VERBOSE");
116
117       if (envVar && (envVar[0] != '\0'))
118       {
119         const int numValue = std::stoi(envVar);
120         return numValue > 0?VerbosityMode::withlog:VerbosityMode::nolog;
121       }
122
123       return VerbosityMode::nolog;
124     };
125
126     if(isActivated == VerbosityMode::undefined)
127       isActivated = isEnvVarSet();
128     return isActivated == VerbosityMode::withlog;
129   }
130
131   void SetVerbosityActivated(bool flag)
132   {
133     isActivated = flag ? VerbosityMode::withlog:VerbosityMode::nolog;
134   }
135
136   VerbosityLevelType VerbosityLevel()
137   {
138     auto isEnvVarSet = []() -> VerbosityLevelType
139     {
140       const char *envVar = std::getenv("SALOME_VERBOSE_LEVEL");
141       if (envVar && (envVar[0] != '\0'))
142       {
143         const int numValue = std::stoi(envVar);
144         return FromIntToVerbosityLevel( static_cast<char>(numValue) );
145       }
146       return VerbosityLevelType::info_level;
147     };
148     if(verbosityLevel == VerbosityLevelType::undefined_level)
149       verbosityLevel = isEnvVarSet();
150     return verbosityLevel;
151   }
152
153   void SetVerbosityLevel(VerbosityLevelType level)
154   {
155     verbosityLevel = level;
156   }
157
158   void SetVerbosityLevelStr(const std::string& level)
159   {
160     verbosityLevel = FromStrToVerbosityLevel(level);
161   }
162
163   std::vector<std::string> GetAllVerbosityLevelPossibilitiesStr()
164   {
165     return {ERROR_LEVEL_VALUE_STR,WARNING_LEVEL_VALUE_STR,INFO_LEVEL_VALUE_STR,DEBUG_LEVEL_VALUE_STR};
166   }
167
168   std::string VerbosityLevelStr()
169   {
170     return FromVerbosityLevelToStr( VerbosityLevel() );
171   }
172
173   bool IsDebugLevel()
174   {
175     return VerbosityLevel() >= VerbosityLevelType::debug_level;
176   }
177
178   bool IsInfoLevel()
179   {
180     return VerbosityLevel() >= VerbosityLevelType::info_level;
181   }
182
183   bool IsWarningLevel()
184   {
185     return VerbosityLevel() >= VerbosityLevelType::warning_level;
186   }
187
188   bool IsErrorLevel()
189   {
190     return VerbosityLevel() >= VerbosityLevelType::error_level;
191   }
192
193   void AppendTimeClock(std::ostream& os)
194   {
195     auto now = std::chrono::system_clock::now();
196     auto duration = now.time_since_epoch();
197     auto timestamp = std::chrono::system_clock::to_time_t(now);
198     std::tm *local_time = std::localtime(&timestamp);
199     auto millis = std::chrono::duration_cast<std::chrono::milliseconds>(duration).count();
200     os  << std::setfill('0') << std::setw(2) << local_time->tm_hour << ":"
201         << std::setw(2) << local_time->tm_min << ":"
202         << std::setw(2) << local_time->tm_sec << "." << std::setw(3) << millis % 1000 << " - ";
203   }
204 }