A toolkit for working with phylogenetic data.
v0.20.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
logging.hpp
Go to the documentation of this file.
1 #ifndef GENESIS_UTILS_CORE_LOGGING_H_
2 #define GENESIS_UTILS_CORE_LOGGING_H_
3 
4 /*
5  Genesis - A toolkit for working with phylogenetic data.
6  Copyright (C) 2014-2017 Lucas Czech
7 
8  This program is free software: you can redistribute it and/or modify
9  it under the terms of the GNU General Public License as published by
10  the Free Software Foundation, either version 3 of the License, or
11  (at your option) any later version.
12 
13  This program is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  GNU General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with this program. If not, see <http://www.gnu.org/licenses/>.
20 
21  Contact:
22  Lucas Czech <lucas.czech@h-its.org>
23  Exelixis Lab, Heidelberg Institute for Theoretical Studies
24  Schloss-Wolfsbrunnenweg 35, D-69118 Heidelberg, Germany
25 */
26 
38 
39 #include <cmath>
40 #include <sstream>
41 #include <string>
42 #include <vector>
43 
44 namespace genesis {
45 namespace utils {
46 
47 // =============================================================================
48 // Macro definitions
49 // =============================================================================
50 
51 // TODO add TIME1..4 (or TMR maybe) for indented timing logs
52 // TODO change macros for timing to be out of usual log levels
53 // TODO define a function that logs the detail column headers (difficult because
54 // of length difference for file name log detail)
55 // TODO offer csv as output format
56 // TODO offer remote streams
57 
58 #ifndef LOG_LEVEL_MAX
59 
64 # define LOG_LEVEL_MAX genesis::utils::Logging::kDebug4
65 #endif
66 
67 // TODO make DEBUG a special macro with proper usage makefile etc,
68 // also add maybe stuff like RELEASE TEST etc, prepend ENV_ or so!
69 // TODO do an undefine first
70 
71 // override this setting when debugging is turned on (eg by makefile)
72 #ifdef DEBUG
73 # define LOG_LEVEL_MAX genesis::utils::Logging::kDebug4
74 #endif
75 
76 // define the actual log macro, so that the compiler can prune calls
77 // to a log with levels above the static max log level
78 #define GENESIS_LOG(level) \
79  if (level > LOG_LEVEL_MAX) ; \
80  else if (level > genesis::utils::Logging::max_level()) ; \
81  else genesis::utils::Logging().get(__FILE__, __LINE__, GENESIS_FUNC, level)
82 
83 // define a similar log macro, this time changing the details of the message
84 #define GENESIS_LOG_DETAILS(level, ...) \
85  if (level > LOG_LEVEL_MAX) ; \
86  else if (level > genesis::utils::Logging::max_level()) ; \
87  else genesis::utils::Logging().get(__FILE__, __LINE__, GENESIS_FUNC, level, {__VA_ARGS__})
88 
89 // define standard logging types as macro shortcuts:
90 
92 #define LOG_ERR GENESIS_LOG(genesis::utils::Logging::kError)
93 
95 #define LOG_WARN GENESIS_LOG(genesis::utils::Logging::kWarning)
96 
98 #define LOG_INFO GENESIS_LOG(genesis::utils::Logging::kInfo)
99 
101 #define LOG_DBG GENESIS_LOG(genesis::utils::Logging::kDebug)
102 
104 #define LOG_DBG1 GENESIS_LOG(genesis::utils::Logging::kDebug1)
105 
107 #define LOG_DBG2 GENESIS_LOG(genesis::utils::Logging::kDebug2)
108 
110 #define LOG_DBG3 GENESIS_LOG(genesis::utils::Logging::kDebug3)
111 
113 #define LOG_DBG4 GENESIS_LOG(genesis::utils::Logging::kDebug4)
114 
115 // define special log shortcuts: the list of bools represent
116 // the members of struct LogDetails and indicate which parts shall be included.
117 
126 #define LOG_BOLD GENESIS_LOG_DETAILS(genesis::utils::Logging::kNone, \
127  false, false, false, false, false, false, false, false, false)
128 
137 #define LOG_TIME GENESIS_LOG_DETAILS(genesis::utils::Logging::kDebug, \
138  false, false, false, false , true, false, false, false, false)
139 
148 #define LOG_SCOPE_LEVEL(level) \
149  genesis::utils::LoggingScopeLevel genesis_logging_scope_level_temp_object(level);
150 
162 inline long logging_progress_value (long value = -1)
163 {
164  static long v = -1;
165  if (value > -1) {
166  v = value;
167  }
168  return v;
169 }
170 
215 #define LOG_PROG( value, quantity ) \
216  if( genesis::utils::Logging::kProgress > LOG_LEVEL_MAX ) ; \
217  else if( genesis::utils::Logging::kProgress > genesis::utils::Logging::max_level() ) ; \
218  else if( (long) genesis::utils::logging_progress_value(value) % \
219  (((long) (quantity) * genesis::utils::Logging::report_percentage() / 100) > 0 ? \
220  ((long) (quantity) * genesis::utils::Logging::report_percentage() / 100) : 1) != 0 ) ; \
221  else genesis::utils::Logging().get(__FILE__, __LINE__, GENESIS_FUNC, genesis::utils::Logging::kProgress) << \
222  (int) round(100.0 * (double) genesis::utils::logging_progress_value() / ((quantity) > 0 ? (quantity) : 1)) << "% "
223 
224 // =============================================================================
225 // Logging Details
226 // =============================================================================
227 
250 typedef struct {
252  bool count;
253 
255  bool date;
256 
258  bool time;
259 
261  bool runtime;
262 
270  bool rundiff;
271 
273  bool file;
274 
279  bool line;
280 
286  bool function;
287 
289  bool level;
291 
292 // =============================================================================
293 // Logging
294 // =============================================================================
295 
351 class Logging
352 {
353 public:
354 
355  // -------------------------------------------------------------------
356  // Class Functions
357  // -------------------------------------------------------------------
358 
372  kNone = 0,
373 
376 
379 
382 
385 
388 
391 
394 
397 
400  };
401 
402  Logging() {};
403  ~Logging();
404 
405  // Logging is kind of singleton, its instances are only provided via the
406  // get functions. do not allow other instances by blocking the copy
407  // constructors and copy assignment
408  Logging (const Logging&) {};
409  Logging& operator = (const Logging&) = delete;
410 
411  // getter for the singleton instance of log, is called by the macros
412  std::ostringstream& get (
413  const std::string& file, const int line, const std::string& function,
414  const LoggingLevel level
415  );
416  std::ostringstream& get (
417  const std::string& file, const int line, const std::string& function,
418  const LoggingLevel level, const LoggingDetails dets
419  );
420 
421  // -------------------------------------------------------------------
422  // Logging Settings
423  // -------------------------------------------------------------------
424 
425  // TODO make logging accept one file, and a setter for cout and for cerr
426  // TODO allow different levels to be logged to different streams?!
427 
428  // methods to handle the output streams to write the log messages to
429  static void log_to_stdout ();
430  static void log_to_stream (std::ostream& os);
431  static void log_to_file (const std::string& fn);
432 
438 
440  static inline LoggingLevel max_level ()
441  {
442  return max_level_;
443  }
444  static void max_level (const LoggingLevel level);
445 
447  static inline int report_percentage ()
448  {
449  return report_percentage_;
450  }
451  static void report_percentage (const int percentage);
452 
453  // return a string representation for a log level
454  static std::string level_to_string (const LoggingLevel level);
455 
457  static std::string debug_indent;
458 
459  // -------------------------------------------------------------------
460  // Static Wrappers
461  // -------------------------------------------------------------------
462 
463  static inline void log_error (const std::string& msg)
464  {
465  LOG_ERR << msg;
466  }
467 
468  static inline void log_warning (const std::string& msg)
469  {
470  LOG_WARN << msg;
471  }
472 
473  static inline void log_info (const std::string& msg)
474  {
475  LOG_INFO << msg;
476  }
477 
478  static inline void log_debug (const std::string& msg)
479  {
480  LOG_DBG << msg;
481  }
482 
483  static inline void log_debug_1 (const std::string& msg)
484  {
485  LOG_DBG1 << msg;
486  }
487 
488  static inline void log_debug_2 (const std::string& msg)
489  {
490  LOG_DBG2 << msg;
491  }
492 
493  static inline void log_debug_3 (const std::string& msg)
494  {
495  LOG_DBG3 << msg;
496  }
497 
498  static inline void log_debug_4 (const std::string& msg)
499  {
500  LOG_DBG4 << msg;
501  }
502 
503  // -------------------------------------------------------------------
504  // Internal Data Members
505  // -------------------------------------------------------------------
506 
507 protected:
508  // storage for information needed during one invocation of a log
509  std::ostringstream buff_;
510  std::string file_;
511  int line_;
512  std::string function_;
515 
516  // dynamic log level limit
518 
519  // how often to report progress messages
520  static int report_percentage_;
521 
522  // how many log calls were made so far
523  static long count_;
524 
525  // when was the last call to logging (used for time measurements)
526  static clock_t last_clock_;
527 
528  // array of streams that are used for output
529  static std::vector<std::ostream*> ostreams_;
530 };
531 
532 // =============================================================================
533 // Logging Scope Level
534 // =============================================================================
535 
541 {
542 public:
544  {
545  previous_level = Logging::max_level();
546  Logging::max_level(scope_level);
547  }
548 
550  {
551  Logging::max_level(previous_level);
552  }
553 
554 private:
555  Logging::LoggingLevel previous_level;
556 };
557 
558 // =============================================================================
559 // Logging Progress
560 // =============================================================================
561 
562 /*
563  * This was a test to make LOG_PROG work with incrementing counters like
564  *
565  * LOG_PROG(++progress, total) << "of something";
566  *
567  * but it is slow and dirty. If used, Logging().get(...) has to be expanded by a
568  * std::string init parameters, that is used to initialize buff_.str(init).
569  *
570  * Also, the definition of LOG_PROG that was used for this is:
571  *
572  * #define LOG_PROG(value, quantity) \
573  * if (genesis::utils::Logging::kProgress > LOG_LEVEL_MAX) ; \
574  * else if (genesis::utils::Logging::kProgress > genesis::utils::Logging::max_level()) ; \
575  * else LOG_PROG_FUNC(value, quantity, __FILE__, __LINE__, GENESIS_FUNC)
576  * %
577 inline std::ostringstream& LOG_PROG_FUNC (const int value, const int quantity, const std::string& file, const int line, const std::string& function)
578 {
579  static std::ostringstream trash;
580  int base = quantity * Logging::report_percentage() / 100;
581  if (value % (base > 0 ? base : 1) != 0) {
582  trash.str("");
583  return trash;
584  } else {
585  std::string init = std::to_string((int) round(100.0 * (double) value / quantity)) + "% ";
586  return Logging().get(file, line, function, Logging::kProgress, Logging::details, init);
587  }
588 }
589 */
590 
591 } // namespace utils
592 } // namespace genesis
593 
594 #endif // include guard
static void log_debug_3(const std::string &msg)
Definition: logging.hpp:493
static std::string debug_indent
Indention string for Debug Levels 1-4.
Definition: logging.hpp:457
#define LOG_ERR
Log an error. See genesis::utils::LoggingLevel.
Definition: logging.hpp:92
static int report_percentage_
Definition: logging.hpp:520
#define LOG_DBG
Log a debug message. See genesis::utils::LoggingLevel.
Definition: logging.hpp:101
Debugging message with indent level 2. See LOG_DBG2.
Definition: logging.hpp:393
static LoggingDetails details
Settings for which information is included with each log message. See LoggingDetails for usage...
Definition: logging.hpp:437
static void log_warning(const std::string &msg)
Definition: logging.hpp:468
Errors, usually non-recoverable. See LOG_ERR.
Definition: logging.hpp:375
static void log_debug(const std::string &msg)
Definition: logging.hpp:478
Special messages that are always logged, e.g. program header.
Definition: logging.hpp:372
static std::vector< std::ostream * > ostreams_
Definition: logging.hpp:529
#define LOG_DBG4
Log a debug message. See genesis::utils::LoggingLevel.
Definition: logging.hpp:113
std::ostringstream buff_
Definition: logging.hpp:509
#define LOG_DBG1
Log a debug message. See genesis::utils::LoggingLevel.
Definition: logging.hpp:104
Logging & operator=(const Logging &)=delete
#define LOG_WARN
Log a warning. See genesis::utils::LoggingLevel.
Definition: logging.hpp:95
Warnings if somthing went wront, but program can continue. See LOG_WARN.
Definition: logging.hpp:378
bool count
Include a counter of how many messages have been logged so far.
Definition: logging.hpp:252
LoggingLevel level_
Definition: logging.hpp:513
static clock_t last_clock_
Definition: logging.hpp:526
static std::string level_to_string(const LoggingLevel level)
Return a string representation of a log level.
Definition: logging.cpp:117
~Logging()
Destructor that is invoked at the end of each log line and does the actual output.
Definition: logging.cpp:173
Logging class with easy and fast usage.
Definition: logging.hpp:351
Provides some valuable additions to STD.
static LoggingLevel max_level()
Get the highest log level that is reported.
Definition: logging.hpp:440
Logging(const Logging &)
Definition: logging.hpp:408
static void log_debug_2(const std::string &msg)
Definition: logging.hpp:488
Debugging message with indent level 4. See LOG_DBG4.
Definition: logging.hpp:399
Debugging message with indent level 3. See LOG_DBG3.
Definition: logging.hpp:396
bool line
Include the line of the file where the log message was generated.
Definition: logging.hpp:279
bool rundiff
Include the run time difference to the last log message in sec.
Definition: logging.hpp:270
static void log_info(const std::string &msg)
Definition: logging.hpp:473
static void log_to_file(const std::string &fn)
Add an output file to which log messages are written.
Definition: logging.cpp:154
static int report_percentage()
Get the current percentage for reporting LOG_PROG messages.
Definition: logging.hpp:447
#define LOG_DBG3
Log a debug message. See genesis::utils::LoggingLevel.
Definition: logging.hpp:110
Infos, for example when a file was written. See LOG_INFO.
Definition: logging.hpp:381
LoggingLevel
Levels of severity used for logging.
Definition: logging.hpp:370
long logging_progress_value(long value=-1)
Hack function to make sure that the value arugment in LOG_PROG is only evaluated once.
Definition: logging.hpp:162
static void log_to_stream(std::ostream &os)
Add an output stream to which log messages are written.
Definition: logging.cpp:144
static void log_error(const std::string &msg)
Definition: logging.hpp:463
bool date
Include the current date.
Definition: logging.hpp:255
bool file
Include the filename where the log message was generated.
Definition: logging.hpp:273
static void log_to_stdout()
Add stdout as output stream to which log messages are written.
Definition: logging.cpp:128
Class that sets the Logging Level to a value von construction and set it back on destruction. This is used by the log scope level macro.
Definition: logging.hpp:540
static void log_debug_1(const std::string &msg)
Definition: logging.hpp:483
bool runtime
Include the current run time of the program in sec.
Definition: logging.hpp:261
#define LOG_DBG2
Log a debug message. See genesis::utils::LoggingLevel.
Definition: logging.hpp:107
Debugging message with indent level 1 (e.g. for loops). See LOG_DBG1.
Definition: logging.hpp:390
Progess, used in long executing functions. See LOG_PROG.
Definition: logging.hpp:384
LoggingDetails details_
Definition: logging.hpp:514
std::string function_
Definition: logging.hpp:512
POD stuct containing the settings for which information is included with each logging message...
Definition: logging.hpp:250
bool level
Include the level (e.g. Info, Debug) of the message.
Definition: logging.hpp:289
static void log_debug_4(const std::string &msg)
Definition: logging.hpp:498
Basic debugging message. See LOG_DBG.
Definition: logging.hpp:387
static LoggingLevel max_level_
Definition: logging.hpp:517
LoggingScopeLevel(Logging::LoggingLevel scope_level)
Definition: logging.hpp:543
#define LOG_INFO
Log an info message. See genesis::utils::LoggingLevel.
Definition: logging.hpp:98
bool time
Include the current time.
Definition: logging.hpp:258