This commit is contained in:
Alexander A. Klimov 2022-06-14 17:15:54 +02:00
parent 92c886a153
commit a00f2f5d15
3 changed files with 90 additions and 19 deletions

View File

@ -299,6 +299,24 @@ void IcingadbCheckTask::ScriptFunc(const Checkable::Ptr& checkable, const CheckR
perfdata->Add(new PerfdataValue("dump_took", dumpTook, false, "seconds", dumpTookThresholds.Warning, dumpTookThresholds.Critical, 0)); perfdata->Add(new PerfdataValue("dump_took", dumpTook, false, "seconds", dumpTookThresholds.Warning, dumpTookThresholds.Critical, 0));
} }
struct {
const char * Name;
int (RedisConnection::* Getter)(RingBuffer::SizeType span, RingBuffer::SizeType tv);
} const icingaWriteSubjects[] = {
{"dump_config", &RedisConnection::GetWrittenConfigFor},
{"dump_state", &RedisConnection::GetWrittenStateFor},
{"dump_history", &RedisConnection::GetWrittenHistoryFor}
};
for (auto subject : icingaWriteSubjects) {
auto perMin ((redis->*subject.Getter)(60));
perfdata->Add(new PerfdataValue(subject.Name, perMin / 60.0, false, "", Empty, Empty, 0));
perfdata->Add(new PerfdataValue(String(subject.Name) + "_1min", perMin, false, "", Empty, Empty, 0));
perfdata->Add(new PerfdataValue(String(subject.Name) + "_5mins", (redis->*subject.Getter)(5 * 60), false, "", Empty, Empty, 0));
perfdata->Add(new PerfdataValue(String(subject.Name) + "_15mins", (redis->*subject.Getter)(15 * 60), false, "", Empty, Empty, 0));
}
msgbuf << "\n\nIcinga DB daemon\n----------------\n" msgbuf << "\n\nIcinga DB daemon\n----------------\n"
<< "\n* Version: " << version; << "\n* Version: " << version;
@ -342,9 +360,9 @@ void IcingadbCheckTask::ScriptFunc(const Checkable::Ptr& checkable, const CheckR
} }
perfdata->Add(new PerfdataValue("queries", qps, false, "", Empty, Empty, 0)); perfdata->Add(new PerfdataValue("queries", qps, false, "", Empty, Empty, 0));
perfdata->Add(new PerfdataValue("queries_1min", redis->GetQueryCount(60), Empty, Empty, 0)); perfdata->Add(new PerfdataValue("queries_1min", redis->GetQueryCount(60), false, "", Empty, Empty, 0));
perfdata->Add(new PerfdataValue("queries_5mins", redis->GetQueryCount(5 * 60), Empty, Empty, 0)); perfdata->Add(new PerfdataValue("queries_5mins", redis->GetQueryCount(5 * 60), false, "", Empty, Empty, 0));
perfdata->Add(new PerfdataValue("queries_15mins", redis->GetQueryCount(15 * 60), Empty, Empty, 0)); perfdata->Add(new PerfdataValue("queries_15mins", redis->GetQueryCount(15 * 60), false, "", Empty, Empty, 0));
perfdata->Add(new PerfdataValue("pending_queries", pendingQueries, false, "", pendingQueriesThresholds.Warning, pendingQueriesThresholds.Critical, 0)); perfdata->Add(new PerfdataValue("pending_queries", pendingQueries, false, "", pendingQueriesThresholds.Warning, pendingQueriesThresholds.Critical, 0));
perfdata->Add(new PerfdataValue("down_for", downFor, false, "seconds", downForThresholds.Warning, downForThresholds.Critical, 0)); perfdata->Add(new PerfdataValue("down_for", downFor, false, "seconds", downForThresholds.Warning, downForThresholds.Critical, 0));
perfdata->Add(new PerfdataValue("heartbeat_lag", heartbeatLag, false, "seconds", heartbeatThresholds.Warning, heartbeatThresholds.Critical)); perfdata->Add(new PerfdataValue("heartbeat_lag", heartbeatLag, false, "seconds", heartbeatThresholds.Warning, heartbeatThresholds.Critical));

