43#include "fileHandler.hpp"
64 : m_buffer(bufferSize + 1),
65 m_nProcesses(nProcesses), m_rank(rank),
66 m_consoleEnabled(false), m_console(&std::cout),
67 m_fileEnabled(false), m_file(nullptr),
68 m_settings(std::make_shared<
Settings>())
71 char *bufferBegin = &m_buffer.front();
72 setp(bufferBegin, bufferBegin + m_buffer.size() - 1);
81 if (m_nProcesses > 1) {
82 int nDigits =
static_cast<int>(std::ceil(log10(m_nProcesses)));
83 std::ostringstream convert;
84 convert << std::setw(nDigits) << m_rank;
85 m_rankPrefix =
"#" + convert.str();
91 m_settings->context =
"";
92 m_settings->indentation = 0;
93 m_settings->consoleTimestampEnabled =
false;
94 m_settings->fileTimestampEnabled =
false;
136LoggerBuffer::int_type LoggerBuffer::overflow(int_type character)
138 if (character != traits_type::eof()) {
143 assert(std::less_equal<char *>()(pptr(), epptr()));
153 return traits_type::eof();
161int LoggerBuffer::sync()
176 const char *bufferBegin = pbase();
177 const char *bufferEnd = pptr();
178 if (bufferBegin == bufferEnd) {
183 const char *lineBegin =
nullptr;
184 const char *lineEnd = bufferBegin;
185 while (lineEnd != bufferEnd) {
188 for (lineEnd = lineBegin; lineEnd != bufferEnd; ++lineEnd) {
189 if (*lineEnd ==
'\n') {
196 bool terminateLine =
false;
197 if (terminate && (lineEnd == bufferEnd)) {
198 if (bufferBegin == bufferEnd) {
199 terminateLine =
true;
200 }
else if (*(bufferEnd - 1) !=
'\n') {
201 terminateLine =
true;
206 std::string consoleTimestamp;
207 std::string fileTimestamp;
208 if (m_settings->consoleTimestampEnabled || m_settings->fileTimestampEnabled) {
209 std::string timestamp = getTimestamp();
210 if (m_settings->consoleTimestampEnabled) {
211 consoleTimestamp = timestamp;
213 if (m_settings->fileTimestampEnabled) {
214 fileTimestamp = timestamp;
219 if (m_console && m_consoleEnabled) {
220 int status = flushLine(*m_console, lineBegin, lineEnd, consoleTimestamp, terminateLine);
227 if (m_file && m_fileEnabled && m_file->is_open()) {
228 int status = flushLine(*m_file, lineBegin, lineEnd, fileTimestamp, terminateLine);
236 pbump(
static_cast<int>(bufferBegin - bufferEnd));
254int LoggerBuffer::flushLine(std::ostream &stream,
const char *begin,
const char *end,
255 const std::string ×tamp,
bool terminate)
257 if (!timestamp.empty()) {
258 stream <<
"[" + timestamp +
"] ";
259 if ((stream.rdstate() & std::ifstream::failbit) != 0) {
264 if (!m_rankPrefix.empty()) {
265 stream << m_rankPrefix <<
" :: ";
266 if ((stream.rdstate() & std::ifstream::failbit) != 0) {
271 if (!m_settings->context.empty()) {
272 stream << m_settings->context +
" :: ";
273 if ((stream.rdstate() & std::ifstream::failbit) != 0) {
278 for (
int i = 0; i < m_settings->indentation; ++i) {
280 if ((stream.rdstate() & std::ifstream::failbit) != 0) {
285 stream.write(begin, end - begin);
286 if ((stream.rdstate() & std::ifstream::failbit) != 0) {
292 if ((stream.rdstate() & std::ifstream::failbit) != 0) {
307 if (m_consoleEnabled == enabled) {
313 m_consoleEnabled = enabled;
349 if (m_fileEnabled == enabled) {
355 m_fileEnabled = enabled;
387 return m_settings.get();
397 if (settings.get() == m_settings.get()) {
403 m_settings = settings;
409std::string LoggerBuffer::getTimestamp()
const
411 static const std::string TIMESTAMP_FORMAT =
"%Y-%m-%d %H:%M:%S";
413 auto currentClock = std::chrono::system_clock::now();
414 std::time_t currentTime = std::chrono::system_clock::to_time_t(currentClock);
416 auto seconds = std::chrono::duration_cast<std::chrono::seconds>(currentClock.time_since_epoch());
417 auto millisecs = std::chrono::duration_cast<std::chrono::milliseconds>(currentClock.time_since_epoch() - seconds);
418 std::array<char, 11> millisecsBuffer;
419 std::snprintf(millisecsBuffer.data(), millisecsBuffer.size(),
"%03u",
static_cast<unsigned int>(millisecs.count()));
421 std::string timestamp;
422 timestamp.resize(23);
423 std::strftime(×tamp[0], timestamp.size(), TIMESTAMP_FORMAT.c_str(), localtime(¤tTime));
425 timestamp[20] = millisecsBuffer[0];
426 timestamp[21] = millisecsBuffer[1];
427 timestamp[22] = millisecsBuffer[2];
447Logger::Logger(
const std::string &name,
const std::shared_ptr<LoggerBuffer> &buffer)
448 : std::ios(nullptr), std::ostream(nullptr),
450 m_buffer(buffer), m_bufferSettings(std::make_shared<LoggerBuffer::Settings>()),
451 m_defaultSeverity(log::LEVEL_INFO), m_defaultVisibility(log::VISIBILITY_MASTER),
452 m_consoleDisabledThreshold(log::LEVEL_NOTSET), m_consoleVerbosityThreshold(log::LEVEL_INFO),
453 m_fileDisabledThreshold(log::LEVEL_NOTSET), m_fileVerbosityThreshold(log::LEVEL_INFO)
456 basic_ios<char>::rdbuf(m_buffer.get());
459 m_bufferSettings->context =
"";
460 m_bufferSettings->indentation = 0;
461 m_bufferSettings->consoleTimestampEnabled =
false;
462 m_bufferSettings->fileTimestampEnabled =
true;
507 m_consoleDisabledThreshold = level;
529 m_fileDisabledThreshold = level;
540 assert(severity != log::Level::LEVEL_NOTSET);
541 m_defaultSeverity = severity;
551 return m_defaultSeverity;
582 assert(visibility != log::VISIBILITY_NOTSET);
583 m_defaultVisibility = visibility;
593 return m_defaultVisibility;
652 return m_bufferSettings->consoleTimestampEnabled;
662 if (m_bufferSettings->consoleTimestampEnabled == enabled) {
666 m_buffer->flush(
true);
668 m_bufferSettings->consoleTimestampEnabled = enabled;
683 m_consoleVerbosityThreshold = threshold;
692void Logger::enableBufferStreams(
log::Level severity, log::Visibility visibility)
695 bool isConsoleEnabled =
true;
696 if (severity <= m_consoleDisabledThreshold) {
697 isConsoleEnabled =
false;
698 }
else if (visibility == log::VISIBILITY_MASTER && (m_buffer->getRank() != 0)) {
699 isConsoleEnabled =
false;
701 isConsoleEnabled = (severity >= m_consoleVerbosityThreshold);
703 m_buffer->setConsoleEnabled(isConsoleEnabled);
706 bool isFileEnabled =
true;
707 if (severity <= m_fileDisabledThreshold) {
708 isFileEnabled =
false;
709 }
else if (visibility == log::VISIBILITY_MASTER && (m_buffer->getRank() != 0)) {
710 isFileEnabled =
false;
712 isFileEnabled = (severity >= m_fileVerbosityThreshold);
714 m_buffer->setFileEnabled(isFileEnabled);
728 return m_consoleVerbosityThreshold;
739 return m_bufferSettings->fileTimestampEnabled;
749 if (m_bufferSettings->fileTimestampEnabled == enabled) {
753 m_buffer->flush(
true);
755 m_bufferSettings->fileTimestampEnabled = enabled;
770 m_fileVerbosityThreshold = threshold;
782 return m_fileVerbosityThreshold;
792 if (m_bufferSettings->context == context) {
796 m_buffer->flush(
true);
798 m_bufferSettings->context = context;
808 return m_bufferSettings->context;
822 m_buffer->flush(
true);
824 m_bufferSettings->indentation += delta;
834 return m_bufferSettings->indentation;
865 print(line +
'\n', severity);
876 print(line +
'\n', visibility);
888 print(line +
'\n', severity, visibility);
932 print<const std::string &>(message, severity, visibility);
947std::unique_ptr<LoggerManager> LoggerManager::m_manager =
nullptr;
952std::string LoggerManager::BITPIT_LOG_NAME =
"bitpit";
957std::string LoggerManager::BITPIT_LOG_DIRECTORY =
".";
962LoggerManager::LoggerManager()
963 : m_defaultName(BITPIT_LOG_NAME), m_defaultDirectory(BITPIT_LOG_DIRECTORY),
964 m_mode(log::MODE_SEPARATE)
975 std::vector<std::string> loggerNames;
976 loggerNames.reserve(m_loggers.size());
977 for (
const auto &entry : m_loggers) {
978 loggerNames.push_back(entry.first);
982 for (
const std::string &name : loggerNames) {
995 m_manager = std::unique_ptr<LoggerManager>(
new LoggerManager());
1018 return cout(m_defaultName, defaultSeverity, defaultVisibility);
1043 if (m_loggers.count(name) == 0) {
1048 if (name == m_defaultName) {
1049 _create(name,
false, m_defaultDirectory, 1, 0);
1051 create(name,
false, m_defaultDirectory, 1, 0);
1055 Logger &logger = *(m_loggers.at(name));
1058 if (defaultSeverity != log::Level::LEVEL_NOTSET) {
1062 if (defaultVisibility != log::VISIBILITY_NOTSET) {
1084 return critical(m_defaultName, defaultVisibility);
1105 return cout(name, log::Level::LEVEL_CRITICAL, defaultVisibility);
1122 return error(m_defaultName, defaultVisibility);
1143 return cout(name, log::Level::LEVEL_ERROR, defaultVisibility);
1160 return warning(m_defaultName, defaultVisibility);
1181 return cout(name, log::Level::LEVEL_WARNING, defaultVisibility);
1198 return info(m_defaultName, defaultVisibility);
1219 return cout(name, log::Level::LEVEL_INFO, defaultVisibility);
1236 return debug(m_defaultName, defaultVisibility);
1257 return cout(name, log::Level::LEVEL_DEBUG, defaultVisibility);
1269 int nProcesses,
int rank)
1271 initialize(mode, m_defaultName, reset, m_defaultDirectory, nProcesses, rank);
1284 int nProcesses,
int rank)
1286 initialize(mode, m_defaultName, reset, directory, nProcesses, rank);
1300 const std::string &directory,
1301 int nProcesses,
int rank)
1304 log::cout().
println(
"Logger initialization has to be called before creating the loggers.");
1312 m_defaultName = name;
1313 m_defaultDirectory = directory;
1316 _create(m_defaultName, reset, directory, nProcesses, rank);
1328 int nProcesses,
int rank)
1330 create(name, reset, m_defaultDirectory, nProcesses, rank);
1343 const std::string &directory,
1344 int nProcesses,
int rank)
1350 m_loggerUsers[name]++;
1352 cout(name) <<
"Detected an attemp to create the logger \"" << name <<
"\" twice" << std::endl;
1353 cout(name) <<
"The previously created logger will be used." << std::endl;
1355 }
else if (name == m_defaultName) {
1356 cout(m_defaultName) <<
"Detected an attemp to overwrite the default logger" << std::endl;
1357 cout(m_defaultName) <<
"The name of the default logger is \"" << name <<
"\"" << std::endl;
1359 }
else if (name ==
"") {
1360 cout() <<
"Detected an attemp to create a logger with an empty name" << std::endl;
1365 if (m_mode == log::MODE_SEPARATE) {
1366 _create(name, reset, directory, nProcesses, rank);
1369 _create(name, defaultLogger.m_buffer);
1391 int &nUsers = m_loggerUsers[name];
1395 if (nUsers == 0 || force) {
1397 m_loggers.erase(name);
1398 m_loggerUsers.erase(name);
1401 if (m_fileStreams.count(name) > 0) {
1403 std::ofstream &fileStream = *(m_fileStreams.at(name));
1407 m_fileStreams.erase(name);
1424 return (m_loggers.count(name) != 0);
1439 return (m_loggers.size() > 0);
1459 cout().
println(
"The policy has to be set before creating the loggers.");
1486void LoggerManager::_create(
const std::string &name,
bool reset,
1487 const std::string &directory,
1488 int nProcesses,
int rank)
1496 if (nProcesses > 1) {
1500 std::string filePath = fileHandler.
getPath();
1503 std::ios_base::openmode fileMode;
1505 fileMode = std::ofstream::out;
1507 fileMode = std::ofstream::app;
1510 m_fileStreams[name] = std::unique_ptr<std::ofstream>(
new std::ofstream());
1511 std::ofstream &fileStream = *(m_fileStreams.at(name));
1512 fileStream.rdbuf()->pubsetbuf(0, 0);
1513 fileStream.open(filePath, fileMode);
1516 std::ostream &consoleStream = std::cout;
1519 std::shared_ptr<LoggerBuffer> buffer = std::make_shared<LoggerBuffer>(nProcesses, rank, 256);
1520 buffer->setFileStream(&fileStream);
1521 buffer->setConsoleStream(&consoleStream);
1524 _create(name, buffer);
1533void LoggerManager::_create(
const std::string &name, std::shared_ptr<LoggerBuffer> &buffer)
1535 m_loggers[name] = std::unique_ptr<Logger>(
new Logger(name, buffer));
1536 m_loggerUsers[name] = 1;
1551 for (
auto &entry : m_loggers) {
1552 entry.second->setVerbosities(threshold);
1567 for (
auto &entry : m_loggers) {
1568 entry.second->setConsoleVerbosity(threshold);
1583 for (
auto &entry : m_loggers) {
1584 entry.second->setFileVerbosity(threshold);
1595 return m_defaultName;
1605 return m_defaultDirectory;
Creates file names and checks status.
std::string getPath() const
void setParallel(bool p_)
void setDirectory(const std::string &d_)
void setName(const std::string &n_)
void setAppendix(const std::string &a_)
std::ofstream & getFileStream()
LoggerBuffer(int nProcesses, int rank, std::size_t bufferSize=256)
void setFileEnabled(bool enabled)
void setSettings(const std::shared_ptr< Settings > &settings)
int getProcessCount() const
const Settings * getSettings() const
void setFileStream(std::ofstream *file)
void setConsoleEnabled(bool enabled)
std::ostream & getConsoleStream()
int flush(bool terminate)
void setConsoleStream(std::ostream *console)
void create(const std::string &name, bool reset=false, int nProcesses=1, int rank=0)
bool setMode(log::Mode mode)
bool exists(const std::string &name) const
Logger & debug(log::Visibility visibility=log::VISIBILITY_NOTSET)
bool destroy(const std::string &name, bool force=false)
void setVerbosities(log::Level threshold)
Logger & critical(log::Visibility visibility=log::VISIBILITY_NOTSET)
std::string getDefaultDirectory() const
log::Mode getMode() const
Logger & cout(log::Level defualtSeverity=log::Level::LEVEL_NOTSET, log::Visibility defualtVisibility=log::VISIBILITY_NOTSET)
Logger & warning(log::Visibility visibility=log::VISIBILITY_NOTSET)
static LoggerManager & manager()
Logger & error(log::Visibility visibility=log::VISIBILITY_NOTSET)
void setFileVerbosity(log::Level threshold)
std::string getDefaultName() const
Logger & info(log::Visibility visibility=log::VISIBILITY_NOTSET)
bool isInitialized() const
void setConsoleVerbosity(log::Level threshold)
void initialize(log::Mode mode, bool reset, int nProcesses, int rank)
void setDefaultVisibility(log::Visibility visibility)
void setDefaultSeverity(log::Level severity)
void setVerbosities(log::Level threshold)
void setConsoleTimestampEnabled(bool enabled)
void setFileVerbosity(log::Level threshold)
log::Level getDefaultSeverity()
void setConsoleVerbosity(log::Level threshold)
void setPriority(log::Priority priority)
bool isConsoleTimestampEnabled() const
void disable(log::Level=log::Level::LEVEL_CRITICAL)
log::Visibility getDefaultVisibility()
log::Level getFileVerbosity()
void setIndentation(int delta)
void disableConsole(log::Level=log::Level::LEVEL_CRITICAL)
bool isFileTimestampEnabled() const
void setVisibility(log::Visibility visibility)
void setFileTimestampEnabled(bool enabled)
void println(const std::string &message)
void disableFile(log::Level=log::Level::LEVEL_CRITICAL)
std::string getName() const
void print(const std::string &message)
void setContext(const std::string &context)
void setTimestampEnabled(bool enabled)
log::Level getConsoleVerbosity()
log::Visibility getVisibility()
log::Priority getPriority()
LoggerManipulator< log::Level > defaultSeverity(const log::Level &severity)
Logger & cout(log::Level defaultSeverity, log::Visibility defaultVisibility)
LoggerManipulator< log::Visibility > defaultVisibility(const log::Visibility &visibility)
LoggerManipulator< log::Level > verbosities(const log::Level &threshold)
Logger & setPriority(Logger &logger, const log::Priority &priority)
LoggerManipulator< log::Visibility > visibility(const log::Visibility &visibility)
Logger & critical(log::Visibility defaultVisibility)
Logger & disable(Logger &logger, const log::Level &level)
LoggerManipulator< log::Level > consoleVerbosity(const log::Level &threshold)
Logger & setDefaultSeverity(Logger &logger, const log::Level &severity)
LoggerManipulator< log::Priority > priority(const log::Priority &priority)
Logger & error(log::Visibility defaultVisibility)
Logger & warning(log::Visibility defaultVisibility)
LoggerManipulator< log::Level > fileVerbosity(const log::Level &threshold)
Logger & debug(log::Visibility defaultVisibility)
LoggerManipulator< int > indent(int delta)
Logger & setFileVerbosity(Logger &logger, const log::Level &threshold)
Logger & setVisibility(Logger &logger, const log::Visibility &visibility)
Logger & info(log::Visibility defaultVisibility)
Logger & disableConsole(Logger &logger, const log::Level &level)
Logger & setDefaultVisibility(Logger &logger, const log::Visibility &visibility)
LoggerManager & manager()
Logger & setVerbosities(Logger &logger, const log::Level &threshold)
Logger & setIndentation(Logger &logger, const int &delta)
LoggerManipulator< std::string > context(const std::string &context)
Logger & disableFile(Logger &logger, const log::Level &level)
Logger & setConsoleVerbosity(Logger &logger, const log::Level &threshold)
Logger & setContext(Logger &logger, const std::string &context)