TrinityCore
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
Log.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/>
3  * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License as published by the
7  * Free Software Foundation; either version 2 of the License, or (at your
8  * option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13  * more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program. If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #ifndef TRINITYCORE_LOG_H
20 #define TRINITYCORE_LOG_H
21 
22 #include "Define.h"
23 #include "Appender.h"
24 #include "Logger.h"
25 #include "StringFormat.h"
26 #include "Common.h"
27 #include <boost/asio/io_service.hpp>
28 #include <boost/asio/strand.hpp>
29 
30 #include <stdarg.h>
31 #include <unordered_map>
32 #include <string>
33 #include <memory>
34 
35 #define LOGGER_ROOT "root"
36 
38 {
39  typedef std::unordered_map<std::string, Logger> LoggerMap;
40 
41  private:
42  Log();
43  ~Log();
44 
45  public:
46 
47  static Log* instance();
48 
49  void Initialize(boost::asio::io_service* ioService);
50  void SetSynchronous(); // Not threadsafe - should only be called from main() after all threads are joined
51  void LoadFromConfig();
52  void Close();
53  bool ShouldLog(std::string const& type, LogLevel level) const;
54  bool SetLogLevel(std::string const& name, char const* level, bool isLogger = true);
55 
56  template<typename Format, typename... Args>
57  inline void outMessage(std::string const& filter, LogLevel const level, Format&& fmt, Args&&... args)
58  {
59  write(Trinity::make_unique<LogMessage>(level, filter,
60  Trinity::StringFormat(std::forward<Format>(fmt), std::forward<Args>(args)...)));
61  }
62 
63  template<typename Format, typename... Args>
64  void outCommand(uint32 account, Format&& fmt, Args&&... args)
65  {
66  if (!ShouldLog("commands.gm", LOG_LEVEL_INFO))
67  return;
68 
69  std::unique_ptr<LogMessage> msg =
70  Trinity::make_unique<LogMessage>(LOG_LEVEL_INFO, "commands.gm",
71  Trinity::StringFormat(std::forward<Format>(fmt), std::forward<Args>(args)...));
72 
73  msg->param1 = std::to_string(account);
74 
75  write(std::move(msg));
76  }
77 
78  void outCharDump(char const* str, uint32 account_id, uint64 guid, char const* name);
79 
80  void SetRealmId(uint32 id);
81 
82  template<class AppenderImpl>
84  {
85  using Index = typename AppenderImpl::TypeIndex;
86  auto itr = appenderFactory.find(Index::value);
87  ASSERT(itr == appenderFactory.end());
88  appenderFactory[Index::value] = &CreateAppender<AppenderImpl>;
89  }
90 
91  std::string const& GetLogsDir() const { return m_logsDir; }
92  std::string const& GetLogsTimestamp() const { return m_logsTimestamp; }
93 
94  private:
95  static std::string GetTimestampStr();
96  void write(std::unique_ptr<LogMessage>&& msg) const;
97 
98  Logger const* GetLoggerByType(std::string const& type) const;
99  Appender* GetAppenderByName(std::string const& name);
100  uint8 NextAppenderId();
101  void CreateAppenderFromConfig(std::string const& name);
102  void CreateLoggerFromConfig(std::string const& name);
103  void ReadAppendersFromConfig();
104  void ReadLoggersFromConfig();
105 
108  LoggerMap loggers;
111 
112  std::string m_logsDir;
113  std::string m_logsTimestamp;
114 
115  boost::asio::io_service* _ioService;
116  boost::asio::strand* _strand;
117 };
118 
119 inline Logger const* Log::GetLoggerByType(std::string const& type) const
120 {
121  LoggerMap::const_iterator it = loggers.find(type);
122  if (it != loggers.end())
123  return &(it->second);
124 
125  if (type == LOGGER_ROOT)
126  return NULL;
127 
128  std::string parentLogger = LOGGER_ROOT;
129  size_t found = type.find_last_of(".");
130  if (found != std::string::npos)
131  parentLogger = type.substr(0,found);
132 
133  return GetLoggerByType(parentLogger);
134 }
135 
136 inline bool Log::ShouldLog(std::string const& type, LogLevel level) const
137 {
138  // TODO: Use cache to store "Type.sub1.sub2": "Type" equivalence, should
139  // Speed up in cases where requesting "Type.sub1.sub2" but only configured
140  // Logger "Type"
141 
142  // Don't even look for a logger if the LogLevel is lower than lowest log levels across all loggers
143  if (level < lowestLogLevel)
144  return false;
145 
146  Logger const* logger = GetLoggerByType(type);
147  if (!logger)
148  return false;
149 
150  LogLevel logLevel = logger->getLogLevel();
151  return logLevel != LOG_LEVEL_DISABLED && logLevel <= level;
152 }
153 
154 #define sLog Log::instance()
155 
156 #define LOG_EXCEPTION_FREE(filterType__, level__, ...) \
157  { \
158  try \
159  { \
160  sLog->outMessage(filterType__, level__, __VA_ARGS__); \
161  } \
162  catch (std::exception& e) \
163  { \
164  sLog->outMessage("server", LOG_LEVEL_ERROR, "Wrong format occurred (%s) at %s:%u.", \
165  e.what(), __FILE__, __LINE__); \
166  } \
167  }
168 
169 #if PLATFORM != PLATFORM_WINDOWS
170 void check_args(const char*, ...) ATTR_PRINTF(1, 2);
171 void check_args(std::string const&, ...);
172 
173 // This will catch format errors on build time
174 #define TC_LOG_MESSAGE_BODY(filterType__, level__, ...) \
175  do { \
176  if (sLog->ShouldLog(filterType__, level__)) \
177  { \
178  if (false) \
179  check_args(__VA_ARGS__); \
180  \
181  LOG_EXCEPTION_FREE(filterType__, level__, __VA_ARGS__); \
182  } \
183  } while (0)
184 #else
185 #define TC_LOG_MESSAGE_BODY(filterType__, level__, ...) \
186  __pragma(warning(push)) \
187  __pragma(warning(disable:4127)) \
188  do { \
189  if (sLog->ShouldLog(filterType__, level__)) \
190  LOG_EXCEPTION_FREE(filterType__, level__, __VA_ARGS__); \
191  } while (0) \
192  __pragma(warning(pop))
193 #endif
194 
195 #define TC_LOG_TRACE(filterType__, ...) \
196  TC_LOG_MESSAGE_BODY(filterType__, LOG_LEVEL_TRACE, __VA_ARGS__)
197 
198 #define TC_LOG_DEBUG(filterType__, ...) \
199  TC_LOG_MESSAGE_BODY(filterType__, LOG_LEVEL_DEBUG, __VA_ARGS__)
200 
201 #define TC_LOG_INFO(filterType__, ...) \
202  TC_LOG_MESSAGE_BODY(filterType__, LOG_LEVEL_INFO, __VA_ARGS__)
203 
204 #define TC_LOG_WARN(filterType__, ...) \
205  TC_LOG_MESSAGE_BODY(filterType__, LOG_LEVEL_WARN, __VA_ARGS__)
206 
207 #define TC_LOG_ERROR(filterType__, ...) \
208  TC_LOG_MESSAGE_BODY(filterType__, LOG_LEVEL_ERROR, __VA_ARGS__)
209 
210 #define TC_LOG_FATAL(filterType__, ...) \
211  TC_LOG_MESSAGE_BODY(filterType__, LOG_LEVEL_FATAL, __VA_ARGS__)
212 
213 #endif
Definition: Logger.h:23
std::unordered_map< uint8, AppenderCreatorFn > AppenderCreatorMap
Definition: Appender.h:118
LoggerMap loggers
Definition: Log.h:108
boost::asio::strand * _strand
Definition: Log.h:116
std::string m_logsDir
Definition: Log.h:112
Definition: Appender.h:36
std::unordered_map< uint8, Appender * > AppenderMap
Definition: Appender.h:114
AppenderCreatorMap appenderFactory
Definition: Log.h:106
LogLevel lowestLogLevel
Definition: Log.h:110
STL namespace.
Definition: Log.h:37
boost::asio::io_service * _ioService
Definition: Log.h:115
arena_t NULL
Definition: jemalloc_internal.h:624
void outMessage(std::string const &filter, LogLevel const level, Format &&fmt, Args &&...args)
Definition: Log.h:57
void outCommand(uint32 account, Format &&fmt, Args &&...args)
Definition: Log.h:64
std::string m_logsTimestamp
Definition: Log.h:113
#define LOGGER_ROOT
Definition: Log.h:35
#define ATTR_PRINTF(F, V)
Definition: Define.h:89
Definition: Appender.h:33
uint8 AppenderId
Definition: Log.h:109
uint32_t uint32
Definition: Define.h:150
static void Initialize(PCASC_SALSA20 pState, LPBYTE pbKey, DWORD cbKeyLength, LPBYTE pbVector)
Definition: CascDecrypt.cpp:81
LogLevel
Definition: Appender.h:31
uint64_t uint64
Definition: Define.h:149
LogLevel getLogLevel() const
Definition: Logger.cpp:33
#define TC_COMMON_API
Definition: Define.h:116
AppenderMap appenders
Definition: Log.h:107
std::string StringFormat(Format &&fmt, Args &&...args)
Default TC string format function.
Definition: StringFormat.h:28
std::string const & GetLogsDir() const
Definition: Log.h:91
Logger const * GetLoggerByType(std::string const &type) const
Definition: Log.h:119
uint8_t uint8
Definition: Define.h:152
#define ASSERT
Definition: Errors.h:55
Definition: format.h:285
const FieldDescriptor value
Definition: descriptor.h:1522
std::unordered_map< std::string, Logger > LoggerMap
Definition: Log.h:39
#define const
Definition: zconf.h:217
std::string param1
Definition: Appender.h:78
bool ShouldLog(std::string const &type, LogLevel level) const
Definition: Log.h:136
Definition: Appender.h:88
void RegisterAppender()
Definition: Log.h:83
std::string const & GetLogsTimestamp() const
Definition: Log.h:92