1
// -*- mode: c++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2; coding: utf-8-unix -*-
2
// ***** BEGIN LICENSE BLOCK *****
3
//////////////////////////////////////////////////////////////////////////
4
// Copyright (c) 2011-2014 RALOVICH, Kristóf //
6
// This program is free software; you can redistribute it and/or modify //
7
// it under the terms of the GNU General Public License as published by //
8
// the Free Software Foundation; either version 3 of the License, or //
9
// (at your option) any later version. //
11
// This program is distributed in the hope that it will be useful, //
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
14
// GNU General Public License for more details. //
16
//////////////////////////////////////////////////////////////////////////
17
// ***** END LICENSE BLOCK *****
21
#include "LazySingleton.hpp"
43
LOG_RAW, //< dont insert any prefix
44
LOG_ERR, //< runtime error
45
LOG_WARN, //< suppressable runtime error
46
LOG_INF, //< runtime information
47
LOG_DBG, //< debug info, mainly for developers
48
LOG_DBG2, //< more debug info
49
LOG_DBG3 //< even more debug info (function trace, )
53
# define psoLogMaxLogLevel antpm::LOG_DBG3
55
# define psoLogMaxLogLevel antpm::LOG_DBG3
60
logLevelToString(const LogLevel& level)
64
case LOG_RAW: return "";
65
case LOG_ERR: return "ERROR: ";
66
case LOG_WARN: return "WW: ";
67
case LOG_INF: return "II: ";
68
case LOG_DBG: return "DBG: ";
69
case LOG_DBG2: return "DBG: ";
70
case LOG_DBG3: return "DBG: ";
77
operator<< (std::ostream& left, const LogLevel level)
79
return left << logLevelToString(level);
82
extern const std::string getVersionString();
86
* Encapsulates a series of C++ style (<<) writes to a log in a
87
* transactional manner.
93
inline LogLine(const LogLevel& level = LOG_INF) : _level(level) {}
94
inline virtual ~LogLine() { T::instance()->print(_level, _oss.str()); }
95
inline std::ostringstream& get() { return _oss; }
97
LogLine(const LogLine&);
98
LogLine& operator= (const LogLine&);
100
const LogLevel _level;
101
std::ostringstream _oss;
108
: public ClassInstantiator<Log>
109
, public LazySingleton<Log, Log>
112
inline Log(const char* logFileName = NULL);
114
inline virtual ~Log();
117
inline virtual int lprintf2(const LogLevel level,
119
...) __attribute__ ((format (printf, 3, 4)));
121
inline virtual int lprintf2(const LogLevel level,
125
inline virtual int vlprintf(const LogLevel level,
128
inline virtual int print(const LogLevel level, const std::string& msg);
130
inline virtual void addSink(std::ostream& os);
131
inline virtual void delSink(std::ostream& os);
133
inline virtual const LogLevel& getLogReportingLevel() const;
134
inline virtual void setLogReportingLevel(const LogLevel& logReportingLevel);
136
inline int writeStreams(const std::string& s);
149
::ctime_s(tmp, 26, <ime);
151
::ctime_r(<ime, tmp);
153
return std::string(tmp);
156
typedef std::list<std::ostream*> SinkList;
159
LogLevel _logReportingLevel;
162
friend class antpm::ClassInstantiator<Log>;
165
Log::Log(const char* logFileName)
166
: _logReportingLevel(psoLogMaxLogLevel)
168
std::ios_base::sync_with_stdio(false);
175
// rotate previous log file
176
if(::access(logFileName, 0x00) != -1)
178
std::string old = std::string(logFileName) + std::string(".old");
179
::remove(old.c_str());
180
::rename(logFileName, old.c_str());
183
_ofs.open(logFileName, std::ios::out | std::ios::trunc);
186
std::cerr << LOG_ERR << __FUNCTION__ << ": Unable to open log file \""
187
<< logFileName << "\" at " << getTimeStamp() << std::endl;
193
std::string ts(getTimeStamp());
194
this->lprintf2(LOG_INF,
195
"%s(): Log file \"%s\" opened at %s",
199
std::string v(antpm::getVersionString());
200
this->lprintf2(LOG_INF,
203
this->lprintf2(LOG_RAW, "logging level: %d\n", this->_logReportingLevel);
211
this->lprintf2(LOG_INF,
212
"%s(): Closing log file at %s",
214
getTimeStamp().c_str());
219
Log::lprintf2(const LogLevel level,
224
va_start(args, format);
225
int chars = this->vlprintf(level,
233
Log::vlprintf(const LogLevel level,
237
std::string s(logLevelToString(level));
247
#ifdef __PSO_BUILD_WIN__
248
_RPT0(_CRT_WARN, s.c_str());
251
return writeStreams(s);
255
Log::print(const LogLevel level, const std::string& msg)
257
const std::string s(std::string(logLevelToString(level)) + msg);
260
_RPT0(_CRT_WARN, s.c_str());
263
return writeStreams(s);
267
Log::addSink(std::ostream& os)
269
_sinks.push_back(&os);
274
Log::delSink(std::ostream& os)
280
Log::getLogReportingLevel() const
282
return _logReportingLevel;
286
Log::setLogReportingLevel(const LogLevel& logReportingLevel)
288
_logReportingLevel = logReportingLevel;
289
this->lprintf2(LOG_RAW, "logging level: %d\n", this->_logReportingLevel);
293
Log::writeStreams(const std::string& s)
301
for(SinkList::iterator i = _sinks.begin(); i != _sinks.end(); i++)
303
(*i)->write(s.c_str(), s.length());
310
return (int)s.length();
316
// ClassInstantiator<Log>::instantiate()
318
// return new Log("antpm.txt");
325
// ClassInstantiator<Log>::instantiate<const char*>(const char* p1)
327
// return new Log(p1);
334
#define lprintf(level, format, ...) \
335
if(level > psoLogMaxLogLevel) \
337
else if(level > antpm::Log::instance()->getLogReportingLevel()) \
339
else antpm::Log::instance()->lprintf2(level, format, __VA_ARGS__)
341
#define lprintf(level, format, ...) \
342
if(level > psoLogMaxLogLevel) \
344
else if(level > antpm::Log::instance()->getLogReportingLevel()) \
346
else antpm::Log::instance()->lprintf2(level, format, ##__VA_ARGS__)
350
if(level > psoLogMaxLogLevel) \
352
else if(level > antpm::Log::instance()->getLogReportingLevel()) \
354
else antpm::LogLine<antpm::Log>(level).get()
357
* Start a log line beginning with the name of the calling function.
359
#define LOGT(level) \
360
if(level > psoLogMaxLogLevel) \
362
else if(level > antpm::Log::instance()->getLogReportingLevel()) \
364
else antpm::LogLine<antpm::Log>(level).get() \
365
<< __FILE__ << ":" << __LINE__ << " " \
366
<< __FUNCTION__ << "(): "
368
//#define logt(level) psoLogt(level)
370
//#define log(level) psoLog(level)