Line data Source code
1 : /*
2 : * Copyright (c) 2010-2015: G-CSC, Goethe University Frankfurt
3 : * Authors: Andreas Vogel, Sebastian Reiter
4 : *
5 : * This file is part of UG4.
6 : *
7 : * UG4 is free software: you can redistribute it and/or modify it under the
8 : * terms of the GNU Lesser General Public License version 3 (as published by the
9 : * Free Software Foundation) with the following additional attribution
10 : * requirements (according to LGPL/GPL v3 §7):
11 : *
12 : * (1) The following notice must be displayed in the Appropriate Legal Notices
13 : * of covered and combined works: "Based on UG4 (www.ug4.org/license)".
14 : *
15 : * (2) The following notice must be displayed at a prominent place in the
16 : * terminal output of covered works: "Based on UG4 (www.ug4.org/license)".
17 : *
18 : * (3) The following bibliography is recommended for citation and must be
19 : * preserved in all covered files:
20 : * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively
21 : * parallel geometric multigrid solver on hierarchically distributed grids.
22 : * Computing and visualization in science 16, 4 (2013), 151-164"
23 : * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel
24 : * flexible software system for simulating pde based models on high performance
25 : * computers. Computing and visualization in science 16, 4 (2013), 165-179"
26 : *
27 : * This program is distributed in the hope that it will be useful,
28 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
29 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 : * GNU Lesser General Public License for more details.
31 : */
32 :
33 : #ifndef __H__UG__COMMON__LOG__
34 : #define __H__UG__COMMON__LOG__
35 :
36 : #include <iostream>
37 : #include <fstream>
38 : #include <string>
39 : #include <sstream>
40 : #include "util/ostream_buffer_splitter.h"
41 : #include "types.h"
42 : #include "ug_config.h"
43 :
44 : #include <vector>
45 : #include <map>
46 : #include "common/util/crc32.h"
47 : #include "debug_id.h"
48 :
49 :
50 : // in order to support VRL logs, we're including bindings_vrl.h
51 : // this is necessary to get access to the JVM environment
52 : #ifdef UG_FOR_VRL
53 : #include <sstream>
54 : #include "bindings/vrl/messaging.h"
55 : #endif
56 :
57 : namespace ug{
58 :
59 : /// \addtogroup ugbase_common
60 : /// \{
61 :
62 : const uint64 UNIT_KILO = 1024; // 2^{10}
63 : const uint64 UNIT_MEGA = UNIT_KILO * 1024; // 2^{20} = 1'048'576
64 : const uint64 UNIT_GIGA = UNIT_MEGA * 1024; // 2^{30} = 1'073'741'824
65 : const uint64 UNIT_TERA = UNIT_GIGA * 1024ll; // 2^{40} = 1'099'511'627'776
66 : const uint64 UNIT_PETA = UNIT_TERA * 1024ll; // 2^{50} = 1'125'899'906'842'624
67 : const uint64 UNIT_EXA = UNIT_PETA * 1024ll; // 2^{60} = 1'152'921'504'606'846'976
68 : //const uint64_t UNIT_ZETTA = UNIT_EXA * 1024ll; // 2^{70} -- too big for 64 bit 'long long int'!
69 :
70 : const uint64 UNIT_KILO_SI = 1000; // 10^{ 3}
71 : const uint64 UNIT_MEGA_SI = UNIT_KILO_SI * 1000; // 10^{ 6}
72 : const uint64 UNIT_GIGA_SI = UNIT_MEGA_SI * 1000; // 10^{ 9}
73 : const uint64 UNIT_TERA_SI = UNIT_GIGA_SI * 1000ll; // 10^{12}
74 : const uint64 UNIT_PETA_SI = UNIT_TERA_SI * 1000ll; // 10^{15}
75 : const uint64 UNIT_EXA_SI = UNIT_PETA_SI * 1000ll; // 10^{18}
76 : //const uint64_t UNIT_ZETTA_SI = UNIT_EXA_SI * 1000ll;// 10^{21} -- too big for 64 bit 'long long int'!
77 :
78 :
79 :
80 : // LogAssistant
81 : /**
82 : * This class provides infrastructure for logging. It separates the log messages
83 : * in different levels:
84 : *
85 : * logger() returns the output stream for normal User information output.
86 : * debug_logger() returns the output stream for debug informations.
87 : *
88 : * Debug messages are grouped by tags and debug levels. It is intended, that
89 : * only messages are printed, when the current level is equal or greater than
90 : * the debug level chosen in the code.
91 : *
92 : * Please note that this class operates on std::clog. Thus, if output-options
93 : * are changed (e.g. file-logging enabled) the stream buffer on which clog
94 : * operates will change too.
95 : */
96 : class UG_API LogAssistant
97 : {
98 : public:
99 : /// returns a reference to the single instance of LogAssistant
100 : static LogAssistant& instance();
101 :
102 : /// flushes all buffers before deletion
103 : ~LogAssistant();
104 :
105 : /// enables or disables file output.
106 : /** a filename can be specified. Default is 'uglog.log'.
107 : * Please note that only the filename given at the first call is considered.
108 : * Filelogging is disabled by default.
109 : */
110 : bool enable_file_output(bool bEnable, const char* filename = "uglog.log");
111 :
112 : /// renames output file if opened.
113 : bool rename_log_file(const char * newname);
114 :
115 : /// enables or disables terminal output.
116 : /** terminal output is enbled by default.*/
117 : bool enable_terminal_output(bool bEnable);
118 :
119 : /// returns the debug output stream
120 : inline std::ostream& debug_logger();
121 :
122 : /// returns the normal output stream
123 : inline std::ostream& logger();
124 :
125 : /// returns the error output stream
126 : /** Note that error-logs are not immediately visible. Instead they are
127 : * gathered and can be printed in one block using LogAssistant::flush_error_log().*/
128 : inline std::ostream& error_logger();
129 :
130 : /// outputs all gathered error-logs to the standard logger and clears the error log.
131 : void flush_error_log();
132 :
133 : /// sets the debug level of all tags to 'lev'
134 0 : bool set_debug_levels(int lev)
135 : {
136 1 : return GetDebugIDManager().set_debug_levels(lev);
137 : }
138 :
139 : /// returns the debug level of debugID
140 : inline int get_debug_level(DebugID &debugID) const
141 : {
142 : return GetDebugIDManager().get_debug_level(debugID);
143 : }
144 : /// returns the debug level of debugID
145 : inline int get_debug_level(const char *debugID) const
146 : {
147 : return GetDebugIDManager().get_debug_level(debugID);
148 : }
149 : /// returns the debug level of debugID
150 : int get_debug_level_noninline(const char *debugID) const;
151 :
152 :
153 : /// sets the debug level of debugID
154 : inline bool set_debug_level(DebugID &debugID, int level)
155 : {
156 : return GetDebugIDManager().set_debug_level(debugID, level);
157 : }
158 :
159 : /// returns the debug level of debugID
160 : inline bool set_debug_level(const char* debugID, int level)
161 : {
162 0 : return GetDebugIDManager().set_debug_level(debugID, level);
163 : }
164 :
165 : bool set_debug_level_noninline(const char* debugID, int level);
166 :
167 : /// returns the debug level of debugID
168 0 : inline std::string get_registered_debug_IDs()
169 : {
170 0 : return GetDebugIDManager().get_registered_debug_IDs();
171 : }
172 :
173 : /// sets the output-process in a parallel environment. Default is 0.
174 : /** pass a procRank of -1 to enable output on all processes.*/
175 : void set_output_process(int procRank);
176 :
177 : /// returns the rank of the current output-process or -1 if all procs perform output.
178 : inline int get_output_process();
179 :
180 : /// returns true if the current process is an output process.
181 : /** This is always true, if the application is executed in a serial environment.*/
182 : bool is_output_process();
183 :
184 : /// returns the process rank of the underlying process (same as pcl::ProcRank)
185 : int get_process_rank();
186 :
187 : void flush();
188 :
189 : protected:
190 : /// updates and sets stream buffers based on current options.
191 : /** Note that this method changes the buffer on which clog works.*/
192 : void update_ostream();
193 :
194 : /// opens the local logFile, if the process is the output-process
195 : bool open_logfile();
196 :
197 : private:
198 : /// Constructor, resets all debug levels to -1
199 : /** Constructor is private since only one instance of LogAssistant may exist.*/
200 : LogAssistant();
201 :
202 : /// Prevent copying through private copy constructor.
203 : LogAssistant(const LogAssistant&);
204 :
205 : /// Performs some initialization
206 : void init();
207 : private:
208 : // streams
209 : std::streambuf* m_emptyBuf;
210 : std::streambuf* m_logBuf;
211 : std::streambuf* m_fileBuf;
212 : std::streambuf* m_splitBuf;
213 :
214 : EmptyStreamBuffer m_emptyBufInst;
215 : OStreamBufferSplitter m_splitBufInst;
216 :
217 : std::string m_logFileName;
218 : std::ofstream m_fileStream;
219 : std::stringstream m_errStream;
220 :
221 : bool m_terminalOutputEnabled;
222 : bool m_fileOutputEnabled;
223 :
224 : int m_outputProc;
225 :
226 : };
227 :
228 : // returns singleton instance of LogAssistant
229 : inline LogAssistant& GetLogAssistant();
230 :
231 : /// returns number 'size' in a more human readable format (using IEC binary prefixes)
232 : inline std::string ConvertNumber (uint64_t size, unsigned int width,
233 : unsigned int numDisplayedDigits);
234 :
235 : /// returns number 'size' in a more human readable format (using SI prefixes)
236 : inline std::string ConvertNumberSI (uint64_t size, unsigned int width,
237 : unsigned int numDisplayedDigits);
238 :
239 : // end group ugbase_common
240 : /// \}
241 :
242 : } // end namespace ug
243 :
244 :
245 : ////////////////////////////////////////////////////////////////////////////////
246 : ////////////////////////////////////////////////////////////////////////////////
247 : // DEBUG LOG
248 : ////////////////////////////////////////////////////////////////////////////////
249 : ////////////////////////////////////////////////////////////////////////////////
250 :
251 :
252 : /// \addtogroup ugbase_common
253 : /// \{
254 :
255 : // Usage:
256 : /* The following macros can be used to control debug messages.
257 : * To use them the define 'UG_ENABLE_DEBUG_LOGS' must be set. Otherwise nothing will be done (no runtime overhead).
258 : *
259 : * UG_SET_DEBUG_LEVEL(__debugID__, level) - sets the debug levels of DebugID __debugID__ to level 'level'
260 : * UG_RESET_DEBUG_LEVELS() - sets the debug level of all Tags to -1
261 : * UG_SET_DEBUG_LEVELS(level) - sets the debug levels of all DebugIDs to level 'level'
262 : * UG_DLOG(__debugID__, level, msg) - prints the message "msg" to the debug log stream, if current level of DebugID __debugID__ is >= level
263 : *
264 : * __debugID__ has to be of type DebugID.
265 : * For a list of standard DebugIDs and how to define your own, see debug_id.h .
266 : *
267 : * Example:
268 : *
269 : UG_RESET_DEBUG_LEVELS();
270 : UG_DLOG(MAIN, 0, "DLOG on level 0.\n"); // no message printed
271 : UG_SET_DEBUG_LEVEL(MAIN, 0);
272 : UG_DLOG(MAIN, 0, "DLOG on level 0.\n"); // message printed
273 : UG_DLOG(MAIN, 1, "DLOG on level 1.\n"); // no message printed
274 : */
275 : #ifdef UG_ENABLE_DEBUG_LOGS
276 : #define UG_SET_DEBUG_LEVEL(__debugID__, level) {ug::GetDebugIDManager().set_debug_level(__debugID__, level);}
277 : #define UG_RESET_DEBUG_LEVELS() {ug::GetDebugIDManager().set_debug_levels(-1);}
278 : #define UG_SET_DEBUG_LEVELS(level) {ug::GetDebugIDManager().set_debug_levels(level);}
279 : #define UG_DEBUG_BEGIN(__debugID__, level) { if(ug::GetDebugIDManager().get_debug_level(__debugID__) >= level) {
280 : #define UG_DEBUG_END(__debugID__, level) }; }
281 : #define IF_DEBUG(__debugID__, level) if(ug::GetDebugIDManager().get_debug_level(__debugID__) >= level)
282 :
283 : #define UG_DLOG(__debugID__, level, msg) \
284 : {if(ug::GetDebugIDManager().get_debug_level(__debugID__) >= level)\
285 : {ug::GetLogAssistant().debug_logger() << msg; ug::GetLogAssistant().debug_logger().flush();}}
286 :
287 : #define UG_DLOGN(__debugID__, level, msg) UG_DLOG(__debugID__, level, msg << "\n");
288 :
289 : #define UG_DLOG_ALL_PROCS(__debugID__, level, msg) \
290 : {if(ug::GetDebugIDManager().get_debug_level(__debugID__) >= level)\
291 : {ug::LogAssistant& la = ug::GetLogAssistant(); int op = la.get_output_process();\
292 : la.set_output_process(-1); la.debug_logger() << "[Proc " << la.get_process_rank() << "]: "\
293 : << msg << std::flush; la.set_output_process(op);}}
294 : #else
295 : #define UG_SET_DEBUG_LEVEL(__debugID__, level) {}
296 : #define UG_RESET_DEBUG_LEVELS() {}
297 : #define UG_SET_DEBUG_LEVELS(level) {}
298 : #define UG_DLOG(__debugID__, level, msg) {}
299 : #define UG_DLOGN(__debugID__, level, msg) {}
300 : #define UG_DLOG_ALL_PROCS(__debugID__, level, msg) {}
301 : #define UG_DEBUG_BEGIN(__debugID__, level) { if(1==0) {
302 : #define UG_DEBUG_END(__debugID__, level) }; }
303 : #define IF_DEBUG(__debugID__, level) if(1==0)
304 : #endif
305 :
306 : ////////////////////////////////////////////////////////////////////////////////
307 : ////////////////////////////////////////////////////////////////////////////////
308 : // WARNING LOG
309 : ////////////////////////////////////////////////////////////////////////////////
310 : ////////////////////////////////////////////////////////////////////////////////
311 :
312 : // Warning and debug logs are disabled when compiling for release
313 : // defines (currently here, should be compiling options)
314 : #ifndef NDEBUG
315 : #define UG_ENABLE_WARNINGS
316 : #else /* NDEBUG */
317 : #undef UG_ENABLE_WARNINGS
318 : #endif /* NDEBUG*/
319 :
320 : // Usage:
321 : /* The following macro can be used to print warning messages.
322 : * To use it the define 'UG_ENABLE_WARNINGS' must be set. Otherwise nothing will
323 : * be done (no runtime overhead).
324 : *
325 : * UG_WARNING(msg) - prints a warning to the normal output stream
326 : */
327 : #ifdef UG_ENABLE_WARNINGS
328 : #define UG_WARNING(msg) {ug::GetLogAssistant().logger() << "UG_WARNING in "\
329 : << __FILE__ << " at line " << __LINE__ << ": " \
330 : << msg << std::flush;}
331 : #else
332 : #define UG_WARNING(msg) {}
333 : #endif
334 :
335 :
336 : // Usage:
337 : /* The following macro can be used to print warning messages if condition is met.
338 : * To use it the define 'UG_ENABLE_WARNINGS' must be set. Otherwise nothing will
339 : * be done (no runtime overhead).
340 : *
341 : * UG_WARNING(cond, msg) - prints a warning to the normal output stream
342 : */
343 : #ifdef UG_ENABLE_WARNINGS
344 : #define UG_COND_WARNING(cond, msg) { if (cond) {ug::GetLogAssistant().logger() << "UG_WARNING in "\
345 : << __FILE__ << " at line " << __LINE__ << ": " \
346 : << msg << std::flush;} }
347 : #else
348 : #define UG_COND_WARNING(cond, msg) {}
349 : #endif
350 :
351 :
352 :
353 :
354 :
355 : ////////////////////////////////////////////////////////////////////////////////
356 : // LOG
357 : /**
358 : * UG_LOG(msg) - prints a message to the normal output stream
359 : */
360 : #ifdef UG_FOR_VRL
361 : #define VRL_LOG(msg) {std::stringstream __ss; __ss << "" << msg;\
362 : ug::vrl::MessageBuffer::addMessage(__ss.str());}
363 : #else
364 : #define VRL_LOG(msg)
365 : #endif
366 :
367 : #define UG_LOG(msg) {ug::GetLogAssistant().logger() << msg << std::flush; VRL_LOG(msg);}
368 : #define UG_COND_LOG(cond, msg) { if (cond) { UG_LOG(msg); } }
369 : #define UG_LOGN(msg) UG_LOG(msg << "\n")
370 : #define UG_COND_LOGN(cond, msg) { if (cond) { UG_LOGN(msg); } }
371 : #define UG_LOG_ALL_PROCS(msg) {ug::LogAssistant& la = ug::GetLogAssistant();\
372 : int op = la.get_output_process(); la.set_output_process(-1);\
373 : la.logger() << "[Proc " << std::setw(3) << la.get_process_rank() << "]: "\
374 : << msg << std::flush; VRL_LOG(msg); la.set_output_process(op);}
375 :
376 : ////////////////////////////////////////////////////////////////////////////////
377 : // LOG
378 : /**
379 : * UG_ERR_LOG(msg) prints msg to LogAssistant::error_logger().
380 : * Those messages are not immediately flushed. Instead they can
381 : * be flushed to the standard logger using LogAssistant::flush_error_log
382 : */
383 : #define UG_ERR_LOG(msg) {ug::GetLogAssistant().error_logger() << msg; VRL_LOG(msg);}
384 :
385 : // include implementation
386 : #include "log_impl.h"
387 :
388 : // end group ugbase_common
389 : /// \}
390 :
391 : #endif /* __H__UG__COMMON__LOG__ */
|