Skip to main content

LogManager.ixx File

Central manager for scoped loggers with configurable sinks. More...

Included Headers

#include <string> #include <unordered_map> #include <unordered_set> #include <memory> #include <mutex> #include <vector> #include <cstring> #include <helios.engine.util.log.Logger> #include <helios.engine.util.log.LogSink>

Namespaces Index

namespacehelios
namespaceengine
namespaceutil
namespacelog

Classes Index

classLogManager

LogManager for managing scoped Loggers and global sink configuration. More...

Macro Definitions Index

#defineLOGGING_ENABLED   true

Description

Central manager for scoped loggers with configurable sinks.

Macro Definitions

LOGGING_ENABLED

#define LOGGING_ENABLED   true

Definition at line 20 of file LogManager.ixx.

20#define LOGGING_ENABLED true

File Listing

The file content with the documentation metadata removed is:

1
5module;
6
7#include <string>
8#include <unordered_map>
9#include <unordered_set>
10#include <memory>
11#include <mutex>
12#include <vector>
13#include <cstring>
14
15export module helios.engine.util.log.LogManager;
16
17import helios.engine.util.log.LogSink;
18import helios.engine.util.log.Logger;
19
20#define LOGGING_ENABLED true
21export namespace helios::engine::util::log {
22
43 class LogManager {
44
45 private:
46
50 bool loggingEnabled_ = LOGGING_ENABLED;
51
55 std::unordered_set<std::string> enabledSinks_;
56
60 std::vector<std::shared_ptr<LogSink>> registeredSinks_;
61
66 std::unordered_map<std::string, std::unique_ptr<Logger>> loggers_;
67
71 const std::unique_ptr<Logger> defaultLogger_;
72
76 mutable std::mutex mapMutex_;
77
81 mutable std::mutex sinkMutex_;
82
86 LogManager() : defaultLogger_(std::make_unique<Logger>("default")) {}
87
93 void updateLoggerSinks() {
94 // Called with sinkMutex_ already held
95 std::lock_guard<std::mutex> mapLock(mapMutex_);
96
97 // Update default logger
98 defaultLogger_->clearSinks();
99 for (const auto& sink : registeredSinks_) {
100 if (sink && enabledSinks_.contains(sink->typeId())) {
101 defaultLogger_->addSink(sink);
102 }
103 }
104
105 // Update all registered loggers
106 for (auto& [scope, logger] : loggers_) {
108 for (const auto& sink : registeredSinks_) {
109 if (sink && enabledSinks_.contains(sink->typeId())) {
111 }
112 }
113 }
114 }
115
116 public:
117
128 static const Logger& loggerForScope(const std::string& scope) noexcept {
130 }
131
132 ~LogManager() = default;
133
139 LogManager(const LogManager&) = delete;
140 LogManager& operator=(const LogManager&) = delete;
141
148 static LogManager instance;
149
150 return instance;
151 }
152
159 return *defaultLogger_;
160 }
161
173 [[nodiscard]] const Logger& logger(const std::string& scope) const noexcept {
174 // mapMutex_ is automatically released when going out of scope
175 std::lock_guard<std::mutex> lock(mapMutex_);
176
177 auto log = loggers_.find(scope);
178 if (log != loggers_.end()) {
179 return *(log->second);
180 }
181
182 return *defaultLogger_;
183 }
184
195 [[nodiscard]] Logger& registerLogger(const std::string& scope) noexcept {
196 // mapMutex_ is automatically released when going out of scope
197 std::lock_guard<std::mutex> lock(mapMutex_);
198
199 if (auto log = loggers_.find(scope); log != loggers_.end()) {
200 return *(log->second);
201 }
202
203 auto logger = std::make_unique<Logger>(scope);
204 loggers_[scope] = std::move(logger);
205 loggers_[scope]->enable(loggingEnabled_);
206
207 // Configure sinks for new logger
208 {
209 std::lock_guard<std::mutex> sinkLock(sinkMutex_);
210 for (const auto& sink : registeredSinks_) {
211 if (sink && enabledSinks_.contains(sink->typeId())) {
212 loggers_[scope]->addSink(sink);
213 }
214 }
215 }
216
217 return *loggers_[scope];
218 }
219
225 void enableLogging(bool enable) noexcept {
226 std::lock_guard<std::mutex> lock(mapMutex_);
227
228 if (loggingEnabled_ == enable) {
229 return;
230 }
231
232 loggingEnabled_ = enable;
233
234 for (auto& [fst, snd]: loggers_) {
235 snd->enable(enable);
236 }
237 }
238
247 void setScopeFilter(const std::string& scope) noexcept {
248 if (!loggingEnabled_) {
249 return;
250 }
251
252 // Make sure the logger exists first (this acquires mapMutex_ internally)
254
255 // Now lock and update the filter
256 std::lock_guard<std::mutex> lock(mapMutex_);
257
258 for (auto& [fst, snd] : loggers_) {
259 if (fst == scope) {
260 snd->enable(true);
261 } else {
262 snd->enable(false);
263 }
264 }
265 }
266
267 // ===== Sink Management =====
268
276 void registerSink(std::shared_ptr<LogSink> sink) {
277 registerSink(std::move(sink), true);
278 }
279
286 void registerSink(std::shared_ptr<LogSink> sink, bool enabled) {
287 if (!sink) return;
288
289 std::lock_guard<std::mutex> lock(sinkMutex_);
290
291 // Check if sink with same typeId is already registered
292 bool alreadyRegistered = false;
293 for (const auto& existing : registeredSinks_) {
294 if (existing && std::strcmp(existing->typeId(), sink->typeId()) == 0) {
295 alreadyRegistered = true;
296 break;
297 }
298 }
299
300 if (!alreadyRegistered) {
301 registeredSinks_.push_back(sink);
302 }
303
304 if (enabled) {
305 enabledSinks_.insert(sink->typeId());
306 }
307
308 updateLoggerSinks();
309 }
310
319 void enableSink(SinkTypeId typeId) {
320 std::lock_guard<std::mutex> lock(sinkMutex_);
321 enabledSinks_.insert(typeId);
322 updateLoggerSinks();
323 }
324
337 template<typename TSink, typename ...Args>
338 void enableSink(Args&& ...args) requires std::derived_from<TSink, LogSink>{
339 auto snk = std::make_shared<TSink>(std::forward<Args>(args)...);
340 enableSink(std::move(snk));
341 }
342
351 void enableSink(std::shared_ptr<LogSink> sink) {
352 if (!sink) return;
353
354 std::lock_guard<std::mutex> lock(sinkMutex_);
355
356 // Check if already registered
357 bool alreadyRegistered = false;
358 for (const auto& existing : registeredSinks_) {
359 if (existing && std::strcmp(existing->typeId(), sink->typeId()) == 0) {
360 alreadyRegistered = true;
361 break;
362 }
363 }
364
365 // Auto-register if not already registered
366 if (!alreadyRegistered) {
367 registeredSinks_.push_back(sink);
368 }
369
370 enabledSinks_.insert(sink->typeId());
371 updateLoggerSinks();
372 }
373
379 void disableSink(SinkTypeId typeId) {
380 std::lock_guard<std::mutex> lock(sinkMutex_);
381 enabledSinks_.erase(typeId);
382 updateLoggerSinks();
383 }
384
390 void disableSink(std::shared_ptr<LogSink> sink) {
391 if (!sink) return;
392 disableSink(sink->typeId());
393 }
394
402 [[nodiscard]] bool isSinkEnabled(SinkTypeId typeId) const noexcept {
403 std::lock_guard<std::mutex> lock(sinkMutex_);
404 return enabledSinks_.contains(typeId);
405 }
406
411 std::lock_guard<std::mutex> lock(sinkMutex_);
412 for (const auto& sink : registeredSinks_) {
413 if (sink) {
414 enabledSinks_.insert(sink->typeId());
415 }
416 }
417 updateLoggerSinks();
418 }
419
424 std::lock_guard<std::mutex> lock(sinkMutex_);
425 enabledSinks_.clear();
426 updateLoggerSinks();
427 }
428 };
429
430}

Generated via doxygen2docusaurus 2.0.0 by Doxygen 1.9.8.