v0.13.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 LogManager::query_interface(boost::typeindex::type_index type_index,
127  UnknownInterface **iface) const {
129  *iface = const_cast<LogManager *>(this);
131 }
132 
135  PetscInt sev_level = SeverityLevel::inform;
136  PetscBool log_scope = PETSC_FALSE;
137  PetscBool log_quiet = PETSC_FALSE;
138  PetscBool log_no_colors = PETSC_FALSE;
139  PetscBool log_time = PETSC_FALSE;
140 
141  CHKERR PetscOptionsBegin(PETSC_COMM_WORLD, "log_",
142  "Logging interface options", "none");
143 
144  CHKERR PetscOptionsEList("-severity_level", "Severity level", "",
145  severityStrings.data(), SeverityLevel::error + 1,
146  severityStrings[sev_level], &sev_level, PETSC_NULL);
147  CHKERR PetscOptionsEList("-sl", "Seeverity level", "",
148  severityStrings.data(), SeverityLevel::error + 1,
149  severityStrings[sev_level], &sev_level, PETSC_NULL);
150 
151  CHKERR PetscOptionsBool("-scope", "Log scope", "", log_scope, &log_scope,
152  NULL);
153 
154  CHKERR PetscOptionsBool("-quiet", "Quiet log attributes", "", log_quiet,
155  &log_quiet, NULL);
156 
157  CHKERR PetscOptionsBool("-no_color", "Terminal with no colors", "",
158  log_no_colors, &log_no_colors, NULL);
159  CHKERR PetscOptionsBool("-nc", "Terminal with no colors", "", log_no_colors,
160  &log_no_colors, NULL);
161 
162  CHKERR PetscOptionsBool("-time", "Log time", "",
163  log_time, &log_time, NULL);
164 
165  ierr = PetscOptionsEnd();
166  CHKERRG(ierr);
167 
168  logging::core::get()->set_filter(MoFEM::LogKeywords::severity >= sev_level);
169 
170  if (log_scope)
171  logging::core::get()->add_global_attribute("Scope", attrs::named_scope());
172 
173  if (log_quiet)
175 
176  if (log_no_colors)
178 
179  if (log_time)
181 
183 }
184 
185 void LogManager::recordFormatterDefault(logging::record_view const &rec,
186  logging::formatting_ostream &strm) {
187 
189 
190  auto sev = rec[severity];
191  auto p = rec[proc_attr];
192  auto l = rec[line_id];
193  auto s = rec[scope];
194  auto tg = rec[tag_attr];
195  auto tl = rec[timeline];
196 
197  auto set_color = [&](const auto str) {
198 #if defined(PETSC_HAVE_UNISTD_H) && defined(PETSC_USE_ISATTY)
199  if (isatty(fileno(stdout)) && !LogManager::InternalData::noColors)
200  strm << str;
201 #endif
202  };
203 
205 
206  auto local_time = boost::posix_time::second_clock::local_time();
207  strm << "(Local time ";
208  strm << local_time.date().year() << "-" << local_time.date().month()
209  << "-" << local_time.date().day() << " "
210  << local_time.time_of_day().hours() << ":"
211  << local_time.time_of_day().minutes() << ":"
212  << local_time.time_of_day().seconds();
213  strm << ") ";
214 
215  }
216 
217  if (!p.empty()) {
218  strm << "[";
219  set_color("\033[32m");
220  strm << p;
221  set_color("\033[0m");
222  strm << "] ";
223  }
224 
225  switch (sev.get()) {
226  case SeverityLevel::error:
227  set_color("\033[1m");
228  case SeverityLevel::warning:
229  set_color("\033[31m");
230  break;
231  case SeverityLevel::inform:
232  set_color("\033[34m");
233  break;
234  case SeverityLevel::verbose:
235  set_color("\033[35m");
236  break;
237  case SeverityLevel::noisy:
238  set_color("\033[36m");
239  break;
240  }
241 
242  strm << sev;
243 
244  set_color("\033[0m");
245 
246  if (!l.empty())
247  strm << std::hex << std::setw(8) << std::setfill('0') << l.get()
248  << std::dec << std::setfill(' ') << ": ";
249 
250  if (!s.empty()) {
251  for (::boost::log::attributes::named_scope_list::const_iterator iter =
252  s->begin();
253  iter != s->end(); ++iter) {
254  const auto path = std::string(iter->file_name.data());
255  const auto file = path.substr(path.find_last_of("/\\") + 1);
256  strm << "(" << file << ":" << iter->line << ">" << iter->scope_name
257  << ")";
258  }
259  strm << " ";
260  }
261 
262  if (!tg.empty()) {
263 
264  set_color("\033[1m");
265  strm << "[" << tg.get() << "] ";
266  set_color("\033[0m");
267  }
268 
269  if (!tl.empty())
270  strm << "[" << tl.get() << "] ";
271  }
272 
273  auto msg = rec[logging::expressions::smessage];
274 
275  strm << msg;
276 }
277 
278 boost::shared_ptr<LogManager::SinkType>
279 LogManager::createSink(boost::shared_ptr<std::ostream> stream_ptr,
280  std::string comm_filter) {
281 
282  auto backend = boost::make_shared<sinks::text_ostream_backend>();
283  if (stream_ptr)
284  backend->add_stream(stream_ptr);
285  backend->auto_flush(true);
286 
287  auto sink = boost::make_shared<SinkType>(backend);
288  sink->set_filter((expr::has_attr(channel) && channel == comm_filter));
289  sink->set_formatter(&recordFormatterDefault);
290 
291  return sink;
292 }
293 
294 void LogManager::createDefaultSinks(MPI_Comm comm) {
295 
296  internalDataPtr = boost::make_shared<InternalData>(comm);
297 
298  auto core_log = logging::core::get();
299  core_log->remove_all_sinks();
300  core_log->add_sink(LogManager::createSink(
301  boost::shared_ptr<std::ostream>(&std::clog, boost::null_deleter()),
302  "PETSC"));
303  core_log->add_sink(createSink(getStrmSelf(), "SELF"));
304  core_log->add_sink(createSink(getStrmWorld(), "WORLD"));
305  core_log->add_sink(createSink(getStrmSync(), "SYNC"));
306 
307  LogManager::setLog("PETSC");
308  LogManager::setLog("SELF");
309  LogManager::setLog("WORLD");
310  LogManager::setLog("SYNC");
311 
312  MOFEM_LOG_TAG("PETSC", "petsc");
313 
314  int rank;
315  MPI_Comm_rank(comm, &rank);
316  core_log->add_global_attribute("Proc", attrs::constant<unsigned int>(rank));
317 }
318 
319 boost::shared_ptr<std::ostream> LogManager::getStrmSelf() {
320  return internalDataPtr->getStrmSelf();
321 }
322 
323 boost::shared_ptr<std::ostream> LogManager::getStrmWorld() {
324  return internalDataPtr->getStrmWorld();
325 }
326 
327 boost::shared_ptr<std::ostream> LogManager::getStrmSync() {
328  return internalDataPtr->getStrmSync();
329 }
330 
331 static char dummy_file;
332 FILE *LogManager::dummy_mofem_fd = (FILE *)&dummy_file;
333 
335 
336  if (bit == 0)
337  return;
338 
339  if (bit & (BitLineID | BitScope)) {
340 
341  if (bit & BitLineID)
342  lg.add_attribute("LineID", attrs::counter<unsigned int>(1));
343 
344  if (bit & BitScope)
345  lg.add_attribute("Scope", attrs::named_scope());
346 
347  } else {
348  THROW_MESSAGE("Wrong cast");
349  }
350 }
351 
352 void LogManager::addAttributes(const std::string channel, const int bit) {
353  addAttributes(getLog(channel), bit);
354 }
355 
356 void LogManager::addTag(LogManager::LoggerType &lg, const std::string tag) {
357  lg.add_attribute("Tag", attrs::constant<std::string>(tag));
358 }
359 
360 void LogManager::addTag(const std::string channel, const std::string tag) {
361  getLog(channel).add_attribute("Tag", attrs::constant<std::string>(tag));
362 }
363 
364 LogManager::LoggerType &LogManager::setLog(const std::string channel) {
365  InternalData::logChannels[channel] =
366  LoggerType(boost::log::keywords::channel = channel);
367  return InternalData::logChannels[channel];
368 }
369 
370 LogManager::LoggerType &LogManager::getLog(const std::string channel) {
371  return InternalData::logChannels.at(channel);
372 }
373 
374 bool LogManager::checkIfChannelExist(const std::string channel) {
375  return InternalData::logChannels.find(channel) !=
377 }
378 
379 std::string LogManager::petscStringCache = std::string();
380 
381 PetscErrorCode LogManager::logPetscFPrintf(FILE *fd, const char format[],
382  va_list Argp) {
384  if (fd != stdout && fd != stderr && fd != dummy_mofem_fd) {
385  CHKERR PetscVFPrintfDefault(fd, format, Argp);
386 
387  } else {
388 
389  std::array<char, 1024> buff;
390  size_t length;
391  CHKERR PetscVSNPrintf(buff.data(), 1024, format, &length, Argp);
392 
393  auto get_str = [&buff]() {
394  std::string str;
395  if (!petscStringCache.empty())
396  str = petscStringCache + std::string(buff.data());
397  else
398  str = std::string(buff.data());
399  return str;
400  };
401  const auto str = get_str();
402 
403  if (!str.empty()) {
404  if (fd != dummy_mofem_fd) {
405 
407  MoFEM::LogManager::SeverityLevel::inform;
408  if (str.find("WARNING") != std::string::npos)
409  sev = MoFEM::LogManager::SeverityLevel::warning;
410 
411  std::istringstream is(str);
412  std::string line;
413  std::vector<std::string> log_list;
414 
415  while (getline(is, line, '\n'))
416  log_list.push_back(line);
417 
418  if (str.back() != '\n') {
419  petscStringCache = log_list.back();
420  log_list.pop_back();
421  } else
422  petscStringCache.clear();
423 
424  for(auto &line : log_list)
425  MOFEM_LOG("PETSC", sev) << line;
426 
427  } else {
428  std::clog << str;
429  }
430  }
431  }
433 }
434 
435 std::string LogManager::getVLikeFormatedString(const char *fmt, va_list args) {
436  std::array<char, 1024> buf;
437  vsprintf(buf.data(), fmt, args);
438  return std::string(buf.data());
439 }
440 
441 std::string LogManager::getCLikeFormatedString(const char *fmt, ...) {
442  va_list args;
443  va_start(args, fmt);
444  auto str = getVLikeFormatedString(fmt, args);
445  va_end(args);
446  return str;
447 }
448 
449 } // namespace MoFEM
static Index< 'p', 3 > p
static int dummy_file_ptr
Definition: LogManager.cpp:19
PetscErrorCode PetscVFPrintfDefault(FILE *fd, const char *format, va_list Argp)
#define MoFEMFunctionReturnHot(a)
Last executable line of each PETSc function used for error handling. Replaces return()
Definition: definitions.h:460
#define MoFEMFunctionBegin
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
Definition: definitions.h:359
#define CHKERRG(n)
Check error code of MoFEM/MOAB/PETSc function.
Definition: definitions.h:496
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return()
Definition: definitions.h:429
#define CHKERR
Inline error check.
Definition: definitions.h:548
#define MoFEMFunctionBeginHot
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
Definition: definitions.h:453
#define THROW_MESSAGE(msg)
Throw MoFEM exception.
Definition: definitions.h:574
static LoggerType & setLog(const std::string channel)
Set ans resset chanel logger.
Definition: LogManager.cpp:364
#define MOFEM_LOG(channel, severity)
Log.
Definition: LogManager.hpp:311
SeverityLevel
Severity levels.
Definition: LogManager.hpp:43
#define MOFEM_LOG_TAG(channel, tag)
Tag channel.
Definition: LogManager.hpp:342
static void addTag(LogManager::LoggerType &lg, const std::string tag)
Add tag to logger.
Definition: LogManager.cpp:356
static void addAttributes(LogManager::LoggerType &lg, const int bit=0)
Add attributes to logger.
Definition: LogManager.cpp:334
static LoggerType & getLog(const std::string channel)
Get logger by channel.
Definition: LogManager.cpp:370
auto bit
set bit
FTensor::Index< 'l', 3 > l
static MoFEMErrorCodeGeneric< PetscErrorCode > ierr
Definition: Exceptions.hpp:87
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
Definition: Exceptions.hpp:67
implementation of Data Operators for Forces and Sources
Definition: Common.hpp:21
static char dummy_file
Definition: LogManager.cpp:331
std::ostream & operator<<(std::ostream &os, const EntitiesFieldData::EntData &e)
Core (interface) class.
Definition: Core.hpp:92
boost::shared_ptr< std::ostream > getStrmWorld()
Definition: LogManager.cpp:98
SynchronizedStreamBuf syncBuf
Definition: LogManager.cpp:82
virtual ~InternalData()=default
boost::shared_ptr< std::ostream > getStrmSync()
Definition: LogManager.cpp:101
static std::map< std::string, LoggerType > logChannels
Definition: LogManager.cpp:93
boost::shared_ptr< std::ostream > getStrmSelf()
Definition: LogManager.cpp:95
Log manager is used to build and partition problems.
Definition: LogManager.hpp:36
static constexpr std::array< char *const, error+1 > severityStrings
Definition: LogManager.hpp:45
static boost::shared_ptr< SinkType > createSink(boost::shared_ptr< std::ostream > stream_ptr, std::string comm_filter)
Create a sink object.
Definition: LogManager.cpp:279
LogManager(const MoFEM::Core &core)
Definition: LogManager.cpp:122
static MoFEMErrorCode getOptions()
Get logger option.
Definition: LogManager.cpp:133
static std::string getCLikeFormatedString(const char *fmt,...)
Converts formatted output to string.
Definition: LogManager.cpp:441
static void createDefaultSinks(MPI_Comm comm)
Create default sinks.
Definition: LogManager.cpp:294
boost::log::sources::severity_channel_logger< SeverityLevel, std::string > LoggerType
Definition of the channel logger.
Definition: LogManager.hpp:74
static boost::shared_ptr< std::ostream > getStrmWorld()
Get the strm world object.
Definition: LogManager.cpp:323
MoFEMErrorCode query_interface(boost::typeindex::type_index type_index, UnknownInterface **iface) const
Definition: LogManager.cpp:126
static PetscErrorCode logPetscFPrintf(FILE *fd, const char format[], va_list Argp)
Use to handle PETSc output.
Definition: LogManager.cpp:381
static std::string getVLikeFormatedString(const char *fmt, va_list args)
Converts formatted output to string.
Definition: LogManager.cpp:435
static boost::shared_ptr< std::ostream > getStrmSync()
Get the strm sync object.
Definition: LogManager.cpp:327
static void recordFormatterDefault(logging::record_view const &rec, logging::formatting_ostream &strm)
Default record formatter.
Definition: LogManager.cpp:185
static bool checkIfChannelExist(const std::string channel)
Check if channel exist.
Definition: LogManager.cpp:374
static boost::shared_ptr< std::ostream > getStrmSelf()
Get the strm self object.
Definition: LogManager.cpp:319
static std::string petscStringCache
Definition: LogManager.hpp:242
static FILE * dummy_mofem_fd
Dummy file pointer (DO NOT USE)
Definition: LogManager.hpp:194
static boost::shared_ptr< InternalData > internalDataPtr
Definition: LogManager.hpp:239
base class for all interface classes