]> granicus.if.org Git - icinga2/commitdiff
Implement additional query statistics for DB IDO
authorGunnar Beutner <gunnar@beutner.name>
Wed, 16 Dec 2015 07:49:47 +0000 (08:49 +0100)
committerGunnar Beutner <gunnar@beutner.name>
Tue, 23 Feb 2016 08:15:16 +0000 (09:15 +0100)
fixes #10860

lib/db_ido/dbconnection.cpp
lib/db_ido/dbconnection.hpp
lib/db_ido_mysql/idomysqlconnection.cpp
lib/db_ido_mysql/idomysqlconnection.hpp
lib/db_ido_pgsql/idopgsqlconnection.cpp
lib/db_ido_pgsql/idopgsqlconnection.hpp

index 81fb681ed14c874e20d42c169b13d6e6c9c496ae..919ef39595a8ece5441a30a2a77ee63e5ad37a41 100644 (file)
@@ -39,7 +39,7 @@ Timer::Ptr DbConnection::m_ProgramStatusTimer;
 boost::once_flag DbConnection::m_OnceFlag = BOOST_ONCE_INIT;
 
 DbConnection::DbConnection(void)
-       : m_QueryStats(15 * 60)
+       : m_QueryStats(15 * 60), m_PendingQueries(0), m_PendingQueriesTimestamp(0)
 { }
 
 void DbConnection::OnConfigLoaded(void)
@@ -65,6 +65,34 @@ void DbConnection::Start(bool runtimeCreated)
        ConfigObject::OnActiveChanged.connect(boost::bind(&DbConnection::UpdateObject, this, _1));
 }
 
+void DbConnection::StatsLoggerTimerHandler(void)
+{
+       int pending = GetPendingQueryCount();
+
+       double now = Utility::GetTime();
+       double gradient = (pending - m_PendingQueries) / (now - m_PendingQueriesTimestamp);
+       double timeToZero = -pending / gradient;
+
+       String timeInfo;
+
+       if (pending > GetQueryCount(5)) {
+               timeInfo = " empty in ";
+               if (timeToZero < 0)
+                       timeInfo += "infinite time, your database isn't able to keep up";
+               else
+                       timeInfo += Utility::FormatDuration(timeToZero);
+       }
+
+       m_PendingQueries = pending;
+       m_PendingQueriesTimestamp = now;
+
+       Log(LogInformation, GetReflectionType()->GetName())
+           << "Query queue items: " << pending
+           << ", query rate: " << std::setw(2) << GetQueryCount(60) / 60.0 << "/s"
+           << " (" << GetQueryCount(60) << "/min " << GetQueryCount(5 * 60) << "/5min " << GetQueryCount(15 * 60) << "/15min);"
+           << timeInfo;
+}
+
 void DbConnection::Resume(void)
 {
        ConfigObject::Resume();
@@ -76,6 +104,11 @@ void DbConnection::Resume(void)
        m_CleanUpTimer->SetInterval(60);
        m_CleanUpTimer->OnTimerExpired.connect(boost::bind(&DbConnection::CleanUpHandler, this));
        m_CleanUpTimer->Start();
+
+       m_StatsLoggerTimer = new Timer();
+       m_StatsLoggerTimer->SetInterval(15);
+       m_StatsLoggerTimer->OnTimerExpired.connect(boost::bind(&DbConnection::StatsLoggerTimerHandler, this));
+       m_StatsLoggerTimer->Start();
 }
 
 void DbConnection::Pause(void)
index e93c6b297acd64a9c3d26c1409072521fa84cd7a..63c12489cabd278be18a181fb7bc025d143b204a 100644 (file)
@@ -114,11 +114,16 @@ private:
        static Timer::Ptr m_ProgramStatusTimer;
        static boost::once_flag m_OnceFlag;
 
+       Timer::Ptr m_StatsLoggerTimer;
+       void StatsLoggerTimerHandler(void);
+
        static void InsertRuntimeVariable(const String& key, const Value& value);
        static void ProgramStatusHandler(void);
 
        mutable boost::mutex m_StatsMutex;
        RingBuffer m_QueryStats;
+       int m_PendingQueries;
+       double m_PendingQueriesTimestamp;
 };
 
 struct database_error : virtual std::exception, virtual boost::exception { };
index 5b1bfd057152ba5776ae89b3c5a7683d91c05c33..a7ec5459e53283b3c73bf22160bbc05d10d9fbc0 100644 (file)
@@ -387,6 +387,18 @@ void IdoMysqlConnection::Reconnect(void)
        ClearCustomVarTable("customvariables");
        ClearCustomVarTable("customvariablestatus");
 
+       m_QueryQueue.Enqueue(boost::bind(&IdoMysqlConnection::FinishConnect, this, startTime), PriorityLow);
+}
+
+void IdoMysqlConnection::FinishConnect(double startTime)
+{
+       AssertOnWorkQueue();
+
+       if (!GetConnected())
+               return;
+
+       FinishAsyncQueries();
+
        Log(LogInformation, "IdoMysqlConnection")
            << "Finished reconnecting to MySQL IDO database in " << std::setw(2) << Utility::GetTime() - startTime << " second(s).";
 
index 71fbc4a6e0306d33152b80cbdd4ac15c43a9dea8..5823e33e3b956d0311156155a6cdbdaff2a3c6c9 100644 (file)
@@ -118,6 +118,8 @@ private:
        void ClearCustomVarTable(const String& table);
 
        void ExceptionHandler(boost::exception_ptr exp);
+
+       void FinishConnect(double startTime);
 };
 
 }
index eb5bce15f1eeddd969953dc6ce0681b1a638e262..581a20a70646125d791116435246ded60f5ea40f 100644 (file)
@@ -377,6 +377,16 @@ void IdoPgsqlConnection::Reconnect(void)
        ClearCustomVarTable("customvariables");
        ClearCustomVarTable("customvariablestatus");
 
+       m_QueryQueue.Enqueue(boost::bind(&IdoPgsqlConnection::FinishConnect, this, startTime), PriorityLow);
+}
+
+void IdoPgsqlConnection::FinishConnect(double startTime)
+{
+       AssertOnWorkQueue();
+
+       if (!GetConnected())
+               return;
+
        Log(LogInformation, "IdoPgsqlConnection")
            << "Finished reconnecting to PostgreSQL IDO database in " << std::setw(2) << Utility::GetTime() - startTime << " second(s).";
 
index d0e2e567316d1eeb8db8044826d201db4cc36475..cdf789ff75365b4fe6fba511dbdcfd79612d281e 100644 (file)
@@ -91,6 +91,8 @@ private:
        void TxTimerHandler(void);
        void ReconnectTimerHandler(void);
 
+       void StatsLoggerTimerHandler(void);
+
        bool CanExecuteQuery(const DbQuery& query);
 
        void InternalExecuteQuery(const DbQuery& query, DbQueryType *typeOverride = NULL);
@@ -101,6 +103,8 @@ private:
        void ClearCustomVarTable(const String& table);
 
        void ExceptionHandler(boost::exception_ptr exp);
+
+       void FinishConnect(double startTime);
 };
 
 }