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