201 lines
4.9 KiB
C++
201 lines
4.9 KiB
C++
/***
|
|
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
|
|
|
File: ConsoleLogger.cpp
|
|
Date: 2021-6-22
|
|
Author: Reece
|
|
***/
|
|
#include <RuntimeInternal.hpp>
|
|
#include "ConsoleLogger.hpp"
|
|
|
|
namespace Aurora::Console::ConsoleLogger
|
|
{
|
|
static Threading::Threads::ThreadUnique_t gFileWriterThread;
|
|
static AuList<AuUInt8> gLogBuffer;
|
|
static Threading::Primitives::RWLockUnique_t gLogMutex;
|
|
static IO::FS::OpenWriteUnique_t gFileHandle;
|
|
|
|
static const auto & gLogConfig = gRuntimeConfig.console.logging;
|
|
|
|
static void EraseFilesByTimestamp(const AuString &path, /*const its not worth reallocation*/ AuList<AuString> &files)
|
|
{
|
|
if (files.size() <= gLogConfig.maxLogs)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// our filenames are usually prefixed by an ISO 8601 timestamp where the most significant bits are last (YYYY-MM-DD?HH-MM-SS)
|
|
// a quick ghetto sort should be all we need. no need to waste time parsing timestamps
|
|
std::sort(files.begin(), files.end());
|
|
|
|
auto amount = files.size() - gLogConfig.maxLogs;
|
|
for (auto x = 0, i = 0; ((x < amount) && (i > files.size())); i++)
|
|
{
|
|
try
|
|
{
|
|
if (IO::FS::Remove(path + "/" + files[i]))
|
|
{
|
|
x++;
|
|
}
|
|
}
|
|
catch (...)
|
|
{
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
static void CleanupOldLogs()
|
|
{
|
|
AuString path;
|
|
AuString procName;
|
|
|
|
if (!Process::GetProcName(procName))
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (!IO::FS::GetProfileDomain(path))
|
|
{
|
|
return;
|
|
}
|
|
|
|
path += "/Logs/";
|
|
path += procName;
|
|
|
|
AuList<AuString> files;
|
|
AuBST<AuString, IO::FS::Stat> fileMeta;
|
|
AuUInt32 size {};
|
|
IO::FS::FilesInDirectory(path, files);
|
|
|
|
for (const auto &file : files)
|
|
{
|
|
IO::FS::Stat stat;
|
|
IO::FS::StatFile(path + "/" + file, stat);
|
|
fileMeta[file] = stat;
|
|
size += stat.size;
|
|
}
|
|
|
|
EraseFilesByTimestamp(path, files);
|
|
// TODO: erase when size >= gLogConfig.maxSizeMb * 1024
|
|
}
|
|
|
|
static void CompressLogs()
|
|
{
|
|
|
|
}
|
|
|
|
void Flush()
|
|
{
|
|
Threading::WaitableLockGuard a(gLogMutex->AsReadable());
|
|
|
|
if (gFileHandle)
|
|
{
|
|
gFileHandle->Write(gLogBuffer.data(), gLogBuffer.size());
|
|
}
|
|
|
|
gLogBuffer.clear();
|
|
}
|
|
|
|
static bool OpenLogFile()
|
|
{
|
|
AuString path;
|
|
AuString procName;
|
|
|
|
if (!Process::GetProcName(procName))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (!IO::FS::GetProfileDomain(path))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
auto tm = Time::ToCivilTime(Time::CurrentClockMS());
|
|
|
|
path += fmt::format("/Logs/{}/{:04}-{:02}-{:02}T{:02}-{:02}-{:02}Z.txt",
|
|
procName,
|
|
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
|
|
tm.tm_hour, tm.tm_min, tm.tm_sec);
|
|
|
|
gFileHandle = IO::FS::OpenWriteUnique(path);
|
|
return gFileHandle ? true : false;
|
|
}
|
|
|
|
static void LogThreadInit()
|
|
{
|
|
CleanupOldLogs();
|
|
|
|
auto thread = Threading::Threads::GetThread();
|
|
while (!thread->Exiting())
|
|
{
|
|
Sleep(500);
|
|
Flush();
|
|
}
|
|
}
|
|
|
|
void Init()
|
|
{
|
|
if (!gLogConfig.enableLogging)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (!OpenLogFile())
|
|
{
|
|
return;
|
|
}
|
|
|
|
gLogMutex = Threading::Primitives::RWLockUnique();
|
|
if (!gLogMutex)
|
|
{
|
|
return;
|
|
}
|
|
|
|
Threading::Threads::AbstractThreadVectors handler;
|
|
handler.DoRun = [](Threading::Threads::IAuroraThread *)
|
|
{
|
|
LogThreadInit();
|
|
};
|
|
|
|
gFileWriterThread = Threading::Threads::ThreadUnique(handler);
|
|
if (!gFileWriterThread)
|
|
{
|
|
return;
|
|
}
|
|
|
|
gFileWriterThread->SetName("ConsoleFIO");
|
|
gFileWriterThread->Run();
|
|
|
|
Console::Hooks::AddHook([&](const Console::ConsoleMessage &string) -> void
|
|
{
|
|
Threading::WaitableLockGuard a(gLogMutex->AsWritable());
|
|
auto str = string.ToSimplified();
|
|
|
|
gLogBuffer.reserve(gLogBuffer.size() + str.size() + 2);
|
|
|
|
gLogBuffer.insert(gLogBuffer.end(), reinterpret_cast<AuUInt8*>(str.data()), reinterpret_cast<AuUInt8*>(str.data()) + str.size());
|
|
|
|
#if defined(AURORA_PLATFORM_WIN32)
|
|
gLogBuffer.insert(gLogBuffer.end(), AuUInt8('\r'));
|
|
#endif
|
|
gLogBuffer.insert(gLogBuffer.end(), AuUInt8('\n'));
|
|
});
|
|
}
|
|
|
|
void Pump()
|
|
{
|
|
|
|
}
|
|
|
|
void Exit()
|
|
{
|
|
Flush();
|
|
gFileWriterThread.reset();
|
|
gLogMutex.reset();
|
|
gFileHandle.reset();
|
|
|
|
CompressLogs();
|
|
}
|
|
} |