Skip to content

Commit

Permalink
Merge pull request #359 from cniethammer/logger-update
Browse files Browse the repository at this point in the history
Logger update
  • Loading branch information
FG-TUM authored Jan 7, 2025
2 parents b2c7c3d + 3c6e79c commit 8411964
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 105 deletions.
16 changes: 11 additions & 5 deletions src/MarDyn.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,10 @@ int run_unit_tests(const Values &options, const std::vector<std::string> &args)
int main(int argc, char** argv) {
#ifdef ENABLE_MPI
MPI_Init(&argc, &argv);
int world_rank = 0;
MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
#endif
Log::global_log = std::make_unique<Log::Logger>(Log::Info);

// Open scope to exclude MPI_Init() and MPI_Finalize().
// This way, all simulation objects are cleaned up before MPI finalizes.
Expand All @@ -149,11 +152,14 @@ int main(int argc, char** argv) {
if( options.is_set_by_user("logfile") ) {
// Print to file
std::string logfileNamePrefix(options.get("logfile"));
std::cout << "Using logfile with prefix " << logfileNamePrefix << std::endl;
Log::global_log = std::make_unique<Log::Logger>(Log::Info, logfileNamePrefix);
} else {
// Print to stream (default: std::cout)
Log::global_log = std::make_unique<Log::Logger>(Log::Info);
std::string logfile_name = logfileNamePrefix;
#ifdef ENABLE_MPI
logfile_name += "_R" + std::to_string(world_rank);
#endif
logfile_name += ".log";
Log::global_log->info() << "Using logfile " << logfile_name << " for further log output." << std::endl;
std::shared_ptr<std::ostream> logfile_ptr = std::make_shared<std::ofstream>(logfile_name);
Log::global_log->set_log_stream(logfile_ptr);
}

#ifdef ENABLE_MPI
Expand Down
4 changes: 2 additions & 2 deletions src/plugins/VectorizationTuner.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ enum MoleculeCntIncreaseTypeEnum{
both //!< both, do linear and exponential measurements, linear measurements will stop after 32 molecules.
};


#include <vector>
#include <fstream>
#include <string>
#include <vector>

#include "particleContainer/adapter/CellProcessor.h"
#include "particleContainer/adapter/FlopCounter.h"
Expand Down
33 changes: 3 additions & 30 deletions src/utils/Logger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,49 +2,22 @@

#include "Logger.h"

#include <memory>

namespace Log {

std::unique_ptr<Logger> global_log;

// Write to stream
Logger::Logger(logLevel level, std::ostream *os) :
_log_level(level), _msg_log_level(Log::Error),
_do_output(true), _filename(""),
// std::cout is managed globally,
// so do nothing when _log_stream goes out of scope
// --> any passed ostream other than std::cout needs to be
// deleted manually!
_log_stream(os, [](std::ostream*){/* no-op deleter */}),
logLevelNames(), _starttime(), _rank(0)
{
init_starting_time();
this->init_log_levels();
#ifdef ENABLE_MPI
MPI_Comm_rank(MPI_COMM_WORLD, &_rank);
#endif
*_log_stream << std::boolalpha; // Print boolean as true/false
}

// Write to file
Logger::Logger(logLevel level, std::string prefix) :
Logger::Logger(logLevel level, std::shared_ptr<std::ostream> os) :
_log_level(level), _msg_log_level(Log::Error),
_do_output(true), _filename(""), _log_stream(nullptr),
_do_output(true),
_log_stream(os),
logLevelNames(), _starttime(), _rank(0)
{
init_starting_time();
this->init_log_levels();
std::stringstream filenamestream;
filenamestream << prefix;
#ifdef ENABLE_MPI
MPI_Comm_rank(MPI_COMM_WORLD, &_rank);
filenamestream << "_R" << _rank;
#endif
filenamestream << ".log";
_filename = filenamestream.str();

_log_stream = std::make_shared<std::ofstream>(_filename.c_str());
*_log_stream << std::boolalpha; // Print boolean as true/false
}

Expand Down
93 changes: 25 additions & 68 deletions src/utils/Logger.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,15 @@

#define USE_GETTIMEOFDAY

#include <iostream>
#include <fstream>
#include <cstdlib>
#include <chrono>
#include <ctime>
#include <cctype>
#include <iomanip>
#include <iostream>
#include <map>
#include <ctime>
#include <string>
#include <sstream>
#include <chrono>
#include <memory>

#ifdef USE_GETTIMEOFDAY
#include <sys/time.h>
#endif
#include <string>
#include <utility>

#ifdef ENABLE_MPI
#include <mpi.h>
Expand Down Expand Up @@ -71,14 +66,7 @@ typedef enum {

/** @brief The Logger class provides a simple interface to handle log messages.
*
* Provides easy interface to handle log messages. Initialize either with
* output level and stream or output level and filename or use default constructor
* values (Error, &(std::cout)).
* Note: Due to the default argument (std::cout), the passed ostream pointer
* will not be deleted automatically! Any passed ostream pointer other than
* std::cout must be deleted manually!
* With a given file basename and MPI Support each rank will create
* and write to its own file.
* The logger provides an easy way to output logging messages with various log levels.
* For writing log messages use fatal(), error(), warning(), info() or debug() as
* with normal streams, e.g.
* > log.error() << "Wrong parameter." << std::endl;
Expand All @@ -96,15 +84,10 @@ class Logger {
logLevel _log_level;
logLevel _msg_log_level;
bool _do_output;
std::string _filename;
std::shared_ptr<std::ostream> _log_stream;
std::map<logLevel, std::string> logLevelNames;
#ifdef USE_GETTIMEOFDAY
timeval _starttime;
#else
time_t _starttime;
#endif

std::chrono::system_clock::time_point _starttime;
int _rank;

/// initialize the list of log levels with the corresponding short names
Expand All @@ -118,32 +101,16 @@ class Logger {
logLevelNames.insert(std::pair<logLevel, std::string>(All, "ALL" ));
}

// don't allow copy-construction
Logger(const Logger&) : _log_level(Log::Error), _msg_log_level(Log::Error), _do_output(true),
_filename(""), _log_stream(nullptr), logLevelNames(), _starttime(), _rank(0)
{ }

// don't allow assignment
Logger& operator=(const Logger&) { return *this; }

public:
/**
* Constructor for a logger to a stream.
*
* Initializes the log level, log stream and the list of log level names.
* If ENABLE_MPI is enabled by default, all process perform logging output.
* Note: Due to the default argument (std::cout), the passed ostream pointer
* will not be deleted automatically! Any passed ostream pointer other than
* std::cout must be deleted manually!
* Note: The default stream used (std::cout) cannot be deleted. Therefore the
* passed shared pointer to it uses a no-op deleter function.
*/
Logger(logLevel level = Log::Error, std::ostream *os = &(std::cout));
/**
* Constructor for a logger to a file.
*
* Initializes the log level, log stream and the list of log level names.
* If ENABLE_MPI is enabled by default, all process perform logging output.
*/
Logger(logLevel level, std::string prefix);
Logger(logLevel level = Log::Error, std::shared_ptr<std::ostream> os = std::shared_ptr<std::ostream>(&std::cout, [](void*){ /* no-op */}));

~Logger() = default;

Expand Down Expand Up @@ -180,22 +147,14 @@ class Logger {
_msg_log_level = level;
if (_msg_log_level <= _log_level && _do_output) {
// Include timestamp
const auto now = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
tm unused{};
const auto* lt = localtime_r(&now, &unused);
//*_log_stream << ctime(&t) << " ";
std::stringstream timestampstream;
// maybe sprintf is easier here...
timestampstream << std::setfill('0') << std::setw(4) << (1900 + lt->tm_year) << std::setw(2) << (1 + lt->tm_mon) << std::setw(2) << lt->tm_mday << "T" << std::setw(2) << lt->tm_hour << std::setw(2) << lt->tm_min << std::setw(2) << lt->tm_sec;
*_log_stream << logLevelNames[level] << ":\t" << timestampstream.str() << " ";
//timestampstream.str(""); timestampstream.clear();
#ifdef USE_GETTIMEOFDAY
timeval tod;
gettimeofday(&tod, 0);
*_log_stream << std::setw(8) << tod.tv_sec - _starttime.tv_sec + (tod.tv_usec - _starttime.tv_usec) / 1.E6 << " ";
#else
*_log_stream << t-_starttime << "\t";
#endif
const auto now = std::chrono::system_clock::now();
const auto time_since_start = now - _starttime;

const auto now_time_t = std::chrono::system_clock::to_time_t(now);
std::tm now_local{};
localtime_r(&now_time_t, &now_local);
*_log_stream << logLevelNames[level] << ":\t" << std::put_time(&now_local, "%Y-%m-%dT%H:%M:%S") << " ";
*_log_stream << std::setw(8) << std::chrono::duration<double>(time_since_start).count() << " ";

*_log_stream << "[" << _rank << "]\t";
}
Expand Down Expand Up @@ -230,10 +189,8 @@ class Logger {
}
/// set log level from string
logLevel set_log_level(std::string l) {
// identify the loglevel by comparing the first char of the names
for (const auto& [lvl, name] : logLevelNames) {
// case-insensitive matching
if (std::toupper(name[0]) == std::toupper(l[0])) {
if (name == l) {
_log_level = lvl;
return _log_level;
}
Expand All @@ -248,6 +205,10 @@ class Logger {
return _log_level;
}

void set_log_stream(std::shared_ptr<std::ostream> os) {
_log_stream = os;
}

/// switch on / off output
bool set_do_output(bool val) {
return _do_output = val;
Expand All @@ -259,11 +220,7 @@ class Logger {

/// initialize starting time
void init_starting_time() {
#ifdef USE_GETTIMEOFDAY
gettimeofday(&_starttime, 0);
#else
_starttime = time(NULL);
#endif
_starttime = std::chrono::system_clock::now();
}

/* methods for easy handling of output processes */
Expand Down

0 comments on commit 8411964

Please sign in to comment.