feat: add logger

This commit is contained in:
k0t9i 2023-10-17 20:20:25 +04:00
parent 03e61a9b9a
commit ab85800275
12 changed files with 248 additions and 1 deletions

View File

@ -19,6 +19,7 @@ namespace L2Bot::Domain::Enums
announcement,
partyroomCommander = 15,
partyroomAll,
heroVoice
heroVoice,
log = 255
};
}

View File

@ -0,0 +1,43 @@
#pragma once
#include <vector>
#include <string>
#include <sstream>
#include <iomanip>
#include "LogLevel.h"
namespace L2Bot::Domain::Logger
{
class LogChannel
{
public:
LogChannel(const std::vector<LogLevel> levels) : m_Levels(levels) {};
virtual ~LogChannel() = default;
void SendToChannel(const std::wstring& logEntry)
{
DoSendToChannel(logEntry);
}
const bool IsAppropriateLevel(const LogLevel level) const
{
return m_Levels.size() == 0 || std::find(m_Levels.begin(), m_Levels.end(), level) != m_Levels.end();
}
protected:
virtual void DoSendToChannel(const std::wstring& logEntry) = 0;
const std::wstring GetCurrentDateTime() const
{
time_t rawTime = std::time(nullptr);
struct tm timeinfo;
localtime_s(&timeinfo, &rawTime);
std::wstringstream oss;
oss << "[" << std::put_time(&timeinfo, L"%Y-%m-%d %H.%M.%S") << "]";
return oss.str();
}
private:
const std::vector<LogLevel> m_Levels;
};
}

View File

@ -0,0 +1,14 @@
#pragma once
#include <cstdint>
namespace L2Bot::Domain::Logger
{
enum class LogLevel : uint8_t
{
error,
warning,
info,
app
};
}

View File

@ -0,0 +1,66 @@
#pragma once
#include <vector>
#include <format>
#include <memory>
#include "LogChannel.h"
#include "LogLevel.h"
namespace L2Bot::Domain::Logger
{
class Logger
{
public:
Logger(std::vector<std::unique_ptr<LogChannel>> channels) : m_Channels(std::move(channels)) {};
virtual ~Logger() = default;
template <class ... Args>
void Error(const std::wformat_string<Args...> format, Args... args) const
{
Log(LogLevel::error, format, args...);
}
template <class ... Args>
void Warning(const std::wformat_string<Args...> format, Args... args) const
{
Log(LogLevel::warning, format, args...);
}
template <class ... Args>
void Info(const std::wformat_string<Args...> format, Args... args) const
{
Log(LogLevel::info, format, args...);
}
template <class ... Args>
void App(const std::wformat_string<Args...> format, Args... args) const
{
Log(LogLevel::app, format, args...);
}
private:
template <class ... Args>
void Log(LogLevel level, const std::wformat_string<Args...> format, Args... args) const
{
std::wstring prefix = L"";
if (level == LogLevel::error) {
prefix = L"[Error]: ";
}
else if (level == LogLevel::warning) {
prefix = L"[Warning]: ";
}
else if (level == LogLevel::info) {
prefix = L"[Info]: ";
}
else if (level == LogLevel::app) {
prefix = L"[App]: ";
}
for (const auto& channel : m_Channels) {
if (channel->IsAppropriateLevel(level)) {
channel->SendToChannel(prefix + std::vformat(format.get(), std::make_wformat_args(args...)));
}
}
}
private:
const std::vector<std::unique_ptr<LogChannel>> m_Channels;
};
}

View File

@ -2,6 +2,7 @@
#include <memory>
#include "../Events/EventDispatcher.h"
#include "../Logger/Logger.h"
namespace L2Bot::Domain::Services
{
@ -21,6 +22,15 @@ namespace L2Bot::Domain::Services
{
m_EventDispatcher = std::move(dispatcher);
}
const std::unique_ptr<Logger::Logger>& GetLogger()
{
return m_Logger;
}
void SetLogger(std::unique_ptr<Logger::Logger> logger)
{
m_Logger = std::move(logger);
}
private:
ServiceLocator() = default;
virtual ~ServiceLocator() = default;
@ -29,5 +39,6 @@ namespace L2Bot::Domain::Services
ServiceLocator& operator=(const ServiceLocator&) = delete;
private:
std::unique_ptr<Events::EventDispatcher> m_EventDispatcher;
std::unique_ptr<Logger::Logger> m_Logger;
};
}

