aboutsummaryrefslogtreecommitdiff
path: root/src/server/shared/Logging
diff options
context:
space:
mode:
authorSpp <spp@jorge.gr>2012-08-03 14:20:18 +0200
committerSpp <spp@jorge.gr>2012-08-03 14:20:18 +0200
commit55ce180f2867700b28921d99f9a0cb9c83330c91 (patch)
treec563db507cce44b680996d42148185cb1512188c /src/server/shared/Logging
parentf85908869986eab0b645f0a697028bcceba7778c (diff)
Core/Logging: Add Asyncronous logging with Loggers ("What to log") and Appenders ("Where to log") system. Will allow to select to full log some parts of core while others are not even logged.
- Logging System is asyncronous to improve performance. - Each msg and Logger has a Log Type and Log Level assigned. Each msg is assigned the Logger of same Log Type or "root" Logger is selected if there is no Logger configured for the given Log Type - Loggers have a list of Appenders to send the msg to. The Msg in the Logger is not sent to Appenders if the msg LogLevel is lower than Logger LogLevel. - There are three (at the moment) types of Appenders: Console, File or DB (this is WIP, not working ATM). Msg is not written to the resource if msg LogLevel is lower than Appender LogLevel. - Appender and Console Log levels can be changed while server is active with command '.set loglevel (a/l) name level' Explanation of use with Sample config: Appender.Console.Type=1 (1 = Console) Appender.Console.Level=2 (2 = Debug) Appender.Server.Type=2 (2 = File) Appender.Server.Level=3 (3 = Info) Appender.Server.File=Server.log Appender.SQL.Type=2 (2 = File) Appender.SQL.Level=1 (1 = Trace) Appender.SQL.File=sql.log Appenders=Console Server (NOTE: SQL has not been included here... that will make core ignore the config for "SQL" as it's not in this list) Logger.root.Type=0 (0 = Default - if it's not created by config, server will create it with LogLevel = DISABLED) Logger.root.Level=5 (5 = Error) Logger.root.Appenders=Console Logger.SQL.Type=26 (26 = SQL) Logger.SQL.Level=3 (2 = Debug) Logger.SQL.Appenders=Console Server SQL Logger.SomeRandomName.Type=24 (24 = Guild) Logger.SomeRandomName.Level=5 (5 = Error) Loggers=root SQL SomeRandomName * At loading Appender SQL will be ignored, as it's not present on "Appenders" * sLog->outDebug(LOG_FILTER_GUILD, "Some log msg related to Guilds") - Msg is sent to Logger of Type LOG_FILTER_GUILD (24). Logger with name SomeRandomName is found but it's LogLevel = 5 and Msg LogLevel=2... Msg is not logged * sLog->outError(LOG_FILTER_GUILD, "Some error log msg related to Guilds") - Msg is sent to Logger of Type LOG_FILTER_GUILD (24). Logger with name SomeRandomeName is found with proper LogLevel but Logger does not have any Appenders assigned to that logger... Msg is not logged * sLog->outDebug(LOG_FILTER_SQL, "Some msg related to SQLs") - Msg is sent to Logger SQL (matches type), as it matches LogLevel the msg is sent to Appenders Console, Server and SQL - Appender Console has lower Log Level: Msg is logged to Console - Appender Server has higher Log Level: Msg is not logged to file - Appender SQL has lower Log Level: Msg is logged to file sql.log * sLog->outDebug(LOG_FILTER_BATTLEGROUND, "Some msg related to Battelgrounds") - Msg is sent to Logger root (Type 0) as no Logger was found with Type LOG_FILTER_BATTLEGROUND (13). As Logger has higher LogLevel msg is not sent to any appender * sLog->outError(LOG_FILTER_BATTLEGROUND, "Some error msg related to Battelgrounds") - Msg is sent to Logger root (Type 0) as no Logger was found with Type LOG_FILTER_BATTLEGROUND (13). Msg has lower LogLevel and is sent to Appender Console - Appender Console has lower LogLevel: Msg is logged to Console
Diffstat (limited to 'src/server/shared/Logging')
-rw-r--r--src/server/shared/Logging/Appender.cpp153
-rw-r--r--src/server/shared/Logging/Appender.h115
-rw-r--r--src/server/shared/Logging/AppenderConsole.cpp174
-rw-r--r--src/server/shared/Logging/AppenderConsole.h42
-rw-r--r--src/server/shared/Logging/AppenderDB.cpp30
-rw-r--r--src/server/shared/Logging/AppenderDB.h19
-rw-r--r--src/server/shared/Logging/AppenderFile.cpp54
-rw-r--r--src/server/shared/Logging/AppenderFile.h22
-rwxr-xr-xsrc/server/shared/Logging/Log.cpp1135
-rwxr-xr-xsrc/server/shared/Logging/Log.h209
-rw-r--r--src/server/shared/Logging/LogOperation.cpp14
-rw-r--r--src/server/shared/Logging/LogOperation.h24
-rw-r--r--src/server/shared/Logging/LogWorker.cpp33
-rw-r--r--src/server/shared/Logging/LogWorker.h30
-rw-r--r--src/server/shared/Logging/Logger.cpp67
-rw-r--r--src/server/shared/Logging/Logger.h29
16 files changed, 1091 insertions, 1059 deletions
diff --git a/src/server/shared/Logging/Appender.cpp b/src/server/shared/Logging/Appender.cpp
new file mode 100644
index 00000000000..38d58f1ffb5
--- /dev/null
+++ b/src/server/shared/Logging/Appender.cpp
@@ -0,0 +1,153 @@
+#include "Appender.h"
+#include "Common.h"
+
+std::string LogMessage::getTimeStr(time_t time)
+{
+ tm* aTm = localtime(&time);
+ char buf[20];
+ snprintf(buf, 20, "%04d-%02d-%02d_%02d:%02d:%02d", aTm->tm_year+1900, aTm->tm_mon+1, aTm->tm_mday, aTm->tm_hour, aTm->tm_min, aTm->tm_sec);
+ return std::string(buf);
+}
+
+std::string LogMessage::getTimeStr()
+{
+ return getTimeStr(mtime);
+}
+
+Appender::Appender(uint8 _id, std::string const& _name, AppenderType _type /* = APPENDER_NONE*/, LogLevel _level /* = LOG_LEVEL_DISABLED */):
+id(_id), name(_name), type(_type), level(_level)
+{
+}
+
+Appender::~Appender()
+{
+}
+
+uint8 Appender::getId() const
+{
+ return id;
+}
+
+std::string const& Appender::getName() const
+{
+ return name;
+}
+
+AppenderType Appender::getType() const
+{
+ return type;
+}
+
+LogLevel Appender::getLogLevel() const
+{
+ return level;
+}
+
+void Appender::setLogLevel(LogLevel _level)
+{
+ level = _level;
+}
+
+void Appender::write(LogMessage& message)
+{
+ if (level && level <= message.level)
+ _write(message);
+ //else fprintf(stderr, "Appender::write: Appender %s, Level %s. Msg %s Level %s Type %s WRONG LEVEL MASK\n", getName().c_str(), getLogLevelString(level), message.text.c_str(), getLogLevelString(message.level), getLogFilterTypeString(message.type)); // DEBUG - RemoveMe
+}
+
+const char* Appender::getLogLevelString(LogLevel level)
+{
+ switch (level)
+ {
+ case LOG_LEVEL_FATAL:
+ return "FATAL";
+ case LOG_LEVEL_ERROR:
+ return "ERROR";
+ case LOG_LEVEL_WARN:
+ return "WARN";
+ case LOG_LEVEL_INFO:
+ return "INFO";
+ case LOG_LEVEL_DEBUG:
+ return "DEBUG";
+ case LOG_LEVEL_TRACE:
+ return "TRACE";
+ default:
+ return "DISABLED";
+ }
+}
+
+char const* Appender::getLogFilterTypeString(LogFilterType type)
+{
+ switch (type)
+ {
+ case LOG_FILTER_GENERAL:
+ return "GENERAL";
+ case LOG_FILTER_UNITS:
+ return "UNITS";
+ case LOG_FILTER_PETS:
+ return "PETS";
+ case LOG_FILTER_VEHICLES:
+ return "VEHICLES";
+ case LOG_FILTER_TSCR:
+ return "TSCR";
+ case LOG_FILTER_DATABASE_AI:
+ return "DATABASE_AI";
+ case LOG_FILTER_MAPSCRIPTS:
+ return "MAPSCRIPTS";
+ case LOG_FILTER_NETWORKIO:
+ return "NETWORKIO";
+ case LOG_FILTER_SPELLS_AURAS:
+ return "SPELLS_AURAS";
+ case LOG_FILTER_ACHIEVEMENTSYS:
+ return "ACHIEVEMENTSYS";
+ case LOG_FILTER_CONDITIONSYS:
+ return "CONDITIONSYS";
+ case LOG_FILTER_POOLSYS:
+ return "POOLSYS";
+ case LOG_FILTER_AUCTIONHOUSE:
+ return "AUCTIONHOUSE";
+ case LOG_FILTER_BATTLEGROUND:
+ return "BATTLEGROUND";
+ case LOG_FILTER_OUTDOORPVP:
+ return "OUTDOORPVP";
+ case LOG_FILTER_CHATSYS:
+ return "CHATSYS";
+ case LOG_FILTER_LFG:
+ return "LFG";
+ case LOG_FILTER_MAPS:
+ return "MAPS";
+ case LOG_FILTER_PLAYER:
+ return "PLAYER";
+ case LOG_FILTER_PLAYER_LOADING:
+ return "PLAYER_LOADING";
+ case LOG_FILTER_PLAYER_ITEMS:
+ return "PLAYER_ITEMS";
+ case LOG_FILTER_PLAYER_SKILLS:
+ return "PLAYER_SKILLS";
+ case LOG_FILTER_PLAYER_CHATLOG:
+ return "PLAYER_CHATLOG";
+ case LOG_FILTER_LOOT:
+ return "LOOT";
+ case LOG_FILTER_GUILD:
+ return "GUILD";
+ case LOG_FILTER_TRANSPORTS:
+ return "TRANSPORTS";
+ case LOG_FILTER_SQL:
+ return "SQL";
+ case LOG_FILTER_GMCOMMAND:
+ return "GMCOMMAND";
+ case LOG_FILTER_REMOTECOMMAND:
+ return "REMOTECOMMAND";
+ case LOG_FILTER_WARDEN:
+ return "WARDEN";
+ case LOG_FILTER_AUTHSERVER:
+ return "AUTHSERVER";
+ case LOG_FILTER_WORLDSERVER:
+ return "WORLDSERVER";
+ case LOG_FILTER_GAMEEVENTS:
+ return "GAMEEVENTS";
+ default:
+ break;
+ }
+ return "???";
+}
diff --git a/src/server/shared/Logging/Appender.h b/src/server/shared/Logging/Appender.h
new file mode 100644
index 00000000000..992554d59aa
--- /dev/null
+++ b/src/server/shared/Logging/Appender.h
@@ -0,0 +1,115 @@
+#ifndef APPENDER_H
+#define APPENDER_H
+
+#include "Define.h"
+
+#include <string>
+#include <map>
+
+enum LogFilterType
+{
+ LOG_FILTER_GENERAL, // This one should only be used inside Log.cpp
+ LOG_FILTER_UNITS, // Anything related to units that doesn't fit in other categories. ie. creature formations
+ LOG_FILTER_PETS,
+ LOG_FILTER_VEHICLES,
+ LOG_FILTER_TSCR, // C++ AI, instance scripts, etc.
+ LOG_FILTER_DATABASE_AI, // SmartAI, EventAI, Creature* * AI
+ LOG_FILTER_MAPSCRIPTS,
+ LOG_FILTER_NETWORKIO,
+ LOG_FILTER_SPELLS_AURAS,
+ LOG_FILTER_ACHIEVEMENTSYS,
+ LOG_FILTER_CONDITIONSYS,
+ LOG_FILTER_POOLSYS,
+ LOG_FILTER_AUCTIONHOUSE,
+ LOG_FILTER_BATTLEGROUND,
+ LOG_FILTER_OUTDOORPVP,
+ LOG_FILTER_CHATSYS,
+ LOG_FILTER_LFG,
+ LOG_FILTER_MAPS,
+ LOG_FILTER_PLAYER, // Any player log that does not fit in other player filters
+ LOG_FILTER_PLAYER_LOADING, // Debug output from Player::_Load functions
+ LOG_FILTER_PLAYER_ITEMS,
+ LOG_FILTER_PLAYER_SKILLS,
+ LOG_FILTER_PLAYER_CHATLOG,
+ LOG_FILTER_LOOT,
+ LOG_FILTER_GUILD,
+ LOG_FILTER_TRANSPORTS,
+ LOG_FILTER_SQL,
+ LOG_FILTER_GMCOMMAND,
+ LOG_FILTER_REMOTECOMMAND,
+ LOG_FILTER_WARDEN,
+ LOG_FILTER_AUTHSERVER,
+ LOG_FILTER_WORLDSERVER,
+ LOG_FILTER_GAMEEVENTS,
+ LOG_FILTER_CALENDAR
+};
+
+const uint8 MaxLogFilter = uint8(LOG_FILTER_CALENDAR) + 1;
+
+// Values assigned have their equivalent in enum ACE_Log_Priority
+enum LogLevel
+{
+ LOG_LEVEL_DISABLED = 0,
+ LOG_LEVEL_TRACE = 1,
+ LOG_LEVEL_DEBUG = 2,
+ LOG_LEVEL_INFO = 3,
+ LOG_LEVEL_WARN = 4,
+ LOG_LEVEL_ERROR = 5,
+ LOG_LEVEL_FATAL = 6,
+};
+
+const uint8 MaxLogLevels = 6;
+
+enum AppenderType
+{
+ APPENDER_NONE,
+ APPENDER_CONSOLE,
+ APPENDER_FILE,
+ APPENDER_DB,
+};
+
+struct LogMessage
+{
+ LogMessage(LogLevel _level, LogFilterType _type, std::string _text): level(_level), type(_type), text(_text)
+ {
+ mtime = time(NULL);
+ }
+
+ static std::string getTimeStr(time_t time);
+ std::string getTimeStr();
+
+ LogLevel level;
+ LogFilterType type;
+ std::string text;
+ uint32 param1;
+ time_t mtime;
+};
+
+class Appender
+{
+ public:
+ Appender(uint8 _id, std::string const& name, AppenderType type = APPENDER_NONE, LogLevel level = LOG_LEVEL_DISABLED);
+ virtual ~Appender();
+
+ uint8 getId() const;
+ std::string const& getName() const;
+ AppenderType getType() const;
+ LogLevel getLogLevel() const;
+
+ void setLogLevel(LogLevel);
+ void write(LogMessage& message);
+ static const char* getLogLevelString(LogLevel level);
+ static const char* getLogFilterTypeString(LogFilterType type);
+
+ private:
+ virtual void _write(LogMessage& /*message*/) {};
+
+ uint8 id;
+ std::string name;
+ AppenderType type;
+ LogLevel level;
+};
+
+typedef std::map<uint8, Appender*> AppenderMap;
+
+#endif
diff --git a/src/server/shared/Logging/AppenderConsole.cpp b/src/server/shared/Logging/AppenderConsole.cpp
new file mode 100644
index 00000000000..ad81a883bfa
--- /dev/null
+++ b/src/server/shared/Logging/AppenderConsole.cpp
@@ -0,0 +1,174 @@
+#include "AppenderConsole.h"
+#include "Config.h"
+#include "Util.h"
+
+#include <sstream>
+
+AppenderConsole::AppenderConsole(uint8 id, std::string const& name, LogLevel level):
+Appender(id, name, APPENDER_CONSOLE, level), _colored(false), _colors()
+{
+}
+
+void AppenderConsole::InitColors(std::string const& str)
+{
+ if (str.empty())
+ {
+ _colored = false;
+ return;
+ }
+
+ int color[MaxLogLevels];
+
+ std::istringstream ss(str);
+
+ for (uint8 i = 0; i < MaxLogLevels; ++i)
+ {
+ ss >> color[i];
+
+ if (!ss)
+ return;
+
+ if (color[i] < 0 || color[i] >= MaxColors)
+ return;
+ }
+
+ for (uint8 i = 0; i < MaxLogLevels; ++i)
+ _colors[i] = ColorTypes(color[i]);
+
+ _colored = true;
+}
+
+void AppenderConsole::SetColor(bool stdout_stream, ColorTypes color)
+{
+ #if PLATFORM == PLATFORWINDOWS
+ static WORD WinColorFG[MaxColors] =
+ {
+ 0, // BLACK
+ FOREGROUND_RED, // RED
+ FOREGROUND_GREEN, // GREEN
+ FOREGROUND_RED | FOREGROUND_GREEN, // BROWN
+ FOREGROUND_BLUE, // BLUE
+ FOREGROUND_RED | FOREGROUND_BLUE, // MAGENTA
+ FOREGROUND_GREEN | FOREGROUND_BLUE, // CYAN
+ FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE, // WHITE
+ // YELLOW
+ FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY,
+ // RED_BOLD
+ FOREGROUND_RED | FOREGROUND_INTENSITY,
+ // GREEN_BOLD
+ FOREGROUND_GREEN | FOREGROUND_INTENSITY,
+ FOREGROUND_BLUE | FOREGROUND_INTENSITY, // BLUE_BOLD
+ // MAGENTA_BOLD
+ FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY,
+ // CYAN_BOLD
+ FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY,
+ // WHITE_BOLD
+ FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY
+ };
+
+ HANDLE hConsole = GetStdHandle(stdout_stream ? STD_OUTPUT_HANDLE : STD_ERROR_HANDLE);
+ SetConsoleTextAttribute(hConsole, WinColorFG[color]);
+ #else
+ enum ANSITextAttr
+ {
+ TA_NORMAL = 0,
+ TA_BOLD = 1,
+ TA_BLINK = 5,
+ TA_REVERSE = 7
+ };
+
+ enum ANSIFgTextAttr
+ {
+ FG_BLACK = 30,
+ FG_RED,
+ FG_GREEN,
+ FG_BROWN,
+ FG_BLUE,
+ FG_MAGENTA,
+ FG_CYAN,
+ FG_WHITE,
+ FG_YELLOW
+ };
+
+ enum ANSIBgTextAttr
+ {
+ BG_BLACK = 40,
+ BG_RED,
+ BG_GREEN,
+ BG_BROWN,
+ BG_BLUE,
+ BG_MAGENTA,
+ BG_CYAN,
+ BG_WHITE
+ };
+
+ static uint8 UnixColorFG[MaxColors] =
+ {
+ FG_BLACK, // BLACK
+ FG_RED, // RED
+ FG_GREEN, // GREEN
+ FG_BROWN, // BROWN
+ FG_BLUE, // BLUE
+ FG_MAGENTA, // MAGENTA
+ FG_CYAN, // CYAN
+ FG_WHITE, // WHITE
+ FG_YELLOW, // YELLOW
+ FG_RED, // LRED
+ FG_GREEN, // LGREEN
+ FG_BLUE, // LBLUE
+ FG_MAGENTA, // LMAGENTA
+ FG_CYAN, // LCYAN
+ FG_WHITE // LWHITE
+ };
+
+ fprintf((stdout_stream? stdout : stderr), "\x1b[%d%sm", UnixColorFG[color], (color >= YELLOW && color < MaxColors ? ";1" : ""));
+ #endif
+}
+
+void AppenderConsole::ResetColor(bool stdout_stream)
+{
+ #if PLATFORM == PLATFORWINDOWS
+ HANDLE hConsole = GetStdHandle(stdout_stream ? STD_OUTPUT_HANDLE : STD_ERROR_HANDLE);
+ SetConsoleTextAttribute(hConsole, FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED);
+ #else
+ fprintf((stdout_stream ? stdout : stderr), "\x1b[0m");
+ #endif
+}
+
+void AppenderConsole::_write(LogMessage& message)
+{
+ bool stdout_stream = message.level == LOG_LEVEL_ERROR || message.level == LOG_LEVEL_FATAL;
+
+ if (_colored)
+ {
+ uint8 index;
+ switch (message.level)
+ {
+ case LOG_LEVEL_TRACE:
+ index = 5;
+ break;
+ case LOG_LEVEL_DEBUG:
+ index = 4;
+ break;
+ case LOG_LEVEL_INFO:
+ index = 3;
+ break;
+ case LOG_LEVEL_WARN:
+ index = 2;
+ break;
+ case LOG_LEVEL_FATAL:
+ index = 0;
+ break;
+ case LOG_LEVEL_ERROR: // No break on purpose
+ default:
+ index = 1;
+ break;
+ }
+
+ SetColor(stdout_stream, _colors[index]);
+ utf8printf(stdout_stream ? stdout : stderr, "%s %-5s [%-15s] %s", message.getTimeStr().c_str(), Appender::getLogLevelString(message.level), Appender::getLogFilterTypeString(message.type), message.text.c_str());
+ ResetColor(stdout_stream);
+ }
+ else
+ utf8printf(stdout_stream ? stdout : stderr, "%s %-5s [%-15s] %s", message.getTimeStr().c_str(), Appender::getLogLevelString(message.level), Appender::getLogFilterTypeString(message.type), message.text.c_str());
+}
diff --git a/src/server/shared/Logging/AppenderConsole.h b/src/server/shared/Logging/AppenderConsole.h
new file mode 100644
index 00000000000..a9f46cf9c4a
--- /dev/null
+++ b/src/server/shared/Logging/AppenderConsole.h
@@ -0,0 +1,42 @@
+#ifndef APPENDERCONSOLE_H
+#define APPENDERCONSOLE_H
+
+#include "Appender.h"
+#include <string>
+
+enum ColorTypes
+{
+ BLACK,
+ RED,
+ GREEN,
+ BROWN,
+ BLUE,
+ MAGENTA,
+ CYAN,
+ GREY,
+ YELLOW,
+ LRED,
+ LGREEN,
+ LBLUE,
+ LMAGENTA,
+ LCYAN,
+ WHITE
+};
+
+const uint8 MaxColors = uint8(WHITE) + 1;
+
+class AppenderConsole: public Appender
+{
+ public:
+ AppenderConsole(uint8 _id, std::string const& name, LogLevel level);
+ void InitColors(const std::string& init_str);
+
+ private:
+ void SetColor(bool stdout_stream, ColorTypes color);
+ void ResetColor(bool stdout_stream);
+ void _write(LogMessage& message);
+ bool _colored;
+ ColorTypes _colors[MaxLogLevels];
+};
+
+#endif
diff --git a/src/server/shared/Logging/AppenderDB.cpp b/src/server/shared/Logging/AppenderDB.cpp
new file mode 100644
index 00000000000..6f3737adf4d
--- /dev/null
+++ b/src/server/shared/Logging/AppenderDB.cpp
@@ -0,0 +1,30 @@
+#include "AppenderDB.h"
+
+/* FIXME
+#include "DatabaseWorkerPool.h"
+#include "Implementation/LoginDatabase.h" // For logging
+extern DatabaseWorkerPool LoginDatabase;
+*/
+
+AppenderDB::AppenderDB(uint8 id, std::string const& name, LogLevel level, uint8 realmId):
+Appender(id, name, APPENDER_DB, level), realm(realmId), enable(false)
+{
+}
+
+AppenderDB::~AppenderDB()
+{
+}
+
+void AppenderDB::_write(LogMessage& /*message*/)
+{
+/* FIXME
+ if (enable)
+ LoginDatabase.PExecute("INSERT INTO logs (time, realm, type, severity, string) "
+ "VALUES (" UI64FMTD ", %u, %u, '%s');", message.mtime, realm, message.type, message.level, message.text.c_str());
+*/
+}
+
+void AppenderDB::setEnable(bool _enable)
+{
+ enable = _enable;
+}
diff --git a/src/server/shared/Logging/AppenderDB.h b/src/server/shared/Logging/AppenderDB.h
new file mode 100644
index 00000000000..ca15fc1a1d5
--- /dev/null
+++ b/src/server/shared/Logging/AppenderDB.h
@@ -0,0 +1,19 @@
+#ifndef APPENDERDB_H
+#define APPENDERDB_H
+
+#include "Appender.h"
+
+class AppenderDB: public Appender
+{
+ public:
+ AppenderDB(uint8 _id, std::string const& _name, LogLevel level, uint8 realmId);
+ ~AppenderDB();
+ void setEnable(bool enable);
+
+ private:
+ uint8 realm;
+ bool enable;
+ void _write(LogMessage& message);
+};
+
+#endif
diff --git a/src/server/shared/Logging/AppenderFile.cpp b/src/server/shared/Logging/AppenderFile.cpp
new file mode 100644
index 00000000000..30c1f271c96
--- /dev/null
+++ b/src/server/shared/Logging/AppenderFile.cpp
@@ -0,0 +1,54 @@
+#include "AppenderFile.h"
+#include "Common.h"
+
+AppenderFile::AppenderFile(uint8 id, std::string const& name, LogLevel level, const char* _filename, const char* _mode, bool _backup)
+ : Appender(id, name, APPENDER_FILE, level)
+ , filename(_filename)
+ , mode(_mode)
+ , backup(_backup)
+{
+ dynamicName = std::string::npos != filename.find("%u");
+ if (!dynamicName)
+ logfile = OpenFile(_filename, _mode, _backup);
+}
+
+AppenderFile::~AppenderFile()
+{
+ if (logfile)
+ {
+ fclose(logfile);
+ logfile = NULL;
+ }
+}
+
+void AppenderFile::_write(LogMessage& message)
+{
+ if (dynamicName)
+ {
+ char namebuf[TRINITY_PATH_MAX];
+ snprintf(namebuf, TRINITY_PATH_MAX, filename.c_str(), message.param1);
+ logfile = OpenFile(namebuf, mode, backup);
+ }
+
+ if (logfile)
+ {
+ fprintf(logfile, "%s %-5s [%-15s] %s", message.getTimeStr().c_str(), Appender::getLogLevelString(message.level), Appender::getLogFilterTypeString(message.type), message.text.c_str());
+
+ fflush(logfile);
+
+ if (dynamicName)
+ fclose(logfile);
+ }
+}
+
+FILE* AppenderFile::OpenFile(std::string const &filename, std::string const &mode, bool backup)
+{
+ if (mode == "w" && backup)
+ {
+ std::string newName(filename);
+ newName.push_back('.');
+ newName.append(LogMessage::getTimeStr(time(NULL)));
+ rename(filename.c_str(), newName.c_str()); // no error handling... if we couldn't make a backup, just ignore
+ }
+ return fopen(filename.c_str(), mode.c_str());
+}
diff --git a/src/server/shared/Logging/AppenderFile.h b/src/server/shared/Logging/AppenderFile.h
new file mode 100644
index 00000000000..a01ea947334
--- /dev/null
+++ b/src/server/shared/Logging/AppenderFile.h
@@ -0,0 +1,22 @@
+#ifndef APPENDERFILE_H
+#define APPENDERFILE_H
+
+#include "Appender.h"
+
+class AppenderFile: public Appender
+{
+ public:
+ AppenderFile(uint8 _id, std::string const& _name, LogLevel level, const char* filename, const char* mode, bool backup);
+ ~AppenderFile();
+ FILE* OpenFile(std::string const& _name, std::string const& _mode, bool _backup);
+
+ private:
+ void _write(LogMessage& message);
+ FILE* logfile;
+ std::string filename;
+ std::string mode;
+ bool dynamicName;
+ bool backup;
+};
+
+#endif
diff --git a/src/server/shared/Logging/Log.cpp b/src/server/shared/Logging/Log.cpp
index 79eab053d08..17c6df44125 100755
--- a/src/server/shared/Logging/Log.cpp
+++ b/src/server/shared/Logging/Log.cpp
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
- * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+ * Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -16,343 +16,246 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "Common.h"
#include "Log.h"
-#include "Configuration/Config.h"
-#include "Util.h"
+#include "Common.h"
+#include "Config.h"
-#include "Implementation/LoginDatabase.h" // For logging
-extern LoginDatabaseWorkerPool LoginDatabase;
+#include "AppenderConsole.h"
+#include "AppenderFile.h"
+#include "AppenderDB.h"
+#include "LogOperation.h"
-#include <stdarg.h>
-#include <stdio.h>
+#include <cstdarg>
+#include <cstdio>
+#include <sstream>
-Log::Log() :
- raLogfile(NULL), logfile(NULL), gmLogfile(NULL), charLogfile(NULL),
- dberLogfile(NULL), chatLogfile(NULL), arenaLogFile(NULL), sqlLogFile(NULL), sqlDevLogFile(NULL), wardenLogFile(NULL),
- m_gmlog_per_account(false), m_enableLogDBLater(false),
- m_enableLogDB(false), m_colored(false)
+Log::Log()
{
- Initialize();
+ SetRealmID(0);
+ AppenderId = 0;
+ /// Common log files data
+ m_logsDir = ConfigMgr::GetStringDefault("LogsDir", "");
+ if (!m_logsDir.empty())
+ if ((m_logsDir.at(m_logsDir.length() - 1) != '/') && (m_logsDir.at(m_logsDir.length() - 1) != '\\'))
+ m_logsDir.push_back('/');
+
+ m_logsTimestamp = "_" + GetTimestampStr();
+
+ ReadAppendersFromConfig();
+ ReadLoggersFromConfig();
+ worker = new LogWorker();
}
Log::~Log()
{
- if (logfile != NULL)
- fclose(logfile);
- logfile = NULL;
-
- if (gmLogfile != NULL)
- fclose(gmLogfile);
- gmLogfile = NULL;
-
- if (charLogfile != NULL)
- fclose(charLogfile);
- charLogfile = NULL;
-
- if (dberLogfile != NULL)
- fclose(dberLogfile);
- dberLogfile = NULL;
-
- if (raLogfile != NULL)
- fclose(raLogfile);
- raLogfile = NULL;
-
- if (chatLogfile != NULL)
- fclose(chatLogfile);
- chatLogfile = NULL;
-
- if (arenaLogFile != NULL)
- fclose(arenaLogFile);
- arenaLogFile = NULL;
-
- if (sqlLogFile != NULL)
- fclose(sqlLogFile);
- sqlLogFile = NULL;
-
- if (sqlDevLogFile != NULL)
- fclose(sqlDevLogFile);
- sqlDevLogFile = NULL;
-
- if (wardenLogFile != NULL)
- fclose(wardenLogFile);
- wardenLogFile = NULL;
+ Close();
}
-void Log::SetLogLevel(char *Level)
+uint8 Log::NextAppenderId()
{
- int32 NewLevel = atoi((char*)Level);
- if (NewLevel < 0)
- NewLevel = 0;
- m_logLevel = NewLevel;
-
- outString("LogLevel is %u", m_logLevel);
+ return AppenderId++;
}
-void Log::SetLogFileLevel(char *Level)
+int32 GetConfigIntDefault(std::string base, const char* name, int32 value)
{
- int32 NewLevel = atoi((char*)Level);
- if (NewLevel < 0)
- NewLevel = 0;
- m_logFileLevel = NewLevel;
+ base.append(name);
+ return ConfigMgr::GetIntDefault(base.c_str(), value);
+}
- outString("LogFileLevel is %u", m_logFileLevel);
+std::string GetConfigStringDefault(std::string base, const char* name, const char* value)
+{
+ base.append(name);
+ return ConfigMgr::GetStringDefault(base.c_str(), value);
}
-void Log::SetDBLogLevel(char *Level)
+// Returns default logger if the requested logger is not found
+Logger* Log::GetLoggerByType(LogFilterType filter)
{
- int32 NewLevel = atoi((char*)Level);
- if (NewLevel < 0)
- NewLevel = 0;
- m_dbLogLevel = NewLevel;
+ LoggerMap::iterator it = loggers.begin();
+ while (it != loggers.end() && it->second.getType() != filter)
+ ++it;
- outString("DBLogLevel is %u", m_dbLogLevel);
+ return it == loggers.end() ? &(loggers[0]) : &(it->second);
}
-void Log::Initialize()
+Appender* Log::GetAppenderByName(std::string const& name)
{
- /// Check whether we'll log GM commands/RA events/character outputs/chat stuffs
- m_dbChar = ConfigMgr::GetBoolDefault("LogDB.Char", false);
- m_dbRA = ConfigMgr::GetBoolDefault("LogDB.RA", false);
- m_dbGM = ConfigMgr::GetBoolDefault("LogDB.GM", false);
- m_dbChat = ConfigMgr::GetBoolDefault("LogDB.Chat", false);
+ AppenderMap::iterator it = appenders.begin();
+ while (it != appenders.end() && it->second && it->second->getName() != name)
+ ++it;
- /// Realm must be 0 by default
- SetRealmID(0);
+ return it == appenders.end() ? NULL : it->second;
+}
- /// Common log files data
- m_logsDir = ConfigMgr::GetStringDefault("LogsDir", "");
- if (!m_logsDir.empty())
- if ((m_logsDir.at(m_logsDir.length() - 1) != '/') && (m_logsDir.at(m_logsDir.length() - 1) != '\\'))
- m_logsDir.push_back('/');
+void Log::CreateAppenderFromConfig(const char* name)
+{
+ if (!name || *name == '\0')
+ return;
- m_logsTimestamp = "_" + GetTimestampStr();
+ std::string base = "Appender.";
+ base.append(name);
+ base.push_back('.');
- /// Open specific log files
- logfile = openLogFile("LogFile", "LogTimestamp", "w");
- InitColors(ConfigMgr::GetStringDefault("LogColors", ""));
+ LogLevel level = LogLevel(GetConfigIntDefault(base, "Level", 0));
+ AppenderType type = AppenderType(GetConfigIntDefault(base, "Type", 0));
- m_gmlog_per_account = ConfigMgr::GetBoolDefault("GmLogPerAccount", false);
- if (!m_gmlog_per_account)
- gmLogfile = openLogFile("GMLogFile", "GmLogTimestamp", "a");
- else
+ switch(type)
{
- // GM log settings for per account case
- m_gmlog_filename_format = ConfigMgr::GetStringDefault("GMLogFile", "");
- if (!m_gmlog_filename_format.empty())
+ case APPENDER_CONSOLE:
{
- bool m_gmlog_timestamp = ConfigMgr::GetBoolDefault("GmLogTimestamp", false);
+ AppenderConsole* appender = new AppenderConsole(NextAppenderId(), name, level);
+ appenders[appender->getId()] = appender;
- size_t dot_pos = m_gmlog_filename_format.find_last_of('.');
- if (dot_pos!=m_gmlog_filename_format.npos)
- {
- if (m_gmlog_timestamp)
- m_gmlog_filename_format.insert(dot_pos, m_logsTimestamp);
+ appender->InitColors(GetConfigStringDefault(base, "Colors", ""));
+ //fprintf(stdout, "Log::CreateAppenderFromConfig: Created Appender %s (%u), Type CONSOLE, Mask %u\n", appender->getName().c_str(), appender->getId(), appender->getLogLevel()); // DEBUG - RemoveMe
+ break;
+ }
+ case APPENDER_FILE:
+ {
+ std::string filename = GetConfigStringDefault(base, "File", "");
+ std::string mode = GetConfigStringDefault(base, "Mode", "a");
+ std::string timestamp = GetConfigStringDefault(base, "Timestamp", "");
+ bool backup = GetConfigIntDefault(base, "Backup", 0);
- m_gmlog_filename_format.insert(dot_pos, "_#%u");
- }
- else
+ if (!timestamp.empty())
{
- m_gmlog_filename_format += "_#%u";
-
- if (m_gmlog_timestamp)
- m_gmlog_filename_format += m_logsTimestamp;
+ size_t dot_pos = filename.find_last_of(".");
+ if (dot_pos != filename.npos)
+ filename.insert(dot_pos, m_logsTimestamp);
+ else
+ filename += m_logsTimestamp;
}
- m_gmlog_filename_format = m_logsDir + m_gmlog_filename_format;
+ uint8 id = NextAppenderId();
+ appenders[id] = new AppenderFile(id, name, level, filename.c_str(), mode.c_str(), backup);
+ //fprintf(stdout, "Log::CreateAppenderFromConfig: Created Appender %s (%u), Type FILE, Mask %u, File %s, Mode %s\n", name, id, level, filename.c_str(), mode.c_str()); // DEBUG - RemoveMe
+ break;
}
+ case APPENDER_DB: // TODO Set realm!
+ {
+ uint8 id = NextAppenderId();
+ appenders[id] = new AppenderDB(id, name, level, realm);
+ break;
+ }
+ default:
+ break;
}
+}
+
+void Log::CreateLoggerFromConfig(const char* name)
+{
+ if (!name || *name == '\0')
+ return;
+
+ std::string base = "Logger.";
+ base.append(name);
+ base.push_back('.');
+
+ LogLevel level = LogLevel(GetConfigIntDefault(base, "Level", 0));
+ int32 type = GetConfigIntDefault(base, "Type", -1);
- charLogfile = openLogFile("CharLogFile", "CharLogTimestamp", "a");
- dberLogfile = openLogFile("DBErrorLogFile", NULL, "a");
- raLogfile = openLogFile("RaLogFile", NULL, "a");
- chatLogfile = openLogFile("ChatLogFile", "ChatLogTimestamp", "a");
- arenaLogFile = openLogFile("ArenaLogFile", NULL, "a");
- sqlLogFile = openLogFile("SQLDriverLogFile", NULL, "a");
- sqlDevLogFile = openLogFile("SQLDeveloperLogFile", NULL, "a");
- wardenLogFile = openLogFile("Warden.LogFile",NULL,"a");
-
- // Main log file settings
- m_logLevel = ConfigMgr::GetIntDefault("LogLevel", LOGL_NORMAL);
- m_logFileLevel = ConfigMgr::GetIntDefault("LogFileLevel", LOGL_NORMAL);
- m_dbLogLevel = ConfigMgr::GetIntDefault("DBLogLevel", LOGL_NORMAL);
- m_sqlDriverQueryLogging = ConfigMgr::GetBoolDefault("SQLDriverQueryLogging", false);
-
- m_DebugLogMask = DebugLogFilters(ConfigMgr::GetIntDefault("DebugLogMask", LOG_FILTER_NONE));
-
- // Char log settings
- m_charLog_Dump = ConfigMgr::GetBoolDefault("CharLogDump", false);
- m_charLog_Dump_Separate = ConfigMgr::GetBoolDefault("CharLogDump.Separate", false);
- if (m_charLog_Dump_Separate)
+ if (type < 0)
{
- m_dumpsDir = ConfigMgr::GetStringDefault("CharLogDump.SeparateDir", "");
- if (!m_dumpsDir.empty())
- if ((m_dumpsDir.at(m_dumpsDir.length() - 1) != '/') && (m_dumpsDir.at(m_dumpsDir.length() - 1) != '\\'))
- m_dumpsDir.push_back('/');
+ fprintf(stderr, "Log::CreateLoggerFromConfig: Missing entry %sType in config. Logger ignored\n", name);
+ return;
}
-}
-void Log::ReloadConfig()
-{
- m_logLevel = ConfigMgr::GetIntDefault("LogLevel", LOGL_NORMAL);
- m_logFileLevel = ConfigMgr::GetIntDefault("LogFileLevel", LOGL_NORMAL);
- m_dbLogLevel = ConfigMgr::GetIntDefault("DBLogLevel", LOGL_NORMAL);
+ Logger& logger = loggers[type];
- m_DebugLogMask = DebugLogFilters(ConfigMgr::GetIntDefault("DebugLogMask", LOG_FILTER_NONE));
-}
+ if (!logger.getName().empty())
+ fprintf(stderr, "Error while configuring Logger %s. Replacing (name: %s, Type: %u, Level: %u) with (name: %s, Type: %u, Level: %u)\n",
+ name, logger.getName().c_str(), logger.getType(), logger.getLogLevel(), name, type, level);
-FILE* Log::openLogFile(char const* configFileName, char const* configTimeStampFlag, char const* mode)
-{
- std::string logfn=ConfigMgr::GetStringDefault(configFileName, "");
- if (logfn.empty())
- return NULL;
+ logger.Create(name, LogFilterType(type), level);
+ //fprintf(stdout, "Log::CreateLoggerFromConfig: Created Logger %s, Type %u, mask %u\n", name, LogFilterType(type), level); // DEBUG - RemoveMe
- if (configTimeStampFlag && ConfigMgr::GetBoolDefault(configTimeStampFlag, false))
+ std::istringstream ss(GetConfigStringDefault(base, "Appenders", ""));
+ std::string str;
+
+ ss >> str;
+ while (ss)
{
- size_t dot_pos = logfn.find_last_of(".");
- if (dot_pos!=logfn.npos)
- logfn.insert(dot_pos, m_logsTimestamp);
+ if (Appender* appender = GetAppenderByName(str))
+ {
+ logger.addAppender(appender->getId(), appender);
+ //fprintf(stdout, "Log::CreateLoggerFromConfig: Added Appender %s to Logger %s\n", appender->getName().c_str(), name); // DEBUG - RemoveMe
+ }
else
- logfn += m_logsTimestamp;
+ fprintf(stderr, "Error while configuring Appender %s in Logger %s. Appender does not exist", str.c_str(), name);
+ ss >> str;
}
-
- return fopen((m_logsDir+logfn).c_str(), mode);
}
-FILE* Log::openGmlogPerAccount(uint32 account)
+void Log::ReadAppendersFromConfig()
{
- if (m_gmlog_filename_format.empty())
- return NULL;
+ std::istringstream ss(ConfigMgr::GetStringDefault("Appenders", ""));
+ std::string name;
- char namebuf[TRINITY_PATH_MAX];
- snprintf(namebuf, TRINITY_PATH_MAX, m_gmlog_filename_format.c_str(), account);
- return fopen(namebuf, "a");
+ do
+ {
+ ss >> name;
+ CreateAppenderFromConfig(name.c_str());
+ name = "";
+ }
+ while (ss);
}
-void Log::outTimestamp(FILE* file)
+void Log::ReadLoggersFromConfig()
{
- time_t t = time(NULL);
- tm* aTm = localtime(&t);
- // YYYY year
- // MM month (2 digits 01-12)
- // DD day (2 digits 01-31)
- // HH hour (2 digits 00-23)
- // MM minutes (2 digits 00-59)
- // SS seconds (2 digits 00-59)
- fprintf(file, "%-4d-%02d-%02d %02d:%02d:%02d ", aTm->tm_year+1900, aTm->tm_mon+1, aTm->tm_mday, aTm->tm_hour, aTm->tm_min, aTm->tm_sec);
-}
+ std::istringstream ss(ConfigMgr::GetStringDefault("Loggers", ""));
+ std::string name;
-void Log::InitColors(const std::string& str)
-{
- if (str.empty())
+ do
{
- m_colored = false;
- return;
+ ss >> name;
+ CreateLoggerFromConfig(name.c_str());
+ name = "";
}
+ while (ss);
- int color[4];
-
- std::istringstream ss(str);
+ LoggerMap::const_iterator it = loggers.begin();
- for (uint8 i = 0; i < LogLevels; ++i)
- {
- ss >> color[i];
+ while (it != loggers.end() && it->first)
+ ++it;
- if (!ss)
- return;
-
- if (color[i] < 0 || color[i] >= Colors)
- return;
- }
+ // root logger must exist. Marking as disabled as its not configured
+ if (it == loggers.end())
+ loggers[0].Create("root", LOG_FILTER_GENERAL, LOG_LEVEL_DISABLED);
+}
- for (uint8 i = 0; i < LogLevels; ++i)
- m_colors[i] = ColorTypes(color[i]);
+void Log::EnableDBAppenders()
+{
+ for (AppenderMap::iterator it = appenders.begin(); it != appenders.end(); ++it)
+ if (it->second && it->second->getType() == APPENDER_DB)
+ ((AppenderDB *)it->second)->setEnable(true);
- m_colored = true;
}
-void Log::SetColor(bool stdout_stream, ColorTypes color)
+void Log::log(LogFilterType filter, LogLevel level, char const* str, ...)
{
- #if PLATFORM == PLATFORM_WINDOWS
- static WORD WinColorFG[Colors] =
- {
- 0, // BLACK
- FOREGROUND_RED, // RED
- FOREGROUND_GREEN, // GREEN
- FOREGROUND_RED | FOREGROUND_GREEN, // BROWN
- FOREGROUND_BLUE, // BLUE
- FOREGROUND_RED | FOREGROUND_BLUE, // MAGENTA
- FOREGROUND_GREEN | FOREGROUND_BLUE, // CYAN
- FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE, // WHITE
- // YELLOW
- FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY,
- // RED_BOLD
- FOREGROUND_RED | FOREGROUND_INTENSITY,
- // GREEN_BOLD
- FOREGROUND_GREEN | FOREGROUND_INTENSITY,
- FOREGROUND_BLUE | FOREGROUND_INTENSITY, // BLUE_BOLD
- // MAGENTA_BOLD
- FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY,
- // CYAN_BOLD
- FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY,
- // WHITE_BOLD
- FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY
- };
-
- HANDLE hConsole = GetStdHandle(stdout_stream ? STD_OUTPUT_HANDLE : STD_ERROR_HANDLE );
- SetConsoleTextAttribute(hConsole, WinColorFG[color]);
- #else
- enum ANSITextAttr
- {
- TA_NORMAL=0,
- TA_BOLD=1,
- TA_BLINK=5,
- TA_REVERSE=7
- };
+ if (!str || !ShouldLog(filter, level))
+ return;
- enum ANSIFgTextAttr
- {
- FG_BLACK=30, FG_RED, FG_GREEN, FG_BROWN, FG_BLUE,
- FG_MAGENTA, FG_CYAN, FG_WHITE, FG_YELLOW
- };
+ va_list ap;
+ va_start(ap, str);
- enum ANSIBgTextAttr
- {
- BG_BLACK=40, BG_RED, BG_GREEN, BG_BROWN, BG_BLUE,
- BG_MAGENTA, BG_CYAN, BG_WHITE
- };
+ vlog(filter, level, str, ap);
- static uint8 UnixColorFG[Colors] =
- {
- FG_BLACK, // BLACK
- FG_RED, // RED
- FG_GREEN, // GREEN
- FG_BROWN, // BROWN
- FG_BLUE, // BLUE
- FG_MAGENTA, // MAGENTA
- FG_CYAN, // CYAN
- FG_WHITE, // WHITE
- FG_YELLOW, // YELLOW
- FG_RED, // LRED
- FG_GREEN, // LGREEN
- FG_BLUE, // LBLUE
- FG_MAGENTA, // LMAGENTA
- FG_CYAN, // LCYAN
- FG_WHITE // LWHITE
- };
-
- fprintf((stdout_stream? stdout : stderr), "\x1b[%d%sm", UnixColorFG[color], (color >= YELLOW && color < Colors ? ";1" : ""));
- #endif
+ va_end(ap);
+}
+
+void Log::vlog(LogFilterType filter, LogLevel level, char const* str, va_list argptr)
+{
+ char text[MAX_QUERY_LEN];
+ vsnprintf(text, MAX_QUERY_LEN, str, argptr);
+ write(new LogMessage(level, filter, text));
}
-void Log::ResetColor(bool stdout_stream)
+void Log::write(LogMessage* msg)
{
- #if PLATFORM == PLATFORM_WINDOWS
- HANDLE hConsole = GetStdHandle(stdout_stream ? STD_OUTPUT_HANDLE : STD_ERROR_HANDLE );
- SetConsoleTextAttribute(hConsole, FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED );
- #else
- fprintf(( stdout_stream ? stdout : stderr ), "\x1b[0m");
- #endif
+ msg->text.append("\n");
+ Logger* logger = GetLoggerByType(msg->type);
+ worker->enqueue(new LogOperation(logger, msg));
}
std::string Log::GetTimestampStr()
@@ -370,710 +273,160 @@ std::string Log::GetTimestampStr()
return std::string(buf);
}
-void Log::outDB(LogTypes type, const char * str)
+bool Log::SetLogLevel(std::string const& name, const char* newLevelc, bool isLogger /* = true */)
{
- if (!str || type >= MAX_LOG_TYPES)
- return;
+ LogLevel newLevel = LogLevel(atoi(newLevelc));
+ if (newLevel < 0)
+ return false;
- std::string logStr(str);
- if (logStr.empty())
- return;
-
- PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_LOG);
-
- stmt->setInt32(0, realm);
- stmt->setUInt8(1, uint8(type));
- stmt->setString(2, logStr);
-
- LoginDatabase.Execute(stmt);
-}
-
-void Log::outString(const char * str, ...)
-{
- if (!str)
- return;
-
- if (m_enableLogDB)
+ if (isLogger)
{
- // we don't want empty strings in the DB
- std::string s(str);
- if (s.empty() || s == " ")
- return;
-
- va_list ap2;
- va_start(ap2, str);
- char nnew_str[MAX_QUERY_LEN];
- vsnprintf(nnew_str, MAX_QUERY_LEN, str, ap2);
- outDB(LOG_TYPE_STRING, nnew_str);
- va_end(ap2);
- }
+ LoggerMap::iterator it = loggers.begin();
+ while (it != loggers.end() && it->second.getName() != name)
+ ++it;
- if (m_colored)
- SetColor(true, m_colors[LOGL_NORMAL]);
+ if (it == loggers.end())
+ return false;
- va_list ap;
-
- va_start(ap, str);
- vutf8printf(stdout, str, &ap);
- va_end(ap);
-
- if (m_colored)
- ResetColor(true);
-
- printf("\n");
- if (logfile)
- {
- outTimestamp(logfile);
- va_start(ap, str);
- vfprintf(logfile, str, ap);
- fprintf(logfile, "\n");
- va_end(ap);
-
- fflush(logfile);
+ it->second.setLogLevel(newLevel);
}
- fflush(stdout);
-}
-
-void Log::outString()
-{
- printf("\n");
- if (logfile)
- {
- outTimestamp(logfile);
- fprintf(logfile, "\n");
- fflush(logfile);
- }
- fflush(stdout);
-}
-
-void Log::outCrash(const char * err, ...)
-{
- if (!err)
- return;
-
- if (m_enableLogDB)
- {
- va_list ap2;
- va_start(ap2, err);
- char nnew_str[MAX_QUERY_LEN];
- vsnprintf(nnew_str, MAX_QUERY_LEN, err, ap2);
- outDB(LOG_TYPE_CRASH, nnew_str);
- va_end(ap2);
- }
-
- if (m_colored)
- SetColor(false, LRED);
-
- va_list ap;
-
- va_start(ap, err);
- vutf8printf(stderr, err, &ap);
- va_end(ap);
-
- if (m_colored)
- ResetColor(false);
-
- fprintf(stderr, "\n");
- if (logfile)
+ else
{
- outTimestamp(logfile);
- fprintf(logfile, "CRASH ALERT: ");
-
- va_start(ap, err);
- vfprintf(logfile, err, ap);
- va_end(ap);
+ Appender* appender = GetAppenderByName(name);
+ if (!appender)
+ return false;
- fprintf(logfile, "\n");
- fflush(logfile);
+ appender->setLogLevel(newLevel);
}
- fflush(stderr);
+ return true;
}
-void Log::outError(const char * err, ...)
+bool Log::ShouldLog(LogFilterType type, LogLevel level) const
{
- if (!err)
- return;
-
- if (m_enableLogDB)
- {
- va_list ap2;
- va_start(ap2, err);
- char nnew_str[MAX_QUERY_LEN];
- vsnprintf(nnew_str, MAX_QUERY_LEN, err, ap2);
- outDB(LOG_TYPE_ERROR, nnew_str);
- va_end(ap2);
- }
-
- if (m_colored)
- SetColor(false, LRED);
-
- va_list ap;
-
- va_start(ap, err);
- vutf8printf(stderr, err, &ap);
- va_end(ap);
+ LoggerMap::const_iterator it = loggers.begin();
+ while (it != loggers.end() && it->second.getType() != type)
+ ++it;
- if (m_colored)
- ResetColor(false);
-
- fprintf( stderr, "\n");
- if (logfile)
+ if (it != loggers.end())
{
- outTimestamp(logfile);
- fprintf(logfile, "ERROR: ");
-
- va_start(ap, err);
- vfprintf(logfile, err, ap);
- va_end(ap);
-
- fprintf(logfile, "\n");
- fflush(logfile);
+ LogLevel loggerLevel = it->second.getLogLevel();
+ return loggerLevel && loggerLevel <= level;
}
- fflush(stderr);
-}
-void Log::outArena(const char * str, ...)
-{
- if (!str)
- return;
+ if (type != LOG_FILTER_GENERAL)
+ return ShouldLog(LOG_FILTER_GENERAL, level);
- if (arenaLogFile)
- {
- va_list ap;
- outTimestamp(arenaLogFile);
- va_start(ap, str);
- vfprintf(arenaLogFile, str, ap);
- fprintf(arenaLogFile, "\n");
- va_end(ap);
- fflush(arenaLogFile);
- }
+ return false;
}
-void Log::outSQLDriver(const char* str, ...)
+void Log::outTrace(LogFilterType filter, const char * str, ...)
{
- if (!str)
+ if (!str || !ShouldLog(filter, LOG_LEVEL_TRACE))
return;
va_list ap;
va_start(ap, str);
- vutf8printf(stdout, str, &ap);
- va_end(ap);
-
- printf("\n");
-
- if (sqlLogFile)
- {
- outTimestamp(sqlLogFile);
-
- va_list apSQL;
- va_start(apSQL, str);
- vfprintf(sqlLogFile, str, apSQL);
- va_end(apSQL);
-
- fprintf(sqlLogFile, "\n");
- fflush(sqlLogFile);
- }
-
- fflush(stdout);
-}
-
-void Log::outErrorDb(const char * err, ...)
-{
- if (!err)
- return;
-
- if (m_colored)
- SetColor(false, LRED);
- va_list ap;
+ vlog(filter, LOG_LEVEL_TRACE, str, ap);
- va_start(ap, err);
- vutf8printf(stderr, err, &ap);
va_end(ap);
-
- if (m_colored)
- ResetColor(false);
-
- fprintf( stderr, "\n" );
-
- if (logfile)
- {
- outTimestamp(logfile);
- fprintf(logfile, "ERROR: " );
-
- va_start(ap, err);
- vfprintf(logfile, err, ap);
- va_end(ap);
-
- fprintf(logfile, "\n" );
- fflush(logfile);
- }
-
- if (dberLogfile)
- {
- outTimestamp(dberLogfile);
- va_start(ap, err);
- vfprintf(dberLogfile, err, ap);
- va_end(ap);
-
- fprintf(dberLogfile, "\n" );
- fflush(dberLogfile);
- }
- fflush(stderr);
}
-void Log::outBasic(const char * str, ...)
+void Log::outDebug(LogFilterType filter, const char * str, ...)
{
- if (!str)
+ if (!str || !ShouldLog(filter, LOG_LEVEL_DEBUG))
return;
- if (m_enableLogDB && m_dbLogLevel > LOGL_NORMAL)
- {
- va_list ap2;
- va_start(ap2, str);
- char nnew_str[MAX_QUERY_LEN];
- vsnprintf(nnew_str, MAX_QUERY_LEN, str, ap2);
- outDB(LOG_TYPE_BASIC, nnew_str);
- va_end(ap2);
- }
-
- if (m_logLevel > LOGL_NORMAL)
- {
- if (m_colored)
- SetColor(true, m_colors[LOGL_BASIC]);
-
- va_list ap;
- va_start(ap, str);
- vutf8printf(stdout, str, &ap);
- va_end(ap);
-
- if (m_colored)
- ResetColor(true);
-
- printf("\n");
-
- if (logfile)
- {
- outTimestamp(logfile);
- va_list ap2;
- va_start(ap2, str);
- vfprintf(logfile, str, ap2);
- fprintf(logfile, "\n" );
- va_end(ap2);
- fflush(logfile);
- }
- }
- fflush(stdout);
-}
-
-void Log::outDetail(const char * str, ...)
-{
- if (!str)
- return;
-
- if (m_enableLogDB && m_dbLogLevel > LOGL_BASIC)
- {
- va_list ap2;
- va_start(ap2, str);
- char nnew_str[MAX_QUERY_LEN];
- vsnprintf(nnew_str, MAX_QUERY_LEN, str, ap2);
- outDB(LOG_TYPE_DETAIL, nnew_str);
- va_end(ap2);
- }
-
- if (m_logLevel > LOGL_BASIC)
- {
- if (m_colored)
- SetColor(true, m_colors[LOGL_DETAIL]);
-
- va_list ap;
- va_start(ap, str);
- vutf8printf(stdout, str, &ap);
- va_end(ap);
-
- if (m_colored)
- ResetColor(true);
+ va_list ap;
+ va_start(ap, str);
- printf("\n");
+ vlog(filter, LOG_LEVEL_DEBUG, str, ap);
- if (logfile)
- {
- outTimestamp(logfile);
- va_list ap2;
- va_start(ap2, str);
- vfprintf(logfile, str, ap2);
- va_end(ap2);
-
- fprintf(logfile, "\n");
- fflush(logfile);
- }
- }
-
- fflush(stdout);
+ va_end(ap);
}
-void Log::outDebugInLine(const char * str, ...)
+void Log::outInfo(LogFilterType filter, const char * str, ...)
{
- if (!str)
+ if (!str || !ShouldLog(filter, LOG_LEVEL_INFO))
return;
- if (m_logLevel > LOGL_DETAIL)
- {
- va_list ap;
- va_start(ap, str);
- vutf8printf(stdout, str, &ap);
- va_end(ap);
+ va_list ap;
+ va_start(ap, str);
- //if (m_colored)
- // ResetColor(true);
+ vlog(filter, LOG_LEVEL_INFO, str, ap);
- if (logfile)
- {
- va_list ap2;
- va_start(ap2, str);
- vfprintf(logfile, str, ap2);
- va_end(ap2);
- }
- }
+ va_end(ap);
}
-void Log::outSQLDev(const char* str, ...)
+void Log::outWarn(LogFilterType filter, const char * str, ...)
{
- if (!str)
+ if (!str || !ShouldLog(filter, LOG_LEVEL_WARN))
return;
va_list ap;
va_start(ap, str);
- vutf8printf(stdout, str, &ap);
- va_end(ap);
- printf("\n");
+ vlog(filter, LOG_LEVEL_WARN, str, ap);
- if (sqlDevLogFile)
- {
- va_list ap2;
- va_start(ap2, str);
- vfprintf(sqlDevLogFile, str, ap2);
- va_end(ap2);
-
- fprintf(sqlDevLogFile, "\n");
- fflush(sqlDevLogFile);
- }
-
- fflush(stdout);
+ va_end(ap);
}
-void Log::outDebug(DebugLogFilters f, const char * str, ...)
+void Log::outError(LogFilterType filter, const char * str, ...)
{
- if (!(m_DebugLogMask & f))
- return;
-
- if (!str)
+ if (!str || !ShouldLog(filter, LOG_LEVEL_ERROR))
return;
- if (m_enableLogDB && m_dbLogLevel > LOGL_DETAIL)
- {
- va_list ap2;
- va_start(ap2, str);
- char nnew_str[MAX_QUERY_LEN];
- vsnprintf(nnew_str, MAX_QUERY_LEN, str, ap2);
- outDB(LOG_TYPE_DEBUG, nnew_str);
- va_end(ap2);
- }
-
- if ( m_logLevel > LOGL_DETAIL )
- {
- if (m_colored)
- SetColor(true, m_colors[LOGL_DEBUG]);
-
- va_list ap;
- va_start(ap, str);
- vutf8printf(stdout, str, &ap);
- va_end(ap);
-
- if (m_colored)
- ResetColor(true);
+ va_list ap;
+ va_start(ap, str);
- printf( "\n" );
+ vlog(filter, LOG_LEVEL_ERROR, str, ap);
- if (logfile)
- {
- outTimestamp(logfile);
- va_list ap2;
- va_start(ap2, str);
- vfprintf(logfile, str, ap2);
- va_end(ap2);
-
- fprintf(logfile, "\n" );
- fflush(logfile);
- }
- }
- fflush(stdout);
+ va_end(ap);
}
-void Log::outStaticDebug(const char * str, ...)
+void Log::outFatal(LogFilterType filter, const char * str, ...)
{
- if (!str)
+ if (!str || !ShouldLog(filter, LOG_LEVEL_FATAL))
return;
- if (m_enableLogDB && m_dbLogLevel > LOGL_DETAIL)
- {
- va_list ap2;
- va_start(ap2, str);
- char nnew_str[MAX_QUERY_LEN];
- vsnprintf(nnew_str, MAX_QUERY_LEN, str, ap2);
- outDB(LOG_TYPE_DEBUG, nnew_str);
- va_end(ap2);
- }
-
- if ( m_logLevel > LOGL_DETAIL )
- {
- if (m_colored)
- SetColor(true, m_colors[LOGL_DEBUG]);
-
- va_list ap;
- va_start(ap, str);
- vutf8printf(stdout, str, &ap);
- va_end(ap);
-
- if (m_colored)
- ResetColor(true);
+ va_list ap;
+ va_start(ap, str);
- printf( "\n" );
+ vlog(filter, LOG_LEVEL_FATAL, str, ap);
- if (logfile)
- {
- outTimestamp(logfile);
- va_list ap2;
- va_start(ap2, str);
- vfprintf(logfile, str, ap2);
- va_end(ap2);
-
- fprintf(logfile, "\n" );
- fflush(logfile);
- }
- }
- fflush(stdout);
+ va_end(ap);
}
-void Log::outStringInLine(const char * str, ...)
+void Log::outCommand(uint32 account, const char * str, ...)
{
- if (!str)
+ if (!str || !ShouldLog(LOG_FILTER_GMCOMMAND, LOG_LEVEL_INFO))
return;
va_list ap;
-
va_start(ap, str);
- vutf8printf(stdout, str, &ap);
+ char text[MAX_QUERY_LEN];
+ vsnprintf(text, MAX_QUERY_LEN, str, ap);
va_end(ap);
- if (logfile)
- {
- va_start(ap, str);
- vfprintf(logfile, str, ap);
- va_end(ap);
- }
-}
-
-void Log::outCommand(uint32 account, const char * str, ...)
-{
- if (!str)
- return;
-
- // TODO: support accountid
- if (m_enableLogDB && m_dbGM)
- {
- va_list ap2;
- va_start(ap2, str);
- char nnew_str[MAX_QUERY_LEN];
- vsnprintf(nnew_str, MAX_QUERY_LEN, str, ap2);
- outDB(LOG_TYPE_GM, nnew_str);
- va_end(ap2);
- }
-
- if (m_logLevel > LOGL_NORMAL)
- {
- if (m_colored)
- SetColor(true, m_colors[LOGL_BASIC]);
-
- va_list ap;
- va_start(ap, str);
- vutf8printf(stdout, str, &ap);
- va_end(ap);
+ LogMessage* msg = new LogMessage(LOG_LEVEL_INFO, LOG_FILTER_GMCOMMAND, text);
+ msg->param1 = account;
- if (m_colored)
- ResetColor(true);
-
- printf("\n");
-
- if (logfile)
- {
- outTimestamp(logfile);
- va_list ap2;
- va_start(ap2, str);
- vfprintf(logfile, str, ap2);
- fprintf(logfile, "\n" );
- va_end(ap2);
- fflush(logfile);
- }
- }
-
- if (m_gmlog_per_account)
- {
- if (FILE* per_file = openGmlogPerAccount (account))
- {
- outTimestamp(per_file);
- va_list ap;
- va_start(ap, str);
- vfprintf(per_file, str, ap);
- fprintf(per_file, "\n" );
- va_end(ap);
- fclose(per_file);
- }
- }
- else if (gmLogfile)
- {
- outTimestamp(gmLogfile);
- va_list ap;
- va_start(ap, str);
- vfprintf(gmLogfile, str, ap);
- fprintf(gmLogfile, "\n" );
- va_end(ap);
- fflush(gmLogfile);
- }
-
- fflush(stdout);
+ write(msg);
}
-void Log::outChar(const char * str, ...)
+void Log::SetRealmID(uint32 id)
{
- if (!str)
- return;
-
- if (m_enableLogDB && m_dbChar)
- {
- va_list ap2;
- va_start(ap2, str);
- char nnew_str[MAX_QUERY_LEN];
- vsnprintf(nnew_str, MAX_QUERY_LEN, str, ap2);
- outDB(LOG_TYPE_CHAR, nnew_str);
- va_end(ap2);
- }
-
- if (charLogfile)
- {
- outTimestamp(charLogfile);
- va_list ap;
- va_start(ap, str);
- vfprintf(charLogfile, str, ap);
- fprintf(charLogfile, "\n" );
- va_end(ap);
- fflush(charLogfile);
- }
-}
-
-void Log::outCharDump(const char * str, uint32 account_id, uint32 guid, const char * name)
-{
- FILE* file = NULL;
- if (m_charLog_Dump_Separate)
- {
- char fileName[29]; // Max length: name(12) + guid(11) + _.log (5) + \0
- snprintf(fileName, 29, "%d_%s.log", guid, name);
- std::string sFileName(m_dumpsDir);
- sFileName.append(fileName);
- file = fopen((m_logsDir + sFileName).c_str(), "w");
- }
- else
- file = charLogfile;
- if (file)
- {
- fprintf(file, "== START DUMP == (account: %u guid: %u name: %s )\n%s\n== END DUMP ==\n",
- account_id, guid, name, str);
- fflush(file);
- if (m_charLog_Dump_Separate)
- fclose(file);
- }
-}
-
-void Log::outRemote(const char * str, ...)
-{
- if (!str)
- return;
-
- if (m_enableLogDB && m_dbRA)
- {
- va_list ap2;
- va_start(ap2, str);
- char nnew_str[MAX_QUERY_LEN];
- vsnprintf(nnew_str, MAX_QUERY_LEN, str, ap2);
- outDB(LOG_TYPE_RA, nnew_str);
- va_end(ap2);
- }
-
- if (raLogfile)
- {
- outTimestamp(raLogfile);
- va_list ap;
- va_start(ap, str);
- vfprintf(raLogfile, str, ap);
- fprintf(raLogfile, "\n" );
- va_end(ap);
- fflush(raLogfile);
- }
+ realm = id;
}
-void Log::outChat(const char * str, ...)
+void Log::Close()
{
- if (!str)
- return;
-
- if (m_enableLogDB && m_dbChat)
- {
- va_list ap2;
- va_start(ap2, str);
- char nnew_str[MAX_QUERY_LEN];
- vsnprintf(nnew_str, MAX_QUERY_LEN, str, ap2);
- outDB(LOG_TYPE_CHAT, nnew_str);
- va_end(ap2);
- }
-
- if (chatLogfile)
- {
- outTimestamp(chatLogfile);
- va_list ap;
- va_start(ap, str);
- vfprintf(chatLogfile, str, ap);
- fprintf(chatLogfile, "\n" );
- fflush(chatLogfile);
- va_end(ap);
- }
-}
-
-void Log::outErrorST(const char * str, ...)
-{
- va_list ap;
- va_start(ap, str);
- char nnew_str[MAX_QUERY_LEN];
- vsnprintf(nnew_str, MAX_QUERY_LEN, str, ap);
- va_end(ap);
-
- ACE_Stack_Trace st;
- outError("%s [Stacktrace: %s]", nnew_str, st.c_str());
-}
-
-void Log::outWarden(const char * str, ...)
-{
- if (!str)
- return;
-
- if (wardenLogFile)
+ for (AppenderMap::iterator it = appenders.begin(); it != appenders.end(); ++it)
{
- outTimestamp(wardenLogFile);
- va_list ap;
- va_start(ap, str);
- vfprintf(wardenLogFile, str, ap);
- fprintf(wardenLogFile, "\n" );
- fflush(wardenLogFile);
- va_end(ap);
+ delete it->second;
+ it->second = NULL;
}
+ appenders.clear();
+ delete worker;
+ worker = NULL;
}
diff --git a/src/server/shared/Logging/Log.h b/src/server/shared/Logging/Log.h
index 296c13d86c9..5e2b7972dc8 100755
--- a/src/server/shared/Logging/Log.h
+++ b/src/server/shared/Logging/Log.h
@@ -19,196 +19,69 @@
#ifndef TRINITYCORE_LOG_H
#define TRINITYCORE_LOG_H
-#include "Common.h"
-#include <ace/Singleton.h>
-
-class Config;
+#include "Define.h"
+#include "Appender.h"
+#include "LogWorker.h"
+#include "Logger.h"
-enum DebugLogFilters
-{
- LOG_FILTER_NONE = 0x00000000,
- LOG_FILTER_UNITS = 0x00000001, // Anything related to units that doesn't fit in other categories. ie. creature formations
- LOG_FILTER_PETS = 0x00000002,
- LOG_FILTER_VEHICLES = 0x00000004,
- LOG_FILTER_TSCR = 0x00000008, // C++ AI, instance scripts, etc.
- LOG_FILTER_DATABASE_AI = 0x00000010, // SmartAI, EventAI, CreatureAI
- LOG_FILTER_MAPSCRIPTS = 0x00000020,
- LOG_FILTER_NETWORKIO = 0x00000040, // Anything packet/netcode related
- LOG_FILTER_SPELLS_AURAS = 0x00000080,
- LOG_FILTER_ACHIEVEMENTSYS = 0x00000100,
- LOG_FILTER_CONDITIONSYS = 0x00000200,
- LOG_FILTER_POOLSYS = 0x00000400,
- LOG_FILTER_AUCTIONHOUSE = 0x00000800,
- LOG_FILTER_BATTLEGROUND = 0x00001000, // Anything related to arena's and battlegrounds
- LOG_FILTER_OUTDOORPVP = 0x00002000,
- LOG_FILTER_CHATSYS = 0x00004000,
- LOG_FILTER_LFG = 0x00008000,
- LOG_FILTER_MAPS = 0x00010000, // Maps, instances, grids, cells, visibility
- LOG_FILTER_PLAYER_LOADING = 0x00020000, // Debug output from Player::_Load functions
- LOG_FILTER_PLAYER_ITEMS = 0x00040000, // Anything item related
- LOG_FILTER_PLAYER_SKILLS = 0x00080000, // Skills related
- LOG_FILTER_LOOT = 0x00100000, // Loot related
- LOG_FILTER_GUILD = 0x00200000, // Guild related
- LOG_FILTER_TRANSPORTS = 0x00400000, // Transport related
- LOG_FILTER_WARDEN = 0x00800000, // Warden related
-};
-
-enum LogTypes
-{
- LOG_TYPE_STRING = 0,
- LOG_TYPE_ERROR = 1,
- LOG_TYPE_BASIC = 2,
- LOG_TYPE_DETAIL = 3,
- LOG_TYPE_DEBUG = 4,
- LOG_TYPE_CHAR = 5,
- LOG_TYPE_WORLD = 6,
- LOG_TYPE_RA = 7,
- LOG_TYPE_GM = 8,
- LOG_TYPE_CRASH = 9,
- LOG_TYPE_CHAT = 10,
- MAX_LOG_TYPES
-};
-
-enum LogLevel
-{
- LOGL_NORMAL = 0,
- LOGL_BASIC,
- LOGL_DETAIL,
- LOGL_DEBUG
-};
-
-const int LogLevels = int(LOGL_DEBUG)+1;
-
-enum ColorTypes
-{
- BLACK,
- RED,
- GREEN,
- BROWN,
- BLUE,
- MAGENTA,
- CYAN,
- GREY,
- YELLOW,
- LRED,
- LGREEN,
- LBLUE,
- LMAGENTA,
- LCYAN,
- WHITE
-};
+#include <ace/Singleton.h>
-const int Colors = int(WHITE)+1;
+#include <string>
+#include <set>
class Log
{
friend class ACE_Singleton<Log, ACE_Thread_Mutex>;
+ typedef std::map<uint8, Logger> LoggerMap;
+
private:
Log();
~Log();
public:
- void Initialize();
-
- void ReloadConfig();
-
- void InitColors(const std::string& init_str);
- void SetColor(bool stdout_stream, ColorTypes color);
- void ResetColor(bool stdout_stream);
-
- void outErrorST(const char * err, ...) ATTR_PRINTF(2, 3);
- void outDB(LogTypes type, const char * str);
- void outString(const char * str, ...) ATTR_PRINTF(2, 3);
- void outString();
- void outStringInLine(const char * str, ...) ATTR_PRINTF(2, 3);
- void outError(const char * err, ...) ATTR_PRINTF(2, 3);
- void outCrash(const char * err, ...) ATTR_PRINTF(2, 3);
- void outBasic(const char * str, ...) ATTR_PRINTF(2, 3);
- void outDetail(const char * str, ...) ATTR_PRINTF(2, 3);
- void outSQLDev(const char * str, ...) ATTR_PRINTF(2, 3);
- void outDebug(DebugLogFilters f, const char* str, ...) ATTR_PRINTF(3, 4);
- void outStaticDebug(const char * str, ...) ATTR_PRINTF(2, 3);
- void outDebugInLine(const char * str, ...) ATTR_PRINTF(2, 3);
- void outErrorDb(const char * str, ...) ATTR_PRINTF(2, 3);
- void outChar(const char * str, ...) ATTR_PRINTF(2, 3);
- void outCommand(uint32 account, const char * str, ...) ATTR_PRINTF(3, 4);
- void outRemote(const char * str, ...) ATTR_PRINTF(2, 3);
- void outChat(const char * str, ...) ATTR_PRINTF(2, 3);
- void outArena(const char * str, ...) ATTR_PRINTF(2, 3);
- void outSQLDriver(const char* str, ...) ATTR_PRINTF(2, 3);
- void outWarden(const char * str, ...) ATTR_PRINTF(2, 3);
- void outCharDump(const char * str, uint32 account_id, uint32 guid, const char * name);
-
- static void outTimestamp(FILE* file);
- static std::string GetTimestampStr();
+ void Close();
+ bool ShouldLog(LogFilterType type, LogLevel level) const;
+ bool SetLogLevel(std::string const& name, char const* level, bool isLogger = true);
- void SetLogLevel(char * Level);
- void SetLogFileLevel(char * Level);
- void SetDBLogLevel(char * Level);
- void SetSQLDriverQueryLogging(bool newStatus) { m_sqlDriverQueryLogging = newStatus; }
- void SetRealmID(uint32 id) { realm = id; }
+ void log(LogFilterType f, LogLevel level, char const* str, ...) ATTR_PRINTF(4,5);
+
+ void outTrace(LogFilterType f, char const* str, ...) ATTR_PRINTF(3,4);
+ void outDebug(LogFilterType f, char const* str, ...) ATTR_PRINTF(3,4);
+ void outInfo(LogFilterType f, char const* str, ...) ATTR_PRINTF(3,4);
+ void outWarn(LogFilterType f, char const* str, ...) ATTR_PRINTF(3,4);
+ void outError(LogFilterType f, char const* str, ...) ATTR_PRINTF(3,4);
+ void outFatal(LogFilterType f, char const* str, ...) ATTR_PRINTF(3,4);
+
+ void EnableDBAppenders();
+ void outCommand(uint32 account, const char * str, ...) ATTR_PRINTF(3, 4);
+ static std::string GetTimestampStr();
- bool IsOutDebug() const { return m_logLevel > 2 || (m_logFileLevel > 2 && logfile); }
- bool IsOutCharDump() const { return m_charLog_Dump; }
+ void SetRealmID(uint32 id);
- bool GetLogDB() const { return m_enableLogDB; }
- bool GetLogDBLater() const { return m_enableLogDBLater; }
- void SetLogDB(bool enable) { m_enableLogDB = enable; }
- void SetLogDBLater(bool value) { m_enableLogDBLater = value; }
- bool GetSQLDriverQueryLogging() const { return m_sqlDriverQueryLogging; }
private:
- FILE* openLogFile(char const* configFileName, char const* configTimeStampFlag, char const* mode);
- FILE* openGmlogPerAccount(uint32 account);
-
- FILE* raLogfile;
- FILE* logfile;
- FILE* gmLogfile;
- FILE* charLogfile;
- FILE* dberLogfile;
- FILE* chatLogfile;
- FILE* arenaLogFile;
- FILE* sqlLogFile;
- FILE* sqlDevLogFile;
- FILE* wardenLogFile;
-
- // cache values for after initilization use (like gm log per account case)
+ void vlog(LogFilterType f, LogLevel level, char const* str, va_list argptr);
+ void write(LogMessage* msg);
+
+ Logger* GetLoggerByType(LogFilterType filter);
+ Appender* GetAppenderByName(std::string const& name);
+ uint8 NextAppenderId();
+ void CreateAppenderFromConfig(const char* name);
+ void CreateLoggerFromConfig(const char* name);
+ void ReadAppendersFromConfig();
+ void ReadLoggersFromConfig();
+
+ AppenderMap appenders;
+ LoggerMap loggers;
+ uint8 AppenderId;
+
std::string m_logsDir;
std::string m_logsTimestamp;
- // gm log control
- bool m_gmlog_per_account;
- std::string m_gmlog_filename_format;
-
- bool m_enableLogDBLater;
- bool m_enableLogDB;
uint32 realm;
-
- // log coloring
- bool m_colored;
- ColorTypes m_colors[4];
-
- // log levels:
- // false: errors only, true: full query logging
- bool m_sqlDriverQueryLogging;
-
- // log levels:
- // 0 minimum/string, 1 basic/error, 2 detail, 3 full/debug
- uint8 m_dbLogLevel;
- uint8 m_logLevel;
- uint8 m_logFileLevel;
- bool m_dbChar;
- bool m_dbRA;
- bool m_dbGM;
- bool m_dbChat;
- bool m_charLog_Dump;
- bool m_charLog_Dump_Separate;
- std::string m_dumpsDir;
-
- DebugLogFilters m_DebugLogMask;
+ LogWorker* worker;
};
#define sLog ACE_Singleton<Log, ACE_Thread_Mutex>::instance()
#endif
-
diff --git a/src/server/shared/Logging/LogOperation.cpp b/src/server/shared/Logging/LogOperation.cpp
new file mode 100644
index 00000000000..59368e519cd
--- /dev/null
+++ b/src/server/shared/Logging/LogOperation.cpp
@@ -0,0 +1,14 @@
+#include "LogOperation.h"
+#include "Logger.h"
+
+LogOperation::~LogOperation()
+{
+ delete msg;
+}
+
+int LogOperation::call()
+{
+ if (logger && msg)
+ logger->write(*msg);
+ return 0;
+}
diff --git a/src/server/shared/Logging/LogOperation.h b/src/server/shared/Logging/LogOperation.h
new file mode 100644
index 00000000000..046ff44e62e
--- /dev/null
+++ b/src/server/shared/Logging/LogOperation.h
@@ -0,0 +1,24 @@
+#ifndef LOGOPERATION_H
+#define LOGOPERATION_H
+
+class Logger;
+struct LogMessage;
+
+class LogOperation
+{
+ public:
+ LogOperation(Logger* _logger, LogMessage* _msg)
+ : logger(_logger)
+ , msg(_msg)
+ { }
+
+ ~LogOperation();
+
+ int call();
+
+ protected:
+ Logger *logger;
+ LogMessage *msg;
+};
+
+#endif
diff --git a/src/server/shared/Logging/LogWorker.cpp b/src/server/shared/Logging/LogWorker.cpp
new file mode 100644
index 00000000000..4dc71f7f878
--- /dev/null
+++ b/src/server/shared/Logging/LogWorker.cpp
@@ -0,0 +1,33 @@
+#include "LogWorker.h"
+
+LogWorker::LogWorker()
+ : m_queue(HIGH_WATERMARK, LOW_WATERMARK)
+{
+ ACE_Task_Base::activate(THR_NEW_LWP | THR_JOINABLE | THR_INHERIT_SCHED, 1);
+}
+
+LogWorker::~LogWorker()
+{
+ m_queue.deactivate();
+ wait();
+}
+
+int LogWorker::enqueue(LogOperation* op)
+{
+ return m_queue.enqueue(op);
+}
+
+int LogWorker::svc()
+{
+ while (1)
+ {
+ LogOperation* request;
+ if (m_queue.dequeue(request) == -1)
+ break;
+
+ request->call();
+ delete request;
+ }
+
+ return 0;
+}
diff --git a/src/server/shared/Logging/LogWorker.h b/src/server/shared/Logging/LogWorker.h
new file mode 100644
index 00000000000..fe51be5376c
--- /dev/null
+++ b/src/server/shared/Logging/LogWorker.h
@@ -0,0 +1,30 @@
+#ifndef LOGWORKER_H
+#define LOGWORKER_H
+
+#include "LogOperation.h"
+
+#include <ace/Task.h>
+#include <ace/Activation_Queue.h>
+
+class LogWorker: protected ACE_Task_Base
+{
+ public:
+ LogWorker();
+ ~LogWorker();
+
+ typedef ACE_Message_Queue_Ex<LogOperation, ACE_MT_SYNCH> LogMessageQueueType;
+
+ enum
+ {
+ HIGH_WATERMARK = 8 * 1024 * 1024,
+ LOW_WATERMARK = 8 * 1024 * 1024
+ };
+
+ int enqueue(LogOperation *op);
+
+ private:
+ virtual int svc();
+ LogMessageQueueType m_queue;
+};
+
+#endif
diff --git a/src/server/shared/Logging/Logger.cpp b/src/server/shared/Logging/Logger.cpp
new file mode 100644
index 00000000000..7464012c0ac
--- /dev/null
+++ b/src/server/shared/Logging/Logger.cpp
@@ -0,0 +1,67 @@
+#include "Logger.h"
+
+Logger::Logger(): name(""), type(LOG_FILTER_GENERAL), level(LOG_LEVEL_DISABLED)
+{
+}
+
+void Logger::Create(std::string const& _name, LogFilterType _type, LogLevel _level)
+{
+ name = _name;
+ type = _type;
+ level = _level;
+}
+
+Logger::~Logger()
+{
+ for (AppenderMap::iterator it = appenders.begin(); it != appenders.end(); ++it)
+ it->second = NULL;
+ appenders.clear();
+}
+
+std::string const& Logger::getName() const
+{
+ return name;
+}
+
+LogFilterType Logger::getType() const
+{
+ return type;
+}
+
+LogLevel Logger::getLogLevel() const
+{
+ return level;
+}
+
+void Logger::addAppender(uint8 id, Appender* appender)
+{
+ appenders[id] = appender;
+}
+
+void Logger::delAppender(uint8 id)
+{
+ AppenderMap::iterator it = appenders.find(id);
+ if (it != appenders.end())
+ {
+ it->second = NULL;
+ appenders.erase(it);
+ }
+}
+
+void Logger::setLogLevel(LogLevel _level)
+{
+ level = _level;
+}
+
+void Logger::write(LogMessage& message)
+{
+ if (!level || level > message.level || message.text.empty())
+ {
+ //fprintf(stderr, "Logger::write: Logger %s, Level %u. Msg %s Level %u WRONG LEVEL MASK OR EMPTY MSG\n", getName().c_str(), messge.level, message.text.c_str(), .message.level); // DEBUG - RemoveMe
+ return;
+ }
+
+ for (AppenderMap::iterator it = appenders.begin(); it != appenders.end(); ++it)
+ if (it->second)
+ it->second->write(message);
+}
diff --git a/src/server/shared/Logging/Logger.h b/src/server/shared/Logging/Logger.h
new file mode 100644
index 00000000000..10b3991a537
--- /dev/null
+++ b/src/server/shared/Logging/Logger.h
@@ -0,0 +1,29 @@
+#ifndef LOGGER_H
+#define LOGGER_H
+
+#include "Appender.h"
+
+class Logger
+{
+ public:
+ Logger();
+ ~Logger();
+
+ void Create(std::string const& name, LogFilterType type, LogLevel level);
+ void addAppender(uint8 type, Appender *);
+ void delAppender(uint8 type);
+
+ std::string const& getName() const;
+ LogFilterType getType() const;
+ LogLevel getLogLevel() const;
+ void setLogLevel(LogLevel level);
+ void write(LogMessage& message);
+
+ private:
+ std::string name;
+ LogFilterType type;
+ LogLevel level;
+ AppenderMap appenders;
+};
+
+#endif