// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "UbaLogWriter.h" #include "UbaMemory.h" #include #define UBA_DEBUG_LOGGER 0 #define UBA_LOG_STALLS 0 namespace uba { class StringBufferBase; struct BinaryReader; struct StringView; using TraverseThreadErrorFunc = Function; struct LogEntry { LogEntryType type; const tchar* string; }; class Logger { public: Logger() {} bool Error(const tchar* format, ...); bool Warning(const tchar* format, ...); Logger& Info(const tchar* format, ...); Logger& Detail(const tchar* format, ...); Logger& Debug(const tchar* format, ...); void Logf(LogEntryType type, const tchar* format, ...); void LogArg(LogEntryType type, const tchar* format, va_list& args); void Log(LogEntryType type, const StringView& str); virtual void BeginScope() = 0; virtual void EndScope() = 0; virtual void Log(LogEntryType type, const tchar* str, u32 strLen) = 0; virtual ~Logger() {} bool ToFalse() { return false; } }; class LoggerWithWriter : public Logger { public: LoggerWithWriter(LogWriter& writer, const tchar* prefix = nullptr); virtual void BeginScope() { m_writer.BeginScope(); } virtual void EndScope() { m_writer.EndScope(); } virtual void Log(LogEntryType type, const tchar* str, u32 strLen) { m_writer.Log(type, str, strLen, m_prefix, m_prefixLen); } using Logger::Log; LogWriter& m_writer; const tchar* m_prefix; u32 m_prefixLen; }; struct MutableLogger : public LoggerWithWriter { MutableLogger(LogWriter& writer, const tchar* prefix) : LoggerWithWriter(writer, prefix) {} virtual void Log(LogEntryType type, const tchar* str, u32 strLen) override { if (!isMuted) LoggerWithWriter::Log(type, str, strLen); } using LoggerWithWriter::Log; Atomic isMuted; }; class FilteredLogWriter : public LogWriter { public: FilteredLogWriter(LogWriter& writer, LogEntryType level = LogEntryType_Detail) : m_writer(writer), m_level(level) {} virtual void BeginScope() override { m_writer.BeginScope(); } virtual void EndScope() override { m_writer.EndScope(); } virtual void Log(LogEntryType type, const tchar* str, u32 strLen, const tchar* prefix = nullptr, u32 prefixLen = 0) override; private: LogWriter& m_writer; LogEntryType m_level; }; struct BytesToText { BytesToText(u64 bytes); operator const tchar* () const { return str; }; tchar str[32]; }; struct CountToText { CountToText(u64 count); operator const tchar* () const { return str; }; tchar str[32]; }; #if UBA_DEBUG_LOGGER Logger* StartDebugLogger(Logger& outerLogger, const tchar* fileName); Logger* StopDebugLogger(Logger* logger); #endif void ParseCallstackInfo(StringBufferBase& out, BinaryReader& reader, const tchar* executable, const StringView* searchPaths); void PrintContentionSummary(class Logger& logger); struct CallstackInfo { Vector data; Vector threadIds; TString desc; }; void TraverseAllCallstacks(const Function& func, const TraverseThreadErrorFunc& errorFunc); void PrintAllCallstacks(Logger& logger); struct LogStallScope { LogStallScope(Logger& logger, LogEntryType type, u64 timeSeconds, const tchar* messageFormat); ~LogStallScope(); void Leave(); Logger& logger; LogEntryType type; u64 timeSeconds; u64 timeStart; const tchar* messageFormat; }; #if UBA_LOG_STALLS #define LOG_STALL_SCOPE(logger, timeSeconds, messageFormat) LogStallScope lss(logger, LogEntryType_Error, timeSeconds, messageFormat); #else #define LOG_STALL_SCOPE(logger, timeSeconds, messageFormat) #endif }