Program Listing for File Logger.h
↰ Return to documentation for file (Utilities/Logger.h)
#ifndef __Logger_h__
#define __Logger_h__
#include <sstream>
#include <iostream>
#include <fstream>
#include <ctime>
#include <iomanip>
#include <vector>
#include <memory>
namespace Utilities
{
enum LogLevel { DEBUG=0, INFO, WARN, ERR };
class LogSink
{
protected:
LogLevel m_minLevel;
public:
LogSink(const LogLevel minLevel) : m_minLevel(minLevel) {}
virtual ~LogSink() {}
virtual void write(const LogLevel level, const std::string &str) = 0;
void setMinLevel(LogLevel level) { m_minLevel = level; }
};
class ConsoleSink : public LogSink
{
public:
ConsoleSink(const LogLevel minLevel) : LogSink(minLevel) {}
virtual void write(const LogLevel level, const std::string &str)
{
if (level < m_minLevel)
return;
// if (level == LogLevel::INFO)
// std::cout << "Info: ";
// else
if (level == LogLevel::WARN)
std::cout << "Warning: ";
else if (level == LogLevel::ERR)
std::cerr << "Error: ";
std::cout << str << std::endl;
}
};
class FileSink : public LogSink
{
protected:
std::ofstream m_file;
public:
FileSink(const LogLevel minLevel, const std::string &fileName)
: LogSink(minLevel)
{
m_file.open(fileName.c_str(), std::ios::out);
if (m_file.fail())
std::cerr << "Failed to open file: " << fileName << "\n";
}
virtual ~FileSink()
{
m_file.close();
}
virtual void write(const LogLevel level, const std::string &str)
{
if (level < m_minLevel)
return;
// print time
time_t t = time(0); // get time now
struct tm * now = localtime(&t);
m_file << "[" << (now->tm_year + 1900) << '-'
<< std::setfill('0') << std::setw(2)
<< (now->tm_mon + 1) << '-'
<< std::setfill('0') << std::setw(2)
<< now->tm_mday << " "
<< std::setfill('0') << std::setw(2)
<< now->tm_hour << ":"
<< std::setfill('0') << std::setw(2)
<< now->tm_min << ":"
<< std::setfill('0')
<< std::setw(2) << now->tm_sec << "] ";
// print level
if (level == LogLevel::DEBUG)
m_file << "Debug: ";
else if (level == LogLevel::INFO)
m_file << "Info: ";
else if (level == LogLevel::WARN)
m_file << "Warning: ";
else if (level == LogLevel::ERR)
m_file << "Error: ";
m_file << str << std::endl;
m_file.flush();
}
};
class BufferSink : public Utilities::LogSink
{
protected:
std::vector<std::pair<Utilities::LogLevel, std::string>> m_buffer;
public:
BufferSink(const LogLevel minLevel) : LogSink(minLevel)
{
m_buffer.reserve(10000);
}
virtual void write(const Utilities::LogLevel level, const std::string& str)
{
if (level < m_minLevel)
return;
m_buffer.push_back({ level, str });
}
std::vector<std::pair<Utilities::LogLevel, std::string>>& getBuffer()
{
return m_buffer;
}
void clearBuffer()
{
m_buffer.clear();
}
};
class Logger
{
public:
Logger() { m_active = true; }
~Logger()
{
m_sinks.clear();
}
protected:
std::vector<std::shared_ptr<LogSink>> m_sinks;
bool m_active;
public:
// Todo: format
void addSink(std::shared_ptr<LogSink> sink)
{
m_sinks.push_back(sink);
}
void removeSink(std::shared_ptr<LogSink> sink)
{
for (auto it = m_sinks.begin(); it != m_sinks.end(); it++)
{
if (*it == sink)
{
m_sinks.erase(it);
break;
}
}
}
std::vector<std::shared_ptr<LogSink>>& getSinks()
{
return m_sinks;
}
void write(const LogLevel level, const std::string &str)
{
if (!m_active)
return;
for (unsigned int i = 0; i < m_sinks.size(); i++)
m_sinks[i]->write(level, str);
}
void activate(const bool b) { m_active = b; }
};
class LogStream
{
public:
LogStream(Logger *logger, const LogLevel level) : m_logger(logger), m_level(level) {}
template <typename T>
LogStream& operator<<(T const & value)
{
m_buffer << value;
return *this;
}
~LogStream() { m_logger->write(m_level, m_buffer.str()); }
protected:
LogLevel m_level;
Logger *m_logger;
std::ostringstream m_buffer;
};
extern Utilities::Logger logger;
#define LOG_DEBUG Utilities::LogStream(&Utilities::logger, Utilities::LogLevel::DEBUG)
#define LOG_INFO Utilities::LogStream(&Utilities::logger, Utilities::LogLevel::INFO)
#define LOG_WARN Utilities::LogStream(&Utilities::logger, Utilities::LogLevel::WARN)
#define LOG_ERR Utilities::LogStream(&Utilities::logger, Utilities::LogLevel::ERR)
#define INIT_LOGGING Utilities::Logger Utilities::logger;
}
#endif