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