Updated the logging system
This commit is contained in:
parent
41fb8415cd
commit
b9e2da8bb4
@ -203,11 +203,11 @@ std::shared_ptr<BasicChannel> BasicChannelTree::findChannelByPath(const std::str
|
||||
index = found + 1;
|
||||
} while (index != 0 && entries.size() <= maxChannelDeep);
|
||||
|
||||
debugMessage("Parsed channel path '" + path + "'. Entries:");
|
||||
debugMessage(LOG_GENERAL, "Parsed channel path \"{}\". Entries:", path);
|
||||
std::shared_ptr<BasicChannel> current = nullptr;
|
||||
for (const auto &name : entries) {
|
||||
current = this->findChannel(name, current);
|
||||
debugMessage(" - '" + name + "' (" + (current ? "found" : "unknown") + ")");
|
||||
debugMessage(LOG_GENERAL, " - \"{}\" {}", name, (current ? "found" : "unknown"));
|
||||
if (!current) break;
|
||||
}
|
||||
return current;
|
||||
|
@ -1,118 +1,119 @@
|
||||
#include "LogUtils.h"
|
||||
#include "LogSinks.h"
|
||||
#include <iomanip>
|
||||
#include <fstream>
|
||||
#include <spdlog/spdlog.h>
|
||||
#include <experimental/filesystem>
|
||||
#include <spdlog/formatter.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace spdlog;
|
||||
namespace fs = std::experimental::filesystem;
|
||||
|
||||
namespace logger {
|
||||
void TerminalSink::log(const spdlog::details::log_msg &msg) {
|
||||
#ifdef HAVE_CXX_TERMINAL
|
||||
void TerminalSink::sink_it_(const spdlog::details::log_msg &msg) {
|
||||
memory_buf_t formatted;
|
||||
this->formatter_->format(msg, formatted);
|
||||
|
||||
std::string_view message{formatted.data(), formatted.size()};
|
||||
|
||||
#ifdef HAVE_CXX_TERMINAL
|
||||
if (terminal::active()) {
|
||||
auto strMsg = msg.formatted.str();
|
||||
size_t index = 0;
|
||||
//Split the string at new lines
|
||||
size_t index{0}, found{0};
|
||||
do {
|
||||
auto eIndex = strMsg.find('\n', index);
|
||||
auto str = terminal::parseCharacterCodes(strMsg.substr(index, eIndex - index));
|
||||
terminal::instance()->writeMessage(str);
|
||||
index = eIndex + 1;
|
||||
} while (index != 0 && index < strMsg.length()); //if eindex == npos and we add the 1 we get 0 :)
|
||||
found = message.find('\n', index);
|
||||
const auto length = (found == -1 ? message.length() : found) - index;
|
||||
const auto line = message.substr(index, length);
|
||||
|
||||
index = found;
|
||||
if(length == 0) continue;
|
||||
|
||||
terminal::instance()->writeMessage(std::string{line});
|
||||
} while(++index);
|
||||
} else
|
||||
#endif
|
||||
cout << msg.formatted.str();
|
||||
#endif
|
||||
cout << message;
|
||||
}
|
||||
|
||||
void TerminalSink::flush() {}
|
||||
void TerminalSink::flush_() {}
|
||||
|
||||
bool TerminalSink::should_log_(const details::log_msg &msg) const {
|
||||
auto _force_message = dynamic_cast<const ::logger::force_log_msg*>(&msg);
|
||||
if(_force_message && _force_message->force)
|
||||
return true;
|
||||
return sink::should_log_(msg);
|
||||
}
|
||||
|
||||
ColoredFileSink::ColoredFileSink(const filename_t &base_filename, size_t max_size, size_t max_files)
|
||||
: rotating_file_sink(
|
||||
base_filename, max_size, max_files) {}
|
||||
|
||||
void ColoredFileSink::_sink_it(const details::log_msg &msg) {
|
||||
details::log_msg _clone;
|
||||
|
||||
#ifdef HAVE_CXX_TERMINAL
|
||||
if (::logger::currentConfig()->file_colored)
|
||||
_clone.formatted << ANSI_RESET << terminal::parseCharacterCodes(msg.formatted.str());
|
||||
else
|
||||
_clone.formatted << terminal::stripCharacterCodes(msg.formatted.str());
|
||||
#else
|
||||
_clone.formatted << msg.formatted.str();
|
||||
#endif
|
||||
sinks::rotating_file_sink_mt::_sink_it(_clone);
|
||||
}
|
||||
|
||||
void CostumeFormatter::format(spdlog::details::log_msg &msg) {
|
||||
msg.formatted.clear();
|
||||
|
||||
string lvlName = level::to_str(msg.level);
|
||||
transform(lvlName.begin(), lvlName.end(), lvlName.begin(), ::toupper);
|
||||
auto org_length = lvlName.length();
|
||||
|
||||
string msgColor;
|
||||
string msgSuffix;
|
||||
#ifdef HAVE_CXX_TERMINAL
|
||||
switch (msg.level) {
|
||||
case level::trace:
|
||||
lvlName = "§9" + lvlName;
|
||||
break;
|
||||
case level::info:
|
||||
lvlName = "§e" + lvlName;
|
||||
break;
|
||||
case level::warn:
|
||||
lvlName = "§6" + lvlName;
|
||||
break;
|
||||
case level::err:
|
||||
lvlName = "§4" + lvlName;
|
||||
break;
|
||||
case level::critical:
|
||||
lvlName = ANSI_BOLD ANSI_REVERSE ANSI_RED + lvlName;
|
||||
msgColor = ANSI_BOLD ANSI_REVERSE ANSI_RED;
|
||||
msgSuffix = ANSI_RESET;
|
||||
break;
|
||||
case level::debug:
|
||||
lvlName = "§9" + lvlName;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
auto strMsg = msg.raw.str();
|
||||
|
||||
auto tp = std::chrono::system_clock::to_time_t(msg.time);
|
||||
|
||||
stringstream prefix;
|
||||
prefix << "[" << std::put_time(std::localtime(&tp), "%F %T") << "] [" << lvlName << "§r] ";
|
||||
for(size_t i = org_length; i < 5; i++)
|
||||
prefix << " ";
|
||||
prefix << msgColor;
|
||||
|
||||
size_t index = 0;
|
||||
do {
|
||||
auto eIndex = strMsg.find('\n', index);
|
||||
auto m = strMsg.substr(index, eIndex - index);
|
||||
msg.formatted << "§r" << prefix.str() << m << msgSuffix << "\n";
|
||||
index = eIndex + 1; //if eindex == npos and we add the 1 we get 0 :)
|
||||
} while (index != 0 && index < strMsg.length());
|
||||
}
|
||||
|
||||
inline std::string CostumeFormatter::time(chrono::time_point<log_clock> point) {
|
||||
inline void append_time(const log_clock::time_point& point, memory_buf_t& dest) {
|
||||
std::time_t time = log_clock::to_time_t(point);
|
||||
std::tm timetm = *std::localtime(&time);
|
||||
char buffer[9];
|
||||
strftime(buffer, 9, "%H:%M:%S", &timetm);
|
||||
return string(buffer, 8);
|
||||
|
||||
static constexpr auto max_length = 9;
|
||||
dest.reserve(dest.size() + max_length);
|
||||
|
||||
auto length = strftime(dest.end(), max_length, "%H:%M:%S", &timetm);
|
||||
if(length < 0)
|
||||
length = 0;
|
||||
|
||||
dest.resize(dest.size() + length);
|
||||
}
|
||||
|
||||
static constexpr std::array<std::string_view, spdlog::level::off + 1> level_mapping_colored{
|
||||
" [" ANSI_LIGHT_BLUE "TRACE" ANSI_RESET "] ",
|
||||
" [" ANSI_LIGHT_BLUE "DEBUG" ANSI_RESET "] ",
|
||||
" [" ANSI_YELLOW "INFO " ANSI_RESET "] ",
|
||||
" [" ANSI_BROWN "WARNING " ANSI_RESET "] ",
|
||||
" [" ANSI_RED "ERROR" ANSI_RESET "] ",
|
||||
" [" ANSI_RED ANSI_BOLD ANSI_REVERSE "CRITICAL" ANSI_RESET "] ",
|
||||
" [" ANSI_GRAY "OFF " ANSI_RESET "] "
|
||||
};
|
||||
|
||||
static constexpr std::array<std::string_view, spdlog::level::off + 1> level_mapping{
|
||||
" [TRACE] ",
|
||||
" [DEBUG] ",
|
||||
" [INFO ] ",
|
||||
" [WARNING ] ",
|
||||
" [ERROR] ",
|
||||
" [CRITICAL] ",
|
||||
" [OFF ] "
|
||||
};
|
||||
|
||||
void LogFormatter::format(const details::log_msg &msg, memory_buf_t &dest) {
|
||||
const auto append = [&](const std::string_view& message) { dest.append(message.begin(), message.end()); };
|
||||
|
||||
dest.clear();
|
||||
auto prefix_begin = dest.end();
|
||||
//Time
|
||||
{
|
||||
dest.push_back('[');
|
||||
append_time(msg.time, dest);
|
||||
dest.push_back(']');
|
||||
}
|
||||
|
||||
//Level
|
||||
{
|
||||
const auto& mapping = this->_colored ? level_mapping_colored : level_mapping;
|
||||
|
||||
size_t level = msg.level.value;
|
||||
if(level >= mapping.size())
|
||||
level = mapping.size() - 1;
|
||||
|
||||
append(mapping[level]);
|
||||
}
|
||||
auto prefix_end = dest.end();
|
||||
|
||||
//Append the prefix to every line
|
||||
std::string_view payload{msg.payload.data(), msg.payload.size()};
|
||||
size_t index{0}, found{0};
|
||||
while(true) {
|
||||
found = payload.find(spdlog::details::os::default_eol, index);
|
||||
auto line = payload.substr(index, (found == -1 ? payload.length() : found) - index);
|
||||
|
||||
auto colored = this->_colored ? terminal::parseCharacterCodes(std::string{line}) : terminal::stripCharacterCodes(std::string{line});
|
||||
dest.append(colored.data(), colored.data() + colored.size());
|
||||
|
||||
index = found;
|
||||
|
||||
append(spdlog::details::os::default_eol);
|
||||
if(++index)
|
||||
dest.append(prefix_begin, prefix_end);
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] std::unique_ptr<formatter> LogFormatter::clone() const {
|
||||
return std::make_unique<LogFormatter>(this->_colored);
|
||||
}
|
||||
}
|
@ -1,50 +1,37 @@
|
||||
#pragma once
|
||||
|
||||
#define SPDLOG_FINAL
|
||||
#define SPDLOG_ALLOW_PROTECT
|
||||
#define SPDLOG_NO_FINAL //We need to override the rotating logger
|
||||
|
||||
#include <spdlog/logger.h>
|
||||
#include <spdlog/sinks/file_sinks.h>
|
||||
#include <spdlog/sinks/base_sink.h>
|
||||
|
||||
namespace logger {
|
||||
struct force_log_msg : public spdlog::details::log_msg
|
||||
{
|
||||
force_log_msg() = default;
|
||||
virtual ~force_log_msg() = default;
|
||||
force_log_msg(const std::string *loggers_name, spdlog::level::level_enum lvl, bool force) : log_msg(loggers_name, lvl), force(force) { }
|
||||
class ColorCodeFormatter : public spdlog::formatter {
|
||||
public:
|
||||
void format(const spdlog::details::log_msg &msg, spdlog::memory_buf_t &dest) override {
|
||||
dest.append(msg.payload.begin(), msg.payload.end());
|
||||
}
|
||||
|
||||
force_log_msg(const log_msg& other) = delete;
|
||||
force_log_msg(log_msg&& other) = delete;
|
||||
force_log_msg(const force_log_msg& other) = delete;
|
||||
force_log_msg& operator=(force_log_msg&& other) = delete;
|
||||
force_log_msg(force_log_msg&& other) = delete;
|
||||
|
||||
|
||||
bool force;
|
||||
[[nodiscard]] std::unique_ptr<formatter> clone() const override {
|
||||
return std::unique_ptr<ColorCodeFormatter>();
|
||||
}
|
||||
};
|
||||
|
||||
class TerminalSink : public spdlog::sinks::sink {
|
||||
//TODO: Mutex really needed here?
|
||||
class TerminalSink : public spdlog::sinks::base_sink<std::mutex> {
|
||||
public:
|
||||
void log(const spdlog::details::log_msg &msg) override;
|
||||
void flush();
|
||||
|
||||
bool should_log_(const spdlog::details::log_msg &msg) const override;
|
||||
void sink_it_(const spdlog::details::log_msg &msg) override;
|
||||
void flush_() override;
|
||||
};
|
||||
|
||||
class ColoredFileSink : public spdlog::sinks::rotating_file_sink_mt {
|
||||
class LogFormatter : public spdlog::formatter {
|
||||
public:
|
||||
ColoredFileSink(const spdlog::filename_t &base_filename, size_t max_size, size_t max_files);
|
||||
explicit LogFormatter(bool colored) : _colored{colored} {}
|
||||
|
||||
protected:
|
||||
void _sink_it(const spdlog::details::log_msg &msg) override;
|
||||
};
|
||||
|
||||
class CostumeFormatter : public spdlog::formatter {
|
||||
public:
|
||||
void format(spdlog::details::log_msg &msg) override;
|
||||
void format(const spdlog::details::log_msg &msg, spdlog::memory_buf_t &dest) override;
|
||||
[[nodiscard]] std::unique_ptr<formatter> clone() const override;
|
||||
|
||||
inline bool colored() const { return this->_colored; }
|
||||
inline void colored(bool flag) { this->_colored = flag; }
|
||||
private:
|
||||
inline std::string time(std::chrono::time_point <spdlog::log_clock> point);
|
||||
bool _colored{true};
|
||||
};
|
||||
}
|
||||
|
@ -4,11 +4,14 @@
|
||||
#include <fstream>
|
||||
#include <map>
|
||||
#include <CXXTerminal/Terminal.h>
|
||||
#include <spdlog/spdlog.h>
|
||||
#include <experimental/filesystem>
|
||||
#include <StringVariable.h>
|
||||
#include <mutex>
|
||||
|
||||
#include <spdlog/spdlog.h>
|
||||
#include <spdlog/async.h>
|
||||
#include <spdlog/sinks/rotating_file_sink.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace std::chrono;
|
||||
using namespace spdlog;
|
||||
@ -20,28 +23,27 @@ namespace logger {
|
||||
map<size_t, std::shared_ptr<spdlog::logger>> loggers;
|
||||
shared_ptr<LoggerConfig> logConfig;
|
||||
shared_ptr<::logger::TerminalSink> terminalSink;
|
||||
shared_ptr<::logger::CostumeFormatter> costumeFormatter;
|
||||
|
||||
shared_ptr<spdlog::logger> logger(int serverId) {
|
||||
if(!::logger::currentConfig())
|
||||
return nullptr;
|
||||
std::shared_ptr<spdlog::details::thread_pool> logging_threads{nullptr};
|
||||
|
||||
size_t group = 0;
|
||||
if(::logger::currentConfig()->vs_group_size > 0 && serverId > 0)
|
||||
group = serverId / ::logger::currentConfig()->vs_group_size;
|
||||
else group = -1;
|
||||
spdlog::level::level_enum min_level{spdlog::level::trace};
|
||||
|
||||
if(loggers.count(group) == 0) {
|
||||
lock_guard lock(loggerLock);
|
||||
if(loggers.count(group) > 0) return loggers[group];
|
||||
//Create a new logger
|
||||
if(group != 0 && group != -1)
|
||||
logger(0)->debug("Creating new grouped logger for group {}", group);
|
||||
void updater_logger_levels(const std::shared_ptr<spdlog::logger>& logger) {
|
||||
for(const auto& sink : logger->sinks())
|
||||
if(dynamic_pointer_cast<TerminalSink>(sink)) {
|
||||
sink->set_level(::logger::currentConfig()->terminalLevel);
|
||||
} else if(dynamic_pointer_cast<spdlog::sinks::rotating_file_sink_mt>(sink)) {
|
||||
sink->set_level(::logger::currentConfig()->logfileLevel);
|
||||
} else if(dynamic_pointer_cast<spdlog::sinks::rotating_file_sink_st>(sink)) {
|
||||
sink->set_level(::logger::currentConfig()->logfileLevel);
|
||||
} else {
|
||||
sink->set_level(min_level);
|
||||
}
|
||||
logger->set_level(min_level);
|
||||
}
|
||||
|
||||
vector<spdlog::sink_ptr> sinks;
|
||||
string path;
|
||||
if(logConfig->logfileLevel != spdlog::level::off) {
|
||||
path = strvar::transform(logConfig->logPath,
|
||||
std::string generate_log_file(int group) {
|
||||
return strvar::transform(logConfig->logPath,
|
||||
strvar::StringValue{"group", group != -1 ? to_string(group) : "general"},
|
||||
strvar::FunctionValue("time", (strvar::FunctionValue::FValueFNEasy) [](std::deque<std::string> value) -> std::string {
|
||||
auto pattern = !value.empty() ? value[0] : "%Y-%m-%d_%H:%M:%S";
|
||||
@ -63,13 +65,55 @@ namespace logger {
|
||||
return string(timeBuffer);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
std::mutex default_lock{};
|
||||
bool default_setup{false};
|
||||
|
||||
std::shared_ptr<spdlog::logger> default_logger() {
|
||||
lock_guard lock{default_lock};
|
||||
if(!default_setup) {
|
||||
default_setup = true;
|
||||
|
||||
spdlog::default_logger()->sinks().clear();
|
||||
auto terminal_sink = make_shared<TerminalSink>();
|
||||
terminal_sink->set_level(spdlog::level::trace);
|
||||
spdlog::default_logger()->sinks().push_back(terminal_sink);
|
||||
|
||||
spdlog::default_logger()->set_formatter(std::make_unique<LogFormatter>(true));
|
||||
}
|
||||
return spdlog::default_logger();
|
||||
}
|
||||
|
||||
shared_ptr<spdlog::logger> logger(int serverId) {
|
||||
if(!::logger::currentConfig())
|
||||
return default_logger();
|
||||
|
||||
size_t group = 0;
|
||||
if(::logger::currentConfig()->vs_group_size > 0 && serverId > 0)
|
||||
group = serverId / ::logger::currentConfig()->vs_group_size;
|
||||
else group = -1;
|
||||
|
||||
if(loggers.count(group) == 0) {
|
||||
lock_guard lock(loggerLock);
|
||||
if(loggers.count(group) > 0) return loggers[group];
|
||||
//Create a new logger
|
||||
if(group != 0 && group != -1)
|
||||
logger(0)->debug("Creating new grouped logger for group {}", group);
|
||||
|
||||
vector<spdlog::sink_ptr> sinks;
|
||||
string path;
|
||||
if(logConfig->logfileLevel != spdlog::level::off) {
|
||||
path = generate_log_file(group);
|
||||
|
||||
auto logFile = fs::u8path(path);
|
||||
if(!logFile.parent_path().empty())
|
||||
fs::create_directories(logFile.parent_path());
|
||||
|
||||
try {
|
||||
auto fileSink = make_shared<ColoredFileSink>(logFile.string(), 1024 * 1024 * 50, 12);
|
||||
sinks.push_back(fileSink);
|
||||
auto sink = make_shared<spdlog::sinks::rotating_file_sink_mt>(logFile.string(), 1024 * 1024 * 50, 12);
|
||||
sink->set_formatter(std::make_unique<LogFormatter>(::logger::currentConfig()->file_colored));
|
||||
sinks.push_back(sink);
|
||||
} catch(std::exception& ex) {
|
||||
if(group != 0 && group != -1)
|
||||
logger(0)->critical("Failed to create file for new log group: {}", ex.what());
|
||||
@ -77,25 +121,19 @@ namespace logger {
|
||||
terminal::instance()->writeMessage("§4[CRITICAL] §eFailed to create main log file: " + string{ex.what()}, false);
|
||||
}
|
||||
} else {
|
||||
path = "/dev/null (" + to_string(serverId) + ")";
|
||||
path = "/dev/null (" + to_string(group) + ")";
|
||||
}
|
||||
sinks.push_back(terminalSink);
|
||||
|
||||
if(!logging_threads)
|
||||
logging_threads = std::make_shared<spdlog::details::thread_pool>(8192, 1); //Only one thread possible here, else elements get reordered
|
||||
#ifdef ASYNC_LOG
|
||||
auto logger = create_async("Logger (" + path + ")", sinks.begin(), sinks.end(), 8192, async_overflow_policy::discard_log_msg, [](){}, std::chrono::milliseconds(500));
|
||||
auto logger = std::make_shared<spdlog::async_logger>("Logger (" + path + ")", sinks.begin(), sinks.end(), logging_threads, async_overflow_policy::block);
|
||||
#else
|
||||
//FIXME!
|
||||
auto logger = create("Logger (" + path + ")", sinks.begin(), sinks.end());
|
||||
#endif
|
||||
logger->set_formatter(costumeFormatter);
|
||||
for(const auto& sink : logger->sinks())
|
||||
if(dynamic_pointer_cast<TerminalSink>(sink)) {
|
||||
sink->set_level(::logger::currentConfig()->terminalLevel);
|
||||
} else if(dynamic_pointer_cast<ColoredFileSink>(sink)) {
|
||||
sink->set_level(::logger::currentConfig()->logfileLevel);
|
||||
} else {
|
||||
sink->set_level(min(::logger::currentConfig()->logfileLevel, ::logger::currentConfig()->terminalLevel));
|
||||
}
|
||||
logger->set_level(min(::logger::currentConfig()->logfileLevel, ::logger::currentConfig()->terminalLevel));
|
||||
updater_logger_levels(logger);
|
||||
loggers[group] = logger;
|
||||
}
|
||||
|
||||
@ -112,22 +150,63 @@ namespace logger {
|
||||
|
||||
terminalSink = make_shared<TerminalSink>();
|
||||
terminalSink->set_level(::logger::currentConfig()->terminalLevel);
|
||||
costumeFormatter = make_shared<CostumeFormatter>();
|
||||
terminalSink->set_formatter(std::make_unique<LogFormatter>(true));
|
||||
min_level = ::min(::logger::currentConfig()->logfileLevel, ::logger::currentConfig()->terminalLevel);
|
||||
|
||||
logger(0)->debug("Log successfully started!");
|
||||
}
|
||||
|
||||
|
||||
bool should_log(spdlog::level::level_enum level) {
|
||||
return level >= min_level;
|
||||
}
|
||||
|
||||
void log(spdlog::level::forceable level, int server_id, const std::string_view& buffer) {
|
||||
auto logger = ::logger::logger(server_id);
|
||||
|
||||
auto message_format = "§8{0:>5} | §r{1}";
|
||||
if(server_id <= 0) {
|
||||
switch (server_id) {
|
||||
case LOG_INSTANCE:
|
||||
message_format = "§8GLOBL | §r{1}";
|
||||
break;
|
||||
case LOG_QUERY:
|
||||
message_format = "§8QUERY | §r{1}";
|
||||
break;
|
||||
case LOG_FT:
|
||||
message_format = "§8 FILE | §r{1}";
|
||||
break;
|
||||
case LOG_GENERAL:
|
||||
message_format = "§8 GEN | §r{1}";
|
||||
break;
|
||||
case LOG_LICENSE_CONTROLL:
|
||||
message_format = "§8 CONTR | §r{1}";
|
||||
break;
|
||||
case LOG_LICENSE_WEB:
|
||||
message_format = "§8 WEBST | §r{1}";
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
logger->log(level, message_format, server_id, buffer);
|
||||
} catch (const std::exception &ex) {
|
||||
//TODO better?
|
||||
std::cerr << "An exception has raised while logging a message (" << ex.what() << "): " << buffer << "\n";
|
||||
} catch(...) {
|
||||
std::cerr << "An unknown exception has raised while logging a message: " << buffer << "\n";
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
void updateLogLevels() {
|
||||
lock_guard lock(loggerLock);
|
||||
for(const auto& loggerEntry : loggers) {
|
||||
auto logger = loggerEntry.second;
|
||||
for(const auto& sink : logger->sinks())
|
||||
if(dynamic_pointer_cast<TerminalSink>(sink))
|
||||
sink->set_level(::logger::currentConfig()->terminalLevel);
|
||||
else if(dynamic_pointer_cast<ColoredFileSink>(sink))
|
||||
sink->set_level(::logger::currentConfig()->logfileLevel);
|
||||
else
|
||||
sink->set_level(min(::logger::currentConfig()->logfileLevel, ::logger::currentConfig()->terminalLevel));
|
||||
logger->set_level(min(::logger::currentConfig()->logfileLevel, ::logger::currentConfig()->terminalLevel));
|
||||
min_level = ::min(::logger::currentConfig()->logfileLevel, ::logger::currentConfig()->terminalLevel);
|
||||
for(const auto& logger : loggers) {
|
||||
updater_logger_levels(logger.second);
|
||||
}
|
||||
}
|
||||
|
||||
@ -152,7 +231,6 @@ namespace logger {
|
||||
|
||||
logConfig = nullptr;
|
||||
terminalSink = nullptr;
|
||||
costumeFormatter = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,28 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#define SPDLOG_EOL "\n"
|
||||
#ifdef SPDLOG_FINAL
|
||||
#undef SPDLOG_FINAL
|
||||
#endif
|
||||
#define SPDLOG_FINAL
|
||||
#define SPDLOG_ALLOW_PROTECT
|
||||
#define SPDLOG_NO_FINAL //We need to override the rotating logger
|
||||
#ifdef byte
|
||||
#undef byte
|
||||
#endif
|
||||
|
||||
#include <spdlog/logger.h>
|
||||
#include <spdlog/fmt/fmt.h>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <chrono>
|
||||
#include "../Definitions.h"
|
||||
#include "LogSinks.h"
|
||||
|
||||
#ifdef HAVE_CXX_TERMINAL
|
||||
#include <CXXTerminal/Terminal.h>
|
||||
#endif
|
||||
|
||||
#define lstream std::stringstream()
|
||||
|
||||
#ifdef log
|
||||
#undef log
|
||||
#endif
|
||||
@ -41,8 +38,29 @@ namespace logger {
|
||||
extern const std::shared_ptr<LoggerConfig>& currentConfig();
|
||||
extern void uninstall();
|
||||
|
||||
extern bool should_log(spdlog::level::level_enum /* level */); //TODO: inline?
|
||||
extern void log(spdlog::level::forceable /* level */, int /* server id */, const std::string_view& /* buffer */);
|
||||
|
||||
extern void updateLogLevels();
|
||||
extern void flush();
|
||||
|
||||
namespace impl {
|
||||
template <spdlog::level::level_enum level, typename... Args>
|
||||
inline void do_log(bool forced, int serverId, const std::string& message, const Args&... args) {
|
||||
if(!forced && !::logger::should_log(level)) return;
|
||||
spdlog::memory_buf_t buffer{};
|
||||
|
||||
auto _logger = ::logger::logger(serverId);
|
||||
std::string fmt_message;
|
||||
try {
|
||||
fmt_message = fmt::format(message, args...);
|
||||
} catch (const std::exception &ex) {
|
||||
fmt_message = "failed to format message '" + std::string{message} + "': " + ex.what();
|
||||
}
|
||||
|
||||
::logger::log(spdlog::level::forceable{level, forced}, serverId, fmt_message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define LOG_LICENSE_CONTROLL (-0x10)
|
||||
@ -53,59 +71,10 @@ namespace logger {
|
||||
#define LOG_FT (-3)
|
||||
#define LOG_GENERAL 0
|
||||
|
||||
#ifdef HAVE_CXX_TERMINAL
|
||||
#define DEFINE_LOG_IMPL_NO_LOGGER(prefix, message) \
|
||||
if(terminal::active()) \
|
||||
terminal::instance()->writeMessage("[" + std::string(prefix) + "] " + message); \
|
||||
else \
|
||||
std::cout << "[" + std::string(prefix) + "] " + message << std::endl;
|
||||
#else
|
||||
#define DEFINE_LOG_IMPL_NO_LOGGER(prefix, message) \
|
||||
std::cout << "[" + std::string(prefix) + "] " + message << std::endl;
|
||||
#endif
|
||||
|
||||
#define DEFINE_LOG_IMPL(name, level, _default_prefix) \
|
||||
template <typename... Args> \
|
||||
inline void name ##Fmt(bool forced, int serverId, const std::string& message, const Args&... args){ \
|
||||
auto _logger = ::logger::logger(serverId); \
|
||||
std::string fmt_message; \
|
||||
try { \
|
||||
fmt::MemoryWriter writer; \
|
||||
writer.write(message, args...); \
|
||||
fmt_message = writer.str(); \
|
||||
} catch (const std::exception &ex) { \
|
||||
fmt_message = "failed to format message '" + message + "': " + ex.what(); \
|
||||
} \
|
||||
if(!_logger) { \
|
||||
DEFINE_LOG_IMPL_NO_LOGGER(_default_prefix, fmt_message); \
|
||||
return; \
|
||||
} \
|
||||
if (!_logger->should_log(level) && !forced) return; \
|
||||
\
|
||||
try { \
|
||||
::logger::force_log_msg log_msg(&_logger->_name, level, forced); \
|
||||
auto fmt = "§8{0:>5} | §r{1}"; \
|
||||
if(serverId > 0); \
|
||||
else if(serverId == LOG_INSTANCE) \
|
||||
fmt = "§8GLOBL | §r{1}"; \
|
||||
else if(serverId == LOG_QUERY) \
|
||||
fmt = "§8QUERY | §r{1}"; \
|
||||
else if(serverId == LOG_FT) \
|
||||
fmt = "§8 FILE | §r{1}"; \
|
||||
else if(serverId == LOG_GENERAL) \
|
||||
fmt = "§8 GEN | §r{1}"; \
|
||||
else if(serverId == LOG_LICENSE_CONTROLL) \
|
||||
fmt = "§8 CONTR | §r{1}"; \
|
||||
else if(serverId == LOG_LICENSE_WEB) \
|
||||
fmt = "§8 WEBST | §r{1}"; \
|
||||
log_msg.raw.write(fmt, serverId, fmt_message); \
|
||||
_logger->_sink_it(log_msg); \
|
||||
} catch (const std::exception &ex) { \
|
||||
_logger->_err_handler(ex.what()); \
|
||||
} catch(...) { \
|
||||
_logger->_err_handler("Unknown exception in logger " + _logger->_name); \
|
||||
throw; \
|
||||
} \
|
||||
inline void name ##Fmt(bool forced, int serverId, const std::string& message, const Args&... args) { \
|
||||
::logger::impl::do_log<level>(forced, serverId, message, args...); \
|
||||
}
|
||||
|
||||
DEFINE_LOG_IMPL(logMessage, spdlog::level::info, "INFO")
|
||||
@ -119,9 +88,9 @@ DEFINE_LOG_IMPL(debugMessage, spdlog::level::debug, "DEBUG")
|
||||
template <typename... Args> \
|
||||
inline void name(int serverId, const std::string& message, const Args&... args){ name ##Fmt(false, serverId, message, args...); } \
|
||||
inline void name(int serverId, const std::string& message){ name ##Fmt(false, serverId, message); } \
|
||||
inline void name(int serverId, std::ostream& str){ std::stringstream s; s << str.rdbuf(); name(serverId, s.str()); } \
|
||||
inline void name(const std::string& message) { name ##Fmt(false, 0, message); } \
|
||||
inline void name(std::ostream& str){ std::stringstream s; s << str.rdbuf(); name(s.str()); } \
|
||||
inline void name(int serverId, std::ostream& str) = delete; \
|
||||
inline void name(const std::string& message) = delete; \
|
||||
inline void name(std::ostream& str) = delete; \
|
||||
inline void name(bool, int, const std::string&) = delete;
|
||||
|
||||
LOG_METHOD(logError);
|
||||
|
@ -184,7 +184,7 @@ namespace memtrack {
|
||||
|
||||
void statistics() {
|
||||
#ifdef NO_IMPL
|
||||
logError("memtracker::statistics() does not work due compiler flags (NO_IMPL)");
|
||||
logError(LOG_GENERAL, "memtracker::statistics() does not work due compiler flags (NO_IMPL)");
|
||||
return;
|
||||
#else
|
||||
map<size_t, deque<void*>> objects;
|
||||
|
@ -21,7 +21,7 @@ namespace sql {
|
||||
}
|
||||
|
||||
AsyncSqlPool::AsyncSqlPool(size_t threads) : _threads(new threads::ThreadPool(threads, "AsyncSqlPool")) {
|
||||
debugMessage("Created a new async thread pool!");
|
||||
debugMessage(LOG_GENERAL, "Created a new async thread pool!");
|
||||
}
|
||||
AsyncSqlPool::~AsyncSqlPool() {
|
||||
delete _threads;
|
||||
|
@ -13,7 +13,7 @@
|
||||
#include <misc/lambda.h>
|
||||
|
||||
#define ALLOW_STACK_ALLOCATION
|
||||
#define LOG_SQL_CMD [](const sql::result &res){ if(!res) logCritical("Failed to execute sql command: " + std::to_string(res.code()) + "/" + res.msg() + " (" __FILE__ + ":" + to_string(__LINE__) + ")"); }
|
||||
#define LOG_SQL_CMD [](const sql::result &res){ if(!res) logCritical(LOG_GENERAL, "Failed to execute sql command: " + std::to_string(res.code()) + "/" + res.msg() + " (" __FILE__ + ":" + to_string(__LINE__) + ")"); }
|
||||
namespace sql {
|
||||
class result;
|
||||
class SqlManager;
|
||||
|
@ -380,7 +380,7 @@ std::shared_ptr<SSLKeyPair> SSLManager::loadSSL(const std::string &key_data, std
|
||||
if(key_path.has_parent_path())
|
||||
fs::create_directories(key_path.parent_path());
|
||||
} catch (fs::filesystem_error& error) {
|
||||
logError("Could not create key directory: " + string(error.what()));
|
||||
logError(LOG_GENERAL, "Could not create key directory: " + string(error.what()));
|
||||
}
|
||||
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user