mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-10 05:09:51 +02:00
This adds command-line arguments, disables it by default on interface, adds target logging, and can deal with variable numbers of fields. It also adds some documentation.
216 lines
6.7 KiB
C++
216 lines
6.7 KiB
C++
//
|
|
// LogHandler.cpp
|
|
// libraries/shared/src
|
|
//
|
|
// Created by Stephen Birarda on 2014-10-28.
|
|
// Migrated from Logging.cpp created on 6/11/13
|
|
// Copyright 2014 High Fidelity, Inc.
|
|
//
|
|
// Distributed under the Apache License, Version 2.0.
|
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
|
//
|
|
|
|
#ifndef hifi_LogHandler_h
|
|
#define hifi_LogHandler_h
|
|
|
|
#include <QObject>
|
|
#include <QString>
|
|
#include <QRegExp>
|
|
#include <QRecursiveMutex>
|
|
#include <vector>
|
|
#include <memory>
|
|
|
|
const int VERBOSE_LOG_INTERVAL_SECONDS = 5;
|
|
|
|
enum LogMsgType {
|
|
LogInfo = QtInfoMsg,
|
|
LogDebug = QtDebugMsg,
|
|
LogWarning = QtWarningMsg,
|
|
LogCritical = QtCriticalMsg,
|
|
LogFatal = QtFatalMsg,
|
|
LogSuppressed = 100
|
|
};
|
|
|
|
///
|
|
|
|
/**
|
|
* @brief Handles custom message handling and sending of stats/logs to Logstash instance
|
|
*
|
|
*/
|
|
class LogHandler : public QObject {
|
|
Q_OBJECT
|
|
public:
|
|
/**
|
|
* @brief Returns the one instance of the LogHandler object
|
|
*
|
|
* @return LogHandler&
|
|
*/
|
|
static LogHandler& getInstance();
|
|
|
|
/**
|
|
* @brief Parse logging options
|
|
*
|
|
* This parses the logging settings in the environment variable, or from the commandline
|
|
*
|
|
* @param options Option list
|
|
* @return true Option list was parsed successfully
|
|
* @return false There was an error
|
|
*/
|
|
bool parseOptions(QString options);
|
|
|
|
/**
|
|
* @brief Set the name of the component that's producing log output
|
|
*
|
|
* For instance, "assignment-client", "audio-mixer", etc.
|
|
* Called once before logging begins
|
|
*
|
|
* @param targetName the desired target name to output in logs
|
|
*/
|
|
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);
|
|
|
|
/**
|
|
* @brief Set whether to output the thread ID
|
|
*
|
|
* @param shouldOutputThreadID
|
|
*/
|
|
void setShouldOutputThreadID(bool shouldOutputThreadID);
|
|
|
|
/**
|
|
* @brief Set whether to display timestamps with milliseconds
|
|
*
|
|
* @param 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;
|
|
|
|
/**
|
|
* @brief Process a log message
|
|
*
|
|
* This writes it to a file, logs it to the console, or sends it to journald.
|
|
*
|
|
* @param type Log message type
|
|
* @param context Context of the log message (source file, line, function)
|
|
* @param message Log message
|
|
* @return QString The log message's text with added severity and timestamp
|
|
*/
|
|
QString printMessage(LogMsgType type, const QMessageLogContext& context, const QString &message);
|
|
|
|
/**
|
|
* @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);
|
|
|
|
int newRepeatedMessageID();
|
|
void printRepeatedMessage(int messageID, LogMsgType type, const QMessageLogContext& context, const QString &message);
|
|
|
|
void setupRepeatedMessageFlusher();
|
|
|
|
/**
|
|
* @brief Break when a message that contains the specified string is logged
|
|
*
|
|
* This is a function intended to be invoked from inside a debugger. It should be of help when it's hard to put a breakpoint
|
|
* on the generating line because it comes from inlined code, or the interesting text is generated at runtime.
|
|
*
|
|
* Example usage:
|
|
*
|
|
* @code {.cpp}
|
|
* LogHandler::breakOnMessage("No instance available for");
|
|
* @endcode
|
|
*
|
|
* Then the debugger should be triggered as soon as a message containing that string is logged. Backtracking
|
|
* through the call stack should lead back to the source.
|
|
*
|
|
* @note Support for creating a breakpoint in software is compiler and OS specific. If there's no support for
|
|
* creating a breakpoint on the current compiler/OS, then an abort will be triggered instead.
|
|
*
|
|
* @param str Text to match
|
|
*/
|
|
static void breakOnMessage(const char *str);
|
|
private:
|
|
LogHandler();
|
|
~LogHandler() = default;
|
|
|
|
void flushRepeatedMessages();
|
|
|
|
QString _targetName;
|
|
bool _shouldOutputProcessID { false };
|
|
bool _shouldOutputThreadID { false };
|
|
bool _shouldDisplayMilliseconds { false };
|
|
bool _useColor { false };
|
|
bool _keepRepeats { false };
|
|
bool _useJournald { false };
|
|
|
|
QString _previousMessage;
|
|
int _repeatCount { 0 };
|
|
|
|
|
|
int _currentMessageID { 0 };
|
|
struct RepeatedMessageRecord {
|
|
int repeatCount;
|
|
QString repeatString;
|
|
};
|
|
std::vector<RepeatedMessageRecord> _repeatedMessageRecords;
|
|
|
|
QStringList _breakMessages;
|
|
static QRecursiveMutex _mutex;
|
|
};
|
|
|
|
#define HIFI_FCDEBUG(category, message) \
|
|
do { \
|
|
if (category.isDebugEnabled()) { \
|
|
static int repeatedMessageID_ = LogHandler::getInstance().newRepeatedMessageID(); \
|
|
QString logString_; \
|
|
QDebug debugStringReceiver_(&logString_); \
|
|
debugStringReceiver_ << message; \
|
|
LogHandler::getInstance().printRepeatedMessage(repeatedMessageID_, LogDebug, QMessageLogContext(__FILE__, \
|
|
__LINE__, __func__, category().categoryName()), logString_); \
|
|
} \
|
|
} while (false)
|
|
|
|
#define HIFI_FDEBUG(message) HIFI_FCDEBUG((*QLoggingCategory::defaultCategory()), message)
|
|
|
|
#define HIFI_FCDEBUG_ID(category, messageID, message) \
|
|
do { \
|
|
if (category.isDebugEnabled()) { \
|
|
QString logString_; \
|
|
QDebug debugStringReceiver_(&logString_); \
|
|
debugStringReceiver_ << message; \
|
|
LogHandler::getInstance().printRepeatedMessage(messageID, LogDebug, QMessageLogContext(__FILE__, \
|
|
__LINE__, __func__, category().categoryName()), logString_); \
|
|
} \
|
|
} while (false)
|
|
|
|
#define HIFI_FDEBUG_ID(messageID, message) HIFI_FCDEBUG_ID((*QLoggingCategory::defaultCategory()), messageID, message)
|
|
|
|
#endif // hifi_LogHandler_h
|