1
0
Fork 0

Update logging code to reduce unnecessary string copying:

* Write into a single fmt::memory_buffer
* Use string_view instead of AString for listener callbacks
* Also collapsed vFLOG and vLOG functions into one per formatting type
This commit is contained in:
Peter Bell 2020-05-15 03:35:43 +01:00 committed by Tiger Wang
parent 13144a08e4
commit 3189a3cbee
11 changed files with 199 additions and 198 deletions

View File

@ -135,6 +135,7 @@ typedef unsigned char Byte;
// Common headers (without macros):
#include "fmt.h"
#include "LoggerSimple.h"
#include "StringUtils.h"
#include "OSSupport/CriticalSection.h"
#include "OSSupport/Event.h"

View File

@ -144,6 +144,7 @@ typedef unsigned char Byte;
// Common headers (without macros):
#include "fmt.h"
#include "LoggerSimple.h"
#include "StringUtils.h"
#include "OSSupport/CriticalSection.h"
#include "OSSupport/Event.h"

View File

@ -33,6 +33,7 @@
#include "../HTTP/UrlParser.h"
#include "../Item.h"
#include "../LineBlockTracer.h"
#include "../Logger.h"
#include "../Server.h"
#include "../Root.h"
#include "../StringCompression.h"
@ -401,7 +402,7 @@ static int tolua_LOG(lua_State * tolua_S)
}
// If the param is a cCompositeChat, read the log level from it:
cLogger::eLogLevel LogLevel = cLogger::llRegular;
eLogLevel LogLevel = eLogLevel::Regular;
tolua_Error err;
if (tolua_isusertype(tolua_S, 1, "cCompositeChat", false, &err))
{
@ -427,7 +428,7 @@ static int tolua_LOGINFO(lua_State * tolua_S)
return 0;
}
cLogger::GetInstance().LogSimple(GetLogMessage(tolua_S), cLogger::llInfo);
cLogger::GetInstance().LogSimple(GetLogMessage(tolua_S), eLogLevel::Info);
return 0;
}
@ -445,7 +446,7 @@ static int tolua_LOGWARN(lua_State * tolua_S)
return 0;
}
cLogger::GetInstance().LogSimple(GetLogMessage(tolua_S), cLogger::llWarning);
cLogger::GetInstance().LogSimple(GetLogMessage(tolua_S), eLogLevel::Warning);
return 0;
}
@ -463,7 +464,7 @@ static int tolua_LOGERROR(lua_State * tolua_S)
return 0;
}
cLogger::GetInstance().LogSimple(GetLogMessage(tolua_S), cLogger::llError);
cLogger::GetInstance().LogSimple(GetLogMessage(tolua_S), eLogLevel::Error);
return 0;
}

View File

@ -269,24 +269,24 @@ AString cCompositeChat::ExtractText(void) const
cLogger::eLogLevel cCompositeChat::MessageTypeToLogLevel(eMessageType a_MessageType)
eLogLevel cCompositeChat::MessageTypeToLogLevel(eMessageType a_MessageType)
{
switch (a_MessageType)
{
case mtCustom: return cLogger::llRegular;
case mtFailure: return cLogger::llWarning;
case mtInformation: return cLogger::llInfo;
case mtSuccess: return cLogger::llRegular;
case mtWarning: return cLogger::llWarning;
case mtFatal: return cLogger::llError;
case mtDeath: return cLogger::llRegular;
case mtPrivateMessage: return cLogger::llRegular;
case mtJoin: return cLogger::llRegular;
case mtLeave: return cLogger::llRegular;
case mtCustom: return eLogLevel::Regular;
case mtFailure: return eLogLevel::Warning;
case mtInformation: return eLogLevel::Info;
case mtSuccess: return eLogLevel::Regular;
case mtWarning: return eLogLevel::Warning;
case mtFatal: return eLogLevel::Error;
case mtDeath: return eLogLevel::Regular;
case mtPrivateMessage: return eLogLevel::Regular;
case mtJoin: return eLogLevel::Regular;
case mtLeave: return eLogLevel::Regular;
case mtMaxPlusOne: break;
}
ASSERT(!"Unhandled MessageType");
return cLogger::llError;
return eLogLevel::Error;
}

