PFASST++
logging.hpp
Go to the documentation of this file.
1 
22 #ifndef _PFASST__LOGGING_HPP_
23 #define _PFASST__LOGGING_HPP_
24 
25 #include <iomanip>
26 #ifndef NDEBUG
27  #include <iostream> // used by pfasst::log::test_logging_levels()
28 #endif
29 #include <string>
30 using namespace std;
31 
32 #ifdef WITH_MPI
33  #include <sstream>
34  #include <mpi.h>
35 #endif
36 
37 #include <boost/algorithm/string.hpp>
38 
39 #include "pfasst/config.hpp"
40 
41 
47 struct OUT
48 {
49  public:
51  static const string black;
52  static const string red;
53  static const string green;
54  static const string yellow;
55  static const string blue;
56  static const string magenta;
57  static const string cyan;
58  static const string white;
60 
62  static const string bold;
63  static const string underline;
65 
67  static const string reset;
68 };
69 
70 const string OUT::black = "\033[30m";
71 const string OUT::red = "\033[31m";
72 const string OUT::green = "\033[32m";
73 const string OUT::yellow = "\033[33m";
74 const string OUT::blue = "\033[34m";
75 const string OUT::magenta = "\033[35m";
76 const string OUT::cyan = "\033[36m";
77 const string OUT::white = "\033[37m";
78 
79 const string OUT::bold = "\033[1m";
80 const string OUT::underline = "\033[4m";
81 
82 const string OUT::reset = "\033[0m";
83 
84 // enable easy logging of STL containers
85 #define ELPP_STL_LOGGING
86 // disable creation of default log file
87 #define ELPP_NO_DEFAULT_LOG_FILE
88 // enable passing `--logging-flags` via command line
89 #define ELPP_LOGGING_FLAGS_FROM_ARG
90 
91 #ifndef NDEBUG
92  #define ELPP_DEBUG_ASSERT_FAILURE
93  #define ELPP_STACKTRACE_ON_CRASH
94 #endif
95 
96 #ifdef PFASST_NO_LOGGING
97  #define ELPP_DISABLE_LOGS
98  #define ML_NOLOG
99 #endif
100 
101 #include <pfasst/easylogging++.h>
102 
104 #ifndef ML_NOLOG
105 
110  #define ML_LOG(level, x) LOG(level) << x
111 
117  #define ML_CLOG(level, logger_id, x) CLOG(level, logger_id) << x
118 
124  #define ML_CLOG_IF(condition, level, logger_id, x) CLOG_IF(condition, level, logger_id) << x
125 
131  #define ML_CVLOG(verbose_level, logger_id, x) CVLOG(verbose_level, logger_id) << x
132 
138  #define ML_CVLOG_IF(condition, verbose_level, logger_id, x) CVLOG_IF(condition, verbose_level, logger_id) << x
139 #else
140  #define ML_LOG(level, x)
141  #define ML_CLOG(level, logger_id, x)
142  #define ML_CLOG_IF(condition, level, logger_id, x)
143  #define ML_CVLOG(verbose_level, logger_id, x)
144  #define ML_CVLOG_IF(condition, verbose_level, logger_id, x)
145 #endif
146 
148 
149 #ifndef PFASST_LOGGER_INITIALIZED
150  // initialize easyloggingpp
151  // FIXME: this might already be called by code using PFASST++
152  INITIALIZE_EASYLOGGINGPP
163  #define PFASST_LOGGER_INITIALIZED
164 #endif
165 
166 #ifndef PFASST_LOGGER_DEFAULT_GLOBAL_MILLISECOND_WIDTH
167  #define PFASST_LOGGER_DEFAULT_GLOBAL_MILLISECOND_WIDTH "2"
169 #endif
170 
171 #ifndef VLOG_FUNC_START
172 
176  #define VLOG_FUNC_START(scope) \
177  pfasst::log::stack_position++; \
178  VLOG(9) << std::string((pfasst::log::stack_position - 1) * 2, ' ') << "START: " << std::string(scope) << "::" << std::string(__func__) << "()"
179 #endif
180 
181 #ifndef VLOG_FUNC_END
182 
186  #define VLOG_FUNC_END(scope) \
187  pfasst::log::stack_position--; \
188  VLOG(9) << std::string(pfasst::log::stack_position * 2, ' ') << "DONE: " << std::string(scope) << "::" << std::string(__func__) << "()";
189 #endif
190 
191 #ifndef LOG_PRECISION
192  #define LOG_PRECISION 5
193 #endif
194 
200 #define LOG_INDENT \
201  string(pfasst::log::stack_position * 2, ' ')
202 
210 #define LOGGER_ID_LENGTH 10
211 
212 
213 namespace pfasst
214 {
232  namespace log
233  {
240  static size_t stack_position;
241 
247  static bool initialized = false;
248 
263  inline string format_mpi_rank(const char fill = ' ')
264  {
265  ostringstream frmter;
266  frmter << std::setw(4) << std::setfill(fill) << pfasst::config::get_rank();
267  return frmter.str();
268  }
269 
285  inline string get_log_file_name()
286  {
287  string log_name = config::get_value<string>("log_prefix", "");
288 #ifdef WITH_MPI
289  if (log_name.size() > 0) {
290  log_name += "_";
291  }
292  log_name += "mpi-rank-" + format_mpi_rank('0');
293 #endif
294  log_name += ".log";
295  return log_name;
296  }
297 
309  inline void set_global_logging_options(el::Configurations* conf,
310  const el::Configurations* default_conf = nullptr)
311  {
312  string milliseconds_width, to_stdout;
313  if (default_conf) {
314  el::Configurations* default_conf_nc = const_cast<el::Configurations*>(default_conf);
315  milliseconds_width = default_conf_nc->get(el::Level::Info,
316  el::ConfigurationType::MillisecondsWidth)->value();
317  to_stdout = default_conf_nc->get(el::Level::Info,
318  el::ConfigurationType::ToStandardOutput)->value();
319  } else {
322  .count("quiet")) ? "false" : "true";
323  }
324 
325  conf->setGlobally(el::ConfigurationType::ToStandardOutput, to_stdout);
326  conf->setGlobally(el::ConfigurationType::Filename, get_log_file_name());
327  }
328 
360  inline static void add_custom_logger(const string& id)
361  {
363  .count("nocolor") ? false : true;
364 
365  const string INFO_COLOR = (colorize) ? OUT::blue : "";
366  const string DEBG_COLOR = (colorize) ? "" : "";
367  const string WARN_COLOR = (colorize) ? OUT::magenta : "";
368  const string ERRO_COLOR = (colorize) ? OUT::red : "";
369  const string FATA_COLOR = (colorize) ? OUT::red + OUT::bold : "";
370  const string VERB_COLOR = (colorize) ? OUT::white : "";
371  const string TIMESTAMP_COLOR = (colorize) ? OUT::white : "";
372  const string RESET = (colorize) ? OUT::reset : "";
373 
374  const string TIMESTAMP = TIMESTAMP_COLOR + "%datetime{%H:%m:%s,%g}" + RESET + " ";
375  const string LEVEL = "%level";
376  const string VLEVEL = "VERB%vlevel";
377  const string POSITION = "%fbase:%line";
378  const string MESSAGE = "%msg";
379 #ifdef WITH_MPI
380  const string MPI_RANK = ", MPI " + format_mpi_rank();
381 #else
382  const string MPI_RANK = "";
383 #endif
384 
385  const size_t id_length = id.size();
386  string id2print = id.substr(0, LOGGER_ID_LENGTH);
387  boost::to_upper(id2print);
388  if (initialized) {
389  ML_CLOG(DEBUG, "default", "initializing custom logger '" << id << "' as '" << id2print << "'");
390  }
391  if (id_length < LOGGER_ID_LENGTH) {
392  id2print.append(LOGGER_ID_LENGTH - id_length, ' ');
393  }
394 
395  el::Logger* logger = el::Loggers::getLogger(id);
396  el::Configurations* conf = logger->configurations();
397  const el::Configurations* default_conf = el::Loggers::defaultConfigurations();
398  set_global_logging_options(conf, default_conf);
399 
400  conf->set(el::Level::Info, el::ConfigurationType::Format,
401  TIMESTAMP + INFO_COLOR + "[" + id2print + ", " + LEVEL + MPI_RANK + "] " + MESSAGE + RESET);
402  conf->set(el::Level::Debug, el::ConfigurationType::Format,
403  TIMESTAMP + DEBG_COLOR + "[" + id2print + ", " + LEVEL + MPI_RANK + "] " + POSITION + " " + MESSAGE + RESET);
404  conf->set(el::Level::Warning, el::ConfigurationType::Format,
405  TIMESTAMP + WARN_COLOR + "[" + id2print + ", " + LEVEL + MPI_RANK + "] " + MESSAGE + RESET);
406  conf->set(el::Level::Error, el::ConfigurationType::Format,
407  TIMESTAMP + ERRO_COLOR + "[" + id2print + ", " + LEVEL + MPI_RANK + "] " + MESSAGE + RESET);
408  conf->set(el::Level::Fatal, el::ConfigurationType::Format,
409  TIMESTAMP + FATA_COLOR + "[" + id2print + ", " + LEVEL + MPI_RANK + "] " + POSITION + " " + MESSAGE + RESET);
410  conf->set(el::Level::Verbose, el::ConfigurationType::Format,
411  TIMESTAMP + VERB_COLOR + "[" + id2print + ", " + VLEVEL + MPI_RANK + "] " + MESSAGE + RESET);
412  el::Loggers::reconfigureLogger(logger, *conf);
413  }
414 
422  inline static void load_default_config()
423  {
424  el::Configurations defaultConf;
425  defaultConf.setToDefault();
426 
427  set_global_logging_options(&defaultConf);
428 
429  el::Loggers::setDefaultConfigurations(defaultConf, true);
430 
431  add_custom_logger("default");
433  add_custom_logger("Controller");
434  add_custom_logger("Communicator");
435  add_custom_logger("Sweeper");
436  add_custom_logger("Encap");
437  add_custom_logger("Quadrature");
438  add_custom_logger("User");
439  }
440 
460  inline static void set_logging_flags()
461  {
462  el::Loggers::addFlag(el::LoggingFlag::LogDetailedCrashReason);
463  el::Loggers::addFlag(el::LoggingFlag::DisableApplicationAbortOnFatalLog);
464 #ifdef NO_COLOR
465  el::Loggers::removeFlag(el::LoggingFlag::ColoredTerminalOutput);
466 #else
467  el::Loggers::addFlag(el::LoggingFlag::ColoredTerminalOutput);
468 #endif
469  el::Loggers::addFlag(el::LoggingFlag::MultiLoggerSupport);
470  el::Loggers::addFlag(el::LoggingFlag::CreateLoggerAutomatically);
471  }
472 
484 #ifdef NDEBUG
485  inline static void test_logging_levels() {}
486 #else
487  inline static void test_logging_levels()
488  {
489  cout << "### Example of different Logging Levels:" << endl;
490  ML_LOG(INFO, "info");
491  ML_LOG(DEBUG, "debug");
492  ML_LOG(WARNING, "warning");
493  ML_LOG(ERROR, "error");
494  ML_LOG(FATAL, "fatal error");
495  ML_LOG(TRACE, "trace");
496  for (size_t level = 0; level <= 9; ++level) {
497  ML_CVLOG(level, "default", "verbosity level " << level);
498  }
499  cout << "### End Example Logging Levels" << endl << endl;
500  }
501 #endif
502 
518  inline static void start_log(int argc, char** argv)
519  {
520  START_EASYLOGGINGPP(argc, argv);
524  ML_CLOG(INFO, "default", "PFASST++ version " << pfasst::VERSION);
525  }
526  } // ::pfasst::log
527 } // ::pfasst
528 
529 #endif // _PFASST__LOGGING_HPP_
string format_mpi_rank(const char fill= ' ')
Formats the local MPI world rank as a string.
Definition: logging.hpp:263
static const string bold
Definition: logging.hpp:62
static void start_log(int argc, char **argv)
Starts easylogging++ with given arguments and loads configuration.
Definition: logging.hpp:518
int get_rank()
Get MPI rank during initialization.
Definition: config.hpp:40
#define LOGGER_ID_LENGTH
Length of logger ID to print.
Definition: logging.hpp:210
static const string underline
Definition: logging.hpp:63
STL namespace.
static const string reset
resets both, colour and style
Definition: logging.hpp:67
static size_t stack_position
Definition: logging.hpp:240
#define ML_CLOG(level, logger_id, x)
same as CLOG(level, logger, x) from easylogging++
Definition: logging.hpp:117
static const string cyan
Definition: logging.hpp:57
static void add_custom_logger(const string &id)
Provides convenient way of adding additional named loggers.
Definition: logging.hpp:360
static const string white
Definition: logging.hpp:58
static const string green
Definition: logging.hpp:53
static void set_logging_flags()
Sets some default flags for easylogging++.
Definition: logging.hpp:460
#define ML_LOG(level, x)
same as LOG(level, x) from easylogging++
Definition: logging.hpp:110
po::variables_map & get_variables_map()
Definition: config_impl.hpp:22
static bool initialized
internal flag identifying whether the default logger has been initialized.
Definition: logging.hpp:247
static options & get_instance()
Accessor to the singleton instance.
Definition: config_impl.hpp:16
static const string black
Definition: logging.hpp:51
static void test_logging_levels()
Prints example logging for all logging levels for the default logger.
Definition: logging.hpp:487
static constexpr const char * VERSION
PFASST++ version: closest release tag and a brief git hash.
Definition: config.hpp:24
#define ML_CVLOG(verbose_level, logger_id, x)
same as CVLOG(verbosity, logger, x) from easylogging++
Definition: logging.hpp:131
static const string blue
Definition: logging.hpp:55
#define PFASST_LOGGER_DEFAULT_GLOBAL_MILLISECOND_WIDTH
precision of milliseconds to be printed
Definition: logging.hpp:168
string get_log_file_name()
Composes the log file name for the local rank.
Definition: logging.hpp:285
void set_global_logging_options(el::Configurations *conf, const el::Configurations *default_conf=nullptr)
Sets global logging options.
Definition: logging.hpp:309
static const string magenta
Definition: logging.hpp:56
static const string yellow
Definition: logging.hpp:54
static const string red
Definition: logging.hpp:52
Some general variables for coloured terminal output.
Definition: logging.hpp:47
static void load_default_config()
Sets default configuration for default loggers.
Definition: logging.hpp:422