1 //                                               -*- C++ -*-
2 /**
3  *  @brief Log records all user information to a file or tty
4  *
5  *  Copyright 2005-2021 Airbus-EDF-IMACS-ONERA-Phimeca
6  *
7  *  This library is free software: you can redistribute it and/or modify
8  *  it under the terms of the GNU Lesser General Public License as published by
9  *  the Free Software Foundation, either version 3 of the License, or
10  *  (at your option) any later version.
11  *
12  *  This library is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU Lesser General Public License for more details.
16  *
17  *  You should have received a copy of the GNU Lesser General Public License
18  *  along with this library.  If not, see <http://www.gnu.org/licenses/>.
19  *
20  */
21 #ifndef OPENTURNS_LOG_HXX
22 #define OPENTURNS_LOG_HXX
23 
24 #include <fstream>
25 #include <map>
26 #include "openturns/OTprivate.hxx"
27 #include "openturns/AtomicInt.hxx"
28 #include "openturns/TTY.hxx"
29 #include "openturns/MutexLock.hxx"
30 
31 
32 #define LOGDEBUG(st)   do { if (OT::Log::HasDebug()  ) OT::Log::Debug(st);   } while(0)
33 #define LOGINFO(st)    do { if (OT::Log::HasInfo()   ) OT::Log::Info(st);    } while(0)
34 #define LOGUSER(st)    do { if (OT::Log::HasUser()   ) OT::Log::User(st);    } while(0)
35 #define LOGWARN(st)    do { if (OT::Log::HasWarn()   ) OT::Log::Warn(st);    } while(0)
36 #define LOGERROR(st)   do { if (OT::Log::HasError()  ) OT::Log::Error(st);   } while(0)
37 #define LOGTRACE(st)   do { if (OT::Log::HasTrace()  ) OT::Log::Trace(st);   } while(0)
38 
39 
40 BEGIN_NAMESPACE_OPENTURNS
41 
42 
43 
44 #ifndef SWIG
45 struct _Prefix
46 {
47   typedef String Value;
48   Value color_, nocolor_, prefix_;
_Prefix_Prefix49   _Prefix() : color_(), nocolor_(), prefix_() {}
_Prefix_Prefix50   _Prefix( const Value & color, const Value & nocolor, const Value & prefix) : color_(color), nocolor_(nocolor), prefix_(prefix) {}
51 };
52 
53 std::ostream & operator << ( std::ostream & os, const _Prefix & pfx );
54 
55 #endif
56 
57 /**
58  * @class log
59  * @brief Records all user information to a file or tty
60  * @internal
61  */
62 
63 class OT_API Log
64 {
65 public:
66 
67   typedef unsigned long Severity;
68 
69 private:
70 #ifndef SWIG
71   /** GetInstance gives a locked access to the singleton */
72   static MutexLockSingleton<Log> GetInstance();
73 #endif
74 
75 public:
76   /** Those flags should be ORed */
77   static const Severity DBG;
78   static const Severity INFO;
79   static const Severity USER;
80   static const Severity WARN;
81   static const Severity ERROR;
82   static const Severity TRACE;
83 
84   static const Severity DEFAULT;
85   static const Severity NONE;
86   static const Severity ALL;
87 
88 #ifndef SWIG
89   /** Change the Log */
90   static void Reset();
91 #endif
92 
93   /** Log messages according to the DBG level
94    * @param msg The message to be logged
95    */
96   static void Debug(const String & msg);
HasDebug()97   static inline Bool HasDebug()
98   {
99     return 0 != (Flags() & Log::DBG);
100   }
101 
102   /** Log messages according to the INFO level
103    * @param msg The message to be logged
104    */
105   static void Info(const String & msg);
HasInfo()106   static inline Bool HasInfo()
107   {
108     return 0 != (Flags() & Log::INFO);
109   }
110 
111   /** Log messages according to the USER level
112    * @param msg The message to be logged
113    */
114   static void User(const String & msg);
HasUser()115   static inline Bool HasUser()
116   {
117     return 0 != (Flags() & Log::USER);
118   }
119 
120   /** Log messages according to the WARN level
121    * @param msg The message to be logged
122    */
123   static void Warn(const String & msg);
HasWarn()124   static inline Bool HasWarn()
125   {
126     return 0 != (Flags() & Log::WARN);
127   }
128 
129   /** Log messages according to the ERROR level
130    * @param msg The message to be logged
131    */
132   static void Error(const String & msg);
HasError()133   static inline Bool HasError()
134   {
135     return 0 != (Flags() & Log::ERROR);
136   }
137 
138   /** Log messages according to the TRACE level
139    * @param msg The message to be logged
140    */
141   static void Trace(const String & msg);
HasTrace()142   static inline Bool HasTrace()
143   {
144     return 0 != (Flags() & Log::TRACE);
145   }
146 
147   /** Divert the output to a file
148    * @param file The filename where the log will be written
149    */
150   static void SetFile(const FileName & file);
151 
152   /** Set the level flags for the messages logged to the file
153    * @param flags An integer built from ORed level flags
154    */
155   static void Show(Severity flags);
156 
157   /** Get the current level flags
158    * @return An integer built from ORed level flags
159    */
160   static Severity Flags();
161 
162   /** Flush pending messages
163    * @internal
164    */
165   static void Flush();
166 
167   /** Does Log show repeated messages or not
168    *  If repeat is false then Log shows every messages it receives
169    *  even if they are identical to the previous ones.
170    *  If repeat is true then Log only shows the first message
171    *  and a message counting how much identical messages were
172    *  received after that.
173    */
174   static void Repeat( Bool repeat );
175 
176   /** Color  accessors. */
177   static void SetColor(const Log::Severity severity,
178                        const TTY::Color color);
179   static void SetColor(const Log::Severity severity,
180                        const String & color);
181   static String GetColor(const Log::Severity severity);
182 
183 #ifndef SWIG
184   struct OT_API Entry
185   {
186     Severity sev_;
187     String msg_;
EntryLog::Entry188     Entry(Severity sev, String msg) : sev_(sev), msg_(msg) {}
EntryLog::Entry189     Entry() : sev_(0), msg_() {}
operator ==Log::Entry190     Bool operator== (const Entry & other) const
191     {
192       return (this->sev_ == other.sev_) && (this->msg_ == other.msg_);
193     }
194   }; /* end struct Entry */
195 #endif
196   ~Log();
197 
198 private:
199   Log();
200   void push(const Entry & entry);
201   void printRepeatedMessage(const Entry & entry);
202   void flush();
203   void repeat( Bool r );
204   void setColor(const Log::Severity severity,
205                 const String & color);
206   String getColor(const Log::Severity severity) const;
207 
208   /** Set the name of the log file */
209   void setFile(const FileName & file);
210 
211   /** Human readable log */
212   mutable std::map<Severity, _Prefix > logName_;
213 
214   /** The environment variable name */
215   const char * openturnsLogSeverityVariableName_;
216 
217   /** Set Severity according to Openturns LogSeverity Variable */
218   void initSeverityFromEnvironment();
219 
220   /** The file where to write messages */
221   std::ostream * p_file_;
222 
223   /** Remember the previous message */
224   mutable Entry previousMessage_;
225   mutable UnsignedInteger count_;
226   mutable AtomicInt repeat_;
227 
228   friend struct Log_init; /* friendship for static member initialization */
229 }; /* end class Log */
230 
231 
232 
233 /** This struct initializes all static members of Log */
234 struct OT_API Log_init
235 {
236   Log_init();
237   ~Log_init();
238 }; /* end struct Log_init */
239 
240 
241 END_NAMESPACE_OPENTURNS
242 
243 #endif /* OPENTURNS_LOG_HXX */
244