ONPOSIX  2.0
 All Classes Namespaces Files Functions Variables Enumerator Friends Macros Pages
Logger.hpp
Go to the documentation of this file.
1 /*
2  * Logger.hpp
3  *
4  * Copyright (C) 2012 Evidence Srl - www.evidence.eu.com
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 #ifndef LOGGER_HPP_
22 #define LOGGER_HPP_
23 
24 #include <fstream>
25 #include <ostream>
26 #include <string>
27 #include <sstream>
28 #include <sys/time.h>
29 
30 /// Comment this line if you don't need multithread support
31 #define LOG_MULTITHREAD
32 
33 /// Log levels:
34 #define LOG_NOLOG 0 ///< No logging
35 #define LOG_ERRORS 1 ///< Log only error messages
36 #define LOG_WARNINGS 2 ///< Log warnings and error messages
37 #define LOG_ALL 3 ///< Log all
38 
39 /// Log level for console messages:
40 #ifndef LOG_LEVEL_CONSOLE
41 #define LOG_LEVEL_CONSOLE LOG_WARNINGS
42 #endif
43 
44 /// Log level for file:
45 #ifndef LOG_LEVEL_FILE
46 #define LOG_LEVEL_FILE LOG_ALL
47 #endif
48 
49 
50 
51 #ifdef LOG_MULTITHREAD
52 #include "PosixMutex.hpp"
53 #endif
54 
55 /**
56  * \brief Macro to set the file used for logging.
57  *
58  * @param Base name of the file used for logging (e.g. "/tmp/myproject")
59  *
60  * Example of configuration of the Logger: *
61  * \code
62  * LOG_FILE("/tmp/myproject);
63  * \endcode
64  */
65 #define LOG_FILE(outputFile) { \
66  onposix::Logger::getInstance().setFile(outputFile); \
67  }
68 
69 
70 
71 /**
72  * \brief Macro to print error messages.
73  *
74  * Example of usage:
75  * \code
76  * ERROR("hello " << "world");
77  * \endcode
78  */
79 #if (defined NDEBUG) || (LOG_LEVEL_CONSOLE < LOG_ERRORS && LOG_LEVEL_FILE < LOG_ERRORS)
80  #define ERROR(...)
81 #elif (LOG_LEVEL_CONSOLE < LOG_ERRORS)
82  #define ERROR(msg) { \
83  std::ostringstream logger_dbg_stream__; \
84  logger_dbg_stream__ << "[ERROR]\t"; \
85  logger_dbg_stream__ << msg; \
86  onposix::Logger::getInstance().printOnFile(__FILE__, __LINE__, \
87  logger_dbg_stream__.str()); \
88  }
89 #elif (LOG_LEVEL_FILE < LOG_ERRORS)
90  #define ERROR(msg) { \
91  std::ostringstream logger_dbg_stream__; \
92  logger_dbg_stream__ << "[ERROR]\t"; \
93  logger_dbg_stream__ << msg; \
94  onposix::Logger::getInstance().printOnConsole(__FILE__, __LINE__, \
95  logger_dbg_stream__.str()); \
96  }
97 #else
98  #define ERROR(msg) { \
99  std::ostringstream logger_dbg_stream__; \
100  logger_dbg_stream__ << "[ERROR]\t"; \
101  logger_dbg_stream__ << msg; \
102  onposix::Logger::getInstance().printOnConsole(__FILE__, __LINE__, \
103  logger_dbg_stream__.str()); \
104  onposix::Logger::getInstance().printOnFile(__FILE__, __LINE__, \
105  logger_dbg_stream__.str()); \
106  }
107 #endif
108 
109 
110 /**
111  * \brief Macro to print warning messages.
112  *
113  * Example of usage:
114  * \code
115  * WARNING("hello " << "world");
116  * \endcode
117  */
118 #if (defined NDEBUG) || (LOG_LEVEL_CONSOLE < LOG_WARNINGS && LOG_LEVEL_FILE < LOG_WARNINGS)
119  #define WARNING(...)
120 #elif (LOG_LEVEL_CONSOLE < LOG_WARNINGS)
121  #define WARNING(msg) { \
122  std::ostringstream logger_dbg_stream__; \
123  logger_dbg_stream__ << "[WARNING]\t"; \
124  logger_dbg_stream__ << msg; \
125  onposix::Logger::getInstance().printOnFile(__FILE__, __LINE__, \
126  logger_dbg_stream__.str()); \
127  }
128 #elif (LOG_LEVEL_FILE < LOG_WARNINGS)
129  #define WARNING(msg) { \
130  std::ostringstream logger_dbg_stream__; \
131  logger_dbg_stream__ << "[WARNING]\t"; \
132  logger_dbg_stream__ << msg; \
133  onposix::Logger::getInstance().printOnConsole(__FILE__, __LINE__, \
134  logger_dbg_stream__.str()); \
135  }
136 #else
137  #define WARNING(msg) { \
138  std::ostringstream logger_dbg_stream__; \
139  logger_dbg_stream__ << "[WARNING]\t"; \
140  logger_dbg_stream__ << msg; \
141  onposix::Logger::getInstance().printOnConsole(__FILE__, __LINE__, \
142  logger_dbg_stream__.str()); \
143  onposix::Logger::getInstance().printOnFile(__FILE__, __LINE__, \
144  logger_dbg_stream__.str()); \
145  }
146 #endif
147 
148 
149 
150 /**
151  * \brief Macro to print debug messages.
152  *
153  * Example of usage:
154  * \code
155  * DEBUG("hello " << "world");
156  * \endcode
157  */
158 #if (defined NDEBUG) || (LOG_LEVEL_CONSOLE < LOG_ALL && LOG_LEVEL_FILE < LOG_ALL)
159  #define DEBUG(...)
160 #elif (LOG_LEVEL_CONSOLE < LOG_ALL)
161  #define DEBUG(msg) { \
162  std::ostringstream logger_dbg_stream__; \
163  logger_dbg_stream__ << "[DEBUG]\t"; \
164  logger_dbg_stream__ << msg; \
165  onposix::Logger::getInstance().printOnFile(__FILE__, __LINE__, \
166  logger_dbg_stream__.str()); \
167  }
168 #elif (LOG_LEVEL_FILE < LOG_ALL)
169  #define DEBUG(msg) { \
170  std::ostringstream logger_dbg_stream__; \
171  logger_dbg_stream__ << "[DEBUG]\t"; \
172  logger_dbg_stream__ << msg; \
173  onposix::Logger::getInstance().printOnConsole(__FILE__, __LINE__, \
174  logger_dbg_stream__.str()); \
175  }
176 #else
177  #define DEBUG(msg) { \
178  std::ostringstream logger_dbg_stream__; \
179  logger_dbg_stream__ << "[DEBUG]\t"; \
180  logger_dbg_stream__ << msg; \
181  onposix::Logger::getInstance().printOnConsole(__FILE__, __LINE__, \
182  logger_dbg_stream__.str()); \
183  onposix::Logger::getInstance().printOnFile(__FILE__, __LINE__, \
184  logger_dbg_stream__.str()); \
185  }
186 #endif
187 
188 
189 namespace onposix {
190 
191 /**
192  * \brief Simple logger to log messages on file and console.
193  *
194  * This is the implementation of a simple logger in C++. It is implemented
195  * as a Singleton, so it can be easily called through the DEBUG, WARNING
196  * and ERROR macros.
197  * It is Pthread-safe.
198  * It allows to log on both file and console.
199  *
200  * Example of configuration of the Logger: *
201  * \code
202  * LOG_FILE("/tmp/myproject);
203  * \endcode
204  *
205  * Example of usage of the Logger:
206  * \code
207  * DEBUG("hello " << "world");
208  * \endcode
209  */
210 class Logger
211 {
212 public:
213  static Logger& getInstance();
214 
215  void printOnFile( const std::string& sourceFile,
216  const int codeLine,
217  const std::string& message);
218  void printOnConsole( const std::string& sourceFile,
219  const int codeLine,
220  const std::string& message);
221 
222  void setFile (const std::string& outputFile);
223 
224  /**
225  * \brief Method to know if the latest message has been printed on file
226  *
227  * @return true if it has been printed; false otherwise
228  */
229  inline bool latestMsgPrintedOnFile() const {
231  }
232 
233  /**
234  * \brief Method to know if the latest message has been printed on file
235  *
236  * @return true if it has been printed; false otherwise
237  */
238  inline bool latestMsgPrintedOnConsole() const {
240  }
241 
242 private:
243  Logger();
244  ~Logger();
245 
246 #ifdef LOG_MULTITHREAD
247  /**
248  * \brief Lock for mutual exclusion between different threads
249  */
251 #endif
252 
253  /**
254  * \brief Pointer to the unique Logger (i.e., Singleton)
255  */
256  static Logger* m_;
257 
258  /**
259  * \brief Initial part of the name of the file used for Logging.
260  *
261  * Date and time are automatically appended.
262  */
263  std::string logFile_;
264 
265  /**
266  * \brief Stream used when logging on a file
267  */
268  std::ofstream out_;
269 
270  /**
271  * \brief Initial time (used to print relative times)
272  */
273  struct timeval initialTime_;
274 
275  /**
276  * \brief Debug: to know if the latest message has been printed
277  * on file.
278  */
280 
281  /**
282  * \brief Debug: to know if the latest message has been printed
283  * on console.
284  */
286 
287  /**
288  * \brief Method to lock in case of multithreading
289  */
290  inline static void lock();
291 
292  /**
293  * \brief Method to unlock in case of multithreading
294  */
295  inline static void unlock();
296 };
297 
298 } /* onposix */
299 
300 #endif /* LOGGER_HPP_ */