GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
Line | Branch | Exec | Source |
1 |
/* |
||
2 |
* Copyright 2015, 2019 |
||
3 |
* LAAS-CNRS |
||
4 |
* Andrea Del Prete, François Bailly, Olivier Stasse |
||
5 |
* |
||
6 |
*/ |
||
7 |
|||
8 |
#ifndef __dynamic_graph_logger_H__ |
||
9 |
#define __dynamic_graph_logger_H__ |
||
10 |
|||
11 |
/* --------------------------------------------------------------------- */ |
||
12 |
/* --- API ------------------------------------------------------------- */ |
||
13 |
/* --------------------------------------------------------------------- */ |
||
14 |
|||
15 |
#if defined(WIN32) |
||
16 |
#if defined(logger_EXPORTS) |
||
17 |
#define LOGGER_EXPORT __declspec(dllexport) |
||
18 |
#else |
||
19 |
#define LOGGER_EXPORT __declspec(dllimport) |
||
20 |
#endif |
||
21 |
#else |
||
22 |
#define LOGGER_EXPORT |
||
23 |
#endif |
||
24 |
|||
25 |
namespace dynamicgraph { |
||
26 |
|||
27 |
/** Enum representing the different kind of messages. |
||
28 |
*/ |
||
29 |
enum MsgType { |
||
30 |
MSG_TYPE_TYPE_BITS = 1 << 0 | 1 << 1 | 1 << 2 | 1 << 3, // 15 |
||
31 |
MSG_TYPE_STREAM_BIT = 1 << 4, // 16 |
||
32 |
|||
33 |
MSG_TYPE_DEBUG = 1 << 3, // 1 |
||
34 |
MSG_TYPE_INFO = 1 << 2, // 2 |
||
35 |
MSG_TYPE_WARNING = 1 << 1, // 4 |
||
36 |
MSG_TYPE_ERROR = 1 << 0, // 8 |
||
37 |
MSG_TYPE_DEBUG_STREAM = MSG_TYPE_DEBUG | MSG_TYPE_STREAM_BIT, // 17 |
||
38 |
MSG_TYPE_INFO_STREAM = MSG_TYPE_INFO | MSG_TYPE_STREAM_BIT, // 18 |
||
39 |
MSG_TYPE_WARNING_STREAM = MSG_TYPE_WARNING | MSG_TYPE_STREAM_BIT, // 20 |
||
40 |
MSG_TYPE_ERROR_STREAM = MSG_TYPE_ERROR | MSG_TYPE_STREAM_BIT // 24 |
||
41 |
}; |
||
42 |
} // namespace dynamicgraph |
||
43 |
|||
44 |
/* --------------------------------------------------------------------- */ |
||
45 |
/* --- INCLUDE --------------------------------------------------------- */ |
||
46 |
/* --------------------------------------------------------------------- */ |
||
47 |
|||
48 |
#include <map> |
||
49 |
/// \todo These 3 headers should be removed. |
||
50 |
#include <dynamic-graph/linear-algebra.h> |
||
51 |
#include <dynamic-graph/real-time-logger-def.h> |
||
52 |
|||
53 |
#include <boost/assign.hpp> |
||
54 |
#include <boost/preprocessor/stringize.hpp> |
||
55 |
#include <dynamic-graph/deprecated.hh> |
||
56 |
#include <fstream> |
||
57 |
#include <iomanip> // std::setprecision |
||
58 |
#include <sstream> |
||
59 |
|||
60 |
namespace dynamicgraph { |
||
61 |
|||
62 |
//#define LOGGER_VERBOSITY_INFO_WARNING_ERROR |
||
63 |
#define LOGGER_VERBOSITY_ALL |
||
64 |
|||
65 |
#define SEND_MSG(msg, type) \ |
||
66 |
sendMsg(msg, type, __FILE__ ":" BOOST_PP_STRINGIZE(__LINE__)) |
||
67 |
|||
68 |
#define SEND_DEBUG_STREAM_MSG(msg) SEND_MSG(msg, MSG_TYPE_DEBUG_STREAM) |
||
69 |
#define SEND_INFO_STREAM_MSG(msg) SEND_MSG(msg, MSG_TYPE_INFO_STREAM) |
||
70 |
#define SEND_WARNING_STREAM_MSG(msg) SEND_MSG(msg, MSG_TYPE_WARNING_STREAM) |
||
71 |
#define SEND_ERROR_STREAM_MSG(msg) SEND_MSG(msg, MSG_TYPE_ERROR_STREAM) |
||
72 |
|||
73 |
#define _DYNAMIC_GRAPH_ENTITY_MSG(entity, type) \ |
||
74 |
(entity).logger().stream(type, __FILE__ BOOST_PP_STRINGIZE(__LINE__)) |
||
75 |
|||
76 |
#define DYNAMIC_GRAPH_ENTITY_DEBUG(entity) \ |
||
77 |
_DYNAMIC_GRAPH_ENTITY_MSG(entity, MSG_TYPE_DEBUG) |
||
78 |
#define DYNAMIC_GRAPH_ENTITY_INFO(entity) \ |
||
79 |
_DYNAMIC_GRAPH_ENTITY_MSG(entity, MSG_TYPE_INFO) |
||
80 |
#define DYNAMIC_GRAPH_ENTITY_WARNING(entity) \ |
||
81 |
_DYNAMIC_GRAPH_ENTITY_MSG(entity, MSG_TYPE_WARNING) |
||
82 |
#define DYNAMIC_GRAPH_ENTITY_ERROR(entity) \ |
||
83 |
_DYNAMIC_GRAPH_ENTITY_MSG(entity, MSG_TYPE_ERROR) |
||
84 |
|||
85 |
#define DYNAMIC_GRAPH_ENTITY_DEBUG_STREAM(entity) \ |
||
86 |
_DYNAMIC_GRAPH_ENTITY_MSG(entity, MSG_TYPE_DEBUG_STREAM) |
||
87 |
#define DYNAMIC_GRAPH_ENTITY_INFO_STREAM(entity) \ |
||
88 |
_DYNAMIC_GRAPH_ENTITY_MSG(entity, MSG_TYPE_INFO_STREAM) |
||
89 |
#define DYNAMIC_GRAPH_ENTITY_WARNING_STREAM(entity) \ |
||
90 |
_DYNAMIC_GRAPH_ENTITY_MSG(entity, MSG_TYPE_WARNING_STREAM) |
||
91 |
#define DYNAMIC_GRAPH_ENTITY_ERROR_STREAM(entity) \ |
||
92 |
_DYNAMIC_GRAPH_ENTITY_MSG(entity, MSG_TYPE_ERROR_STREAM) |
||
93 |
|||
94 |
template <typename T> |
||
95 |
40000 |
std::string toString(const T &v, const int precision = 3, |
|
96 |
const int width = -1) { |
||
97 |
✓✗ | 80000 |
std::stringstream ss; |
98 |
✗✓ | 40000 |
if (width > precision) |
99 |
ss << std::fixed << std::setw(width) << std::setprecision(precision) << v; |
||
100 |
else |
||
101 |
✓✗✓✗ ✓✗ |
40000 |
ss << std::fixed << std::setprecision(precision) << v; |
102 |
✓✗ | 80000 |
return ss.str(); |
103 |
} |
||
104 |
|||
105 |
template <typename T> |
||
106 |
20000 |
std::string toString(const std::vector<T> &v, const int precision = 3, |
|
107 |
const int width = -1, const std::string separator = ", ") { |
||
108 |
✓✗ | 40000 |
std::stringstream ss; |
109 |
✓✓ | 20000 |
if (width > precision) { |
110 |
✓✓ | 30000 |
for (unsigned int i = 0; i < v.size() - 1; i++) |
111 |
✓✗✓✗ ✓✗ |
20000 |
ss << std::fixed << std::setw(width) << std::setprecision(precision) |
112 |
✓✗✓✗ |
20000 |
<< v[i] << separator; |
113 |
✓✗✓✗ ✓✗ |
10000 |
ss << std::fixed << std::setw(width) << std::setprecision(precision) |
114 |
✓✗ | 10000 |
<< v[v.size() - 1]; |
115 |
} else { |
||
116 |
✓✓ | 30000 |
for (unsigned int i = 0; i < v.size() - 1; i++) |
117 |
✓✗✓✗ ✓✗✓✗ |
20000 |
ss << std::fixed << std::setprecision(precision) << v[i] << separator; |
118 |
✓✗✓✗ ✓✗ |
10000 |
ss << std::fixed << std::setprecision(precision) << v[v.size() - 1]; |
119 |
} |
||
120 |
|||
121 |
✓✗ | 40000 |
return ss.str(); |
122 |
} |
||
123 |
|||
124 |
template <typename T> |
||
125 |
std::string toString(const Eigen::MatrixBase<T> &v, const int precision = 3, |
||
126 |
const int width = -1, const std::string separator = ", ") { |
||
127 |
std::stringstream ss; |
||
128 |
if (width > precision) { |
||
129 |
for (unsigned int i = 0; i < v.size() - 1; i++) |
||
130 |
ss << std::fixed << std::setw(width) << std::setprecision(precision) |
||
131 |
<< v[i] << separator; |
||
132 |
ss << std::fixed << std::setw(width) << std::setprecision(precision) |
||
133 |
<< v[v.size() - 1]; |
||
134 |
} else { |
||
135 |
for (unsigned int i = 0; i < v.size() - 1; i++) |
||
136 |
ss << std::fixed << std::setprecision(precision) << v[i] << separator; |
||
137 |
ss << std::setprecision(precision) << v[v.size() - 1]; |
||
138 |
} |
||
139 |
|||
140 |
return ss.str(); |
||
141 |
} |
||
142 |
|||
143 |
enum LoggerVerbosity { |
||
144 |
VERBOSITY_ALL = MSG_TYPE_DEBUG, |
||
145 |
VERBOSITY_INFO_WARNING_ERROR = MSG_TYPE_INFO, |
||
146 |
VERBOSITY_WARNING_ERROR = MSG_TYPE_WARNING, |
||
147 |
VERBOSITY_ERROR = MSG_TYPE_ERROR, |
||
148 |
VERBOSITY_NONE = 0 |
||
149 |
}; |
||
150 |
|||
151 |
/// \ingroup debug |
||
152 |
/// |
||
153 |
/// \brief Class for logging messages |
||
154 |
/// |
||
155 |
/// It is intended to be used like this: |
||
156 |
/// \code |
||
157 |
/// #define ENABLE_RT_LOG |
||
158 |
/// #include <dynamic-graph/real-time-logger.h> |
||
159 |
/// |
||
160 |
/// // Somewhere in the main function of your executable |
||
161 |
/// int main (int argc, char** argv) { |
||
162 |
/// std::ofstream of; |
||
163 |
/// of.open("/tmp/dg-LOGS.txt",std::ofstream::out|std::ofstream::app); |
||
164 |
/// dgADD_OSTREAM_TO_RTLOG (of); |
||
165 |
/// } |
||
166 |
/// |
||
167 |
/// // Somewhere in your library |
||
168 |
/// dynamicgraph::LoggerVerbosity aLoggerVerbosityLevel = |
||
169 |
/// VERBOSITY_WARNING_ERROR; |
||
170 |
/// entity.setLoggerVerbosityLevel(aLoggerVerbosityLevel); |
||
171 |
/// ... |
||
172 |
/// // using macros |
||
173 |
/// DYNAMIC_GRAPH_ENTITY_WARNING(entity) << "your message\n"; |
||
174 |
/// |
||
175 |
/// // or the equivalent code without macros: |
||
176 |
/// // Please use '\n' instead of std::endl and flushing will have no effect |
||
177 |
/// entity.logger.stream(dynamicgraph::MSG_TYPE_WARNING, |
||
178 |
/// __FILE__ BOOST_PP_STRINGIZE(__LINE__)) |
||
179 |
/// << your message << '\n'; |
||
180 |
/// |
||
181 |
/// \endcode |
||
182 |
/// |
||
183 |
/// \todo remove m_timeSample and streamPrintPeriod to rather use a simple |
||
184 |
/// integer counting the number of calls. This will achieve exactly the |
||
185 |
/// same behaviour without rouding numerical errors. |
||
186 |
class Logger { |
||
187 |
public: |
||
188 |
/** Constructor */ |
||
189 |
Logger(double timeSample = 0.001, double streamPrintPeriod = 1.0); |
||
190 |
|||
191 |
/** Destructor */ |
||
192 |
~Logger(); |
||
193 |
|||
194 |
/** Method to be called at every control iteration |
||
195 |
* to decrement the internal Logger's counter. */ |
||
196 |
void countdown(); |
||
197 |
|||
198 |
/** Get an output stream independently of the debug level. |
||
199 |
*/ |
||
200 |
10000 |
RTLoggerStream stream() { |
|
201 |
10000 |
return ::dynamicgraph::RealTimeLogger::instance().front(); |
|
202 |
} |
||
203 |
|||
204 |
/** Print the specified message on standard output if the verbosity level |
||
205 |
* allows it. The lineId is used to identify the point where sendMsg is |
||
206 |
* called so that streaming messages are printed only every streamPrintPeriod |
||
207 |
* iterations. |
||
208 |
* \param type specifies the verbosity level, for instance MSG_TYPE_DEBUG |
||
209 |
* \param lineId typically __FILE__ ":" BOOST_PP_STRINGIZE(__LINE__) |
||
210 |
*/ |
||
211 |
150020 |
RTLoggerStream stream(MsgType type, const std::string &lineId = "") { |
|
212 |
150020 |
RealTimeLogger &rtlogger = ::dynamicgraph::RealTimeLogger::instance(); |
|
213 |
✓✓ | 150020 |
if (acceptMsg(type, lineId)) return rtlogger.front(); |
214 |
25210 |
return rtlogger.emptyStream(); |
|
215 |
} |
||
216 |
|||
217 |
/** \deprecated instead, use |
||
218 |
* \code |
||
219 |
* stream(type, lineId) << msg << '\n'; |
||
220 |
* \endcode |
||
221 |
*/ |
||
222 |
[[deprecated("use stream(type, lineId) << msg")]] void sendMsg( |
||
223 |
std::string msg, MsgType type, const std::string &lineId = ""); |
||
224 |
|||
225 |
/** \deprecated instead, use |
||
226 |
* \code |
||
227 |
* stream(type, lineId) << msg << '\n'; |
||
228 |
* \endcode |
||
229 |
*/ |
||
230 |
[[deprecated("use stream(type, lineId) << msg")]] void sendMsg( |
||
231 |
std::string msg, MsgType type, const std::string &file, int line); |
||
232 |
|||
233 |
/** Set the sampling time at which the method countdown() |
||
234 |
* is going to be called. */ |
||
235 |
bool setTimeSample(double t); |
||
236 |
|||
237 |
/** Get the sampling time at which the method countdown() |
||
238 |
* is going to be called. */ |
||
239 |
double getTimeSample(); |
||
240 |
|||
241 |
/** Set the time period for printing of streaming messages. */ |
||
242 |
bool setStreamPrintPeriod(double s); |
||
243 |
|||
244 |
/** Get the time period for printing of streaming messages. */ |
||
245 |
double getStreamPrintPeriod(); |
||
246 |
|||
247 |
/** Set the verbosity level of the logger. */ |
||
248 |
void setVerbosity(LoggerVerbosity lv); |
||
249 |
|||
250 |
/** Get the verbosity level of the logger. */ |
||
251 |
LoggerVerbosity getVerbosity(); |
||
252 |
|||
253 |
protected: |
||
254 |
LoggerVerbosity m_lv; /// verbosity of the logger |
||
255 |
double m_timeSample; |
||
256 |
/// specify the period of call of the countdown method |
||
257 |
double m_streamPrintPeriod; /// specify the time period of the stream prints |
||
258 |
double m_printCountdown; |
||
259 |
/// every time this is < 0 (i.e. every _streamPrintPeriod sec) print stuff |
||
260 |
|||
261 |
typedef std::map<std::string, double> StreamCounterMap_t; |
||
262 |
/** Pointer to the dynamic structure which holds |
||
263 |
the collection of streaming messages */ |
||
264 |
StreamCounterMap_t m_stream_msg_counters; |
||
265 |
|||
266 |
128010 |
inline bool isStreamMsg(MsgType m) { return (m & MSG_TYPE_STREAM_BIT); } |
|
267 |
|||
268 |
/** Check whether a message of type \p m and from \p c lineId should be |
||
269 |
* accepted. \note If \p m is a stream type, the internal counter associated |
||
270 |
* to \p lineId is updated. |
||
271 |
*/ |
||
272 |
150020 |
bool acceptMsg(MsgType m, const std::string &lineId) { |
|
273 |
// If more verbose than the current verbosity level |
||
274 |
✓✓ | 150020 |
if ((m & MSG_TYPE_TYPE_BITS) > m_lv) return false; |
275 |
|||
276 |
// if print is allowed by current verbosity level |
||
277 |
✓✓ | 128010 |
if (isStreamMsg(m)) return checkStreamPeriod(lineId); |
278 |
84010 |
return true; |
|
279 |
} |
||
280 |
|||
281 |
/** Check whether a message from \c lineId should be accepted. |
||
282 |
* \note The internal counter associated to \c lineId is updated. |
||
283 |
*/ |
||
284 |
bool checkStreamPeriod(const std::string &lineId); |
||
285 |
}; |
||
286 |
|||
287 |
} // namespace dynamicgraph |
||
288 |
|||
289 |
#endif // #ifndef __sot_torque_control_logger_H__ |
Generated by: GCOVR (Version 4.2) |