SDRAngel  4.11.5
Developer docs for <a href="https://github.com/f4exb/sdrangel">SDRangel<\a>, an Open Source Qt5 / OpenGL 3.0+ SDR and signal analyzer frontend to various hardware.
logger.cpp
Go to the documentation of this file.
1 
6 #include "logger.h"
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <QMutex>
10 #include <QDateTime>
11 #include <QThread>
12 #include <QObject>
13 
14 using namespace qtwebapp;
15 
17 
18 
19 QThreadStorage<QHash<QString,QString>*> Logger::logVars;
20 
21 
22 QMutex Logger::mutex;
23 
24 
25 Logger::Logger(QObject* parent)
26  : QObject(parent),
27  msgFormat("{timestamp} {type} {msg}"),
28  timestampFormat("yyyy-MM-dd HH:mm:ss.zzz"),
29  minLevel(QtDebugMsg),
30  bufferSize(0)
31  {}
32 
33 
34 Logger::Logger(const QString msgFormat, const QString timestampFormat, const QtMsgType minLevel, const int bufferSize, QObject* parent)
35  :QObject(parent)
36 {
37  this->msgFormat=msgFormat;
38  this->timestampFormat=timestampFormat;
39  this->minLevel=minLevel;
40  this->bufferSize=bufferSize;
41 }
42 
43 
44 void Logger::msgHandler(const QtMsgType type, const QString &message, const QString &file, const QString &function, const int line)
45 {
46  static QMutex recursiveMutex(QMutex::Recursive);
47  static QMutex nonRecursiveMutex(QMutex::NonRecursive);
48 
49  // Prevent multiple threads from calling this method simultaneoulsy.
50  // But allow recursive calls, which is required to prevent a deadlock
51  // if the logger itself produces an error message.
52  recursiveMutex.lock();
53 
54  // Fall back to stderr when this method has been called recursively.
55  if (defaultLogger && nonRecursiveMutex.tryLock())
56  {
57  defaultLogger->log(type, message, file, function, line);
58  nonRecursiveMutex.unlock();
59  }
60  else
61  {
62  fputs(qPrintable(message),stderr);
63  fflush(stderr);
64  }
65 
66  // Abort the program after logging a fatal message
67  if (type==QtFatalMsg)
68  {
69  abort();
70  }
71 
72  recursiveMutex.unlock();
73 }
74 
75 
76 #if QT_VERSION >= 0x050000
77  void Logger::msgHandler5(const QtMsgType type, const QMessageLogContext &context, const QString &message)
78  {
79  (void)(context); // suppress "unused parameter" warning
80  msgHandler(type,message,context.file,context.function,context.line);
81  }
82 #else
83  void Logger::msgHandler4(const QtMsgType type, const char* message)
84  {
85  msgHandler(type,message);
86  }
87 #endif
88 
89 
91 {
92  if (defaultLogger==this)
93  {
94 #if QT_VERSION >= 0x050000
95  qInstallMessageHandler(0);
96 #else
97  qInstallMsgHandler(0);
98 #endif
99  defaultLogger=0;
100  }
101 }
102 
103 
104 void Logger::write(const LogMessage* logMessage)
105 {
106  fputs(qPrintable(logMessage->toString(msgFormat,timestampFormat)),stderr);
107  fflush(stderr);
108 }
109 
110 
112 {
113  defaultLogger=this;
114 #if QT_VERSION >= 0x050000
115  qInstallMessageHandler(msgHandler5);
116 #else
117  qInstallMsgHandler(msgHandler4);
118 #endif
119 }
120 
121 
122 void Logger::set(const QString& name, const QString& value)
123 {
124  mutex.lock();
125  if (!logVars.hasLocalData())
126  {
127  logVars.setLocalData(new QHash<QString,QString>);
128  }
129  logVars.localData()->insert(name,value);
130  mutex.unlock();
131 }
132 
133 
134 void Logger::clear(const bool buffer, const bool variables)
135 {
136  mutex.lock();
137  if (buffer && buffers.hasLocalData())
138  {
139  QList<LogMessage*>* buffer=buffers.localData();
140  while (buffer && !buffer->isEmpty()) {
141  LogMessage* logMessage=buffer->takeLast();
142  delete logMessage;
143  }
144  }
145  if (variables && logVars.hasLocalData())
146  {
147  logVars.localData()->clear();
148  }
149  mutex.unlock();
150 }
151 
152 
153 void Logger::log(const QtMsgType type, const QString& message, const QString &file, const QString &function, const int line)
154 {
155  mutex.lock();
156 
157  // If the buffer is enabled, write the message into it
158  if (bufferSize>0) {
159  // Create new thread local buffer, if necessary
160  if (!buffers.hasLocalData()) {
161  buffers.setLocalData(new QList<LogMessage*>());
162  }
163  QList<LogMessage*>* buffer=buffers.localData();
164  // Append the decorated log message
165  LogMessage* logMessage=new LogMessage(type,message,logVars.localData(),file,function,line);
166  buffer->append(logMessage);
167  // Delete oldest message if the buffer became too large
168  if (buffer->size()>bufferSize)
169  {
170  delete buffer->takeFirst();
171  }
172  // If the type of the message is high enough, print the whole buffer
173  if (type>=minLevel) {
174  while (!buffer->isEmpty())
175  {
176  LogMessage* logMessage=buffer->takeFirst();
177  write(logMessage);
178  delete logMessage;
179  }
180  }
181  }
182 
183  // Buffer is disabled, print the message if the type is high enough
184  else {
185  if (type>=minLevel)
186  {
187  LogMessage logMessage(type,message,logVars.localData(),file,function,line);
188  write(&logMessage);
189  }
190  }
191  mutex.unlock();
192 }
QString timestampFormat
Definition: logger.h:133
virtual void log(const QtMsgType type, const QString &message, const QString &file="", const QString &function="", const int line=0)
Definition: logger.cpp:153
void installMsgHandler()
Definition: logger.cpp:111
Logger(QObject *parent)
Definition: logger.cpp:25
QtMsgType minLevel
Definition: logger.h:136
static void msgHandler(const QtMsgType type, const QString &message, const QString &file="", const QString &function="", const int line=0)
Definition: logger.cpp:44
virtual void write(const LogMessage *logMessage)
Definition: logger.cpp:104
virtual void clear(const bool buffer=true, const bool variables=true)
Definition: logger.cpp:134
static QThreadStorage< QHash< QString, QString > * > logVars
Definition: logger.h:195
static void msgHandler4(const QtMsgType type, const char *message)
Definition: logger.cpp:83
QString toString(const QString &msgFormat, const QString &timestampFormat) const
Definition: logmessage.cpp:29
QString msgFormat
Definition: logger.h:130
QThreadStorage< QList< LogMessage * > * > buffers
Definition: logger.h:198
static void set(const QString &name, const QString &value)
Definition: logger.cpp:122
static QMutex mutex
Definition: logger.h:142
virtual ~Logger()
Definition: logger.cpp:90
static Logger * defaultLogger
Definition: logger.h:153