galaxy 1.0.0
Real-Time C++23 Game Programming Framework. Built on data-driven design principles and agile software engineering.
Loading...
Searching...
No Matches
Log.hpp
Go to the documentation of this file.
1
7
8#ifndef GALAXY_LOGGING_LOG_HPP_
9#define GALAXY_LOGGING_LOG_HPP_
10
11#include <filesystem>
12#include <source_location>
13#include <stacktrace>
14
15#include <BS_thread_pool.hpp>
16#include <entt/locator/locator.hpp>
17#include <magic_enum/magic_enum.hpp>
18
22
23#define GALAXY_INFO galaxy::LogLevel::INFO
24#define GALAXY_WARN galaxy::LogLevel::WARNING
25#define GALAXY_ERROR galaxy::LogLevel::ERROR
26#define GALAXY_FATAL galaxy::LogLevel::FATAL
27#define GALAXY_LOG_SET_MIN_LEVEL(level) entt::locator<galaxy::Log>::value().set_min_level<level>()
28#define GALAXY_ADD_SINK(sink, ...) entt::locator<galaxy::Log>::value().add_sink<sink>(__VA_ARGS__)
29#define GALAXY_LOG(level, msg, ...) entt::locator<galaxy::Log>::value().log<level>(std::stacktrace::current(), std::source_location::current(), msg __VA_OPT__(, ) __VA_ARGS__)
30
31namespace galaxy
32{
38 class Log final
39 {
40 public:
44 Log() noexcept;
45
49 ~Log() noexcept;
50
61 template<std::derived_from<Sink> SinkTo, typename... Args>
62 [[maybe_unused]]
63 SinkTo& add_sink(Args&&... args);
64
72 template<LogLevel level>
73 void set_min_level() noexcept;
74
86 template<LogLevel level, typename... MsgInputs>
87 void log(const std::stacktrace& trace, const std::source_location& loc, std::string_view message, const MsgInputs&... args);
88
89 private:
93 Log(const Log&) = delete;
94
98 Log(Log&&) = delete;
99
103 Log& operator=(const Log&) = delete;
104
108 Log& operator=(Log&&) = delete;
109
110 private:
115
119 std::vector<std::unique_ptr<Sink>> m_sinks;
120
124 std::mutex m_mutex;
125 };
126
127 template<std::derived_from<Sink> SinkTo, typename... Args>
128 inline SinkTo& Log::add_sink(Args&&... args)
129 {
130 m_sinks.push_back(std::make_unique<SinkTo>(std::forward<Args>(args)...));
131 SinkTo* ptr = dynamic_cast<SinkTo*>(m_sinks.back().get());
132 return *ptr;
133 }
134
135 template<LogLevel level>
136 inline void Log::set_min_level() noexcept
137 {
138 m_min_level = level;
139 }
140
141 template<LogLevel level, typename... MsgInputs>
142 inline void Log::log(const std::stacktrace& trace, const std::source_location& loc, std::string_view message, const MsgInputs&... args)
143 {
144 auto& tp = entt::locator<BS::priority_thread_pool>::value();
145 tp.detach_task(
146 [this, trace = trace, loc = loc, message = message, ... args = args]() {
147 if (level >= m_min_level)
148 {
149 // clang-format off
150 LogMessage lm
151 {
153 .level = level,
154 .time = std::format("{0:%r}", std::chrono::zoned_time {std::chrono::current_zone(), std::chrono::system_clock::now()}.get_local_time()),
155 .file = std::filesystem::path(loc.file_name()).filename().string(),
156 .line = loc.line(),
157 .message = std::vformat(message, std::make_format_args(args...)),
158 .trace = std::to_string(trace)
159 };
160 // clang-format on
161
162 // Send message to all sinks.
163 const std::lock_guard<std::mutex> lock(m_mutex);
164
165 for (const auto& sink : m_sinks)
166 {
167 sink->sink(lm);
168 }
169
170 // Then throw error if its FATAL.
171 if constexpr (level == LogLevel::FATAL)
172 {
173 throw std::runtime_error(lm.trace);
174 }
175 }
176 },
177 BS::pr::lowest
178 );
179 }
180} // namespace galaxy
181
182#endif
Sink based logging system.
Definition Log.hpp:39
std::mutex m_mutex
Only do 1 set of sinks at a time.
Definition Log.hpp:124
Log & operator=(Log &&)=delete
Move assignment operator.
Log() noexcept
Constructor.
Definition Log.cpp:38
Log & operator=(const Log &)=delete
Copy assignment operator.
Log(Log &&)=delete
Move constructor.
~Log() noexcept
Destructor.
Definition Log.cpp:45
std::vector< std::unique_ptr< Sink > > m_sinks
List of sinks.
Definition Log.hpp:119
LogLevel m_min_level
Minimum level for a message to be logged.
Definition Log.hpp:114
void log(const std::stacktrace &trace, const std::source_location &loc, std::string_view message, const MsgInputs &... args)
Log a message.
Definition Log.hpp:142
Log(const Log &)=delete
Copy constructor.
SinkTo & add_sink(Args &&... args)
Add a sink to log to.
Definition Log.hpp:128
void set_min_level() noexcept
Set a minimum log level.
Definition Log.hpp:136
Application.hpp galaxy.
LogLevel
Used to determine filtering and colouring of log messages.
Definition LogLevel.hpp:24
@ FATAL
Fatal Log Level.
constexpr const char *const get_loglevel_colour()
Definition LogLevel.hpp:47
Parts of a log message to be passed to sinks.