v0.15.0
Loading...
Searching...
No Matches
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
19namespace MoFEM {
20
21using namespace MoFEM::LogKeywords;
22
23std::ostream &operator<<(std::ostream &strm,
24 const LogManager::SeverityLevel &level) {
25
26 strm << "<" << LogManager::severityStrings[level] << "> ";
27
28 return strm;
29}
30
32 : public boost::enable_shared_from_this<LogManager::InternalData> {
33
34 class SelfStreamBuf : public std::stringbuf {
35 virtual int sync() {
36 if (!this->str().empty()) {
37 PetscFPrintf(PETSC_COMM_SELF, LogManager::dummy_mofem_fd, "%s",
38 this->str().c_str());
39 this->str("");
40 }
41 return 0;
42 }
43 };
44
45 struct WorldStreamBuf : public std::stringbuf {
46 WorldStreamBuf(MPI_Comm comm) : cOmm(comm) {}
47 virtual int sync() {
48 if (!this->str().empty()) {
49 PetscFPrintf(cOmm, LogManager::dummy_mofem_fd, "%s",
50 this->str().c_str());
51 this->str("");
52 }
53 return 0;
54 }
55
56 private:
57 MPI_Comm cOmm;
58 };
59
60 struct SynchronizedStreamBuf : public std::stringbuf {
61 SynchronizedStreamBuf(MPI_Comm comm, FILE *fd) : cOmm(comm), fD(fd) {}
62 virtual int sync() {
63 if (!this->str().empty()) {
64 PetscSynchronizedFPrintf(cOmm, fD, "%s", this->str().c_str());
65 this->str("");
66 }
67 return 0;
68 }
69
70 private:
71 MPI_Comm cOmm;
72 FILE *fD;
73 };
74
75 class NulStreambuf : public std::streambuf {
76 char dummyBuffer[64];
77
78 protected:
79 virtual int overflow(int c) {
80 setp(dummyBuffer, dummyBuffer + sizeof(dummyBuffer));
81 return (c == traits_type::eof()) ? '\0' : c;
82 }
83 };
84
88
89 std::ostream strmSelf;
90 std::ostream strmWorld;
91 std::ostream strmSync;
92
93 class NulOStream : private NulStreambuf, public std::ostream {
94 public:
95 NulOStream() : std::ostream(this) {}
96 NulStreambuf *rdbuf() { return this; }
97 };
98
100
101 static bool logQuiet;
102 static bool noColors;
103 static bool sinksAdd;
104 static bool logTime;
105
106 static std::map<std::string, LoggerType> logChannels;
107
108 boost::shared_ptr<std::ostream> getStrmSelf() {
109 return boost::shared_ptr<std::ostream>(shared_from_this(), &strmSelf);
110 }
111 boost::shared_ptr<std::ostream> getStrmWorld() {
112 return boost::shared_ptr<std::ostream>(shared_from_this(), &strmWorld);
113 }
114 boost::shared_ptr<std::ostream> getStrmSync() {
115 return boost::shared_ptr<std::ostream>(shared_from_this(), &strmSync);
116 }
117 boost::shared_ptr<std::ostream> getStrmNull() {
118 return boost::shared_ptr<std::ostream>(shared_from_this(), &nullSelf);
119 }
120
124
125 virtual ~InternalData() = default;
126};
127
132
133std::map<std::string, LogManager::LoggerType>
135
136boost::shared_ptr<LogManager::InternalData> LogManager::internalDataPtr;
137
139 : cOre(const_cast<MoFEM::Core &>(core)) {}
140
142LogManager::query_interface(boost::typeindex::type_index type_index,
143 UnknownInterface **iface) const {
145 *iface = const_cast<LogManager *>(this);
147}
148
151 PetscInt sev_level = SeverityLevel::inform;
152 PetscBool log_scope = PETSC_FALSE;
153 PetscBool log_quiet = PETSC_FALSE;
154 PetscBool log_no_colors = PETSC_FALSE;
155 PetscBool log_time = PETSC_FALSE;
156
157 PetscOptionsBegin(PETSC_COMM_WORLD, "log_", "Logging interface options",
158 "none");
159
160 CHKERR PetscOptionsEList("-severity_level", "Severity level", "",
162 severityStrings[sev_level], &sev_level,
163 PETSC_NULLPTR);
164 CHKERR PetscOptionsEList("-sl", "Severity level", "", severityStrings.data(),
166 &sev_level, PETSC_NULLPTR);
167
168 CHKERR PetscOptionsBool("-scope", "Log scope", "", log_scope, &log_scope,
169 NULL);
170
171 CHKERR PetscOptionsBool("-quiet", "Quiet log attributes", "", log_quiet,
172 &log_quiet, NULL);
173
174 CHKERR PetscOptionsBool("-no_color", "Terminal with no colors", "",
175 log_no_colors, &log_no_colors, NULL);
176 CHKERR PetscOptionsBool("-nc", "Terminal with no colors", "", log_no_colors,
177 &log_no_colors, NULL);
178
179 CHKERR PetscOptionsBool("-time", "Log time", "", log_time, &log_time, NULL);
180
181 PetscOptionsEnd();
182
183 logging::core::get()->set_filter(MoFEM::LogKeywords::severity >= sev_level);
184
185 if (log_scope)
186 logging::core::get()->add_global_attribute("Scope", attrs::named_scope());
187
188 if (log_quiet)
190
191 if (log_no_colors)
193
194 if (log_time)
196
198}
199
200void LogManager::recordFormatterDefault(logging::record_view const &rec,
201 logging::formatting_ostream &strm) {
202
204
205 auto sev = rec[severity];
206 auto p = rec[proc_attr];
207 auto l = rec[line_id];
208 auto s = rec[scope];
209 auto tg = rec[tag_attr];
210 auto tl = rec[timeline];
211
212 auto set_color = [&](const auto str) {
213#if defined(PETSC_HAVE_UNISTD_H) && defined(PETSC_USE_ISATTY)
214 if (isatty(fileno(stdout)) && !LogManager::InternalData::noColors)
215 strm << str;
216#endif
217 };
218
220
221 auto local_time = boost::posix_time::second_clock::local_time();
222 strm << "(Local time ";
223 strm << local_time.date().year() << "-" << local_time.date().month()
224 << "-" << local_time.date().day() << " "
225 << local_time.time_of_day().hours() << ":"
226 << local_time.time_of_day().minutes() << ":"
227 << local_time.time_of_day().seconds();
228 strm << ") ";
229 }
230
231 if (!p.empty()) {
232 strm << "[";
233 set_color("\033[32m");
234 strm << p;
235 set_color("\033[0m");
236 strm << "] ";
237 }
238
239 switch (sev.get()) {
241 set_color("\033[1m");
243 set_color("\033[31m");
244 break;
246 set_color("\033[34m");
247 break;
249 set_color("\033[35m");
250 break;
252 set_color("\033[36m");
253 break;
254 }
255
256 strm << sev;
257
258 set_color("\033[0m");
259
260 if (!l.empty())
261 strm << std::hex << std::setw(8) << std::setfill('0') << l.get()
262 << std::dec << std::setfill(' ') << ": ";
263
264 if (!s.empty()) {
265 for (::boost::log::attributes::named_scope_list::const_iterator iter =
266 s->begin();
267 iter != s->end(); ++iter) {
268 const auto path = std::string(iter->file_name.data());
269 const auto file = path.substr(path.find_last_of("/\\") + 1);
270 strm << "(" << file << ":" << iter->line << ">" << iter->scope_name
271 << ")";
272 }
273 strm << " ";
274 }
275
276 if (!tg.empty()) {
277
278 set_color("\033[1m");
279 strm << "[" << tg.get() << "] ";
280 set_color("\033[0m");
281 }
282
283 if (!tl.empty())
284 strm << "[" << tl.get() << "] ";
285 }
286
287 auto msg = rec[logging::expressions::smessage];
288
289 strm << msg;
290}
291
292boost::shared_ptr<LogManager::SinkType>
293LogManager::createSink(boost::shared_ptr<std::ostream> stream_ptr,
294 std::string comm_filter) {
295
296 auto backend = boost::make_shared<sinks::text_ostream_backend>();
297 if (stream_ptr)
298 backend->add_stream(stream_ptr);
299 backend->auto_flush(true);
300
301 auto sink = boost::make_shared<SinkType>(backend);
302 sink->set_filter((expr::has_attr(channel) && channel == comm_filter));
303 sink->set_formatter(&recordFormatterDefault);
304
305 return sink;
306}
307
309
310 internalDataPtr = boost::make_shared<InternalData>(comm);
311
312 auto core_log = logging::core::get();
313 core_log->remove_all_sinks();
314 core_log->add_sink(LogManager::createSink(
315 boost::shared_ptr<std::ostream>(&std::clog, boost::null_deleter()),
316 "PETSC"));
317 core_log->add_sink(createSink(getStrmSelf(), "SELF"));
318 core_log->add_sink(createSink(getStrmWorld(), "WORLD"));
319 core_log->add_sink(createSink(getStrmSync(), "SYNC"));
320 core_log->add_sink(createSink(getStrmNull(), "NULL"));
321
322 LogManager::setLog("PETSC");
323 LogManager::setLog("SELF");
324 LogManager::setLog("WORLD");
325 LogManager::setLog("SYNC");
326 LogManager::setLog("NULL");
327
328 MOFEM_LOG_TAG("PETSC", "petsc");
329
330 int rank;
331 MPI_Comm_rank(comm, &rank);
332 core_log->add_global_attribute("Proc", attrs::constant<unsigned int>(rank));
333}
334
335boost::shared_ptr<std::ostream> LogManager::getStrmSelf() {
336 return internalDataPtr->getStrmSelf();
337}
338
339boost::shared_ptr<std::ostream> LogManager::getStrmWorld() {
340 return internalDataPtr->getStrmWorld();
341}
342
343boost::shared_ptr<std::ostream> LogManager::getStrmSync() {
344 return internalDataPtr->getStrmSync();
345}
346
347boost::shared_ptr<std::ostream> LogManager::getStrmNull() {
348 return internalDataPtr->getStrmNull();
349}
350
351boost::shared_ptr<std::ostream> LogManager::getStrmSync(MPI_Comm comm,
352 FILE *fd) {
353 auto buff_ptr =
354 boost::make_shared<InternalData::SynchronizedStreamBuf>(comm, fd);
355 return boost::shared_ptr<std::ostream>(buff_ptr,
356 new std::ostream(buff_ptr.get()));
357}
358
359static char dummy_file;
361
363
364 if (bit == 0)
365 return;
366
367 if (bit & (BitLineID | BitScope)) {
368
369 if (bit & BitLineID)
370 lg.add_attribute("LineID", attrs::counter<unsigned int>(1));
371
372 if (bit & BitScope)
373 lg.add_attribute("Scope", attrs::named_scope());
374
375 } else {
376 THROW_MESSAGE("Wrong cast");
377 }
378}
379
380void LogManager::addAttributes(const std::string channel, const int bit) {
381 addAttributes(getLog(channel), bit);
382}
383
384void LogManager::addTag(LogManager::LoggerType &lg, const std::string tag) {
385 lg.add_attribute("Tag", attrs::constant<std::string>(tag));
386}
387
388void LogManager::addTag(const std::string channel, const std::string tag) {
389 getLog(channel).add_attribute("Tag", attrs::constant<std::string>(tag));
390}
391
392LogManager::LoggerType &LogManager::setLog(const std::string channel) {
394 LoggerType(boost::log::keywords::channel = channel);
395 return InternalData::logChannels[channel];
396}
397
398LogManager::LoggerType &LogManager::getLog(const std::string channel) {
399 auto it = InternalData::logChannels.find(channel);
400 if (it == InternalData::logChannels.end()) {
402 "Channel <" + channel + "> not found");
403 }
404 return it->second;
405}
406
407bool LogManager::checkIfChannelExist(const std::string channel) {
408 return InternalData::logChannels.find(channel) !=
410}
411
412std::string LogManager::petscStringCache = std::string();
413
414PetscErrorCode LogManager::logPetscFPrintf(FILE *fd, const char format[],
415 va_list Argp) {
417 if (fd != stdout && fd != stderr && fd != dummy_mofem_fd) {
418 CHKERR PetscVFPrintfDefault(fd, format, Argp);
419
420 } else {
421
422 std::array<char, 1024> buff;
423 size_t length;
424 CHKERR PetscVSNPrintf(buff.data(), 1024, format, &length, Argp);
425
426 auto get_str = [&buff]() {
427 std::string str;
428 if (!petscStringCache.empty())
429 str = petscStringCache + std::string(buff.data());
430 else
431 str = std::string(buff.data());
432 return str;
433 };
434 const auto str = get_str();
435
436 if (!str.empty()) {
437 if (fd != dummy_mofem_fd) {
438
441 if (str.find("WARNING") != std::string::npos)
443
444 std::istringstream is(str);
445 std::string line;
446 std::vector<std::string> log_list;
447
448 while (getline(is, line, '\n'))
449 log_list.push_back(line);
450
451 if (str.back() != '\n') {
452 petscStringCache = log_list.back();
453 log_list.pop_back();
454 } else
455 petscStringCache.clear();
456
457 for (auto &line : log_list)
458 MOFEM_LOG("PETSC", sev) << line;
459
460 } else {
461 std::clog << str;
462 }
463 }
464 }
466}
467
468std::string LogManager::getVLikeFormatedString(const char *fmt, va_list args) {
469 std::array<char, 1024> buf;
470 vsprintf(buf.data(), fmt, args);
471 return std::string(buf.data());
472}
473
474std::string LogManager::getCLikeFormatedString(const char *fmt, ...) {
475 va_list args;
476 va_start(args, fmt);
477 auto str = getVLikeFormatedString(fmt, args);
478 va_end(args);
479 return str;
480}
481
482} // namespace MoFEM
PetscErrorCode PetscVFPrintfDefault(FILE *fd, const char *format, va_list Argp)
#define CHK_THROW_MESSAGE(err, msg)
Check and throw MoFEM exception.
#define MoFEMFunctionReturnHot(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define MoFEMFunctionBegin
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
@ MOFEM_DATA_INCONSISTENCY
Definition definitions.h:31
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define CHKERR
Inline error check.
#define MoFEMFunctionBeginHot
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
#define THROW_MESSAGE(msg)
Throw MoFEM exception.
static LoggerType & setLog(const std::string channel)
Set ans resset chanel logger.
#define MOFEM_LOG(channel, severity)
Log.
SeverityLevel
Severity levels.
#define MOFEM_LOG_TAG(channel, tag)
Tag channel.
static void addTag(LogManager::LoggerType &lg, const std::string tag)
Add tag to logger.
static void addAttributes(LogManager::LoggerType &lg, const int bit=0)
Add attributes to logger.
static LoggerType & getLog(const std::string channel)
Get logger by channel.
auto bit
set bit
const double c
speed of light (cm/ns)
FTensor::Index< 'l', 3 > l
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
implementation of Data Operators for Forces and Sources
Definition Common.hpp:10
std::ostream & operator<<(std::ostream &os, const EntitiesFieldData::EntData &e)
static char dummy_file
Core (interface) class.
Definition Core.hpp:82
boost::shared_ptr< std::ostream > getStrmWorld()
boost::shared_ptr< std::ostream > getStrmNull()
SynchronizedStreamBuf syncBuf
virtual ~InternalData()=default
boost::shared_ptr< std::ostream > getStrmSync()
static std::map< std::string, LoggerType > logChannels
boost::shared_ptr< std::ostream > getStrmSelf()
Log manager is used to build and partition problems.
static boost::shared_ptr< std::ostream > getStrmNull()
Get the strm null object.
boost::log::sources::severity_channel_logger< SeverityLevel, std::string > LoggerType
Definition of the channel logger.
static boost::shared_ptr< SinkType > createSink(boost::shared_ptr< std::ostream > stream_ptr, std::string comm_filter)
Create a sink object.
LogManager(const MoFEM::Core &core)
static MoFEMErrorCode getOptions()
Get logger option.
static std::string getCLikeFormatedString(const char *fmt,...)
Converts formatted output to string.
static void createDefaultSinks(MPI_Comm comm)
Create default sinks.
static boost::shared_ptr< std::ostream > getStrmWorld()
Get the strm world object.
MoFEMErrorCode query_interface(boost::typeindex::type_index type_index, UnknownInterface **iface) const
static PetscErrorCode logPetscFPrintf(FILE *fd, const char format[], va_list Argp)
Use to handle PETSc output.
static std::string getVLikeFormatedString(const char *fmt, va_list args)
Converts formatted output to string.
static boost::shared_ptr< std::ostream > getStrmSync()
Get the strm sync object.
static void recordFormatterDefault(logging::record_view const &rec, logging::formatting_ostream &strm)
Default record formatter.
static bool checkIfChannelExist(const std::string channel)
Check if channel exist.
static boost::shared_ptr< std::ostream > getStrmSelf()
Get the strm self object.
static std::string petscStringCache
static FILE * dummy_mofem_fd
Dummy file pointer (DO NOT USE)
static boost::shared_ptr< InternalData > internalDataPtr
static constexpr std::array< char *const, error+1 > severityStrings
base class for all interface classes