Skip to content

Commit 9610e4a

Browse files
Add flush_threshold/flush_interval logic to GelfWriter
1 parent 54a46c8 commit 9610e4a

4 files changed

Lines changed: 51 additions & 9 deletions

File tree

doc/09-object-types.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1318,6 +1318,8 @@ Configuration Attributes:
13181318
diconnect\_timeout | Duration | **Optional.** Timeout to wait for any outstanding data to be flushed to GELF before disconnecting. Defaults to `10s`.
13191319
source | String | **Optional.** Source name for this instance. Defaults to `icinga2`.
13201320
enable\_send\_perfdata | Boolean | **Optional.** Enable performance data for 'CHECK RESULT' events.
1321+
flush\_interval | Duration | **Optional.** How long to buffer data points before sending. Defaults to `15s`.
1322+
flush\_threshold | Number | **Optional.** How many bytes to buffer before forcing a flush to the backend. Defaults to `2MiB`.
13211323
enable\_ha | Boolean | **Optional.** Enable the high availability functionality. Only valid in a [cluster setup](06-distributed-monitoring.md#distributed-monitoring-high-availability-features). Defaults to `false`.
13221324
enable\_tls | Boolean | **Optional.** Whether to use a TLS stream. Defaults to `false`.
13231325
insecure\_noverify | Boolean | **Optional.** Disable TLS peer verification.

lib/perfdata/gelfwriter.cpp

Lines changed: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// SPDX-License-Identifier: GPL-2.0-or-later
33

44
#include "perfdata/gelfwriter.hpp"
5+
#include "base/defer.hpp"
56
#include "perfdata/gelfwriter-ti.cpp"
67
#include "icinga/service.hpp"
78
#include "icinga/notification.hpp"
@@ -91,6 +92,13 @@ void GelfWriter::Resume()
9192
/* Register exception handler for WQ tasks. */
9293
m_WorkQueue.SetExceptionCallback([this](std::exception_ptr exp) { ExceptionHandler(std::move(exp)); });
9394

95+
/* Setup timer for periodically flushing m_DataBuffer */
96+
m_FlushTimer = Timer::Create();
97+
m_FlushTimer->SetInterval(GetFlushInterval());
98+
m_FlushTimer->OnTimerExpired.connect([this](const Timer * const&) { FlushTimeout(); });
99+
m_FlushTimer->Start();
100+
m_FlushTimer->Reschedule(0);
101+
94102
m_Connection = new PerfdataWriterConnection{this, GetHost(), GetPort(), m_SslContext, !GetInsecureNoverify()};
95103
m_LockedConnection.store(m_Connection);
96104

@@ -117,6 +125,8 @@ void GelfWriter::Pause()
117125
m_HandleNotifications.disconnect();
118126
m_HandleStateChanges.disconnect();
119127

128+
m_FlushTimer->Stop(true);
129+
120130
std::promise<void> queueDonePromise;
121131

122132
m_WorkQueue.Enqueue([&]() {
@@ -361,19 +371,38 @@ void GelfWriter::SendLogMessage(const Checkable::Ptr& checkable, const String& g
361371
{
362372
AssertOnWorkQueue();
363373

364-
std::ostringstream msgbuf;
365-
msgbuf << gelfMessage;
366-
msgbuf << '\0';
374+
Log(LogDebug, "GelfWriter")
375+
<< "Checkable '" << checkable->GetName() << "' sending message '" << gelfMessage << "'.";
367376

368-
auto log = msgbuf.str();
377+
m_MsgBuf.GetData().reserve(m_MsgBuf.GetLength() + gelfMessage.GetLength() + 1);
378+
m_MsgBuf += gelfMessage;
379+
m_MsgBuf += '\0';
369380

370-
try {
371-
Log(LogDebug, "GelfWriter")
372-
<< "Checkable '" << checkable->GetName() << "' sending message '" << log << "'.";
381+
if (GetFlushThreshold() <= m_MsgBuf.GetLength()) {
382+
Flush();
383+
}
384+
}
373385

374-
m_Connection->Send(boost::asio::const_buffer{log.data(), log.length()});
386+
/**
387+
* Queues a Flush on the work-queue if none is queued yet.
388+
*/
389+
void GelfWriter::FlushTimeout()
390+
{
391+
if (m_FlushTimerInQueue.exchange(true, std::memory_order_relaxed)) {
392+
return;
393+
}
394+
395+
m_WorkQueue.Enqueue([&]() {
396+
Defer resetFlushTimer{[&]() { m_FlushTimerInQueue.store(false, std::memory_order_relaxed); }};
397+
Flush();
398+
});
399+
}
400+
401+
void GelfWriter::Flush()
402+
{
403+
try {
404+
m_Connection->Send(boost::asio::buffer(std::exchange(m_MsgBuf.GetData(), {})));
375405
} catch (const PerfdataWriterConnection::Stopped& ex) {
376406
Log(LogDebug, "GelfWriter") << ex.what();
377-
return;
378407
}
379408
}

lib/perfdata/gelfwriter.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ class GelfWriter final : public ObjectImpl<GelfWriter>
3535
private:
3636
PerfdataWriterConnection::Ptr m_Connection;
3737
Locked<PerfdataWriterConnection::Ptr> m_LockedConnection;
38+
Timer::Ptr m_FlushTimer;
39+
std::atomic_bool m_FlushTimerInQueue{false};
40+
String m_MsgBuf;
3841
WorkQueue m_WorkQueue{10000000, 1};
3942
Shared<boost::asio::ssl::context>::Ptr m_SslContext;
4043

@@ -47,6 +50,8 @@ class GelfWriter final : public ObjectImpl<GelfWriter>
4750

4851
String ComposeGelfMessage(const Dictionary::Ptr& fields, const String& source, double ts);
4952
void SendLogMessage(const Checkable::Ptr& checkable, const String& gelfMessage);
53+
void FlushTimeout();
54+
void Flush();
5055

5156
void AssertOnWorkQueue();
5257

lib/perfdata/gelfwriter.ti

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,12 @@ class GelfWriter : ConfigObject
2424
[config] bool enable_send_perfdata {
2525
default {{{ return false; }}}
2626
};
27+
[config] int flush_interval {
28+
default {{{ return 15; }}}
29+
};
30+
[config] std::size_t flush_threshold {
31+
default {{{ return 2 * 1024 * 1024; }}}
32+
};
2733

2834
[config] double disconnect_timeout {
2935
default {{{ return 10; }}}

0 commit comments

Comments
 (0)