#46 - C++ Logger Class

Date: 2019-02-02 12:00 - C++

Simple classes to help you log events or errors to a file or anywhere you need.

// Logger.h
#pragma once

#include <string>
#include <mutex>

#define LOG_MSG(msg) YourNamespace::Logger::defaultLogger()->log(YourNamespace::Severity::NONE, (msg))
#define LOG_INFO(msg) YourNamespace::Logger::defaultLogger()->log(YourNamespace::Severity::INFO, (msg))
#define LOG_WARNING(msg) YourNamespace::Logger::defaultLogger()->log(YourNamespace::Severity::WARNING, (msg))
#define LOG_DEBUG(msg) YourNamespace::Logger::defaultLogger()->log(YourNamespace::Severity::DEBUG, (msg))
#define LOG_ERROR(msg) YourNamespace::Logger::defaultLogger()->log(YourNamespace::Severity::ERROR, (msg))
#define LOG_FATAL(msg) YourNamespace::Logger::defaultLogger()->log(YourNamespace::Severity::FATAL, (msg))

namespace YourNamespace {
	enum class Severity { NONE, INFO, WARNING, DEBUG, ERROR, FATAL };
	class Logger {
		static Logger* _defaultLogger;
	public:
		static Logger* defaultLogger();
	private:
		std::mutex writeMutex;
		std::string getSeverityName(Severity severity);
	protected:
		virtual void write(const std::string& msg) = 0;
		virtual std::string getHeader();
	public:
		Logger(const std::string& name);
		void log(Severity severity, const std::string& msg);
		virtual ~Logger();
	};
}

// Logger.cpp
#include "Logger.h"

#include <sstream>
#include <iomanip>
#include <ctime>

#include "FileLogger.h"

using namespace YourNamespace;

Logger* Logger::_defaultLogger = new FileLogger("default.log");

Logger* Logger::defaultLogger() {
	return _defaultLogger;
}

std::string Logger::getSeverityName(Severity severity) {
	switch(severity) {
		case Severity::NONE:
			return " ";
		case Severity::INFO:
			return "[INFO] ";
		case Severity::WARNING:
			return "[WARNING] ";
		case Severity::DEBUG:
			return "[DEBUG] ";
		case Severity::ERROR:
			return "[ERROR] ";
		case Severity::FATAL:
			return "[FATAL] ";
	}
	return "[UNKNOWN] ";
}

std::string Logger::getHeader() {
	std::time_t t = std::time(nullptr);
    std::tm tm;
	localtime_s(&tm, &t);
	std::stringstream header;
	header << "[" << std::put_time(&tm, "%H:%M:%S") << "]";
    return header.str();
}
Logger::Logger(const std::string& name) {
}

void Logger::log(Severity severity, const std::string& msg) {
	std::lock_guard<std::mutex> lock(writeMutex);

	write(getHeader() + getSeverityName(severity) + msg);
}

Logger::~Logger() {
}

// FileLogger.h
#pragma once

#include "Logger.h"

#include <fstream>
#include <memory>

namespace YourNamespace {
	class FileLogger : public YourNamespace::Logger {
		std::unique_ptr<std::ofstream> fileOut;
	protected:
		void write(const std::string& msg);
	public:
		FileLogger(const std::string& name);
		~FileLogger();
	};
}

// FileLogger.cpp
#include "FileLogger.h"

using namespace YourNamespace;

void FileLogger::write(const std::string& msg) {
	(*fileOut) << msg << std::endl;
	fileOut->flush();
}

FileLogger::FileLogger(const std::string& name) : Logger(name), fileOut(new std::ofstream) {
	fileOut->open(name, std::ios_base::binary|std::ios_base::out);
	if(!fileOut->is_open())
		throw std::runtime_error("LOGGER: Unable to open an output stream.");
}

FileLogger::~FileLogger() {
	if(fileOut)
		fileOut->close();
}

Previous snippet | Next snippet