ReXGlue SDK
Loading...
Searching...
No Matches
logger.h
Go to the documentation of this file.
1
10
11#pragma once
12
13#include <chrono>
14#include <deque>
15#include <filesystem>
16#include <fstream>
17#include <memory>
18#include <mutex>
19#include <span>
20#include <string>
21#include <string_view>
22#include <vector>
23
25#include <rex/module.h>
26#include <rex/platform.h>
27#include <rex/result.h>
28#include <rex/setting.h>
29#include <rex/types.h>
30#include <rex/utility.h>
31
32namespace rex::log {
33
35enum class TimestampStyle : u8 {
36 kNone,
40};
41
43struct LineFormat {
44 TimestampStyle timestamp = TimestampStyle::kNone;
45 bool category = true;
46 bool thread = false;
47 bool color = true;
48};
49
51struct Message {
52 Level level = Level::kInfo;
53 std::string_view category;
54 std::string_view text;
55 std::chrono::system_clock::time_point time;
56 u32 thread_id = 0;
57 u64 sequence = 0;
58};
59
65REX_API std::string FormatLine(const Message& message, const LineFormat& format);
66
68inline constexpr std::string_view kColorReset = "\x1b[0m";
69
71REX_API std::string_view LevelColor(Level level);
72
77
78} // namespace rex::log
79
80namespace rex::log {
81
83class ILogSink : public NonCopyable {
84 public:
85 virtual ~ILogSink() = default;
86
87 virtual void Write(const Message& message) = 0;
88
89 virtual void Flush() = 0;
90};
91
93class REX_API LogFileSink final : public ILogSink {
94 public:
102 [[nodiscard]] static Result<std::unique_ptr<LogFileSink>> Open(const std::filesystem::path& path,
103 LineFormat format);
104
105 void Write(const Message& message) override;
106
107 void Flush() override;
108
112 const std::filesystem::path& GetPath() const;
113
119 LogFileSink(std::filesystem::path path, std::ofstream file, LineFormat format);
120
121 private:
122 std::filesystem::path path_;
123 std::ofstream file_;
124 LineFormat format_;
125};
126
129 Level level = Level::kInfo;
130 std::string category;
131 std::string text;
132 std::chrono::system_clock::time_point time;
133 u32 thread_id = 0;
134 u64 sequence = 0;
135};
136
138class REX_API LogCaptureSink final : public ILogSink {
139 public:
140 static constexpr size_t kCapacity = 4096;
141
145 void Write(const Message& message) override;
146
148 void Flush() override;
149
157 u64 CopySince(u64 after, std::vector<CapturedMessage>& out) const;
158
160 u64 GetLatestSequence() const;
161
162 private:
163 mutable std::mutex mutex_;
164 std::deque<CapturedMessage> messages_;
165};
166
167} // namespace rex::log
168
169namespace rex {
170
171class ProcessLoggerControl;
172
181 [[nodiscard]] virtual Result<void> AddCategories(
182 std::span<const log::LogCategory* const> categories) = 0;
183
187 virtual void RemoveCategories(std::span<const log::LogCategory* const> categories) = 0;
188
196 [[nodiscard]] virtual ScopeGuard AddSink(log::ILogSink& sink) = 0;
197
199 virtual void Flush() = 0;
200
206 virtual void Emit(const log::Message& message) = 0;
207};
208
214class REX_API Logger final : public SettingOwner, public ILogger {
215 public:
216 ~Logger() override;
217
218 REX_SETTING(std::string, level, "info",
219 "Lowest level written by a category without its own level",
220 Allowed("trace", "dev", "debug", "info", "warn", "error", "critical", "off"));
221 REX_SETTING(std::string, flush_level, "warn", "Lowest level that flushes every sink at once",
222 Allowed("trace", "dev", "debug", "info", "warn", "error", "critical", "off"),
223 kStartupOnly);
224 REX_SETTING(i32, flush_interval, 1, "Seconds between flushes", Range{0, 60}, kStartupOnly);
225 REX_SETTING(bool, console, true, "Write to the console", kStartupOnly);
226 REX_SETTING(bool, debugger, true, "Write to an attached debugger", kStartupOnly);
227 REX_SETTING(bool, file, true, "Write a log file under app.log_root", kStartupOnly);
228 REX_SETTING(std::string, file_name, "", "File name, the app name when empty", kStartupOnly);
229 REX_SETTING(i64, folder_budget, 0, "Bytes of old log files kept, 0 keeps all",
230 Range{0, 9007199254740992.0}, kStartupOnly);
231 REX_SETTING(std::string, pattern, "%^%Y-%m-%d %H:%M:%S.%e %Q %-10n %j %v%$",
232 "Layout of each line, an spdlog pattern with %Q for the level letter and %j for the "
233 "thread",
234 kStartupOnly);
235 REX_SETTING(bool, color, false, "Color the console", kStartupOnly);
236
238 std::span<const log::LogCategory* const> categories) override;
239
240 void RemoveCategories(std::span<const log::LogCategory* const> categories) override;
241
242 [[nodiscard]] ScopeGuard AddSink(log::ILogSink& sink) override;
243
244 void Flush() override;
245
246 void Emit(const log::Message& message) override;
247
248 struct State;
249
250 private:
251 Logger();
252 friend REX_API Logger& GetLogger();
253 friend class ProcessLoggerControl;
254
255 void ApplySettled();
256 [[nodiscard]] Result<void> OpenFile(const std::filesystem::path& log_root,
257 std::string_view app_name);
258 void EndSession();
259
260 std::unique_ptr<State> state_;
261};
262
265
266#define REX_LOGGER() ::rex::GetLogger()
267
268} // namespace rex
Definition logger.h:174
Definition logger.h:214
void Flush() override
ScopeGuard AddSink(log::ILogSink &sink) override
void Emit(const log::Message &message) override
friend Logger & GetLogger()
void RemoveCategories(std::span< const log::LogCategory *const > categories) override
Result< void > AddCategories(std::span< const log::LogCategory *const > categories) override
Definition utility.h:305
SettingOwner(std::string_view scope)
Definition logger.h:83
Definition logger.h:138
void Write(const Message &message) override
void Flush() override
u64 GetLatestSequence() const
u64 CopySince(u64 after, std::vector< CapturedMessage > &out) const
LogFileSink(std::filesystem::path path, std::ofstream file, LineFormat format)
static Result< std::unique_ptr< LogFileSink > > Open(const std::filesystem::path &path, LineFormat format)
const std::filesystem::path & GetPath() const
Interfaces, factory and module declaration.
#define REX_DECLARE_INTERFACE(Name, version)
Definition module.h:114
Definition log_category.h:29
std::string FormatLine(const Message &message, const LineFormat &format)
Level
Definition log_category.h:32
@ kInfo
Definition log_category.h:36
constexpr std::string_view kColorReset
Definition logger.h:68
TimestampStyle
Definition logger.h:35
@ kElapsed
Definition logger.h:39
@ kClock
Definition logger.h:37
@ kDateTime
Definition logger.h:38
char LevelLetter(Level level)
std::string_view LevelColor(Level level)
Definition app.h:36
std::expected< T, Error > Result
Definition result.h:98
Logger & GetLogger()
Platform flags, packing macros and export markers.
#define REX_API
Definition platform.h:177
Typed settings and the owners that declare them.
Definition setting.h:84
Definition setting.h:78
Definition logger.h:128
Definition logger.h:43
bool color
Definition logger.h:47
bool thread
Definition logger.h:46
Definition logger.h:51
u64 sequence
Definition logger.h:57
Integer types, byte order wrappers and size literals.
Move only function, const propagating pointer and scope guard.