Created
August 30, 2017 21:23
-
-
Save bengotow/82e081fb94a17b905ec85ca9736c9c74 to your computer and use it in GitHub Desktop.
SPDLog Sink for "Flush Within Xmsec"
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
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