View File

@ -7,7 +7,6 @@
#include "Defines.h"
#include "json/json.h"
#include "Logger.h"
@ -231,7 +230,7 @@ public:
/** Converts the MessageType to a LogLevel value.
Used by the logging bindings when logging a cCompositeChat object. */
static cLogger::eLogLevel MessageTypeToLogLevel(eMessageType a_MessageType);
static eLogLevel MessageTypeToLogLevel(eMessageType a_MessageType);
/** Adds the chat part's style (represented by the part's stylestring) into the Json object. */
void AddChatPartStyle(Json::Value & a_Value, const AString & a_PartStyle) const;

View File

@ -200,46 +200,43 @@ template class SizeChecker<UInt8, 1>;
// Common headers (part 1, without macros):
#include "fmt.h"
#include "StringUtils.h"
#include "LoggerSimple.h"
#include "OSSupport/CriticalSection.h"
#include "OSSupport/Event.h"
#include "OSSupport/File.h"
#include "OSSupport/StackTrace.h"
#ifndef TEST_GLOBALS
#ifdef TEST_GLOBALS
#include "LoggerSimple.h"
#else
#include "fmt/printf.h"
// Logging functions
template <typename ... Args>
void LOG(const char * a_Format, const Args & ... a_Args)
// Basic logging function implementations
namespace Logger
{
fmt::printf(a_Format, a_Args...);
inline void LogFormat(
std::string_view a_Format, eLogLevel, fmt::format_args a_ArgList
)
{
fmt::vprint(a_Format, a_ArgList);
putchar('\n');
fflush(stdout);
}
#define LOGERROR LOG
#define LOGWARNING LOG
#define LOGD LOG
#define LOGINFO LOG
#define LOGWARN LOG
template <typename ... Args>
void FLOG(const char * a_Format, const Args & ... a_Args)
inline void LogPrintf(
std::string_view a_Format, eLogLevel, fmt::printf_args a_ArgList
)
{
fmt::print(a_Format, a_Args...);
fmt::vprintf(a_Format, a_ArgList);
putchar('\n');
fflush(stdout);
}
#define FLOGERROR FLOG
#define FLOGWARNING FLOG
#define FLOGD FLOG
#define FLOGINFO FLOG
#define FLOGWARN FLOG
inline void LogSimple(std::string_view a_Message, eLogLevel)
{
fmt::print("{}\n", a_Message);
fflush(stdout);
}
} // namespace Logger
#endif

View File

