mirror of
https://github.com/f4exb/sdrangel.git
synced 2024-12-23 10:05:46 -05:00
193 lines
4.8 KiB
C++
193 lines
4.8 KiB
C++
/**
|
|
@file
|
|
@author Stefan Frings
|
|
*/
|
|
|
|
#include "logger.h"
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <QMutex>
|
|
#include <QDateTime>
|
|
#include <QThread>
|
|
#include <QObject>
|
|
|
|
using namespace qtwebapp;
|
|
|
|
Logger* Logger::defaultLogger=0;
|
|
|
|
|
|
QThreadStorage<QHash<QString,QString>*> Logger::logVars;
|
|
|
|
|
|
QMutex Logger::mutex;
|
|
|
|
|
|
Logger::Logger(QObject* parent)
|
|
: QObject(parent),
|
|
msgFormat("{timestamp} {type} {msg}"),
|
|
timestampFormat("yyyy-MM-dd 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;
|
|
}
|
|
|
|
|
|
void Logger::msgHandler(const QtMsgType type, const QString &message, const QString &file, const QString &function, const int line)
|
|
{
|
|
static QMutex recursiveMutex(QMutex::Recursive);
|
|
static QMutex nonRecursiveMutex(QMutex::NonRecursive);
|
|
|
|
// Prevent multiple threads from calling this method simultaneoulsy.
|
|
// But allow recursive calls, which is required to prevent a deadlock
|
|
// if the logger itself produces an error message.
|
|
recursiveMutex.lock();
|
|
|
|
// Fall back to stderr when this method has been called recursively.
|
|
if (defaultLogger && nonRecursiveMutex.tryLock())
|
|
{
|
|
defaultLogger->log(type, message, file, function, line);
|
|
nonRecursiveMutex.unlock();
|
|
}
|
|
else
|
|
{
|
|
fputs(qPrintable(message),stderr);
|
|
fflush(stderr);
|
|
}
|
|
|
|
// Abort the program after logging a fatal message
|
|
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); // suppress "unused parameter" warning
|
|
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(0);
|
|
#else
|
|
qInstallMsgHandler(0);
|
|
#endif
|
|
defaultLogger=0;
|
|
}
|
|
}
|
|
|
|
|
|
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)
|
|
{
|
|
mutex.lock();
|
|
|
|
// If the buffer is enabled, write the message into it
|
|
if (bufferSize>0) {
|
|
// Create new thread local buffer, if necessary
|
|
if (!buffers.hasLocalData()) {
|
|
buffers.setLocalData(new QList<LogMessage*>());
|
|
}
|
|
QList<LogMessage*>* buffer=buffers.localData();
|
|
// Append the decorated log message
|
|
LogMessage* logMessage=new LogMessage(type,message,logVars.localData(),file,function,line);
|
|
buffer->append(logMessage);
|
|
// Delete oldest message if the buffer became too large
|
|
if (buffer->size()>bufferSize)
|
|
{
|
|
delete buffer->takeFirst();
|
|
}
|
|
// If the type of the message is high enough, print the whole buffer
|
|
if (type>=minLevel) {
|
|
while (!buffer->isEmpty())
|
|
{
|
|
LogMessage* logMessage=buffer->takeFirst();
|
|
write(logMessage);
|
|
delete logMessage;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Buffer is disabled, print the message if the type is high enough
|
|
else {
|
|
if (type>=minLevel)
|
|
{
|
|
LogMessage logMessage(type,message,logVars.localData(),file,function,line);
|
|
write(&logMessage);
|
|
}
|
|
}
|
|
mutex.unlock();
|
|
}
|