View File

@ -113,7 +113,7 @@ void LogQuery(RedisConnection::Query& query, Log& msg)
* @param query Redis query * @param query Redis query
* @param priority The query's priority * @param priority The query's priority
*/ */
void RedisConnection::FireAndForgetQuery(RedisConnection::Query query, RedisConnection::QueryPriority priority) void RedisConnection::FireAndForgetQuery(RedisConnection::Query query, RedisConnection::QueryPriority priority, QueryAffects affects)
{ {
{ {
Log msg (LogDebug, "IcingaDB", "Firing and forgetting query:"); Log msg (LogDebug, "IcingaDB", "Firing and forgetting query:");
@ -122,8 +122,8 @@ void RedisConnection::FireAndForgetQuery(RedisConnection::Query query, RedisConn
auto item (Shared<Query>::Make(std::move(query))); auto item (Shared<Query>::Make(std::move(query)));
asio::post(m_Strand, [this, item, priority]() { asio::post(m_Strand, [this, item, priority, affects]() {
m_Queues.Writes[priority].emplace(WriteQueueItem{item, nullptr, nullptr, nullptr}); m_Queues.Writes[priority].emplace(WriteQueueItem{item, nullptr, nullptr, nullptr, nullptr, affects});
m_QueuedWrites.Set(); m_QueuedWrites.Set();
IncreasePendingQueries(1); IncreasePendingQueries(1);
}); });
@ -135,7 +135,7 @@ void RedisConnection::FireAndForgetQuery(RedisConnection::Query query, RedisConn
* @param queries Redis queries * @param queries Redis queries
* @param priority The queries' priority * @param priority The queries' priority
*/ */
void RedisConnection::FireAndForgetQueries(RedisConnection::Queries queries, RedisConnection::QueryPriority priority) void RedisConnection::FireAndForgetQueries(RedisConnection::Queries queries, RedisConnection::QueryPriority priority, QueryAffects affects)
{ {
for (auto& query : queries) { for (auto& query : queries) {
Log msg (LogDebug, "IcingaDB", "Firing and forgetting query:"); Log msg (LogDebug, "IcingaDB", "Firing and forgetting query:");
@ -144,8 +144,8 @@ void RedisConnection::FireAndForgetQueries(RedisConnection::Queries queries, Red
auto item (Shared<Queries>::Make(std::move(queries))); auto item (Shared<Queries>::Make(std::move(queries)));
asio::post(m_Strand, [this, item, priority]() { asio::post(m_Strand, [this, item, priority, affects]() {
m_Queues.Writes[priority].emplace(WriteQueueItem{nullptr, item, nullptr, nullptr}); m_Queues.Writes[priority].emplace(WriteQueueItem{nullptr, item, nullptr, nullptr, nullptr, affects});
m_QueuedWrites.Set(); m_QueuedWrites.Set();
IncreasePendingQueries(item->size()); IncreasePendingQueries(item->size());
}); });
@ -159,7 +159,7 @@ void RedisConnection::FireAndForgetQueries(RedisConnection::Queries queries, Red
* *
* @return The response * @return The response
*/ */
RedisConnection::Reply RedisConnection::GetResultOfQuery(RedisConnection::Query query, RedisConnection::QueryPriority priority) RedisConnection::Reply RedisConnection::GetResultOfQuery(RedisConnection::Query query, RedisConnection::QueryPriority priority, QueryAffects affects)
{ {
{ {
Log msg (LogDebug, "IcingaDB", "Executing query:"); Log msg (LogDebug, "IcingaDB", "Executing query:");
@ -170,8 +170,8 @@ RedisConnection::Reply RedisConnection::GetResultOfQuery(RedisConnection::Query
auto future (promise.get_future()); auto future (promise.get_future());
auto item (Shared<std::pair<Query, std::promise<Reply>>>::Make(std::move(query), std::move(promise))); auto item (Shared<std::pair<Query, std::promise<Reply>>>::Make(std::move(query), std::move(promise)));
asio::post(m_Strand, [this, item, priority]() { asio::post(m_Strand, [this, item, priority, affects]() {
m_Queues.Writes[priority].emplace(WriteQueueItem{nullptr, nullptr, item, nullptr}); m_Queues.Writes[priority].emplace(WriteQueueItem{nullptr, nullptr, item, nullptr, nullptr, affects});
m_QueuedWrites.Set(); m_QueuedWrites.Set();
IncreasePendingQueries(1); IncreasePendingQueries(1);
}); });
@ -189,7 +189,7 @@ RedisConnection::Reply RedisConnection::GetResultOfQuery(RedisConnection::Query
* *
* @return The responses * @return The responses
*/ */
RedisConnection::Replies RedisConnection::GetResultsOfQueries(RedisConnection::Queries queries, RedisConnection::QueryPriority priority) RedisConnection::Replies RedisConnection::GetResultsOfQueries(RedisConnection::Queries queries, RedisConnection::QueryPriority priority, QueryAffects affects)
{ {
for (auto& query : queries) { for (auto& query : queries) {
Log msg (LogDebug, "IcingaDB", "Executing query:"); Log msg (LogDebug, "IcingaDB", "Executing query:");
@ -200,8 +200,8 @@ RedisConnection::Replies RedisConnection::GetResultsOfQueries(RedisConnection::Q
auto future (promise.get_future()); auto future (promise.get_future());
auto item (Shared<std::pair<Queries, std::promise<Replies>>>::Make(std::move(queries), std::move(promise))); auto item (Shared<std::pair<Queries, std::promise<Replies>>>::Make(std::move(queries), std::move(promise)));
asio::post(m_Strand, [this, item, priority]() { asio::post(m_Strand, [this, item, priority, affects]() {
m_Queues.Writes[priority].emplace(WriteQueueItem{nullptr, nullptr, nullptr, item}); m_Queues.Writes[priority].emplace(WriteQueueItem{nullptr, nullptr, nullptr, item, nullptr, affects});
m_QueuedWrites.Set(); m_QueuedWrites.Set();
IncreasePendingQueries(item->first.size()); IncreasePendingQueries(item->first.size());
}); });
@ -625,6 +625,8 @@ void RedisConnection::WriteItem(boost::asio::yield_context& yc, RedisConnection:
if (next.Callback) { if (next.Callback) {
next.Callback(yc); next.Callback(yc);
} }
RecordAffected(next.Affects, Utility::GetTime());
} }
/** /**
@ -706,3 +708,26 @@ void RedisConnection::DecreasePendingQueries(int count)
m_OutputQueries.InsertValue(Utility::GetTime(), count); m_OutputQueries.InsertValue(Utility::GetTime(), count);
} }
} }
void RedisConnection::RecordAffected(RedisConnection::QueryAffects affected, double when)
{
if (m_Parent) {
auto parent (m_Parent);
asio::post(parent->m_Strand, [parent, affected, when]() {
parent->RecordAffected(affected, when);
});
} else {
if (affected.Config) {
m_WrittenConfig.InsertValue(when, affected.Config);
}
if (affected.State) {
m_WrittenState.InsertValue(when, affected.State);
}
if (affected.History) {
m_WrittenHistory.InsertValue(when, affected.History);
}
}
}

View File

@ -74,6 +74,13 @@ namespace icinga
SyncConnection = 255 SyncConnection = 255
}; };
struct QueryAffects
{
size_t Config = 0;
size_t State = 0;
size_t History = 0;
};
RedisConnection(const String& host, int port, const String& path, const String& password, int db, RedisConnection(const String& host, int port, const String& path, const String& password, int db,
bool useTls, bool insecure, const String& certPath, const String& keyPath, const String& caPath, const String& crlPath, bool useTls, bool insecure, const String& certPath, const String& keyPath, const String& caPath, const String& crlPath,
const String& tlsProtocolmin, const String& cipherList, double connectTimeout, DebugInfo di, const Ptr& parent = nullptr); const String& tlsProtocolmin, const String& cipherList, double connectTimeout, DebugInfo di, const Ptr& parent = nullptr);
@ -84,11 +91,11 @@ namespace icinga
bool IsConnected(); bool IsConnected();
void FireAndForgetQuery(Query query, QueryPriority priority); void FireAndForgetQuery(Query query, QueryPriority priority, QueryAffects affects = {});
void FireAndForgetQueries(Queries queries, QueryPriority priority); void FireAndForgetQueries(Queries queries, QueryPriority priority, QueryAffects affects = {});
Reply GetResultOfQuery(Query query, QueryPriority priority); Reply GetResultOfQuery(Query query, QueryPriority priority, QueryAffects affects = {});
Replies GetResultsOfQueries(Queries queries, QueryPriority priority); Replies GetResultsOfQueries(Queries queries, QueryPriority priority, QueryAffects affects = {});
void EnqueueCallback(const std::function<void(boost::asio::yield_context&)>& callback, QueryPriority priority); void EnqueueCallback(const std::function<void(boost::asio::yield_context&)>& callback, QueryPriority priority);
void Sync(); void Sync();
@ -110,6 +117,21 @@ namespace icinga
return m_PendingQueries; return m_PendingQueries;
} }
inline int GetWrittenConfigFor(RingBuffer::SizeType span, RingBuffer::SizeType tv = Utility::GetTime())
{
return m_WrittenConfig.UpdateAndGetValues(tv, span);
}
inline int GetWrittenStateFor(RingBuffer::SizeType span, RingBuffer::SizeType tv = Utility::GetTime())
{
return m_WrittenState.UpdateAndGetValues(tv, span);
}
inline int GetWrittenHistoryFor(RingBuffer::SizeType span, RingBuffer::SizeType tv = Utility::GetTime())
{
return m_WrittenHistory.UpdateAndGetValues(tv, span);
}
private: private:
/** /**
* What to do with the responses to Redis queries. * What to do with the responses to Redis queries.
@ -146,6 +168,8 @@ namespace icinga
Shared<std::pair<Query, std::promise<Reply>>>::Ptr GetResultOfQuery; Shared<std::pair<Query, std::promise<Reply>>>::Ptr GetResultOfQuery;
Shared<std::pair<Queries, std::promise<Replies>>>::Ptr GetResultsOfQueries; Shared<std::pair<Queries, std::promise<Replies>>>::Ptr GetResultsOfQueries;
std::function<void(boost::asio::yield_context&)> Callback; std::function<void(boost::asio::yield_context&)> Callback;
QueryAffects Affects;
}; };
typedef boost::asio::ip::tcp Tcp; typedef boost::asio::ip::tcp Tcp;
@ -187,6 +211,7 @@ namespace icinga
void IncreasePendingQueries(int count); void IncreasePendingQueries(int count);
void DecreasePendingQueries(int count); void DecreasePendingQueries(int count);
void RecordAffected(QueryAffects affected, double when);
template<class StreamPtr> template<class StreamPtr>
void Handshake(StreamPtr& stream, boost::asio::yield_context& yc); void Handshake(StreamPtr& stream, boost::asio::yield_context& yc);
@ -238,6 +263,9 @@ namespace icinga
// Stats // Stats
RingBuffer m_InputQueries{10}; RingBuffer m_InputQueries{10};
RingBuffer m_OutputQueries{15 * 60}; RingBuffer m_OutputQueries{15 * 60};
RingBuffer m_WrittenConfig{15 * 60};
RingBuffer m_WrittenState{15 * 60};
RingBuffer m_WrittenHistory{15 * 60};
int m_PendingQueries{0}; int m_PendingQueries{0};
boost::asio::deadline_timer m_LogStatsTimer; boost::asio::deadline_timer m_LogStatsTimer;
Ptr m_Parent; Ptr m_Parent;