AntiMicroX
logger.h
Go to the documentation of this file.
1 /* antimicrox Gamepad to KB+M event mapper
2  * Copyright (C) 2015 Travis Nickles <nickles.travis@gmail.com>
3  * Copyright (C) 2020 Jagoda Górska <juliagoda.pl@protonmail>
4  * Copyright (C) 2020 Paweł Kotiuk
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10 
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15 
16  * You should have received a copy of the GNU General Public License
17  * along with this program. If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #ifndef LOGGER_H
21 #define LOGGER_H
22 
23 #include <QFile>
24 #include <QMutex>
25 #include <QObject>
26 #include <QTextStream>
27 #include <QThread>
28 
29 #include <sstream>
30 
38 #define PRINT_STDOUT() StreamPrinter(stdout, __LINE__, __FILE__)
39 #define PRINT_STDERR() StreamPrinter(stderr, __LINE__, __FILE__)
40 
41 #define DEBUG() LogHelper(Logger::LogLevel::LOG_DEBUG, __LINE__, __FILE__)
42 #define VERBOSE() LogHelper(Logger::LogLevel::LOG_VERBOSE, __LINE__, __FILE__)
43 #define INFO() LogHelper(Logger::LogLevel::LOG_INFO, __LINE__, __FILE__)
44 #define WARN() LogHelper(Logger::LogLevel::LOG_WARNING, __LINE__, __FILE__)
45 #define ERROR() LogHelper(Logger::LogLevel::LOG_ERROR, __LINE__, __FILE__)
46 
57 class Logger : public QObject
58 {
59  Q_OBJECT
60  Q_ENUMS(LogLevel)
61 
62  public:
63  enum LogLevel
64  {
65  LOG_NONE = 0,
66  LOG_ERROR = 1,
68  LOG_INFO = 3,
70  LOG_DEBUG = 5,
72  };
73 
74  ~Logger();
75 
76  static void loggerMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg);
77 
78  static void setLogLevel(LogLevel level);
80  static bool isDebugEnabled();
81 
82  static void setCurrentStream(QTextStream *stream);
83  static void setCurrentLogFile(QString filename);
84  static QString getCurrentLogFile();
85  bool isWritingToFile();
86  static QTextStream *getCurrentStream();
87 
94  inline static Logger *getInstance(bool raiseExceptionForNull = true)
95  {
96  if (raiseExceptionForNull && instance == nullptr)
97  {
98  throw std::runtime_error("There is no logger instance");
99  }
100  return instance;
101  }
102 
103  static Logger *createInstance(QTextStream *stream = nullptr, LogLevel outputLevel = LOG_INFO, QObject *parent = nullptr);
104 
105  protected:
106  explicit Logger(QTextStream *stream, LogLevel output_lvl = LOG_INFO, QObject *parent = nullptr);
107  void closeLogger(bool closeStream = true);
108 
109  static Logger *instance;
110 
111  QFile outputFile;
112  QTextStream outFileStream;
113  QTextStream *outputStream;
114 
116  QMutex logMutex;
117  QThread *loggingThread; // in this thread all of writing operations will be executed
118 
119  public slots:
120  void logMessage(const QString &message, const Logger::LogLevel level, const uint lineno, const QString &filename);
121 };
122 
128 class LogHelper : public QObject
129 {
130  Q_OBJECT
131  public:
132  QString message;
134  uint lineno;
135  QString filename;
138 
139  LogHelper(const Logger::LogLevel level, const uint lineno, const QString &filename, const QString &message = "")
140  : message(message)
141  , level(level)
142  , lineno(lineno)
143  , filename(filename)
144  , is_message_sent(false)
145  {
146  Logger *pointer = Logger::getInstance();
147  log_level = pointer->getCurrentLogLevel();
148  connect(this, &LogHelper::logMessage, pointer, &Logger::logMessage);
149  };
150 
152  {
153  if (!is_message_sent)
154  sendMessage();
155  }
156 
157  void sendMessage()
158  {
159  is_message_sent = true;
161  };
162 
163  LogHelper &operator<<(const QString &s)
164  {
165  if (log_level != Logger::LogLevel::LOG_NONE)
166  message = message + s;
167  return *this;
168  };
169  template <typename Message> LogHelper &operator<<(Message ch)
170  {
171  if (log_level != Logger::LogLevel::LOG_NONE)
172  {
173  // The simplest way of building string from possible variables
174  std::stringstream str;
175  str << ch;
176  message = message + str.str().c_str();
177  }
178  return *this;
179  }
180  signals:
181  void logMessage(const QString &message, const Logger::LogLevel level, const uint lineno, const QString &filename);
182 };
183 
190 class StreamPrinter : public QObject
191 {
192  Q_OBJECT
193  private:
194  QTextStream m_stream;
195  std::stringstream m_message;
196  uint m_lineno;
197  QString m_filename;
198 
199  public:
200  StreamPrinter(FILE *file, uint lineno = 0, QString filename = "")
201  : m_stream(file)
202  , m_message("")
203  , m_lineno(lineno)
204  , m_filename(filename)
205  {
206  if (file == stdout)
207  {
208  m_message << "Printed stdout message📓: ";
209  } else if (file == stderr)
210  {
211  m_message << "Printed stderr message📓: ";
212  } else
213  {
214  m_message << "unknown stream ";
215  }
216  };
217 
219  {
220  // When logger prints to stream, then we already have printed messages into console,
221  // there is no need to duplicate
222  if (Logger::getInstance()->isWritingToFile())
223  LogHelper(Logger::LogLevel::LOG_INFO, m_lineno, m_filename, QString(m_message.str().c_str())).sendMessage();
224  };
225 
226  template <typename Message> StreamPrinter &operator<<(Message ch)
227  {
228  m_stream << ch;
229  m_message << ch;
230  return *this;
231  }
232 
233  StreamPrinter &operator<<(const QString &s)
234  {
235  m_stream << s;
236  m_message << s.toStdString();
237  return *this;
238  };
239 };
240 
241 #endif // LOGGER_H
VERBOSE
#define VERBOSE()
Definition: logger.h:42
Logger::loggingThread
QThread * loggingThread
Definition: logger.h:117
StreamPrinter::operator<<
StreamPrinter & operator<<(const QString &s)
Definition: logger.h:233
LogHelper::is_message_sent
bool is_message_sent
Definition: logger.h:136
Logger::outputFile
QFile outputFile
Definition: logger.h:111
Logger::LOG_MAX
@ LOG_MAX
Definition: logger.h:71
Logger::Logger
Logger(QTextStream *stream, LogLevel output_lvl=LOG_INFO, QObject *parent=nullptr)
Outputs log messages to a given text stream. Client code should determine whether it points to a cons...
Definition: logger.cpp:43
Logger::getInstance
static Logger * getInstance(bool raiseExceptionForNull=true)
Get the Instance of logger.
Definition: logger.h:94
StreamPrinter::m_lineno
uint m_lineno
Definition: logger.h:196
Logger::setLogLevel
static void setLogLevel(LogLevel level)
Set the highest logging level. Determines which messages are output to the output stream.
Definition: logger.cpp:76
Logger::setCurrentStream
static void setCurrentStream(QTextStream *stream)
Definition: logger.cpp:96
logger.h
Logger::LOG_DEBUG
@ LOG_DEBUG
Definition: logger.h:70
Logger::instance
static Logger * instance
Definition: logger.h:109
LogHelper::LogHelper
LogHelper(const Logger::LogLevel level, const uint lineno, const QString &filename, const QString &message="")
Definition: logger.h:139
Logger::logMutex
QMutex logMutex
Definition: logger.h:116
Logger::getCurrentStream
static QTextStream * getCurrentStream()
Definition: logger.cpp:107
LogHelper::operator<<
LogHelper & operator<<(const QString &s)
Definition: logger.h:163
Logger::isDebugEnabled
static bool isDebugEnabled()
Definition: logger.cpp:260
StreamPrinter::~StreamPrinter
~StreamPrinter()
Definition: logger.h:218
StreamPrinter::m_filename
QString m_filename
Definition: logger.h:197
LogHelper::sendMessage
void sendMessage()
Definition: logger.h:157
Logger::createInstance
static Logger * createInstance(QTextStream *stream=nullptr, LogLevel outputLevel=LOG_INFO, QObject *parent=nullptr)
Create instance of logger, if there is any other instance it will de deleted.
Definition: logger.cpp:250
Logger::LogLevel
LogLevel
Definition: logger.h:63
LogHelper::operator<<
LogHelper & operator<<(Message ch)
Definition: logger.h:169
LogHelper::logMessage
void logMessage(const QString &message, const Logger::LogLevel level, const uint lineno, const QString &filename)
Logger::getCurrentLogFile
static QString getCurrentLogFile()
Definition: logger.cpp:269
Logger::isWritingToFile
bool isWritingToFile()
Definition: logger.cpp:199
Logger::LOG_VERBOSE
@ LOG_VERBOSE
Definition: logger.h:69
LogHelper::level
Logger::LogLevel level
Definition: logger.h:133
Logger::outputStream
QTextStream * outputStream
Definition: logger.h:113
LogHelper::message
QString message
Definition: logger.h:132
StreamPrinter::operator<<
StreamPrinter & operator<<(Message ch)
Definition: logger.h:226
Logger::LOG_WARNING
@ LOG_WARNING
Definition: logger.h:67
LogHelper::~LogHelper
~LogHelper()
Definition: logger.h:151
Logger::getCurrentLogLevel
LogLevel getCurrentLogLevel()
Get the current output level associated with the logger.
Definition: logger.cpp:90
StreamPrinter
Simple adapter for QTextStream additionally logging printed values Logs are printed when StreamPrinte...
Definition: logger.h:190
Logger::logMessage
void logMessage(const QString &message, const Logger::LogLevel level, const uint lineno, const QString &filename)
Write an individual message to the text stream.
Definition: logger.cpp:140
StreamPrinter::m_stream
QTextStream m_stream
Definition: logger.h:194
StreamPrinter::m_message
std::stringstream m_message
Definition: logger.h:195
Logger::~Logger
~Logger()
Close output stream and set instance to 0.
Definition: logger.cpp:60
Logger::outFileStream
QTextStream outFileStream
Definition: logger.h:112
Logger::LOG_ERROR
@ LOG_ERROR
Definition: logger.h:66
LogHelper
simple helper class used for constructing log message and sending it to Logger
Definition: logger.h:128
StreamPrinter::StreamPrinter
StreamPrinter(FILE *file, uint lineno=0, QString filename="")
Definition: logger.h:200
Logger::outputLevel
LogLevel outputLevel
Definition: logger.h:115
Logger::loggerMessageHandler
static void loggerMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg)
log message handling function
Definition: logger.cpp:210
Logger::LOG_INFO
@ LOG_INFO
Definition: logger.h:68
LogHelper::filename
QString filename
Definition: logger.h:135
Logger
Custom singleton class used for logging across application.
Definition: logger.h:57
Logger::closeLogger
void closeLogger(bool closeStream=true)
Flushes output stream and closes stream if requested.
Definition: logger.cpp:118
Logger::LOG_NONE
@ LOG_NONE
Definition: logger.h:65
LogHelper::lineno
uint lineno
Definition: logger.h:134
LogHelper::log_level
Logger::LogLevel log_level
Definition: logger.h:137
Logger::setCurrentLogFile
static void setCurrentLogFile(QString filename)
Definition: logger.cpp:172