aboutsummaryrefslogtreecommitdiff
path: root/src/zencore/logging/registry.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/zencore/logging/registry.cpp')
-rw-r--r--src/zencore/logging/registry.cpp330
1 files changed, 330 insertions, 0 deletions
diff --git a/src/zencore/logging/registry.cpp b/src/zencore/logging/registry.cpp
new file mode 100644
index 000000000..3ed1fb0df
--- /dev/null
+++ b/src/zencore/logging/registry.cpp
@@ -0,0 +1,330 @@
+// Copyright Epic Games, Inc. All Rights Reserved.
+
+#include <zencore/logging/registry.h>
+
+#include <zencore/logging/ansicolorsink.h>
+#include <zencore/logging/messageonlyformatter.h>
+
+#include <atomic>
+#include <condition_variable>
+#include <mutex>
+#include <thread>
+#include <unordered_map>
+
+namespace zen::logging {
+
+struct Registry::Impl
+{
+ Impl()
+ {
+ // Create default logger with a stdout color sink
+ SinkPtr DefaultSink(new AnsiColorStdoutSink());
+ m_DefaultLogger = Ref<Logger>(new Logger("", DefaultSink));
+ m_Loggers[""] = m_DefaultLogger;
+ }
+
+ ~Impl() { StopPeriodicFlush(); }
+
+ void Register(Ref<Logger> InLogger)
+ {
+ std::lock_guard<std::mutex> Lock(m_Mutex);
+ if (m_ErrorHandler)
+ {
+ InLogger->SetErrorHandler(m_ErrorHandler);
+ }
+ m_Loggers[std::string(InLogger->Name())] = std::move(InLogger);
+ }
+
+ void Drop(const std::string& Name)
+ {
+ std::lock_guard<std::mutex> Lock(m_Mutex);
+ m_Loggers.erase(Name);
+ }
+
+ Ref<Logger> Get(const std::string& Name)
+ {
+ std::lock_guard<std::mutex> Lock(m_Mutex);
+ auto It = m_Loggers.find(Name);
+ if (It != m_Loggers.end())
+ {
+ return It->second;
+ }
+ return {};
+ }
+
+ void SetDefaultLogger(Ref<Logger> InLogger)
+ {
+ std::lock_guard<std::mutex> Lock(m_Mutex);
+ if (InLogger)
+ {
+ m_Loggers[std::string(InLogger->Name())] = InLogger;
+ }
+ m_DefaultLogger = std::move(InLogger);
+ }
+
+ Logger* DefaultLoggerRaw() { return m_DefaultLogger.Get(); }
+
+ Ref<Logger> DefaultLogger()
+ {
+ std::lock_guard<std::mutex> Lock(m_Mutex);
+ return m_DefaultLogger;
+ }
+
+ void SetGlobalLevel(LogLevel Level)
+ {
+ m_GlobalLevel.store(Level, std::memory_order_relaxed);
+ std::lock_guard<std::mutex> Lock(m_Mutex);
+ for (auto& [Name, CurLogger] : m_Loggers)
+ {
+ CurLogger->SetLevel(Level);
+ }
+ }
+
+ LogLevel GetGlobalLevel() const { return m_GlobalLevel.load(std::memory_order_relaxed); }
+
+ void SetLevels(Registry::LogLevels Levels, LogLevel* DefaultLevel)
+ {
+ std::lock_guard<std::mutex> Lock(m_Mutex);
+
+ if (DefaultLevel)
+ {
+ m_GlobalLevel.store(*DefaultLevel, std::memory_order_relaxed);
+ for (auto& [Name, CurLogger] : m_Loggers)
+ {
+ CurLogger->SetLevel(*DefaultLevel);
+ }
+ }
+
+ for (auto& [LoggerName, Level] : Levels)
+ {
+ auto It = m_Loggers.find(LoggerName);
+ if (It != m_Loggers.end())
+ {
+ It->second->SetLevel(Level);
+ }
+ }
+ }
+
+ void FlushAll()
+ {
+ std::lock_guard<std::mutex> Lock(m_Mutex);
+ for (auto& [Name, CurLogger] : m_Loggers)
+ {
+ try
+ {
+ CurLogger->Flush();
+ }
+ catch (const std::exception&)
+ {
+ }
+ }
+ }
+
+ void FlushOn(LogLevel Level)
+ {
+ std::lock_guard<std::mutex> Lock(m_Mutex);
+ m_FlushLevel = Level;
+ for (auto& [Name, CurLogger] : m_Loggers)
+ {
+ CurLogger->SetFlushLevel(Level);
+ }
+ }
+
+ void FlushEvery(std::chrono::seconds Interval)
+ {
+ StopPeriodicFlush();
+
+ m_PeriodicFlushRunning.store(true, std::memory_order_relaxed);
+
+ m_FlushThread = std::thread([this, Interval] {
+ while (m_PeriodicFlushRunning.load(std::memory_order_relaxed))
+ {
+ {
+ std::unique_lock<std::mutex> Lock(m_PeriodicFlushMutex);
+ m_PeriodicFlushCv.wait_for(Lock, Interval, [this] { return !m_PeriodicFlushRunning.load(std::memory_order_relaxed); });
+ }
+
+ if (m_PeriodicFlushRunning.load(std::memory_order_relaxed))
+ {
+ FlushAll();
+ }
+ }
+ });
+ }
+
+ void SetFormatter(std::unique_ptr<Formatter> InFormatter)
+ {
+ std::lock_guard<std::mutex> Lock(m_Mutex);
+ for (auto& [Name, CurLogger] : m_Loggers)
+ {
+ CurLogger->SetFormatter(InFormatter->Clone());
+ }
+ }
+
+ void ApplyAll(void (*Func)(void*, Ref<Logger>), void* Context)
+ {
+ std::lock_guard<std::mutex> Lock(m_Mutex);
+ for (auto& [Name, CurLogger] : m_Loggers)
+ {
+ Func(Context, CurLogger);
+ }
+ }
+
+ void SetErrorHandler(ErrorHandler* Handler)
+ {
+ std::lock_guard<std::mutex> Lock(m_Mutex);
+ m_ErrorHandler = Handler;
+ for (auto& [Name, CurLogger] : m_Loggers)
+ {
+ CurLogger->SetErrorHandler(Handler);
+ }
+ }
+
+ void Shutdown()
+ {
+ StopPeriodicFlush();
+ FlushAll();
+
+ std::lock_guard<std::mutex> Lock(m_Mutex);
+ m_Loggers.clear();
+ m_DefaultLogger = nullptr;
+ }
+
+private:
+ void StopPeriodicFlush()
+ {
+ if (m_FlushThread.joinable())
+ {
+ m_PeriodicFlushRunning.store(false, std::memory_order_relaxed);
+ {
+ std::lock_guard<std::mutex> Lock(m_PeriodicFlushMutex);
+ m_PeriodicFlushCv.notify_one();
+ }
+ m_FlushThread.join();
+ }
+ }
+
+ std::mutex m_Mutex;
+ std::unordered_map<std::string, Ref<Logger>> m_Loggers;
+ Ref<Logger> m_DefaultLogger;
+ std::atomic<LogLevel> m_GlobalLevel{Trace};
+ LogLevel m_FlushLevel{Off};
+ ErrorHandler* m_ErrorHandler = nullptr;
+
+ // Periodic flush
+ std::atomic<bool> m_PeriodicFlushRunning{false};
+ std::mutex m_PeriodicFlushMutex;
+ std::condition_variable m_PeriodicFlushCv;
+ std::thread m_FlushThread;
+};
+
+Registry&
+Registry::Instance()
+{
+ static Registry s_Instance;
+ return s_Instance;
+}
+
+Registry::Registry() : m_Impl(std::make_unique<Impl>())
+{
+}
+
+Registry::~Registry() = default;
+
+void
+Registry::Register(Ref<Logger> InLogger)
+{
+ m_Impl->Register(std::move(InLogger));
+}
+
+void
+Registry::Drop(const std::string& Name)
+{
+ m_Impl->Drop(Name);
+}
+
+Ref<Logger>
+Registry::Get(const std::string& Name)
+{
+ return m_Impl->Get(Name);
+}
+
+void
+Registry::SetDefaultLogger(Ref<Logger> InLogger)
+{
+ m_Impl->SetDefaultLogger(std::move(InLogger));
+}
+
+Logger*
+Registry::DefaultLoggerRaw()
+{
+ return m_Impl->DefaultLoggerRaw();
+}
+
+Ref<Logger>
+Registry::DefaultLogger()
+{
+ return m_Impl->DefaultLogger();
+}
+
+void
+Registry::SetGlobalLevel(LogLevel Level)
+{
+ m_Impl->SetGlobalLevel(Level);
+}
+
+LogLevel
+Registry::GetGlobalLevel() const
+{
+ return m_Impl->GetGlobalLevel();
+}
+
+void
+Registry::SetLevels(LogLevels Levels, LogLevel* DefaultLevel)
+{
+ m_Impl->SetLevels(Levels, DefaultLevel);
+}
+
+void
+Registry::FlushAll()
+{
+ m_Impl->FlushAll();
+}
+
+void
+Registry::FlushOn(LogLevel Level)
+{
+ m_Impl->FlushOn(Level);
+}
+
+void
+Registry::FlushEvery(std::chrono::seconds Interval)
+{
+ m_Impl->FlushEvery(Interval);
+}
+
+void
+Registry::SetFormatter(std::unique_ptr<Formatter> InFormatter)
+{
+ m_Impl->SetFormatter(std::move(InFormatter));
+}
+
+void
+Registry::ApplyAllImpl(void (*Func)(void*, Ref<Logger>), void* Context)
+{
+ m_Impl->ApplyAll(Func, Context);
+}
+
+void
+Registry::SetErrorHandler(ErrorHandler* Handler)
+{
+ m_Impl->SetErrorHandler(Handler);
+}
+
+void
+Registry::Shutdown()
+{
+ m_Impl->Shutdown();
+}
+
+} // namespace zen::logging