LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
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.
49  std::string const& GetApplicationName();
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 
137  MaybeLogger_(std::string const& category,
138  std::string const& file = {},
139  int const line_number = 0)
140  {
141  // Verbatim messages have the full file path, otherwise just the basename.
142  std::string filename{file};
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 \
227  { \
228  category, __FILE__, __LINE__ \
229  }
230 #define MF_LOG_WARNING(category) \
231  mf::LogWarning \
232  { \
233  category, __FILE__, __LINE__ \
234  }
235 #define MF_LOG_ERROR(category) \
236  mf::LogError \
237  { \
238  category, __FILE__, __LINE__ \
239  }
240 #define MF_LOG_SYSTEM(category) \
241  mf::LogSystem \
242  { \
243  category, __FILE__, __LINE__ \
244  }
245 
246 // Verbatim messages, no decorations at all.
247 // Note: MF_LOG_TRACE is below.
248 #define MF_LOG_VERBATIM(category) \
249  mf::LogVerbatim \
250  { \
251  category, __FILE__, __LINE__ \
252  }
253 #define MF_LOG_PRINT(category) \
254  mf::LogPrint \
255  { \
256  category, __FILE__, __LINE__ \
257  }
258 #define MF_LOG_PROBLEM(category) \
259  mf::LogProblem \
260  { \
261  category, __FILE__, __LINE__ \
262  }
263 #define MF_LOG_ABSOLUTE(category) \
264  mf::LogAbsolute \
265  { \
266  category, __FILE__, __LINE__ \
267  }
268 
269 #undef MF_SUPPRESS_LOG_DEBUG
270 
271 // Suppress MF_LOG_DEBUG/TRACE if NDEBUG or MF_NDEBUG are set,
272 // except see below for MF_DEBUG which takes precendence.
273 #if defined(NDEBUG) || defined(MF_NDEBUG)
274 #define MF_SUPPRESS_LOG_DEBUG
275 #endif // NDEBUG || MF_NDEBUG
276 
277 // If MF_DEBUG is defined, MF_LOG_DEBUG/TRACE are active unconditionally,
278 // no matter what NDEBUG or MF_NDEBUG say.
279 #ifdef MF_DEBUG
280 #undef MF_SUPPRESS_LOG_DEBUG
281 #endif // MF_DEBUG
282 
283 #ifdef MF_SUPPRESS_LOG_DEBUG
284 
285 #define MF_LOG_DEBUG(id) \
286  mf::NeverLogger_ \
287  {}
288 #define MF_LOG_TRACE(id) \
289  mf::NeverLogger_ \
290  {}
291 
292 #else // MF_SUPPRESS_LOG_DEBUG
293 
294 #define MF_LOG_DEBUG(id) \
295  mf::LogDebug \
296  { \
297  id, __FILE__, __LINE__ \
298  }
299 #define MF_LOG_TRACE(id) \
300  mf::LogTrace \
301  { \
302  id, __FILE__, __LINE__ \
303  }
304 
305 #endif // MF_SUPPRESS_LOG_DEBUG
306 
307 #undef MF_SUPPRESS_LOG_DEBUG
308 
309 #endif /* messagefacility_MessageLogger_MessageLogger_h */
310 
311 // Local Variables:
312 // mode: c++
313 // End:
void SetIteration(string const &val)
void SetHostAddr(string const &hostaddr)
void EndMessageFacility()
string const & GetModuleName()
STL namespace.
void FlushMessageLog()
MaybeLogger_(std::string const &category, std::string const &file={}, int const line_number=0)
void SetContextIteration(string const &val)
TFile f
Definition: plotHisto.C:6
bool isMessageProcessingSetUp()
void StartMessageFacility(fhicl::ParameterSet const &pset, string const &applicationName)
bool isWarningEnabled()
bool isInfoEnabled()
parameter set interface
bool isDebugEnabled()
void LogStatistics()
void SetHostName(string const &hostname)
string const & GetHostName()
string const & GetIteration()
TFile * file
void SetContextSinglet(string const &val)
void LogErrorObj(ErrorObj *msg)
void SetModuleName(string const &val)
void SetApplicationName(string const &applicationName)
void SetPid(long const pid)
string const & GetApplicationName()
string const & GetHostAddr()
long GetPid()