Use a circular buffer to store only the last 250 log messages
This commit is contained in:
parent
c6005be4a1
commit
a942687050
3 changed files with 21 additions and 43 deletions
|
@ -30,7 +30,6 @@
|
|||
#include <boost/filesystem/fstream.hpp>
|
||||
#include <boost/range/algorithm.hpp>
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
#include <functional>
|
||||
|
||||
namespace agi {
|
||||
|
@ -43,30 +42,17 @@ LogSink *log;
|
|||
/// Keep this ordered the same as Severity
|
||||
const char *Severity_ID = "EAWID";
|
||||
|
||||
SinkMessage::SinkMessage(const char *section, Severity severity, const char *file, const char *func, int line, timeval tv)
|
||||
: section(section)
|
||||
, severity(severity)
|
||||
, file(file)
|
||||
, func(func)
|
||||
, line(line)
|
||||
, tv(tv)
|
||||
{
|
||||
}
|
||||
|
||||
/// @todo The log files need to be trimmed after N amount.
|
||||
LogSink::~LogSink() {
|
||||
// The destructor for emitters may try to log messages, so disable all the
|
||||
// emitters before destructing any
|
||||
std::vector<Emitter*> emitters_temp;
|
||||
swap(emitters_temp, emitters);
|
||||
util::delete_clear(emitters_temp);
|
||||
|
||||
util::delete_clear(sink);
|
||||
}
|
||||
|
||||
void LogSink::log(SinkMessage *sm) {
|
||||
sink.push_back(sm);
|
||||
boost::for_each(emitters, [=](Emitter *em) { em->log(sm); });
|
||||
void LogSink::Log(SinkMessage const& sm) {
|
||||
messages.push_back(sm);
|
||||
boost::for_each(emitters, [=](Emitter *em) { em->log(&messages.back()); });
|
||||
}
|
||||
|
||||
void LogSink::Subscribe(Emitter *em) {
|
||||
|
@ -83,12 +69,17 @@ void LogSink::Unsubscribe(Emitter *em) {
|
|||
Message::Message(const char *section, Severity severity, const char *file, const char *func, int line)
|
||||
: msg(nullptr, 1024)
|
||||
{
|
||||
sm = new SinkMessage(section, severity, file, func, line, util::time_log());
|
||||
sm.section = section;
|
||||
sm.severity = severity;
|
||||
sm.file = file;
|
||||
sm.func = func;
|
||||
sm.line = line;
|
||||
sm.tv = util::time_log();
|
||||
}
|
||||
|
||||
Message::~Message() {
|
||||
sm->message = std::string(msg.str(), (std::string::size_type)msg.pcount());
|
||||
agi::log::log->log(sm);
|
||||
sm.message = std::string(msg.str(), (std::string::size_type)msg.pcount());
|
||||
agi::log::log->Log(sm);
|
||||
msg.freeze(false);
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#include <libaegisub/time.h>
|
||||
|
||||
#include <ctime>
|
||||
#include <deque>
|
||||
#include <boost/circular_buffer.hpp>
|
||||
#include <iosfwd>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
@ -68,15 +68,6 @@ extern LogSink *log;
|
|||
|
||||
/// Container to hold a single message
|
||||
struct SinkMessage {
|
||||
/// @brief Constructor
|
||||
/// @param section Section info
|
||||
/// @param severity Severity
|
||||
/// @param file File name
|
||||
/// @param func Function name
|
||||
/// @param line Source line
|
||||
/// @param tv Log time
|
||||
SinkMessage(const char *section, Severity severity, const char *file, const char *func, int line, timeval tv);
|
||||
|
||||
const char *section; ///< Section info eg "video/open" "video/seek" etc
|
||||
Severity severity; ///< Severity
|
||||
const char *file; ///< Source file
|
||||
|
@ -88,23 +79,19 @@ struct SinkMessage {
|
|||
|
||||
class Emitter;
|
||||
|
||||
/// Message sink for holding all messages
|
||||
typedef std::deque<SinkMessage*> Sink;
|
||||
|
||||
/// Log sink, single destination for all messages
|
||||
class LogSink {
|
||||
/// Log sink
|
||||
Sink sink;
|
||||
boost::circular_buffer<SinkMessage> messages;
|
||||
|
||||
/// List of pointers to emitters
|
||||
std::vector<Emitter*> emitters;
|
||||
|
||||
public:
|
||||
/// Destructor
|
||||
LogSink() : messages(250) { }
|
||||
~LogSink();
|
||||
|
||||
/// Insert a message into the sink.
|
||||
void log(SinkMessage *sm);
|
||||
void Log(SinkMessage const& sm);
|
||||
|
||||
/// @brief Subscribe an emitter
|
||||
/// @param em Emitter to add
|
||||
|
@ -118,7 +105,7 @@ public:
|
|||
|
||||
/// @brief @get the complete (current) log.
|
||||
/// @return Const pointer to internal sink.
|
||||
const Sink* GetSink() const { return &sink; }
|
||||
decltype(messages) const& GetSink() const { return messages; }
|
||||
};
|
||||
|
||||
/// An emitter to produce human readable output for a log sink.
|
||||
|
@ -150,7 +137,7 @@ public:
|
|||
/// Generates a message and submits it to the log sink.
|
||||
class Message {
|
||||
std::ostrstream msg;
|
||||
SinkMessage *sm;
|
||||
SinkMessage sm;
|
||||
|
||||
public:
|
||||
Message(const char *section, Severity severity, const char *file, const char *func, int line);
|
||||
|
|
|
@ -57,15 +57,15 @@ public:
|
|||
EmitLog(wxTextCtrl *t)
|
||||
: text_ctrl(t)
|
||||
{
|
||||
const agi::log::Sink *sink = agi::log::log->GetSink();
|
||||
for_each(sink->begin(), sink->end(), std::bind(&EmitLog::log, this, std::placeholders::_1));
|
||||
for (auto sm : agi::log::log->GetSink())
|
||||
log(&sm);
|
||||
}
|
||||
|
||||
void log(agi::log::SinkMessage *sm) {
|
||||
#ifndef _WIN32
|
||||
tm tmtime;
|
||||
localtime_r(&sm->tv.tv_sec, &tmtime);
|
||||
wxString log = wxString::Format("%c %02d:%02d:%02d %-6ld <%-25s> [%s:%s:%d] %s\n",
|
||||
auto log = wxString::Format("%c %02d:%02d:%02d %-6ld <%-25s> [%s:%s:%d] %s\n",
|
||||
agi::log::Severity_ID[sm->severity],
|
||||
(int)tmtime.tm_hour,
|
||||
(int)tmtime.tm_min,
|
||||
|
@ -77,7 +77,7 @@ public:
|
|||
sm->line,
|
||||
to_wx(sm->message));
|
||||
#else
|
||||
wxString log = wxString::Format("%c %-6ld <%-25s> [%s:%s:%d] %s\n",
|
||||
auto log = wxString::Format("%c %-6ld <%-25s> [%s:%s:%d] %s\n",
|
||||
agi::log::Severity_ID[sm->severity],
|
||||
sm->tv.tv_usec,
|
||||
sm->section,
|
||||
|
|
Loading…
Reference in a new issue