-Logger::~Logger() {
- QDateTime date = QDateTime::currentDateTime();
- if(_stream->logLevel == DebugLevel) _stream->buffer.prepend("Debug: ");
- else if (_stream->logLevel == InfoLevel) _stream->buffer.prepend("Info: ");
- else if (_stream->logLevel == WarningLevel) _stream->buffer.prepend("Warning: ");
- else if (_stream->logLevel == ErrorLevel) _stream->buffer.prepend("Error: ");
- _stream->buffer.prepend(date.toString("yyyy-MM-dd hh:mm:ss "));
- log();
- delete _stream;
-}
-
-void Logger::log() {
- LogLevel lvl;
- if (Global::parser.value("loglevel") == "Debug") lvl = DebugLevel;
- else if (Global::parser.value("loglevel") == "Info") lvl = InfoLevel;
- else if (Global::parser.value("loglevel") == "Warning") lvl = WarningLevel;
- else if (Global::parser.value("loglevel") == "Error") lvl = ErrorLevel;
- else lvl = InfoLevel;
-
- if(_stream->logLevel < lvl) return;
-
- // if we can't open logfile we log to stdout
- QTextStream out(stdout);
- QFile file;
- if(!Global::parser.value("logfile").isEmpty()) {
- file.setFileName(Global::parser.value("logfile"));
- if (file.open(QIODevice::Append | QIODevice::Text)) {
- out.setDevice(&file);
- _stream->buffer.remove(QChar('\n'));
- }
- }
- out << _stream->buffer << "\n";
- if(file.isOpen()) file.close();
+ _initialized = true;
+
+ // Now that we've setup our logging backends, output pending messages
+ for (auto&& message : _messages) {
+ outputMessage(message);
+ }
+ if (!_keepMessages) {
+ _messages.clear();
+ }
+}
+
+void Logger::messageHandler(QtMsgType type, const QMessageLogContext&, const QString& message)
+{
+ Quassel::instance()->logger()->handleMessage(type, message);
+}
+
+void Logger::handleMessage(QtMsgType type, const QString& msg)
+{
+ switch (type) {
+ case QtDebugMsg:
+ handleMessage(LogLevel::Debug, msg);
+ break;
+ case QtInfoMsg:
+ handleMessage(LogLevel::Info, msg);
+ break;
+ case QtWarningMsg:
+ handleMessage(LogLevel::Warning, msg);
+ break;
+ case QtCriticalMsg:
+ handleMessage(LogLevel::Error, msg);
+ break;
+ case QtFatalMsg:
+ handleMessage(LogLevel::Fatal, msg);
+ break;
+ }
+}
+
+void Logger::handleMessage(LogLevel level, const QString& msg)
+{
+ QString logString;
+
+ // Only add the log level to the message if we do not output to syslog
+ if (!_syslogEnabled) {
+ switch (level) {
+ case LogLevel::Debug:
+ logString = "[Debug] ";
+ break;
+ case LogLevel::Info:
+ logString = "[Info ] ";
+ break;
+ case LogLevel::Warning:
+ logString = "[Warn ] ";
+ break;
+ case LogLevel::Error:
+ logString = "[Error] ";
+ break;
+ case LogLevel::Fatal:
+ logString = "[FATAL] ";
+ break;
+ }
+ }
+
+ // Use signal connection to make this method thread-safe
+ emit messageLogged({QDateTime::currentDateTime(), level, logString += msg});
+}
+
+void Logger::onMessageLogged(const LogEntry& message)
+{
+ if (_keepMessages) {
+ _messages.push_back(message);
+ }
+
+ // If setup() wasn't called yet, just store the message - will be output later
+ if (_initialized) {
+ outputMessage(message);
+ }
+}
+
+void Logger::outputMessage(const LogEntry& message)
+{
+ if (message.logLevel < _outputLevel) {
+ return;
+ }
+
+#ifdef HAVE_SYSLOG
+ if (_syslogEnabled) {
+ int prio{LOG_INFO};
+ switch (message.logLevel) {
+ case LogLevel::Debug:
+ prio = LOG_DEBUG;
+ break;
+ case LogLevel::Info:
+ prio = LOG_INFO;
+ break;
+ case LogLevel::Warning:
+ prio = LOG_WARNING;
+ break;
+ case LogLevel::Error:
+ prio = LOG_ERR;
+ break;
+ case LogLevel::Fatal:
+ prio = LOG_CRIT;
+ }
+ syslog(prio, "%s", qPrintable(message.message));
+ }
+#endif
+
+ if (!_logFile.fileName().isEmpty() || !_syslogEnabled) {
+ _logFile.write(msgWithTime(message));
+ }
+
+#ifndef Q_OS_MAC
+ // For fatal messages, write log to dump file
+ if (message.logLevel == LogLevel::Fatal) {
+ QFile dumpFile{Quassel::instance()->coreDumpFileName()};
+ if (dumpFile.open(QIODevice::Append)) {
+ dumpFile.write(msgWithTime(message));
+ dumpFile.close();
+ }
+ }
+#endif