Add separate log levels for each output

`stdout_output_level` for printing to stdout, `console_output_level` for
printing to local console and remote console and `loglevel` for the log
file.

Keep the old log level filters 0 for info and more severe, 1 for debug
and more severe and 2 for trace and more severe, introducing -1 for
warn, and -2 for error. -3 will show no log messages at all.
This commit is contained in:
heinrich5991 2022-06-13 21:43:05 +02:00
parent e6725a9668
commit 85566fbe92
15 changed files with 216 additions and 50 deletions

View file

@ -20,16 +20,10 @@
#include <android/log.h>
#endif
std::atomic<LEVEL> loglevel = LEVEL_INFO;
std::atomic<ILogger *> global_logger = nullptr;
thread_local ILogger *scope_logger = nullptr;
thread_local bool in_logger = false;
void log_set_loglevel(LEVEL level)
{
loglevel.store(level, std::memory_order_release);
}
void log_set_global_logger(ILogger *logger)
{
ILogger *null = nullptr;
@ -80,9 +74,6 @@ void log_log_impl(LEVEL level, bool have_color, LOG_COLOR color, const char *sys
void log_log_impl(LEVEL level, bool have_color, LOG_COLOR color, const char *sys, const char *fmt, va_list args)
{
if(level > loglevel.load(std::memory_order_acquire))
return;
// Make sure we're not logging recursively.
if(in_logger)
{
@ -146,12 +137,21 @@ void log_log_color(LEVEL level, LOG_COLOR color, const char *sys, const char *fm
va_end(args);
}
bool CLogFilter::Filters(const CLogMessage *pMessage)
{
return pMessage->m_Level > m_MaxLevel.load(std::memory_order_relaxed);
}
#if defined(CONF_PLATFORM_ANDROID)
class CLoggerAndroid : public ILogger
{
public:
void Log(const CLogMessage *pMessage) override
{
if(m_Filter.Filters(pMessage))
{
return;
}
int AndroidLevel;
switch(pMessage->m_Level)
{
@ -184,9 +184,14 @@ public:
CLoggerCollection(std::vector<std::shared_ptr<ILogger>> &&vpLoggers) :
m_vpLoggers(std::move(vpLoggers))
{
m_Filter.m_MaxLevel.store(LEVEL_TRACE, std::memory_order_relaxed);
}
void Log(const CLogMessage *pMessage) override
{
if(m_Filter.Filters(pMessage))
{
return;
}
for(auto &pLogger : m_vpLoggers)
{
pLogger->Log(pMessage);
@ -221,6 +226,10 @@ public:
}
void Log(const CLogMessage *pMessage) override
{
if(m_Filter.Filters(pMessage))
{
return;
}
aio_lock(m_pAio);
if(m_AnsiTruecolor)
{
@ -329,6 +338,10 @@ public:
}
void Log(const CLogMessage *pMessage) override
{
if(m_Filter.Filters(pMessage))
{
return;
}
const std::wstring WideMessage = windows_utf8_to_wide(pMessage->m_aLine) + L"\r\n";
int Color = m_BackgroundColor;
@ -372,6 +385,10 @@ public:
}
void Log(const CLogMessage *pMessage) override
{
if(m_Filter.Filters(pMessage))
{
return;
}
m_OutputLock.lock();
DWORD Written; // we don't care about the value, but Windows 7 crashes if we pass NULL
WriteFile(m_pFile, pMessage->m_aLine, pMessage->m_LineLength, &Written, NULL);
@ -408,6 +425,10 @@ class CLoggerWindowsDebugger : public ILogger
public:
void Log(const CLogMessage *pMessage) override
{
if(m_Filter.Filters(pMessage))
{
return;
}
const std::wstring WideMessage = windows_utf8_to_wide(pMessage->m_aLine);
OutputDebugStringW(WideMessage.c_str());
}
@ -452,6 +473,12 @@ void CFutureLogger::Log(const CLogMessage *pMessage)
return;
}
m_PendingLock.lock();
pLogger = std::atomic_load_explicit(&m_pLogger, std::memory_order_relaxed);
if(pLogger)
{
pLogger->Log(pMessage);
return;
}
m_vPending.push_back(*pMessage);
m_PendingLock.unlock();
}
@ -464,3 +491,12 @@ void CFutureLogger::GlobalFinish()
pLogger->GlobalFinish();
}
}
void CFutureLogger::OnFilterChange()
{
auto pLogger = std::atomic_load_explicit(&m_pLogger, std::memory_order_acquire);
if(pLogger)
{
pLogger->SetFilter(m_Filter);
}
}

View file

@ -50,11 +50,36 @@ public:
}
};
class ILogger
class CLogFilter
{
public:
/**
* The highest `LEVEL` that is still logged, -1 corresponds to no
* printing at all.
*/
std::atomic_int m_MaxLevel{LEVEL_INFO};
bool Filters(const CLogMessage *pMessage);
};
class ILogger
{
protected:
CLogFilter m_Filter;
public:
virtual ~ILogger() {}
/**
* Set a new filter. It's up to the logger implementation to actually
* use the filter.
*/
void SetFilter(const CLogFilter &Filter)
{
m_Filter.m_MaxLevel.store(Filter.m_MaxLevel.load(std::memory_order_relaxed), std::memory_order_relaxed);
OnFilterChange();
}
/**
* Send the specified message to the logging backend.
*
@ -77,18 +102,12 @@ public:
* @see log_global_logger_finish
*/
virtual void GlobalFinish() {}
/**
* Notifies thte logger of a changed `m_Filter`.
*/
virtual void OnFilterChange() {}
};
/**
* @ingroup Log
*
* Sets the global loglevel to the given value. Log messages with a less severe
* loglevel will not be forwarded to loggers.
*
* @param level The loglevel.
*/
void log_set_loglevel(LEVEL level);
/**
* @ingroup Log
*
@ -198,6 +217,9 @@ std::unique_ptr<ILogger> log_logger_windows_debugger();
*
* Useful when you want to set a global logger without all logging targets
* being configured.
*
* This logger forwards `SetFilter` calls, `SetFilter` calls before a logger is
* set have no effect.
*/
class CFutureLogger : public ILogger
{
@ -214,6 +236,7 @@ public:
void Set(std::shared_ptr<ILogger> pLogger);
void Log(const CLogMessage *pMessage) override;
void GlobalFinish() override;
void OnFilterChange() override;
};
/**

View file

@ -4356,12 +4356,6 @@ void CClient::ConchainTimeoutSeed(IConsole::IResult *pResult, void *pUserData, I
pSelf->m_GenerateTimeoutSeed = false;
}
void CClient::ConchainLoglevel(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData)
{
pfnCallback(pResult, pCallbackUserData);
log_set_loglevel((LEVEL)g_Config.m_Loglevel);
}
void CClient::ConchainPassword(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData)
{
CClient *pSelf = (CClient *)pUserData;
@ -4390,6 +4384,26 @@ void CClient::ConchainReplays(IConsole::IResult *pResult, void *pUserData, ICons
}
}
void CClient::ConchainLoglevel(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData)
{
CClient *pSelf = (CClient *)pUserData;
pfnCallback(pResult, pCallbackUserData);
if(pResult->NumArguments())
{
pSelf->m_pFileLogger->SetFilter(CLogFilter{IConsole::ToLogLevelFilter(g_Config.m_Loglevel)});
}
}
void CClient::ConchainStdoutOutputLevel(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData)
{
CClient *pSelf = (CClient *)pUserData;
pfnCallback(pResult, pCallbackUserData);
if(pResult->NumArguments() && pSelf->m_pStdoutLogger)
{
pSelf->m_pStdoutLogger->SetFilter(CLogFilter{IConsole::ToLogLevelFilter(g_Config.m_StdoutOutputLevel)});
}
}
void CClient::RegisterCommands()
{
m_pConsole = Kernel()->RequestInterface<IConsole>();
@ -4446,7 +4460,6 @@ void CClient::RegisterCommands()
m_pConsole->Chain("cl_timeout_seed", ConchainTimeoutSeed, this);
m_pConsole->Chain("cl_replays", ConchainReplays, this);
m_pConsole->Chain("loglevel", ConchainLoglevel, this);
m_pConsole->Chain("password", ConchainPassword, this);
// used for server browser update
@ -4462,6 +4475,9 @@ void CClient::RegisterCommands()
m_pConsole->Chain("gfx_borderless", ConchainWindowBordered, this);
m_pConsole->Chain("gfx_vsync", ConchainWindowVSync, this);
m_pConsole->Chain("loglevel", ConchainLoglevel, this);
m_pConsole->Chain("stdout_output_level", ConchainStdoutOutputLevel, this);
// DDRace
#define CONSOLE_COMMAND(name, params, flags, callback, userdata, help) m_pConsole->Register(name, params, flags, 0, 0, help);
@ -4577,14 +4593,19 @@ int main(int argc, const char **argv)
#endif
std::vector<std::shared_ptr<ILogger>> vpLoggers;
std::shared_ptr<ILogger> pStdoutLogger = nullptr;
#if defined(CONF_PLATFORM_ANDROID)
vpLoggers.push_back(std::shared_ptr<ILogger>(log_logger_android()));
pStdoutLogger = std::shared_ptr<ILogger>(log_logger_android());
#else
if(!Silent)
{
vpLoggers.push_back(std::shared_ptr<ILogger>(log_logger_stdout()));
pStdoutLogger = std::shared_ptr<ILogger>(log_logger_stdout());
}
#endif
if(pStdoutLogger)
{
vpLoggers.push_back(pStdoutLogger);
}
std::shared_ptr<CFutureLogger> pFutureFileLogger = std::make_shared<CFutureLogger>();
vpLoggers.push_back(pFutureFileLogger);
std::shared_ptr<CFutureLogger> pFutureConsoleLogger = std::make_shared<CFutureLogger>();
@ -4625,6 +4646,8 @@ int main(int argc, const char **argv)
CleanerFunctions.push([]() { SDL_Quit(); });
CClient *pClient = CreateClient();
pClient->SetLoggers(pFutureFileLogger, std::move(pStdoutLogger));
IKernel *pKernel = IKernel::Create();
pKernel->RegisterInterface(pClient, false);
pClient->RegisterInterfaces();
@ -4790,7 +4813,6 @@ int main(int argc, const char **argv)
pSteam->ClearConnectAddress();
}
log_set_loglevel((LEVEL)g_Config.m_Loglevel);
const int Mode = g_Config.m_Logappend ? IOFLAG_APPEND : IOFLAG_WRITE;
if(g_Config.m_Logfile[0])
{
@ -5087,3 +5109,9 @@ void CClient::GetGPUInfoString(char (&aGPUInfo)[256])
str_copy(aGPUInfo, "Graphics backend was not yet initialized.");
}
}
void CClient::SetLoggers(std::shared_ptr<ILogger> &&pFileLogger, std::shared_ptr<ILogger> &&pStdoutLogger)
{
m_pFileLogger = pFileLogger;
m_pStdoutLogger = pStdoutLogger;
}

View file

@ -298,6 +298,9 @@ class CClient : public IClient, public CDemoPlayer::IListener
int MaxLatencyTicks() const;
int PredictionMargin() const;
std::shared_ptr<ILogger> m_pFileLogger = nullptr;
std::shared_ptr<ILogger> m_pStdoutLogger = nullptr;
public:
IEngine *Engine() { return m_pEngine; }
IEngineGraphics *Graphics() { return m_pGraphics; }
@ -465,9 +468,10 @@ public:
static void ConchainWindowScreen(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
static void ConchainWindowVSync(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
static void ConchainTimeoutSeed(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
static void ConchainLoglevel(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
static void ConchainPassword(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
static void ConchainReplays(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
static void ConchainLoglevel(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
static void ConchainStdoutOutputLevel(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
static void Con_DemoSlice(IConsole::IResult *pResult, void *pUserData);
static void Con_DemoSliceBegin(IConsole::IResult *pResult, void *pUserData);
@ -551,6 +555,7 @@ public:
void ShowMessageBox(const char *pTitle, const char *pMessage, EMessageBoxType Type = MESSAGE_BOX_TYPE_ERROR) override;
void GetGPUInfoString(char (&aGPUInfo)[256]) override;
void SetLoggers(std::shared_ptr<ILogger> &&pFileLogger, std::shared_ptr<ILogger> &&pStdoutLogger);
};
#endif

View file

@ -122,6 +122,7 @@ public:
virtual void ResetServerGameSettings() = 0;
static LEVEL ToLogLevel(int ConsoleLevel);
static int ToLogLevelFilter(int ConsoleLevel);
// DDRace

View file

@ -67,14 +67,19 @@ int main(int argc, const char **argv)
#endif
std::vector<std::shared_ptr<ILogger>> vpLoggers;
std::shared_ptr<ILogger> pStdoutLogger;
#if defined(CONF_PLATFORM_ANDROID)
vpLoggers.push_back(std::shared_ptr<ILogger>(log_logger_android()));
pStdoutLogger = std::shared_ptr<ILogger>(log_logger_android());
#else
if(!Silent)
{
vpLoggers.push_back(std::shared_ptr<ILogger>(log_logger_stdout()));
pStdoutLogger = std::shared_ptr<ILogger>(log_logger_stdout());
}
#endif
if(pStdoutLogger)
{
vpLoggers.push_back(pStdoutLogger);
}
std::shared_ptr<CFutureLogger> pFutureFileLogger = std::make_shared<CFutureLogger>();
vpLoggers.push_back(pFutureFileLogger);
std::shared_ptr<CFutureLogger> pFutureConsoleLogger = std::make_shared<CFutureLogger>();
@ -102,6 +107,8 @@ int main(int argc, const char **argv)
#endif
CServer *pServer = CreateServer();
pServer->SetLoggers(pFutureFileLogger, std::move(pStdoutLogger));
IKernel *pKernel = IKernel::Create();
// create the components
@ -169,7 +176,6 @@ int main(int argc, const char **argv)
pConsole->Register("sv_test_cmds", "", CFGFLAG_SERVER, CServer::ConTestingCommands, pConsole, "Turns testing commands aka cheats on/off (setting only works in initial config)");
pConsole->Register("sv_rescue", "", CFGFLAG_SERVER, CServer::ConRescue, pConsole, "Allow /rescue command so players can teleport themselves out of freeze (setting only works in initial config)");
log_set_loglevel((LEVEL)g_Config.m_Loglevel);
const int Mode = g_Config.m_Logappend ? IOFLAG_APPEND : IOFLAG_WRITE;
if(g_Config.m_Logfile[0])
{

View file

@ -284,6 +284,10 @@ public:
void CRconClientLogger::Log(const CLogMessage *pMessage)
{
if(m_Filter.Filters(pMessage))
{
return;
}
m_pServer->SendRconLogLine(m_ClientID, pMessage);
}
@ -553,11 +557,11 @@ int CServer::Init()
void CServer::SendLogLine(const CLogMessage *pMessage)
{
if(pMessage->m_Level <= IConsole::ToLogLevel(g_Config.m_ConsoleOutputLevel))
if(pMessage->m_Level <= IConsole::ToLogLevelFilter(g_Config.m_ConsoleOutputLevel))
{
SendRconLogLine(-1, pMessage);
}
if(pMessage->m_Level <= IConsole::ToLogLevel(g_Config.m_EcOutputLevel))
if(pMessage->m_Level <= IConsole::ToLogLevelFilter(g_Config.m_EcOutputLevel))
{
m_Econ.Send(-1, pMessage->m_aLine);
}
@ -3499,12 +3503,6 @@ void CServer::ConDumpSqlServers(IConsole::IResult *pResult, void *pUserData)
}
}
void CServer::ConchainLoglevel(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData)
{
pfnCallback(pResult, pCallbackUserData);
log_set_loglevel((LEVEL)g_Config.m_Loglevel);
}
void CServer::ConchainSpecialInfoupdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData)
{
pfnCallback(pResult, pCallbackUserData);
@ -3669,6 +3667,26 @@ void CServer::ConchainSixupUpdate(IConsole::IResult *pResult, void *pUserData, I
pThis->m_MapReload |= (pThis->m_apCurrentMapData[MAP_TYPE_SIXUP] != 0) != (pResult->GetInteger(0) != 0);
}
void CServer::ConchainLoglevel(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData)
{
CServer *pSelf = (CServer *)pUserData;
pfnCallback(pResult, pCallbackUserData);
if(pResult->NumArguments())
{
pSelf->m_pFileLogger->SetFilter(CLogFilter{IConsole::ToLogLevelFilter(g_Config.m_Loglevel)});
}
}
void CServer::ConchainStdoutOutputLevel(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData)
{
CServer *pSelf = (CServer *)pUserData;
pfnCallback(pResult, pCallbackUserData);
if(pResult->NumArguments() && pSelf->m_pStdoutLogger)
{
pSelf->m_pStdoutLogger->SetFilter(CLogFilter{IConsole::ToLogLevelFilter(g_Config.m_StdoutOutputLevel)});
}
}
#if defined(CONF_FAMILY_UNIX)
void CServer::ConchainConnLoggingServerChange(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData)
{
@ -3736,7 +3754,6 @@ void CServer::RegisterCommands()
RustVersionRegister(*Console());
Console()->Chain("sv_name", ConchainSpecialInfoupdate, this);
Console()->Chain("loglevel", ConchainLoglevel, this);
Console()->Chain("password", ConchainSpecialInfoupdate, this);
Console()->Chain("sv_max_clients_per_ip", ConchainMaxclientsperipUpdate, this);
@ -3748,6 +3765,9 @@ void CServer::RegisterCommands()
Console()->Chain("sv_map", ConchainMapUpdate, this);
Console()->Chain("sv_sixup", ConchainSixupUpdate, this);
Console()->Chain("loglevel", ConchainLoglevel, this);
Console()->Chain("stdout_output_level", ConchainStdoutOutputLevel, this);
#if defined(CONF_FAMILY_UNIX)
Console()->Chain("sv_conn_logging_server", ConchainConnLoggingServerChange, this);
#endif
@ -3868,3 +3888,9 @@ void CServer::SetErrorShutdown(const char *pReason)
{
str_copy(m_aErrorShutdownReason, pReason);
}
void CServer::SetLoggers(std::shared_ptr<ILogger> &&pFileLogger, std::shared_ptr<ILogger> &&pStdoutLogger)
{
m_pFileLogger = pFileLogger;
m_pStdoutLogger = pStdoutLogger;
}

View file

@ -36,6 +36,7 @@ class CLogMessage;
class CMsgPacker;
class CPacker;
class IEngineMap;
class ILogger;
class CSnapIDPool
{
@ -273,6 +274,9 @@ public:
std::vector<std::string> m_vAnnouncements;
char m_aAnnouncementFile[IO_MAX_PATH_LENGTH];
std::shared_ptr<ILogger> m_pFileLogger = nullptr;
std::shared_ptr<ILogger> m_pStdoutLogger = nullptr;
CServer();
~CServer();
@ -418,7 +422,6 @@ public:
static void ConAddSqlServer(IConsole::IResult *pResult, void *pUserData);
static void ConDumpSqlServers(IConsole::IResult *pResult, void *pUserData);
static void ConchainLoglevel(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
static void ConchainSpecialInfoupdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
static void ConchainMaxclientsperipUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
static void ConchainCommandAccessUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
@ -432,6 +435,8 @@ public:
static void ConchainRconHelperPasswordChange(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
static void ConchainMapUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
static void ConchainSixupUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
static void ConchainLoglevel(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
static void ConchainStdoutOutputLevel(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
#if defined(CONF_FAMILY_UNIX)
static void ConchainConnLoggingServerChange(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
@ -481,6 +486,8 @@ public:
bool IsSixup(int ClientID) const override { return ClientID != SERVER_DEMO_CLIENT && m_aClients[ClientID].m_Sixup; }
void SetLoggers(std::shared_ptr<ILogger> &&pFileLogger, std::shared_ptr<ILogger> &&pStdoutLogger);
#ifdef CONF_FAMILY_UNIX
enum CONN_LOGGING_CMD
{

View file

@ -11,6 +11,10 @@ CServerLogger::CServerLogger(CServer *pServer) :
void CServerLogger::Log(const CLogMessage *pMessage)
{
if(m_Filter.Filters(pMessage))
{
return;
}
m_PendingLock.lock();
if(m_MainThread == std::this_thread::get_id())
{

View file

@ -30,6 +30,10 @@ public:
void CAssertionLogger::Log(const CLogMessage *pMessage)
{
if(m_Filter.Filters(pMessage))
{
return;
}
std::unique_lock<std::mutex> Lock(m_DbgMessageMutex);
SDebugMessageItem *pMsgItem = (SDebugMessageItem *)m_DbgMessages.Allocate(sizeof(SDebugMessageItem));
str_copy(pMsgItem->m_aMessage, pMessage->m_aLine);

View file

@ -11,10 +11,11 @@ MACRO_CONFIG_STR(PlayerClan, player_clan, 12, "", CFGFLAG_SAVE | CFGFLAG_CLIENT
MACRO_CONFIG_INT(PlayerCountry, player_country, -1, -1, 1000, CFGFLAG_SAVE | CFGFLAG_CLIENT | CFGFLAG_INSENSITIVE, "Country of the player")
MACRO_CONFIG_STR(Password, password, 32, "", CFGFLAG_CLIENT | CFGFLAG_SERVER | CFGFLAG_NONTEEHISTORIC, "Password to the server")
MACRO_CONFIG_STR(Logfile, logfile, 128, "", CFGFLAG_SAVE | CFGFLAG_CLIENT | CFGFLAG_SERVER, "Filename to log all output to")
MACRO_CONFIG_INT(Loglevel, loglevel, 2, 0, 4, CFGFLAG_SAVE | CFGFLAG_CLIENT | CFGFLAG_SERVER, "Log level (0 = Error, 1 = Warn, 2 = Info, 3 = Debug, 4 = Trace)")
MACRO_CONFIG_INT(Loglevel, loglevel, 0, -3, 2, CFGFLAG_SAVE | CFGFLAG_CLIENT | CFGFLAG_SERVER, "Log level (-3 = none, -2 = error, 1 = Warn, 2 = Info, 3 = Debug, 4 = Trace)")
MACRO_CONFIG_INT(Logappend, logappend, 1, 0, 1, CFGFLAG_SAVE | CFGFLAG_CLIENT | CFGFLAG_SERVER, "Append to logfile instead of overwriting it every time")
MACRO_CONFIG_INT(ConsoleOutputLevel, console_output_level, 0, 0, 2, CFGFLAG_SAVE | CFGFLAG_CLIENT | CFGFLAG_SERVER, "Adjusts the amount of information in the console")
MACRO_CONFIG_INT(ConsoleEnableColors, console_enable_colors, 1, 0, 1, CFGFLAG_SAVE | CFGFLAG_CLIENT | CFGFLAG_SERVER, "Enable colors in console output")
MACRO_CONFIG_INT(StdoutOutputLevel, stdout_output_level, 0, -3, 2, CFGFLAG_CLIENT | CFGFLAG_SERVER, "Adjusts the amount of information in the console (-3 = none, -2 = error only, -1 = warn, 0 = info, 1 = debug, 2 = trace)")
MACRO_CONFIG_INT(ConsoleOutputLevel, console_output_level, 0, -3, 2, CFGFLAG_CLIENT | CFGFLAG_SERVER, "Adjusts the amount of information in the console (-3 = none, -2 = error only, -1 = warn, 0 = info, 1 = debug, 2 = trace)")
MACRO_CONFIG_INT(ConsoleEnableColors, console_enable_colors, 1, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SERVER, "Enable colors in console output")
MACRO_CONFIG_INT(Events, events, 1, 0, 1, CFGFLAG_SAVE | CFGFLAG_CLIENT | CFGFLAG_SERVER, "Enable triggering of events, (eye emotes on some holidays in server, christmas skins in client).")
MACRO_CONFIG_STR(SteamName, steam_name, 16, "", CFGFLAG_SAVE | CFGFLAG_CLIENT, "Last seen name of the Steam profile")

View file

@ -293,6 +293,15 @@ LEVEL IConsole::ToLogLevel(int Level)
return LEVEL_INFO;
}
int IConsole::ToLogLevelFilter(int Level)
{
if(!(-3 <= Level && Level <= 2))
{
dbg_assert(0, "invalid log level filter");
}
return Level + 2;
}
LOG_COLOR ColorToLogColor(ColorRGBA Color)
{
return LOG_COLOR{

View file

@ -42,8 +42,7 @@ public:
void CConsoleLogger::Log(const CLogMessage *pMessage)
{
// TODO: Fix thread-unsafety of accessing `g_Config.m_ConsoleOutputLevel`
if(pMessage->m_Level > IConsole::ToLogLevel(g_Config.m_ConsoleOutputLevel))
if(m_Filter.Filters(pMessage))
{
return;
}
@ -384,6 +383,8 @@ CGameConsole::CGameConsole() :
m_ConsoleState = CONSOLE_CLOSED;
m_StateChangeEnd = 0.0f;
m_StateChangeDuration = 0.1f;
m_pConsoleLogger = new CConsoleLogger(this);
}
CGameConsole::~CGameConsole()
@ -940,6 +941,16 @@ void CGameConsole::ConConsolePageDown(IConsole::IResult *pResult, void *pUserDat
pConsole->m_BacklogCurPage = 0;
}
void CGameConsole::ConchainConsoleOutputLevel(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData)
{
CGameConsole *pSelf = (CGameConsole *)pUserData;
pfnCallback(pResult, pCallbackUserData);
if(pResult->NumArguments())
{
pSelf->m_pConsoleLogger->SetFilter(CLogFilter{IConsole::ToLogLevelFilter(g_Config.m_ConsoleOutputLevel)});
}
}
void CGameConsole::RequireUsername(bool UsernameReq)
{
if((m_RemoteConsole.m_UsernameReq = UsernameReq))
@ -974,11 +985,11 @@ void CGameConsole::OnConsoleInit()
Console()->Register("console_page_up", "", CFGFLAG_CLIENT, ConConsolePageUp, this, "Previous page in console");
Console()->Register("console_page_down", "", CFGFLAG_CLIENT, ConConsolePageDown, this, "Next page in console");
Console()->Chain("console_output_level", ConchainConsoleOutputLevel, this);
}
void CGameConsole::OnInit()
{
m_pConsoleLogger = new CConsoleLogger(this);
Engine()->SetAdditionalLogger(std::unique_ptr<ILogger>(m_pConsoleLogger));
// add resize event
Graphics()->AddWindowResizeListener([this]() {

View file

@ -118,6 +118,7 @@ class CGameConsole : public CComponent
static void ConDumpRemoteConsole(IConsole::IResult *pResult, void *pUserData);
static void ConConsolePageUp(IConsole::IResult *pResult, void *pUserData);
static void ConConsolePageDown(IConsole::IResult *pResult, void *pUserData);
static void ConchainConsoleOutputLevel(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
public:
enum

View file

@ -54,6 +54,10 @@ void CClientChatLogger::Log(const CLogMessage *pMessage)
{
if(str_comp(pMessage->m_aSystem, "chatresp") == 0)
{
if(m_Filter.Filters(pMessage))
{
return;
}
m_pGameServer->SendChatTarget(m_ClientID, pMessage->Message());
}
else