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 <entt/locator/locator.hpp>
16#include <magic_enum/magic_enum.hpp>
17
21
22#define GALAXY_INFO galaxy::logging::LogLevel::_INFO_
23#define GALAXY_DEBUG galaxy::logging::LogLevel::_DEBUG_
24#define GALAXY_WARNING galaxy::logging::LogLevel::_WARNING_
25#define GALAXY_ERROR galaxy::logging::LogLevel::_ERROR_
26#define GALAXY_FATAL galaxy::logging::LogLevel::_FATAL_
27#define GALAXY_LOG_SET_MIN_LEVEL(level) entt::locator<galaxy::logging::Log>::value().set_min_level<level>()
28#define GALAXY_ADD_SINK(sink, ...) entt::locator<galaxy::logging::Log>::value().add_sink<sink>(__VA_ARGS__)
29#define GALAXY_LOG(level, msg, ...) entt::locator<galaxy::logging::Log>::value().log<level>(std::source_location::current(), msg __VA_OPT__(, ) __VA_ARGS__)
30
31namespace galaxy
32{
33 namespace logging
34 {
40 class Log final
41 {
42 public:
46 Log() noexcept;
47
51 ~Log() noexcept;
52
63 template<std::derived_from<Sink> SinkTo, typename... Args>
64 [[maybe_unused]]
65 SinkTo& add_sink(Args&&... args);
66
74 template<LogLevel level>
75 void set_min_level() noexcept;
76
87 template<LogLevel level, typename... MsgInputs>
88 void log(const std::source_location& loc, std::string_view message, const MsgInputs&... args);
89
90 private:
94 Log(const Log&) = delete;
95
99 Log(Log&&) = delete;
100
104 Log& operator=(const Log&) = delete;
105
109 Log& operator=(Log&&) = delete;
110
111 private:
116
120 std::vector<std::unique_ptr<Sink>> m_sinks;
121 };
122
123 template<std::derived_from<Sink> SinkTo, typename... Args>
124 inline SinkTo& Log::add_sink(Args&&... args)
125 {
126 m_sinks.push_back(std::make_unique<SinkTo>(std::forward<Args>(args)...));
127 SinkTo* ptr = dynamic_cast<SinkTo*>(m_sinks.back().get());
128 return *ptr;
129 }
130
131 template<LogLevel level>
132 inline void Log::set_min_level() noexcept
133 {
134 m_min_level = level;
135 }
136
137 template<LogLevel level, typename... MsgInputs>
138 inline void Log::log(const std::source_location& loc, std::string_view message, const MsgInputs&... args)
139 {
140 if (level >= m_min_level)
141 {
142 auto trace = std::stacktrace::current();
143
144 // clang-format off
145 LogMessage lm
146 {
147 .time = std::format("{0:%r}", std::chrono::zoned_time {std::chrono::current_zone(), std::chrono::system_clock::now()}.get_local_time()),
148 .file = std::filesystem::path(loc.file_name()).filename().string(),
149 .line = std::to_string(loc.line()),
150 .message = std::vformat(message, std::make_format_args(args...)),
151 .trace = std::to_string(trace)
152 };
153 // clang-format on
154
155 lm.level = magic_enum::enum_name<LogLevel>(level);
156 strutils::replace_all(lm.level, "_", "");
157
158 if constexpr (level == LogLevel::_INFO_ || level == LogLevel::_DEBUG_)
159 {
160 lm.colour = "\x1b[1m\x1b[33m";
161 }
162 else if constexpr (level == LogLevel::_WARNING_)
163 {
164 lm.colour = "\x1b[1m\x1b[31m";
165 }
166 else if constexpr (level == LogLevel::_ERROR_ || level == LogLevel::_FATAL_)
167 {
168 lm.colour = "\x1b[41m\x1b[37m";
169 }
170
171 for (const auto& sink : m_sinks)
172 {
173 sink->sink_message(lm);
174 }
175
176 if constexpr (level == LogLevel::_FATAL_)
177 {
178 throw std::runtime_error(std::to_string(trace));
179 }
180 }
181 }
182 } // namespace logging
183} // namespace galaxy
184
185#endif
Sink based logging system.
Definition Log.hpp:41
Log & operator=(const Log &)=delete
Copy assignment operator.
Log(Log &&)=delete
Move constructor.
void set_min_level() noexcept
Set a minimum log level.
Definition Log.hpp:132
std::vector< std::unique_ptr< Sink > > m_sinks
List of sinks.
Definition Log.hpp:120
SinkTo & add_sink(Args &&... args)
Add a sink to log to.
Definition Log.hpp:124
void log(const std::source_location &loc, std::string_view message, const MsgInputs &... args)
Log a message.
Definition Log.hpp:138
LogLevel m_min_level
Minimum level for a message to be logged.
Definition Log.hpp:115
Log & operator=(Log &&)=delete
Move assignment operator.
Log(const Log &)=delete
Copy constructor.
~Log() noexcept
Destructor.
Definition Log.cpp:22
Log() noexcept
Constructor.
Definition Log.cpp:16
LogLevel
Used to determine filtering and colouring of log messages.
Definition LogLevel.hpp:19
@ _DEBUG_
Debug Log Level.
@ _ERROR_
Error Log Level.
@ _FATAL_
Fatal Log Level.
@ _INFO_
Info Log Level.
@ _WARNING_
Warning Log Level.
void replace_all(std::string &input, std::string_view to_replace, std::string_view replace_with) noexcept
Replaces all occurrences of a string.
Timer.hpp galaxy.
Definition Async.hpp:17
Parts of a log message to be passed to sinks.
std::string level
Level of message.