228 lines
8.2 KiB
C++
228 lines
8.2 KiB
C++
#pragma once
|
|
|
|
#include "dtcore/inc/dtstring.h"
|
|
#include "dtcore/inc/dtdatetime.h"
|
|
|
|
#pragma warning(push)
|
|
#include <memory>
|
|
#pragma warning(pop)
|
|
|
|
namespace dt
|
|
{
|
|
class LoggerImpl;
|
|
|
|
enum class LogLevel
|
|
{
|
|
Trace,
|
|
Debug,
|
|
Info,
|
|
Success,
|
|
Warning,
|
|
Error,
|
|
Always,
|
|
Off
|
|
};
|
|
|
|
class LogContext
|
|
{
|
|
public:
|
|
DT_CORE_DLL_ENTRY LogContext() = default;
|
|
DT_CORE_DLL_ENTRY LogContext(const String& key, const String& value, bool visible);
|
|
|
|
DT_CORE_DLL_ENTRY const String& GetKey() const { return m_Key; }
|
|
DT_CORE_DLL_ENTRY const String& GetValue() const { return m_Value; }
|
|
DT_CORE_DLL_ENTRY bool IsVisible() const { return m_Visible; }
|
|
|
|
private:
|
|
String m_Key;
|
|
String m_Value;
|
|
bool m_Visible = false;
|
|
};
|
|
|
|
class LogContexts
|
|
{
|
|
public:
|
|
DT_CORE_DLL_ENTRY LogContexts();
|
|
DT_CORE_DLL_ENTRY LogContexts(const Vector<LogContext>& contexts, const LogContexts* parentContexts = nullptr);
|
|
DT_CORE_DLL_ENTRY LogContexts(const LogContexts& rhs);
|
|
DT_CORE_DLL_ENTRY LogContexts& operator=(const LogContexts& rhs);
|
|
DT_CORE_DLL_ENTRY bool operator==(const LogContexts& rhs) const { return m_Snapshot == rhs.m_Snapshot; }
|
|
|
|
DT_CORE_DLL_ENTRY bool TryGetValue(const String& key, String* value) const;
|
|
typedef Vector<LogContext>::ConstIterator ConstIterator;
|
|
DT_CORE_DLL_ENTRY ConstIterator Begin() const { return m_Snapshot->Begin(); }
|
|
DT_CORE_DLL_ENTRY ConstIterator End() const { return m_Snapshot->End(); }
|
|
DT_CORE_DLL_ENTRY ConstIterator begin() const { return m_Snapshot->Begin(); }
|
|
DT_CORE_DLL_ENTRY ConstIterator end() const { return m_Snapshot->End(); }
|
|
DT_CORE_DLL_ENTRY const LogContext& Back() const { return m_Snapshot->Back(); }
|
|
DT_CORE_DLL_ENTRY const LogContext& operator[](SizeT index) const { return (*m_Snapshot)[index]; }
|
|
DT_CORE_DLL_ENTRY SizeT Size() const { return m_Snapshot->Size(); }
|
|
DT_CORE_DLL_ENTRY bool Empty() const { return m_Snapshot->Empty(); }
|
|
DT_CORE_DLL_ENTRY bool HasAnyVisibleContext() const;
|
|
|
|
private:
|
|
std::shared_ptr<const Vector<LogContext>> m_Snapshot;
|
|
};
|
|
|
|
DT_CORE_DLL_ENTRY String& operator<<(String& buf, const LogContexts& contexts);
|
|
|
|
class LogChannel
|
|
{
|
|
public:
|
|
DT_CORE_DLL_ENTRY LogChannel(const char* name);
|
|
|
|
DT_CORE_DLL_ENTRY const char* GetName() const { return m_Name; }
|
|
|
|
private:
|
|
const char* m_Name;
|
|
};
|
|
|
|
class LogStatement
|
|
{
|
|
public:
|
|
DT_CORE_DLL_ENTRY LogStatement(const DateTime& date,
|
|
const LogChannel& channel,
|
|
LogLevel level,
|
|
const LogContexts& contexts,
|
|
const String& message,
|
|
const char* file,
|
|
int line);
|
|
DT_CORE_DLL_ENTRY LogStatement(const LogStatement& rhs);
|
|
|
|
DT_CORE_DLL_ENTRY DateTime GetDate() const { return m_Date; }
|
|
DT_CORE_DLL_ENTRY const LogChannel& GetChannel() const { return m_Channel; }
|
|
DT_CORE_DLL_ENTRY LogLevel GetLevel() const { return m_Level; }
|
|
DT_CORE_DLL_ENTRY const char* GetFile() const { return m_File; }
|
|
DT_CORE_DLL_ENTRY int GetLine() const { return m_Line; }
|
|
DT_CORE_DLL_ENTRY const LogContexts& GetContexts() const { return m_Contexts; }
|
|
DT_CORE_DLL_ENTRY const String& GetLogMessage() const { return m_Message; }
|
|
|
|
private:
|
|
LogStatement& operator=(const LogStatement&) = delete;
|
|
|
|
const DateTime m_Date;
|
|
const LogChannel& m_Channel;
|
|
const LogLevel m_Level;
|
|
const LogContexts m_Contexts;
|
|
const String m_Message;
|
|
const char* m_File;
|
|
const int m_Line;
|
|
};
|
|
|
|
class LogAppender
|
|
{
|
|
public:
|
|
DT_CORE_DLL_ENTRY virtual ~LogAppender() {}
|
|
DT_CORE_DLL_ENTRY virtual void Write(LogStatement& msg) = 0;
|
|
DT_CORE_DLL_ENTRY virtual void Flush() = 0;
|
|
};
|
|
|
|
class Logger
|
|
{
|
|
public:
|
|
DT_CORE_DLL_ENTRY Logger();
|
|
DT_CORE_DLL_ENTRY ~Logger();
|
|
|
|
DT_CORE_DLL_ENTRY static Logger& Get();
|
|
|
|
DT_CORE_DLL_ENTRY void SetLevel(LogLevel lvl);
|
|
DT_CORE_DLL_ENTRY LogLevel GetLevel() const;
|
|
|
|
DT_CORE_DLL_ENTRY static const char* GetLevelString(LogLevel lvl);
|
|
DT_CORE_DLL_ENTRY static LogLevel GetLevelFromString(const String& level);
|
|
|
|
DT_CORE_DLL_ENTRY void AddAppender(LogAppender& appender);
|
|
DT_CORE_DLL_ENTRY void RemoveAppender(LogAppender& appender);
|
|
|
|
DT_CORE_DLL_ENTRY void Write(const LogChannel& channel, LogLevel lvl, const String& msg, const char* file, int line);
|
|
DT_CORE_DLL_ENTRY void Flush();
|
|
|
|
DT_CORE_DLL_ENTRY LogContexts GetThreadContexts() const;
|
|
|
|
DT_CORE_DLL_ENTRY LogContexts GetGlobalContexts() const;
|
|
|
|
public:
|
|
// internal
|
|
DT_CORE_DLL_ENTRY void InternalPushThreadContexts(const LogContexts& contexts);
|
|
DT_CORE_DLL_ENTRY void InternalPopThreadContexts(const LogContexts& contexts);
|
|
DT_CORE_DLL_ENTRY void InternalPushGlobalContexts(const LogContexts& contexts);
|
|
DT_CORE_DLL_ENTRY void InternalPopGlobalContexts(const LogContexts& contexts);
|
|
|
|
private:
|
|
friend LoggerImpl;
|
|
LoggerImpl* m_Impl;
|
|
};
|
|
|
|
#define DT_LOG_IF(level) \
|
|
if (level >= dt::Logger::Get().GetLevel())
|
|
|
|
#define DT_LOG(level, channel, expr) \
|
|
DT_LOG_IF(level) \
|
|
{ \
|
|
dt::String logText; \
|
|
logText << expr; \
|
|
dt::Logger::Get().Write(channel, level, logText, __FILE__, __LINE__); \
|
|
}
|
|
|
|
#define DT_LOG_TRACE(channel, expr) DT_LOG(dt::LogLevel::Trace, channel, expr)
|
|
#define DT_LOG_DEBUG(channel, expr) DT_LOG(dt::LogLevel::Debug, channel, expr)
|
|
#define DT_LOG_INFO(channel, expr) DT_LOG(dt::LogLevel::Info, channel, expr)
|
|
#define DT_LOG_SUCCESS(channel, expr) DT_LOG(dt::LogLevel::Success, channel, expr)
|
|
#define DT_LOG_WARNING(channel, expr) DT_LOG(dt::LogLevel::Warning, channel, expr)
|
|
#define DT_LOG_ERROR(channel, expr) DT_LOG(dt::LogLevel::Error, channel, expr)
|
|
#define DT_LOG_ALWAYS(channel, expr) DT_LOG(dt::LogLevel::Always, channel, expr)
|
|
|
|
#define DT_LOG_IF_TRACE() DT_LOG_IF(dt::LogLevel::Trace)
|
|
#define DT_LOG_IF_DEBUG() DT_LOG_IF(dt::LogLevel::Debug)
|
|
#define DT_LOG_IF_INFO() DT_LOG_IF(dt::LogLevel::Info)
|
|
#define DT_LOG_IF_SUCCESS() DT_LOG_IF(dt::LogLevel::Success)
|
|
#define DT_LOG_IF_WARNING() DT_LOG_IF(dt::LogLevel::Warning)
|
|
#define DT_LOG_IF_ERROR() DT_LOG_IF(dt::LogLevel::Error)
|
|
#define DT_LOG_IF_ALWAYS() DT_LOG_IF(dt::LogLevel::Always)
|
|
|
|
class LoggerAutoThreadContexts
|
|
{
|
|
public:
|
|
DT_CORE_DLL_ENTRY LoggerAutoThreadContexts(const LogContexts& contexts);
|
|
DT_CORE_DLL_ENTRY ~LoggerAutoThreadContexts();
|
|
|
|
private:
|
|
LogContexts m_Contexts;
|
|
};
|
|
|
|
#define DT_LOG_AUTO_THREAD_CONTEXTS(contexts) \
|
|
dt::LoggerAutoThreadContexts DT_UNIQUE_IDENTIFIER(logCtx)(contexts);
|
|
|
|
class LoggerAutoGlobalContexts
|
|
{
|
|
public:
|
|
DT_CORE_DLL_ENTRY LoggerAutoGlobalContexts(const LogContexts& contexts);
|
|
DT_CORE_DLL_ENTRY ~LoggerAutoGlobalContexts();
|
|
|
|
private:
|
|
LogContexts m_Contexts;
|
|
};
|
|
|
|
#define DT_LOG_AUTO_GLOBAL_CONTEXTS(contexts) \
|
|
dt::LoggerAutoGlobalContexts DT_UNIQUE_IDENTIFIER(logCtx)(contexts);
|
|
|
|
static LogChannel LogChannelGeneral("General");
|
|
static LogChannel LogChannelDatabase("Database");
|
|
static LogChannel LogChannelRunner("Runner");
|
|
static LogChannel LogChannelServiceAgency("Agency");
|
|
static LogChannel LogChannelServiceLog("Log");
|
|
static LogChannel LogChannelServiceTest("Test");
|
|
static LogChannel LogChannelServiceArtefact("Artefact");
|
|
static LogChannel LogChannelServiceConnection("Connection");
|
|
static LogChannel LogChannelServiceDetection("Detection");
|
|
static LogChannel LogChannelServiceTestManagementTool("TestManagementTool");
|
|
static LogChannel LogChannelService("Service");
|
|
static LogChannel LogChannelMessage("Message");
|
|
static LogChannel LogChannelProfiling("Profiling");
|
|
static LogChannel LogChannelStateMachine("State");
|
|
static LogChannel LogChannelToken("Token");
|
|
static LogChannel LogChannelScript("Script");
|
|
static LogChannel LogChannelBloomberg("Bloomberg");
|
|
|
|
}
|
|
|