2013-10-05 23:13:40 +00:00
|
|
|
// Copyright (c) 2010, Razvan Petru
|
|
|
|
// All rights reserved.
|
|
|
|
|
|
|
|
// Redistribution and use in source and binary forms, with or without modification,
|
|
|
|
// are permitted provided that the following conditions are met:
|
|
|
|
|
|
|
|
// * Redistributions of source code must retain the above copyright notice, this
|
|
|
|
// list of conditions and the following disclaimer.
|
|
|
|
// * Redistributions in binary form must reproduce the above copyright notice, this
|
|
|
|
// list of conditions and the following disclaimer in the documentation and/or other
|
|
|
|
// materials provided with the distribution.
|
|
|
|
// * The name of the contributors may not be used to endorse or promote products
|
|
|
|
// derived from this software without specific prior written permission.
|
|
|
|
|
|
|
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
|
|
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
|
|
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
|
|
// IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
|
|
|
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
|
|
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
|
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
|
|
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
|
|
|
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
|
|
|
// OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
|
|
|
|
#include "QsLog.h"
|
|
|
|
#include "QsLogDest.h"
|
|
|
|
#include <QMutex>
|
|
|
|
#include <QList>
|
|
|
|
#include <QDateTime>
|
|
|
|
#include <QtGlobal>
|
|
|
|
#include <cassert>
|
|
|
|
#include <cstdlib>
|
|
|
|
#include <stdexcept>
|
|
|
|
|
|
|
|
namespace QsLogging
|
|
|
|
{
|
|
|
|
typedef QList<Destination *> DestinationList;
|
|
|
|
|
2015-01-12 21:18:26 +00:00
|
|
|
static const char *LevelStrings[] = {"TRACE", "DEBUG", "INFO", "WARN", "ERROR", "FATAL", "UNKNOWN"};
|
2013-10-05 23:13:40 +00:00
|
|
|
|
|
|
|
static const char *LevelToText(Level theLevel)
|
|
|
|
{
|
|
|
|
if (theLevel > FatalLevel)
|
|
|
|
{
|
|
|
|
assert(!"bad log level");
|
|
|
|
return LevelStrings[UnknownLevel];
|
|
|
|
}
|
|
|
|
return LevelStrings[theLevel];
|
|
|
|
}
|
|
|
|
|
|
|
|
class LoggerImpl
|
|
|
|
{
|
|
|
|
public:
|
2013-10-06 01:07:57 +00:00
|
|
|
LoggerImpl() : level(InfoLevel)
|
2013-10-05 23:13:40 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
QMutex logMutex;
|
|
|
|
Level level;
|
|
|
|
DestinationList destList;
|
2015-01-12 21:18:26 +00:00
|
|
|
QDateTime startTime;
|
2013-10-05 23:13:40 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
Logger::Logger() : d(new LoggerImpl)
|
|
|
|
{
|
2015-01-12 21:18:26 +00:00
|
|
|
d->startTime = QDateTime::currentDateTime();
|
2013-10-05 23:13:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Logger::~Logger()
|
|
|
|
{
|
|
|
|
delete d;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Logger::addDestination(Destination *destination)
|
|
|
|
{
|
|
|
|
assert(destination);
|
|
|
|
d->destList.push_back(destination);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Logger::setLoggingLevel(Level newLevel)
|
|
|
|
{
|
|
|
|
d->level = newLevel;
|
|
|
|
}
|
|
|
|
|
|
|
|
Level Logger::loggingLevel() const
|
|
|
|
{
|
|
|
|
return d->level;
|
|
|
|
}
|
|
|
|
|
2015-01-12 21:18:26 +00:00
|
|
|
QDateTime Logger::timeOfStart() const
|
|
|
|
{
|
|
|
|
return d->startTime;
|
|
|
|
}
|
|
|
|
|
|
|
|
qint64 Logger::timeSinceStart() const
|
|
|
|
{
|
|
|
|
return d->startTime.msecsTo(QDateTime::currentDateTime());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-10-05 23:13:40 +00:00
|
|
|
//! creates the complete log message and passes it to the logger
|
|
|
|
void Logger::Helper::writeToLog()
|
|
|
|
{
|
|
|
|
const char *const levelName = LevelToText(level);
|
|
|
|
Logger &logger = Logger::instance();
|
2015-01-12 21:18:26 +00:00
|
|
|
qint64 msecstotal = logger.timeSinceStart();
|
|
|
|
qint64 seconds = msecstotal / 1000;
|
|
|
|
qint64 msecs = msecstotal % 1000;
|
|
|
|
QString foo;
|
|
|
|
char buf[1024];
|
|
|
|
|
|
|
|
::snprintf(buf, 1024, "%5lld.%03lld", seconds, msecs);
|
|
|
|
|
|
|
|
const QString completeMessage(QString("%1\t%2\t%3").arg(buf).arg(levelName, 5).arg(buffer));
|
|
|
|
|
2013-10-05 23:13:40 +00:00
|
|
|
QMutexLocker lock(&logger.d->logMutex);
|
|
|
|
logger.write(completeMessage);
|
|
|
|
}
|
|
|
|
|
|
|
|
Logger::Helper::Helper(Level logLevel) : level(logLevel), qtDebug(&buffer)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
Logger::Helper::~Helper()
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
writeToLog();
|
|
|
|
}
|
|
|
|
catch (std::exception &e)
|
|
|
|
{
|
|
|
|
// you shouldn't throw exceptions from a sink
|
|
|
|
Q_UNUSED(e);
|
|
|
|
assert(!"exception in logger helper destructor");
|
|
|
|
throw;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//! sends the message to all the destinations
|
|
|
|
void Logger::write(const QString &message)
|
|
|
|
{
|
|
|
|
for (DestinationList::iterator it = d->destList.begin(), endIt = d->destList.end();
|
|
|
|
it != endIt; ++it)
|
|
|
|
{
|
|
|
|
if (!(*it))
|
|
|
|
{
|
|
|
|
assert(!"null log destination");
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
(*it)->write(message);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-12-11 19:17:23 +00:00
|
|
|
void Logger::removeDestination(Destination* destination)
|
|
|
|
{
|
|
|
|
d->destList.removeAll(destination);
|
|
|
|
}
|
|
|
|
|
2013-10-05 23:13:40 +00:00
|
|
|
} // end namespace
|