@ -11,6 +11,38 @@
static void WriteLogOpener(fmt::memory_buffer & Buffer)
{
time_t rawtime;
time(&rawtime);
struct tm * timeinfo;
#ifdef _MSC_VER
struct tm timeinforeal;
timeinfo = &timeinforeal;
localtime_s(timeinfo, &rawtime);
#else
timeinfo = localtime(&rawtime);
#endif
#ifdef _DEBUG
const auto ThreadID = std::hash<std::thread::id>()(std::this_thread::get_id());
fmt::format_to(
Buffer, "[{0:04x}|{1:02d}:{2:02d}:{3:02d}] ",
ThreadID, timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec
);
#else
fmt::format_to(
Buffer, "[{0:02d}:{1:02d}:{2:02d}] ",
timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec
);
#endif
}
cLogger & cLogger::GetInstance(void)
{
static cLogger Instance;
@ -30,32 +62,24 @@ void cLogger::InitiateMultithreading()
void cLogger::LogSimple(const AString & a_Message, eLogLevel a_LogLevel)
void cLogger::LogSimple(std::string_view a_Message, eLogLevel a_LogLevel)
{
time_t rawtime;
time(&rawtime);
struct tm * timeinfo;
#ifdef _MSC_VER
struct tm timeinforeal;
timeinfo = &timeinforeal;
localtime_s(timeinfo, &rawtime);
#else
timeinfo = localtime(&rawtime);
#endif
AString Line;
#ifdef _DEBUG
Printf(Line, "[%04llx|%02d:%02d:%02d] %s\n", static_cast<UInt64>(std::hash<std::thread::id>()(std::this_thread::get_id())), timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec, a_Message);
#else
Printf(Line, "[%02d:%02d:%02d] %s\n", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec, a_Message);
#endif
fmt::memory_buffer Buffer;
WriteLogOpener(Buffer);
fmt::format_to(Buffer, "{0}\n", a_Message);
LogLine(std::string_view(Buffer.data(), Buffer.size()), a_LogLevel);
}
void cLogger::LogLine(std::string_view a_Line, eLogLevel a_LogLevel)
{
cCSLock Lock(m_CriticalSection);
for (size_t i = 0; i < m_LogListeners.size(); i++)
{
m_LogListeners[i]->Log(Line, a_LogLevel);
m_LogListeners[i]->Log(a_Line, a_LogLevel);
}
}
@ -63,18 +87,32 @@ void cLogger::LogSimple(const AString & a_Message, eLogLevel a_LogLevel)
void cLogger::vLogPrintf(const char * a_Format, eLogLevel a_LogLevel, fmt::printf_args a_ArgList)
void cLogger::LogPrintf(
std::string_view a_Format, eLogLevel a_LogLevel, fmt::printf_args a_ArgList
)
{
LogSimple(vPrintf(a_Format, a_ArgList), a_LogLevel);
fmt::memory_buffer Buffer;
WriteLogOpener(Buffer);
fmt::printf(Buffer, fmt::to_string_view(a_Format), a_ArgList);
fmt::format_to(Buffer, "\n");
LogLine(std::string_view(Buffer.data(), Buffer.size()), a_LogLevel);
}
void cLogger::vLogFormat(const char * a_Format, eLogLevel a_LogLevel, fmt::format_args a_ArgList)
void cLogger::LogFormat(
std::string_view a_Format, eLogLevel a_LogLevel, fmt::format_args a_ArgList
)
{
LogSimple(fmt::vformat(a_Format, a_ArgList), a_LogLevel);
fmt::memory_buffer Buffer;
WriteLogOpener(Buffer);
fmt::vformat_to(Buffer, a_Format, a_ArgList);
fmt::format_to(Buffer, "\n");
LogLine(std::string_view(Buffer.data(), Buffer.size()), a_LogLevel);
}
@ -117,72 +155,31 @@ void cLogger::DetachListener(cListener * a_Listener)
////////////////////////////////////////////////////////////////////////////////
// Global functions
void vFLOG(const char * a_Format, fmt::format_args a_ArgList)
void Logger::LogFormat(
std::string_view a_Format, eLogLevel a_LogLevel, fmt::format_args a_ArgList
)
{
cLogger::GetInstance().vLogFormat(a_Format, cLogger::llRegular, a_ArgList);
cLogger::GetInstance().LogFormat(a_Format, a_LogLevel, a_ArgList);
}
void vFLOGINFO(const char * a_Format, fmt::format_args a_ArgList)
void Logger::LogPrintf(
std::string_view a_Format, eLogLevel a_LogLevel, fmt::printf_args a_ArgList
)
{
cLogger::GetInstance().vLogFormat( a_Format, cLogger::llInfo, a_ArgList);
cLogger::GetInstance().LogPrintf(a_Format, a_LogLevel, a_ArgList);
}
void vFLOGWARNING(const char * a_Format, fmt::format_args a_ArgList)
void Logger::LogSimple(std::string_view a_Message, eLogLevel a_LogLevel)
{
cLogger::GetInstance().vLogFormat( a_Format, cLogger::llWarning, a_ArgList);
}
void vFLOGERROR(const char * a_Format, fmt::format_args a_ArgList)
{
cLogger::GetInstance().vLogFormat(a_Format, cLogger::llError, a_ArgList);
}
void vLOG(const char * a_Format, fmt::printf_args a_ArgList)
{
cLogger::GetInstance().vLogPrintf(a_Format, cLogger::llRegular, a_ArgList);
}
void vLOGINFO(const char * a_Format, fmt::printf_args a_ArgList)
{
cLogger::GetInstance().vLogPrintf(a_Format, cLogger::llInfo, a_ArgList);
}
void vLOGWARNING(const char * a_Format, fmt::printf_args a_ArgList)
{
cLogger::GetInstance().vLogPrintf(a_Format, cLogger::llWarning, a_ArgList);
}
void vLOGERROR(const char * a_Format, fmt::printf_args a_ArgList)
{
cLogger::GetInstance().vLogPrintf( a_Format, cLogger::llError, a_ArgList);
cLogger::GetInstance().LogSimple(a_Message, a_LogLevel);
}

View File

@ -6,19 +6,10 @@ class cLogger
{
public:
enum eLogLevel
{
llRegular,
llInfo,
llWarning,
llError,
};
class cListener
{
public:
virtual void Log(AString a_Message, eLogLevel a_LogLevel) = 0;
virtual void Log(std::string_view a_Message, eLogLevel a_LogLevel) = 0;
virtual ~cListener(){}
};
@ -59,23 +50,17 @@ public:
};
/** Log a message formatted with a printf style formatting string. */
void vLogPrintf(const char * a_Format, eLogLevel a_LogLevel, fmt::printf_args a_ArgList);
template <typename... Args>
void LogPrintf(const char * a_Format, eLogLevel a_LogLevel, const Args & ... args)
{
vLogPrintf(a_Format, a_LogLevel, fmt::make_printf_args(args...));
}
void LogPrintf(
std::string_view a_Format, eLogLevel a_LogLevel, fmt::printf_args a_ArgList
);
/** Log a message formatted with a python style formatting string. */
void vLogFormat(const char * a_Format, eLogLevel a_LogLevel, fmt::format_args a_ArgList);
template <typename... Args>
void LogFormat(const char * a_Format, eLogLevel a_LogLevel, const Args & ... args)
{
vLogFormat(a_Format, a_LogLevel, fmt::make_format_args(args...));
}
void LogFormat(
std::string_view a_Format, eLogLevel a_LogLevel, fmt::format_args a_ArgList
);
/** Logs the simple text message at the specified log level. */
void LogSimple(const AString & a_Message, eLogLevel a_LogLevel = llRegular);
void LogSimple(std::string_view a_Message, eLogLevel a_LogLevel = eLogLevel::Regular);
cAttachment AttachListener(std::unique_ptr<cListener> a_Listener);
@ -88,6 +73,7 @@ private:
std::vector<std::unique_ptr<cListener>> m_LogListeners;
void DetachListener(cListener * a_Listener);
void LogLine(std::string_view a_Line, eLogLevel a_LogLevel);
};

