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 \
146  (*(::armarx::LogSender::createLogSender()->setFile(__FILE__)->setLine(__LINE__)->setFunction( \
147  ARMARX_FUNCTION)))
148 
149 /**
150  * \def ARMARX_LOG
151  * \deprecated
152  * \ingroup Logging
153  * This macro retrieves the armarx::LogSender instance of this class which
154  * can then be used to log data using the << operator .
155  * This macro can be used by classes that inherit from Logging.
156  *
157  * \note This is deprecated. Use the macros with attached logging level instead like ARMARX_INFO.
158  *
159  * example:
160  * \code
161  * ARMARX_LOG << eWARN << "cycle time dropped below " << 1 << "fps in " << "Capturer" << endl;
162  * \endcode
163  *
164  */
165 #define ARMARX_LOG \
166  (*ARMARX_LOG_S.setLocalMinimumLoggingLevel(this->Logging::minimumLoggingLevel)) \
167  << this->::armarx::Logging::tag
168 
169 
170 #define _ARMARX_LOG_INTERNAL_S(level) \
171  (level < ::armarx::LogSender::GetGlobalMinimumLoggingLevel()) ? _GlobalDummyLogSender \
172  : ARMARX_LOG_S << level
173 
174 #define _ARMARX_LOG_INTERNAL_(level) \
175  (checkLogLevel(level)) ? _GlobalDummyLogSender \
176  : (*loghelper(__FILE__, __LINE__, ARMARX_FUNCTION)) << level
177 
178 
179 //! \ingroup Logging
180 //! The normal logging level
181 #define ARMARX_INFO _ARMARX_LOG_INTERNAL_(::armarx::MessageTypeT::INFO)
182 //! \ingroup Logging
183 //! The logging level for output that is only interesting while debugging
184 #define ARMARX_DEBUG _ARMARX_LOG_INTERNAL_(::armarx::MessageTypeT::DEBUG)
185 //! \ingroup Logging
186 //! The logging level for verbose information
187 #define ARMARX_VERBOSE _ARMARX_LOG_INTERNAL_(::armarx::MessageTypeT::VERBOSE)
188 //! \ingroup Logging
189 //! The logging level for always important information, but expected behaviour (in contrast to ARMARX_WARNING)
190 #define ARMARX_IMPORTANT _ARMARX_LOG_INTERNAL_(::armarx::MessageTypeT::IMPORTANT)
191 //! \ingroup Logging
192 //! The logging level for unexpected behaviour, but not a serious problem
193 #define ARMARX_WARNING _ARMARX_LOG_INTERNAL_(::armarx::MessageTypeT::WARN)
194 //! \ingroup Logging
195 //! The logging level for unexpected behaviour, that must be fixed
196 #define ARMARX_ERROR _ARMARX_LOG_INTERNAL_(::armarx::MessageTypeT::ERROR)
197 //! \ingroup Logging
198 //! The logging level for unexpected behaviour, that will lead to a seriously malfunctioning program and probably to program exit
199 #define ARMARX_FATAL _ARMARX_LOG_INTERNAL_(::armarx::MessageTypeT::FATAL)
200 
201 //! \ingroup Logging
202 #define ARMARX_INFO_S _ARMARX_LOG_INTERNAL_S(::armarx::MessageTypeT::INFO)
203 //! \ingroup Logging
204 //! The logging level for output that is only interesting while debugging
205 #define ARMARX_DEBUG_S _ARMARX_LOG_INTERNAL_S(::armarx::MessageTypeT::DEBUG)
206 //! \ingroup Logging
207 #define ARMARX_VERBOSE_S _ARMARX_LOG_INTERNAL_S(::armarx::MessageTypeT::VERBOSE)
208 //! \ingroup Logging
209 //! The logging level for always important information, but expected behaviour (in contrast to ARMARX_WARNING)
210 #define ARMARX_IMPORTANT_S _ARMARX_LOG_INTERNAL_S(::armarx::MessageTypeT::IMPORTANT)
211 //! \ingroup Logging
212 //! The logging level for unexpected behaviour, but not a serious problem
213 #define ARMARX_WARNING_S _ARMARX_LOG_INTERNAL_S(::armarx::MessageTypeT::WARN)
214 //! \ingroup Logging
215 //! The logging level for unexpected behaviour, that must be fixed
216 #define ARMARX_ERROR_S _ARMARX_LOG_INTERNAL_S(::armarx::MessageTypeT::ERROR)
217 //! \ingroup Logging
218 //! The logging level for unexpected behaviour, that will lead to a seriously malfunctioning program and probably to program exit
219 #define ARMARX_FATAL_S _ARMARX_LOG_INTERNAL_S(::armarx::MessageTypeT::FATAL)
220 
221 namespace armarx
222 {
223  class LogSender;
224  using LogSenderPtr = std::shared_ptr<LogSender>;
225 
226  struct SpamFilterData;
227  using SpamFilterDataPtr = std::shared_ptr<SpamFilterData>;
228 
229  /**
230  \class Logging
231  \brief Base Class for all Logging classes.
232  \ingroup Logging
233 
234  Inherit from this class in order to use ArmarX Logging facitities.
235 
236  You should call setTag() in the derived class's constructor,
237  otherwise the category string will be empty.
238  */
240  {
241  public:
242  Logging();
243  virtual ~Logging();
244  void setTag(const LogTag& tag);
245  void setTag(const std::string& tagName);
246  /*!
247  * \brief With setLocalMinimumLoggingLevel the minimum verbosity-level of
248  * log-messages can be set.
249  * \param level The minimum logging level
250  */
251  void setLocalMinimumLoggingLevel(MessageTypeT level);
252  MessageTypeT getEffectiveLoggingLevel() const;
253 
254  /**
255  * @brief disables the logging for the current line for the given amount of seconds.
256  * Usage:
257  * @verbatim
258  ARMARX_INFO << deactivateSpam(1) << "My Controller value" << x;
259  @endverbatim
260  * @note Needs to be called like above. Just calling it has no effect.
261  * @param deactivationDurationSec Duration for which the logging is deactivated.
262  * @param identifier Additional log entry identifier. Useful, when having a loop and each iteration should be printed.
263  * @param deactivate If true the logging is disabled. If false the logging is immediately enabled.
264  * @return Internal datastruct for the logging framework.
265  */
266  SpamFilterDataPtr deactivateSpam(float deactivationDurationSec = 10.0f,
267  const std::string& identifier = "",
268  bool deactivate = true) const;
269 
270  protected:
271  /** Retrieve log sender.
272  *
273  * This method is usually called by using one of the loggin macro ARMARX_LOG.
274  *
275  * @return pointer to the logSender
276  */
277  const LogSenderPtr& getLogSender() const;
281  LogSenderPtr loghelper(const char* file, int line, const char* function) const;
282  bool checkLogLevel(MessageTypeT level) const;
283 
284  private:
285  LogSenderPtr logSender;
286  };
287 } // namespace armarx
288 
289 /**
290  * @brief use this macro to write output code that is executed when printed
291  * and thus not executed if the debug level prevents printing.
292  * In the code you should write to the stream out to output messages.
293  *
294  * Example:
295  * \code{.cpp}
296  * ARMARX_DEBUG << ARMARX_STREAM_PRINTER
297  {
298  for (const std::string& elem : someSetOfStrings)
299  {
300  if(elem.size() == 5)
301  {
302  out << " " << elem << "\n";
303  }
304  }
305  };
306  * \endcode
307  * This code will only run if the effective debug level is Debug and only
308  * entries are printed which satisfy the if condition
309  */
310 #define ARMARX_STREAM_PRINTER ::armarx::detail::StreamPrinterTag::tag* [&](std::ostream & out)
311 
312 armarx::LogSenderPtr loghelper(const char* file, int line, const char* function);
314 armarx::SpamFilterDataPtr deactivateSpam(float deactivationDurationSec = 10.0f,
315  const std::string& identifier = "",
316  bool deactivate = true);
317 
319 deactivateSpam(const std::string& identifier,
320  float deactivationDurationSec = 10.0f,
321  bool deactivate = true)
322 {
323  return deactivateSpam(deactivationDurationSec, identifier, deactivate);
324 }
armarx::MessageTypeT
MessageTypeT
Definition: LogSender.h:45
armarx::Logging::minimumLoggingLevel
MessageTypeT minimumLoggingLevel
Definition: Logging.h:279
_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:65
trace.h
loghelper
armarx::LogSenderPtr loghelper(const char *file, int line, const char *function)
Definition: Logging.cpp:143
armarx::Logging::spamFilter
SpamFilterDataPtr spamFilter
Definition: Logging.h:280
StringHelpers.h
armarx::SpamFilterDataPtr
std::shared_ptr< SpamFilterData > SpamFilterDataPtr
Definition: Logging.h:227
armarx::SpamFilterData
Definition: SpamFilterData.h:16
deactivateSpam
armarx::SpamFilterDataPtr deactivateSpam(float deactivationDurationSec=10.0f, const std::string &identifier="", bool deactivate=true)
Definition: Logging.cpp:158
checkLogLevel
bool checkLogLevel(armarx::MessageTypeT level)
Definition: Logging.cpp:150
armarx::control::hardware_config::tagName
std::string tagName(ConfigTag tag)
Definition: Config.cpp:301
armarx::Logging
Base Class for all Logging classes.
Definition: Logging.h:239
armarx::LogSenderPtr
std::shared_ptr< LogSender > LogSenderPtr
Typedef of std::shared_ptr for convenience.
Definition: Logging.h:224
LogSender.h
armarx::Logging::tag
LogTag tag
Definition: Logging.h:278
ARMARXCORE_IMPORT_EXPORT
#define ARMARXCORE_IMPORT_EXPORT
Definition: ImportExport.h:38
armarx::LogTag
Definition: LoggingUtil.h:71
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:27