ManaPlus
logger.cpp
Go to the documentation of this file.
1 /*
2  * The ManaPlus Client
3  * Copyright (C) 2004-2009 The Mana World Development Team
4  * Copyright (C) 2009-2010 The Mana Developers
5  * Copyright (C) 2011-2019 The ManaPlus Developers
6  *
7  * This file is part of The ManaPlus Client.
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program. If not, see <http://www.gnu.org/licenses/>.
21  */
22 
23 #include "logger.h"
24 
25 #include "settings.h"
26 
28 
29 #include "utils/cast.h"
30 #include "utils/foreach.h"
31 #include "utils/stringutils.h"
32 
33 #include <iostream>
34 
35 #ifdef WIN32
36 #include <windows.h>
37 #elif defined __APPLE__
38 #include <Carbon/Carbon.h>
39 #endif // WIN32
40 
41 #include <sys/time.h>
42 
43 #include <sstream>
44 
45 #ifdef USE_SDL2
46 #include <SDL_messagebox.h>
47 #endif // USE_SDl2
48 
49 #ifdef ENABLEDEBUGLOG
50 #if defined(__ANDROID__)
51 #include <android/log.h>
52 #ifdef SPECIAL_LOGGING
53 #define SPECIALLOG(x) __android_log_print(ANDROID_LOG_INFO, "manaplus", x);
54 #define DSPECIALLOG(x) __android_log_print(ANDROID_LOG_VERBOSE, \
55  "manaplus", x);
56 #else // SPECIAL_LOGGING
57 #define SPECIALLOG(x) if (mDebugLog) \
58  __android_log_print(ANDROID_LOG_INFO, "manaplus", x);
59 #define DSPECIALLOG(x) if (mDebugLog) \
60  __android_log_print(ANDROID_LOG_VERBOSE, "manaplus", x);
61 #endif // SPECIAL_LOGGING
62 #elif defined __native_client__
63 #ifdef SPECIAL_LOGGING
64 #define SPECIALLOG(x) std::cerr << x;
65 #define DSPECIALLOG(x) std::cerr << x;
66 #else // SPECIAL_LOGGING
67 #define SPECIALLOG(x) if (mDebugLog) \
68  std::cerr << x;
69 #define DSPECIALLOG(x) if (mDebugLog) \
70  std::cerr << x;
71 #endif // SPECIAL_LOGGING
72 #else // defined(__ANDROID__)
73 #define SPECIALLOG(x)
74 #define DSPECIALLOG(x)
75 #endif // defined(__ANDROID__)
76 #endif // ENABLEDEBUGLOG
77 
78 #include "debug.h"
79 
80 #define DATESTREAM \
81  std::string timeStr = strprintf( \
82  "[%02d:%02d:%02d.%02d]", \
83  CAST_S32(((tv.tv_sec / 60) / 60) % 24), \
84  CAST_S32((tv.tv_sec / 60) % 60), \
85  CAST_S32(tv.tv_sec % 60), \
86  CAST_S32((tv.tv_usec / 10000) % 100));
87 
88 Logger *logger = nullptr; // Log object
89 
91  mLogFile(nullptr),
92  mDelayedLog(),
93  mMutex(SDL_CreateMutex()),
94  mThreadLocked(false),
95  mLogToStandardOut(true),
96  mDebugLog(false),
97  mReportUnimplemented(false)
98 {
99 #if defined __native_client__ && defined(NACL_LOG)
100  std::cout.setf(std::ios_base::unitbuf);
101 #endif // defined __native_client__ && defined(NACL_LOG)
102 }
103 
105 {
106  closeFile();
107  SDL_DestroyMutex(mMutex);
108 }
109 
111 {
112  if (mLogFile != nullptr)
113  {
114  fclose(mLogFile);
115  mLogFile = nullptr;
116  }
117 }
118 
119 void Logger::setLogFile(const std::string &logFilename)
120 {
121  closeFile();
122 
123 #ifdef __SWITCH__
124  mLogFile = nullptr;
125 #else
126  mLogFile = fopen(logFilename.c_str(), "wt");
127 #endif
128 
129  if (mLogFile == nullptr)
130  {
131  std::cout << "Warning: error while opening " << logFilename <<
132  " for writing.\n";
133  mLogToStandardOut = true;
134  }
135  else
136  {
137  mLogToStandardOut = false;
138  }
139 }
140 
141 void Logger::log(const std::string &str)
142 {
143  log("%s", str.c_str());
144 }
145 
146 #ifdef ENABLEDEBUGLOG
147 void Logger::dlog(const std::string &str)
148 {
149  if (!mDebugLog)
150  return;
151 
152  // Get the current system time
153  timeval tv;
154  gettimeofday(&tv, nullptr);
155 
156  // Print the log entry
157  DATESTREAM
158  DSPECIALLOG(str.c_str())
159 
160  if (mLogFile != nullptr)
161  {
162  fprintf(mLogFile,
163  "%s %s\n",
164  timeStr.c_str(),
165  str.c_str());
166  }
167 
168  if (mLogToStandardOut)
169  {
170  fprintf(stdout,
171  "%s %s\n",
172  timeStr.c_str(),
173  str.c_str());
174  }
175 }
176 
177 void Logger::dlog2(const std::string &str,
178  const int pos,
179  const char* const comment)
180 {
181  if (!mDebugLog)
182  return;
183 
184  // Get the current system time
185  timeval tv;
186  gettimeofday(&tv, nullptr);
187 
188  // Print the log entry
189  DATESTREAM
190  DSPECIALLOG(str.c_str())
191 
192  if (mLogFile != nullptr)
193  {
194  if (comment != nullptr)
195  {
196  fprintf(mLogFile,
197  "%s %04d %s: %s\n",
198  timeStr.c_str(),
199  pos,
200  str.c_str(),
201  comment);
202  }
203  else
204  {
205  fprintf(mLogFile,
206  "%s %04d %s\n",
207  timeStr.c_str(),
208  pos,
209  str.c_str());
210  }
211  fflush(mLogFile);
212  }
213 
214  if (mLogToStandardOut)
215  {
216  if (comment != nullptr)
217  {
218  fprintf(stdout,
219  "%s %04d %s: %s\n",
220  timeStr.c_str(),
221  pos,
222  str.c_str(),
223  comment);
224  }
225  else
226  {
227  fprintf(stdout,
228  "%s %04d %s\n",
229  timeStr.c_str(),
230  pos,
231  str.c_str());
232  }
233  }
234 }
235 #endif // ENABLEDEBUGLOG
236 
237 void Logger::log1(const char *const buf)
238 {
240  return;
241 
242  // Get the current system time
243  timeval tv;
244  gettimeofday(&tv, nullptr);
245 
246  // Print the log entry
247  DATESTREAM
248  SPECIALLOG(buf)
249 
250  if (mLogFile != nullptr)
251  {
252  fprintf(mLogFile,
253  "%s %s\n",
254  timeStr.c_str(),
255  buf);
256  fflush(mLogFile);
257  }
258 
259  if (mLogToStandardOut)
260  {
261  fprintf(stdout,
262  "%s %s\n",
263  timeStr.c_str(),
264  buf);
265  }
266 }
267 
268 void Logger::log(const char *const log_text, ...)
269 {
271  return;
272 
273  unsigned size = 1024;
274  if (strlen(log_text) * 3 > size)
275  size = CAST_U32(strlen(log_text) * 3);
276 
277  char* buf = new char[CAST_SIZE(size + 1)];
278  va_list ap;
279 
280  // Use a temporary buffer to fill in the variables
281  va_start(ap, log_text);
282  vsnprintf(buf, size, log_text, ap);
283  buf[size] = 0;
284  va_end(ap);
285 
286  // Get the current system time
287  timeval tv;
288  gettimeofday(&tv, nullptr);
289 
290  // Print the log entry
291  DATESTREAM
292  SPECIALLOG(buf)
293 
294  if (mLogFile != nullptr)
295  {
296  fprintf(mLogFile,
297  "%s %s\n",
298  timeStr.c_str(),
299  buf);
300  fflush(mLogFile);
301  }
302 
303  if (mLogToStandardOut)
304  {
305  fprintf(stdout,
306  "%s %s\n",
307  timeStr.c_str(),
308  buf);
309  }
310 
311  // Delete temporary buffer
312  delete [] buf;
313 }
314 
315 void Logger::assertLog(const char *const log_text, ...)
316 {
318  return;
319 
320  unsigned size = 1024;
321  if (strlen(log_text) * 3 > size)
322  size = CAST_U32(strlen(log_text) * 3);
323 
324  char* buf = new char[CAST_SIZE(size + 1)];
325  va_list ap;
326 
327  // Use a temporary buffer to fill in the variables
328  va_start(ap, log_text);
329  vsnprintf(buf, size, log_text, ap);
330  buf[size] = 0;
331  va_end(ap);
332 
333  // Get the current system time
334  timeval tv;
335  gettimeofday(&tv, nullptr);
336 
337  // Print the log entry
338  DATESTREAM
339  SPECIALLOG(buf)
340 
341  if (mLogFile != nullptr)
342  {
343  fprintf(mLogFile,
344  "%s %s\n",
345  timeStr.c_str(),
346  buf);
347  fflush(mLogFile);
348  }
349 
350  if (mLogToStandardOut)
351  {
352  fprintf(stdout,
353  "%s %s\n",
354  timeStr.c_str(),
355  buf);
356  }
357 
359 
360  // Delete temporary buffer
361  delete [] buf;
362 }
363 
364 void Logger::log_r(const char *const log_text, ...)
365 {
367  return;
368 
369  SDL_mutexP(mMutex);
370 
371  unsigned size = 1024;
372  if (strlen(log_text) * 3 > size)
373  size = CAST_U32(strlen(log_text) * 3);
374 
375  char* buf = new char[CAST_SIZE(size + 1)];
376  va_list ap;
377 
378  // Use a temporary buffer to fill in the variables
379  va_start(ap, log_text);
380  vsnprintf(buf, size, log_text, ap);
381  buf[size] = 0;
382  va_end(ap);
383 
384  // Get the current system time
385  timeval tv;
386  gettimeofday(&tv, nullptr);
387 
388  // Print the log entry
389  DATESTREAM
390  SPECIALLOG(buf)
391 
392  if (mLogFile != nullptr)
393  {
394  std::string tmpStr = strprintf(
395  "%s %s\n",
396  timeStr.c_str(),
397  buf);
398  mThreadLocked = true;
399  mDelayedLog.push_back(tmpStr);
400  mThreadLocked = false;
401  }
402 
403  if (mLogToStandardOut)
404  {
405  fprintf(stdout,
406  "%s %s\n",
407  timeStr.c_str(),
408  buf);
409  }
410 
411  // Delete temporary buffer
412  delete [] buf;
413 
414  SDL_mutexV(mMutex);
415 }
416 
418 {
419  if (!mThreadLocked)
420  {
421  SDL_mutexP(mMutex);
422  FOR_EACH (STD_VECTOR<std::string>::const_iterator, it, mDelayedLog)
423  {
424  fputs((*it).c_str(), mLogFile);
425  fputs("\n", mLogFile);
426  }
427  fflush(mLogFile);
428  mDelayedLog.clear();
429  SDL_mutexV(mMutex);
430  }
431 }
432 
433 // here string must be safe for any usage
434 void Logger::safeError(const std::string &error_text)
435 {
436  log("Error: %s", error_text.c_str());
437 #ifdef USE_SDL2
438  SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR,
439  "Error",
440  error_text.c_str(),
441  nullptr);
442 #else // USE_SDL2
443 #ifdef WIN32
444  MessageBox(nullptr, error_text.c_str(), "Error", MB_ICONERROR | MB_OK);
445 #elif defined __APPLE__
446 // Str255 msg;
447 // CFStringRef error;
448 // error = CFStringCreateWithCString(nullptr,
449 // error_text.c_str(),
450 // kCFStringEncodingMacRoman);
451 // CFStringGetPascalString(error, msg, 255, kCFStringEncodingMacRoman);
452 // StandardAlert(kAlertStopAlert,
453 // (const unsigned char*)"\pError",
454 // (ConstStr255Param) msg, nullptr, nullptr);
455 #elif defined(__linux__) || defined(__linux)
456  std::cerr << "Error: " << error_text << std::endl;
457  const std::string msg = std::string("xmessage \"").append(
458  error_text).append("\"");
459  if (system(msg.c_str()) == -1)
460  std::cerr << "Error: " << error_text << std::endl;
461 #else // WIN32
462 
463  std::cerr << "Error: " << error_text << std::endl;
464 #endif // WIN32
465 #endif // USE_SDL2
466 
467  exit(1);
468 }
469 
470 // here string can be unsafe strings
471 void Logger::error(const std::string &error_text)
472 {
473  log("Error: %s", error_text.c_str());
474 #ifdef USE_SDL2
475  SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR,
476  "Error",
477  error_text.c_str(),
478  nullptr);
479 #else // USE_SDL2
480 #ifdef WIN32
481  MessageBox(nullptr, error_text.c_str(), "Error", MB_ICONERROR | MB_OK);
482 #elif defined __APPLE__
483 // Str255 msg;
484 // CFStringRef error;
485 // error = CFStringCreateWithCString(nullptr,
486 // error_text.c_str(),
487 // kCFStringEncodingMacRoman);
488 // CFStringGetPascalString(error, msg, 255, kCFStringEncodingMacRoman);
489 // StandardAlert(kAlertStopAlert,
490 // (const unsigned char*)"\pError",
491 // (ConstStr255Param) msg, nullptr, nullptr);
492 #elif defined(__linux__) || defined(__linux)
493  std::cerr << "Error: " << error_text << std::endl;
494  const std::string msg("xmessage \"Error happened. "
495  "Please see log file for more information.\"");
496  if (system(msg.c_str()) == -1)
497  std::cerr << "Error: " << error_text << std::endl;
498 #else // WIN32
499 
500  std::cerr << "Error: " << error_text << std::endl;
501 #endif // WIN32
502 #endif // USE_SDL2
503 
504  exit(1);
505 }
506 
507 void Logger::unimplemented(const int id)
508 {
510  return;
511 
512  const std::string str = strprintf("Unimplimented packet: %d (0x%x)",
513  id,
514  CAST_U32(id));
516  log(str);
517 }
518 
519 void Logger::unimplemented(const int id,
520  const int id2)
521 {
523  return;
524 
525  const std::string str = strprintf(
526  "Unimplimented field value %d for packet %d (0x%x)",
527  id2,
528  id,
529  CAST_U32(id));
531  log(str);
532 }
533 
534 void Logger::unimplemented(const uint32_t id,
535  const uint32_t id2,
536  const uint32_t id3) const
537 {
539  return;
540 
541  const std::string str = strprintf(
542  "Wrong actual or planned inbound packet size!. "
543  "Packet id: %u(0x%x), Planned size: %u, Actual size: %u",
544  id,
545  id,
546  id2,
547  id3);
549 }
550 
551 FILE *Logger::getFile() const
552 {
553  return mLogFile;
554 }
DATESTREAM
#define DATESTREAM
Definition: logger.cpp:80
Logger::getFile
FILE * getFile() const
Definition: logger.cpp:551
debugmessagelistener.h
cast.h
Logger::closeFile
void closeFile()
Definition: logger.cpp:110
CAST_SIZE
#define CAST_SIZE
Definition: cast.h:33
settings.h
logger.h
DebugMessageListener::distributeEvent
static void distributeEvent(const std::string &msg)
Definition: debugmessagelistener.cpp:29
settings
Settings settings
Definition: settings.cpp:31
Actions::msg
bool msg(InputEvent &event)
Definition: chat.cpp:38
Logger::safeError
void safeError(const std::string &error_text) __attribute__((noreturn))
Definition: logger.cpp:434
Logger::mDelayedLog
std::vector< std::string > mDelayedLog
Definition: logger.h:219
CAST_U32
#define CAST_U32
Definition: cast.h:30
Logger::mLogToStandardOut
bool mLogToStandardOut
Definition: logger.h:222
Logger::flush
void flush()
Definition: logger.cpp:417
logger
Logger * logger
Definition: logger.cpp:88
Logger::mThreadLocked
volatile bool mThreadLocked
Definition: logger.h:221
nullptr
#define nullptr
Definition: localconsts.h:44
strprintf
std::string strprintf(const char *const format,...)
Definition: stringutils.cpp:99
Logger::dlog
void dlog(const std::string &str)
Definition: logger.cpp:147
Logger::assertLog
void assertLog(const char *const log_text,...)
Definition: logger.cpp:315
Logger::setLogFile
void setLogFile(const std::string &logFilename)
Definition: logger.cpp:119
Logger::~Logger
~Logger()
Definition: logger.cpp:104
stringutils.h
Logger::log1
void log1(const char *const log_text)
Definition: logger.cpp:237
Logger::mDebugLog
bool mDebugLog
Definition: logger.h:223
SPECIALLOG
#define SPECIALLOG(x)
Definition: logger.cpp:73
Logger::dlog2
void dlog2(const std::string &str, const int pos, const char *const comment)
Definition: logger.cpp:177
foreach.h
EmoteDB::size
int size()
Definition: emotedb.cpp:305
Logger::log_r
void log_r(const char *const log_text,...)
Definition: logger.cpp:364
Settings::disableLoggingInGame
bool disableLoggingInGame
Definition: settings.h:160
Logger::Logger
Logger()
Definition: logger.cpp:90
Logger
Definition: logger.h:67
Logger::mMutex
SDL_mutex * mMutex
Definition: logger.h:220
Logger::mReportUnimplemented
bool mReportUnimplemented
Definition: logger.h:224
Logger::unimplemented
void unimplemented(const int id)
Definition: logger.cpp:507
Logger::error
void error(const std::string &error_text) __attribute__((noreturn))
Definition: logger.cpp:471
DSPECIALLOG
#define DSPECIALLOG(x)
Definition: logger.cpp:74
Logger::mLogFile
FILE * mLogFile
Definition: logger.h:218
Logger::log
void log(const char *const log_text,...)
Definition: logger.cpp:268
FOR_EACH
#define FOR_EACH(type, iter, array)
Definition: foreach.h:24
debug.h