|
2 | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
3 | 3 |
|
4 | 4 | #include "perfdata/gelfwriter.hpp" |
| 5 | +#include "base/defer.hpp" |
5 | 6 | #include "perfdata/gelfwriter-ti.cpp" |
6 | 7 | #include "icinga/service.hpp" |
7 | 8 | #include "icinga/notification.hpp" |
@@ -90,6 +91,13 @@ void GelfWriter::Resume() |
90 | 91 | /* Register exception handler for WQ tasks. */ |
91 | 92 | m_WorkQueue.SetExceptionCallback([this](boost::exception_ptr exp) { ExceptionHandler(std::move(exp)); }); |
92 | 93 |
|
| 94 | + /* Setup timer for periodically flushing m_DataBuffer */ |
| 95 | + m_FlushTimer = Timer::Create(); |
| 96 | + m_FlushTimer->SetInterval(GetFlushInterval()); |
| 97 | + m_FlushTimer->OnTimerExpired.connect([this](const Timer * const&) { FlushTimeout(); }); |
| 98 | + m_FlushTimer->Start(); |
| 99 | + m_FlushTimer->Reschedule(0); |
| 100 | + |
93 | 101 | m_Connection = new PerfdataWriterConnection{this, GetHost(), GetPort(), m_SslContext, !GetInsecureNoverify()}; |
94 | 102 |
|
95 | 103 | /* Register event handlers. */ |
@@ -360,19 +368,38 @@ void GelfWriter::SendLogMessage(const Checkable::Ptr& checkable, const String& g |
360 | 368 | { |
361 | 369 | AssertOnWorkQueue(); |
362 | 370 |
|
363 | | - std::ostringstream msgbuf; |
364 | | - msgbuf << gelfMessage; |
365 | | - msgbuf << '\0'; |
| 371 | + Log(LogDebug, "GelfWriter") |
| 372 | + << "Checkable '" << checkable->GetName() << "' sending message '" << gelfMessage << "'."; |
366 | 373 |
|
367 | | - auto log = msgbuf.str(); |
| 374 | + m_MsgBuf.GetData().reserve(m_MsgBuf.GetLength() + gelfMessage.GetLength() + 1); |
| 375 | + m_MsgBuf += gelfMessage; |
| 376 | + m_MsgBuf += '\0'; |
368 | 377 |
|
369 | | - try { |
370 | | - Log(LogDebug, "GelfWriter") |
371 | | - << "Checkable '" << checkable->GetName() << "' sending message '" << log << "'."; |
| 378 | + if (GetFlushThreshold() <= m_MsgBuf.GetLength()) { |
| 379 | + Flush(); |
| 380 | + } |
| 381 | +} |
| 382 | + |
| 383 | +/** |
| 384 | + * Queues a Flush on the work-queue if none is queued yet. |
| 385 | + */ |
| 386 | +void GelfWriter::FlushTimeout() |
| 387 | +{ |
| 388 | + if (m_FlushTimerInQueue.exchange(true, std::memory_order_relaxed)) { |
| 389 | + return; |
| 390 | + } |
| 391 | + |
| 392 | + m_WorkQueue.Enqueue([&]() { |
| 393 | + Defer resetFlushTimer{[&]() { m_FlushTimerInQueue.store(false, std::memory_order_relaxed); }}; |
| 394 | + Flush(); |
| 395 | + }); |
| 396 | +} |
372 | 397 |
|
373 | | - m_Connection->Send(boost::asio::const_buffer{log.data(), log.length()}); |
| 398 | +void GelfWriter::Flush() |
| 399 | +{ |
| 400 | + try { |
| 401 | + m_Connection->Send(boost::asio::buffer(std::exchange(m_MsgBuf.GetData(), {}))); |
374 | 402 | } catch (const PerfdataWriterConnection::Stopped& ex) { |
375 | 403 | Log(LogDebug, "GelfWriter") << ex.what(); |
376 | | - return; |
377 | 404 | } |
378 | 405 | } |
0 commit comments