MessageLogger.h
Go to the documentation of this file.
1 #ifndef messagefacility_MessageLogger_MessageLogger_h
2 #define messagefacility_MessageLogger_MessageLogger_h
3 // vim: set sw=2 expandtab :
4 
7 
8 #include <memory>
9 #include <ostream>
10 #include <string>
11 #include <type_traits>
12 #include <utility>
13 
14 namespace fhicl {
15  class ParameterSet;
16 }
17 
18 namespace mf {
19 
20  // Start and stop the system.
21  // The system is still usable if StartMessageFacility has not been called, but
22  // it logs only to cerr and does not process any configuration options.
24  std::string const& applicationName = "");
25  void EndMessageFacility();
26 
27  // Will return true if StartMessageFacility has been called, and
28  // EndMessageFacility has not yet been called.
30 
31  // Log a message.
32  void LogErrorObj(ErrorObj*);
33 
34  // Log collected statistics to configured statistics destinations.
35  void LogStatistics();
36 
37  // OBSOLETE. Does nothing.
38  void FlushMessageLog();
39 
40  // These four set the system-wide values, but they can still be
41  // overridden on a per-message basis.
42  void SetApplicationName(std::string const&);
43  void SetHostName(std::string const&);
44  void SetHostAddr(std::string const&);
45  void SetPid(long);
46 
47  // These four set the system-wide values, but they can still be
48  // overridden on a per-message basis.
50  std::string const& GetHostName();
51  std::string const& GetHostAddr();
52  long GetPid();
53 
54  // What is printed in the message header as the iteration (either
55  // run/subrun/event number or phase), thread-local. Note: Obsolete! Remove
56  // when user code migrated.
57  void SetContextIteration(std::string const&);
58 
59  // What is printed in the message header as the iteration (either
60  // run/subrun/event number or phase), thread-local.
61  void SetIteration(std::string const&);
62 
63  // What is printed in the message header as the iteration (either
64  // run/subrun/event number or phase), thread-local.
65  std::string const& GetIteration();
66 
67  // What is printed in the message header as the module name, thread-local.
68  // Note: Obsolete! Remove when user code migrated.
69  void SetContextSinglet(std::string const&);
70 
71  // What is printed in the message header as the module name, thread-local.
72  void SetModuleName(std::string const&);
73 
74  // What is printed in the message header as the module name, thread-local.
75  std::string const& GetModuleName();
76 
77  // Obsolete! Delete these when user code migrated.
78  bool isDebugEnabled();
79  bool isInfoEnabled();
80  bool isWarningEnabled();
81 
82  class NeverLogger_ {
83  public:
84  // Dedicated function for char const* to avoid unnecessary
85  // template instantiations of char const[]. Will take precedence
86  // over the template version.
87  decltype(auto)
88  operator<<(char const*)
89  {
90  return std::forward<NeverLogger_>(*this);
91  }
92 
93  template <class T>
94  decltype(auto)
95  operator<<(T const&)
96  {
97  return std::forward<NeverLogger_>(*this);
98  }
99 
100  decltype(auto)
101  operator<<(std::ostream& (*)(std::ostream&))
102  {
103  return std::forward<NeverLogger_>(*this);
104  }
105  decltype(auto)
106  operator<<(std::ios_base& (*)(std::ios_base&))
107  {
108  return std::forward<NeverLogger_>(*this);
109  }
110  };
111 
112  template <ELseverityLevel::ELsev_ SEV, bool VERBATIM>
113  class MaybeLogger_ {
114  public:
115  MaybeLogger_(MaybeLogger_ const&) = delete;
116  MaybeLogger_& operator=(MaybeLogger_ const&) = delete;
117  MaybeLogger_& operator=(MaybeLogger_&&) = delete;
118 
120  {
121  if (msg_ == nullptr) {
122  return;
123  }
124  try {
125  msg_->setModule(GetModuleName());
126  msg_->setIteration(GetIteration());
127  LogErrorObj(msg_.release());
128  }
129  catch (...) {
130  // FIXME: We should never ignore errors!
131  }
132  }
133 
134  constexpr MaybeLogger_() noexcept = default;
135  MaybeLogger_(MaybeLogger_&& rhs) noexcept = default;
136 
138  std::string const& file = {},
139  int const line_number = 0)
140  {
141  // Verbatim messages have the full file path, otherwise just the basename.
143  if (!VERBATIM) {
144  auto const lastSlash = file.find_last_of('/');
145  if ((lastSlash != std::string::npos) &&
146  (lastSlash != (file.size() - 1))) {
147  filename = file.substr(lastSlash + 1, file.size() - lastSlash - 1);
148  }
149  }
150  msg_ = std::make_unique<ErrorObj>(
151  SEV, category, VERBATIM, filename, line_number);
152  }
153 
154  // Dedicated function for char const* to avoid unnecessary
155  // template instantiations of char const[]. Will take precedence
156  // over the template version.
157  decltype(auto)
158  operator<<(char const* s)
159  {
160  if (msg_) {
161  (*msg_) << s;
162  }
163  return std::forward<MaybeLogger_>(*this);
164  }
165 
166  template <class T>
167  decltype(auto)
168  operator<<(T const& t)
169  {
170  if (msg_) {
171  (*msg_) << t;
172  }
173  return std::forward<MaybeLogger_>(*this);
174  }
175 
176  decltype(auto)
177  operator<<(std::ostream& (*f)(std::ostream&))
178  {
179  if (msg_) {
180  (*msg_) << f;
181  }
182  return std::forward<MaybeLogger_>(*this);
183  }
184 
185  decltype(auto)
186  operator<<(std::ios_base& (*f)(std::ios_base&))
187  {
188  if (msg_) {
189  (*msg_) << f;
190  }
191  return std::forward<MaybeLogger_>(*this);
192  }
193 
194  private:
195  std::unique_ptr<ErrorObj> msg_{nullptr};
196  };
197 
198  //======================================================================
199  // Usage: LogXXX("category") << stuff. See also MF_LOG_XXX macros, below.
200  //
201  // Statements follow pattern:
202  // using LogXXX = MaybeLogger_<severity-level, verbatim>;
203  //
204  // Verbatim: "No-frills" formatting.
205  //======================================================================
206 
207  // Non-verbatim messages, standard decorations.
213 
214  // Verbatim messages, no decorations at all.
220 
221 } // namespace mf
222 
223 // Non-verbatim messages, standard decorations.
224 // Note: MF_LOG_DEBUG is below.
225 #define MF_LOG_INFO(category) \
226  mf::LogInfo { category, __FILE__, __LINE__ }
227 #define MF_LOG_WARNING(category) \
228  mf::LogWarning { category, __FILE__, __LINE__ }
229 #define MF_LOG_ERROR(category) \
230  mf::LogError { category, __FILE__, __LINE__ }
231 #define MF_LOG_SYSTEM(category) \
232  mf::LogSystem { category, __FILE__, __LINE__ }
233 
234 // Verbatim messages, no decorations at all.
235 // Note: MF_LOG_TRACE is below.
236 #define MF_LOG_VERBATIM(category) \
237  mf::LogVerbatim { category, __FILE__, __LINE__ }
238 #define MF_LOG_PRINT(category) \
239  mf::LogPrint { category, __FILE__, __LINE__ }
240 #define MF_LOG_PROBLEM(category) \
241  mf::LogProblem { category, __FILE__, __LINE__ }
242 #define MF_LOG_ABSOLUTE(category) \
243  mf::LogAbsolute { category, __FILE__, __LINE__ }
244 
245 #undef MF_SUPPRESS_LOG_DEBUG
246 
247 // Suppress MF_LOG_DEBUG/TRACE if NDEBUG or MF_NDEBUG are set,
248 // except see below for MF_DEBUG which takes precendence.
249 #if defined(NDEBUG) || defined(MF_NDEBUG)
250 #define MF_SUPPRESS_LOG_DEBUG
251 #endif // NDEBUG || MF_NDEBUG
252 
253 // If MF_DEBUG is defined, MF_LOG_DEBUG/TRACE are active unconditionally,
254 // no matter what NDEBUG or MF_NDEBUG say.
255 #ifdef MF_DEBUG
256 #undef MF_SUPPRESS_LOG_DEBUG
257 #endif // MF_DEBUG
258 
259 #ifdef MF_SUPPRESS_LOG_DEBUG
260 
261 #define MF_LOG_DEBUG(id) \
262  mf::NeverLogger_ {}
263 #define MF_LOG_TRACE(id) \
264  mf::NeverLogger_ {}
265 
266 #else // MF_SUPPRESS_LOG_DEBUG
267 
268 #define MF_LOG_DEBUG(id) \
269  mf::LogDebug { id, __FILE__, __LINE__ }
270 #define MF_LOG_TRACE(id) \
271  mf::LogTrace { id, __FILE__, __LINE__ }
272 
273 #endif // MF_SUPPRESS_LOG_DEBUG
274 
275 #undef MF_SUPPRESS_LOG_DEBUG
276 
277 #endif /* messagefacility_MessageLogger_MessageLogger_h */
278 
279 // Local Variables:
280 // mode: c++
281 // End:
void SetIteration(string const &val)
void SetHostAddr(string const &hostaddr)
void EndMessageFacility()
std::string string
Definition: nybbler.cc:12
string const & GetModuleName()
STL namespace.
string filename
Definition: train.py:213
void FlushMessageLog()
MaybeLogger_(std::string const &category, std::string const &file={}, int const line_number=0)
void SetContextIteration(string const &val)
bool isMessageProcessingSetUp()
void StartMessageFacility(fhicl::ParameterSet const &pset, string const &applicationName)
bool isWarningEnabled()
bool isInfoEnabled()
bool isDebugEnabled()
void LogStatistics()
void SetHostName(string const &hostname)
string const & GetHostName()
string const & GetIteration()
void SetContextSinglet(string const &val)
void LogErrorObj(ErrorObj *msg)
void SetModuleName(string const &val)
void SetApplicationName(string const &applicationName)
static QCString * s
Definition: config.cpp:1042
void SetPid(long const pid)
string const & GetApplicationName()
string const & GetHostAddr()
long GetPid()