Logging system buffers startup messages.
This allows adding log callbacks easier during startup, without missing the initial messages, which might be very important.
This commit is contained in:
+54
-21
@@ -181,9 +181,9 @@ class LogStreamPrivate : public SGThread
|
|||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* storage of a single log entry. Note this is not used for a persistent
|
* storage of a single log entry. This is used to pass log entries from
|
||||||
* store, but rather for short term buffering between the submitting
|
* the various threads to the logging thread, and also to store the startup
|
||||||
* and output threads.
|
* entries
|
||||||
*/
|
*/
|
||||||
class LogEntry
|
class LogEntry
|
||||||
{
|
{
|
||||||
@@ -195,19 +195,24 @@ private:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
sgDebugClass debugClass;
|
const sgDebugClass debugClass;
|
||||||
sgDebugPriority debugPriority;
|
const sgDebugPriority debugPriority;
|
||||||
const char* file;
|
const char* file;
|
||||||
int line;
|
const int line;
|
||||||
std::string message;
|
const std::string message;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RAII object to pause the logging thread if it's running, and restart it.
|
||||||
|
* used to safely make configuration changes.
|
||||||
|
*/
|
||||||
class PauseThread
|
class PauseThread
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PauseThread(LogStreamPrivate* parent) : m_parent(parent)
|
PauseThread(LogStreamPrivate* parent)
|
||||||
|
: m_parent(parent)
|
||||||
|
, m_wasRunning(m_parent->stop())
|
||||||
{
|
{
|
||||||
m_wasRunning = m_parent->stop();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
~PauseThread()
|
~PauseThread()
|
||||||
@@ -218,17 +223,13 @@ private:
|
|||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
LogStreamPrivate* m_parent;
|
LogStreamPrivate* m_parent;
|
||||||
bool m_wasRunning;
|
const bool m_wasRunning;
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
LogStreamPrivate() :
|
LogStreamPrivate() :
|
||||||
m_logClass(SG_ALL),
|
m_logClass(SG_ALL),
|
||||||
m_logPriority(SG_ALERT),
|
m_logPriority(SG_ALERT)
|
||||||
#if defined (SG_WINDOWS)
|
|
||||||
m_stdout_isRedirectedAlready(false),
|
|
||||||
m_stderr_isRedirectedAlready(false),
|
|
||||||
#endif
|
|
||||||
m_isRunning(false)
|
|
||||||
{
|
{
|
||||||
#if defined (SG_WINDOWS)
|
#if defined (SG_WINDOWS)
|
||||||
/*
|
/*
|
||||||
@@ -332,7 +333,7 @@ public:
|
|||||||
|
|
||||||
~LogStreamPrivate()
|
~LogStreamPrivate()
|
||||||
{
|
{
|
||||||
BOOST_FOREACH(simgear::LogCallback* cb, m_callbacks) {
|
for (simgear::LogCallback* cb : m_callbacks) {
|
||||||
delete cb;
|
delete cb;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -340,6 +341,10 @@ public:
|
|||||||
SGMutex m_lock;
|
SGMutex m_lock;
|
||||||
SGBlockingQueue<LogEntry> m_entries;
|
SGBlockingQueue<LogEntry> m_entries;
|
||||||
|
|
||||||
|
// log entries posted during startup
|
||||||
|
std::vector<LogEntry> m_startupEntries;
|
||||||
|
bool m_startupLogging = false;
|
||||||
|
|
||||||
typedef std::vector<simgear::LogCallback*> CallbackVec;
|
typedef std::vector<simgear::LogCallback*> CallbackVec;
|
||||||
CallbackVec m_callbacks;
|
CallbackVec m_callbacks;
|
||||||
/// subset of callbacks which correspond to stdout / console,
|
/// subset of callbacks which correspond to stdout / console,
|
||||||
@@ -348,11 +353,11 @@ public:
|
|||||||
|
|
||||||
sgDebugClass m_logClass;
|
sgDebugClass m_logClass;
|
||||||
sgDebugPriority m_logPriority;
|
sgDebugPriority m_logPriority;
|
||||||
bool m_isRunning;
|
bool m_isRunning = false;
|
||||||
#if defined (SG_WINDOWS)
|
#if defined (SG_WINDOWS)
|
||||||
// track whether the console was redirected on launch (in the constructor, which is called early on)
|
// track whether the console was redirected on launch (in the constructor, which is called early on)
|
||||||
bool m_stderr_isRedirectedAlready;
|
bool m_stderr_isRedirectedAlready = false;
|
||||||
bool m_stdout_isRedirectedAlready;
|
bool m_stdout_isRedirectedAlready = false;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void startLog()
|
void startLog()
|
||||||
@@ -363,6 +368,16 @@ public:
|
|||||||
start();
|
start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setStartupLoggingEnabled(bool on)
|
||||||
|
{
|
||||||
|
if (m_startupLogging == on) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_startupLogging = on;
|
||||||
|
m_startupEntries.clear();
|
||||||
|
}
|
||||||
|
|
||||||
virtual void run()
|
virtual void run()
|
||||||
{
|
{
|
||||||
while (1) {
|
while (1) {
|
||||||
@@ -373,8 +388,14 @@ public:
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_startupLogging) {
|
||||||
|
// save to the startup list for not-yet-added callbacks to
|
||||||
|
// pull down on startup
|
||||||
|
m_startupEntries.push_back(entry);
|
||||||
|
}
|
||||||
|
|
||||||
// submit to each installed callback in turn
|
// submit to each installed callback in turn
|
||||||
BOOST_FOREACH(simgear::LogCallback* cb, m_callbacks) {
|
for (simgear::LogCallback* cb : m_callbacks) {
|
||||||
(*cb)(entry.debugClass, entry.debugPriority,
|
(*cb)(entry.debugClass, entry.debugPriority,
|
||||||
entry.file, entry.line, entry.message);
|
entry.file, entry.line, entry.message);
|
||||||
}
|
}
|
||||||
@@ -401,6 +422,13 @@ public:
|
|||||||
{
|
{
|
||||||
PauseThread pause(this);
|
PauseThread pause(this);
|
||||||
m_callbacks.push_back(cb);
|
m_callbacks.push_back(cb);
|
||||||
|
|
||||||
|
// we clear startup entries not using this, so always safe to run
|
||||||
|
// this code, container will simply be empty
|
||||||
|
for (auto entry : m_startupEntries) {
|
||||||
|
(*cb)(entry.debugClass, entry.debugPriority,
|
||||||
|
entry.file, entry.line, entry.message);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void removeCallback(simgear::LogCallback* cb)
|
void removeCallback(simgear::LogCallback* cb)
|
||||||
@@ -557,6 +585,11 @@ logstream::logToFile( const SGPath& aPath, sgDebugClass c, sgDebugPriority p )
|
|||||||
global_privateLogstream->addCallback(new FileLogCallback(aPath, c, p));
|
global_privateLogstream->addCallback(new FileLogCallback(aPath, c, p));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void logstream::setStartupLoggingEnabled(bool enabled)
|
||||||
|
{
|
||||||
|
global_privateLogstream->setStartupLoggingEnabled(enabled);
|
||||||
|
}
|
||||||
|
|
||||||
namespace simgear
|
namespace simgear
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|||||||
@@ -134,6 +134,12 @@ public:
|
|||||||
|
|
||||||
void removeCallback(simgear::LogCallback* cb);
|
void removeCallback(simgear::LogCallback* cb);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* optionally record all entries and submit them to new log callbacks that
|
||||||
|
* are added. This allows simplified logging configuration, but still including
|
||||||
|
* early startup information in all logs.
|
||||||
|
*/
|
||||||
|
void setStartupLoggingEnabled(bool enabled);
|
||||||
private:
|
private:
|
||||||
// constructor
|
// constructor
|
||||||
logstream();
|
logstream();
|
||||||
|
|||||||
Reference in New Issue
Block a user