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
21namespace tlx {
22
23//! template class for formatting. contains a print() method.
24template <typename AnyType, typename Enable = void>
26
27/*!
28
29\brief LOG and sLOG for development and debugging
30
31This is a short description of how to use \ref LOG and \ref sLOG for rapid
32development of modules with debug output, and how to **keep it afterwards**.
33
34There are two classes Logger and SpacingLogger, but one does not use these
35directly.
36
37Instead there are the macros: \ref LOG and \ref sLOG that can be used as such:
38\code
39LOG << "This will be printed with a newline";
40sLOG << "Print variables a" << a << "b" << b << "c" << c;
41\endcode
42
43There macros only print the lines if the boolean variable **debug** is
44true. This variable is searched for in the scope of the LOG, which means it can
45be set or overridden in the function scope, the class scope, from **inherited
46classes**, or even the global scope.
47
48\code
49class 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
70There are two variation of \ref LOG and \ref sLOG : append 0 or 1 for
71temporarily 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
73setting.
74
75After a module works as intended, one can just set `debug = false`, and all
76debug output will disappear and be optimized out.
77 */
78class Logger
79{
80private:
81 //! collector stream
82 std::ostringstream oss_;
83
84public:
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{
105private:
106 //! true until the first element it outputted.
107 bool first_ = true;
108
109 //! collector stream
110 std::ostringstream oss_;
111
112public:
113 //! construction: add prefix if desired
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
127};
128
130{
131public:
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{
164public:
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{
182public:
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{
203public:
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
216protected:
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
230template <typename AnyType>
231class LoggerFormatter<AnyType>
232{
233public:
234 static void print(std::ostream& os, const AnyType& t) {
235 os << t;
236 }
237};
238
239template <typename A, typename B>
240class LoggerFormatter<std::pair<A, B> >
241{
242public:
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
252template <typename T, class A>
253class LoggerFormatter<std::vector<T, A> >
254{
255public:
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 << ',';
263 }
264 os << ']';
265 }
266};
267
268} // namespace tlx
269
270#endif // !TLX_LOGGER_CORE_HEADER
271
272/******************************************************************************/
Class to hook logger output in the local thread.
Definition: core.hpp:202
void append_log_line(const std::string &line) final
method the receive log lines
Definition: core.cpp:136
std::string get()
return transcript of log
Definition: core.cpp:132
LoggerOutputHook * next_
previous logger, will be restored by destructor
Definition: core.hpp:218
void clear()
clear transcript
Definition: core.cpp:128
std::ostringstream oss_
string stream collecting
Definition: core.hpp:224
bool echo_
whether to echo each line to next logger output
Definition: core.hpp:221
LoggerCollectOutput(bool echo=false)
Definition: core.cpp:118
static void print(std::ostream &os, const AnyType &t)
Definition: core.hpp:234
static void print(std::ostream &os, const std::pair< A, B > &p)
Definition: core.hpp:243
static void print(std::ostream &os, const std::vector< T, A > &data)
Definition: core.hpp:256
template class for formatting. contains a print() method.
Definition: core.hpp:25
Abstract class to implement output hooks for logging.
Definition: core.hpp:181
virtual void append_log_line(const std::string &line)=0
method the receive log lines
virtual ~LoggerOutputHook()
virtual destructor
Definition: core.cpp:114
Abstract class to implement prefix output hooks for logging.
Definition: core.hpp:163
virtual void add_log_prefix(std::ostream &os)=0
method to add prefix to log lines
virtual ~LoggerPrefixHook()
virtual destructor
Definition: core.cpp:110
void operator&(Logger &)
Definition: core.hpp:132
LOG and sLOG for development and debugging.
Definition: core.hpp:79
~Logger()
destructor: output a newline
Definition: core.cpp:92
Logger()
construction: add prefix if desired
Definition: core.cpp:86
std::ostringstream oss_
collector stream
Definition: core.hpp:82
Logger & operator<<(const AnyType &at)
output any type, including io manipulators
Definition: core.hpp:90
A logging class which outputs spaces between elements pushed via operator<<.
Definition: core.hpp:104
SpacingLogger()
construction: add prefix if desired
Definition: core.cpp:97
SpacingLogger & operator<<(const AnyType &at)
output any type, including io manipulators
Definition: core.hpp:118
bool first_
true until the first element it outputted.
Definition: core.hpp:107
~SpacingLogger()
destructor: output a newline
Definition: core.cpp:103
std::ostringstream oss_
collector stream
Definition: core.hpp:110
STL namespace.
LoggerOutputHook * set_logger_output_hook(LoggerOutputHook *hook)
set new LoggerOutputHook instance to receive global log lines.
Definition: core.cpp:65
LoggerPrefixHook * set_logger_prefix_hook(LoggerPrefixHook *hook)
Set new LoggerPrefixHook instance to prefix global log lines.
Definition: core.cpp:80
LoggerOutputHook * set_logger_to_stderr()
install default logger to cerr / stderr instead of stdout.
Definition: core.cpp:69