Split the json log writing into a seperate class from LogSink
Originally committed to SVN as r6248.
This commit is contained in:
parent
59ce8bf414
commit
e2d31b708e
5 changed files with 76 additions and 52 deletions
|
@ -64,49 +64,17 @@ SinkMessage::~SinkMessage() {
|
||||||
delete message;
|
delete message;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
LogSink::LogSink(const std::string& dir_log): dir_log(dir_log) {
|
|
||||||
util::time_log(time_start);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @todo The log files need to be trimmed after N amount.
|
/// @todo The log files need to be trimmed after N amount.
|
||||||
LogSink::~LogSink() {
|
LogSink::~LogSink() {
|
||||||
json::Object root;
|
// The destructor for emitters may try to log messages, so disable all the
|
||||||
json::Array &array = root["log"];
|
// emitters before destructing any
|
||||||
|
std::vector<Emitter*> emitters_temp;
|
||||||
|
swap(emitters_temp, emitters);
|
||||||
|
util::delete_clear(emitters_temp);
|
||||||
|
|
||||||
agi_timeval time_close;
|
util::delete_clear(sink);
|
||||||
util::time_log(time_close);
|
|
||||||
|
|
||||||
for (unsigned int i=0; i < sink.size(); i++) {
|
|
||||||
json::Object entry;
|
|
||||||
entry["sec"] = sink[i]->tv.tv_sec;
|
|
||||||
entry["usec"] = sink[i]->tv.tv_usec;
|
|
||||||
entry["severity"] = sink[i]->severity,
|
|
||||||
entry["section"] = sink[i]->section;
|
|
||||||
entry["file"] = sink[i]->file;
|
|
||||||
entry["func"] = sink[i]->func;
|
|
||||||
entry["line"] = sink[i]->line;
|
|
||||||
entry["message"] = std::string(sink[i]->message, sink[i]->len);
|
|
||||||
|
|
||||||
array.push_back(entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
json::Array &timeval_open = root["timeval"]["open"];
|
|
||||||
timeval_open.push_back(time_start.tv_sec);
|
|
||||||
timeval_open.push_back(time_start.tv_usec);
|
|
||||||
|
|
||||||
json::Array &timeval_close = root["timeval"]["close"];
|
|
||||||
timeval_close.push_back(time_close.tv_sec);
|
|
||||||
timeval_close.push_back(time_close.tv_usec);
|
|
||||||
|
|
||||||
std::stringstream str;
|
|
||||||
str << dir_log << time_start.tv_sec << ".json";
|
|
||||||
json::Writer::Write(root, io::Save(str.str()).Get());
|
|
||||||
|
|
||||||
agi::util::delete_clear(sink);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void LogSink::log(SinkMessage *sm) {
|
void LogSink::log(SinkMessage *sm) {
|
||||||
sink.push_back(sm);
|
sink.push_back(sm);
|
||||||
|
|
||||||
|
@ -147,5 +115,47 @@ Message::~Message() {
|
||||||
agi::log::log->log(sm);
|
agi::log::log->log(sm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JsonEmitter::JsonEmitter(std::string const& directory, const agi::log::LogSink *log_sink)
|
||||||
|
: directory(directory)
|
||||||
|
, log_sink(log_sink)
|
||||||
|
{
|
||||||
|
util::time_log(time_start);
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonEmitter::~JsonEmitter() {
|
||||||
|
json::Object root;
|
||||||
|
json::Array &array = root["log"];
|
||||||
|
|
||||||
|
agi_timeval time_close;
|
||||||
|
util::time_log(time_close);
|
||||||
|
|
||||||
|
Sink const& sink = *log_sink->GetSink();
|
||||||
|
for (unsigned int i=0; i < sink.size(); i++) {
|
||||||
|
json::Object entry;
|
||||||
|
entry["sec"] = sink[i]->tv.tv_sec;
|
||||||
|
entry["usec"] = sink[i]->tv.tv_usec;
|
||||||
|
entry["severity"] = sink[i]->severity;
|
||||||
|
entry["section"] = sink[i]->section;
|
||||||
|
entry["file"] = sink[i]->file;
|
||||||
|
entry["func"] = sink[i]->func;
|
||||||
|
entry["line"] = sink[i]->line;
|
||||||
|
entry["message"] = std::string(sink[i]->message, sink[i]->len);
|
||||||
|
|
||||||
|
array.push_back(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
json::Array &timeval_open = root["timeval"]["open"];
|
||||||
|
timeval_open.push_back(time_start.tv_sec);
|
||||||
|
timeval_open.push_back(time_start.tv_usec);
|
||||||
|
|
||||||
|
json::Array &timeval_close = root["timeval"]["close"];
|
||||||
|
timeval_close.push_back(time_close.tv_sec);
|
||||||
|
timeval_close.push_back(time_close.tv_usec);
|
||||||
|
|
||||||
|
std::stringstream str;
|
||||||
|
str << directory << time_start.tv_sec << ".json";
|
||||||
|
json::Writer::Write(root, io::Save(str.str()).Get());
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace log
|
} // namespace log
|
||||||
} // namespace agi
|
} // namespace agi
|
||||||
|
|
|
@ -110,17 +110,7 @@ class LogSink {
|
||||||
/// List of pointers to emitters
|
/// List of pointers to emitters
|
||||||
std::vector<Emitter*> emitters;
|
std::vector<Emitter*> emitters;
|
||||||
|
|
||||||
/// Init time for log writing purposes.
|
|
||||||
agi_timeval time_start;
|
|
||||||
|
|
||||||
/// Directory to place logfiles.
|
|
||||||
const std::string dir_log;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// Constructor
|
|
||||||
/// @param dir_log Directory to place log files.
|
|
||||||
LogSink(const std::string &dir_log);
|
|
||||||
|
|
||||||
/// Destructor
|
/// Destructor
|
||||||
~LogSink();
|
~LogSink();
|
||||||
|
|
||||||
|
@ -139,7 +129,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() { return &sink; }
|
const Sink* GetSink() const { return &sink; }
|
||||||
};
|
};
|
||||||
|
|
||||||
/// An emitter to produce human readable output for a log sink.
|
/// An emitter to produce human readable output for a log sink.
|
||||||
|
@ -152,6 +142,28 @@ public:
|
||||||
virtual void log(SinkMessage *sm)=0;
|
virtual void log(SinkMessage *sm)=0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// A simple emitter which writes the log to a file in json format when it's destroyed
|
||||||
|
class JsonEmitter : public Emitter {
|
||||||
|
/// Init time
|
||||||
|
agi_timeval time_start;
|
||||||
|
|
||||||
|
/// Directory to write the log file in
|
||||||
|
std::string directory;
|
||||||
|
|
||||||
|
/// Parent sink to get messages from
|
||||||
|
const agi::log::LogSink *log_sink;
|
||||||
|
public:
|
||||||
|
/// Constructor
|
||||||
|
/// @param directory Directory to write the log file in
|
||||||
|
/// @param log_sink Parent sink to get messages from
|
||||||
|
JsonEmitter(std::string const& directory, const agi::log::LogSink *log_sink);
|
||||||
|
/// Destructor
|
||||||
|
~JsonEmitter();
|
||||||
|
|
||||||
|
/// No-op log function as everything is done in the destructor
|
||||||
|
void log(SinkMessage *) { }
|
||||||
|
};
|
||||||
|
|
||||||
/// Generates a message and submits it to the log sink.
|
/// Generates a message and submits it to the log sink.
|
||||||
class Message {
|
class Message {
|
||||||
const int len;
|
const int len;
|
||||||
|
|
|
@ -43,7 +43,7 @@ bool Reporter::OnInit() {
|
||||||
|
|
||||||
const std::string path_log(util::config_path() + "log/");
|
const std::string path_log(util::config_path() + "log/");
|
||||||
wxFileName::Mkdir(path_log, 0777, wxPATH_MKDIR_FULL);
|
wxFileName::Mkdir(path_log, 0777, wxPATH_MKDIR_FULL);
|
||||||
agi::log::log = new agi::log::LogSink(path_log);
|
agi::log::log = new agi::log::LogSink;
|
||||||
// if ( !wxApp::OnInit() )
|
// if ( !wxApp::OnInit() )
|
||||||
// return false;
|
// return false;
|
||||||
|
|
||||||
|
|
|
@ -144,7 +144,8 @@ bool AegisubApp::OnInit() {
|
||||||
// logging.
|
// logging.
|
||||||
wxString path_log = StandardPaths::DecodePath("?user/log/");
|
wxString path_log = StandardPaths::DecodePath("?user/log/");
|
||||||
wxFileName::Mkdir(path_log, 0777, wxPATH_MKDIR_FULL);
|
wxFileName::Mkdir(path_log, 0777, wxPATH_MKDIR_FULL);
|
||||||
agi::log::log = new agi::log::LogSink(STD_STR(path_log));
|
agi::log::log = new agi::log::LogSink;
|
||||||
|
agi::log::log->Subscribe(new agi::log::JsonEmitter(STD_STR(path_log), agi::log::log));
|
||||||
|
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
agi::log::log->Subscribe(new agi::log::EmitSTDOUT());
|
agi::log::log->Subscribe(new agi::log::EmitSTDOUT());
|
||||||
|
|
|
@ -24,7 +24,8 @@
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
int retval;
|
int retval;
|
||||||
agi::log::log = new agi::log::LogSink("./");
|
agi::log::log = new agi::log::LogSink;
|
||||||
|
agi::log::log->Subscribe(new agi::log::JsonEmitter("./", agi::log::log));
|
||||||
::testing::InitGoogleTest(&argc, argv);
|
::testing::InitGoogleTest(&argc, argv);
|
||||||
|
|
||||||
retval = RUN_ALL_TESTS();
|
retval = RUN_ALL_TESTS();
|
||||||
|
|
Loading…
Reference in a new issue