Skip to content

Commit c38fd4a

Browse files
committed
Provide zones and endpoints (ex local) stats via /v1/status
1 parent b16d96d commit c38fd4a

File tree

4 files changed

+198
-0
lines changed

4 files changed

+198
-0
lines changed

lib/remote/endpoint.cpp

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,12 @@
2222
#include "remote/apilistener.hpp"
2323
#include "remote/jsonrpcconnection.hpp"
2424
#include "remote/zone.hpp"
25+
#include "base/perfdatavalue.hpp"
2526
#include "base/configtype.hpp"
2627
#include "base/utility.hpp"
2728
#include "base/exception.hpp"
2829
#include "base/convert.hpp"
30+
#include "base/statsfunction.hpp"
2931

3032
using namespace icinga;
3133

@@ -34,6 +36,8 @@ REGISTER_TYPE(Endpoint);
3436
boost::signals2::signal<void(const Endpoint::Ptr&, const JsonRpcConnection::Ptr&)> Endpoint::OnConnected;
3537
boost::signals2::signal<void(const Endpoint::Ptr&, const JsonRpcConnection::Ptr&)> Endpoint::OnDisconnected;
3638

39+
REGISTER_STATSFUNCTION(Endpoint, &Endpoint::StatsFunc);
40+
3741
void Endpoint::OnAllConfigLoaded()
3842
{
3943
ObjectImpl<Endpoint>::OnAllConfigLoaded();
@@ -118,6 +122,48 @@ Endpoint::Ptr Endpoint::GetLocalEndpoint()
118122
return listener->GetLocalEndpoint();
119123
}
120124

