Logging.h
Go to the documentation of this file.
1 /*
2 * This file is part of ArmarX.
3 *
4 * Copyright (C) 2011-2016, High Performance Humanoid Technologies (H2T), Karlsruhe Institute of Technology (KIT), all rights reserved.
5 *
6 * ArmarX is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * ArmarX is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 * @package ArmarXCore::core
19 * @author Kai Welke (welke at kit dot edu)
20 * @author Mirko Wächter 2012 (mirko dot waechter @ kit dot edu)
21 * @date 2010
22 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
23 * GNU General Public License
24 */
25 #pragma once
26 
27 #include <boost/current_function.hpp>
28 
32 
33 /**
34  * \page LoggingDoc ArmarX Logging
35  *
36  * Every output in ArmarX should be done with the built-in logging features.
37  * The ArmarX logging facilities are
38  * available anytime and anywhere in the code and should be used
39  * instead of std::cout or printf().<br/>
40  * ArmarX Logging provides the following main features:
41  * \li usable like std::cout
42  * \li stores meta data like file, line, time, who etc.
43  * \li offers several different log levels (from debug to fatal)
44  * \li can log backtraces
45  * \li provides logs over network (Ice)
46  * \li LogViewer (GUI) which works through Ice
47  * \li thread safety
48  * \li console coloring
49  * \li redirection of std::cout/cerr to ArmarX log
50  *
51  * \section LoggingDoc-Usage How to use the ArmarX logging facilities
52  *
53  * For logging there are a few macros available (e.g. "ARMARX_INFO"). They all
54  * begin with "ARMARX_". Followed by the log level (e.g. "ARMARX_INFO").
55  * <br/>
56  *
57  * An example looks like this:<br/>
58  * \code
59  * ARMARX_INFO << "cycle time dropped below " << 1 << " fps in Capturer";
60  * \endcode
61  *
62  * After the c++-line has ended (i.e. after the semi-colon), the data is written
63  * as <b>one entry</b> into the log.
64  *
65  * To be able use the logging facilities, one has to include the file <ArmarXCore/core/logging/Logging.h>.<p/>
66  *
67  * If you want to use all logging features, you need to let your class inherit from armarx::Logging.
68  * Then features like tagging and spam-deactivation are available.
69  *
70  * \note To log inside a static function of a class inheriting from Logging, you have to
71  * use the logging macros ending on _S, e.g. ARMARX_INFO_S.
72  *
73  * \note If the current minimum log-level is below the used log level, the output string calculation is completly skipped.
74  * This means no code with effect on any variable should be put into the logging-code-line.
75  * This also means it is performance-wise safe to have a lot debug messages in the code.
76  *
77  * The main features in detail:
78  * \li <b>usable like std::cout</b><br/>
79  * The usage of ArmarX logging works like std::cout. That means after the macro (e.g.
80  * "ARMARX_INFO") follows the streaming operator (<<). There are conversions
81  * for all of the standard types available like with std::cout and some
82  * additional types (e.g. std::vector, QString in Gui). These can be easily
83  * extended by overloading/specializing the armarx::LogSender::operator<< <T>().
84  * \li <b>stores meta data like file, line, time, who etc.</b><br/>
85  * At the moment the logging stores the following meta data: time, tag, log-level,
86  * Ice-component, file, line, function, threadId and backtrace (for log-level
87  * eWARN and above).
88  * \li <b>offers several different log levels (from debug to fatal)</b><br>
89  * There are 5 log levels available. In order of increasing severity:
90  * debug, verbose, info, warning, error, fatal (The corresponding macros are:
91  * ARMARX_DEBUG, ARMARX_VERBOSE, ARMARX_INFO, ARMARX_WARNING, ARMARX_ERROR, ARMARX_FATAL).
92  * \li <b>can log backtraces</b><br>
93  * For the log levels warning and above a backtrace is stored in the meta data.
94  * For lower levels the backtrace is empty to reduce the network traffic.<br/>
95  * The backtrace is not shown in the console, only in the LogViewer.
96  * \li <b>provides logs over network (Ice)</b><br/>
97  * All log output is automatically streamed via Ice, if an Ice connection is available.<br/>
98  * If the connection is not established yet, all log outputs are buffered locally
99  * until the connection is ready.<br/>
100  * The logging facilties are using the publish-subscribe-methodology of Ice for this,
101  * so potential log-viewers can just subscribe to the topic "Log"(Type: LogPrx).
102  * \li <b>LogViewer (GUI)</b><br/>
103  * The LogViewer is an ArmarX Gui Widget, that provides a comfortable
104  * access to the logs. It offers the possibility to define custom filters, to split
105  * the data in several logs, to search quickly through the log file and much more.
106  * \li <b>thread safety</b><br/>
107  * As opposed to std::cout the ArmarX logging facilities are thread safe.
108  * So there is no mixing of log entries of different threads.
109  * \li <b>console coloring</b><br/>
110  * If activated (default) the output on the console of different log levels
111  * is colorized. Additionally, the user can just use the streaming operator <<
112  * and the LogSender color enum (e.g. LogSender::eGreen) to set the color
113  * for the current output message.
114  *
115  *
116  *
117  *
118  *
119  */
120 
121 
122 #define ARMARX_FUNCTION BOOST_CURRENT_FUNCTION
123 //! Dummy instance for faster skipped logging (if verbosity level is lower than selected level) - DO NOT USE THIS VARIABLE
125 
126 /**
127  * \defgroup Logging
128  * \ingroup core-utility
129  * \copydoc LoggingDoc
130 
131  * \def ARMARX_LOG_S
132  * \ingroup Logging
133  * This macro creates a new temporary instance which
134  * can then be used to log data using the << operator.
135  * This macro is dedicated to the special case logging in a static function of a class that inherits Logging.
136  * For all other cases the non static version should be used (without _S).
137  * S stands for static.
138 
139  * example:
140  * \code
141  * ARMARX_LOG_S << eWARN << "cycle time dropped below " << 1 << "fps in " << "Capturer" << endl;
142  * \endcode
143  *
144  */
145 #define ARMARX_LOG_S (*(::armarx::LogSender::createLogSender()->setFile(__FILE__)->setLine(__LINE__)->setFunction(ARMARX_FUNCTION)))
146 
147 /**
148  * \def ARMARX_LOG
149  * \deprecated
150  * \ingroup Logging
151  * This macro retrieves the armarx::LogSender instance of this class which
152  * can then be used to log data using the << operator .
153  * This macro can be used by classes that inherit from Logging.
154  *
155  * \note This is deprecated. Use the macros with attached logging level instead like ARMARX_INFO.
156  *
157  * example:
158  * \code
159  * ARMARX_LOG << eWARN << "cycle time dropped below " << 1 << "fps in " << "Capturer" << endl;
160  * \endcode
161  *
162  */
163 #define ARMARX_LOG (*ARMARX_LOG_S.setLocalMinimumLoggingLevel(this->Logging::minimumLoggingLevel)) << this->::armarx::Logging::tag
164 
165 
166 #define _ARMARX_LOG_INTERNAL_S(level) (level < ::armarx::LogSender::GetGlobalMinimumLoggingLevel()) ? _GlobalDummyLogSender : ARMARX_LOG_S << level
167 
168 #define _ARMARX_LOG_INTERNAL_(level) (checkLogLevel(level)) ? _GlobalDummyLogSender : (*loghelper(__FILE__, __LINE__, ARMARX_FUNCTION)) << level
169 
170 
171 
172 //! \ingroup Logging
173 //! The normal logging level
174 #define ARMARX_INFO _ARMARX_LOG_INTERNAL_(::armarx::MessageTypeT::INFO)
175 //! \ingroup Logging
176 //! The logging level for output that is only interesting while debugging
177 #define ARMARX_DEBUG _ARMARX_LOG_INTERNAL_(::armarx::MessageTypeT::DEBUG)
178 //! \ingroup Logging
179 //! The logging level for verbose information
180 #define ARMARX_VERBOSE _ARMARX_LOG_INTERNAL_(::armarx::MessageTypeT::VERBOSE)
181 //! \ingroup Logging
182 //! The logging level for always important information, but expected behaviour (in contrast to ARMARX_WARNING)
183 #define ARMARX_IMPORTANT _ARMARX_LOG_INTERNAL_(::armarx::MessageTypeT::IMPORTANT)
184 //! \ingroup Logging
185 //! The logging level for unexpected behaviour, but not a serious problem
186 #define ARMARX_WARNING _ARMARX_LOG_INTERNAL_(::armarx::MessageTypeT::WARN)
187 //! \ingroup Logging
188 //! The logging level for unexpected behaviour, that must be fixed
189 #define ARMARX_ERROR _ARMARX_LOG_INTERNAL_(::armarx::MessageTypeT::ERROR)
190 //! \ingroup Logging
191 //! The logging level for unexpected behaviour, that will lead to a seriously malfunctioning program and probably to program exit
192 #define ARMARX_FATAL _ARMARX_LOG_INTERNAL_(::armarx::MessageTypeT::FATAL)
193 
194 //! \ingroup Logging
195 #define ARMARX_INFO_S _ARMARX_LOG_INTERNAL_S(::armarx::MessageTypeT::INFO)
196 //! \ingroup Logging
197 //! The logging level for output that is only interesting while debugging
198 #define ARMARX_DEBUG_S _ARMARX_LOG_INTERNAL_S(::armarx::MessageTypeT::DEBUG)
199 //! \ingroup Logging
200 #define ARMARX_VERBOSE_S _ARMARX_LOG_INTERNAL_S(::armarx::MessageTypeT::VERBOSE)
201 //! \ingroup Logging
202 //! The logging level for always important information, but expected behaviour (in contrast to ARMARX_WARNING)
203 #define ARMARX_IMPORTANT_S _ARMARX_LOG_INTERNAL_S(::armarx::MessageTypeT::IMPORTANT)
204 //! \ingroup Logging
205 //! The logging level for unexpected behaviour, but not a serious problem
206 #define ARMARX_WARNING_S _ARMARX_LOG_INTERNAL_S(::armarx::MessageTypeT::WARN)
207 //! \ingroup Logging
208 //! The logging level for unexpected behaviour, that must be fixed
209 #define ARMARX_ERROR_S _ARMARX_LOG_INTERNAL_S(::armarx::MessageTypeT::ERROR)
210 //! \ingroup Logging
211 //! The logging level for unexpected behaviour, that will lead to a seriously malfunctioning program and probably to program exit
212 #define ARMARX_FATAL_S _ARMARX_LOG_INTERNAL_S(::armarx::MessageTypeT::FATAL)
213 
214 namespace armarx
215 {
216  class LogSender;
217  using LogSenderPtr = std::shared_ptr<LogSender>;
218 
219  struct SpamFilterData;
220  using SpamFilterDataPtr = std::shared_ptr<SpamFilterData>;
221 
222  /**
223  \class Logging
224  \brief Base Class for all Logging classes.
225  \ingroup Logging
226 
227  Inherit from this class in order to use ArmarX Logging facitities.
228 
229  You should call setTag() in the derived class's constructor,
230  otherwise the category string will be empty.
231  */
233  {
234  public:
235 
236 
237  Logging();
238  virtual ~Logging();
239  void setTag(const LogTag& tag);
240  void setTag(const std::string& tagName);
241  /*!
242  * \brief With setLocalMinimumLoggingLevel the minimum verbosity-level of
243  * log-messages can be set.
244  * \param level The minimum logging level
245  */
246  void setLocalMinimumLoggingLevel(MessageTypeT level);
247  MessageTypeT getEffectiveLoggingLevel() const;
248 
249  /**
250  * @brief disables the logging for the current line for the given amount of seconds.
251  * Usage:
252  * @verbatim
253  ARMARX_INFO << deactivateSpam(1) << "My Controller value" << x;
254  @endverbatim
255  * @note Needs to be called like above. Just calling it has no effect.
256  * @param deactivationDurationSec Duration for which the logging is deactivated.
257  * @param identifier Additional log entry identifier. Useful, when having a loop and each iteration should be printed.
258  * @param deactivate If true the logging is disabled. If false the logging is immediately enabled.
259  * @return Internal datastruct for the logging framework.
260  */
261  SpamFilterDataPtr deactivateSpam(float deactivationDurationSec = 10.0f, const std::string& identifier = "", bool deactivate = true) const;
262 
263  protected:
264  /** Retrieve log sender.
265  *
266  * This method is usually called by using one of the loggin macro ARMARX_LOG.
267  *
268  * @return pointer to the logSender
269  */
270  const LogSenderPtr& getLogSender() const;
274  LogSenderPtr loghelper(const char* file, int line, const char* function) const;
275  bool checkLogLevel(MessageTypeT level) const;
276 
277  private:
278  LogSenderPtr logSender;
279 
280  };
281 }
282 
283 /**
284  * @brief use this macro to write output code that is executed when printed
285  * and thus not executed if the debug level prevents printing.
286  * In the code you should write to the stream out to output messages.
287  *
288  * Example:
289  * \code{.cpp}
290  * ARMARX_DEBUG << ARMARX_STREAM_PRINTER
291  {
292  for (const std::string& elem : someSetOfStrings)
293  {
294  if(elem.size() == 5)
295  {
296  out << " " << elem << "\n";
297  }
298  }
299  };
300  * \endcode
301  * This code will only run if the effective debug level is Debug and only
302  * entries are printed which satisfy the if condition
303  */
304 #define ARMARX_STREAM_PRINTER ::armarx::detail::StreamPrinterTag::tag * [&](std::ostream& out)
305 
306 armarx::LogSenderPtr loghelper(const char* file, int line, const char* function);
308 armarx::SpamFilterDataPtr deactivateSpam(float deactivationDurationSec = 10.0f, const std::string& identifier = "", bool deactivate = true);
309 inline armarx::SpamFilterDataPtr deactivateSpam(const std::string& identifier, float deactivationDurationSec = 10.0f, bool deactivate = true)
310 {
311  return deactivateSpam(deactivationDurationSec, identifier, deactivate);
312 }
313 
armarx::MessageTypeT
MessageTypeT
Definition: LogSender.h:45
armarx::Logging::minimumLoggingLevel
MessageTypeT minimumLoggingLevel
Definition: Logging.h:272
_GlobalDummyLogSender
const armarx::LogSender _GlobalDummyLogSender
Dummy instance for faster skipped logging (if verbosity level is lower than selected level) - DO NOT ...
Definition: Logging.h:124
armarx::LogSender
Wrapper for the Log IceStorm topic with convenience methods for logging.
Definition: LogSender.h:66
trace.h
loghelper
armarx::LogSenderPtr loghelper(const char *file, int line, const char *function)
Definition: Logging.cpp:131
armarx::Logging::spamFilter
SpamFilterDataPtr spamFilter
Definition: Logging.h:273
StringHelpers.h
armarx::SpamFilterDataPtr
std::shared_ptr< SpamFilterData > SpamFilterDataPtr
Definition: Logging.h:220
armarx::SpamFilterData
Definition: SpamFilterData.h:15
deactivateSpam
armarx::SpamFilterDataPtr deactivateSpam(float deactivationDurationSec=10.0f, const std::string &identifier="", bool deactivate=true)
Definition: Logging.cpp:143
checkLogLevel
bool checkLogLevel(armarx::MessageTypeT level)
Definition: Logging.cpp:136
armarx::control::hardware_config::tagName
std::string tagName(ConfigTag tag)
Definition: Config.cpp:302
armarx::Logging
Base Class for all Logging classes.
Definition: Logging.h:232
armarx::LogSenderPtr
std::shared_ptr< LogSender > LogSenderPtr
Typedef of std::shared_ptr for convenience.
Definition: Logging.h:217
LogSender.h
armarx::Logging::tag
LogTag tag
Definition: Logging.h:271
ARMARXCORE_IMPORT_EXPORT
#define ARMARXCORE_IMPORT_EXPORT
Definition: ImportExport.h:38
armarx::LogTag
Definition: LoggingUtil.h:66
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:28