22
22
#include " base/function.hpp"
23
23
#include " base/objectlock.hpp"
24
24
#include " base/scriptglobal.hpp"
25
- #include " base/utility.hpp"
26
25
#include " base/value.hpp"
27
26
#include " remote/apifunction.hpp"
28
27
#include " remote/endpoint.hpp"
29
28
#include " remote/messageorigin.hpp"
30
29
#include " remote/statsreporter.hpp"
31
30
#include " remote/zone.hpp"
32
31
#include < boost/bind.hpp>
32
+ #include < boost/thread/mutex.hpp>
33
33
#include < atomic>
34
+ #include < set>
34
35
35
36
using namespace icinga ;
36
37
@@ -56,20 +57,40 @@ void StatsReporter::OnConnected(const Endpoint::Ptr& endpoint)
56
57
57
58
void StatsReporter::ReportStats ()
58
59
{
59
- Dictionary::Ptr stats ;
60
+ Dictionary::Ptr message ;
60
61
61
62
for (auto & zone : Zone::GetLocalZone ()->GetAllParents ()) {
62
63
for (auto & endpoint : zone->GetEndpoints ()) {
63
64
for (auto & client : endpoint->GetClients ()) {
64
- if (!stats ) {
65
- stats = GenerateStats () ;
65
+ if (!message ) {
66
+ Dictionary:: Ptr allStats = new Dictionary ;
66
67
67
- if (!stats) {
68
- return ;
68
+ auto stats (GenerateStats ());
69
+
70
+ if (stats)
71
+ allStats->Set (Endpoint::GetLocalEndpoint ()->GetName (), stats);
72
+
73
+ {
74
+ boost::mutex::scoped_lock lock (m_Mutex);
75
+
76
+ for (auto & endpointStats : m_SecondaryStats) {
77
+ allStats->Set (endpointStats.first , endpointStats.second );
78
+ }
69
79
}
80
+
81
+ if (!allStats->GetLength ())
82
+ return ;
83
+
84
+ message = new Dictionary ({
85
+ { " jsonrpc" , " 2.0" },
86
+ { " method" , " event::ClusterStats" },
87
+ { " params" , new Dictionary ({
88
+ { " stats" , allStats }
89
+ }) }
90
+ });
70
91
}
71
92
72
- client->SendMessage (stats );
93
+ client->SendMessage (message );
73
94
74
95
break ;
75
96
}
@@ -93,21 +114,50 @@ Dictionary::Ptr StatsReporter::GenerateStats()
93
114
}
94
115
}
95
116
96
- return new Dictionary ({
97
- { " jsonrpc" , " 2.0" },
98
- { " method" , " event::ClusterStats" },
99
- { " params" , new Dictionary ({
100
- { " ctime" , Utility::GetTime () },
101
- { " stats" , status }
102
- }) }
103
- });
117
+ return status;
104
118
}
105
119
106
120
return nullptr ;
107
121
}
108
122
109
123
Value StatsReporter::ClusterStatsAPIHandler (const MessageOrigin::Ptr & origin, const Dictionary::Ptr & params)
110
124
{
111
- // TODO
125
+ auto endpoint (origin->FromClient ->GetEndpoint ());
126
+
127
+ if (endpoint && endpoint->GetZone ()->IsChildOf (Zone::GetLocalZone ())) {
128
+ auto rawStats (params->Get (" stats" ));
129
+
130
+ if (rawStats.IsObject ()) {
131
+ Dictionary::Ptr allStats (rawStats);
132
+
133
+ if (allStats) {
134
+ // For security reasons
135
+ std::set<String> neighborhood;
136
+
137
+ for (auto & endpoint : Zone::GetLocalZone ()->GetEndpoints ()) {
138
+ neighborhood.emplace (endpoint->GetName ());
139
+ }
140
+
141
+ ObjectLock lock (allStats);
142
+
143
+ for (auto & endpointStats : allStats) {
144
+ if (endpointStats.second .IsObject ()) {
145
+ Dictionary::Ptr stats (endpointStats.second );
146
+
147
+ if (stats && neighborhood.find (endpointStats.first ) == neighborhood.end ()) {
148
+ m_Instance.ClusterStatsHandler (endpointStats.first , endpointStats.second );
149
+ }
150
+ }
151
+ }
152
+ }
153
+ }
154
+ }
155
+
112
156
return Empty;
113
157
}
158
+
159
+ void StatsReporter::ClusterStatsHandler (const String& endpoint, const Dictionary::Ptr & stats)
160
+ {
161
+ boost::mutex::scoped_lock lock (m_Mutex);
162
+ m_SecondaryStats[endpoint] = stats;
163
+ }
0 commit comments