GNU Radio Manual and C++ API Reference  3.10.9.1
The Free & Open Software Radio Ecosystem
logger.h
Go to the documentation of this file.
1 /* -*- c++ -*- */
2 /*
3  * Copyright 2012-2013 Free Software Foundation, Inc.
4  * Copyright 2021,2022 Marcus Müller
5  *
6  * This file is part of GNU Radio
7  *
8  * SPDX-License-Identifier: GPL-3.0-or-later
9  *
10  */
11 
12 #ifndef INCLUDED_GR_LOGGER_H
13 #define INCLUDED_GR_LOGGER_H
14 
15 /*!
16  * \ingroup logging
17  * \brief GNU Radio logging wrapper
18  *
19  */
20 #ifdef DISABLE_LOGGER_H
21 // pygccxml as of v2.2.1 has a difficult time parsing headers that
22 // include spdlog or format
23 // Since it only needs the top level header info, this is a hack to not
24 // transitively include anything logger related when parsing the
25 // headers
26 #include <memory>
27 namespace gr {
28 using logger_ptr = std::shared_ptr<void>;
29 }
30 #else
31 
32 // Since this file is included in *all* gr::blocks, please make sure this list of includes
33 // keeps as short as possible; if anything is needed only by the implementation in
34 // buffer.cc, then only include it there
35 #include <gnuradio/api.h>
36 #include <spdlog/common.h> /* important to include before spdlog/fmt/anything.h,
37  * see https://github.com/gabime/spdlog/issues/2922 */
38 #include <spdlog/fmt/fmt.h>
39 #include <spdlog/fmt/ostr.h>
40 #include <spdlog/version.h>
41 #include <memory>
42 
43 #include <spdlog/spdlog.h>
44 
45 #include <spdlog/sinks/dist_sink.h>
46 
47 #include <boost/format.hpp>
48 
49 namespace gr {
50 using log_level = spdlog::level::level_enum;
51 
53 {
54 public:
55  /* \brief deleted copy constructor
56  * get your own logging system, or, more likely, use the singleton.
57  */
58  logging(logging const&) = delete;
59 
60  // \brief deleted assignment operator
61  void operator=(logging const&) = delete;
62 
63  // \brief singleton to access the one logging system
64  static logging& singleton();
65 
66  //! \brief get the default logging level
67  inline log_level default_level() const { return _default_backend->level(); }
68 
69  //! \brief get the debug logging level
70  inline log_level debug_level() const { return _debug_backend->level(); }
71 
72  //! \brief set the default logging level
74 
75  //! \brief set the debug logging level
77 
78  spdlog::sink_ptr default_backend() const;
79  //! \brief adds a logging sink
80  void add_default_sink(const spdlog::sink_ptr& sink);
81  //! \brief adds a debugging sink
82  void add_debug_sink(const spdlog::sink_ptr& sink);
83  //! \brief add a default-constructed console sink to the default logger
85  //! \brief add a default-constructed console sink to the debugging logger
87 
88  static constexpr const char* default_pattern = "%n :%l: %v";
89 
90 private:
91  logging();
92  std::shared_ptr<spdlog::sinks::dist_sink_mt> _default_backend, _debug_backend;
93 };
94 
95 /*!
96  * \brief GR_LOG macros
97  * \ingroup logging
98  *
99  * These macros wrap the standard LOG4CPP_LEVEL macros. The available macros
100  * are:
101  * LOG_DEBUG
102  * LOG_INFO
103  * LOG_WARN
104  * LOG_TRACE
105  * LOG_ERROR
106  * LOG_ALERT
107  * LOG_CRIT
108  * LOG_FATAL
109  * LOG_EMERG
110  */
111 
112 /********************* Start Classes and Methods for Python ******************/
113 /*!
114  * \brief Logger class for referencing loggers in python. Not
115  * needed in C++ (use macros) Wraps and manipulates loggers for
116  * python as python has no macros
117  * \ingroup logging
118  *
119  */
121 {
122 private:
123  /*! \brief pointer to logger associated with this wrapper class */
124  std::string _name;
125  using underlying_logger_ptr = std::shared_ptr<spdlog::logger>;
126 
127 #if SPDLOG_VERSION >= 11000
128  // spdlog 1.10 onwards can depend either on fmt or std format, so it defined
129  // its own alias for format strings
130  template <typename... Args>
131  using format_string_t = spdlog::format_string_t<Args...>;
132 #elif SPDLOG_VERSION >= 10910
133  // spdlog 1.9.1 supported/enforced fmt compile time format string validation
134  // in c++20 by using fmt::format_string in its logging functions
135  template <typename... Args>
136  using format_string_t = fmt::format_string<Args...>;
137 #else
138  // lower versions of spdlog did not support compile time validation
139  template <typename... Args>
140  using format_string_t = const spdlog::string_view_t&;
141 #endif
142 
143 public:
144  /*!
145  * \brief constructor Provide name of logger to associate with this class
146  * \param logger_name Name of logger associated with class
147  *
148  * Creates a new logger. Loggers inherit the logging level (through `gr.prefs` or
149  * through `gr::logging::singleton().set_default_level()`) that is set at the time of
150  * their creation.
151  */
152  logger(const std::string& logger_name);
153 
154  /*! \brief Destructor */
155  // FIXME implement or = default
156  ~logger() = default;
157 
158  underlying_logger_ptr d_logger;
159 
160  // Wrappers for logging macros
161  /*! \brief inline function, wrapper to set the logger level */
162  void set_level(const std::string& level);
163  void set_level(const log_level level);
164 
165  /*! \brief inline function, wrapper to get the logger level */
166  void get_level(std::string& level) const;
167  const std::string get_string_level() const;
169 
170  const std::string& name() const;
171  void set_name(const std::string& name);
172 
173  /*! \brief inline function, wrapper for TRACE message */
174  template <typename... Args>
175  inline void trace(format_string_t<Args...> msg, Args&&... args)
176  {
177  d_logger->trace(msg, std::forward<Args>(args)...);
178  }
179 
180  /*! \brief inline function, wrapper for DEBUG message */
181  template <typename... Args>
182  inline void debug(format_string_t<Args...> msg, Args&&... args)
183  {
184  d_logger->debug(msg, std::forward<Args>(args)...);
185  }
186 
187  /*! \brief inline function, wrapper for INFO message */
188  template <typename... Args>
189  inline void info(format_string_t<Args...> msg, Args&&... args)
190  {
191  d_logger->info(msg, std::forward<Args>(args)...);
192  }
193 
194  /*! \brief inline function, wrapper for INFO message, DEPRECATED */
195  template <typename... Args>
196  inline void notice(format_string_t<Args...> msg, Args&&... args)
197  {
198  d_logger->info(msg, std::forward<Args>(args)...);
199  }
200 
201  /*! \brief inline function, wrapper for WARN message */
202  template <typename... Args>
203  inline void warn(format_string_t<Args...> msg, Args&&... args)
204  {
205  d_logger->warn(msg, std::forward<Args>(args)...);
206  }
207 
208  /*! \brief inline function, wrapper for ERROR message */
209  template <typename... Args>
210  inline void error(format_string_t<Args...> msg, Args&&... args)
211  {
212  d_logger->error(msg, std::forward<Args>(args)...);
213  }
214 
215  /*! \brief inline function, wrapper for CRITICAL message */
216  template <typename... Args>
217  inline void crit(format_string_t<Args...> msg, Args&&... args)
218  {
219  d_logger->critical(msg, std::forward<Args>(args)...);
220  }
221 
222  /*! \brief inline function, wrapper for CRITICAL message, DEPRECATED */
223  template <typename... Args>
224  inline void alert(format_string_t<Args...> msg, Args&&... args)
225  {
226  d_logger->critical(msg, std::forward<Args>(args)...);
227  }
228 
229  /*! \brief inline function, wrapper for CRITICAL message, DEPRECATED */
230  template <typename... Args>
231  inline void fatal(format_string_t<Args...> msg, Args&&... args)
232  {
233  d_logger->critical(msg, std::forward<Args>(args)...);
234  }
235 
236  /*! \brief inline function, wrapper for CRITICAL message, DEPRECATED */
237  template <typename... Args>
238  inline void emerg(format_string_t<Args...> msg, Args&&... args)
239  {
240  d_logger->critical(msg, std::forward<Args>(args)...);
241  }
242  /*! \brief inline function, wrapper for logging with ad-hoc adjustable level*/
243  template <typename... Args>
244  inline void
245  log(spdlog::level::level_enum level, format_string_t<Args...> msg, Args&&... args)
246  {
247  d_logger->log(level, msg, std::forward<Args>(args)...);
248  }
249 };
250 using logger_ptr = std::shared_ptr<logger>;
251 
252 /*!
253  * Function to use the GR prefs files to get and setup the two
254  * default loggers defined there. The loggers are unique to the
255  * class in which they are called, and we pass it the \p name to
256  * identify where the log message originates from. For a GNU Radio
257  * block, we use 'alias()' for this value, and this is set up for us
258  * automatically in gr::block.
259  */
260 GR_RUNTIME_API bool
261 configure_default_loggers(gr::logger_ptr& l, gr::logger_ptr& d, const std::string& name);
262 
263 } /* namespace gr */
264 
265 // global logging shorthands
266 
267 #define GR_LOG_TRACE(log, msg) \
268  { \
269  log->d_logger->trace(msg); \
270  }
271 
272 #define GR_LOG_DEBUG(log, msg) \
273  { \
274  log->d_logger->debug(msg); \
275  }
276 
277 #define GR_LOG_INFO(log, msg) \
278  { \
279  log->d_logger->info(msg); \
280  }
281 
282 #define GR_LOG_NOTICE(log, msg) \
283  { \
284  log->d_logger->info(msg); \
285  }
286 
287 
288 #define GR_LOG_WARN(log, msg) \
289  { \
290  log->d_logger->warn(msg); \
291  }
292 
293 #define GR_LOG_ERROR(log, msg) \
294  { \
295  log->d_logger->error(msg); \
296  }
297 
298 #define GR_LOG_CRIT(log, msg) \
299  { \
300  log->d_logger->critical(msg); \
301  }
302 
303 #define GR_LOG_ALERT(log, msg) \
304  { \
305  log->d_logger->critical(msg); \
306  }
307 
308 #define GR_LOG_FATAL(log, msg) \
309  { \
310  log->d_logger->critical(msg); \
311  }
312 
313 #define GR_LOG_EMERG(log, msg) \
314  { \
315  log->d_logger->critical(msg); \
316  }
317 
318 // Helper class to allow passing of boost::format to fmt
319 template <>
320 struct fmt::formatter<boost::format> : formatter<string_view> {
321  // parse is inherited from formatter<string_view>.
322  template <typename FormatContext>
323  auto format(const boost::format& bfmt, FormatContext& ctx)
324  -> decltype(formatter<string_view>::format(bfmt.str(), ctx))
325  {
326  return formatter<string_view>::format(bfmt.str(), ctx);
327  }
328 };
329 
330 #endif
331 
332 #endif /* INCLUDED_GR_LOGGER_H */
GR_LOG macros.
Definition: logger.h:121
void alert(format_string_t< Args... > msg, Args &&... args)
inline function, wrapper for CRITICAL message, DEPRECATED
Definition: logger.h:224
void set_name(const std::string &name)
const std::string & name() const
void get_level(std::string &level) const
inline function, wrapper to get the logger level
void error(format_string_t< Args... > msg, Args &&... args)
inline function, wrapper for ERROR message
Definition: logger.h:210
void trace(format_string_t< Args... > msg, Args &&... args)
inline function, wrapper for TRACE message
Definition: logger.h:175
void log(spdlog::level::level_enum level, format_string_t< Args... > msg, Args &&... args)
inline function, wrapper for logging with ad-hoc adjustable level
Definition: logger.h:245
~logger()=default
Destructor.
underlying_logger_ptr d_logger
Definition: logger.h:158
void crit(format_string_t< Args... > msg, Args &&... args)
inline function, wrapper for CRITICAL message
Definition: logger.h:217
void info(format_string_t< Args... > msg, Args &&... args)
inline function, wrapper for INFO message
Definition: logger.h:189
void debug(format_string_t< Args... > msg, Args &&... args)
inline function, wrapper for DEBUG message
Definition: logger.h:182
logger(const std::string &logger_name)
constructor Provide name of logger to associate with this class
void set_level(const log_level level)
void notice(format_string_t< Args... > msg, Args &&... args)
inline function, wrapper for INFO message, DEPRECATED
Definition: logger.h:196
void set_level(const std::string &level)
inline function, wrapper to set the logger level
void fatal(format_string_t< Args... > msg, Args &&... args)
inline function, wrapper for CRITICAL message, DEPRECATED
Definition: logger.h:231
void emerg(format_string_t< Args... > msg, Args &&... args)
inline function, wrapper for CRITICAL message, DEPRECATED
Definition: logger.h:238
log_level get_level() const
const std::string get_string_level() const
void warn(format_string_t< Args... > msg, Args &&... args)
inline function, wrapper for WARN message
Definition: logger.h:203
Definition: logger.h:53
void set_default_level(log_level level)
set the default logging level
void add_default_sink(const spdlog::sink_ptr &sink)
adds a logging sink
spdlog::sink_ptr default_backend() const
void operator=(logging const &)=delete
void add_default_console_sink()
add a default-constructed console sink to the default logger
logging(logging const &)=delete
void add_debug_console_sink()
add a default-constructed console sink to the debugging logger
void set_debug_level(log_level level)
set the debug logging level
log_level debug_level() const
get the debug logging level
Definition: logger.h:70
static logging & singleton()
void add_debug_sink(const spdlog::sink_ptr &sink)
adds a debugging sink
log_level default_level() const
get the default logging level
Definition: logger.h:67
#define GR_RUNTIME_API
Definition: gnuradio-runtime/include/gnuradio/api.h:18
GR_RUNTIME_API const pmt::pmt_t msg()
GNU Radio logging wrapper.
Definition: basic_block.h:29
std::shared_ptr< logger > logger_ptr
Definition: logger.h:250
GR_RUNTIME_API bool configure_default_loggers(gr::logger_ptr &l, gr::logger_ptr &d, const std::string &name)
spdlog::level::level_enum log_level
Definition: logger.h:50
auto format(const boost::format &bfmt, FormatContext &ctx) -> decltype(formatter< string_view >::format(bfmt.str(), ctx))
Definition: logger.h:323
fmt::format_context::iterator format(const gr::io_signature &iosig, format_context &ctx) const