mirror of
https://github.com/overte-org/overte.git
synced 2025-08-08 14:18:24 +02:00
Initial implementation
This commit is contained in:
parent
cd91f9f273
commit
ad4f0c1a8c
3 changed files with 156 additions and 20 deletions
|
@ -21,6 +21,16 @@ if (APPLE)
|
||||||
target_link_libraries(${TARGET_NAME} ${FRAMEWORK_IOKIT} ${CORE_FOUNDATION} ${OpenGL})
|
target_link_libraries(${TARGET_NAME} ${FRAMEWORK_IOKIT} ${CORE_FOUNDATION} ${OpenGL})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if (UNIX AND NOT APPLE)
|
||||||
|
find_package(Journald)
|
||||||
|
|
||||||
|
if (${JOURNALD_FOUND})
|
||||||
|
target_link_libraries(${TARGET_NAME} ${JOURNALD_LIBRARIES})
|
||||||
|
target_include_directories(${TARGET_NAME} PRIVATE ${JOURNALD_INCLUDE_DIR})
|
||||||
|
target_compile_definitions(${TARGET_NAME} PUBLIC HAS_JOURNALD)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
target_zlib()
|
target_zlib()
|
||||||
target_nsight()
|
target_nsight()
|
||||||
target_json()
|
target_json()
|
||||||
|
|
|
@ -31,6 +31,10 @@
|
||||||
#include <QtCore/QTimer>
|
#include <QtCore/QTimer>
|
||||||
#include <QRecursiveMutex>
|
#include <QRecursiveMutex>
|
||||||
|
|
||||||
|
#ifdef HAS_JOURNALD
|
||||||
|
#include <systemd/sd-journal.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
QRecursiveMutex LogHandler::_mutex;
|
QRecursiveMutex LogHandler::_mutex;
|
||||||
|
|
||||||
LogHandler& LogHandler::getInstance() {
|
LogHandler& LogHandler::getInstance() {
|
||||||
|
@ -51,6 +55,10 @@ LogHandler::LogHandler() {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAS_JOURNALD
|
||||||
|
_useJournald = true;
|
||||||
|
#endif
|
||||||
|
|
||||||
auto optionList = logOptions.split(",");
|
auto optionList = logOptions.split(",");
|
||||||
|
|
||||||
for (auto option : optionList) {
|
for (auto option : optionList) {
|
||||||
|
@ -68,6 +76,8 @@ LogHandler::LogHandler() {
|
||||||
_shouldDisplayMilliseconds = true;
|
_shouldDisplayMilliseconds = true;
|
||||||
} else if (option == "keep_repeats") {
|
} else if (option == "keep_repeats") {
|
||||||
_keepRepeats = true;
|
_keepRepeats = true;
|
||||||
|
} else if (option == "nojournald") {
|
||||||
|
_useJournald = false;
|
||||||
} else if (option != "") {
|
} else if (option != "") {
|
||||||
fprintf(stdout, "Unrecognized option in VIRCADIA_LOG_OPTIONS: '%s'\n", option.toUtf8().constData());
|
fprintf(stdout, "Unrecognized option in VIRCADIA_LOG_OPTIONS: '%s'\n", option.toUtf8().constData());
|
||||||
}
|
}
|
||||||
|
@ -142,6 +152,13 @@ void LogHandler::setShouldDisplayMilliseconds(bool shouldDisplayMilliseconds) {
|
||||||
_shouldDisplayMilliseconds = shouldDisplayMilliseconds;
|
_shouldDisplayMilliseconds = shouldDisplayMilliseconds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool LogHandler::isJournaldAvailable() const {
|
||||||
|
#ifdef HAS_JOURNALD
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void LogHandler::flushRepeatedMessages() {
|
void LogHandler::flushRepeatedMessages() {
|
||||||
QMutexLocker lock(&_mutex);
|
QMutexLocker lock(&_mutex);
|
||||||
|
@ -163,6 +180,7 @@ QString LogHandler::printMessage(LogMsgType type, const QMessageLogContext& cont
|
||||||
if (message.isEmpty()) {
|
if (message.isEmpty()) {
|
||||||
return QString();
|
return QString();
|
||||||
}
|
}
|
||||||
|
|
||||||
QMutexLocker lock(&_mutex);
|
QMutexLocker lock(&_mutex);
|
||||||
|
|
||||||
// log prefix is in the following format
|
// log prefix is in the following format
|
||||||
|
@ -196,8 +214,49 @@ QString LogHandler::printMessage(LogMsgType type, const QMessageLogContext& cont
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This is returned from this function and wanted by the LogEntityServer,
|
||||||
|
// so we have to have it even when using journald.
|
||||||
QString logMessage = QString("%1 %2\n").arg(prefixString, message.split('\n').join('\n' + prefixString + " "));
|
QString logMessage = QString("%1 %2\n").arg(prefixString, message.split('\n').join('\n' + prefixString + " "));
|
||||||
|
|
||||||
|
if ( _useJournald ) {
|
||||||
|
#ifdef HAS_JOURNALD
|
||||||
|
int priority = LOG_NOTICE;
|
||||||
|
switch(type) {
|
||||||
|
case LogMsgType::LogFatal: priority = LOG_EMERG; break;
|
||||||
|
case LogMsgType::LogCritical: priority = LOG_CRIT; break;
|
||||||
|
case LogMsgType::LogWarning: priority = LOG_WARNING; break;
|
||||||
|
case LogMsgType::LogInfo: priority = LOG_INFO; break;
|
||||||
|
case LogMsgType::LogDebug: priority = LOG_DEBUG; break;
|
||||||
|
case LogMsgType::LogSuppressed: priority = LOG_DEBUG; break;
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "Unrecognized log type: %i", (int)type);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t threadID = (size_t)QThread::currentThreadId();
|
||||||
|
QString sd_file = QString("CODE_FILE=%1").arg(context.file);
|
||||||
|
QString sd_line = QString("CODE_LINE=%1").arg(context.line);
|
||||||
|
|
||||||
|
int retval = sd_journal_send_with_location(sd_file.toUtf8().constData(),
|
||||||
|
sd_line.toUtf8().constData(),
|
||||||
|
context.function == NULL ? "(unknown)" : context.function,
|
||||||
|
"MESSAGE=%s", message.toUtf8().constData(),
|
||||||
|
"PRIORITY=%i", priority,
|
||||||
|
"CATEGORY=%s", context.category,
|
||||||
|
"TID=%i", threadID,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
if ( retval != 0 ) {
|
||||||
|
fprintf(stderr, "Failed to log message, error %i: ", retval);
|
||||||
|
fprintf(stderr, "file=%s, line=%i, func=%s, prio=%i, msg=%s\n",
|
||||||
|
context.file,
|
||||||
|
context.line,
|
||||||
|
context.function,
|
||||||
|
priority,
|
||||||
|
message.toUtf8().constData()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
const char* color = "";
|
const char* color = "";
|
||||||
const char* resetColor = "";
|
const char* resetColor = "";
|
||||||
|
|
||||||
|
@ -217,6 +276,13 @@ QString LogHandler::printMessage(LogMsgType type, const QMessageLogContext& cont
|
||||||
_repeatCount++;
|
_repeatCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_previousMessage = message;
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
// On windows, this will output log lines into the Visual Studio "output" tab
|
||||||
|
OutputDebugStringA(qPrintable(logMessage));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
if ( !_breakMessages.empty() ) {
|
if ( !_breakMessages.empty() ) {
|
||||||
for(const auto &str : _breakMessages) {
|
for(const auto &str : _breakMessages) {
|
||||||
if (logMessage.contains(str)) {
|
if (logMessage.contains(str)) {
|
||||||
|
@ -229,6 +295,7 @@ QString LogHandler::printMessage(LogMsgType type, const QMessageLogContext& cont
|
||||||
// On windows, this will output log lines into the Visual Studio "output" tab
|
// On windows, this will output log lines into the Visual Studio "output" tab
|
||||||
OutputDebugStringA(qPrintable(logMessage));
|
OutputDebugStringA(qPrintable(logMessage));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return logMessage;
|
return logMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,24 +31,82 @@ enum LogMsgType {
|
||||||
LogSuppressed = 100
|
LogSuppressed = 100
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Handles custom message handling and sending of stats/logs to Logstash instance
|
///
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Handles custom message handling and sending of stats/logs to Logstash instance
|
||||||
|
*
|
||||||
|
*/
|
||||||
class LogHandler : public QObject {
|
class LogHandler : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Returns the one instance of the LogHandler object
|
||||||
|
*
|
||||||
|
* @return LogHandler&
|
||||||
|
*/
|
||||||
static LogHandler& getInstance();
|
static LogHandler& getInstance();
|
||||||
|
|
||||||
/// sets the target name to output via the verboseMessageHandler, called once before logging begins
|
/**
|
||||||
/// \param targetName the desired target name to output in logs
|
* @brief Set the Target Name to output via the verboseMessageHandler
|
||||||
|
*
|
||||||
|
* Called once before logging begins
|
||||||
|
*
|
||||||
|
* @param targetName the desired target name to output in logs
|
||||||
|
*/
|
||||||
void setTargetName(const QString& targetName);
|
void setTargetName(const QString& targetName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set whether to output the process ID
|
||||||
|
*
|
||||||
|
* @note This has no effect when logging with journald, the PID is always logged
|
||||||
|
*
|
||||||
|
* @param shouldOutputProcessID Whether to output the PID
|
||||||
|
*/
|
||||||
void setShouldOutputProcessID(bool shouldOutputProcessID);
|
void setShouldOutputProcessID(bool shouldOutputProcessID);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set whether to output the thread ID
|
||||||
|
*
|
||||||
|
* @param shouldOutputThreadID
|
||||||
|
*/
|
||||||
void setShouldOutputThreadID(bool shouldOutputThreadID);
|
void setShouldOutputThreadID(bool shouldOutputThreadID);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set whether to display timestamps with milliseconds
|
||||||
|
*
|
||||||
|
* @param shouldDisplayMilliseconds
|
||||||
|
*/
|
||||||
void setShouldDisplayMilliseconds(bool shouldDisplayMilliseconds);
|
void setShouldDisplayMilliseconds(bool shouldDisplayMilliseconds);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set whether to use Journald, if it's available
|
||||||
|
*
|
||||||
|
* @param shouldUseJournald Whether to use journald
|
||||||
|
*/
|
||||||
|
void setShouldUseJournald(bool shouldUseJournald);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Whether Journald is available on this version/system.
|
||||||
|
*
|
||||||
|
* Support is available depending on compile options and only on Linux.
|
||||||
|
*
|
||||||
|
* @return true Journald is available
|
||||||
|
* @return false Journald is not available
|
||||||
|
*/
|
||||||
|
bool isJournaldAvailable() const;
|
||||||
|
|
||||||
QString printMessage(LogMsgType type, const QMessageLogContext& context, const QString &message);
|
QString printMessage(LogMsgType type, const QMessageLogContext& context, const QString &message);
|
||||||
|
|
||||||
/// a qtMessageHandler that can be hooked up to a target that links to Qt
|
/**
|
||||||
/// prints various process, message type, and time information
|
* @brief A qtMessageHandler that can be hooked up to a target that links to Qt
|
||||||
|
*
|
||||||
|
* Prints various process, message type, and time information
|
||||||
|
*
|
||||||
|
* @param type Log message type
|
||||||
|
* @param context Context of the log message (source file, line, function)
|
||||||
|
* @param message Log message
|
||||||
|
*/
|
||||||
static void verboseMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString &message);
|
static void verboseMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString &message);
|
||||||
|
|
||||||
int newRepeatedMessageID();
|
int newRepeatedMessageID();
|
||||||
|
@ -89,6 +147,7 @@ private:
|
||||||
bool _shouldDisplayMilliseconds { false };
|
bool _shouldDisplayMilliseconds { false };
|
||||||
bool _useColor { false };
|
bool _useColor { false };
|
||||||
bool _keepRepeats { false };
|
bool _keepRepeats { false };
|
||||||
|
bool _useJournald { false };
|
||||||
|
|
||||||
QString _previousMessage;
|
QString _previousMessage;
|
||||||
int _repeatCount { 0 };
|
int _repeatCount { 0 };
|
||||||
|
|
Loading…
Reference in a new issue