125+
void Endpoint::StatsFunc(const Dictionary::Ptr& status, const Array::Ptr& perfdata)
126+
{
127+
auto unorderedEndpoints (ConfigType::GetObjectsByType<Endpoint>());
128+
std::set<Endpoint::Ptr> endpoints (unorderedEndpoints.begin(), unorderedEndpoints.end());
129+
Dictionary::Ptr ourStatus = new Dictionary;
130+
131+
unorderedEndpoints.clear();
132+
endpoints.erase(GetLocalEndpoint());
133+
134+
for (auto& endpoint : endpoints) {
135+
ourStatus->Set(endpoint->GetName(), new Dictionary({
136+
{"local_log_position", endpoint->GetLocalLogPosition()},
137+
{"remote_log_position", endpoint->GetRemoteLogPosition()},
138+
{"connecting", endpoint->GetConnecting()},
139+
{"syncing", endpoint->GetSyncing()},
140+
{"connected", endpoint->GetConnected()},
141+
{"last_message_sent", endpoint->GetLastMessageSent()},
142+
{"last_message_received", endpoint->GetLastMessageReceived()},
143+
{"messages_sent_per_second", endpoint->GetMessagesSentPerSecond()},
144+
{"messages_received_per_second", endpoint->GetMessagesReceivedPerSecond()},
145+
{"bytes_sent_per_second", endpoint->GetBytesSentPerSecond()},
146+
{"bytes_received_per_second", endpoint->GetBytesReceivedPerSecond()}
147+
}));
148+
}
149+
150+
{
151+
ObjectLock ourStatusLock (ourStatus);
152+
153+
for (auto& nameEndpointStatus : ourStatus) {
154+
Dictionary::Ptr endpointStatus = nameEndpointStatus.second;
155+
ObjectLock endpointStatusLock (endpointStatus);
156+
auto labelPrefix ("endpoint_" + nameEndpointStatus.first + "_");
157+
158+
for (auto& labelValue : endpointStatus) {
159+
perfdata->Add(new PerfdataValue(labelPrefix + labelValue.first, labelValue.second));
160+
}
161+
}
162+
}
163+
164+
status->Set("endpoint", ourStatus);
165+
}
166+
121167
void Endpoint::AddMessageSent(int bytes)
122168
{
123169
double time = Utility::GetTime();

lib/remote/endpoint.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222

2323
#include "remote/i2-remote.hpp"
2424
#include "remote/endpoint-ti.hpp"
25+
#include "base/array.hpp"
26+
#include "base/dictionary.hpp"
2527
#include "base/ringbuffer.hpp"
2628
#include <set>
2729

@@ -54,6 +56,7 @@ class Endpoint final : public ObjectImpl<Endpoint>
5456
bool GetConnected() const override;
5557

5658
static Endpoint::Ptr GetLocalEndpoint();
59+
static void StatsFunc(const Dictionary::Ptr& status, const Array::Ptr& perfdata);
5760

5861
void SetCachedZone(const intrusive_ptr<Zone>& zone);
5962

lib/remote/zone.cpp

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,18 @@
2020
#include "remote/zone.hpp"
2121
#include "remote/zone-ti.cpp"
2222
#include "remote/jsonrpcconnection.hpp"
23+
#include "base/perfdatavalue.hpp"
2324
#include "base/objectlock.hpp"
2425
#include "base/logger.hpp"
26+
#include "base/statsfunction.hpp"
27+
#include <limits>
2528

2629
using namespace icinga;
2730

2831
REGISTER_TYPE(Zone);
2932

33+
REGISTER_STATSFUNCTION(Zone, &Zone::StatsFunc);
34+
3035
void Zone::OnAllConfigLoaded()
3136
{
3237
ObjectImpl<Zone>::OnAllConfigLoaded();
@@ -147,6 +152,147 @@ Zone::Ptr Zone::GetLocalZone()
147152
return local->GetZone();
148153
}
149154

155+
static std::set<String> l_StatsFuncAggregateSum ({
156+
"messages_sent_per_second", "messages_received_per_second", "bytes_sent_per_second", "bytes_received_per_second"
157+
});
158+
159+
static std::set<String> l_StatsFuncAggregateCount ({
160+
"connecting", "syncing", "connected"
161+
});
162+
163+
static std::set<String> l_StatsFuncAggregateMin ({
164+
"last_message_sent", "last_message_received"
165+
});
166+
167+
void Zone::StatsFunc(const Dictionary::Ptr& status, const Array::Ptr& perfdata)
168+
{
169+
Dictionary::Ptr ourStatus = new Dictionary;
170+
auto localEndpoint (Endpoint::GetLocalEndpoint());
171+
172+
for (auto& zone : ConfigType::GetObjectsByType<Zone>()) {
173+
Dictionary::Ptr endpointStats = new Dictionary({
174+
{"local_log_position", (Array::Ptr)new Array},
175+
{"remote_log_position", (Array::Ptr)new Array},
176+
{"connecting", (Array::Ptr)new Array},
177+
{"syncing", (Array::Ptr)new Array},
178+
{"connected", (Array::Ptr)new Array},
179+
{"last_message_sent", (Array::Ptr)new Array},
180+
{"last_message_received", (Array::Ptr)new Array},
181+
{"messages_sent_per_second", (Array::Ptr)new Array},
182+
{"messages_received_per_second", (Array::Ptr)new Array},
183+
{"bytes_sent_per_second", (Array::Ptr)new Array},
184+
{"bytes_received_per_second", (Array::Ptr)new Array}
185+
});
186+
187+
auto endpoints (zone->GetEndpoints());
188+
189+
endpoints.erase(localEndpoint);
190+
191+
for (auto& endpoint : endpoints) {
192+
((Array::Ptr)endpointStats->Get("local_log_position"))->Add(endpoint->GetLocalLogPosition());
193+
((Array::Ptr)endpointStats->Get("remote_log_position"))->Add(endpoint->GetRemoteLogPosition());
194+
((Array::Ptr)endpointStats->Get("connecting"))->Add(endpoint->GetConnecting());
195+
((Array::Ptr)endpointStats->Get("syncing"))->Add(endpoint->GetSyncing());
196+
((Array::Ptr)endpointStats->Get("connected"))->Add(endpoint->GetConnected());
197+
((Array::Ptr)endpointStats->Get("last_message_sent"))->Add(endpoint->GetLastMessageSent());
198+
((Array::Ptr)endpointStats->Get("last_message_received"))->Add(endpoint->GetLastMessageReceived());
199+
((Array::Ptr)endpointStats->Get("messages_sent_per_second"))->Add(endpoint->GetMessagesSentPerSecond());
200+
((Array::Ptr)endpointStats->Get("messages_received_per_second"))->Add(endpoint->GetMessagesReceivedPerSecond());
201+
((Array::Ptr)endpointStats->Get("bytes_sent_per_second"))->Add(endpoint->GetBytesSentPerSecond());
202+
((Array::Ptr)endpointStats->Get("bytes_received_per_second"))->Add(endpoint->GetBytesReceivedPerSecond());
203+
}
204+
205+
for (auto& label : l_StatsFuncAggregateSum) {
206+
auto sum (0.0);
207+
Array::Ptr values = endpointStats->Get(label);
208+
ObjectLock valuesLock (values);
209+
210+
for (auto& value : values) {
211+
sum += value.Get<double>();
212+
}
213+
214+
endpointStats->Set(label, sum);
215+
}
216+
217+
for (auto& label : l_StatsFuncAggregateCount) {
218+
uintmax_t count = 0;
219+
Array::Ptr values = endpointStats->Get(label);
220+
ObjectLock valuesLock (values);
221+
222+
for (auto& value : values) {
223+
if (value.Get<bool>()) {
224+
++count;
225+
}
226+
}
227+
228+
endpointStats->Set(label, count);
229+
}
230+
231+
for (auto& label : l_StatsFuncAggregateMin) {
232+
auto min (std::numeric_limits<double>::infinity());
233+
auto hasAny (false);
234+
Array::Ptr values = endpointStats->Get(label);
235+
ObjectLock valuesLock (values);
236+
237+
for (auto& value : values) {
238+
auto number (value.Get<double>());
239+
240+
if (number < min) {
241+
min = number;
242+
}
243+
244+
hasAny = true;
245+
}
246+
247+
endpointStats->Set(label, hasAny ? min : 0.0);
248+
}
249+
250+
{
251+
auto maxDiff (-std::numeric_limits<double>::infinity());
252+
Array::Ptr remoteLogPositions = endpointStats->Get("remote_log_position");
253+
ObjectLock remoteLogPositionLock (remoteLogPositions);
254+
auto remoteLogPosition (begin(remoteLogPositions));
255+
auto hasAny (false);
256+
Array::Ptr localLogPositions = endpointStats->Get("local_log_position");
257+
ObjectLock localLogPositionLock (localLogPositions);
258+
259+
for (auto& localLogPosition : localLogPositions) {
260+
auto diff (localLogPosition - *remoteLogPosition);
261+
262+
if (diff > maxDiff) {
263+
maxDiff = diff;
264+
}
265+
266+
hasAny = true;
267+
268+
++remoteLogPosition;
269+
}
270+
271+
endpointStats->Set("client_log_lag", hasAny ? maxDiff : 0.0);
272+
endpointStats->Remove("local_log_position");
273+
endpointStats->Remove("remote_log_position");
274+
}
275+
276+
ourStatus->Set(zone->GetName(), endpointStats);
277+
}
278+
279+
{
280+
ObjectLock ourStatusLock (ourStatus);
281+
282+
for (auto& nameZoneStatus : ourStatus) {
283+
Dictionary::Ptr zoneStatus = nameZoneStatus.second;
284+
ObjectLock zoneStatusLock (zoneStatus);
285+
auto labelPrefix ("zone_" + nameZoneStatus.first + "_");
286+
287+
for (auto& labelValue : zoneStatus) {
288+
perfdata->Add(new PerfdataValue(labelPrefix + labelValue.first, labelValue.second));
289+
}
290+
}
291+
}
292+
293+
status->Set("zone", ourStatus);
294+
}
295+
150296
void Zone::ValidateEndpointsRaw(const Lazy<Array::Ptr>& lvalue, const ValidationUtils& utils)
151297
{
152298
ObjectImpl<Zone>::ValidateEndpointsRaw(lvalue, utils);

lib/remote/zone.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
#ifndef ZONE_H
2121
#define ZONE_H
2222

23+
#include "base/array.hpp"
24+
#include "base/dictionary.hpp"
2325
#include "remote/i2-remote.hpp"
2426
#include "remote/zone-ti.hpp"
2527
#include "remote/endpoint.hpp"
@@ -48,6 +50,7 @@ class Zone final : public ObjectImpl<Zone>
4850
bool IsSingleInstance() const;
4951

5052
static Zone::Ptr GetLocalZone();
53+
static void StatsFunc(const Dictionary::Ptr& status, const Array::Ptr& perfdata);
5154

5255
protected:
5356
void ValidateEndpointsRaw(const Lazy<Array::Ptr>& lvalue, const ValidationUtils& utils) override;

0 commit comments

Comments
 (0)