tlx
core.hpp
Go to the documentation of this file.
1 /*******************************************************************************
2  * tlx/logger/core.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 <tb@panthema.net>
9  *
10  * All rights reserved. Published under the Boost Software License, Version 1.0
11  ******************************************************************************/
12 
13 #ifndef TLX_LOGGER_CORE_HEADER
14 #define TLX_LOGGER_CORE_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&) { }
133  void operator & (SpacingLogger&) { }
134 };
135 
136 //! Explicitly specify the condition for logging
137 #define TLX_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 TLX_LOG TLX_LOGC(debug)
142 
143 //! Override default output: never or always output log.
144 #define TLX_LOG0 TLX_LOGC(false)
145 #define TLX_LOG1 TLX_LOGC(true)
146 
147 //! Explicitly specify the condition for logging
148 #define TLX_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 TLX_sLOG TLX_sLOGC(debug)
153 
154 //! Override default output: never or always output log.
155 #define TLX_sLOG0 TLX_sLOGC(false)
156 #define TLX_sLOG1 TLX_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 //! install default logger to cerr / stderr instead of stdout. returns the old
195 //! hook.
197 
198 /*----------------------------------------------------------------------------*/
199 
200 //! Class to hook logger output in the local thread
202 {
203 public:
204  explicit LoggerCollectOutput(bool echo = false);
206 
207  //! return transcript of log
208  std::string get();
209 
210  //! clear transcript
211  void clear();
212 
213  //! method the receive log lines
214  void append_log_line(const std::string& line) final;
215 
216 protected:
217  //! previous logger, will be restored by destructor
219 
220  //! whether to echo each line to next logger output
221  bool echo_;
222 
223  //! string stream collecting
224  std::ostringstream oss_;
225 };
226 
227 /******************************************************************************/
228 // Formatters
229 
230 template <typename AnyType>
231 class LoggerFormatter<AnyType>
232 {
233 public:
234  static void print(std::ostream& os, const AnyType& t) {
235  os << t;
236  }
237 };
238 
239 template <typename A, typename B>
240 class LoggerFormatter<std::pair<A, B> >
241 {
242 public:
243  static void print(std::ostream& os, const std::pair<A, B>& p) {
244  os << '(';
245  LoggerFormatter<A>::print(os, p.first);
246  os << ',';
247  LoggerFormatter<B>::print(os, p.second);
248  os << ')';
249  }
250 };
251 
252 template <typename T, class A>
253 class LoggerFormatter<std::vector<T, A> >
254 {
255 public:
256  static void print(std::ostream& os, const std::vector<T, A>& data) {
257  os << '[';
258  for (typename std::vector<T>::const_iterator it = data.begin();
259  it != data.end(); ++it)
260  {
261  if (it != data.begin()) os << ',';
262  LoggerFormatter<T>::print(os, *it);
263  }
264  os << ']';
265  }
266 };
267 
268 } // namespace tlx
269 
270 #endif // !TLX_LOGGER_CORE_HEADER
271 
272 /******************************************************************************/
LOG and sLOG for development and debugging.
Definition: core.hpp:78
A logging class which outputs spaces between elements pushed via operator<<.
Definition: core.hpp:103
static void print(std::ostream &os, const std::pair< A, B > &p)
Definition: core.hpp:243
LoggerOutputHook * set_logger_output_hook(LoggerOutputHook *hook)
set new LoggerOutputHook instance to receive global log lines.
Definition: core.cpp:65
static void print(std::ostream &os, const std::vector< T, A > &data)
Definition: core.hpp:256
LoggerOutputHook * next_
previous logger, will be restored by destructor
Definition: core.hpp:218
STL namespace.
Class to hook logger output in the local thread.
Definition: core.hpp:201
std::ostringstream oss_
collector stream
Definition: core.hpp:82
Abstract class to implement output hooks for logging.
Definition: core.hpp:180
static void print(std::ostream &os, const AnyType &t)
Definition: core.hpp:234
bool echo_
whether to echo each line to next logger output
Definition: core.hpp:221
template class for formatting. contains a print() method.
Definition: core.hpp:25
Abstract class to implement prefix output hooks for logging.
Definition: core.hpp:162
~Logger()
destructor: output a newline
Definition: core.cpp:92
LoggerOutputHook * set_logger_to_stderr()
install default logger to cerr / stderr instead of stdout.
Definition: core.cpp:69
std::ostringstream oss_
collector stream
Definition: core.hpp:110
LoggerPrefixHook * set_logger_prefix_hook(LoggerPrefixHook *hook)
Set new LoggerPrefixHook instance to prefix global log lines.
Definition: core.cpp:80
std::ostringstream oss_
string stream collecting
Definition: core.hpp:224
Logger & operator<<(const AnyType &at)
output any type, including io manipulators
Definition: core.hpp:90
Logger()
construction: add prefix if desired
Definition: core.cpp:86