Thrill  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
logger.hpp
Go to the documentation of this file.
1 /*******************************************************************************
2  * tlx/logger.hpp
3  *
4  * Simple logging methods using ostream output.
5  *
6  * Part of tlx - http://panthema.net/tlx
7  *
8  * Copyright (C) 2015-2018 Timo Bingmann <[email protected]>
9  *
10  * All rights reserved. Published under the Boost Software License, Version 1.0
11  ******************************************************************************/
12 
13 #ifndef TLX_LOGGER_HEADER
14 #define TLX_LOGGER_HEADER
15 
16 #include <sstream>
17 #include <string>
18 #include <utility>
19 #include <vector>
20 
21 namespace tlx {
22 
23 //! template class for formatting. contains a print() method.
24 template <typename AnyType, typename Enable = void>
26 
27 /*!
28 
29 \brief LOG and sLOG for development and debugging
30 
31 This is a short description of how to use \ref LOG and \ref sLOG for rapid
32 development of modules with debug output, and how to **keep it afterwards**.
33 
34 There are two classes Logger and SpacingLogger, but one does not use these
35 directly.
36 
37 Instead there are the macros: \ref LOG and \ref sLOG that can be used as such:
38 \code
39 LOG << "This will be printed with a newline";
40 sLOG << "Print variables a" << a << "b" << b << "c" << c;
41 \endcode
42 
43 There macros only print the lines if the boolean variable **debug** is
44 true. This variable is searched for in the scope of the LOG, which means it can
45 be set or overridden in the function scope, the class scope, from **inherited
46 classes**, or even the global scope.
47 
48 \code
49 class MyClass
50 {
51  static constexpr bool debug = true;
52 
53  void func1()
54  {
55  LOG << "Hello World";
56 
57  LOG0 << "This is temporarily disabled.";
58  }
59 
60  void func2()
61  {
62  static constexpr bool debug = false;
63  LOG << "This is not printed any more.";
64 
65  LOG1 << "But this is forced.";
66  }
67 };
68 \endcode
69 
70 There are two variation of \ref LOG and \ref sLOG : append 0 or 1 for
71 temporarily disabled or enabled debug lines. These macros are then \ref LOG0,
72 \ref LOG1, \ref sLOG0, and \ref sLOG1. The suffix overrides the debug variable's
73 setting.
74 
75 After a module works as intended, one can just set `debug = false`, and all
76 debug output will disappear and be optimized out.
77  */
78 class Logger
79 {
80 private:
81  //! collector stream
82  std::ostringstream oss_;
83 
84 public:
85  //! construction: add prefix if desired
86  Logger();
87 
88  //! output any type, including io manipulators
89  template <typename AnyType>
90  Logger& operator << (const AnyType& at) {
92  return *this;
93  }
94 
95  //! destructor: output a newline
96  ~Logger();
97 };
98 
99 /*!
100  * A logging class which outputs spaces between elements pushed via
101  * operator<<. Depending on the real parameter the output may be suppressed.
102  */
104 {
105 private:
106  //! true until the first element it outputted.
107  bool first_ = true;
108 
109  //! collector stream
110  std::ostringstream oss_;
111 
112 public:
113  //! construction: add prefix if desired
114  SpacingLogger();
115 
116  //! output any type, including io manipulators
117  template <typename AnyType>
118  SpacingLogger& operator << (const AnyType& at) {
119  if (!first_) oss_ << ' ';
120  else first_ = false;
122  return *this;
123  }
124 
125  //! destructor: output a newline
126  ~SpacingLogger();
127 };
128 
130 {
131 public:
132  void operator & (Logger&) { }
134 };
135 
136 //! Explicitly specify the condition for logging
137 #define LOGC(cond) \
138  !(cond) ? (void)0 : ::tlx::LoggerVoidify() & ::tlx::Logger()
139 
140 //! Default logging method: output if the local debug variable is true.
141 #define LOG LOGC(debug)
142 
143 //! Override default output: never or always output log.
144 #define LOG0 LOGC(false)
145 #define LOG1 LOGC(true)
146 
147 //! Explicitly specify the condition for logging
148 #define sLOGC(cond) \
149  !(cond) ? (void)0 : ::tlx::LoggerVoidify() & ::tlx::SpacingLogger()
150 
151 //! Default logging method: output if the local debug variable is true.
152 #define sLOG sLOGC(debug)
153 
154 //! Override default output: never or always output log.
155 #define sLOG0 sLOGC(false)
156 #define sLOG1 sLOGC(true)
157 
158 /******************************************************************************/
159 // Hook to add prefixes to log lines
160 
161 //! Abstract class to implement prefix output hooks for logging
163 {
164 public:
165  //! virtual destructor
166  virtual ~LoggerPrefixHook();
167 
168  //! method to add prefix to log lines
169  virtual void add_log_prefix(std::ostream& os) = 0;
170 };
171 
172 //! Set new LoggerPrefixHook instance to prefix global log lines. Returns the
173 //! old hook.
175 
176 /******************************************************************************/
177 // Hook to collect logger output
178 
179 //! Abstract class to implement output hooks for logging
181 {
182 public:
183  //! virtual destructor
184  virtual ~LoggerOutputHook();
185 
186  //! method the receive log lines
187  virtual void append_log_line(const std::string& line) = 0;
188 };
189 
190 //! Set new LoggerOutputHook instance to receive global log lines. Returns the
191 //! old hook.
193 
194 /*----------------------------------------------------------------------------*/
195 
196 //! Class to hook logger output in the local thread
198 {
199 public:
200  explicit LoggerCollectOutput(bool echo = false);
202 
203  //! return transcript of log
204  std::string get();
205 
206  //! clear transcript
207  void clear();
208 
209  //! method the receive log lines
210  void append_log_line(const std::string& line) final;
211 
212 protected:
213  //! previous logger, will be restored by destructor
215 
216  //! whether to echo each line to next logger output
217  bool echo_;
218 
219  //! string stream collecting
220  std::ostringstream oss_;
221 };
222 
223 /******************************************************************************/
224 // Formatters
225 
226 template <typename AnyType>
227 class LoggerFormatter<AnyType>
228 {
229 public:
230  static void print(std::ostream& os, const AnyType& t) {
231  os << t;
232  }
233 };
234 
235 template <typename A, typename B>
236 class LoggerFormatter<std::pair<A, B> >
237 {
238 public:
239  static void print(std::ostream& os, const std::pair<A, B>& p) {
240  os << '(';
241  LoggerFormatter<A>::print(os, p.first);
242  os << ',';
243  LoggerFormatter<B>::print(os, p.second);
244  os << ')';
245  }
246 };
247 
248 template <typename T, class A>
249 class LoggerFormatter<std::vector<T, A> >
250 {
251 public:
252  static void print(std::ostream& os, const std::vector<T, A>& data) {
253  os << '[';
254  for (typename std::vector<T>::const_iterator it = data.begin();
255  it != data.end(); ++it)
256  {
257  if (it != data.begin()) os << ',';
258  LoggerFormatter<T>::print(os, *it);
259  }
260  os << ']';
261  }
262 };
263 
264 } // namespace tlx
265 
266 #endif // !TLX_LOGGER_HEADER
267 
268 /******************************************************************************/
LOG and sLOG for development and debugging.
Definition: logger.hpp:78
virtual ~LoggerPrefixHook()
virtual destructor
Definition: logger.cpp:87
A logging class which outputs spaces between elements pushed via operator<<.
Definition: logger.hpp:103
virtual ~LoggerOutputHook()
virtual destructor
Definition: logger.cpp:91
static void print(std::ostream &os, const std::pair< A, B > &p)
Definition: logger.hpp:239
LoggerOutputHook * set_logger_output_hook(LoggerOutputHook *hook)
Definition: logger.cpp:48
static void print(std::ostream &os, const std::vector< T, A > &data)
Definition: logger.hpp:252
LoggerOutputHook * next_
previous logger, will be restored by destructor
Definition: logger.hpp:214
bool first_
true until the first element it outputted.
Definition: logger.hpp:107
~SpacingLogger()
destructor: output a newline
Definition: logger.cpp:80
void append_log_line(const std::string &line) final
method the receive log lines
Definition: logger.cpp:113
Class to hook logger output in the local thread.
Definition: logger.hpp:197
std::ostringstream oss_
collector stream
Definition: logger.hpp:82
LoggerCollectOutput(bool echo=false)
Definition: logger.cpp:95
SpacingLogger()
construction: add prefix if desired
Definition: logger.cpp:74
Abstract class to implement output hooks for logging.
Definition: logger.hpp:180
static void print(std::ostream &os, const AnyType &t)
Definition: logger.hpp:230
SpacingLogger & operator<<(const AnyType &at)
output any type, including io manipulators
Definition: logger.hpp:118
bool echo_
whether to echo each line to next logger output
Definition: logger.hpp:217
virtual void append_log_line(const std::string &line)=0
method the receive log lines
template class for formatting. contains a print() method.
Definition: logger.hpp:25
std::basic_string< char, std::char_traits< char >, Allocator< char > > string
string with Manager tracking
Definition: allocator.hpp:220
std::vector< T, Allocator< T > > vector
vector with Manager tracking
Definition: allocator.hpp:228
Abstract class to implement prefix output hooks for logging.
Definition: logger.hpp:162
~Logger()
destructor: output a newline
Definition: logger.cpp:69
void clear()
clear transcript
Definition: logger.cpp:105
void operator&(Logger &)
Definition: logger.hpp:132
std::ostringstream oss_
collector stream
Definition: logger.hpp:110
LoggerPrefixHook * set_logger_prefix_hook(LoggerPrefixHook *hook)
Definition: logger.cpp:57
std::ostringstream oss_
string stream collecting
Definition: logger.hpp:220
virtual void add_log_prefix(std::ostream &os)=0
method to add prefix to log lines
Logger & operator<<(const AnyType &at)
output any type, including io manipulators
Definition: logger.hpp:90
Logger()
construction: add prefix if desired
Definition: logger.cpp:63