Minor update - Log system rework

+ GetLogLevelInfo return a struct of info relative to a type of log

+ filtered log in the UI
This commit is contained in:
CatChow0 2025-01-19 14:41:37 +01:00
parent a88ed06198
commit 161166837f
3 changed files with 135 additions and 118 deletions

View File

@ -8,6 +8,7 @@
#include <filesystem> #include <filesystem>
#include <deque> #include <deque>
#include <unordered_set> #include <unordered_set>
#include <imgui.h>
class Logger class Logger
{ {
@ -52,29 +53,36 @@ public:
LogLevel level; LogLevel level;
}; };
static const char* LogLevelToString(LogLevel level) struct LogLevelInfo
{ {
switch (level) const char* name;
{ int value;
case LogLevel::Info: return "INFO"; ImVec4 color;
case LogLevel::Warning: return "WARNING"; };
case LogLevel::Error: return "ERROR";
case LogLevel::Shutdown: return "SHUTDOWN"; static const LogLevelInfo GetLogLevelInfo(LogLevel level)
case LogLevel::Initialize: return "INITIALIZE"; {
case LogLevel::Update: return "UPDATE"; switch (level)
case LogLevel::Render: return "RENDER"; {
case LogLevel::Input: return "INPUT"; case LogLevel::Info: return LogLevelInfo{ "Info", 0, ImVec4(0.0f, 1.0f, 0.0f, 1.0f) };
case LogLevel::Physics: return "PHYSICS"; case LogLevel::Warning: return LogLevelInfo{ "Warning", 1, ImVec4(1.0f, 1.0f, 0.0f, 1.0f) };
case LogLevel::Audio: return "AUDIO"; case LogLevel::Error: return LogLevelInfo{ "Error", 2, ImVec4(1.0f, 0.0f, 0.0f, 1.0f) };
case LogLevel::Network: return "NETWORK"; case LogLevel::Shutdown: return LogLevelInfo{ "Shutdown", 3, ImVec4(0.0f, 0.0f, 1.0f, 1.0f) };
case LogLevel::Scripting: return "SCRIPTING"; case LogLevel::Initialize: return LogLevelInfo{ "Initialize", 4, ImVec4(0.0f, 1.0f, 1.0f, 1.0f) };
case LogLevel::AI: return "AI"; case LogLevel::Update: return LogLevelInfo{ "Update", 5, ImVec4(1.0f, 0.0f, 1.0f, 1.0f) };
case LogLevel::Resource: return "RESOURCE"; case LogLevel::Render: return LogLevelInfo{ "Render", 6, ImVec4(1.0f, 1.0f, 1.0f, 1.0f) };
case LogLevel::Memory: return "MEMORY"; case LogLevel::Input: return LogLevelInfo{ "Input", 7, ImVec4(0.5f, 0.5f, 0.5f, 1.0f) };
case LogLevel::Debug: return "DEBUG"; case LogLevel::Physics: return LogLevelInfo{ "Physics", 8, ImVec4(0.5f, 0.5f, 0.5f, 1.0f) };
default: return "Unknown"; case LogLevel::Audio: return LogLevelInfo{ "Audio", 9, ImVec4(0.5f, 0.5f, 0.5f, 1.0f) };
} case LogLevel::Network: return LogLevelInfo{ "Network", 10, ImVec4(0.5f, 0.5f, 0.5f, 1.0f) };
} case LogLevel::Scripting: return LogLevelInfo{ "Scripting", 11, ImVec4(0.5f, 0.5f, 0.5f, 1.0f) };
case LogLevel::AI: return LogLevelInfo{ "AI", 12, ImVec4(0.5f, 0.5f, 0.5f, 1.0f) };
case LogLevel::Resource: return LogLevelInfo{ "Resource", 13, ImVec4(0.5f, 0.5f, 0.5f, 1.0f) };
case LogLevel::Memory: return LogLevelInfo{ "Memory", 14, ImVec4(0.5f, 0.5f, 0.5f, 1.0f) };
case LogLevel::Debug: return LogLevelInfo{ "Debug", 15, ImVec4(0.5f, 0.5f, 0.5f, 1.0f) };
default: return LogLevelInfo{ "Unknown", 16, ImVec4(1.0f, 1.0f, 1.0f, 1.0f) };
}
}
Logger() Logger()
{ {
@ -96,14 +104,28 @@ public:
ManageLogFiles(directoryPath); ManageLogFiles(directoryPath);
m_logFilePath = directoryPath + "\\" + m_logFileName; m_logFilePath = directoryPath + "\\" + m_logFileName;
// enable the 4 first log levels
for (int i = 0; i < LogLevelCount; i++)
{
m_disabledLogLevels[i] = false;
if (i > 3)
{
m_disabledLogLevels[i] = true;
}
}
} }
void Log(const std::string& message, const std::string& fileName, int lineNumber, LogLevel level = LogLevel::Info) void Log(const std::string& message, const std::string& fileName, int lineNumber, LogLevel level = LogLevel::Info)
{ {
if (m_disabledLogLevels.find(level) != m_disabledLogLevels.end()) // Si le niveau de log est désactivé, ne faites rien
{ if (m_disabledLogLevels[GetLogLevelInfo(level).value])
return; {
} return;
}
auto now = std::chrono::system_clock::now(); auto now = std::chrono::system_clock::now();
auto in_time_t = std::chrono::system_clock::to_time_t(now); auto in_time_t = std::chrono::system_clock::to_time_t(now);
@ -115,7 +137,7 @@ public:
auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()) % 1000; auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()) % 1000;
// Utilisez LogLevelToString pour obtenir la chaîne de caractères du niveau de log // Utilisez LogLevelToString pour obtenir la chaîne de caractères du niveau de log
std::string levelStr = LogLevelToString(level); std::string levelStr = GetLogLevelInfo(level).name;
std::stringstream ss; std::stringstream ss;
ss << "[" << std::put_time(&buf, "%Y-%m-%d") << "] " ss << "[" << std::put_time(&buf, "%Y-%m-%d") << "] "
@ -136,10 +158,12 @@ public:
void Log(const std::string& message, LogLevel level) void Log(const std::string& message, LogLevel level)
{ {
if (m_disabledLogLevels.find(level) != m_disabledLogLevels.end())
{ // Si le niveau de log est désactivé, ne faites rien
return; if (m_disabledLogLevels[GetLogLevelInfo(level).value])
} {
return;
}
if (logBuffer.size() >= logBufferSize) if (logBuffer.size() >= logBufferSize)
{ {
@ -191,7 +215,7 @@ public:
m_logFileName = ss.str(); m_logFileName = ss.str();
} }
std::unordered_set<LogLevel> m_disabledLogLevels; bool m_disabledLogLevels[LogLevelCount];
private: private:
std::string m_filename; std::string m_filename;

View File

@ -5,7 +5,7 @@ Collapsed=0
[Window][Khaotic Engine] [Window][Khaotic Engine]
Pos=1180,27 Pos=1180,27
Size=396,489 Size=396,566
Collapsed=0 Collapsed=0
DockId=0x00000005,0 DockId=0x00000005,0
@ -35,7 +35,7 @@ DockId=0x00000004,2
[Window][Engine Settings] [Window][Engine Settings]
Pos=1180,27 Pos=1180,27
Size=396,489 Size=396,566
Collapsed=0 Collapsed=0
DockId=0x00000005,1 DockId=0x00000005,1
@ -45,7 +45,7 @@ Collapsed=0
[Window][Render Window] [Window][Render Window]
Pos=8,27 Pos=8,27
Size=1170,489 Size=1170,566
Collapsed=0 Collapsed=0
DockId=0x00000002,0 DockId=0x00000002,0
@ -65,19 +65,27 @@ Size=1568,335
Collapsed=0 Collapsed=0
DockId=0x0000000C,0 DockId=0x0000000C,0
[Docking][Data] [Window][Log Window]
DockSpace ID=0xC0DFADC4 Pos=8,27 Size=1568,826 Split=X Pos=8,595
DockNode ID=0x00000001 Parent=0xC0DFADC4 SizeRef=330,1094 Split=Y Selected=0x393905AB Size=1568,258
DockNode ID=0x00000004 Parent=0x00000001 SizeRef=330,487 Selected=0x393905AB Collapsed=0
DockNode ID=0x00000006 Parent=0x00000001 SizeRef=330,485 Selected=0x031DC75C DockId=0x0000000E,0
DockNode ID=0x00000003 Parent=0xC0DFADC4 SizeRef=1700,1094 CentralNode=1
DockSpace ID=0xCCBD8CF7 Window=0x3DA2F1DE Pos=8,27 Size=1568,826 Split=Y [Docking][Data]
DockNode ID=0x0000000B Parent=0xCCBD8CF7 SizeRef=1568,637 Split=X DockSpace ID=0xC0DFADC4 Pos=8,27 Size=1568,826 Split=X
DockNode ID=0x00000007 Parent=0x0000000B SizeRef=290,826 Split=Y Selected=0x393905AB DockNode ID=0x00000001 Parent=0xC0DFADC4 SizeRef=330,1094 Split=Y Selected=0x393905AB
DockNode ID=0x00000009 Parent=0x00000007 SizeRef=395,413 Selected=0x393905AB DockNode ID=0x00000004 Parent=0x00000001 SizeRef=330,487 Selected=0x393905AB
DockNode ID=0x0000000A Parent=0x00000007 SizeRef=395,411 Selected=0x031DC75C DockNode ID=0x00000006 Parent=0x00000001 SizeRef=330,485 Selected=0x031DC75C
DockNode ID=0x00000008 Parent=0x0000000B SizeRef=1276,826 Split=X DockNode ID=0x00000003 Parent=0xC0DFADC4 SizeRef=1700,1094 CentralNode=1
DockNode ID=0x00000002 Parent=0x00000008 SizeRef=878,826 CentralNode=1 Selected=0x9204953B DockSpace ID=0xCCBD8CF7 Window=0x3DA2F1DE Pos=8,27 Size=1568,826 Split=Y
DockNode ID=0x00000005 Parent=0x00000008 SizeRef=396,826 Selected=0x9F035453 DockNode ID=0x0000000D Parent=0xCCBD8CF7 SizeRef=1568,566 Split=Y
DockNode ID=0x0000000C Parent=0xCCBD8CF7 SizeRef=1568,335 Selected=0x139FDA3F DockNode ID=0x0000000B Parent=0x0000000D SizeRef=1568,637 Split=X
DockNode ID=0x00000007 Parent=0x0000000B SizeRef=290,826 Split=Y Selected=0x393905AB
DockNode ID=0x00000009 Parent=0x00000007 SizeRef=395,413 Selected=0x393905AB
DockNode ID=0x0000000A Parent=0x00000007 SizeRef=395,411 Selected=0x031DC75C
DockNode ID=0x00000008 Parent=0x0000000B SizeRef=1276,826 Split=X
DockNode ID=0x00000002 Parent=0x00000008 SizeRef=878,826 CentralNode=1 Selected=0x9204953B
DockNode ID=0x00000005 Parent=0x00000008 SizeRef=396,826 Selected=0x0B098C4B
DockNode ID=0x0000000C Parent=0x0000000D SizeRef=1568,335 Selected=0x139FDA3F
DockNode ID=0x0000000E Parent=0xCCBD8CF7 SizeRef=1568,258 Selected=0xAB74BEE9

View File

@ -522,87 +522,72 @@ void imguiManager::WidgetEngineSettingsWindow(ApplicationClass* app)
void imguiManager::WidgetLogWindow(ApplicationClass* app) void imguiManager::WidgetLogWindow(ApplicationClass* app)
{ {
static bool logLevelVisible[Logger::LogLevelCount] = { true }; ImGui::Begin("Log Window");
ImGui::Begin("Log", &showLogWindow); // Filtre de recherche
static ImGuiTextFilter filter;
filter.Draw("Filter (inc,-exc)", 180);
// Champ de saisie pour le filtre // Place the menu on the same line as the filter
static char filterBuffer[256] = ""; ImGui::SameLine();
ImGui::InputText("Filter", filterBuffer, IM_ARRAYSIZE(filterBuffer));
ImGui::SameLine(); // Menu déroulant pour les niveaux de log
if (ImGui::BeginMenu("Log Levels"))
{
for (size_t i = 0; i < Logger::LogLevelCount; ++i)
{
bool isVisible = !Logger::Get().m_disabledLogLevels[i];
if (ImGui::Checkbox(Logger::Get().GetLogLevelInfo(static_cast<Logger::LogLevel>(i)).name, &isVisible))
{
Logger::Get().m_disabledLogLevels[i] = !isVisible;
}
}
ImGui::EndMenu();
}
// Menu déroulant pour les niveaux de log const auto& logBuffer = Logger::Get().GetLogBuffer();
if (ImGui::BeginMenu("Log Levels")) std::vector<Logger::LogEntry> logfiltered;
int logCount = logBuffer.size();
int filteredLogCount = 0;
// Affichage des logs filtrés
ImGui::BeginChild("Log");
// Compter le nombre de logs qui passent le filtre et les ajouter a la liste des message a afficher
for (const auto& log : logBuffer)
{ {
for (size_t i = 0; i < Logger::LogLevelCount; ++i) if (filter.PassFilter(log.message.c_str()) && !Logger::Get().m_disabledLogLevels[static_cast<size_t>(log.level)])
{ {
bool isVisible = logLevelVisible[i]; logfiltered.push_back(log);
if (ImGui::Checkbox(Logger::LogLevelToString(static_cast<Logger::LogLevel>(i)), &isVisible)) filteredLogCount++;
{
logLevelVisible[i] = isVisible;
if (isVisible)
{
Logger::Get().m_disabledLogLevels.erase(static_cast<Logger::LogLevel>(i));
}
else
{
Logger::Get().m_disabledLogLevels.insert(static_cast<Logger::LogLevel>(i));
}
}
}
ImGui::EndMenu();
}
// Récupérer les logs depuis le logBuffer
const std::deque<Logger::LogEntry>& logs = logBuffer;
// Afficher les logs dans ImGui avec le filtre
ImGui::BeginChild("LogScrollRegion", ImVec2(0, 0), false, ImGuiWindowFlags_HorizontalScrollbar);
ImGuiListClipper clipper;
clipper.Begin(logs.size());
while (clipper.Step())
{
for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; ++i)
{
if (strstr(logs[i].message.c_str(), filterBuffer) != nullptr)
{
ImVec4 color;
switch (logs[i].level)
{
case Logger::LogLevel::Error:
color = ImVec4(1.0f, 0.0f, 0.0f, 1.0f); // Rouge pour les messages d'erreur
break;
case Logger::LogLevel::Warning:
color = ImVec4(1.0f, 1.0f, 0.0f, 1.0f); // Jaune pour les messages d'avertissement
break;
case Logger::LogLevel::Info:
color = ImVec4(0.0f, 1.0f, 0.0f, 1.0f); // Vert pour les messages d'info
break;
case Logger::LogLevel::Initialize:
case Logger::LogLevel::Shutdown:
default:
color = ImVec4(1.0f, 1.0f, 1.0f, 1.0f); // Blanc par défaut
break;
}
ImGui::PushStyleColor(ImGuiCol_Text, color);
ImGui::TextUnformatted(logs[i].message.c_str());
ImGui::PopStyleColor();
}
} }
} }
clipper.End();
// Scroll to the bottom of the log window if (filteredLogCount == 0)
if (ImGui::GetScrollY() >= ImGui::GetScrollMaxY())
{ {
ImGui::SetScrollHereY(1.0f); ImGui::Text("No logs to display.");
}
else
{
ImGuiListClipper clipper;
clipper.Begin(logCount);
while (clipper.Step())
{
for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)
{
if (i < logfiltered.size()) {
const auto& log = logfiltered[i];
ImGui::TextColored(Logger::Get().GetLogLevelInfo(log.level).color, log.message.c_str());
}
}
}
clipper.End();
} }
ImGui::EndChild(); ImGui::EndChild();
ImGui::End(); ImGui::End();
} }