Commit 051dacaf authored by Ronan's avatar Ronan

feat(src/app/Logger): use a relative context path and thread safe

parent a4dd00e1
......@@ -106,6 +106,7 @@ set(SOURCES
src/components/timeline/TimelineModel.cpp
src/externals/single-application/SingleApplication.cpp
src/main.cpp
src/utils.cpp
)
set(HEADERS
......
......@@ -176,11 +176,12 @@ void App::parseArgs () {
m_parser.process(*this);
// Initialise logger (do not do this before this point because the application has to be created
// for the logs to be put in the correct directory
// Initialize logger. (Do not do this before this point because the
// application has to be created for the logs to be put in the correct
// directory.)
Logger::init();
if (m_parser.isSet("verbose")) {
Logger::instance()->setVerbose(true);
Logger::getInstance()->setVerbose(true);
}
}
......
......@@ -24,6 +24,7 @@
#include <linphone/linphonecore.h>
#include <QDateTime>
#include "../utils.hpp"
#include "Paths.hpp"
#include "Logger.hpp"
......@@ -48,13 +49,50 @@
#define MAX_LOGS_COLLECTION_SIZE 104857600 /* 100MB. */
#define SRC_PATTERN "/linphone-desktop/src/"
using namespace std;
// =============================================================================
QMutex Logger::m_mutex;
Logger *Logger::m_instance = nullptr;
// -----------------------------------------------------------------------------
static void qtLogger (QtMsgType type, const QMessageLogContext &context, const QString &msg) {
static void linphoneLog (const char *domain, OrtpLogLevel type, const char *fmt, va_list args) {
const char *format;
if (type == ORTP_DEBUG)
format = GREEN "[%s][Debug]" YELLOW "Core:%s: " RESET "%s\n";
else if (type == ORTP_TRACE)
format = BLUE "[%s][Trace]" YELLOW "Core:%s: " RESET "%s\n";
else if (type == ORTP_MESSAGE)
format = BLUE "[%s][Info]" YELLOW "Core:%s: " RESET "%s\n";
else if (type == ORTP_WARNING)
format = RED "[%s][Warning]" YELLOW "Core:%s: " RESET "%s\n";
else if (type == ORTP_ERROR)
format = RED "[%s][Critical]" YELLOW "Core:%s: " RESET "%s\n";
else if (type == ORTP_FATAL)
format = RED "[%s][Fatal]" YELLOW "Core:%s: " RESET "%s\n";
else
return;
QByteArray date_time = QDateTime::currentDateTime().toString("HH:mm:ss").toLocal8Bit();
char *msg = bctbx_strdup_vprintf(fmt, args);
fprintf(stderr, format, date_time.constData(), domain, msg);
bctbx_free(msg);
if (type == ORTP_FATAL)
abort();
}
// -----------------------------------------------------------------------------
void Logger::log (QtMsgType type, const QMessageLogContext &context, const QString &msg) {
const char *format;
BctbxLogLevel level;
......@@ -79,48 +117,33 @@ static void qtLogger (QtMsgType type, const QMessageLogContext &context, const Q
const char *context_str = "";
#ifdef QT_MESSAGELOGCONTEXT
QByteArray context_arr = QStringLiteral("%1:%2: ").arg(context.file).arg(context.line).toLocal8Bit();
context_str = context_arr.constData();
#endif // ifdef QT_MESSAGELOGCONTEXT
QByteArray local_msg = msg.toLocal8Bit();
QByteArray date_time = QDateTime::currentDateTime().toString("HH:mm:ss").toLocal8Bit();
fprintf(stderr, format, date_time.constData(), context_str, local_msg.constData());
bctbx_log(QT_DOMAIN, level, "QT: %s%s", context_str, local_msg.constData());
QByteArray context_arr;
if (type == QtFatalMsg)
abort();
}
// -----------------------------------------------------------------------------
{
const char *file = context.file;
const char *pos = file ? ::Utils::rstrstr(file, SRC_PATTERN) : file;
static void linphoneLogger (const char *domain, OrtpLogLevel type, const char *fmt, va_list args) {
const char *format;
context_arr = QStringLiteral("%1:%2: ")
.arg(pos ? pos + sizeof(SRC_PATTERN) - 1 : file)
.arg(context.line)
.toLocal8Bit();
context_str = context_arr.constData();
}
if (type == ORTP_DEBUG)
format = GREEN "[%s][Debug]" YELLOW "Core:%s: " RESET "%s\n";
else if (type == ORTP_TRACE)
format = BLUE "[%s][Trace]" YELLOW "Core:%s: " RESET "%s\n";
else if (type == ORTP_MESSAGE)
format = BLUE "[%s][Info]" YELLOW "Core:%s: " RESET "%s\n";
else if (type == ORTP_WARNING)
format = RED "[%s][Warning]" YELLOW "Core:%s: " RESET "%s\n";
else if (type == ORTP_ERROR)
format = RED "[%s][Critical]" YELLOW "Core:%s: " RESET "%s\n";
else if (type == ORTP_FATAL)
format = RED "[%s][Fatal]" YELLOW "Core:%s: " RESET "%s\n";
else
return;
#endif // ifdef QT_MESSAGELOGCONTEXT
QByteArray local_msg = msg.toLocal8Bit();
QByteArray date_time = QDateTime::currentDateTime().toString("HH:mm:ss").toLocal8Bit();
char *msg = bctbx_strdup_vprintf(fmt, args);
fprintf(stderr, format, date_time.constData(), domain, msg);
m_mutex.lock();
bctbx_free(msg);
fprintf(stderr, format, date_time.constData(), context_str, local_msg.constData());
bctbx_log(QT_DOMAIN, level, "QT: %s%s", context_str, local_msg.constData());
if (type == ORTP_FATAL)
m_mutex.unlock();
if (type == QtFatalMsg)
abort();
}
......@@ -131,13 +154,13 @@ void Logger::init () {
return;
m_instance = new Logger();
qInstallMessageHandler(qtLogger);
qInstallMessageHandler(Logger::log);
linphone_core_set_log_level(ORTP_MESSAGE);
linphone_core_set_log_handler(
[](const char *domain, OrtpLogLevel type, const char *fmt, va_list args) {
if (m_instance->isVerbose())
linphoneLogger(domain, type, fmt, args);
linphoneLog(domain, type, fmt, args);
}
);
......
......@@ -23,23 +23,36 @@
#ifndef LOGGER_H_
#define LOGGER_H_
#include <QtGlobal>
#include <QMutex>
// =============================================================================
class Logger {
public:
~Logger () = default;
bool isVerbose () const {
return m_verbose;
}
void setVerbose (bool verbose) {
m_verbose = verbose;
}
static void init ();
static Logger *instance () { return m_instance; };
bool isVerbose () const { return m_verbose; };
void setVerbose (bool verbose) { m_verbose = verbose; };
static Logger *getInstance () {
return m_instance;
}
private:
Logger () = default;
static void log (QtMsgType type, const QMessageLogContext &context, const QString &msg);
bool m_verbose = false;
static QMutex m_mutex;
static Logger *m_instance;
};
......
/*
* utils.cpp
* Copyright (C) 2017 Belledonne Communications, Grenoble, France
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Created on: March 24, 2017
* Author: Ronan Abhamon
*/
#include "utils.hpp"
// =============================================================================
char *Utils::rstrstr (const char *a, const char *b) {
size_t a_len = strlen(a);
size_t b_len = strlen(b);
const char *s;
if (b_len > a_len)
return NULL;
for (s = a + a_len - b_len; s >= a; --s) {
if (!strncmp(s, b, b_len))
return const_cast<char *>(s);
}
return NULL;
}
......@@ -49,6 +49,8 @@ namespace Utils {
return findParentType<T>(parent);
}
char *rstrstr (const char *a, const char *b);
}
#endif // UTILS_H_
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment