1
0
mirror of https://github.com/binary-kitchen/doorlockd synced 2024-06-11 18:52:34 +02:00
doorlockd-mirror/doorlockd/logger.cpp
2015-05-14 22:03:00 +02:00

193 lines
4.6 KiB
C++

// (c) 2015 Ralf Ramsauer - Logger class from the sdfs project
#include <iostream>
#include <cstdarg>
#include <ctime>
#include <iomanip>
#include <sstream>
#include <map>
#include <mutex>
#ifdef _WIN32
#include <Windows.h>
#endif
#include "config.h"
#include "logger.h"
using std::map;
using std::string;
using std::mutex;
using std::lock_guard;
using std::move;
using std::cerr;
using std::endl;
#ifdef USE_COLORIZED_LOGS
#ifdef _WIN32 // If Windows, Use Windows Terminal coloring
const static map<LogLevel, WORD> colorAttribute = {
{LogLevel::error, FOREGROUND_RED },
{LogLevel::warning, FOREGROUND_RED | FOREGROUND_GREEN },
{LogLevel::notice, FOREGROUND_BLUE },
{LogLevel::info, FOREGROUND_GREEN },
{LogLevel::debug, FOREGROUND_BLUE | FOREGROUND_RED },
{LogLevel::debug2, FOREGROUND_BLUE | FOREGROUND_RED },
};
#else // Use ANSI Escape sequences
const static map<LogLevel, string> prefix_ansicolor = {
{LogLevel::error, "\x1b[1m\x1b[31m" },
{LogLevel::warning, "\x1b[1m\x1b[33m" },
{LogLevel::notice, "\x1b[1m\x1b[34m" },
{LogLevel::info, "\x1b[1m\x1b[32m" },
{LogLevel::debug, "\x1b[1m\x1b[35m" },
{LogLevel::debug2, "\x1b[1m\x1b[36m" },
};
const static string suffix_ansireset = "\x1b[0m";
#endif
#endif
const static map<LogLevel, string> logLevel = {
{LogLevel::error, "ERROR " },
{LogLevel::warning, "WARNING" },
{LogLevel::notice, "NOTICE " },
{LogLevel::info, "INFO " },
{LogLevel::debug, "DEBUG " },
{LogLevel::debug2, "DEBUG2 " },
};
Logger::Logger(const LogLevel level) :
_level(level),
_ostreamMutex()
{
}
Logger::~Logger()
{
}
Logger &Logger::get()
{
static Logger l(DEFAULT_LOG_LEVEL);
return l;
}
void Logger::operator ()(const std::string &message, const LogLevel level) const
{
if(level > _level)
{
return;
}
std::ostringstream prefix;
auto t = std::time(nullptr);
auto tm = *std::localtime(&t);
#if defined(USE_COLORIZED_LOGS) && !defined(_WIN32)
prefix << prefix_ansicolor.at(level);
#endif
// GCC does not support put_time :-(
/*stringstream ss;
ss << std::put_time(&tm, "%d-%m-%Y %H-%M-%S");
prefix = "[" + ss.str() + "] ";*/
const size_t BUFFER_SIZE = 80;
char timeBuffer[BUFFER_SIZE];
std::strftime(timeBuffer, BUFFER_SIZE, "%Y-%m-%d %H:%M:%S", &tm);
prefix << "[" << timeBuffer << "] -- " << logLevel.at(level) << " :: ";
// Critical section
{
lock_guard<mutex> lock(_ostreamMutex);
#if defined(USE_COLORIZED_LOGS) && !defined(_WIN32)
cerr << prefix.str() << message << suffix_ansireset << endl;
cerr.flush();
#elif defined(USE_COLORIZED_LOGS) && defined(_WIN32)
// taken from GTEST
const HANDLE stdout_handle = GetStdHandle(STD_ERROR_HANDLE);
// Gets the current text color.
CONSOLE_SCREEN_BUFFER_INFO buffer_info;
GetConsoleScreenBufferInfo(stdout_handle, &buffer_info);
const WORD old_color_attrs = buffer_info.wAttributes;
// We need to flush the stream buffers into the console before each
// SetConsoleTextAttribute call lest it affect the text that is already
// printed but has not yet reached the console.
cerr.flush();
SetConsoleTextAttribute(stdout_handle,
colorAttribute.at(level) | FOREGROUND_INTENSITY);
cerr << prefix.str() << message << endl;
cerr.flush();
// Restores the text color.
SetConsoleTextAttribute(stdout_handle, old_color_attrs);
#else
cerr << prefix.str() << message << endl;
cerr.flush();
#endif
}
}
void Logger::operator ()(const std::ostringstream &message, const LogLevel level) const
{
(*this)(message.str(), level);
}
void Logger::operator ()(const LogLevel level, const char* format, ...) const
{
if(level > _level)
{
return;
}
va_list argp;
char* message = nullptr;
// determine buffer length
va_start(argp, format);
int size = vsnprintf(nullptr, 0, format, argp) + 1;
va_end(argp);
if (size >= 0)
{
message = (char*)malloc(size);
if (message == nullptr)
{
(*this)("[LOGGER] CRITICAL: MEMORY ALLOCATION ERROR",
LogLevel::error);
}
va_start(argp,format);
vsnprintf(message, size, format, argp);
va_end(argp);
(*this)(string(message), level);
free(message);
} else {
(*this)("[LOGGER] CRITICAL: VSNPRINTF ERROR",
LogLevel::error);
}
}
void Logger::level(const LogLevel level)
{
_level = level;
}
LogLevel Logger::level() const
{
return _level;
}
void foo(void) {
}