BitShares-Core  4.0.0
BitShares blockchain implementation and command-line interface software
logger.hpp
Go to the documentation of this file.
1 #pragma once
2 #include <fc/config.hpp>
3 #include <fc/time.hpp>
4 #include <fc/log/appender.hpp>
5 #include <fc/log/log_message.hpp>
6 #include <cstddef>
7 #include <memory>
8 
9 namespace fc
10 {
21  class logger
22  {
23  public:
24  static logger get( const std::string& name = "default");
25 
26  logger();
27  logger( const string& name, const logger& parent = nullptr );
28  logger( std::nullptr_t );
29  logger( const logger& c );
30  logger( logger&& c );
31  ~logger();
32  logger& operator=(const logger&);
33  logger& operator=(logger&&);
34  friend bool operator==( const logger&, std::nullptr_t );
35  friend bool operator!=( const logger&, std::nullptr_t );
36 
37  logger& set_log_level( log_level e );
38  log_level get_log_level()const;
39  logger& set_parent( const logger& l );
40  logger get_parent()const;
41 
42  void set_name( const std::string& n );
43  const std::string& name()const;
44 
45  void add_appender( const appender::ptr& a );
46  std::vector<appender::ptr> get_appenders()const;
47  void remove_appender( const appender::ptr& a );
48 
49  bool is_enabled( log_level e )const;
50  void log( log_message m );
51 
52  private:
53  class impl;
54  std::shared_ptr<impl> my;
55  };
56 
57 } // namespace fc
58 
59 #ifndef DEFAULT_LOGGER
60 #define DEFAULT_LOGGER
61 #endif
62 
63 // suppress warning "conditional expression is constant" in the while(0) for visual c++
64 // http://cnicholson.net/2009/03/stupid-c-tricks-dowhile0-and-c4127/
65 #define FC_MULTILINE_MACRO_BEGIN do {
66 #ifdef _MSC_VER
67 # define FC_MULTILINE_MACRO_END \
68  __pragma(warning(push)) \
69  __pragma(warning(disable:4127)) \
70  } while (0) \
71  __pragma(warning(pop))
72 #else
73 # define FC_MULTILINE_MACRO_END } while (0)
74 #endif
75 
76 #define fc_dlog( LOGGER, FORMAT, ... ) \
77  FC_MULTILINE_MACRO_BEGIN \
78  if( (LOGGER).is_enabled( fc::log_level::debug ) ) \
79  (LOGGER).log( FC_LOG_MESSAGE( debug, FORMAT, __VA_ARGS__ ) ); \
80  FC_MULTILINE_MACRO_END
81 
82 #define fc_ilog( LOGGER, FORMAT, ... ) \
83  FC_MULTILINE_MACRO_BEGIN \
84  if( (LOGGER).is_enabled( fc::log_level::info ) ) \
85  (LOGGER).log( FC_LOG_MESSAGE( info, FORMAT, __VA_ARGS__ ) ); \
86  FC_MULTILINE_MACRO_END
87 
88 #define fc_wlog( LOGGER, FORMAT, ... ) \
89  FC_MULTILINE_MACRO_BEGIN \
90  if( (LOGGER).is_enabled( fc::log_level::warn ) ) \
91  (LOGGER).log( FC_LOG_MESSAGE( warn, FORMAT, __VA_ARGS__ ) ); \
92  FC_MULTILINE_MACRO_END
93 
94 #define fc_elog( LOGGER, FORMAT, ... ) \
95  FC_MULTILINE_MACRO_BEGIN \
96  if( (LOGGER).is_enabled( fc::log_level::error ) ) \
97  (LOGGER).log( FC_LOG_MESSAGE( error, FORMAT, __VA_ARGS__ ) ); \
98  FC_MULTILINE_MACRO_END
99 
100 #define dlog( FORMAT, ... ) \
101  FC_MULTILINE_MACRO_BEGIN \
102  if( (fc::logger::get(DEFAULT_LOGGER)).is_enabled( fc::log_level::debug ) ) \
103  (fc::logger::get(DEFAULT_LOGGER)).log( FC_LOG_MESSAGE( debug, FORMAT, __VA_ARGS__ ) ); \
104  FC_MULTILINE_MACRO_END
105 
110 #define ulog( FORMAT, ... ) \
111  FC_MULTILINE_MACRO_BEGIN \
112  if( (fc::logger::get("user")).is_enabled( fc::log_level::debug ) ) \
113  (fc::logger::get("user")).log( FC_LOG_MESSAGE( debug, FORMAT, __VA_ARGS__ ) ); \
114  FC_MULTILINE_MACRO_END
115 
116 
117 #define ilog( FORMAT, ... ) \
118  FC_MULTILINE_MACRO_BEGIN \
119  if( (fc::logger::get(DEFAULT_LOGGER)).is_enabled( fc::log_level::info ) ) \
120  (fc::logger::get(DEFAULT_LOGGER)).log( FC_LOG_MESSAGE( info, FORMAT, __VA_ARGS__ ) ); \
121  FC_MULTILINE_MACRO_END
122 
123 #define wlog( FORMAT, ... ) \
124  FC_MULTILINE_MACRO_BEGIN \
125  if( (fc::logger::get(DEFAULT_LOGGER)).is_enabled( fc::log_level::warn ) ) \
126  (fc::logger::get(DEFAULT_LOGGER)).log( FC_LOG_MESSAGE( warn, FORMAT, __VA_ARGS__ ) ); \
127  FC_MULTILINE_MACRO_END
128 
129 #define elog( FORMAT, ... ) \
130  FC_MULTILINE_MACRO_BEGIN \
131  if( (fc::logger::get(DEFAULT_LOGGER)).is_enabled( fc::log_level::error ) ) \
132  (fc::logger::get(DEFAULT_LOGGER)).log( FC_LOG_MESSAGE( error, FORMAT, __VA_ARGS__ ) ); \
133  FC_MULTILINE_MACRO_END
134 
135 #include <boost/preprocessor/seq/for_each.hpp>
136 #include <boost/preprocessor/seq/enum.hpp>
137 #include <boost/preprocessor/seq/size.hpp>
138 #include <boost/preprocessor/seq/seq.hpp>
139 #include <boost/preprocessor/stringize.hpp>
140 #include <boost/preprocessor/punctuation/paren.hpp>
141 
142 
143 #define FC_FORMAT_ARG(r, unused, base) \
144  BOOST_PP_STRINGIZE(base) ": ${" BOOST_PP_STRINGIZE( base ) "} "
145 
146 #define FC_FORMAT_ARGS(r, unused, base) \
147  BOOST_PP_LPAREN() BOOST_PP_STRINGIZE(base),fc::variant(base,FC_MAX_LOG_OBJECT_DEPTH) BOOST_PP_RPAREN()
148 
149 #define FC_FORMAT( SEQ )\
150  BOOST_PP_SEQ_FOR_EACH( FC_FORMAT_ARG, v, SEQ )
151 
152 // takes a ... instead of a SEQ arg because it can be called with an empty SEQ
153 // from FC_CAPTURE_AND_THROW()
154 #define FC_FORMAT_ARG_PARAMS( ... )\
155  BOOST_PP_SEQ_FOR_EACH( FC_FORMAT_ARGS, v, __VA_ARGS__ )
156 
157 #define FC_DUMP_FORMAT_ARG_NAME(r, unused, base) \
158  "(" BOOST_PP_STRINGIZE(base) ")"
159 
160 #define FC_DUMP_FORMAT_ARG_NAMES( SEQ )\
161  BOOST_PP_SEQ_FOR_EACH( FC_DUMP_FORMAT_ARG_NAME, v, SEQ )
162 
163 // TODO FC_FORMAT_ARG_PARAMS(...) may throw exceptions when calling fc::variant(...) inside,
164 // as a quick-fix / workaround, we catch all exceptions here.
165 // However, to log as much info as possible, it's better to catch exceptions when processing each argument
166 #define idump( SEQ ) \
167 { \
168  try { \
169  ilog( FC_FORMAT(SEQ), FC_FORMAT_ARG_PARAMS(SEQ) ); \
170  } catch( ... ) { \
171  ilog ( "[ERROR: Got exception while trying to dump ( ${args} )]",("args",FC_DUMP_FORMAT_ARG_NAMES(SEQ)) ); \
172  } \
173 }
174 #define wdump( SEQ ) \
175 { \
176  try { \
177  wlog( FC_FORMAT(SEQ), FC_FORMAT_ARG_PARAMS(SEQ) ); \
178  } catch( ... ) { \
179  wlog ( "[ERROR: Got exception while trying to dump ( ${args} )]",("args",FC_DUMP_FORMAT_ARG_NAMES(SEQ)) ); \
180  } \
181 }
182 #define edump( SEQ ) \
183 { \
184  try { \
185  elog( FC_FORMAT(SEQ), FC_FORMAT_ARG_PARAMS(SEQ) ); \
186  } catch( ... ) { \
187  elog ( "[ERROR: Got exception while trying to dump ( ${args} )]",("args",FC_DUMP_FORMAT_ARG_NAMES(SEQ)) ); \
188  } \
189 }
190 
191 // this disables all normal logging statements -- not something you'd normally want to do,
192 // but it's useful if you're benchmarking something and suspect logging is causing
193 // a slowdown.
194 #ifdef FC_DISABLE_LOGGING
195 # undef ulog
196 # define ulog(...) FC_MULTILINE_MACRO_BEGIN FC_MULTILINE_MACRO_END
197 # undef elog
198 # define elog(...) FC_MULTILINE_MACRO_BEGIN FC_MULTILINE_MACRO_END
199 # undef wlog
200 # define wlog(...) FC_MULTILINE_MACRO_BEGIN FC_MULTILINE_MACRO_END
201 # undef ilog
202 # define ilog(...) FC_MULTILINE_MACRO_BEGIN FC_MULTILINE_MACRO_END
203 # undef dlog
204 # define dlog(...) FC_MULTILINE_MACRO_BEGIN FC_MULTILINE_MACRO_END
205 #endif
Defines types and helper macros necessary for generating log messages.
void set_name(const std::string &n)
Definition: logger.cpp:74
void add_appender(const appender::ptr &a)
Definition: logger.cpp:99
logger & set_parent(const logger &l)
Definition: logger.cpp:94
const std::string & name() const
Definition: logger.cpp:75
friend bool operator!=(const logger &, std::nullptr_t)
Definition: logger.cpp:58
logger get_parent() const
Definition: logger.cpp:93
friend bool operator==(const logger &, std::nullptr_t)
Definition: logger.cpp:57
std::shared_ptr< appender > ptr
Definition: appender.hpp:30
log_level get_log_level() const
Definition: logger.cpp:96
void log(log_message m)
Definition: logger.cpp:64
logger & set_log_level(log_level e)
Definition: logger.cpp:97
std::vector< appender::ptr > get_appenders() const
Definition: logger.cpp:102
aggregates a message along with the context and associated meta-information.
bool is_enabled(log_level e) const
Definition: logger.cpp:60
Definition: api.hpp:15
logger & operator=(const logger &)
Definition: logger.cpp:49
void remove_appender(const appender::ptr &a)