View File

@ -194,6 +194,9 @@
<ClInclude Include="Domain\Events\SkillCreatedEvent.h" />
<ClInclude Include="Domain\Events\SkillUsedEvent.h" />
<ClInclude Include="Domain\Events\SpoiledEvent.h" />
<ClInclude Include="Domain\Logger\LogChannel.h" />
<ClInclude Include="Domain\Logger\Logger.h" />
<ClInclude Include="Domain\Logger\LogLevel.h" />
<ClInclude Include="Domain\Serializers\IncomingMessageFactoryInterface.h" />
<ClInclude Include="Domain\Serializers\IncomingMessage.h" />
<ClInclude Include="Domain\Services\HeroServiceInterface.h" />

View File

@ -225,6 +225,15 @@
<ClInclude Include="Domain\Services\ServiceLocator.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Domain\Logger\LogLevel.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Domain\Logger\LogChannel.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Domain\Logger\Logger.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="pch.cpp">

View File

@ -165,6 +165,9 @@
<ClInclude Include="Common\Common.h" />
<ClInclude Include="Common\TimerMap.h" />
<ClInclude Include="Application.h" />
<ClInclude Include="Logger\OutputDebugLogChannel.h" />
<ClInclude Include="Logger\FileLogChannel.h" />
<ClInclude Include="Logger\ChatLogChannel.h" />
<ClInclude Include="Serializers\JsonIncomingMessageFactory.h" />
<ClInclude Include="Serializers\JsonSerializer.h" />
<ClInclude Include="Versions\Interlude\Services\HeroService.h" />

View File

@ -147,6 +147,15 @@
<ClInclude Include="Versions\Interlude\Services\HeroService.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Logger\OutputDebugLogChannel.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Logger\FileLogChannel.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Logger\ChatLogChannel.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="dllmain.cpp">

View File

@ -0,0 +1,39 @@
#pragma once
#include "Domain/Enums/ChatChannelEnum.h"
#include "Domain/Events/ChatMessageCreatedEvent.h"
#include "Domain/Logger/LogChannel.h"
#include "Domain/Services/ServiceLocator.h"
using namespace L2Bot::Domain;
class ChatLogChannel : public Logger::LogChannel
{
public:
ChatLogChannel(const Enums::ChatChannelEnum chatChannel, const std::vector<Logger::LogLevel> levels) :
Logger::LogChannel(levels),
m_ChatChannel(chatChannel)
{
};
virtual ~ChatLogChannel() = default;
protected:
void DoSendToChannel(const std::wstring& logEntry) override
{
Services::ServiceLocator::GetInstance().GetEventDispatcher()->Dispatch(
Events::ChatMessageCreatedEvent
{
DTO::ChatMessageData
{
0,
static_cast<uint8_t>(m_ChatChannel),
L"",
GetCurrentDateTime() + logEntry
}
}
);
}
private:
const Enums::ChatChannelEnum m_ChatChannel;
};

View File

@ -0,0 +1,30 @@
#pragma once
#include <Windows.h>
#include <fstream>
#include "Domain/Logger/LogChannel.h"
using namespace L2Bot::Domain;
class FileLogChannel : public Logger::LogChannel
{
public:
FileLogChannel(const std::wstring& path, const std::vector<Logger::LogLevel> levels) :
m_FileStream(path.c_str(), std::wofstream::app),
Logger::LogChannel(levels)
{
};
virtual ~FileLogChannel()
{
m_FileStream.close();
}
protected:
void DoSendToChannel(const std::wstring& logEntry) override
{
m_FileStream << GetCurrentDateTime() << logEntry << std::endl;
}
private:
std::wofstream m_FileStream;
};

View File

@ -0,0 +1,19 @@
#pragma once
#include <Windows.h>
#include "Domain/Logger/LogChannel.h"
using namespace L2Bot::Domain;
class OutputDebugLogChannel : public Logger::LogChannel
{
public:
OutputDebugLogChannel(const std::vector<Logger::LogLevel> levels) : Logger::LogChannel(levels) {};
virtual ~OutputDebugLogChannel() = default;
protected:
void DoSendToChannel(const std::wstring& logEntry) override
{
OutputDebugStringW((GetCurrentDateTime() + logEntry).c_str());
}
};