AuroraRuntime/Source/Console/Logging/Logger.cpp

274 lines
5.9 KiB
C++
Raw Normal View History

#include <Source/RuntimeInternal.hpp>
#include "Logger.hpp"
#include "../Hooks/Hooks.hpp" // HACK:
namespace Aurora::Console::Logging
{
static AuList<AuTuple<Logger *, AuUInt8, ConsoleMessage>> gLogTasks;
static AuThreadPrimitives::SpinLock gGlobalSpin;
static AuList<Logger *> gFlushableLoggers;
Logger::Logger(const AuList<AuSPtr<IBasicSink>> &sinks) : sinks(sinks)
{
AuMemset(shouldFilter, 0, sizeof(shouldFilter));
{
AU_LOCK_GUARD(gGlobalSpin);
AuTryInsert(gFlushableLoggers, this);
}
}
Logger::~Logger()
{
Disable();
}
void Logger::WriteLines(AuUInt8 level, const ConsoleMessage &msg)
{
try
{
if (msg.line.find('\n') == AuString::npos) [[likely]]
{
AddToPushQueue(level, msg);
WriteNow(level, msg);
}
else [[unlikely]]
{
Parse::SplitNewlines(msg.line,
[&](const AuString &line)
{
ConsoleMessage dup = msg;
dup.line = line;
AddToPushQueue(level, dup);
WriteNow(level, dup);
});
}
}
catch (...)
{
// Loggers experiencing something fucky is a liablity
Hooks::WriteLoggerFailedWarning();
}
}
void Logger::WriteMessage(AuUInt8 level, const ConsoleMessage &msg)
{
// Accounts for atomic shutdown
{
AU_LOCK_GUARD(spin);
if (shouldFilter[level])
{
return;
}
}
WriteLines(level, msg);
}
void Logger::AddToPushQueue(AuUInt8 level, const ConsoleMessage &msg)
{
AU_LOCK_GUARD(gGlobalSpin);
while (!AuTryInsert(gLogTasks, AuMakeTuple(this, level, msg)))
{
SysPushErrorMem("Push failed - trying again");
spin.Unlock();
AuThreading::Sleep(100);
spin.Lock();
}
}
void Logger::PushFilter(AuUInt8 level, bool shouldFilter)
{
AU_LOCK_GUARD(spin);
try
{
while (!AuTryInsert(filters, AuMakeTuple(level, shouldFilter)))
{
SysPushErrorMem("Push failed - trying again. wont be able to handle pop - wont syspanic yet");
AuThreading::Sleep(100);
}
AuMemset(this->shouldFilter, 0, sizeof(this->shouldFilter));
for (auto &tuple : filters)
{
auto level = std::get<0>(tuple);
auto shouldFilter = std::get<1>(tuple);
this->shouldFilter[level] = shouldFilter;
}
}
catch (...)
{
}
}
void Logger::PopFilter()
{
try
{
AU_LOCK_GUARD(spin);
filters.pop_back();
}
catch (...)
{
}
}
void ForceFlushLoggers()
{
decltype(gLogTasks) logTasks;
{
AU_LOCK_GUARD(gGlobalSpin);
try
{
logTasks = AuExchange(gLogTasks, {});
}
catch (...)
{
}
if (logTasks.empty())
{
return;
}
}
try
{
for (const auto &logEntry : logTasks)
{
auto &logger = std::get<0>(logEntry);
auto &level = std::get<1>(logEntry);
auto &message = std::get<2>(logEntry);
logger->WriteLater(level, message);
}
}
catch (...)
{
}
{
AU_LOCK_GUARD(gGlobalSpin);
for (const auto &logger : gFlushableLoggers)
{
for (const auto &sink : logger->sinks)
{
try
{
sink->OnFlush();
}
catch (...)
{
SysPushErrorGeneric("...");
}
}
}
}
}
void Logger::Disable()
{
{
AU_LOCK_GUARD(spin);
AuMemset(shouldFilter, 1, sizeof(shouldFilter));
}
{
AU_LOCK_GUARD(gGlobalSpin);
AuTryDeleteList(gFlushableLoggers, this);
}
ForceFlushLoggers();
}
void Logger::WriteNow(AuUInt8 level, const ConsoleMessage &msg)
{
try
{
for (const auto &sink : this->sinks)
{
try
{
sink->OnMessageNonblocking(level, msg);
}
catch (...)
{
SysPushErrorGeneric("Failed to pump a logger");
}
}
}
catch (...)
{
}
}
void Logger::WriteLater(AuUInt8 level, const ConsoleMessage &msg)
{
try
{
for (const auto &sink : this->sinks)
{
try
{
sink->OnMessageBlocking(level, msg);
}
catch (...)
{
SysPushErrorGeneric("Failed to pump a logger");
}
}
}
catch (...)
{
}
}
void InitLoggers()
{
}
void DeinitLoggers()
{
ForceFlushLoggers();
}
AUKN_SYM ILogger *NewLoggerNew(const AuList<AuSPtr<IBasicSink>> &sinks)
{
try
{
auto logger = _new Logger(sinks);
if (!logger)
{
return nullptr;
}
return logger;
}
catch (...)
{
return {};
}
}
AUKN_SYM void NewLoggerRelease(ILogger *logger)
{
SafeDelete<Logger *>(logger);
}
}