// Copyright Epic Games, Inc. All Rights Reserved. #include #include #include #include namespace zen::logging { struct Logger::Impl { std::string m_Name; std::vector m_Sinks; ErrorHandler* m_ErrorHandler = nullptr; }; Logger::Logger(std::string_view InName, SinkPtr InSink) : m_Impl(std::make_unique()) { m_Impl->m_Name = InName; m_Impl->m_Sinks.push_back(std::move(InSink)); } Logger::Logger(std::string_view InName, std::span InSinks) : m_Impl(std::make_unique()) { m_Impl->m_Name = InName; m_Impl->m_Sinks.assign(InSinks.begin(), InSinks.end()); } Logger::~Logger() = default; void Logger::Log(const LogPoint& Point, fmt::format_args Args) { if (!ShouldLog(Point.Level)) { return; } fmt::basic_memory_buffer Buffer; fmt::vformat_to(fmt::appender(Buffer), Point.FormatString, Args); LogMessage LogMsg(Point, m_Impl->m_Name, std::string_view(Buffer.data(), Buffer.size())); LogMsg.SetThreadId(GetCurrentThreadId()); SinkIt(LogMsg); FlushIfNeeded(Point.Level); } void Logger::SinkIt(const LogMessage& Msg) { for (auto& CurrentSink : m_Impl->m_Sinks) { if (CurrentSink->ShouldLog(Msg.GetLevel())) { try { CurrentSink->Log(Msg); } catch (const std::exception& Ex) { if (m_Impl->m_ErrorHandler) { m_Impl->m_ErrorHandler->HandleError(Ex.what()); } } } } } void Logger::FlushIfNeeded(LogLevel InLevel) { if (InLevel >= m_FlushLevel.load(std::memory_order_relaxed)) { Flush(); } } void Logger::Flush() { for (auto& CurrentSink : m_Impl->m_Sinks) { try { CurrentSink->Flush(); } catch (const std::exception& Ex) { if (m_Impl->m_ErrorHandler) { m_Impl->m_ErrorHandler->HandleError(Ex.what()); } } } } void Logger::SetSinks(std::vector InSinks) { m_Impl->m_Sinks = std::move(InSinks); } void Logger::AddSink(SinkPtr InSink) { m_Impl->m_Sinks.push_back(std::move(InSink)); } void Logger::SetErrorHandler(ErrorHandler* Handler) { m_Impl->m_ErrorHandler = Handler; } void Logger::SetFormatter(std::unique_ptr InFormatter) { for (auto& CurrentSink : m_Impl->m_Sinks) { CurrentSink->SetFormatter(InFormatter->Clone()); } } std::string_view Logger::Name() const { return m_Impl->m_Name; } Ref Logger::Clone(std::string_view NewName) const { Ref Cloned(new Logger(NewName, m_Impl->m_Sinks)); Cloned->SetLevel(m_Level.load(std::memory_order_relaxed)); Cloned->SetFlushLevel(m_FlushLevel.load(std::memory_order_relaxed)); Cloned->SetErrorHandler(m_Impl->m_ErrorHandler); return Cloned; } } // namespace zen::logging