v0.10.0
LogManager.cpp
Go to the documentation of this file.
1 /**
2  * @file LogManager.cpp
3  * @brief Log and register warnings
4  *
5  */
6 
7 #include <MoFEM.hpp>
8 
9 #undef likely
10 
11 #include <cstddef>
12 #include <string>
13 #include <ostream>
14 #include <fstream>
15 #include <iomanip>
16 
17 #include <boost/date_time/posix_time/posix_time.hpp>
18 
19 static int dummy_file_ptr = 1;
20 
21 namespace MoFEM {
22 
23 using namespace MoFEM::LogKeywords;
24 
25 constexpr std::array<char *const, LogManager::SeverityLevel::error + 1>
27 
28 std::ostream &operator<<(std::ostream &strm,
29  const LogManager::SeverityLevel &level) {
30 
31  strm << "<" << LogManager::severityStrings[level] << "> ";
32 
33  return strm;
34 }
35 
37  : public boost::enable_shared_from_this<LogManager::InternalData> {
38 
39  class SelfStreamBuf : public std::stringbuf {
40  virtual int sync() {
41  if (!this->str().empty()) {
42  PetscFPrintf(PETSC_COMM_SELF, LogManager::dummy_mofem_fd, "%s",
43  this->str().c_str());
44  this->str("");
45  }
46  return 0;
47  }
48  };
49 
50  struct WorldStreamBuf : public std::stringbuf {
51  WorldStreamBuf(MPI_Comm comm) : cOmm(comm) {}
52  virtual int sync() {
53  if (!this->str().empty()) {
54  PetscFPrintf(cOmm, LogManager::dummy_mofem_fd, "%s",
55  this->str().c_str());
56  this->str("");
57  }
58  return 0;
59  }
60 
61  private:
62  MPI_Comm cOmm;
63  };
64 
65  struct SynchronizedStreamBuf : public std::stringbuf {
66  SynchronizedStreamBuf(MPI_Comm comm) : cOmm(comm) {}
67  virtual int sync() {
68  if (!this->str().empty()) {
69  PetscSynchronizedFPrintf(cOmm, LogManager::dummy_mofem_fd, "%s",
70  this->str().c_str());
71  this->str("");
72  }
73  return 0;
74  }
75 
76  private:
77  MPI_Comm cOmm;
78  };
79 
83 
84  std::ostream strmSelf;
85  std::ostream strmWorld;
86  std::ostream strmSync;
87 
88  static bool logQuiet;
89  static bool noColors;
90  static bool sinksAdd;
91  static bool logTime;
92 
93  static std::map<std::string, LoggerType> logChannels;
94 
95  boost::shared_ptr<std::ostream> getStrmSelf() {
96  return boost::shared_ptr<std::ostream>(shared_from_this(), &strmSelf);
97  }
98  boost::shared_ptr<std::ostream> getStrmWorld() {
99  return boost::shared_ptr<std::ostream>(shared_from_this(), &strmWorld);
100  }
101  boost::shared_ptr<std::ostream> getStrmSync() {
102  return boost::shared_ptr<std::ostream>(shared_from_this(), &strmSync);
103  }
104 
105  InternalData(MPI_Comm comm)
106  : worldBuf(comm), syncBuf(comm), strmSelf(&selfBuf), strmWorld(&worldBuf),
107  strmSync(&syncBuf) {}
108 
109  virtual ~InternalData() = default;
110 };
111 
116 
117 std::map<std::string, LogManager::LoggerType>
119 
120 boost::shared_ptr<LogManager::InternalData> LogManager::internalDataPtr;
121 
123  : cOre(const_cast<MoFEM::Core &>(core)) {}
124 
126  UnknownInterface **iface) const {
128  *iface = NULL;
129  if (uuid == IDD_MOFEMLogManager) {
130  *iface = const_cast<LogManager *>(this);
132  }
133  SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "unknown interface");
135 }
136 
139  PetscInt sev_level = SeverityLevel::inform;
140  PetscBool log_scope = PETSC_FALSE;
141  PetscBool log_quiet = PETSC_FALSE;
142  PetscBool log_no_colors = PETSC_FALSE;
143  PetscBool log_time = PETSC_FALSE;
144 
145  CHKERR PetscOptionsBegin(PETSC_COMM_WORLD, "log_",
146  "Logging interface options", "none");
147 
148  CHKERR PetscOptionsEList("-severity_level", "Scope level", "",
149  severityStrings.data(), SeverityLevel::error + 1,
150  severityStrings[sev_level], &sev_level, PETSC_NULL);
151 
152  CHKERR PetscOptionsBool("-scope", "Log scope", "", log_scope, &log_scope,
153  NULL);
154 
155  CHKERR PetscOptionsBool("-quiet", "Quiet log attributes", "", log_quiet,
156  &log_quiet, NULL);
157 
158  CHKERR PetscOptionsBool("-no_color", "Terminal with no colors", "",
159  log_no_colors, &log_no_colors, NULL);
160 
161  CHKERR PetscOptionsBool("-time", "Log time", "",
162  log_time, &log_time, NULL);
163 
164  ierr = PetscOptionsEnd();
165  CHKERRG(ierr);
166 
167  logging::core::get()->set_filter(MoFEM::LogKeywords::severity >= sev_level);
168 
169  if (log_scope)
170  logging::core::get()->add_global_attribute("Scope", attrs::named_scope());
171 
172  if (log_quiet)
174 
175  if (log_no_colors)
177 
178  if (log_time)
180 
182 }
183 
184 void LogManager::recordFormatterDefault(logging::record_view const &rec,
185  logging::formatting_ostream &strm) {
186 
188 
189  auto sev = rec[severity];
190  auto p = rec[proc_attr];
191  auto l = rec[line_id];
192  auto s = rec[scope];
193  auto tg = rec[tag_attr];
194  auto tl = rec[timeline];
195 
196  auto set_color = [&](const auto str) {
197 #if defined(PETSC_HAVE_UNISTD_H) && defined(PETSC_USE_ISATTY)
198  if (isatty(fileno(stdout)) && !LogManager::InternalData::noColors)
199  strm << str;
200 #endif
201  };
202 
204 
205  auto local_time = boost::posix_time::second_clock::local_time();
206  strm << "(Local time ";
207  strm << local_time.date().year() << "-" << local_time.date().month()
208  << "-" << local_time.date().day() << " "
209  << local_time.time_of_day().hours() << ":"
210  << local_time.time_of_day().minutes() << ":"
211  << local_time.time_of_day().seconds();
212  strm << ") ";
213 
214  }
215 
216  if (!p.empty()) {
217  strm << "[";
218  set_color("\033[32m");
219  strm << p;
220  set_color("\033[0m");
221  strm << "] ";
222  }
223 
224  switch (sev.get()) {
225  case SeverityLevel::error:
226  set_color("\033[1m");
227  case SeverityLevel::warning:
228  set_color("\033[31m");
229  break;
230  case SeverityLevel::inform:
231  set_color("\033[34m");
232  break;
233  case SeverityLevel::verbose:
234  set_color("\033[35m");
235  break;
236  case SeverityLevel::noisy:
237  set_color("\033[36m");
238  break;
239  }
240 
241  strm << sev;
242 
243  set_color("\033[0m");
244 
245  if (!l.empty())
246  strm << std::hex << std::setw(8) << std::setfill('0') << l.get()
247  << std::dec << std::setfill(' ') << ": ";
248 
249  if (!s.empty()) {
250  for (::boost::log::attributes::named_scope_list::const_iterator iter =
251  s->begin();
252  iter != s->end(); ++iter) {
253  const auto path = std::string(iter->file_name.data());
254  const auto file = path.substr(path.find_last_of("/\\") + 1);
255  strm << "(" << file << ":" << iter->line << ">" << iter->scope_name
256  << ")";
257  }
258  strm << " ";
259  }
260 
261  if (!tg.empty()) {
262 
263  set_color("\033[1m");
264  strm << "[" << tg.get() << "] ";
265  set_color("\033[0m");
266  }
267 
268  if (!tl.empty())
269  strm << "[" << tl.get() << "] ";
270  }
271 
272  auto msg = rec[logging::expressions::smessage];
273 
274  strm << msg;
275 }
276 
277 boost::shared_ptr<LogManager::SinkType>
278 LogManager::createSink(boost::shared_ptr<std::ostream> stream_ptr,
279  std::string comm_filter) {
280 
281  auto backend = boost::make_shared<sinks::text_ostream_backend>();
282  if (stream_ptr)
283  backend->add_stream(stream_ptr);
284  backend->auto_flush(true);
285 
286  auto sink = boost::make_shared<SinkType>(backend);
287  sink->set_filter((expr::has_attr(channel) && channel == comm_filter));
288  sink->set_formatter(&recordFormatterDefault);
289 
290  return sink;
291 }
292 
293 void LogManager::createDefaultSinks(MPI_Comm comm) {
294 
295  internalDataPtr = boost::make_shared<InternalData>(comm);
296 
297  auto core_log = logging::core::get();
298  core_log->remove_all_sinks();
299  core_log->add_sink(LogManager::createSink(
300  boost::shared_ptr<std::ostream>(&std::clog, boost::null_deleter()),
301  "PETSC"));
302  core_log->add_sink(createSink(getStrmSelf(), "SELF"));
303  core_log->add_sink(createSink(getStrmWorld(), "WORLD"));
304  core_log->add_sink(createSink(getStrmSync(), "SYNC"));
305 
306  LogManager::setLog("PETSC");
307  LogManager::setLog("SELF");
308  LogManager::setLog("WORLD");
309  LogManager::setLog("SYNC");
310 
311  MOFEM_LOG_TAG("PETSC", "petsc");
312 
313  int rank;
314  MPI_Comm_rank(comm, &rank);
315  core_log->add_global_attribute("Proc", attrs::constant<unsigned int>(rank));
316 }
317 
318 boost::shared_ptr<std::ostream> LogManager::getStrmSelf() {
319  return internalDataPtr->getStrmSelf();
320 }
321 
322 boost::shared_ptr<std::ostream> LogManager::getStrmWorld() {
323  return internalDataPtr->getStrmWorld();
324 }
325 
326 boost::shared_ptr<std::ostream> LogManager::getStrmSync() {
327  return internalDataPtr->getStrmSync();
328 }
329 
330 static char dummy_file;
331 FILE *LogManager::dummy_mofem_fd = (FILE *)&dummy_file;
332 
334 
335  if (bit == 0)
336  return;
337 
338  if (bit & (BitLineID | BitScope)) {
339 
340  if (bit & BitLineID)
341  lg.add_attribute("LineID", attrs::counter<unsigned int>(1));
342 
343  if (bit & BitScope)
344  lg.add_attribute("Scope", attrs::named_scope());
345 
346  } else {
347  THROW_MESSAGE("Wrong cast");
348  }
349 }
350 
351 void LogManager::addAttributes(const std::string channel, const int bit) {
352  addAttributes(getLog(channel), bit);
353 }
354 
355 void LogManager::addTag(LogManager::LoggerType &lg, const std::string tag) {
356  lg.add_attribute("Tag", attrs::constant<std::string>(tag));
357 }
358 
359 void LogManager::addTag(const std::string channel, const std::string tag) {
360  getLog(channel).add_attribute("Tag", attrs::constant<std::string>(tag));
361 }
362 
363 LogManager::LoggerType &LogManager::setLog(const std::string channel) {
364  InternalData::logChannels[channel] =
365  LoggerType(boost::log::keywords::channel = channel);
366  return InternalData::logChannels[channel];
367 }
368 
369 LogManager::LoggerType &LogManager::getLog(const std::string channel) {
370  return InternalData::logChannels.at(channel);
371 }
372 
373 std::string LogManager::petscStringCache = std::string();
374 
375 PetscErrorCode LogManager::logPetscFPrintf(FILE *fd, const char format[],
376  va_list Argp) {
378  if (fd != stdout && fd != stderr && fd != dummy_mofem_fd) {
379  CHKERR PetscVFPrintfDefault(fd, format, Argp);
380 
381  } else {
382 
383  std::array<char, 1024> buff;
384  size_t length;
385  CHKERR PetscVSNPrintf(buff.data(), 1024, format, &length, Argp);
386 
387  auto get_str = [&buff]() {
388  std::string str;
389  if (!petscStringCache.empty())
390  str = petscStringCache + std::string(buff.data());
391  else
392  str = std::string(buff.data());
393  return str;
394  };
395  const auto str = get_str();
396 
397  if (!str.empty()) {
398  if (fd != dummy_mofem_fd) {
399 
401  MoFEM::LogManager::SeverityLevel::inform;
402  if (str.find("WARNING") != std::string::npos)
403  sev = MoFEM::LogManager::SeverityLevel::warning;
404 
405  std::istringstream is(str);
406  std::string line;
407  std::vector<std::string> log_list;
408 
409  while (getline(is, line, '\n'))
410  log_list.push_back(line);
411 
412  if (str.back() != '\n') {
413  petscStringCache = log_list.back();
414  log_list.pop_back();
415  } else
416  petscStringCache.clear();
417 
418  for(auto &line : log_list)
419  MOFEM_LOG("PETSC", sev) << line;
420 
421  } else {
422  std::clog << str;
423  }
424  }
425  }
427 }
428 
429 std::string LogManager::getVLikeFormatedString(const char *fmt, va_list args) {
430  std::array<char, 1024> buf;
431  vsprintf(buf.data(), fmt, args);
432  return std::string(buf.data());
433 }
434 
435 std::string LogManager::getCLikeFormatedString(const char *fmt, ...) {
436  va_list args;
437  va_start(args, fmt);
438  auto str = getVLikeFormatedString(fmt, args);
439  va_end(args);
440  return str;
441 }
442 
443 } // namespace MoFEM
static boost::shared_ptr< std::ostream > getStrmWorld()
Get the strm world object.
Definition: LogManager.cpp:322
MoFEM interface unique ID.
SeverityLevel
Severity levels.
Definition: LogManager.hpp:46
FTensor::Index< 'l', 3 > l
SynchronizedStreamBuf syncBuf
Definition: LogManager.cpp:82
static char dummy_file
Definition: LogManager.cpp:330
static const MOFEMuuid IDD_MOFEMLogManager
Definition: LogManager.hpp:31
boost::shared_ptr< std::ostream > getStrmSync()
Definition: LogManager.cpp:101
static void createDefaultSinks(MPI_Comm comm)
Create default sinks.
Definition: LogManager.cpp:293
#define MoFEMFunctionBeginHot
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
Definition: definitions.h:509
static std::map< std::string, LoggerType > logChannels
Definition: LogManager.cpp:93
#define MOFEM_LOG_TAG(channel, tag)
Tag channelTag channel tag is set until MOFEM_LOG_CHANNEL is called, then new tag can be set.
Definition: LogManager.hpp:334
static Index< 'p', 3 > p
static PetscErrorCode logPetscFPrintf(FILE *fd, const char format[], va_list Argp)
Use to handle PETSc output.
Definition: LogManager.cpp:375
#define MOFEM_LOG(channel, severity)
Log.
Definition: LogManager.hpp:303
base class for all interface classes
static MoFEMErrorCode getOptions()
Get logger option.
Definition: LogManager.cpp:137
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return()
Definition: definitions.h:485
#define CHKERRG(n)
Check error code of MoFEM/MOAB/PETSc function.
Definition: definitions.h:552
static boost::shared_ptr< std::ostream > getStrmSelf()
Get the strm self object.
Definition: LogManager.cpp:318
PetscErrorCode PetscVFPrintfDefault(FILE *fd, const char *format, va_list Argp)
#define THROW_MESSAGE(a)
Throw MoFEM exception.
Definition: definitions.h:628
static std::string getCLikeFormatedString(const char *fmt,...)
Converts formatted output to string.
Definition: LogManager.cpp:435
#define MoFEMFunctionReturnHot(a)
Last executable line of each PETSc function used for error handling. Replaces return()
Definition: definitions.h:516
static void addAttributes(LogManager::LoggerType &lg, const int bit=0)
Add attributes to logger.
Definition: LogManager.cpp:333
static int dummy_file_ptr
Definition: LogManager.cpp:19
static FILE * dummy_mofem_fd
Dummy file pointer (DO NOT USE)
Definition: LogManager.hpp:188
implementation of Data Operators for Forces and Sources
Definition: Common.hpp:21
static boost::shared_ptr< SinkType > createSink(boost::shared_ptr< std::ostream > stream_ptr, std::string comm_filter)
Create a sink object.
Definition: LogManager.cpp:278
std::ostream & operator<<(std::ostream &os, const DataForcesAndSourcesCore::EntData &e)
static LoggerType & setLog(const std::string channel)
Set ans resset chanel logger.
Definition: LogManager.cpp:363
static void addTag(LogManager::LoggerType &lg, const std::string tag)
Add tag to logger.
Definition: LogManager.cpp:355
static boost::shared_ptr< std::ostream > getStrmSync()
Get the strm sync object.
Definition: LogManager.cpp:326
static MoFEMErrorCodeGeneric< PetscErrorCode > ierr
Definition: Exceptions.hpp:87
static constexpr std::array< char *const, error+1 > severityStrings
Definition: LogManager.hpp:48
static boost::shared_ptr< InternalData > internalDataPtr
Definition: LogManager.hpp:233
boost::shared_ptr< std::ostream > getStrmSelf()
Definition: LogManager.cpp:95
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
Definition: Exceptions.hpp:67
boost::shared_ptr< std::ostream > getStrmWorld()
Definition: LogManager.cpp:98
static LoggerType & getLog(const std::string channel)
Get logger by channel.
Definition: LogManager.cpp:369
#define CHKERR
Inline error check.
Definition: definitions.h:604
static void recordFormatterDefault(logging::record_view const &rec, logging::formatting_ostream &strm)
Default record formatter.
Definition: LogManager.cpp:184
Core (interface) class.
Definition: Core.hpp:77
#define MoFEMFunctionBegin
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
Definition: definitions.h:415
boost::log::sources::severity_channel_logger< SeverityLevel, std::string > LoggerType
Definition of the channel logger.
Definition: LogManager.hpp:77
static std::string getVLikeFormatedString(const char *fmt, va_list args)
Converts formatted output to string.
Definition: LogManager.cpp:429
MoFEMErrorCode query_interface(const MOFEMuuid &uuid, UnknownInterface **iface) const
Definition: LogManager.cpp:125
static std::string petscStringCache
Definition: LogManager.hpp:236
LogManager(const MoFEM::Core &core)
Definition: LogManager.cpp:122