mirror of
https://github.com/binary-kitchen/doorlockd
synced 2024-11-16 03:59:11 +01:00
193 lines
4.6 KiB
C++
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) {
|
||
|
}
|