Skip to content

Commit 1ff5291

Browse files
committed
feat(Logger): added FlushQueue method
1 parent 6c109e5 commit 1ff5291

2 files changed

Lines changed: 163 additions & 138 deletions

File tree

include/AsyncLogger/Logger.hpp

Lines changed: 75 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,68 +1,76 @@
1-
#pragma once
2-
#ifndef USE_FMT
3-
#include <format>
4-
#define FORMAT std::format
5-
#define VFORMAT std::vformat
6-
#define MAKE_FORMAT_ARGS std::make_format_args
7-
#else
8-
#include <fmt/core.h>
9-
#define FORMAT fmt::format
10-
#define VFORMAT fmt::vformat
11-
#define MAKE_FORMAT_ARGS fmt::make_format_args
12-
#endif
13-
#include <functional>
14-
#include "concurrency/shared_queue.hpp"
15-
#include "LogCapture.hpp"
16-
#include "LogIntermediate.hpp"
17-
#include "LogLevel.hpp"
18-
#include "LogMessage.hpp"
19-
20-
namespace al
21-
{
22-
using LogMessagePtr = std::shared_ptr<LogMessage>;
23-
using LogSink = std::function<void(LogMessagePtr)>;
24-
25-
class Logger
26-
{
27-
public:
28-
Logger() = default;
29-
virtual ~Logger() = default;
30-
31-
static void AddSink(LogSink sink);
32-
static void Destroy();
33-
static void Init();
34-
35-
protected:
36-
static void PushMessage(const eLogLevel level, std::chrono::system_clock::time_point&& timestamp, std::source_location&& location, std::string&& message) noexcept;
37-
38-
private:
39-
void CallSinks(LogMessagePtr msgPtr);
40-
void DestroyImpl();
41-
void InitImpl();
42-
void QueueMessage(LogMessagePtr msgPtr);
43-
44-
static Logger& GetInstance()
45-
{
46-
static Logger i{};
47-
return i;
48-
}
49-
50-
private:
51-
friend LogCapture::~LogCapture();
52-
53-
shared_queue<std::function<void()>> m_Queue;
54-
std::vector<LogSink> m_Sinks;
55-
bool m_Running = false;
56-
std::thread m_LogWorker;
57-
58-
};
59-
60-
extern LogCapture LOG(const eLogLevel level, std::source_location location = std::source_location::current());
61-
62-
template<typename ...Args>
63-
inline void LOGF(const eLogLevel level, LogIntermediate formatString, Args&&... formatArgs)
64-
{
65-
auto capture = LogCapture(level, std::move(formatString.Location()));
66-
capture << VFORMAT(formatString.FormatString(), MAKE_FORMAT_ARGS(std::forward<Args>(formatArgs)...));
67-
}
1+
#pragma once
2+
#ifndef USE_FMT
3+
#include <format>
4+
#define FORMAT std::format
5+
#define VFORMAT std::vformat
6+
#define MAKE_FORMAT_ARGS std::make_format_args
7+
#else
8+
#include <fmt/core.h>
9+
#define FORMAT fmt::format
10+
#define VFORMAT fmt::vformat
11+
#define MAKE_FORMAT_ARGS fmt::make_format_args
12+
#endif
13+
#include <functional>
14+
#include "concurrency/shared_queue.hpp"
15+
#include "LogCapture.hpp"
16+
#include "LogIntermediate.hpp"
17+
#include "LogLevel.hpp"
18+
#include "LogMessage.hpp"
19+
20+
namespace al
21+
{
22+
using LogMessagePtr = std::shared_ptr<LogMessage>;
23+
using LogSink = std::function<void(LogMessagePtr)>;
24+
25+
class Logger
26+
{
27+
public:
28+
Logger() = default;
29+
virtual ~Logger() = default;
30+
31+
static void AddSink(LogSink sink);
32+
static void Destroy();
33+
static void Init();
34+
/**
35+
* @brief Attempts to flush the log queue immediately until it's completely empty.
36+
*/
37+
static void FlushQueue();
38+
39+
protected:
40+
static void PushMessage(const eLogLevel level, std::chrono::system_clock::time_point&& timestamp, std::source_location&& location, std::string&& message) noexcept;
41+
42+
private:
43+
void CallSinks(LogMessagePtr msgPtr);
44+
void DestroyImpl();
45+
void InitImpl();
46+
/**
47+
* @brief Attempts to flush the entire log queue before returning
48+
*/
49+
void FlushQueueImpl();
50+
void QueueMessage(LogMessagePtr msgPtr);
51+
52+
static Logger& GetInstance()
53+
{
54+
static Logger i{};
55+
return i;
56+
}
57+
58+
private:
59+
friend LogCapture::~LogCapture();
60+
61+
shared_queue<std::function<void()>> m_Queue;
62+
std::vector<LogSink> m_Sinks;
63+
bool m_Running = false;
64+
std::thread m_LogWorker;
65+
66+
};
67+
68+
extern LogCapture LOG(const eLogLevel level, std::source_location location = std::source_location::current());
69+
70+
template<typename ...Args>
71+
inline void LOGF(const eLogLevel level, LogIntermediate formatString, Args&&... formatArgs)
72+
{
73+
auto capture = LogCapture(level, std::move(formatString.Location()));
74+
capture << VFORMAT(formatString.FormatString(), MAKE_FORMAT_ARGS(std::forward<Args>(formatArgs)...));
75+
}
6876
}

src/Logger.cpp

Lines changed: 88 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,72 +1,89 @@
1-
#include "Logger.hpp"
2-
#include "LogCapture.hpp"
3-
#include "LogMessage.hpp"
4-
5-
namespace al
6-
{
7-
LogCapture LOG(const eLogLevel level, std::source_location location)
8-
{
9-
return LogCapture{ level, std::move(location) };
10-
}
11-
12-
void Logger::AddSink(LogSink sink)
13-
{
14-
Logger::GetInstance().m_Sinks.push_back(sink);
15-
}
16-
17-
void Logger::Destroy()
18-
{
19-
Logger::GetInstance().DestroyImpl();
20-
}
21-
22-
void Logger::Init()
23-
{
24-
Logger::GetInstance().InitImpl();
25-
}
26-
27-
void Logger::PushMessage(const eLogLevel level, std::chrono::system_clock::time_point&& timestamp, std::source_location&& location, std::string&& message) noexcept
28-
{
29-
auto msgPtr = std::make_shared<LogMessage>(level, std::move(timestamp), std::move(location), std::move(message));
30-
31-
Logger::GetInstance().QueueMessage(std::move(msgPtr));
32-
}
33-
34-
void Logger::CallSinks(LogMessagePtr msgPtr)
35-
{
36-
for (const auto &sink : m_Sinks)
37-
{
38-
sink(msgPtr);
39-
}
40-
}
41-
42-
void Logger::DestroyImpl()
43-
{
44-
m_Queue.push([this]
45-
{
46-
m_Running = false;
47-
});
48-
m_LogWorker.join();
49-
}
50-
51-
void Logger::InitImpl()
52-
{
53-
m_Running = true;
54-
m_LogWorker = std::thread([this]
55-
{
56-
while (m_Running)
57-
{
58-
std::function<void()> func;
59-
m_Queue.wait_and_pop(func);
60-
func();
61-
}
62-
});
63-
}
64-
65-
void Logger::QueueMessage(LogMessagePtr msgPtr)
66-
{
67-
m_Queue.push([this, msgPtr = std::move(msgPtr)]
68-
{
69-
CallSinks(msgPtr);
70-
});
71-
}
1+
#include "Logger.hpp"
2+
#include "LogCapture.hpp"
3+
#include "LogMessage.hpp"
4+
5+
namespace al
6+
{
7+
LogCapture LOG(const eLogLevel level, std::source_location location)
8+
{
9+
return LogCapture{ level, std::move(location) };
10+
}
11+
12+
void Logger::AddSink(LogSink sink)
13+
{
14+
Logger::GetInstance().m_Sinks.push_back(sink);
15+
}
16+
17+
void Logger::Destroy()
18+
{
19+
Logger::GetInstance().DestroyImpl();
20+
}
21+
22+
void Logger::Init()
23+
{
24+
Logger::GetInstance().InitImpl();
25+
}
26+
27+
void Logger::FlushQueue()
28+
{
29+
GetInstance().FlushQueueImpl();
30+
}
31+
32+
void Logger::PushMessage(const eLogLevel level,
33+
std::chrono::system_clock::time_point &&timestamp,
34+
std::source_location &&location,
35+
std::string &&message) noexcept {
36+
auto msgPtr = std::make_shared<LogMessage>(level, std::move(timestamp), std::move(location), std::move(message));
37+
38+
Logger::GetInstance().QueueMessage(std::move(msgPtr));
39+
}
40+
41+
void Logger::CallSinks(LogMessagePtr msgPtr)
42+
{
43+
for (const auto &sink : m_Sinks)
44+
{
45+
sink(msgPtr);
46+
}
47+
}
48+
49+
void Logger::DestroyImpl()
50+
{
51+
m_Queue.push([this]
52+
{
53+
m_Running = false;
54+
});
55+
m_LogWorker.join();
56+
}
57+
58+
void Logger::InitImpl()
59+
{
60+
m_Running = true;
61+
m_LogWorker = std::thread([this]
62+
{
63+
while (m_Running)
64+
{
65+
std::function<void()> func;
66+
m_Queue.wait_and_pop(func);
67+
func();
68+
}
69+
});
70+
}
71+
72+
void Logger::FlushQueueImpl()
73+
{
74+
while (!m_Queue.empty())
75+
{
76+
std::function<void()> func;
77+
m_Queue.wait_and_pop(func);
78+
func();
79+
}
80+
}
81+
82+
void Logger::QueueMessage(LogMessagePtr msgPtr)
83+
{
84+
m_Queue.push([this, msgPtr = std::move(msgPtr)]
85+
{
86+
CallSinks(msgPtr);
87+
});
88+
}
7289
}

0 commit comments

Comments
 (0)