OpenWalnut  1.2.5
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
WLogger.h
1 //---------------------------------------------------------------------------
2 //
3 // Project: OpenWalnut ( http://www.openwalnut.org )
4 //
5 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
6 // For more information see http://www.openwalnut.org/copying
7 //
8 // This file is part of OpenWalnut.
9 //
10 // OpenWalnut is free software: you can redistribute it and/or modify
11 // it under the terms of the GNU Lesser General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // OpenWalnut is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public License
21 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
22 //
23 //---------------------------------------------------------------------------
24 
25 #ifndef WLOGGER_H
26 #define WLOGGER_H
27 
28 #include <ostream>
29 #include <sstream>
30 #include <string>
31 #include <vector>
32 
33 #include <boost/shared_ptr.hpp>
34 #include <boost/signals2/signal.hpp>
35 
36 #include "WLogEntry.h"
37 #include "WLogStream.h"
38 #include "WStringUtils.h"
39 #include "WSharedSequenceContainer.h"
40 #include "WExportCommon.h"
41 
42 /**
43  * This class defines the interface for adding logs and managing several output streams for them. The actual log entry is in \ref WLogEntry and
44  * the output is done in \ref WLogStream.
45  */
46 class OWCOMMON_EXPORT WLogger // NOLINT
47 {
48 public:
49  /**
50  * Create the first and only instance of the logger as it is a singleton.
51  *
52  * \param output the output stream to use
53  * \param level the default log level
54  */
55  static void startup( std::ostream& output = std::cout, LogLevel level = LL_DEBUG ); // NOLINT - we need this non-const ref here
56 
57  /**
58  * Destructor.
59  */
60  virtual ~WLogger();
61 
62  /**
63  * Returns pointer to the currently running logger instance.
64  *
65  * \return pointer to logger instance.
66  */
67  static WLogger* getLogger();
68 
69  /**
70  * Adds a new stream to the logger. This is useful to register file streams or uncolored GUI based outputs.
71  * \note It is not intended to allow getting streams or modifying them except you are the owner/creator.
72  *
73  * \param s the stream to add.
74  */
75  void addStream( WLogStream::SharedPtr s );
76 
77  /**
78  * Set the default format used for log entries.
79  *
80  * \param format the format string. See WLogEntry for details.
81  */
82  void setDefaultFormat( std::string format );
83 
84  /**
85  * Set the default log-level used for log entries in default console-output
86  *
87  * \param level the log-level
88  */
89  void setDefaultLogLevel( const LogLevel& level );
90 
91  /**
92  * Gets the default format used for log entries. This actually returns the format of the first log stream.
93  *
94  * \return format string. See WLogEntry for details.
95  */
96  std::string getDefaultFormat();
97 
98  /**
99  * Appends a log message to the logging queue.
100  * \param message the log entry
101  * \param source indicates where this entry comes from
102  * \param level The logging level of the current message
103  */
104  void addLogMessage( std::string message, std::string source = "", LogLevel level = LL_DEBUG );
105 
106  /**
107  * Types of signals supported by the logger
108  */
109  typedef enum
110  {
111  AddLog = 0 //!< for added logs
112  }
113  LogEvent;
114 
115  /**
116  * The type for all callbacks which get a log entry as parameter.
117  */
118  typedef boost::function< void ( WLogEntry& ) > LogEntryCallback;
119 
120  /**
121  * Subscribe to the specified signal.
122  *
123  * \note If you want to listen to incoming log entries, you can also utilize the WLogStream class.
124  *
125  * \param event the kind of signal the callback should be used for.
126  * \param callback the callback.
127  *
128  * \return the connection object. Disconnect it explicitly!
129  */
130  boost::signals2::connection subscribeSignal( LogEvent event, LogEntryCallback callback );
131 
132 protected:
133 
134 private:
135  /**
136  * Constructor. The logger is created using the static method startup.
137  *
138  * \param output the stream where to print log messages to
139  * \param level logging level, i.e. verboseness
140  */
141  WLogger( std::ostream& output, LogLevel level ); // NOLINT - we need this non-const ref here
142 
143  /**
144  * We do not want a copy constructor, so we define it private.
145  */
146  WLogger( const WLogger& );
147 
148  /**
149  * The output stream list type.
150  */
152 
153  /**
154  * The list of outputs to print the messages to.
155  */
157 
158  /**
159  * Signal called whenever a new log message arrives.
160  */
161  boost::signals2::signal< void( WLogEntry& ) > m_addLogSignal;
162 };
163 
164 /**
165  * This namespace collects several convenient access points such as wlog::err
166  * for logging with streams to our WLogger.
167  */
168 namespace wlog
169 {
170  /**
171  * Resource class for streamed logging.
172  */
173  class OWCOMMON_EXPORT WStreamedLogger // NOLINT
174  {
175  public:
176  /**
177  * Creates new streamed logger instance. Logging is deferred until
178  * destruction of this instance.
179  *
180  * \param source Source from which the log message originates
181  * \param level The LogLevel of the message
182  */
183  WStreamedLogger( const std::string& source, LogLevel level );
184 
185  /**
186  * Appends something loggable (to std::string castable) to the log.
187  *
188  * \param loggable Token that should be streamed into the Logger
189  * \return The streamed logger for further use
190  */
191  template< typename T > WStreamedLogger operator<<( const T& loggable );
192 
193  // Doxygen should ignore the TypeDef below which are just an alias for std::endl etc.
194  // \cond Suppress_Doxygen
195  typedef std::basic_ostream< char, std::char_traits< char > > OutStreamType;
196  typedef OutStreamType& ( *StreamManipulatorFunctor )( OutStreamType& );
197  // \endcond
198 
199  /**
200  * This is totally crazy man! Don't get dizzy on that, watch out and
201  * ask a C++ guru next to your side, which is probably named Christian
202  * or have a look on that: http://stackoverflow.com/questions/1134388/stdendl-is-of-unknown-type-when-overloading-operator
203  *
204  * Allow std::endl to be streamed into log messages.
205  *
206  * \param manip Function pointer e.g. std::endl, std::flush, std::ends
207  * \return The streamed logger for further use
208  */
209  WStreamedLogger operator<<( StreamManipulatorFunctor manip );
210 
211  protected:
212  private:
213  /**
214  * Actually implementing the streaming functionality.
215  */
216  class Buffer
217  {
218  public: // NOLINT inner classes may have also lables
219  /**
220  * Constructs a new stream for logging.
221  *
222  * \param source String identifying the source of the message
223  * \param level LogLevel of the message
224  */
225  Buffer( const std::string& source, LogLevel level );
226 
227  /**
228  * Commits the logging expression to our WLogger
229  */
230  virtual ~Buffer();
231 
232  std::ostringstream m_logString; //!< queuing up parts of the log message
233  LogLevel m_level; //!< Default logging level for this stream
234  std::string m_source; //!< The source of the logging message
235  };
236 
237  /**
238  * Forbid assignment
239  *
240  * \param rhs The instance which SHOULD be copied over
241  * \return A reference to the variable for which assignment was INTENDED.
242  */
243  WStreamedLogger& operator=( const WStreamedLogger& rhs );
244 
245  boost::shared_ptr< Buffer > m_buffer; //!< Collects the message parts.
246  };
247 
248  inline WStreamedLogger::WStreamedLogger( const std::string& source, LogLevel level )
249  : m_buffer( new Buffer( source, level ) )
250  {
251  }
252 
253  template< typename T > inline WStreamedLogger WStreamedLogger::operator<<( const T& loggable )
254  {
255  using string_utils::operator<<; // in case we want to log arrays or vectors
256  m_buffer->m_logString << loggable;
257  return *this;
258  }
259 
260  inline WStreamedLogger WStreamedLogger::operator<<( StreamManipulatorFunctor manip )
261  {
262  manip( m_buffer->m_logString );
263  return *this;
264  }
265 
266  inline WStreamedLogger::Buffer::Buffer( const std::string& source, LogLevel level )
267  : m_logString(),
268  m_level( level ),
269  m_source( source )
270  {
271  }
272 
273  /**
274  * Convenient function for logging messages to our WLogger but not for
275  * public use outside of this module.
276  *
277  * \param source Indicate the source where this log message origins.
278  * \param level The LogLevel of this message
279  * \return The logger created using the functions parameters
280  */
281  inline WStreamedLogger _wlog( const std::string& source, LogLevel level )
282  {
283  return WStreamedLogger( source, level );
284  }
285 
286  /**
287  * Logging an error message.
288  *
289  * \param source Indicate the source where this log message origins.
290  * \return The logger with the error message.
291  */
292  inline WStreamedLogger error( const std::string& source )
293  {
294  return _wlog( source, LL_ERROR );
295  }
296 
297  /**
298  * Logging a warning message.
299  *
300  * \param source Indicate the source where this log message origins.
301  * \return The logger with the warning message.
302  */
303  inline WStreamedLogger warn( const std::string& source )
304  {
305  return _wlog( source, LL_WARNING );
306  }
307 
308  /**
309  * Logging an information message.
310  *
311  * \param source Indicate the source where this log message origins.
312  * \return The logger with the warning message.
313  */
314  inline WStreamedLogger info( const std::string& source )
315  {
316  return _wlog( source, LL_INFO );
317  }
318 
319  /**
320  * Logging a debug message.
321  *
322  * \param source Indicate the source where this log message origins.
323  * \return The logger with the debug message.
324  */
325  inline WStreamedLogger debug( const std::string& source )
326  {
327  return _wlog( source, LL_DEBUG );
328  }
329 } // end of namespace log
330 
331 #endif // WLOGGER_H