Use a circular buffer to store only the last 250 log messages

This commit is contained in:
Thomas Goyne 2013-01-23 10:41:28 -08:00
parent c6005be4a1
commit a942687050
3 changed files with 21 additions and 43 deletions

View file

@ -30,7 +30,6 @@
#include <boost/filesystem/fstream.hpp> #include <boost/filesystem/fstream.hpp>
#include <boost/range/algorithm.hpp> #include <boost/range/algorithm.hpp>
#include <cstring> #include <cstring>
#include <fstream>
#include <functional> #include <functional>
namespace agi { namespace agi {
@ -43,30 +42,17 @@ LogSink *log;
/// Keep this ordered the same as Severity /// Keep this ordered the same as Severity
const char *Severity_ID = "EAWID"; 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() { LogSink::~LogSink() {
// The destructor for emitters may try to log messages, so disable all the // The destructor for emitters may try to log messages, so disable all the
// emitters before destructing any // emitters before destructing any
std::vector<Emitter*> emitters_temp; std::vector<Emitter*> emitters_temp;
swap(emitters_temp, emitters); swap(emitters_temp, emitters);
util::delete_clear(emitters_temp); util::delete_clear(emitters_temp);
util::delete_clear(sink);
} }
void LogSink::log(SinkMessage *sm) { void LogSink::Log(SinkMessage const& sm) {
sink.push_back(sm); messages.push_back(sm);
boost::for_each(emitters, [=](Emitter *em) { em->log(sm); }); boost::for_each(emitters, [=](Emitter *em) { em->log(&messages.back()); });
} }
void LogSink::Subscribe(Emitter *em) { 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) Message::Message(const char *section, Severity severity, const char *file, const char *func, int line)
: msg(nullptr, 1024) : 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() { Message::~Message() {
sm->message = std::string(msg.str(), (std::string::size_type)msg.pcount()); sm.message = std::string(msg.str(), (std::string::size_type)msg.pcount());
agi::log::log->log(sm); agi::log::log->Log(sm);
msg.freeze(false); msg.freeze(false);
} }

View file

@ -20,7 +20,7 @@
#include <libaegisub/time.h> #include <libaegisub/time.h>
#include <ctime> #include <ctime>
#include <deque> #include <boost/circular_buffer.hpp>
#include <iosfwd> #include <iosfwd>
#include <memory> #include <memory>
#include <vector> #include <vector>
@ -68,15 +68,6 @@ extern LogSink *log;
/// Container to hold a single message /// Container to hold a single message
struct SinkMessage { 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 const char *section; ///< Section info eg "video/open" "video/seek" etc
Severity severity; ///< Severity Severity severity; ///< Severity
const char *file; ///< Source file const char *file; ///< Source file
@ -88,23 +79,19 @@ struct SinkMessage {
class Emitter; class Emitter;
/// Message sink for holding all messages
typedef std::deque<SinkMessage*> Sink;
/// Log sink, single destination for all messages /// Log sink, single destination for all messages
class LogSink { class LogSink {
/// Log sink boost::circular_buffer<SinkMessage> messages;
Sink sink;
/// List of pointers to emitters /// List of pointers to emitters
std::vector<Emitter*> emitters; std::vector<Emitter*> emitters;
public: public:
/// Destructor LogSink() : messages(250) { }
~LogSink(); ~LogSink();
/// Insert a message into the sink. /// Insert a message into the sink.
void log(SinkMessage *sm); void Log(SinkMessage const& sm);
/// @brief Subscribe an emitter /// @brief Subscribe an emitter
/// @param em Emitter to add /// @param em Emitter to add
@ -118,7 +105,7 @@ public:
/// @brief @get the complete (current) log. /// @brief @get the complete (current) log.
/// @return Const pointer to internal sink. /// @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. /// 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. /// Generates a message and submits it to the log sink.
class Message { class Message {
std::ostrstream msg; std::ostrstream msg;
SinkMessage *sm; SinkMessage sm;
public: public:
Message(const char *section, Severity severity, const char *file, const char *func, int line); Message(const char *section, Severity severity, const char *file, const char *func, int line);

View file

@ -57,15 +57,15 @@ public:
EmitLog(wxTextCtrl *t) EmitLog(wxTextCtrl *t)
: text_ctrl(t) : text_ctrl(t)
{ {
const agi::log::Sink *sink = agi::log::log->GetSink(); for (auto sm : agi::log::log->GetSink())
for_each(sink->begin(), sink->end(), std::bind(&EmitLog::log, this, std::placeholders::_1)); log(&sm);
} }
void log(agi::log::SinkMessage *sm) { void log(agi::log::SinkMessage *sm) {
#ifndef _WIN32 #ifndef _WIN32
tm tmtime; tm tmtime;
localtime_r(&sm->tv.tv_sec, &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], agi::log::Severity_ID[sm->severity],
(int)tmtime.tm_hour, (int)tmtime.tm_hour,
(int)tmtime.tm_min, (int)tmtime.tm_min,
@ -77,7 +77,7 @@ public:
sm->line, sm->line,
to_wx(sm->message)); to_wx(sm->message));
#else #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], agi::log::Severity_ID[sm->severity],
sm->tv.tv_usec, sm->tv.tv_usec,
sm->section, sm->section,