GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: include/dynamic-graph/logger.h Lines: 28 29 96.6 %
Date: 2023-03-15 12:04:10 Branches: 36 68 52.9 %

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__