Skip to content

Commit 4a60b3e

Browse files
authored
Merge pull request #65 from rayshader/timestamp_log_rotation
Enable log rotation with timestamp context.
2 parents 441700d + 8ffb0ff commit 4a60b3e

File tree

7 files changed

+93
-5
lines changed

7 files changed

+93
-5
lines changed

src/dll/App.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,9 @@ void App::Startup()
149149
system->Startup();
150150
}
151151

152+
auto pluginNames = GetPluginSystem()->GetActivePlugins();
153+
GetLoggerSystem()->RotateLogs(pluginNames);
154+
152155
spdlog::info("RED4ext has been started");
153156
}
154157

src/dll/Systems/LoggerSystem.cpp

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1-
#include "stdafx.hpp"
21
#include "LoggerSystem.hpp"
2+
#include "Config.hpp"
3+
#include "Paths.hpp"
4+
#include "stdafx.hpp"
35

46
LoggerSystem::LoggerSystem(const Paths& aPaths, const Config& aConfig, const DevConsole& aDevConsole)
57
: m_paths(aPaths)
@@ -32,6 +34,65 @@ void LoggerSystem::Shutdown()
3234
spdlog::trace("{} logger(s) flushed", count);
3335
}
3436

37+
void LoggerSystem::RotateLogs(std::vector<std::wstring> pluginNames) const
38+
{
39+
std::error_code error;
40+
auto files = std::filesystem::directory_iterator(m_paths.GetLogsDir(), error);
41+
42+
if (error)
43+
{
44+
// Ignore and try the next time.
45+
return;
46+
}
47+
spdlog::trace("Rotate logs...");
48+
pluginNames.emplace_back(L"RED4ext");
49+
50+
// List all log files.
51+
std::vector<std::filesystem::path> logs;
52+
53+
for (const std::filesystem::directory_entry& file : files)
54+
{
55+
const auto fileName = file.path().filename().wstring();
56+
57+
if (file.is_regular_file() && fileName.ends_with(L".log"))
58+
{
59+
logs.emplace_back(file.path());
60+
}
61+
}
62+
const Config::LoggingConfig config = m_config.GetLogging();
63+
64+
// Rotate oldest logs per plugin.
65+
for (auto pluginName : pluginNames)
66+
{
67+
pluginName = Utils::ToLower(pluginName);
68+
std::vector<std::filesystem::path> pluginLogs;
69+
70+
logs.erase(std::remove_if(logs.begin(), logs.end(),
71+
[&pluginName, &pluginLogs](const auto& log)
72+
{
73+
if (log.filename().wstring().starts_with(pluginName))
74+
{
75+
pluginLogs.push_back(log);
76+
return true;
77+
}
78+
return false;
79+
}),
80+
logs.end());
81+
std::sort(pluginLogs.begin(), pluginLogs.end(), [](const auto& a, const auto& b) { return a > b; });
82+
83+
// maxFiles is guaranteed to be >= 1.
84+
for (size_t i = config.maxFiles; i < pluginLogs.size(); i++)
85+
{
86+
std::filesystem::remove(pluginLogs[i], error);
87+
}
88+
}
89+
// Remove log files of removed plugins.
90+
for (const auto& log : logs)
91+
{
92+
std::filesystem::remove(log, error);
93+
}
94+
}
95+
3596
void LoggerSystem::Trace(std::shared_ptr<PluginBase> aPlugin, std::string_view aText)
3697
{
3798
Log(aPlugin, spdlog::level::trace, aText);

src/dll/Systems/LoggerSystem.hpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ class LoggerSystem : public ISystem
1616
void Startup() final;
1717
void Shutdown() final;
1818

19+
void RotateLogs(std::vector<std::wstring> plugins) const;
20+
1921
void Trace(std::shared_ptr<PluginBase> aPlugin, std::string_view aText);
2022
void Trace(std::shared_ptr<PluginBase> aPlugin, std::wstring_view aText);
2123

@@ -60,14 +62,12 @@ class LoggerSystem : public ISystem
6062
const auto stem = path.stem();
6163
auto fileName = stem.wstring();
6264

63-
std::transform(fileName.begin(), fileName.end(), fileName.begin(),
64-
[](wchar_t aC) { return std::towlower(aC); });
65+
fileName = Utils::ToLower(fileName);
6566

6667
const auto logName = aPlugin->GetName();
6768

6869
fileName = fmt::format(L"{}-{}.log", fileName, Utils::FormatCurrentTimestamp());
69-
logger =
70-
Utils::CreateLogger(logName, fileName, m_paths, m_config, m_devConsole);
70+
logger = Utils::CreateLogger(logName, fileName, m_paths, m_config, m_devConsole);
7171
m_loggers.emplace(aPlugin, logger);
7272
}
7373
}

src/dll/Systems/PluginSystem.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,18 @@ const std::vector<PluginSystem::PluginName>& PluginSystem::GetIncompatiblePlugin
185185
return m_incompatiblePlugins;
186186
}
187187

188+
std::vector<PluginSystem::PluginName> PluginSystem::GetActivePlugins() const
189+
{
190+
std::vector<PluginSystem::PluginName> plugins;
191+
192+
plugins.reserve(m_plugins.size());
193+
for (const auto& [handle, plugin] : m_plugins)
194+
{
195+
plugins.emplace_back(plugin->GetName());
196+
}
197+
return plugins;
198+
}
199+
188200
void PluginSystem::Load(const std::filesystem::path& aPath, bool aUseAlteredSearchPath)
189201
{
190202
spdlog::info(L"Loading plugin from '{}'...", aPath);

src/dll/Systems/PluginSystem.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ class PluginSystem : public ISystem
2020

2121
std::shared_ptr<PluginBase> GetPlugin(HMODULE aModule) const;
2222
const std::vector<PluginName>& GetIncompatiblePlugins() const;
23+
std::vector<PluginName> GetActivePlugins() const;
2324

2425
private:
2526
using Map_t = std::unordered_map<HMODULE, std::shared_ptr<PluginBase>>;

src/dll/Utils.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "stdafx.hpp"
66

77
#include <ctime>
8+
#include <cwctype>
89

910
#include <spdlog/sinks/rotating_file_sink.h>
1011
#include <spdlog/sinks/stdout_color_sinks.h>
@@ -230,3 +231,11 @@ std::wstring Utils::Widen(const std::string_view aText)
230231

231232
return result;
232233
}
234+
235+
std::wstring Utils::ToLower(const std::wstring& acText)
236+
{
237+
std::wstring text = acText;
238+
239+
std::transform(text.begin(), text.end(), text.begin(), std::towlower);
240+
return text;
241+
}

src/dll/Utils.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ int32_t ShowMessageBox(const std::wstring_view aText, uint32_t aType = MB_OK);
2121
std::string Narrow(const std::wstring_view aText);
2222
std::wstring Widen(const std::string_view aText);
2323

24+
std::wstring ToLower(const std::wstring& acText);
25+
2426
template<typename... Args>
2527
int32_t ShowMessageBox(uint32_t aType, const std::wstring_view aText, Args&&... aArgs)
2628
{

0 commit comments

Comments
 (0)