244 lines
5.7 KiB
C++
244 lines
5.7 KiB
C++
|
|
#include "logger.h"
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <QDateTime>
|
|
#include <QThread>
|
|
#include <QObject>
|
|
#include <iostream>
|
|
|
|
Logger* Logger::defaultLogger=nullptr;
|
|
|
|
|
|
QThreadStorage<QHash<QString,QString>*> Logger::logVars;
|
|
|
|
|
|
QMutex Logger::mutex;
|
|
|
|
|
|
Logger::Logger(QObject* parent)
|
|
: QObject(parent),
|
|
msgFormat("{timestamp} {type} {msg}"),
|
|
timestampFormat("dd.MM.yyyy hh:mm:ss.zzz"),
|
|
minLevel(QtDebugMsg),
|
|
bufferSize(0)
|
|
{}
|
|
|
|
|
|
Logger::Logger(const QString msgFormat, const QString timestampFormat, const QtMsgType minLevel, const int bufferSize, QObject* parent)
|
|
:QObject(parent)
|
|
{
|
|
this->msgFormat=msgFormat;
|
|
this->timestampFormat=timestampFormat;
|
|
this->minLevel=minLevel;
|
|
this->bufferSize=bufferSize;
|
|
}
|
|
|
|
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
|
static QRecursiveMutex recursiveMutex;
|
|
static QMutex nonRecursiveMutex;
|
|
#else
|
|
static QMutex recursiveMutex(QMutex::Recursive);
|
|
static QMutex nonRecursiveMutex(QMutex::NonRecursive);
|
|
#endif
|
|
|
|
void Logger::msgHandler(const QtMsgType type, const QString &message, const QString &file, const QString &function, const int line)
|
|
{
|
|
|
|
recursiveMutex.lock();
|
|
|
|
if (defaultLogger && nonRecursiveMutex.tryLock())
|
|
{
|
|
defaultLogger->log(type, message, file, function, line);
|
|
nonRecursiveMutex.unlock();
|
|
}
|
|
else
|
|
{
|
|
fputs(qPrintable(message),stderr);
|
|
fflush(stderr);
|
|
}
|
|
|
|
if (type==QtFatalMsg)
|
|
{
|
|
abort();
|
|
}
|
|
|
|
recursiveMutex.unlock();
|
|
}
|
|
|
|
|
|
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
|
|
void Logger::msgHandler5(const QtMsgType type, const QMessageLogContext &context, const QString &message)
|
|
{
|
|
(void)(context);
|
|
msgHandler(type,message,context.file,context.function,context.line);
|
|
}
|
|
#else
|
|
void Logger::msgHandler4(const QtMsgType type, const char* message)
|
|
{
|
|
msgHandler(type,message);
|
|
}
|
|
#endif
|
|
|
|
|
|
Logger::~Logger()
|
|
{
|
|
if (defaultLogger==this)
|
|
{
|
|
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
|
|
qInstallMessageHandler(nullptr);
|
|
#else
|
|
qInstallMsgHandler(nullptr);
|
|
#endif
|
|
defaultLogger=nullptr;
|
|
}
|
|
}
|
|
|
|
|
|
void Logger::write(const LogMessage* logMessage)
|
|
{
|
|
fputs(qPrintable(logMessage->toString(msgFormat,timestampFormat)), stderr);
|
|
fflush(stderr);
|
|
}
|
|
|
|
|
|
void Logger::installMsgHandler()
|
|
{
|
|
defaultLogger=this;
|
|
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
|
|
qInstallMessageHandler(msgHandler5);
|
|
#else
|
|
qInstallMsgHandler(msgHandler4);
|
|
#endif
|
|
}
|
|
|
|
|
|
void Logger::set(const QString& name, const QString& value)
|
|
{
|
|
mutex.lock();
|
|
if (!logVars.hasLocalData())
|
|
{
|
|
logVars.setLocalData(new QHash<QString,QString>);
|
|
}
|
|
logVars.localData()->insert(name,value);
|
|
mutex.unlock();
|
|
}
|
|
|
|
|
|
void Logger::clear(const bool buffer, const bool variables)
|
|
{
|
|
mutex.lock();
|
|
if (buffer && buffers.hasLocalData())
|
|
{
|
|
QList<LogMessage*>* buffer=buffers.localData();
|
|
while (buffer && !buffer->isEmpty())
|
|
{
|
|
LogMessage* logMessage=buffer->takeLast();
|
|
delete logMessage;
|
|
}
|
|
}
|
|
if (variables && logVars.hasLocalData())
|
|
{
|
|
logVars.localData()->clear();
|
|
}
|
|
mutex.unlock();
|
|
}
|
|
|
|
|
|
void Logger::log(const QtMsgType type, const QString& message, const QString &file, const QString &function, const int line)
|
|
{
|
|
bool toPrint=false;
|
|
|
|
switch (type)
|
|
{
|
|
case QtDebugMsg:
|
|
if (minLevel==QtDebugMsg)
|
|
{
|
|
toPrint=true;
|
|
}
|
|
break;
|
|
|
|
#if QT_VERSION >= QT_VERSION_CHECK(5, 5, 0)
|
|
case QtInfoMsg:
|
|
if (minLevel==QtDebugMsg ||
|
|
minLevel==QtInfoMsg)
|
|
{
|
|
toPrint=true;
|
|
}
|
|
break;
|
|
#endif
|
|
|
|
case QtWarningMsg:
|
|
if (minLevel==QtDebugMsg ||
|
|
#if QT_VERSION >= QT_VERSION_CHECK(5, 5, 0)
|
|
minLevel==QtInfoMsg ||
|
|
#endif
|
|
minLevel==QtWarningMsg)
|
|
{
|
|
toPrint=true;
|
|
}
|
|
break;
|
|
|
|
case QtCriticalMsg:
|
|
if (minLevel==QtDebugMsg ||
|
|
#if QT_VERSION >= QT_VERSION_CHECK(5, 5, 0)
|
|
minLevel==QtInfoMsg ||
|
|
#endif
|
|
minLevel==QtWarningMsg ||
|
|
minLevel==QtCriticalMsg)
|
|
{
|
|
toPrint=true;
|
|
}
|
|
break;
|
|
|
|
case QtFatalMsg:
|
|
toPrint=true;
|
|
break;
|
|
|
|
default:
|
|
toPrint=true;
|
|
}
|
|
|
|
mutex.lock();
|
|
|
|
LogMessage* logMessage=new LogMessage(type,message,logVars.localData(),file,function,line);
|
|
std::cout << qPrintable(logMessage->toString(msgFormat,"hh:mm:ss.zzz")) << std::flush;
|
|
if (bufferSize>0)
|
|
{
|
|
|
|
if (!buffers.hasLocalData())
|
|
{
|
|
buffers.setLocalData(new QList<LogMessage*>());
|
|
}
|
|
QList<LogMessage*>* buffer=buffers.localData();
|
|
|
|
|
|
buffer->append(logMessage);
|
|
|
|
if (buffer->size()>bufferSize)
|
|
{
|
|
delete buffer->takeFirst();
|
|
}
|
|
|
|
if (toPrint)
|
|
{
|
|
while (!buffer->isEmpty())
|
|
{
|
|
LogMessage* logMessage=buffer->takeFirst();
|
|
write(logMessage);
|
|
delete logMessage;
|
|
}
|
|
}
|
|
}
|
|
|
|
else
|
|
{
|
|
if (toPrint)
|
|
{
|
|
LogMessage logMessage(type,message,logVars.localData(),file,function,line);
|
|
write(&logMessage);
|
|
}
|
|
}
|
|
mutex.unlock();
|
|
}
|