Flow123d  master-f44eb46
logger.hh
Go to the documentation of this file.
1 /*!
2  *
3  * Copyright (C) 2015 Technical University of Liberec. All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it under
6  * the terms of the GNU General Public License version 3 as published by the
7  * Free Software Foundation. (http://www.gnu.org/licenses/gpl-3.0.en.html)
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12  *
13  *
14  * @file logger.hh
15  * @brief
16  */
17 
18 #ifndef LOGGER_HH_
19 #define LOGGER_HH_
20 
21 
22 #include <iostream>
23 #include <algorithm> // for forward
24 #include <string> // for string
25 #include <sstream>
26 #include <vector>
27 #include <string>
28 
29 
30 #include "system/fmt/format.h"
31 #include "system/exc_common.hh"
32 
33 
34 
35 /**
36  * @brief Helper class, store mask specifying streams
37  *
38  * Defines masks of all used streams as static methods and allows combining and comparing masks using
39  * the overloaded operators.
40  */
41 class StreamMask {
42 public:
43  /// Empty constructor
45  : mask_(0) {}
46 
47  /// Constructor set \p mask_ value
48  StreamMask(int mask)
49  : mask_(mask) {}
50 
51  /// Predefined mask of std::cout output
52  static StreamMask cout;
53 
54  /// Predefined mask of std::cerr output
55  static StreamMask cerr;
56 
57  /// Predefined mask of log file output
58  static StreamMask log;
59 
60  // Overload & operator
61  StreamMask operator &(const StreamMask &other);
62 
63  // Overload | operator
64  StreamMask operator |(const StreamMask &other);
65 
66  // Overload () operator
67  int operator()(void);
68 
69 private:
70  int mask_;
71 };
72 
73 
74 /**
75  * @brief Class for storing logger messages.
76  *
77  * Allow define different levels of log messages and distinguish output streams
78  * for individual leves. These output streams are -
79  * - standard console output (std::cout)
80  * - standard error output (std::cerr)
81  * - file output (see \p LoggerOptions class)
82  *
83  * Logger distinguishes four type of levels -
84  * - warning: printed to standard error and file output
85  * - message: printed to standard console and file output
86  * - log: printed to file output
87  * - debug: printed to file output (level is used only in debug mode)
88  *
89  * File output is optional. See \p LoggerOptions for setting this output stream.
90  *
91  * <b>Example of Logger usage:</b>
92  *
93  * For individual levels are defined macros -
94  * - MessageOut()
95  * - WarningOut()
96  * - LogOut()
97  * - DebugOut()
98  * that ensure display of actual code point (source file, line and function).
99  *
100  * Logger message is created by using an operator << and allow to add each type
101  * that has override this operator. Message is terminated with manipulator
102  * std::endl. Implicitly logger message is printed only in processor with rank
103  * zero. If necessary printed message for all process, it provides a method
104  * every_proc().
105  *
106  * Examples of logger messages formating:
107  *
108  @code
109  MessageOut() << "End of simulation at time: " << secondary_eq->solved_time() << "\n";
110  WarningOut() << "Unprocessed keys '" << keys_vec << "'." << "\n";
111  LogOut() << "Write output to output stream: " << this->_base_filename << " for time: " << time << "\n";
112  DebugOut() << "Calling 'initialize' of empty equation '" << typeid(*this).name() << "'." << "\n";
113  @endcode
114  *
115  * See that output of vectors of printable objects is supported.
116  * Implementation of Logger does not support manipulator std::endl. Please, use "\n" instead.
117  * New line character "\n" can be used multiple times.
118  *
119  * Logger allow using fmtlib functionality for simpler formatting of message:
120  *
121  @code
122  MessageOut() << fmt::format("Start time: {}\nEnd time: {}\n", this->start_time(), this->end_time());
123  MessageOut().fmt("Start time: {}\nEnd time: {}\n", this->start_time(), this->end_time());
124  @endcode
125  *
126  * Messages are printed only on the zero MPI process by default.
127  * Parallel output on all processes must be required explicitly:
128  *
129  @code
130  MessageOut().every_proc() << "Size distributed at process: " << distr->lsize() << "\n";
131  @endcode
132  *
133  *
134  */
135 class Logger : public std::ostream {
136 public:
137 
138  /**
139  * @brief Enum of types of Logger messages.
140  *
141  * Rules:
142  * 1. Warning and Error are the only messages that goes to CERR.
143  * 2. All messages goes to the log file unless it is suppressed by the _no_log option
144  * if the user provides empty log file name.
145  * 3. If the log file was not initialized YET all LOG output goes to COUT unless it already goes to CERR.
146  * 4. 'message' goes to the COUT if LOG is suppressed.
147  * 5. 'debug' goes to both COUT and LOG, but are suppresed by FLOW123D_DEBUG.
148  *
149  */
150  enum MsgType {
151  warning = 0,
152  message = 1,
153  log = 2,
154  debug = 3,
155  error = 4
156  };
157 
158  /// Return string value of given MsgType in full or shorter format (e.g. "WARNING" of "Wrn")
159  static const std::string msg_type_string(MsgType msg_type, bool full_format = true);
160 
161  /// Constructor.
162  Logger(MsgType type);
163 
164  /// Stores values for printing out line number, function, etc
165  Logger& set_context(const char* file_name, const char* function, const int line);
166 
167  /// Set flag every_process_ to true
168  Logger& every_proc();
169 
170  /**
171  * @brief Allow use functionality of fmtlib for formating message.
172  *
173  * See examples in description of Logger class.
174  */
175  template<class... T>
176  Logger& fmt(T&&... t)
177  {
178  try {
179  return *this << fmt::format(std::forward<T>(t)...);
180  } catch (const fmt::FormatError & e) {
181  THROW(ExcMessage() << EI_Message("FormatError: " + std::string(e.what())));
182  }
183  }
184 
185  /// Destructor.
186  ~Logger();
187 
188 
189 private:
190  /// Set @p streams_mask_ according to the type of message.
191  void set_mask();
192 
193  /// Print formated message to given screen stream if mask corresponds with @p streams_mask_.
194  void print_to_screen(std::ostream& stream, std::stringstream& scr_stream, StreamMask mask);
195 
196  /// Print formated message to given file stream if mask corresponds with @p streams_mask_.
197  void print_to_file(std::ofstream& stream, std::stringstream& file_stream, StreamMask mask);
198 
199  /// Print header to screen stream, helper method called from \p print_to_screen.
200  bool print_screen_header(std::stringstream& scr_stream);
201 
202  /// Print header to file stream, helper method called from \p print_to_file.
203  void print_file_header(std::stringstream& file_stream);
204 
205  /// Return compact (relative) path to the given source file.
206  std::string compact_file_name(std::string file_name);
207 
208  std::stringstream cout_stream_; ///< Store messages printed to cout output stream
209  std::stringstream cerr_stream_; ///< Store messages printed to cerr output stream
210  std::stringstream file_stream_; ///< Store messages printed to file
211 
212  MsgType type_; ///< Type of message.
213  bool every_process_; ///< Flag marked if log message is printing for all processes or only for zero process.
214  std::string file_name_; ///< Actual file.
215  std::string function_; ///< Actual function.
216  int line_; ///< Actual line.
217  std::string date_time_; ///< Actual date and time.
218  int mpi_rank_; ///< Actual process (if MPI is supported)
219  StreamMask streams_mask_; ///< Mask of logger, specifies streams in actual time into which to be written
220  StreamMask full_streams_mask_; ///< Mask of logger, specifies all streams into which to be written in logger message
221 
222  // Generic printing.
223  template <class T>
224  friend Logger &operator<<(Logger & log, const T & x);
225  // Vector printing support.
226  template <class T>
227  friend Logger &operator<<(Logger & log, const std::vector<T> & vec);
228  // Parametric stream modificator (.
229  friend Logger &operator<<(Logger & log, std::ostream & (*pf) (std::ostream &) );
230  // Stream mask modificator.
231  friend Logger &operator<<(Logger & log, StreamMask mask);
232 };
233 
234 
235 Logger &operator<<(Logger & log, StreamMask mask);
236 
237 
238 Logger &operator<<(Logger & log, std::ostream & (*pf) (std::ostream &) );
239 
240 
241 template <class T>
243 {
244  for (T const& c : vec)
245  log << c << " ";
246  return log;
247 }
248 
249 template <class T, long unsigned int N>
250 Logger &operator<<(Logger & log, const std::array<T, N> & vec)
251 {
252  for (T const& c : vec)
253  log << c << " ";
254  return log;
255 }
256 
257 
258 template <class T>
259 Logger &operator<<(Logger & log, const T & x)
260 {
261  if ( (log.streams_mask_ & StreamMask::cout)() ) log.cout_stream_ << x;
262  if ( (log.streams_mask_ & StreamMask::cerr)() ) log.cerr_stream_ << x;
263  if ( (log.streams_mask_ & StreamMask::log )() ) log.file_stream_ << x;
264  return log;
265 }
266 
267 
268 
269 
270 
271 /// Internal macro defining universal record of log
272 #define _LOG(type) \
273  Logger( type ).set_context( __FILE__, __func__, __LINE__)
274 /// Macro defining 'message' record of log
275 #define MessageOut() \
276  _LOG( Logger::MsgType::message )
277 /// Macro defining 'warning' record of log
278 #define WarningOut() \
279  _LOG( Logger::MsgType::warning )
280 /// Macro defining 'log' record of log
281 #define LogOut() \
282  _LOG( Logger::MsgType::log )
283 /// Macro defining 'debug' record of log
284 #define DebugOut() \
285  _LOG( Logger::MsgType::debug )
286 
287 /**
288  * Print variable name and value.
289  * Usage:
290  * DebugOut() << print_var(x) << print_var(y)
291  */
292 #define print_var(var) \
293  std::string(#var) << "=" << (var) << ", "
294 
295 #include <iostream>
296 #include <vector>
297 
298 /**
299  * Manipulator template to print containers.
300  */
301 namespace manipulators
302 {
303  template <typename Cont, typename Delim=const char*>
304  struct Array {
305  Array(Cont const& v, Delim d = ", ") : _v(v), _d(std::move(d)) { }
306 
307  Cont const& _v;
308  Delim _d;
309 
310  friend std::ostream& operator<<(std::ostream& os, Array const& manip) {
311  using namespace std;
312  auto f = begin(manip._v), l(end(manip._v));
313 
314  os << "{ ";
315  while (f != l)
316  if ((os << *f) && (++f != l))
317  os << manip._d;
318  return os << " }";
319  }
320  };
321 
322 }
323 
324 template <typename T, typename Delim=const char*>
325 manipulators::Array<T, Delim> format(T const& deduce, Delim delim = ", ") {
326  return { deduce, std::move(delim) };
327 }
328 
329 
330 #endif /* LOGGER_HH_ */
Class for storing logger messages.
Definition: logger.hh:135
static const std::string msg_type_string(MsgType msg_type, bool full_format=true)
Return string value of given MsgType in full or shorter format (e.g. "WARNING" of "Wrn")
Definition: logger.cc:85
Logger & set_context(const char *file_name, const char *function, const int line)
Stores values for printing out line number, function, etc.
Definition: logger.cc:99
std::stringstream cerr_stream_
Store messages printed to cerr output stream.
Definition: logger.hh:209
friend Logger & operator<<(Logger &log, const T &x)
Definition: logger.hh:259
Logger & every_proc()
Set flag every_process_ to true.
Definition: logger.cc:110
StreamMask streams_mask_
Mask of logger, specifies streams in actual time into which to be written.
Definition: logger.hh:219
void set_mask()
Set streams_mask_ according to the type of message.
Definition: logger.cc:118
MsgType
Enum of types of Logger messages.
Definition: logger.hh:150
@ message
Definition: logger.hh:152
@ warning
Definition: logger.hh:151
@ debug
Definition: logger.hh:154
@ log
Definition: logger.hh:153
@ error
Definition: logger.hh:155
std::string file_name_
Actual file.
Definition: logger.hh:214
Logger(MsgType type)
Constructor.
Definition: logger.cc:64
MsgType type_
Type of message.
Definition: logger.hh:212
bool every_process_
Flag marked if log message is printing for all processes or only for zero process.
Definition: logger.hh:213
void print_file_header(std::stringstream &file_stream)
Print header to file stream, helper method called from print_to_file.
Definition: logger.cc:259
int line_
Actual line.
Definition: logger.hh:216
std::string function_
Actual function.
Definition: logger.hh:215
void print_to_screen(std::ostream &stream, std::stringstream &scr_stream, StreamMask mask)
Print formated message to given screen stream if mask corresponds with streams_mask_.
Definition: logger.cc:172
std::stringstream cout_stream_
Store messages printed to cout output stream.
Definition: logger.hh:208
std::string compact_file_name(std::string file_name)
Return compact (relative) path to the given source file.
Definition: logger.cc:230
int mpi_rank_
Actual process (if MPI is supported)
Definition: logger.hh:218
Logger & fmt(T &&... t)
Allow use functionality of fmtlib for formating message.
Definition: logger.hh:176
~Logger()
Destructor.
Definition: logger.cc:75
std::string date_time_
Actual date and time.
Definition: logger.hh:217
StreamMask full_streams_mask_
Mask of logger, specifies all streams into which to be written in logger message.
Definition: logger.hh:220
bool print_screen_header(std::stringstream &scr_stream)
Print header to screen stream, helper method called from print_to_screen.
Definition: logger.cc:240
std::stringstream file_stream_
Store messages printed to file.
Definition: logger.hh:210
void print_to_file(std::ofstream &stream, std::stringstream &file_stream, StreamMask mask)
Print formated message to given file stream if mask corresponds with streams_mask_.
Definition: logger.cc:200
Helper class, store mask specifying streams.
Definition: logger.hh:41
static StreamMask cerr
Predefined mask of std::cerr output.
Definition: logger.hh:55
int operator()(void)
Definition: logger.cc:53
static StreamMask log
Predefined mask of log file output.
Definition: logger.hh:58
StreamMask(int mask)
Constructor set mask_ value.
Definition: logger.hh:48
StreamMask operator|(const StreamMask &other)
Definition: logger.cc:48
StreamMask operator&(const StreamMask &other)
Definition: logger.cc:43
StreamMask()
Empty constructor.
Definition: logger.hh:44
int mask_
Definition: logger.hh:70
static StreamMask cout
Predefined mask of std::cout output.
Definition: logger.hh:52
#define THROW(whole_exception_expr)
Wrapper for throw. Saves the throwing point.
Definition: exceptions.hh:53
manipulators::Array< T, Delim > format(T const &deduce, Delim delim=", ")
Definition: logger.hh:325
Logger & operator<<(Logger &log, StreamMask mask)
Definition: logger.cc:281
ArmaVec< double, N > vec
Definition: armor.hh:885
fmt::BufferedFile & move(fmt::BufferedFile &f)
Definition: posix.h:380
Cont const & _v
Definition: logger.hh:307
Array(Cont const &v, Delim d=", ")
Definition: logger.hh:305
friend std::ostream & operator<<(std::ostream &os, Array const &manip)
Definition: logger.hh:310