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