Further implement logging system
This commit is contained in:
parent
b67d8a11e8
commit
174af32355
11
src/Main.cpp
11
src/Main.cpp
|
@ -5,19 +5,12 @@
|
||||||
|
|
||||||
using namespace Feather;
|
using namespace Feather;
|
||||||
|
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
ServerProperties properties("server.properties");
|
ServerProperties properties("server.properties");
|
||||||
properties.Save();
|
properties.Save();
|
||||||
|
auto server = DedicatedServer(&properties);
|
||||||
// TEMP
|
|
||||||
|
|
||||||
printf("Starting server on port %d\n", properties.serverPort.GetValue());
|
|
||||||
|
|
||||||
Log_Info("Starting server on port %d\n", properties.serverPort.GetValue());
|
|
||||||
Logging::GlobalLogger.LogDirect(Logging::LOG_GENERAL, Logging::Level::INFO, "Starting server on port %d\n", properties.serverPort.GetValue() );
|
|
||||||
|
|
||||||
//auto server = DedicatedServer(&properties);
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,23 +3,127 @@
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstdarg>
|
#include <cstdarg>
|
||||||
|
|
||||||
#define MAX_LOG_MESSAGE_LENGTH 2048
|
// Platform-dependent console initialization
|
||||||
|
static void InitPlatformConsole();
|
||||||
|
|
||||||
namespace Feather::Logging
|
namespace Feather::Logging
|
||||||
{
|
{
|
||||||
Channel LOG_GENERAL;
|
|
||||||
|
|
||||||
Logger GlobalLogger;
|
Logger GlobalLogger;
|
||||||
|
|
||||||
void Logger::LogDirect(Channel channel, Level level, const char *message, ...)
|
ChannelID LOG_GENERAL = REGISTER_LOGGING_CHANNEL("General");
|
||||||
|
|
||||||
|
// Since min and max are inclusive we have to add 1 here
|
||||||
|
// This assumes max > min (they better be)
|
||||||
|
static constexpr int NUM_LEVELS = ((int)Level::MAX_LEVEL - (int)Level::MIN_LEVEL) + 1;
|
||||||
|
|
||||||
|
// Temporary solution while we don't have named enums
|
||||||
|
static const char *s_levelNames[NUM_LEVELS] = {"ERROR", "WARNING", "INFO", "DEBUG", "TRACE"};
|
||||||
|
|
||||||
|
// Shifts an enum value to be a positive index in s_levelNames
|
||||||
|
static constexpr int LEVEL_NAME_OFFSET = 0 - (int)Level::MIN_LEVEL;
|
||||||
|
|
||||||
|
|
||||||
|
Logger::Logger()
|
||||||
|
{
|
||||||
|
InitPlatformConsole();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Logger::LogDirect(ChannelID channel, Level level, const char *message, ...)
|
||||||
{
|
{
|
||||||
char buffer[MAX_LOG_MESSAGE_LENGTH];
|
char buffer[MAX_LOG_MESSAGE_LENGTH];
|
||||||
|
int offset = 0;
|
||||||
|
|
||||||
|
// All color escape sequences follow the following ANSI format:
|
||||||
|
// ESC (\x1B) CSI ([) <COLOR CODES> SGR (m)
|
||||||
|
switch (level)
|
||||||
|
{
|
||||||
|
case Level::WARNING:
|
||||||
|
// 1 BRIGHT, 33 YELLOW
|
||||||
|
offset += snprintf(buffer + offset, MAX_LOG_MESSAGE_LENGTH - offset, "\x1B[1;33m");
|
||||||
|
break;
|
||||||
|
case Level::ERROR:
|
||||||
|
// 1 BRIGHT, 31 RED
|
||||||
|
offset += snprintf(buffer + offset, MAX_LOG_MESSAGE_LENGTH - offset, "\x1B[1;31m");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
case Level::INFO:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* levelName = s_levelNames[(int)level + LEVEL_NAME_OFFSET];
|
||||||
|
|
||||||
|
if (channel == LOG_GENERAL) {
|
||||||
|
// Print only severity level
|
||||||
|
offset += snprintf(buffer + offset, MAX_LOG_MESSAGE_LENGTH - offset, "[%s] ", levelName);
|
||||||
|
} else {
|
||||||
|
// Print channel name and severity level
|
||||||
|
const char *channelName = m_channels[channel]->GetName();
|
||||||
|
offset += snprintf(buffer + offset, MAX_LOG_MESSAGE_LENGTH - offset, "[%s] [%s] ", channelName, levelName);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write our message
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, message);
|
va_start(args, message);
|
||||||
vsnprintf(buffer, MAX_LOG_MESSAGE_LENGTH, message, args);
|
offset += vsnprintf(buffer + offset, MAX_LOG_MESSAGE_LENGTH - offset, message, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
||||||
printf(buffer);
|
// Ignore any terminal newline
|
||||||
|
if (buffer[offset - 1] == '\n') offset--;
|
||||||
|
|
||||||
|
// Append ANSI style reset code 0 and newline
|
||||||
|
offset += snprintf(buffer + offset, MAX_LOG_MESSAGE_LENGTH - offset, "\x1b[0m\n");
|
||||||
|
|
||||||
|
if (level >= Level::INFO) {
|
||||||
|
// Info and above go to stdout
|
||||||
|
printf(buffer);
|
||||||
|
} else {
|
||||||
|
// Error and warn go to stderr
|
||||||
|
fprintf(stderr, buffer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
ChannelID Logger::RegisterChannel(const char* name)
|
||||||
|
{
|
||||||
|
Channel* channel = new Channel(name);
|
||||||
|
if (m_channelCount >= MAX_LOGGING_CHANNEL_COUNT) {
|
||||||
|
// complain
|
||||||
|
}
|
||||||
|
m_channels[m_channelCount] = channel;
|
||||||
|
int id = m_channelCount++;
|
||||||
|
printf("Registered channel %d '%s'\n", id, name);
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
|
||||||
|
#ifndef WIN32_LEAN_AND_MEAN
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void InitPlatformConsole()
|
||||||
|
{
|
||||||
|
static bool s_initialized = false;
|
||||||
|
if (s_initialized)
|
||||||
|
return;
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
|
if (handle != INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
DWORD mode = 0;
|
||||||
|
if (GetConsoleMode(handle, &mode))
|
||||||
|
{
|
||||||
|
mode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
|
||||||
|
SetConsoleMode(handle, mode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
s_initialized = true;
|
||||||
|
}
|
||||||
|
|
|
@ -2,6 +2,11 @@
|
||||||
|
|
||||||
namespace Feather::Logging
|
namespace Feather::Logging
|
||||||
{
|
{
|
||||||
|
const int MAX_LOG_MESSAGE_LENGTH = 2048;
|
||||||
|
const int MAX_LOGGING_CHANNEL_COUNT = 256;
|
||||||
|
|
||||||
|
/*==== Severity Levels ==============================*/
|
||||||
|
|
||||||
enum class Level
|
enum class Level
|
||||||
{
|
{
|
||||||
// Serious problems
|
// Serious problems
|
||||||
|
@ -18,26 +23,51 @@ namespace Feather::Logging
|
||||||
|
|
||||||
// Fine grained spew
|
// Fine grained spew
|
||||||
TRACE = 2,
|
TRACE = 2,
|
||||||
|
|
||||||
|
// These are an inclusve interval
|
||||||
|
MIN_LEVEL = ERROR,
|
||||||
|
MAX_LEVEL = TRACE,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*==== Channels ==============================*/
|
||||||
|
|
||||||
|
typedef int ChannelID;
|
||||||
|
|
||||||
class Channel
|
class Channel
|
||||||
{
|
{
|
||||||
|
const char* m_name;
|
||||||
|
public:
|
||||||
|
Channel(const char* name) : m_name(name) {}
|
||||||
|
|
||||||
|
inline const char* GetName() { return m_name; }
|
||||||
};
|
};
|
||||||
|
|
||||||
extern Channel LOG_GENERAL;
|
extern ChannelID LOG_GENERAL;
|
||||||
|
|
||||||
|
/*==== Logger ==============================*/
|
||||||
|
|
||||||
class Logger
|
class Logger
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void LogDirect(Channel channel, Level level, const char* message, ...);
|
Logger();
|
||||||
|
void LogDirect(ChannelID channel, Level level, const char* message, ...);
|
||||||
|
|
||||||
|
ChannelID RegisterChannel(const char* name);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Channel* m_channels[MAX_LOGGING_CHANNEL_COUNT];
|
||||||
|
ChannelID m_channelCount = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern Logger GlobalLogger;
|
extern Logger GlobalLogger;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define Log_Msg( Channel, Message, Args... )
|
#define REGISTER_LOGGING_CHANNEL(Name) Feather::Logging::GlobalLogger.RegisterChannel(Name);
|
||||||
|
|
||||||
#define Log_Debug(Message, Args...)
|
#define Log_Msg(_Channel, _Level, _Message, ...) Feather::Logging::GlobalLogger.LogDirect(Feather::Logging::_Channel, Feather::Logging::Level::_Level, _Message, ##__VA_ARGS__)
|
||||||
#define Log_Info(Message, ...) Feather::Logging::GlobalLogger.LogDirect(Feather::Logging::LOG_GENERAL, Feather::Logging::Level::INFO, Message, ##__VA_ARGS__)
|
|
||||||
#define Log_Warn(Message, Args...)
|
#define Log_Info(Message, ...) Log_Msg(LOG_GENERAL, INFO, Message, ##__VA_ARGS__)
|
||||||
|
#define Log_Warn(Message, ...) Log_Msg(LOG_GENERAL, WARNING, Message, ##__VA_ARGS__)
|
||||||
|
#define Log_Error(Message, ...) Log_Msg(LOG_GENERAL, ERROR, Message, ##__VA_ARGS__)
|
||||||
|
#define Log_Debug(Message, ...) Log_Msg(LOG_GENERAL, DEBUG, Message, ##__VA_ARGS__)
|
||||||
|
#define Log_Trace(Message, ...) Log_Msg(LOG_GENERAL, TRACE, Message, ##__VA_ARGS__)
|
||||||
|
|
Loading…
Reference in New Issue