]> 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>
Wed, 16 Dec 2015 09:46:27 +0000 (10:46 +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 67a2368101272dd8778c06f71c1d00e97fa9ba16..15bf6a398243afc18f9fc2ff2b9684fc1e5b8c9c 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 e304c7006736aeaa4d98e3d88842a8af8af82370..f0ac39ad4caa4b7dc7e30c8e5c940c84422ba42d 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 fcaaa6b3767fe1fe2846979f22cc47ee5006bee8..6ea1dcfbe5634132b98087328c210e7892a4a2fc 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 87f84fe256e4ecf6feedd48dde71bd3cd4460e24..e2aa8f43615b4ebf9b1041eb1803ab73e8152f4f 100644 (file)
@@ -118,6 +118,8 @@ private:
        void ClearCustomVarTable(const String& table);
 
        void ExceptionHandler(boost::exception_ptr exp);
+
+       void FinishConnect(double startTime);
 };
 
 }
index fc4828902550c90bd83d136963d990c531b74a28..ac312cf3f985dbc8992f347f781887d771450e4d 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 747a6fa04c95c2c5352c18d7119afbf1b03d1c91..737a8d6fa57e74bc08c5f49684cb4d5c9a83c978 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);
 };
 
 }