Project SkyFire Core
SkyFire 5.4.8 server core API documentation
Loading...
Searching...
No Matches
Log.cpp
Go to the documentation of this file.
1/*
2* This file is part of Project SkyFire https://www.projectskyfire.org.
3* See LICENSE.md file for Copyright information
4*/
5
6#include "AppenderConsole.h"
7#include "AppenderDB.h"
8#include "AppenderFile.h"
9#include "Common.h"
10#include "Config.h"
11#include "Log.h"
12#include "LogOperation.h"
13#include "Platform/TimeUtils.h"
14#include "Util.h"
15
16#include <cstdarg>
17#include <cstdio>
18#include <sstream>
19
21{
24}
25
27{
28 Close();
29}
30
32{
33 return AppenderId++;
34}
35
36int32 GetConfigIntDefault(std::string base, const char* name, int32 value)
37{
38 base.append(name);
39 return sConfigMgr->GetIntDefault(base.c_str(), value);
40}
41
42std::string GetConfigStringDefault(std::string base, const char* name, const char* value)
43{
44 base.append(name);
45 return sConfigMgr->GetStringDefault(base.c_str(), value);
46}
47
48Appender* Log::GetAppenderByName(std::string const& name)
49{
50 AppenderMap::iterator it = appenders.begin();
51 while (it != appenders.end() && it->second && it->second->getName() != name)
52 ++it;
53
54 return it == appenders.end() ? NULL : it->second;
55}
56
57void Log::CreateAppenderFromConfig(std::string const& appenderName)
58{
59 if (appenderName.empty())
60 return;
61
62 // Format=type, level, flags, optional1, optional2
63 // if type = File. optional1 = file and option2 = mode
64 // if type = Console. optional1 = Color
65 std::string options = sConfigMgr->GetStringDefault(appenderName.c_str(), "");
66
67 Tokenizer tokens(options, ',');
68 Tokenizer::const_iterator iter = tokens.begin();
69
70 size_t size = tokens.size();
71 std::string name = appenderName.substr(9);
72
73 if (size < 2)
74 {
75 fprintf(stderr, "Log::CreateAppenderFromConfig: Wrong configuration for appender %s. Config line: %s\n", name.c_str(), options.c_str());
76 return;
77 }
78
80 AppenderType type = AppenderType(atoi(*iter++));
81 LogLevel level = LogLevel(atoi(*iter++));
82
83 if (level > LogLevel::LOG_LEVEL_FATAL)
84 {
85 fprintf(stderr, "Log::CreateAppenderFromConfig: Wrong Log Level %d for appender %s\n", static_cast<int>(level), name.c_str());
86 return;
87 }
88
89 if (size > 2)
90 flags = AppenderFlags(atoi(*iter++));
91
92 switch (type)
93 {
95 {
96 AppenderConsole* appender = new AppenderConsole(NextAppenderId(), name, level, flags);
97 appenders[appender->getId()] = appender;
98 if (size > 3)
99 appender->InitColors(*iter++);
100 //fprintf(stdout, "Log::CreateAppenderFromConfig: Created Appender %s (%u), Type CONSOLE, Mask %u\n", appender->getName().c_str(), appender->getId(), appender->getLogLevel());
101 break;
102 }
104 {
105 std::string filename;
106 std::string mode = "a";
107
108 if (size < 4)
109 {
110 fprintf(stderr, "Log::CreateAppenderFromConfig: Missing file name for appender %s\n", name.c_str());
111 return;
112 }
113
114 filename = *iter++;
115
116 if (size > 4)
117 mode = *iter++;
118
120 {
121 size_t dot_pos = filename.find_last_of(".");
122 if (dot_pos != filename.npos)
123 filename.insert(dot_pos, m_logsTimestamp);
124 else
125 filename += m_logsTimestamp;
126 }
127
128 uint64 maxFileSize = 0;
129 if (size > 5)
130 maxFileSize = atoi(*iter++);
131
132 uint8 id = NextAppenderId();
133 appenders[id] = new AppenderFile(id, name, level, filename.c_str(), m_logsDir.c_str(), mode.c_str(), flags, maxFileSize);
134 //fprintf(stdout, "Log::CreateAppenderFromConfig: Created Appender %s (%u), Type FILE, Mask %u, File %s, Mode %s\n", name.c_str(), id, level, filename.c_str(), mode.c_str());
135 break;
136 }
138 {
139 uint8 id = NextAppenderId();
140 appenders[id] = new AppenderDB(id, name, level);
141 break;
142 }
143 default:
144 fprintf(stderr, "Log::CreateAppenderFromConfig: Unknown type %d for appender %s\n", static_cast<int>(type), name.c_str());
145 break;
146 }
147}
148
149void Log::CreateLoggerFromConfig(std::string const& appenderName)
150{
151 if (appenderName.empty())
152 return;
153
155 uint8 type = uint8(-1);
156
157 std::string options = sConfigMgr->GetStringDefault(appenderName.c_str(), "");
158 std::string name = appenderName.substr(7);
159
160 if (options.empty())
161 {
162 fprintf(stderr, "Log::CreateLoggerFromConfig: Missing config option Logger.%s\n", name.c_str());
163 return;
164 }
165
166 Tokenizer tokens(options, ',');
167 Tokenizer::const_iterator iter = tokens.begin();
168
169 if (tokens.size() != 2)
170 {
171 fprintf(stderr, "Log::CreateLoggerFromConfig: Wrong config option Logger.%s=%s\n", name.c_str(), options.c_str());
172 return;
173 }
174
175 Logger& logger = loggers[name];
176 if (!logger.getName().empty())
177 {
178 fprintf(stderr, "Error while configuring Logger %s. Already defined\n", name.c_str());
179 return;
180 }
181
182 level = LogLevel(atoi(*iter++));
183 if (level > LogLevel::LOG_LEVEL_FATAL)
184 {
185 fprintf(stderr, "Log::CreateLoggerFromConfig: Wrong Log Level %u for logger %s\n", type, name.c_str());
186 return;
187 }
188
189 logger.Create(name, level);
190 //fprintf(stdout, "Log::CreateLoggerFromConfig: Created Logger %s, Level %u\n", name.c_str(), level);
191
192 std::istringstream ss(*iter);
193 std::string str;
194
195 ss >> str;
196 while (ss)
197 {
198 if (Appender* appender = GetAppenderByName(str))
199 {
200 logger.addAppender(appender->getId(), appender);
201 //fprintf(stdout, "Log::CreateLoggerFromConfig: Added Appender %s to Logger %s\n", appender->getName().c_str(), name.c_str());
202 }
203 else
204 fprintf(stderr, "Error while configuring Appender %s in Logger %s. Appender does not exist", str.c_str(), name.c_str());
205 ss >> str;
206 }
207}
208
210{
211 std::list<std::string> keys = sConfigMgr->GetKeysByString("Appender.");
212
213 while (!keys.empty())
214 {
215 CreateAppenderFromConfig(keys.front());
216 keys.pop_front();
217 }
218}
219
221{
222 std::list<std::string> keys = sConfigMgr->GetKeysByString("Logger.");
223
224 while (!keys.empty())
225 {
226 CreateLoggerFromConfig(keys.front());
227 keys.pop_front();
228 }
229
230 // Bad config configuration, creating default config
231 if (loggers.find(LOGGER_ROOT) == loggers.end())
232 {
233 fprintf(stderr, "Wrong Loggers configuration. Review your Logger config section.\n"
234 "Creating default loggers [root (Error), server (Info)] to console\n");
235
236 Close(); // Clean any Logger or Appender created
237
239 appenders[appender->getId()] = appender;
240
241 Logger& logger = loggers[LOGGER_ROOT];
243 logger.addAppender(appender->getId(), appender);
244
245 logger = loggers["server"];
246 logger.Create("server", LogLevel::LOG_LEVEL_ERROR);
247 logger.addAppender(appender->getId(), appender);
248 }
249}
250
251void Log::vlog(std::string const& filter, LogLevel level, char const* str, va_list argptr)
252{
253 char text[MAX_QUERY_LEN];
254 vsnprintf(text, MAX_QUERY_LEN, str, argptr);
255 write(new LogMessage(level, filter, text));
256}
257
258void Log::write(LogMessage* msg) const
259{
260 Logger const* logger = GetLoggerByType(msg->type);
261 msg->text.append("\n");
262
263 if (worker)
264 worker->enqueue(new LogOperation(logger, msg));
265 else
266 {
267 logger->write(*msg);
268 delete msg;
269 }
270}
271
273{
274 time_t t = time(NULL);
275 tm aTm;
276 Skyfire::LocalTime(t, aTm);
277 char buf[20];
278 snprintf(buf, sizeof(buf), "%u-%u-%u_%u-%u-%u", uint32(aTm.tm_year + 1900), uint32(aTm.tm_mon + 1), uint32(aTm.tm_mday), uint32(aTm.tm_hour), uint32(aTm.tm_min), uint32(aTm.tm_sec));
279 return std::string(buf);
280}
281
282bool Log::SetLogLevel(std::string const& name, const char* newLevelc, bool isLogger /* = true */)
283{
284 LogLevel newLevel = LogLevel(atoi(newLevelc));
285 if (newLevel < LogLevel::LOG_LEVEL_DISABLED)
286 return false;
287
288 if (isLogger)
289 {
290 LoggerMap::iterator it = loggers.begin();
291 while (it != loggers.end() && it->second.getName() != name)
292 ++it;
293
294 if (it == loggers.end())
295 return false;
296
297 it->second.setLogLevel(newLevel);
298 }
299 else
300 {
301 Appender* appender = GetAppenderByName(name);
302 if (!appender)
303 return false;
304
305 appender->setLogLevel(newLevel);
306 }
307
308 return true;
309}
310
311void Log::outCharDump(char const* str, uint32 accountId, uint32 guid, char const* name)
312{
313 if (!str || !ShouldLog("entities.player.dump", LogLevel::LOG_LEVEL_INFO))
314 return;
315
316 std::ostringstream ss;
317 ss << "== START DUMP == (account: " << accountId << " guid: " << guid << " name: " << name
318 << ")\n" << str << "\n== END DUMP ==\n";
319
320 LogMessage* msg = new LogMessage(LogLevel::LOG_LEVEL_INFO, "entities.player.dump", ss.str());
321 std::ostringstream param;
322 param << guid << '_' << name;
323
324 msg->param1 = param.str();
325
326 write(msg);
327}
328
329void Log::outCommand(uint32 account, const char* str, ...)
330{
331 if (!str || !ShouldLog("commands.gm", LogLevel::LOG_LEVEL_INFO))
332 return;
333
334 va_list ap;
335 va_start(ap, str);
336 char text[MAX_QUERY_LEN];
337 vsnprintf(text, MAX_QUERY_LEN, str, ap);
338 va_end(ap);
339
340 LogMessage* msg = new LogMessage(LogLevel::LOG_LEVEL_INFO, "commands.gm", text);
341
342 std::ostringstream ss;
343 ss << account;
344 msg->param1 = ss.str();
345
346 write(msg);
347}
348
350{
351 for (AppenderMap::iterator it = appenders.begin(); it != appenders.end(); ++it)
352 if (it->second && it->second->getType() == AppenderType::APPENDER_DB)
353 ((AppenderDB*)it->second)->setRealmId(id);
354}
355
357{
358 delete worker;
359 worker = NULL;
360 loggers.clear();
361 for (AppenderMap::iterator it = appenders.begin(); it != appenders.end(); ++it)
362 {
363 delete it->second;
364 it->second = NULL;
365 }
366 appenders.clear();
367}
368
370{
371 Close();
372
373 if (sConfigMgr->GetBoolDefault("Log.Async.Enable", false))
374 worker = new LogWorker();
375
376 AppenderId = 0;
377 m_logsDir = sConfigMgr->GetStringDefault("LogsDir", "");
378 if (!m_logsDir.empty())
379 if ((m_logsDir.at(m_logsDir.length() - 1) != '/') && (m_logsDir.at(m_logsDir.length() - 1) != '\\'))
380 m_logsDir.push_back('/');
381
384}
AppenderType
Definition Appender.h:29
@ APPENDER_CONSOLE
Definition Appender.h:31
AppenderFlags
Definition Appender.h:37
@ APPENDER_FLAGS_NONE
Definition Appender.h:38
@ APPENDER_FLAGS_USE_TIMESTAMP
Definition Appender.h:42
LogLevel
Definition Appender.h:16
@ LOG_LEVEL_DISABLED
Definition Appender.h:17
@ LOG_LEVEL_ERROR
Definition Appender.h:22
@ LOG_LEVEL_INFO
Definition Appender.h:20
@ LOG_LEVEL_FATAL
Definition Appender.h:23
@ LOG_LEVEL_DEBUG
Definition Appender.h:19
#define vsnprintf
Definition Common.h:100
#define MAX_QUERY_LEN
Definition Common.h:195
#define sConfigMgr
Definition Config.h:64
std::int32_t int32
Definition Define.h:73
std::uint8_t uint8
Definition Define.h:79
std::uint32_t uint32
Definition Define.h:77
std::uint64_t uint64
Definition Define.h:76
int32 GetConfigIntDefault(std::string base, const char *name, int32 value)
Definition Log.cpp:36
std::string GetConfigStringDefault(std::string base, const char *name, const char *value)
Definition Log.cpp:42
#define LOGGER_ROOT
Definition Log.h:19
void InitColors(const std::string &init_str)
uint8 getId() const
Definition Appender.cpp:29
void setLogLevel(LogLevel)
Definition Appender.cpp:54
~Log()
Definition Log.cpp:26
AppenderMap appenders
Definition Log.h:57
uint8 NextAppenderId()
Definition Log.cpp:31
bool ShouldLog(std::string const &type, LogLevel level) const
Definition Log.h:84
void CreateAppenderFromConfig(std::string const &name)
Definition Log.cpp:57
Appender * GetAppenderByName(std::string const &name)
Definition Log.cpp:48
void SetRealmId(uint32 id)
Definition Log.cpp:349
void write(LogMessage *msg) const
Definition Log.cpp:258
bool SetLogLevel(std::string const &name, char const *level, bool isLogger=true)
Definition Log.cpp:282
void LoadFromConfig()
Definition Log.cpp:369
std::string m_logsTimestamp
Definition Log.h:62
void ReadAppendersFromConfig()
Definition Log.cpp:209
uint8 AppenderId
Definition Log.h:59
static std::string GetTimestampStr()
Definition Log.cpp:272
void void outCommand(uint32 account, const char *str,...) ATTR_PRINTF(3
Definition Log.cpp:329
LogWorker * worker
Definition Log.h:64
LoggerMap loggers
Definition Log.h:58
std::string m_logsDir
Definition Log.h:61
void vlog(std::string const &f, LogLevel level, char const *str, va_list argptr)
Definition Log.cpp:251
void Close()
Definition Log.cpp:356
void CreateLoggerFromConfig(std::string const &name)
Definition Log.cpp:149
void void void outCharDump(char const *str, uint32 account_id, uint32 guid, char const *name)
Definition Log.cpp:311
Log()
Definition Log.cpp:20
void ReadLoggersFromConfig()
Definition Log.cpp:220
Logger const * GetLoggerByType(std::string const &type) const
Definition Log.h:67
void addAppender(uint8 type, Appender *)
Definition Logger.cpp:26
void write(LogMessage &message) const
Definition Logger.cpp:41
void Create(std::string const &name, LogLevel level)
Definition Logger.cpp:10
std::string const & getName() const
Definition Logger.cpp:16
size_type size() const
Definition Util.h:46
StorageType::const_iterator const_iterator
Definition Util.h:35
const_iterator begin() const
Definition Util.h:43
bool LocalTime(time_t const &time, tm &result)
Definition TimeUtils.h:57
std::string type
Definition Appender.h:56
std::string text
Definition Appender.h:57
std::string param1
Definition Appender.h:59