From ed2ebdf0d043c31cddcfd63530d6c1bc0e73a4e9 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Tue, 28 Mar 2017 11:30:14 +0200 Subject: [PATCH] RedisWriter: publish Icinga 2 stats as a simple "keepalive" Use case: a reader subscribes to config changes. As they happen rarely, chances are good that the connection will time out in the meantime. Now, a reconnect is easy - but you wouldn't know whether you missed any config changes. So you are required to issue a new sync to be on the safe side. Given a 60sec connection timeout (think: SSL layer, firewalls etc) when no traffic happens this would be too expensive. Some kind of a heartbeat available for subscription would allow subscribers to artificially keep the connection alive. As a first simple solution to this I'd suggest to publish CIB data, that might be useful anyways. refs #4991 fixes #5098 Signed-off-by: Michael Friedrich --- lib/redis/rediswriter.cpp | 28 ++++++++++++++++++++++++++++ lib/redis/rediswriter.hpp | 3 +++ 2 files changed, 31 insertions(+) diff --git a/lib/redis/rediswriter.cpp b/lib/redis/rediswriter.cpp index 0674f9d62..70403068b 100644 --- a/lib/redis/rediswriter.cpp +++ b/lib/redis/rediswriter.cpp @@ -21,6 +21,7 @@ #include "redis/rediswriter.tcpp" #include "remote/eventqueue.hpp" #include "base/json.hpp" +#include "base/statsfunction.hpp" using namespace icinga; @@ -55,6 +56,11 @@ void RedisWriter::Start(bool runtimeCreated) m_SubscriptionTimer->OnTimerExpired.connect(boost::bind(&RedisWriter::UpdateSubscriptionsTimerHandler, this)); m_SubscriptionTimer->Start(); + m_StatsTimer = new Timer(); + m_StatsTimer->SetInterval(10); + m_StatsTimer->OnTimerExpired.connect(boost::bind(&RedisWriter::PublishStatsTimerHandler, this)); + m_StatsTimer->Start(); + boost::thread thread(boost::bind(&RedisWriter::HandleEvents, this)); thread.detach(); } @@ -202,6 +208,28 @@ void RedisWriter::UpdateSubscriptions(void) << "Current Redis event subscriptions: " << m_Subscriptions.size(); } +void RedisWriter::PublishStatsTimerHandler(void) +{ + m_WorkQueue.Enqueue(boost::bind(&RedisWriter::PublishStats, this)); +} + +void RedisWriter::PublishStats(void) +{ + AssertOnWorkQueue(); + + if (!m_Context) + return; + + //TODO: Figure out if more stats can be useful here. + StatsFunction::Ptr func = StatsFunctionRegistry::GetInstance()->GetItem("CIB"); + Dictionary::Ptr status = new Dictionary(); + Array::Ptr perfdata = new Array(); + func->Invoke(status, perfdata); + String jsonStats = JsonEncode(status); + + ExecuteQuery({ "PUBLISH", "icinga:stats", jsonStats }); +} + void RedisWriter::HandleEvents(void) { String queueName = Utility::NewUniqueID(); diff --git a/lib/redis/rediswriter.hpp b/lib/redis/rediswriter.hpp index 04af7c520..d9bcabc07 100644 --- a/lib/redis/rediswriter.hpp +++ b/lib/redis/rediswriter.hpp @@ -58,6 +58,8 @@ private: void UpdateSubscriptionsTimerHandler(void); void UpdateSubscriptions(void); + void PublishStatsTimerHandler(void); + void PublishStats(void); /* config & status dump */ void UpdateAllConfigObjects(void); @@ -86,6 +88,7 @@ private: boost::shared_ptr ExecuteQuery(const std::vector& query); + Timer::Ptr m_StatsTimer; Timer::Ptr m_ReconnectTimer; Timer::Ptr m_SubscriptionTimer; WorkQueue m_WorkQueue;