Skip to content

Instantly share code, notes, and snippets.

@bengotow
Created August 30, 2017 21:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bengotow/82e081fb94a17b905ec85ca9736c9c74 to your computer and use it in GitHub Desktop.
Save bengotow/82e081fb94a17b905ec85ca9736c9c74 to your computer and use it in GitHub Desktop.
SPDLog Sink for "Flush Within Xmsec"
/*
The code below shows a custom SPDLog sink that uses a separate thread and a C++0x condition_variable
to ensure that a spdlog::sinks::rotating_file_sink_mt is flushed to disk within a second of a new
log message being emitted. When no messages are arriving, the helper thread has very low wake overhead
and sleeps for 30s.
*/
std::mutex spdFlushMtx;
std::condition_variable spdFlushCV;
int spdUnflushed = 0;
bool spdFlushExit = false;
void runFlushLoop() {
while (true) {
auto desiredTime = std::chrono::system_clock::now();
desiredTime += chrono::milliseconds(30000);
{
// Wait for a message, or for 30 seconds, whichever happens first
unique_lock<mutex> lck(spdFlushMtx);
spdFlushCV.wait_until(lck, desiredTime);
if (spdFlushExit) {
return;
}
if (spdUnflushed == 0) {
continue; // detect, avoid spurious wakes
}
}
// Debounce 1sec for more messages to arrive
sleep(1);
{
// Perform flush
unique_lock<mutex> lck(spdFlushMtx);
spdlog::get("logger")->flush();
spdUnflushed = 0;
}
}
}
/*
This is a SPDLog sink that wakes the flush thread,
ensuring that logged messages are flushed to disk
within one second.
*/
class SPDFlusherSink : public spdlog::sinks::sink {
public:
std::thread * flushThread;
SPDFlusherSink() {
flushThread = new std::thread(runFlushLoop);
}
~SPDFlusherSink() {
lock_guard<mutex> lck(spdFlushMtx);
spdFlushExit = true;
spdFlushCV.notify_one();
}
void log(const spdlog::details::log_msg& msg) {
// ensure we have a flush queued
lock_guard<mutex> lck(spdFlushMtx);
spdUnflushed += 1;
spdFlushCV.notify_one();
}
void flush() {
// no-op
}
};
// Example Usage:
string logPath = string(getenv("CONFIG_DIR_PATH")) + "/mailsync.log";
std::vector<shared_ptr<spdlog::sinks::sink>> sinks;
sinks.push_back(make_shared<spdlog::sinks::rotating_file_sink_mt>(logPath, 1048576 * 5, 3));
sinks.push_back(make_shared<SPDFlusherSink>());
spdlog::create("logger", std::begin(sinks), std::end(sinks));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment