aboutsummaryrefslogtreecommitdiff
path: root/src/server/shared/Logging
diff options
context:
space:
mode:
Diffstat (limited to 'src/server/shared/Logging')
-rw-r--r--src/server/shared/Logging/Appender.cpp224
-rw-r--r--src/server/shared/Logging/Appender.h156
-rw-r--r--src/server/shared/Logging/AppenderConsole.cpp193
-rw-r--r--src/server/shared/Logging/AppenderConsole.h59
-rw-r--r--src/server/shared/Logging/AppenderDB.cpp55
-rw-r--r--src/server/shared/Logging/AppenderDB.h36
-rw-r--r--src/server/shared/Logging/AppenderFile.cpp74
-rw-r--r--src/server/shared/Logging/AppenderFile.h40
-rwxr-xr-xsrc/server/shared/Logging/Log.cpp1183
-rwxr-xr-xsrc/server/shared/Logging/Log.h211
-rw-r--r--src/server/shared/Logging/LogOperation.cpp31
-rw-r--r--src/server/shared/Logging/LogOperation.h41
-rw-r--r--src/server/shared/Logging/LogWorker.cpp50
-rw-r--r--src/server/shared/Logging/LogWorker.h47
-rw-r--r--src/server/shared/Logging/Logger.cpp84
-rw-r--r--src/server/shared/Logging/Logger.h46
16 files changed, 1487 insertions, 1043 deletions
diff --git a/src/server/shared/Logging/Appender.cpp b/src/server/shared/Logging/Appender.cpp
new file mode 100644
index 00000000000..348ec4b3c7c
--- /dev/null
+++ b/src/server/shared/Logging/Appender.cpp
@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
+ *
+ * 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
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#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 */, AppenderFlags _flags /* = APPENDER_FLAGS_NONE */):
+id(_id), name(_name), type(_type), level(_level), flags(_flags)
+{
+}
+
+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;
+}
+
+AppenderFlags Appender::getFlags() const
+{
+ return flags;
+}
+
+void Appender::setLogLevel(LogLevel _level)
+{
+ level = _level;
+}
+
+void Appender::write(LogMessage& message)
+{
+ if (!level || level > message.level)
+ {
+ //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
+ return;
+ }
+
+ message.prefix.clear();
+ if (flags & APPENDER_FLAGS_PREFIX_TIMESTAMP)
+ message.prefix.append(message.getTimeStr().c_str());
+
+ if (flags & APPENDER_FLAGS_PREFIX_LOGLEVEL)
+ {
+ if (!message.prefix.empty())
+ message.prefix.push_back(' ');
+
+ char text[MAX_QUERY_LEN];
+ snprintf(text, MAX_QUERY_LEN, "%-5s", Appender::getLogLevelString(message.level));
+ message.prefix.append(text);
+ }
+
+ if (flags & APPENDER_FLAGS_PREFIX_LOGFILTERTYPE)
+ {
+ if (!message.prefix.empty())
+ message.prefix.push_back(' ');
+
+ char text[MAX_QUERY_LEN];
+ snprintf(text, MAX_QUERY_LEN, "[%s]", Appender::getLogFilterTypeString(message.type));
+ message.prefix.append(text);
+ }
+
+ if (!message.prefix.empty())
+ message.prefix.push_back(' ');
+
+ _write(message);
+}
+
+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";
+ case LOG_FILTER_CALENDAR:
+ return "CALENDAR";
+ case LOG_FILTER_CHARACTER:
+ return "CHARACTER";
+ case LOG_FILTER_ARENAS:
+ return "ARENAS";
+ case LOG_FILTER_SQL_DRIVER:
+ return "SQL DRIVER";
+ case LOG_FILTER_SQL_DEV:
+ return "SQL DEV";
+ case LOG_FILTER_PLAYER_DUMP:
+ return "PLAYER DUMP";
+ case LOG_FILTER_BATTLEFIELD:
+ return "BATTLEFIELD";
+ case LOG_FILTER_SERVER_LOADING:
+ return "SERVER LOADING";
+ case LOG_FILTER_OPCODES:
+ return "OPCODE";
+ 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..c0e03b13db1
--- /dev/null
+++ b/src/server/shared/Logging/Appender.h
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
+ *
+ * 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
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef APPENDER_H
+#define APPENDER_H
+
+#include "Define.h"
+#include <time.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,
+ LOG_FILTER_CHARACTER,
+ LOG_FILTER_ARENAS,
+ LOG_FILTER_SQL_DRIVER,
+ LOG_FILTER_SQL_DEV,
+ LOG_FILTER_PLAYER_DUMP,
+ LOG_FILTER_BATTLEFIELD,
+ LOG_FILTER_SERVER_LOADING,
+ LOG_FILTER_OPCODES
+};
+
+const uint8 MaxLogFilter = uint8(LOG_FILTER_OPCODES) + 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,
+};
+
+enum AppenderFlags
+{
+ APPENDER_FLAGS_NONE = 0x00,
+ APPENDER_FLAGS_PREFIX_TIMESTAMP = 0x01,
+ APPENDER_FLAGS_PREFIX_LOGLEVEL = 0x02,
+ APPENDER_FLAGS_PREFIX_LOGFILTERTYPE = 0x04,
+ APPENDER_FLAGS_USE_TIMESTAMP = 0x08, // only used by FileAppender
+ APPENDER_FLAGS_MAKE_FILE_BACKUP = 0x10 // only used by FileAppender
+};
+
+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;
+ std::string prefix;
+ std::string param1;
+ time_t mtime;
+};
+
+class Appender
+{
+ public:
+ Appender(uint8 _id, std::string const& name, AppenderType type = APPENDER_NONE, LogLevel level = LOG_LEVEL_DISABLED, AppenderFlags flags = APPENDER_FLAGS_NONE);
+ virtual ~Appender();
+
+ uint8 getId() const;
+ std::string const& getName() const;
+ AppenderType getType() const;
+ LogLevel getLogLevel() const;
+ AppenderFlags getFlags() 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*/) = 0;
+
+ uint8 id;
+ std::string name;
+ AppenderType type;
+ LogLevel level;
+ AppenderFlags flags;
+};
+
+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..839f8512ad7
--- /dev/null
+++ b/src/server/shared/Logging/AppenderConsole.cpp
@@ -0,0 +1,193 @@
+/*
+ * Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
+ *
+ * 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
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "AppenderConsole.h"
+#include "Config.h"
+#include "Util.h"
+
+#include <sstream>
+
+AppenderConsole::AppenderConsole(uint8 id, std::string const& name, LogLevel level, AppenderFlags flags):
+Appender(id, name, APPENDER_CONSOLE, level, flags), _colored(false)
+{
+ for (uint8 i = 0; i < MaxLogLevels; ++i)
+ _colors[i] = ColorTypes(MaxColors);
+}
+
+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%s", message.prefix.c_str(), message.text.c_str());
+ ResetColor(stdout_stream);
+ }
+ else
+ utf8printf(stdout_stream ? stdout : stderr, "%s%s", message.prefix.c_str(), 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..ad7d9543cdb
--- /dev/null
+++ b/src/server/shared/Logging/AppenderConsole.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
+ *
+ * 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
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#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, AppenderFlags flags);
+ 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..d85a4db9f7a
--- /dev/null
+++ b/src/server/shared/Logging/AppenderDB.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
+ *
+ * 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
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "AppenderDB.h"
+#include "Database/DatabaseEnv.h"
+
+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)
+{
+ if (!enable)
+ return;
+ switch (message.type)
+ {
+ case LOG_FILTER_SQL:
+ case LOG_FILTER_SQL_DRIVER:
+ case LOG_FILTER_SQL_DEV:
+ break; // Avoid infinite loop, PExecute triggers Logging with LOG_FILTER_SQL type
+ default:
+ PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_LOG);
+ stmt->setUInt64(0, message.mtime);
+ stmt->setUInt32(1, realm);
+ stmt->setUInt8(2, message.type);
+ stmt->setUInt8(3, message.level);
+ stmt->setString(4, message.text);
+ LoginDatabase.Execute(stmt);
+ break;
+ }
+}
+
+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..4399195b181
--- /dev/null
+++ b/src/server/shared/Logging/AppenderDB.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
+ *
+ * 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
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#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..67adff39aae
--- /dev/null
+++ b/src/server/shared/Logging/AppenderFile.cpp
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
+ *
+ * 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
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "AppenderFile.h"
+#include "Common.h"
+
+AppenderFile::AppenderFile(uint8 id, std::string const& name, LogLevel level, const char* _filename, const char* _logDir, const char* _mode, AppenderFlags _flags)
+ : Appender(id, name, APPENDER_FILE, level, _flags)
+ , filename(_filename)
+ , logDir(_logDir)
+ , mode(_mode)
+{
+ dynamicName = std::string::npos != filename.find("%s");
+ backup = _flags & APPENDER_FLAGS_MAKE_FILE_BACKUP;
+
+ logfile = !dynamicName ? OpenFile(_filename, _mode, backup) : NULL;
+}
+
+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.c_str());
+ logfile = OpenFile(namebuf, mode, backup);
+ }
+
+ if (logfile)
+ {
+ fprintf(logfile, "%s%s", message.prefix.c_str(), message.text.c_str());
+ fflush(logfile);
+
+ if (dynamicName)
+ {
+ fclose(logfile);
+ logfile = NULL;
+ }
+ }
+}
+
+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((logDir + 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..e9cb858f625
--- /dev/null
+++ b/src/server/shared/Logging/AppenderFile.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
+ *
+ * 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
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#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* logDir, const char* mode, AppenderFlags flags);
+ ~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 logDir;
+ 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..3a24190d8fa 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,1064 +16,497 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "Common.h"
#include "Log.h"
-#include "Configuration/Config.h"
+#include "Common.h"
+#include "Config.h"
#include "Util.h"
+#include "AppenderConsole.h"
+#include "AppenderFile.h"
+#include "AppenderDB.h"
+#include "LogOperation.h"
-#include "Implementation/LoginDatabase.h" // For logging
-extern LoginDatabaseWorkerPool LoginDatabase;
-
-#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() : worker(NULL)
{
- Initialize();
+ SetRealmID(0);
+ m_logsTimestamp = "_" + GetTimestampStr();
+ LoadFromConfig();
}
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;
-
- outString("LogFileLevel is %u", m_logFileLevel);
+ base.append(name);
+ return ConfigMgr::GetIntDefault(base.c_str(), value);
}
-void Log::SetDBLogLevel(char *Level)
+std::string GetConfigStringDefault(std::string base, const char* name, const char* value)
{
- int32 NewLevel = atoi((char*)Level);
- if (NewLevel < 0)
- NewLevel = 0;
- m_dbLogLevel = NewLevel;
-
- outString("DBLogLevel is %u", m_dbLogLevel);
+ base.append(name);
+ return ConfigMgr::GetStringDefault(base.c_str(), value);
}
-void Log::Initialize()
+// Returns default logger if the requested logger is not found
+Logger* Log::GetLoggerByType(LogFilterType filter)
{
- /// 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);
-
- /// Realm must be 0 by default
- SetRealmID(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();
-
- /// Open specific log files
- logfile = openLogFile("LogFile", "LogTimestamp", "w");
- InitColors(ConfigMgr::GetStringDefault("LogColors", ""));
-
- m_gmlog_per_account = ConfigMgr::GetBoolDefault("GmLogPerAccount", false);
- if (!m_gmlog_per_account)
- gmLogfile = openLogFile("GMLogFile", "GmLogTimestamp", "a");
- else
- {
- // GM log settings for per account case
- m_gmlog_filename_format = ConfigMgr::GetStringDefault("GMLogFile", "");
- if (!m_gmlog_filename_format.empty())
- {
- bool m_gmlog_timestamp = ConfigMgr::GetBoolDefault("GmLogTimestamp", false);
-
- 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);
-
- m_gmlog_filename_format.insert(dot_pos, "_#%u");
- }
- else
- {
- m_gmlog_filename_format += "_#%u";
-
- if (m_gmlog_timestamp)
- m_gmlog_filename_format += m_logsTimestamp;
- }
+ LoggerMap::iterator it = loggers.begin();
+ while (it != loggers.end() && it->second.getType() != filter)
+ ++it;
- m_gmlog_filename_format = m_logsDir + m_gmlog_filename_format;
- }
- }
-
- 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)
- {
- 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('/');
- }
-}
-
-void Log::ReloadConfig()
-{
- m_logLevel = ConfigMgr::GetIntDefault("LogLevel", LOGL_NORMAL);
- m_logFileLevel = ConfigMgr::GetIntDefault("LogFileLevel", LOGL_NORMAL);
- m_dbLogLevel = ConfigMgr::GetIntDefault("DBLogLevel", LOGL_NORMAL);
-
- m_DebugLogMask = DebugLogFilters(ConfigMgr::GetIntDefault("DebugLogMask", LOG_FILTER_NONE));
+ return it == loggers.end() ? &(loggers[0]) : &(it->second);
}
-FILE* Log::openLogFile(char const* configFileName, char const* configTimeStampFlag, char const* mode)
+Appender* Log::GetAppenderByName(std::string const& name)
{
- std::string logfn=ConfigMgr::GetStringDefault(configFileName, "");
- if (logfn.empty())
- return NULL;
-
- if (configTimeStampFlag && ConfigMgr::GetBoolDefault(configTimeStampFlag, false))
- {
- size_t dot_pos = logfn.find_last_of(".");
- if (dot_pos!=logfn.npos)
- logfn.insert(dot_pos, m_logsTimestamp);
- else
- logfn += m_logsTimestamp;
- }
+ AppenderMap::iterator it = appenders.begin();
+ while (it != appenders.end() && it->second && it->second->getName() != name)
+ ++it;
- return fopen((m_logsDir+logfn).c_str(), mode);
+ return it == appenders.end() ? NULL : it->second;
}
-FILE* Log::openGmlogPerAccount(uint32 account)
+void Log::CreateAppenderFromConfig(const char* name)
{
- if (m_gmlog_filename_format.empty())
- return NULL;
+ if (!name || *name == '\0')
+ return;
- char namebuf[TRINITY_PATH_MAX];
- snprintf(namebuf, TRINITY_PATH_MAX, m_gmlog_filename_format.c_str(), account);
- return fopen(namebuf, "a");
-}
+ // Format=type,level,flags,optional1,optional2
+ // if type = File. optional1 = file and option2 = mode
+ // if type = Console. optional1 = Color
+ std::string options = "Appender.";
+ options.append(name);
+ options = ConfigMgr::GetStringDefault(options.c_str(), "");
+ Tokens tokens(options, ',');
+ Tokens::iterator iter = tokens.begin();
-void Log::outTimestamp(FILE* file)
-{
- 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);
-}
-
-void Log::InitColors(const std::string& str)
-{
- if (str.empty())
+ if (tokens.size() < 2)
{
- m_colored = false;
+ fprintf(stderr, "Log::CreateAppenderFromConfig: Wrong configuration for appender %s. Config line: %s\n", name, options.c_str());
return;
}
- int color[4];
-
- std::istringstream ss(str);
-
- for (uint8 i = 0; i < LogLevels; ++i)
+ AppenderFlags flags = APPENDER_FLAGS_NONE;
+ AppenderType type = AppenderType(atoi(*iter));
+ ++iter;
+ LogLevel level = LogLevel(atoi(*iter));
+ if (level > LOG_LEVEL_FATAL)
{
- ss >> color[i];
-
- if (!ss)
- return;
-
- if (color[i] < 0 || color[i] >= Colors)
- return;
+ fprintf(stderr, "Log::CreateAppenderFromConfig: Wrong Log Level %u for appender %s\n", level, name);
+ return;
}
- for (uint8 i = 0; i < LogLevels; ++i)
- m_colors[i] = ColorTypes(color[i]);
+ if (++iter != tokens.end())
+ flags = AppenderFlags(atoi(*iter));
- m_colored = true;
-}
-
-void Log::SetColor(bool stdout_stream, ColorTypes color)
-{
- #if PLATFORM == PLATFORM_WINDOWS
- static WORD WinColorFG[Colors] =
+ switch (type)
{
- 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
- };
+ case APPENDER_CONSOLE:
+ {
+ AppenderConsole* appender = new AppenderConsole(NextAppenderId(), name, level, flags);
+ appenders[appender->getId()] = appender;
+ if (++iter != tokens.end())
+ appender->InitColors(*iter);
+ //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;
+ std::string mode = "a";
- enum ANSIFgTextAttr
- {
- FG_BLACK=30, FG_RED, FG_GREEN, FG_BROWN, FG_BLUE,
- FG_MAGENTA, FG_CYAN, FG_WHITE, FG_YELLOW
- };
+ if (++iter == tokens.end())
+ {
+ fprintf(stderr, "Log::CreateAppenderFromConfig: Missing file name for appender %s\n", name);
+ return;
+ }
- enum ANSIBgTextAttr
- {
- BG_BLACK=40, BG_RED, BG_GREEN, BG_BROWN, BG_BLUE,
- BG_MAGENTA, BG_CYAN, BG_WHITE
- };
+ filename = *iter;
- 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
-}
+ if (++iter != tokens.end())
+ mode = *iter;
-void Log::ResetColor(bool stdout_stream)
-{
- #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
-}
+ 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;
+ }
-std::string Log::GetTimestampStr()
-{
- 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)
- 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);
+ uint8 id = NextAppenderId();
+ appenders[id] = new AppenderFile(id, name, level, filename.c_str(), m_logsDir.c_str(), mode.c_str(), flags);
+ //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:
+ {
+ uint8 id = NextAppenderId();
+ appenders[id] = new AppenderDB(id, name, level, realm);
+ break;
+ }
+ default:
+ fprintf(stderr, "Log::CreateAppenderFromConfig: Unknown type %u for appender %s\n", type, name);
+ break;
+ }
}
-void Log::outDB(LogTypes type, const char * str)
+void Log::CreateLoggerFromConfig(const char* name)
{
- if (!str || type >= MAX_LOG_TYPES)
- return;
-
- std::string logStr(str);
- if (logStr.empty())
+ if (!name || *name == '\0')
return;
- PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_LOG);
-
- stmt->setInt32(0, realm);
- stmt->setUInt8(1, uint8(type));
- stmt->setString(2, logStr);
+ LogLevel level = LOG_LEVEL_DISABLED;
+ int32 type = -1;
- LoginDatabase.Execute(stmt);
-}
+ std::string options = "Logger.";
+ options.append(name);
+ options = ConfigMgr::GetStringDefault(options.c_str(), "");
-void Log::outString(const char * str, ...)
-{
- if (!str)
- return;
-
- if (m_enableLogDB)
+ if (options.empty())
{
- // 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);
+ fprintf(stderr, "Log::CreateLoggerFromConfig: Missing config option Logger.%s\n", name);
+ return;
}
- if (m_colored)
- SetColor(true, m_colors[LOGL_NORMAL]);
+ Tokens tokens(options, ',');
+ Tokens::iterator iter = tokens.begin();
- va_list ap;
-
- va_start(ap, str);
- vutf8printf(stdout, str, &ap);
- va_end(ap);
-
- if (m_colored)
- ResetColor(true);
-
- printf("\n");
- if (logfile)
+ if (tokens.size() != 3)
{
- outTimestamp(logfile);
- va_start(ap, str);
- vfprintf(logfile, str, ap);
- fprintf(logfile, "\n");
- va_end(ap);
-
- fflush(logfile);
+ fprintf(stderr, "Log::CreateLoggerFromConfig: Wrong config option Logger.%s=%s\n", name, options.c_str());
+ return;
}
- fflush(stdout);
-}
-void Log::outString()
-{
- printf("\n");
- if (logfile)
+ type = atoi(*iter);
+ if (type > MaxLogFilter)
{
- outTimestamp(logfile);
- fprintf(logfile, "\n");
- fflush(logfile);
+ fprintf(stderr, "Log::CreateLoggerFromConfig: Wrong type %u for logger %s\n", type, name);
+ return;
}
- fflush(stdout);
-}
-void Log::outCrash(const char * err, ...)
-{
- if (!err)
+ Logger& logger = loggers[type];
+ if (!logger.getName().empty())
+ {
+ fprintf(stderr, "Error while configuring Logger %s. Already defined\n", name);
return;
+ }
- if (m_enableLogDB)
+ ++iter;
+ level = LogLevel(atoi(*iter));
+ if (level > LOG_LEVEL_FATAL)
{
- 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);
+ fprintf(stderr, "Log::CreateLoggerFromConfig: Wrong Log Level %u for logger %s\n", type, name);
+ return;
}
- if (m_colored)
- SetColor(false, LRED);
-
- va_list ap;
-
- va_start(ap, err);
- vutf8printf(stderr, err, &ap);
- va_end(ap);
+ 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 (m_colored)
- ResetColor(false);
+ ++iter;
+ std::istringstream ss(*iter);
+ std::string str;
- fprintf(stderr, "\n");
- if (logfile)
+ ss >> str;
+ while (ss)
{
- outTimestamp(logfile);
- fprintf(logfile, "CRASH ALERT: ");
-
- va_start(ap, err);
- vfprintf(logfile, err, ap);
- va_end(ap);
-
- fprintf(logfile, "\n");
- fflush(logfile);
+ 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
+ fprintf(stderr, "Error while configuring Appender %s in Logger %s. Appender does not exist", str.c_str(), name);
+ ss >> str;
}
- fflush(stderr);
}
-void Log::outError(const char * err, ...)
+void Log::ReadAppendersFromConfig()
{
- if (!err)
- return;
+ std::istringstream ss(ConfigMgr::GetStringDefault("Appenders", ""));
+ std::string name;
- if (m_enableLogDB)
+ do
{
- 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);
+ ss >> name;
+ CreateAppenderFromConfig(name.c_str());
+ name = "";
}
+ while (ss);
+}
- 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);
+void Log::ReadLoggersFromConfig()
+{
+ std::istringstream ss(ConfigMgr::GetStringDefault("Loggers", ""));
+ std::string name;
- fprintf( stderr, "\n");
- if (logfile)
+ do
{
- outTimestamp(logfile);
- fprintf(logfile, "ERROR: ");
+ ss >> name;
+ CreateLoggerFromConfig(name.c_str());
+ name = "";
+ }
+ while (ss);
- va_start(ap, err);
- vfprintf(logfile, err, ap);
- va_end(ap);
+ LoggerMap::const_iterator it = loggers.begin();
- fprintf(logfile, "\n");
- fflush(logfile);
- }
- fflush(stderr);
+ while (it != loggers.end() && it->first)
+ ++it;
+
+ // 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);
}
-void Log::outArena(const char * str, ...)
+void Log::EnableDBAppenders()
{
- if (!str)
- return;
-
- if (arenaLogFile)
- {
- va_list ap;
- outTimestamp(arenaLogFile);
- va_start(ap, str);
- vfprintf(arenaLogFile, str, ap);
- fprintf(arenaLogFile, "\n");
- va_end(ap);
- fflush(arenaLogFile);
- }
+ for (AppenderMap::iterator it = appenders.begin(); it != appenders.end(); ++it)
+ if (it->second && it->second->getType() == APPENDER_DB)
+ ((AppenderDB *)it->second)->setEnable(true);
}
-void Log::outSQLDriver(const char* str, ...)
+void Log::log(LogFilterType filter, LogLevel level, char const* str, ...)
{
- if (!str)
+ if (!str || !ShouldLog(filter, level))
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);
- }
+ vlog(filter, level, str, ap);
- fflush(stdout);
+ va_end(ap);
}
-void Log::outErrorDb(const char * err, ...)
+void Log::vlog(LogFilterType filter, LogLevel level, char const* str, va_list argptr)
{
- if (!err)
- return;
-
- if (m_colored)
- SetColor(false, LRED);
-
- va_list ap;
+ char text[MAX_QUERY_LEN];
+ vsnprintf(text, MAX_QUERY_LEN, str, argptr);
+ write(new LogMessage(level, filter, text));
+}
- va_start(ap, err);
- vutf8printf(stderr, err, &ap);
- va_end(ap);
+void Log::write(LogMessage* msg)
+{
+ msg->text.append("\n");
+ Logger* logger = GetLoggerByType(msg->type);
+ worker->enqueue(new LogOperation(logger, msg));
+}
- if (m_colored)
- ResetColor(false);
+std::string Log::GetTimestampStr()
+{
+ 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)
+ 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);
+}
- fprintf( stderr, "\n" );
+bool Log::SetLogLevel(std::string const& name, const char* newLevelc, bool isLogger /* = true */)
+{
+ LogLevel newLevel = LogLevel(atoi(newLevelc));
+ if (newLevel < 0)
+ return false;
- if (logfile)
+ if (isLogger)
{
- outTimestamp(logfile);
- fprintf(logfile, "ERROR: " );
+ LoggerMap::iterator it = loggers.begin();
+ while (it != loggers.end() && it->second.getName() != name)
+ ++it;
- va_start(ap, err);
- vfprintf(logfile, err, ap);
- va_end(ap);
+ if (it == loggers.end())
+ return false;
- fprintf(logfile, "\n" );
- fflush(logfile);
+ it->second.setLogLevel(newLevel);
}
-
- if (dberLogfile)
+ else
{
- outTimestamp(dberLogfile);
- va_start(ap, err);
- vfprintf(dberLogfile, err, ap);
- va_end(ap);
+ Appender* appender = GetAppenderByName(name);
+ if (!appender)
+ return false;
- fprintf(dberLogfile, "\n" );
- fflush(dberLogfile);
+ appender->setLogLevel(newLevel);
}
- fflush(stderr);
+ return true;
}
-void Log::outBasic(const char * str, ...)
+bool Log::ShouldLog(LogFilterType type, LogLevel level) const
{
- if (!str)
- return;
+ LoggerMap::const_iterator it = loggers.begin();
+ while (it != loggers.end() && it->second.getType() != type)
+ ++it;
- if (m_enableLogDB && m_dbLogLevel > LOGL_NORMAL)
+ if (it != loggers.end())
{
- 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);
+ LogLevel loggerLevel = it->second.getLogLevel();
+ return loggerLevel && loggerLevel <= level;
}
- 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);
+ if (type != LOG_FILTER_GENERAL)
+ return ShouldLog(LOG_FILTER_GENERAL, level);
- 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);
+ return false;
}
-void Log::outDetail(const char * str, ...)
+void Log::outTrace(LogFilterType filter, const char * str, ...)
{
- if (!str)
+ if (!str || !ShouldLog(filter, LOG_LEVEL_TRACE))
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);
-
- printf("\n");
+ va_list ap;
+ va_start(ap, str);
- if (logfile)
- {
- outTimestamp(logfile);
- va_list ap2;
- va_start(ap2, str);
- vfprintf(logfile, str, ap2);
- va_end(ap2);
-
- fprintf(logfile, "\n");
- fflush(logfile);
- }
- }
+ vlog(filter, LOG_LEVEL_TRACE, str, ap);
- fflush(stdout);
+ va_end(ap);
}
-void Log::outDebugInLine(const char * str, ...)
+void Log::outDebug(LogFilterType filter, const char * str, ...)
{
- if (!str)
+ if (!str || !ShouldLog(filter, LOG_LEVEL_DEBUG))
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_DEBUG, 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::outInfo(LogFilterType filter, const char * str, ...)
{
- if (!str)
+ if (!str || !ShouldLog(filter, LOG_LEVEL_INFO))
return;
va_list ap;
va_start(ap, str);
- vutf8printf(stdout, str, &ap);
- va_end(ap);
-
- printf("\n");
- if (sqlDevLogFile)
- {
- va_list ap2;
- va_start(ap2, str);
- vfprintf(sqlDevLogFile, str, ap2);
- va_end(ap2);
-
- fprintf(sqlDevLogFile, "\n");
- fflush(sqlDevLogFile);
- }
+ vlog(filter, LOG_LEVEL_INFO, str, ap);
- fflush(stdout);
+ va_end(ap);
}
-void Log::outDebug(DebugLogFilters f, const char * str, ...)
+void Log::outWarn(LogFilterType filter, const char * str, ...)
{
- if (!(m_DebugLogMask & f))
- return;
-
- if (!str)
+ if (!str || !ShouldLog(filter, LOG_LEVEL_WARN))
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_WARN, 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::outError(LogFilterType filter, const char * str, ...)
{
- 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::outStringInLine(const char * str, ...)
+void Log::outFatal(LogFilterType filter, const char * str, ...)
{
- if (!str)
+ if (!str || !ShouldLog(filter, LOG_LEVEL_FATAL))
return;
va_list ap;
-
va_start(ap, str);
- vutf8printf(stdout, str, &ap);
- va_end(ap);
- if (logfile)
- {
- va_start(ap, str);
- vfprintf(logfile, str, ap);
- va_end(ap);
- }
+ vlog(filter, LOG_LEVEL_FATAL, str, ap);
+
+ va_end(ap);
}
-void Log::outCommand(uint32 account, const char * str, ...)
+void Log::outCharDump(const char* param, const char * str, ...)
{
- if (!str)
+ if (!str || !ShouldLog(LOG_FILTER_PLAYER_DUMP, LOG_LEVEL_INFO))
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);
-
- if (m_colored)
- ResetColor(true);
-
- printf("\n");
+ va_list ap;
+ va_start(ap, str);
+ char text[MAX_QUERY_LEN];
+ vsnprintf(text, MAX_QUERY_LEN, str, ap);
+ va_end(ap);
- if (logfile)
- {
- outTimestamp(logfile);
- va_list ap2;
- va_start(ap2, str);
- vfprintf(logfile, str, ap2);
- fprintf(logfile, "\n" );
- va_end(ap2);
- fflush(logfile);
- }
- }
+ LogMessage* msg = new LogMessage(LOG_LEVEL_INFO, LOG_FILTER_PLAYER_DUMP, text);
+ msg->param1 = param;
- 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::outCommand(uint32 account, const char * str, ...)
{
- if (!str)
+ if (!str || !ShouldLog(LOG_FILTER_GMCOMMAND, LOG_LEVEL_INFO))
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);
- }
+ va_list ap;
+ va_start(ap, str);
+ char text[MAX_QUERY_LEN];
+ vsnprintf(text, MAX_QUERY_LEN, str, ap);
+ va_end(ap);
- if (charLogfile)
- {
- outTimestamp(charLogfile);
- va_list ap;
- va_start(ap, str);
- vfprintf(charLogfile, str, ap);
- fprintf(charLogfile, "\n" );
- va_end(ap);
- fflush(charLogfile);
- }
-}
+ LogMessage* msg = new LogMessage(LOG_LEVEL_INFO, LOG_FILTER_GMCOMMAND, text);
-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);
- }
+ std::ostringstream ss;
+ ss << account;
+ msg->param1 = ss.str();
+
+ write(msg);
}
-void Log::outRemote(const char * str, ...)
+void Log::SetRealmID(uint32 id)
{
- 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)
+ delete worker;
+ worker = NULL;
+ loggers.clear();
+ for (AppenderMap::iterator it = appenders.begin(); it != appenders.end(); ++it)
{
- 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);
+ delete it->second;
+ it->second = NULL;
}
+ appenders.clear();
}
-void Log::outErrorST(const char * str, ...)
+void Log::LoadFromConfig()
{
- 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)
- {
- outTimestamp(wardenLogFile);
- va_list ap;
- va_start(ap, str);
- vfprintf(wardenLogFile, str, ap);
- fprintf(wardenLogFile, "\n" );
- fflush(wardenLogFile);
- va_end(ap);
- }
+ Close();
+ AppenderId = 0;
+ 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('/');
+ ReadAppendersFromConfig();
+ ReadLoggersFromConfig();
+ worker = new LogWorker();
}
diff --git a/src/server/shared/Logging/Log.h b/src/server/shared/Logging/Log.h
index 296c13d86c9..cd1e9dc80df 100755
--- a/src/server/shared/Logging/Log.h
+++ b/src/server/shared/Logging/Log.h
@@ -19,196 +19,71 @@
#ifndef TRINITYCORE_LOG_H
#define TRINITYCORE_LOG_H
-#include "Common.h"
-#include <ace/Singleton.h>
-
-class Config;
-
-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;
+#include "Define.h"
+#include "Appender.h"
+#include "LogWorker.h"
+#include "Logger.h"
-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);
+ void LoadFromConfig();
+ void Close();
+ bool ShouldLog(LogFilterType type, LogLevel level) const;
+ bool SetLogLevel(std::string const& name, char const* level, bool isLogger = true);
+
+ 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);
+ void outCharDump(const char* param, const char* str, ...) ATTR_PRINTF(3, 4);
static std::string GetTimestampStr();
- 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; }
-
- 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..b36dd3a8b1e
--- /dev/null
+++ b/src/server/shared/Logging/LogOperation.cpp
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
+ *
+ * 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
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#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..d872670d756
--- /dev/null
+++ b/src/server/shared/Logging/LogOperation.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
+ *
+ * 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
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#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..a12faaf224c
--- /dev/null
+++ b/src/server/shared/Logging/LogWorker.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
+ *
+ * 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
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#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..ea1744f9790
--- /dev/null
+++ b/src/server/shared/Logging/LogWorker.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
+ *
+ * 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
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#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..10276eb3acb
--- /dev/null
+++ b/src/server/shared/Logging/Logger.cpp
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
+ *
+ * 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
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#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..9d13f08620f
--- /dev/null
+++ b/src/server/shared/Logging/Logger.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
+ *
+ * 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
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#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