fabric/logging.cpp
fabric/logging.cpp
Namespaces
| Name |
|---|
| Syntalos |
Source code
/*
* Copyright (C) 2022-2026 Matthias Klumpp <matthias@tenstral.net>
*
* Licensed under the GNU Lesser General Public License Version 3
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the license, or
* (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this software. If not, see <http://www.gnu.org/licenses/>.
*/
// Backend headers must come before logging.h to avoid partial specialization
// conflicts: DeferredFormatCodec.h (pulled in by logging.h) triggers instantiation
// of fmtquill formatters before format.h can partially specialize them.
#include <quill/Backend.h>
#include <quill/Frontend.h>
#include <quill/sinks/ConsoleSink.h>
#include "logging.h"
#include <iostream>
#include <datactl/logging.h>
namespace Syntalos
{
static std::shared_ptr<quill::Sink> g_consoleSink = nullptr;
static quill::LogLevel g_defaultLogLevel = quill::LogLevel::Info;
quill::Logger *getLogger(const std::string &name)
{
quill::PatternFormatterOptions fmtOpt{"%(time) %(thread_name):%(logger): %(message)", "%H:%M:%S.%Qus"};
auto logger = quill::Frontend::create_or_get_logger(name, g_consoleSink, fmtOpt);
logger->set_log_level(g_defaultLogLevel);
return logger;
}
quill::Logger *getLogger(const QString &name)
{
return getLogger(name.toStdString());
}
quill::Logger *getLogger(const char *name)
{
return getLogger(std::string(name));
}
quill::Logger *logModTmp(const char *name)
{
const auto logName = std::format("mod.{}", name);
return getLogger(logName);
}
static void datactlLogHandler(const datactl::LogMessage &m)
{
// cache one Quill logger per datactl category (categories are static strings, map by pointer)
thread_local std::unordered_map<const char *, quill::Logger *> loggers;
auto [it, inserted] = loggers.emplace(m.category, nullptr);
if (inserted)
it->second = getLogger(m.category);
QUILL_LOG_RUNTIME_METADATA_CALL(
quill::MacroMetadata::Event::LogWithRuntimeMetadataShallowCopy,
it->second,
static_cast<quill::LogLevel>(m.severity),
m.file,
m.line,
m.function,
"",
"{}",
m.message);
}
void removeLogger(quill::Logger *logger)
{
quill::Frontend::remove_logger_blocking(logger);
}
void initializeSyLogSystem(quill::LogLevel consoleLogLevel)
{
// trying to initialize the log system twice is a critical error
if (g_consoleSink) {
std::cerr << "Tried to initialize the Syntalos logging system twice. This is not allowed!" << std::endl;
abort();
return;
}
quill::BackendOptions backendOptn;
// we want to log UTF-8 characters, so disable sanitization
backendOptn.check_printable_char = {};
// start Quill's async logging backend
quill::Backend::start(backendOptn);
// register our console sink
g_consoleSink = quill::Frontend::create_or_get_sink<quill::ConsoleSink>("sy_console");
// forward datactl library log messages into Quill
datactl::setLogHandler(datactlLogHandler);
// configure defaults
g_defaultLogLevel = consoleLogLevel;
g_consoleSink->set_log_level_filter(consoleLogLevel);
}
void shutdownSyLogSystem()
{
quill::Backend::stop();
}
} // namespace Syntalos
Updated on 2026-04-24 at 06:25:18 +0000