Core/Logging: Refactored appender creation to allow using logging without mysql dependency in tools (future task)

This commit is contained in:
Shauren
2015-08-16 00:12:18 +02:00
parent 21e0880fba
commit d5cf594bfe
12 changed files with 123 additions and 97 deletions

View File

@@ -31,6 +31,7 @@
#include "Config.h"
#include "DatabaseEnv.h"
#include "Log.h"
#include "AppenderDB.h"
#include "ProcessPriority.h"
#include "RealmList.h"
#include "SystemConfig.h"
@@ -104,6 +105,9 @@ int main(int argc, char** argv)
return 1;
}
sLog->RegisterAppender<AppenderDB>();
sLog->Initialize(nullptr);
TC_LOG_INFO("server.bnetserver", "%s (bnetserver)", _FULLVERSION);
TC_LOG_INFO("server.bnetserver", "<Ctrl-C> to stop.\n");
TC_LOG_INFO("server.bnetserver", "Using configuration file %s.", configFile.c_str());

View File

@@ -37,8 +37,8 @@ std::string LogMessage::getTimeStr()
return getTimeStr(mtime);
}
Appender::Appender(uint8 _id, std::string const& _name, AppenderType _type /* = APPENDER_NONE*/, LogLevel _level /* = LOG_LEVEL_DISABLED */, AppenderFlags _flags /* = APPENDER_FLAGS_NONE */):
id(_id), name(_name), type(_type), level(_level), flags(_flags) { }
Appender::Appender(uint8 _id, std::string const& _name, LogLevel _level /* = LOG_LEVEL_DISABLED */, AppenderFlags _flags /* = APPENDER_FLAGS_NONE */):
id(_id), name(_name), level(_level), flags(_flags) { }
Appender::~Appender() { }
@@ -52,11 +52,6 @@ std::string const& Appender::getName() const
return name;
}
AppenderType Appender::getType() const
{
return type;
}
LogLevel Appender::getLogLevel() const
{
return level;

View File

@@ -22,6 +22,7 @@
#include <string>
#include <time.h>
#include <type_traits>
#include <utility>
#include "Define.h"
// Values assigned have their equivalent in enum ACE_Log_Priority
@@ -85,18 +86,19 @@ struct LogMessage
class Appender
{
public:
Appender(uint8 _id, std::string const& name, AppenderType type = APPENDER_NONE, LogLevel level = LOG_LEVEL_DISABLED, AppenderFlags flags = APPENDER_FLAGS_NONE);
Appender(uint8 _id, std::string const& name, LogLevel level = LOG_LEVEL_DISABLED, AppenderFlags flags = APPENDER_FLAGS_NONE);
virtual ~Appender();
uint8 getId() const;
std::string const& getName() const;
AppenderType getType() const;
virtual AppenderType getType() const = 0;
LogLevel getLogLevel() const;
AppenderFlags getFlags() const;
void setLogLevel(LogLevel);
void write(LogMessage* message);
static const char* getLogLevelString(LogLevel level);
virtual void setRealmId(uint32 /*realmId*/) { }
private:
virtual void _write(LogMessage const* /*message*/) = 0;
@@ -110,4 +112,20 @@ class Appender
typedef std::unordered_map<uint8, Appender*> AppenderMap;
typedef std::vector<char const*> ExtraAppenderArgs;
typedef Appender*(*AppenderCreatorFn)(uint8 id, std::string const& name, LogLevel level, AppenderFlags flags, ExtraAppenderArgs extraArgs);
typedef std::unordered_map<uint8, AppenderCreatorFn> AppenderCreatorMap;
template<class AppenderImpl>
Appender* CreateAppender(uint8 id, std::string const& name, LogLevel level, AppenderFlags flags, ExtraAppenderArgs extraArgs)
{
return new AppenderImpl(id, name, level, flags, std::forward<ExtraAppenderArgs>(extraArgs));
}
class InvalidAppenderArgsException : public std::length_error
{
public:
using std::length_error::length_error;
};
#endif

View File

@@ -25,11 +25,14 @@
#include <Windows.h>
#endif
AppenderConsole::AppenderConsole(uint8 id, std::string const& name, LogLevel level, AppenderFlags flags):
Appender(id, name, APPENDER_CONSOLE, level, flags), _colored(false)
AppenderConsole::AppenderConsole(uint8 id, std::string const& name, LogLevel level, AppenderFlags flags, ExtraAppenderArgs extraArgs)
: Appender(id, name, level, flags), _colored(false)
{
for (uint8 i = 0; i < MaxLogLevels; ++i)
_colors[i] = ColorTypes(MaxColors);
if (!extraArgs.empty())
InitColors(extraArgs[0]);
}
void AppenderConsole::InitColors(std::string const& str)

View File

@@ -42,11 +42,14 @@ enum ColorTypes
const uint8 MaxColors = uint8(WHITE) + 1;
class AppenderConsole: public Appender
class AppenderConsole : public Appender
{
public:
AppenderConsole(uint8 _id, std::string const& name, LogLevel level, AppenderFlags flags);
typedef std::integral_constant<AppenderType, APPENDER_CONSOLE>::type TypeIndex;
AppenderConsole(uint8 _id, std::string const& name, LogLevel level, AppenderFlags flags, ExtraAppenderArgs extraArgs);
void InitColors(const std::string& init_str);
AppenderType getType() const override { return TypeIndex::value; }
private:
void SetColor(bool stdout_stream, ColorTypes color);

View File

@@ -18,8 +18,8 @@
#include "AppenderDB.h"
#include "Database/DatabaseEnv.h"
AppenderDB::AppenderDB(uint8 id, std::string const& name, LogLevel level)
: Appender(id, name, APPENDER_DB, level), realmId(0), enabled(false) { }
AppenderDB::AppenderDB(uint8 id, std::string const& name, LogLevel level, AppenderFlags /*flags*/, ExtraAppenderArgs /*extraArgs*/)
: Appender(id, name, level), realmId(0), enabled(false) { }
AppenderDB::~AppenderDB() { }

View File

@@ -23,10 +23,13 @@
class AppenderDB: public Appender
{
public:
AppenderDB(uint8 _id, std::string const& _name, LogLevel level);
typedef std::integral_constant<AppenderType, APPENDER_DB>::type TypeIndex;
AppenderDB(uint8 id, std::string const& name, LogLevel level, AppenderFlags flags, ExtraAppenderArgs extraArgs);
~AppenderDB();
void setRealmId(uint32 realmId);
void setRealmId(uint32 realmId) override;
AppenderType getType() const override { return TypeIndex::value; }
private:
uint32 realmId;

View File

@@ -17,24 +17,45 @@
#include "AppenderFile.h"
#include "Common.h"
#include "StringFormat.h"
#include "Log.h"
#if PLATFORM == PLATFORM_WINDOWS
# include <Windows.h>
#endif
AppenderFile::AppenderFile(uint8 id, std::string const& name, LogLevel level, const char* filename, const char* logDir, const char* mode, AppenderFlags flags, uint64 fileSize):
Appender(id, name, APPENDER_FILE, level, flags),
AppenderFile::AppenderFile(uint8 id, std::string const& name, LogLevel level, AppenderFlags flags, ExtraAppenderArgs extraArgs) :
Appender(id, name, level, flags),
logfile(NULL),
_fileName(filename),
_logDir(logDir),
_maxFileSize(fileSize),
_logDir(sLog->GetLogsDir()),
_fileSize(0)
{
if (extraArgs.empty())
throw InvalidAppenderArgsException(Trinity::StringFormat("Log::CreateAppenderFromConfig: Missing file name for appender %s\n", name.c_str()));
_fileName = extraArgs[0];
char const* mode = "a";
if (extraArgs.size() > 1)
mode = extraArgs[1];
if (flags & APPENDER_FLAGS_USE_TIMESTAMP)
{
size_t dot_pos = _fileName.find_last_of(".");
if (dot_pos != std::string::npos)
_fileName.insert(dot_pos, sLog->GetLogsTimestamp());
else
_fileName += sLog->GetLogsTimestamp();
}
if (extraArgs.size() > 2)
_maxFileSize = atoi(extraArgs[2]);
_dynamicName = std::string::npos != _fileName.find("%s");
_backup = (flags & APPENDER_FLAGS_MAKE_FILE_BACKUP) != 0;
if (!_dynamicName)
logfile = OpenFile(filename, mode, !strcmp(mode, "w") && _backup);
logfile = OpenFile(_fileName, mode, !strcmp(mode, "w") && _backup);
}
AppenderFile::~AppenderFile()

View File

@@ -21,12 +21,15 @@
#include <atomic>
#include "Appender.h"
class AppenderFile: public Appender
class AppenderFile : public Appender
{
public:
AppenderFile(uint8 id, std::string const& name, LogLevel level, const char* filename, const char* logDir, const char* mode, AppenderFlags flags, uint64 maxSize);
typedef std::integral_constant<AppenderType, APPENDER_FILE>::type TypeIndex;
AppenderFile(uint8 id, std::string const& name, LogLevel level, AppenderFlags flags, ExtraAppenderArgs extraArgs);
~AppenderFile();
FILE* OpenFile(std::string const& name, std::string const& mode, bool backup);
AppenderType getType() const override { return TypeIndex::value; }
private:
void CloseFile();

View File

@@ -32,7 +32,8 @@
Log::Log() : _ioService(nullptr), _strand(nullptr)
{
m_logsTimestamp = "_" + GetTimestampStr();
LoadFromConfig();
RegisterAppender<AppenderConsole>();
RegisterAppender<AppenderFile>();
}
Log::~Log()
@@ -102,60 +103,21 @@ void Log::CreateAppenderFromConfig(std::string const& appenderName)
if (size > 2)
flags = AppenderFlags(atoi(*iter++));
switch (type)
auto factoryFunction = appenderFactory.find(type);
if (factoryFunction == appenderFactory.end())
{
case APPENDER_CONSOLE:
{
AppenderConsole* appender = new AppenderConsole(NextAppenderId(), name, level, flags);
appenders[appender->getId()] = appender;
if (size > 3)
appender->InitColors(*iter++);
//fprintf(stdout, "Log::CreateAppenderFromConfig: Created Appender %s (%u), Type CONSOLE, Mask %u\n", appender->getName().c_str(), appender->getId(), appender->getLogLevel());
break;
}
case APPENDER_FILE:
{
std::string filename;
std::string mode = "a";
fprintf(stderr, "Log::CreateAppenderFromConfig: Unknown type %d for appender %s\n", type, name.c_str());
return;
}
if (size < 4)
{
fprintf(stderr, "Log::CreateAppenderFromConfig: Missing file name for appender %s\n", name.c_str());
return;
}
filename = *iter++;
if (size > 4)
mode = *iter++;
if (flags & APPENDER_FLAGS_USE_TIMESTAMP)
{
size_t dot_pos = filename.find_last_of(".");
if (dot_pos != filename.npos)
filename.insert(dot_pos, m_logsTimestamp);
else
filename += m_logsTimestamp;
}
uint64 maxFileSize = 0;
if (size > 5)
maxFileSize = atoi(*iter++);
uint8 id = NextAppenderId();
appenders[id] = new AppenderFile(id, name, level, filename.c_str(), m_logsDir.c_str(), mode.c_str(), flags, maxFileSize);
//fprintf(stdout, "Log::CreateAppenderFromConfig: Created Appender %s (%u), Type FILE, Mask %u, File %s, Mode %s\n", name.c_str(), id, level, filename.c_str(), mode.c_str());
break;
}
case APPENDER_DB:
{
uint8 id = NextAppenderId();
appenders[id] = new AppenderDB(id, name, level);
break;
}
default:
fprintf(stderr, "Log::CreateAppenderFromConfig: Unknown type %d for appender %s\n", type, name.c_str());
break;
try
{
Appender* appender = factoryFunction->second(NextAppenderId(), name, level, flags, ExtraAppenderArgs(iter, tokens.end()));
appenders[appender->getId()] = appender;
}
catch (InvalidAppenderArgsException const& iaae)
{
fprintf(stderr, iaae.what());
}
}
@@ -251,7 +213,7 @@ void Log::ReadLoggersFromConfig()
Close(); // Clean any Logger or Appender created
AppenderConsole* appender = new AppenderConsole(NextAppenderId(), "Console", LOG_LEVEL_DEBUG, APPENDER_FLAGS_NONE);
AppenderConsole* appender = new AppenderConsole(NextAppenderId(), "Console", LOG_LEVEL_DEBUG, APPENDER_FLAGS_NONE, ExtraAppenderArgs());
appenders[appender->getId()] = appender;
Logger& logger = loggers[LOGGER_ROOT];
@@ -348,21 +310,29 @@ void Log::outCharDump(char const* str, uint32 accountId, uint64 guid, char const
void Log::SetRealmId(uint32 id)
{
for (AppenderMap::iterator it = appenders.begin(); it != appenders.end(); ++it)
if (it->second && it->second->getType() == APPENDER_DB)
static_cast<AppenderDB*>(it->second)->setRealmId(id);
it->second->setRealmId(id);
}
void Log::Close()
{
loggers.clear();
for (AppenderMap::iterator it = appenders.begin(); it != appenders.end(); ++it)
{
delete it->second;
it->second = NULL;
}
appenders.clear();
}
void Log::Initialize(boost::asio::io_service* ioService)
{
if (ioService)
{
_ioService = ioService;
_strand = new boost::asio::strand(*ioService);
}
LoadFromConfig();
}
void Log::LoadFromConfig()
{
Close();

View File

@@ -44,19 +44,13 @@ class Log
public:
static Log* instance(boost::asio::io_service* ioService = nullptr)
static Log* instance()
{
static Log instance;
if (ioService != nullptr)
{
instance._ioService = ioService;
instance._strand = new boost::asio::strand(*ioService);
}
return &instance;
}
void Initialize(boost::asio::io_service* ioService);
void LoadFromConfig();
void Close();
bool ShouldLog(std::string const& type, LogLevel level) const;
@@ -88,6 +82,18 @@ class Log
void SetRealmId(uint32 id);
template<class AppenderImpl>
void RegisterAppender()
{
using Index = typename AppenderImpl::TypeIndex;
auto itr = appenderFactory.find(Index::value);
ASSERT(itr == appenderFactory.end());
appenderFactory[Index::value] = &CreateAppender<AppenderImpl>;
}
std::string const& GetLogsDir() const { return m_logsDir; }
std::string const& GetLogsTimestamp() const { return m_logsTimestamp; }
private:
static std::string GetTimestampStr();
void write(std::unique_ptr<LogMessage>&& msg) const;
@@ -100,6 +106,7 @@ class Log
void ReadAppendersFromConfig();
void ReadLoggersFromConfig();
AppenderCreatorMap appenderFactory;
AppenderMap appenders;
LoggerMap loggers;
uint8 AppenderId;

View File

@@ -45,6 +45,7 @@
#include "BattlenetServerManager.h"
#include "Realm/Realm.h"
#include "DatabaseLoader.h"
#include "AppenderDB.h"
#include <openssl/opensslv.h>
#include <openssl/crypto.h>
#include <boost/asio/io_service.hpp>
@@ -125,11 +126,9 @@ extern int main(int argc, char** argv)
return 1;
}
if (sConfigMgr->GetBoolDefault("Log.Async.Enable", false))
{
// If logs are supposed to be handled async then we need to pass the io_service into the Log singleton
Log::instance(&_ioService);
}
sLog->RegisterAppender<AppenderDB>();
// If logs are supposed to be handled async then we need to pass the io_service into the Log singleton
sLog->Initialize(sConfigMgr->GetBoolDefault("Log.Async.Enable", false) ? &_ioService : nullptr);
TC_LOG_INFO("server.worldserver", "%s (worldserver-daemon)", _FULLVERSION);
TC_LOG_INFO("server.worldserver", "<Ctrl-C> to stop.\n");