View File

@ -15,13 +15,13 @@
{
protected:
virtual void SetLogColour(cLogger::eLogLevel a_LogLevel) = 0;
virtual void SetLogColour(eLogLevel a_LogLevel) = 0;
virtual void SetDefaultLogColour() = 0;
virtual void Log(AString a_Message, cLogger::eLogLevel a_LogLevel) override
virtual void Log(std::string_view a_Message, eLogLevel a_LogLevel) override
{
SetLogColour(a_LogLevel);
fputs(a_Message.c_str(), stdout);
fwrite(a_Message.data(), 1, a_Message.size(), stdout);
SetDefaultLogColour();
}
};
@ -46,40 +46,40 @@
}
#ifdef _DEBUG
virtual void Log(AString a_Message, cLogger::eLogLevel a_LogLevel) override
virtual void Log(std::string_view a_Message, eLogLevel a_LogLevel) override
{
Super::Log(a_Message, a_LogLevel);
// In a Windows Debug build, output the log to debug console as well:
OutputDebugStringA(a_Message.c_str());
OutputDebugStringA(AString(a_Message).c_str());
}
#endif
virtual void SetLogColour(cLogger::eLogLevel a_LogLevel) override
virtual void SetLogColour(eLogLevel a_LogLevel) override
{
// by default, gray on black
WORD Attrib = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED;
switch (a_LogLevel)
{
case cLogger::llRegular:
case eLogLevel::Regular:
{
// Gray on black
Attrib = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED;
break;
}
case cLogger::llInfo:
case eLogLevel::Info:
{
// Yellow on black
Attrib = FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY;
break;
}
case cLogger::llWarning:
case eLogLevel::Warning:
{
// Red on black
Attrib = FOREGROUND_RED | FOREGROUND_INTENSITY;
break;
}
case cLogger::llError:
case eLogLevel::Error:
{
// Black on red
Attrib = BACKGROUND_RED | BACKGROUND_INTENSITY;
@ -111,29 +111,29 @@
: public cColouredConsoleListener
{
public:
virtual void SetLogColour(cLogger::eLogLevel a_LogLevel) override
virtual void SetLogColour(eLogLevel a_LogLevel) override
{
switch (a_LogLevel)
{
case cLogger::llRegular:
case eLogLevel::Regular:
{
// Whatever the console default is
printf("\x1b[0m");
break;
}
case cLogger::llInfo:
case eLogLevel::Info:
{
// Yellow on black
printf("\x1b[33;1m");
break;
}
case cLogger::llWarning:
case eLogLevel::Warning:
{
// Red on black
printf("\x1b[31;1m");
break;
}
case cLogger::llError:
case eLogLevel::Error:
{
// Yellow on red
printf("\x1b[1;33;41;1m");
@ -161,33 +161,32 @@ class cVanillaCPPConsoleListener
: public cLogger::cListener
{
public:
virtual void Log(AString a_Message, cLogger::eLogLevel a_LogLevel) override
virtual void Log(std::string_view a_Message, eLogLevel a_LogLevel) override
{
AString LogLevelString;
switch (a_LogLevel)
{
case cLogger::llRegular:
case eLogLevel::Regular:
{
LogLevelString = "Log";
fputs("Log: ", stdout);
break;
}
case cLogger::llInfo:
case eLogLevel::Info:
{
LogLevelString = "Info";
fputs("Info: ", stdout);
break;
}
case cLogger::llWarning:
case eLogLevel::Warning:
{
LogLevelString = "Warning";
fputs("Warning: ", stdout);
break;
}
case cLogger::llError:
case eLogLevel::Error:
{
LogLevelString = "Error";
fputs("Error: ", stdout);
break;
}
}
printf("%s: %s", LogLevelString.c_str(), a_Message.c_str());
fwrite(a_Message.data(), 1, a_Message.size(), stdout);
}
};
@ -199,7 +198,7 @@ public:
class cNullConsoleListener
: public cLogger::cListener
{
virtual void Log(AString a_Message, cLogger::eLogLevel a_LogLevel) override
virtual void Log(std::string_view a_Message, eLogLevel a_LogLevel) override
{
}
};
@ -275,36 +274,38 @@ public:
return success;
}
virtual void Log(AString a_Message, cLogger::eLogLevel a_LogLevel) override
virtual void Log(std::string_view a_Message, eLogLevel a_LogLevel) override
{
const char * LogLevelPrefix = "Unkn ";
std::string_view LogLevelPrefix = "Unkn ";
bool ShouldFlush = false;
switch (a_LogLevel)
{
case cLogger::llRegular:
case eLogLevel::Regular:
{
LogLevelPrefix = " ";
break;
}
case cLogger::llInfo:
case eLogLevel::Info:
{
LogLevelPrefix = "Info ";
break;
}
case cLogger::llWarning:
case eLogLevel::Warning:
{
LogLevelPrefix = "Warn ";
ShouldFlush = true;
break;
}
case cLogger::llError:
case eLogLevel::Error:
{
LogLevelPrefix = "Err ";
ShouldFlush = true;
break;
}
}
m_File.Printf("%s%s", LogLevelPrefix, a_Message.c_str());
m_File.Write(LogLevelPrefix);
m_File.Write(a_Message);
if (ShouldFlush)
{
m_File.Flush();

View File

@ -2,64 +2,77 @@
// Logging free functions defined in Logger.cpp
#pragma once
enum class eLogLevel
{
Regular,
Info,
Warning,
Error,
};
namespace Logger
{
extern void LogFormat(
std::string_view a_Format, eLogLevel a_LogLevel, fmt::format_args a_ArgList
);
extern void LogPrintf(
std::string_view a_Format, eLogLevel a_LogLevel, fmt::printf_args a_ArgList
);
extern void LogSimple(std::string_view a_Message, eLogLevel a_LogLevel);
} // namespace Logger
// python style format specified logging
extern void vFLOG(const char * a_Format, fmt::format_args a_ArgList);
template <typename... Args>
void FLOG(const char * a_Format, const Args & ... args)
void FLOG(std::string_view a_Format, const Args & ... args)
{
vFLOG(a_Format, fmt::make_format_args(args...));
Logger::LogFormat(a_Format, eLogLevel::Regular, fmt::make_format_args(args...));
}
extern void vFLOGINFO(const char * a_Format, fmt::format_args a_ArgList);
template <typename... Args>
void FLOGINFO(const char * a_Format, const Args & ... args)
void FLOGINFO(std::string_view a_Format, const Args & ... args)
{
vFLOGINFO(a_Format, fmt::make_format_args(args...));
Logger::LogFormat(a_Format, eLogLevel::Info, fmt::make_format_args(args...));
}
extern void vFLOGWARNING(const char * a_Format, fmt::format_args a_ArgList);
template <typename... Args>
void FLOGWARNING(const char * a_Format, const Args & ... args)
void FLOGWARNING(std::string_view a_Format, const Args & ... args)
{
vFLOGWARNING(a_Format, fmt::make_format_args(args...));
Logger::LogFormat(a_Format, eLogLevel::Warning, fmt::make_format_args(args...));
}
extern void vFLOGERROR(const char * a_Format, fmt::format_args a_ArgList);
template <typename... Args>
void FLOGERROR(const char * a_Format, const Args & ... args)
void FLOGERROR(std::string_view a_Format, const Args & ... args)
{
vFLOGERROR(a_Format, fmt::make_format_args(args...));
Logger::LogFormat(a_Format, eLogLevel::Error, fmt::make_format_args(args...));
}
// printf style format specified logging (DEPRECATED)
extern void vLOG(const char * a_Format, fmt::printf_args a_ArgList);
template <typename... Args>
void LOG(const char * a_Format, const Args & ... args)
void LOG(std::string_view a_Format, const Args & ... args)
{
vLOG(a_Format, fmt::make_printf_args(args...));
Logger::LogPrintf(a_Format, eLogLevel::Regular, fmt::make_printf_args(args...));
}
extern void vLOGINFO(const char * a_Format, fmt::printf_args a_ArgList);
template <typename... Args>
void LOGINFO(const char * a_Format, const Args & ... args)
void LOGINFO(std::string_view a_Format, const Args & ... args)
{
vLOGINFO(a_Format, fmt::make_printf_args(args...));
Logger::LogPrintf(a_Format, eLogLevel::Info, fmt::make_printf_args(args...));
}
extern void vLOGWARNING(const char * a_Format, fmt::printf_args a_ArgList);
template <typename... Args>
void LOGWARNING(const char * a_Format, const Args & ... args)
void LOGWARNING(std::string_view a_Format, const Args & ... args)
{
vLOGWARNING(a_Format, fmt::make_printf_args(args...));
Logger::LogPrintf(a_Format, eLogLevel::Warning, fmt::make_printf_args(args...));
}
extern void vLOGERROR(const char * a_Format, fmt::printf_args a_ArgList);
template <typename... Args>
void LOGERROR(const char * a_Format, const Args & ... args)
void LOGERROR(std::string_view a_Format, const Args & ... args)
{
vLOGERROR(a_Format, fmt::make_printf_args(args...));
Logger::LogPrintf(a_Format, eLogLevel::Error, fmt::make_printf_args(args...));
}

View File

@ -80,6 +80,11 @@ public:
/** Writes up to a_NumBytes bytes from a_Buffer, returns the number of bytes actually written, or -1 on failure; asserts if not open */
int Write(const void * a_Buffer, size_t a_NumBytes);
int Write(std::string_view a_String)
{
return Write(a_String.data(), a_String.size());
}
/** Seeks to iPosition bytes from file start, returns old position or -1 for failure; asserts if not open */
long Seek (int iPosition);