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.
filelogger.cpp
Go to the documentation of this file.
1 
6 #include "filelogger.h"
7 #include <QTime>
8 #include <QStringList>
9 #include <QThread>
10 #include <QtGlobal>
11 #include <QFile>
12 #include <QTimerEvent>
13 #include <QDir>
14 #include <QFileInfo>
15 #include <stdio.h>
16 
17 using namespace qtwebapp;
18 
20 {
21  mutex.lock();
22 
23  if (useQtSettings) {
25  } else {
27  }
28 
29  mutex.unlock();
30 }
31 
33 {
34  // Save old file name for later comparison with new settings
35  QString oldFileName = fileName;
36 
37  // Load new config settings
38  settings->sync();
39  fileName = settings->value("fileName").toString();
40 
41  // Convert relative fileName to absolute, based on the directory of the config file.
42 #ifdef Q_OS_WIN32
43  if (QDir::isRelativePath(fileName) && settings->format()!=QSettings::NativeFormat)
44 #else
45  if (QDir::isRelativePath(fileName))
46 #endif
47  {
48  QFileInfo configFile(settings->fileName());
49  fileName = QFileInfo(configFile.absolutePath(), fileName).absoluteFilePath();
50  }
51 
52  maxSize = settings->value("maxSize", 0).toLongLong();
53  maxBackups = settings->value("maxBackups", 0).toInt();
54  msgFormat = settings->value("msgFormat", "{timestamp} {type} {msg}").toString();
55  timestampFormat = settings->value("timestampFormat", "yyyy-MM-dd HH:mm:ss.zzz").toString();
56  minLevel = static_cast<QtMsgType>(settings->value("minLevel", 0).toInt());
57  bufferSize = settings->value("bufferSize", 0).toInt();
58 
59  // Create new file if the filename has been changed
60  if (oldFileName != fileName)
61  {
62  fprintf(stderr, "FileLogger::refreshQtSettings: Logging to %s\n", qPrintable(fileName));
63  close();
64  open();
65  }
66 }
67 
69 {
70  // Save old file name for later comparison with new settings
71  QString oldFileName = fileName;
72 
73  // Load new config settings
75 
76  // Convert relative fileName to absolute, based on the current working directory
77  if (QDir::isRelativePath(fileName)) {
78  fileName = QFileInfo(QDir::currentPath(), fileName).absoluteFilePath();
79  }
80 
87 
88  // Create new file if the filename has been changed
89  if (oldFileName != fileName)
90  {
91  fprintf(stderr, "FileLogger::refreshQtSettings: Logging to new file %s\n", qPrintable(fileName));
92  close();
93  open();
94  }
95 }
96 
97 FileLogger::FileLogger(QSettings* settings, const int refreshInterval, QObject* parent) :
98  Logger(parent), fileName(""), useQtSettings(true)
99 {
100  Q_ASSERT(settings != 0);
101  Q_ASSERT(refreshInterval >= 0);
102 
103  this->settings = settings;
104  file = 0;
105 
106  if (refreshInterval > 0) {
107  refreshTimer.start(refreshInterval, this);
108  }
109 
110  flushTimer.start(1000, this);
111 
112  refreshSettings();
113 }
114 
115 FileLogger::FileLogger(const FileLoggerSettings& settings, const int refreshInterval, QObject* parent) :
116  Logger(parent), fileName(""), useQtSettings(false)
117 {
118  Q_ASSERT(refreshInterval >= 0);
119 
121  file = 0;
122 
123  if (refreshInterval > 0) {
124  refreshTimer.start(refreshInterval, this);
125  }
126 
127  flushTimer.start(1000, this);
128 
129  refreshSettings();
130 }
131 
133 {
134  close();
135 }
136 
137 void FileLogger::write(const LogMessage* logMessage)
138 {
139  // Try to write to the file
140  if (file)
141  {
142  // Write the message
143  file->write(qPrintable(logMessage->toString(msgFormat, timestampFormat)));
144 
145  // Flush error messages immediately, to ensure that no important message
146  // gets lost when the program terinates abnormally.
147  if (logMessage->getType() >= QtCriticalMsg) {
148  file->flush();
149  }
150 
151  // Check for success
152  if (file->error())
153  {
154  close();
155  fprintf(stderr, "FileLogger::write: Cannot write to log file %s: %s\n", qPrintable(fileName), qPrintable(file->errorString()));
156  }
157  }
158 
159  // Fall-back to the super class method, if writing failed
160  if (!file && useQtSettings) {
161  Logger::write(logMessage);
162  }
163 
164 }
165 
167 {
168  if (fileName.isEmpty())
169  {
170  fprintf(stderr, "FileLogger::open: Name of logFile is empty\n");
171  }
172  else
173  {
174  file = new QFile(fileName);
175 
176  if (!file->open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text))
177  {
178  fprintf(stderr, "FileLogger::open: Cannot open log file %s: %s\n", qPrintable(fileName), qPrintable(file->errorString()));
179  file = 0;
180  }
181  else
182  {
183  fprintf(stderr, "FileLogger::open: Opened log file %s\n", qPrintable(fileName));
184  }
185  }
186 }
187 
189 {
190  if (file)
191  {
192  file->close();
193  delete file;
194  file = 0;
195  }
196 }
197 
199 {
200  fprintf(stderr, "FileLogger::rotate\n");
201  // count current number of existing backup files
202  int count = 0;
203 
204  forever
205  {
206  QFile bakFile(QString("%1.%2").arg(fileName).arg(count + 1));
207 
208  if (bakFile.exists()) {
209  ++count;
210  } else {
211  break;
212  }
213  }
214 
215  // Remove all old backup files that exceed the maximum number
216  while (maxBackups > 0 && count >= maxBackups)
217  {
218  QFile::remove(QString("%1.%2").arg(fileName).arg(count));
219  --count;
220  }
221 
222  // Rotate backup files
223  for (int i = count; i > 0; --i)
224  {
225  QFile::rename(QString("%1.%2").arg(fileName).arg(i), QString("%1.%2").arg(fileName).arg(i + 1));
226  }
227 
228  // Backup the current logfile
229  QFile::rename(fileName, fileName + ".1");
230 }
231 
232 void FileLogger::timerEvent(QTimerEvent* event)
233 {
234  if (!event) {
235  return;
236  } else if (event->timerId() == refreshTimer.timerId()) {
237  refreshSettings();
238  }
239  else if (event->timerId() == flushTimer.timerId() && file)
240  {
241  mutex.lock();
242 
243  // Flush the I/O buffer
244  file->flush();
245 
246  // Rotate the file if it is too large
247  if (maxSize > 0 && file->size() >= maxSize)
248  {
249  close();
250  rotate();
251  open();
252  }
253 
254  mutex.unlock();
255  }
256 }
void refreshFileLogSettings()
Definition: filelogger.cpp:68
virtual void write(const LogMessage *logMessage)
Definition: filelogger.cpp:137
QString timestampFormat
Definition: logger.h:133
QtMsgType getType() const
Definition: logmessage.cpp:87
QtMsgType minLevel
Definition: logger.h:136
FileLogger(QSettings *settings, const int refreshInterval=10000, QObject *parent=0)
Definition: filelogger.cpp:97
Fixed< IntType, IntBits > arg(const std::complex< Fixed< IntType, IntBits > > &val)
Definition: fixed.h:2401
QSettings * settings
Definition: filelogger.h:120
virtual void write(const LogMessage *logMessage)
Definition: logger.cpp:104
int32_t i
Definition: decimators.h:244
QBasicTimer refreshTimer
Definition: filelogger.h:129
QString toString(const QString &msgFormat, const QString &timestampFormat) const
Definition: logmessage.cpp:29
QString msgFormat
Definition: logger.h:130
FileLoggerSettings fileLoggerSettings
Definition: filelogger.h:123
QBasicTimer flushTimer
Definition: filelogger.h:132
void timerEvent(QTimerEvent *event)
Definition: filelogger.cpp:232
static QMutex mutex
Definition: logger.h:142