1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 #include "MgrStatMonitor.h"
5 #include "mon/OSDMonitor.h"
7 #include "mon/PGMonitor.h"
8 #include "messages/MGetPoolStats.h"
9 #include "messages/MGetPoolStatsReply.h"
10 #include "messages/MMonMgrReport.h"
11 #include "messages/MStatfs.h"
12 #include "messages/MStatfsReply.h"
13 #include "messages/MServiceMap.h"
15 class MgrPGStatService
: public MonPGStatService
{
18 MgrPGStatService(PGMapDigest
& d
) : digest(d
) {}
20 const pool_stat_t
* get_pool_stat(int poolid
) const override
{
21 auto i
= digest
.pg_pool_sum
.find(poolid
);
22 if (i
!= digest
.pg_pool_sum
.end()) {
28 ceph_statfs
get_statfs() const override
{
29 return digest
.get_statfs();
32 void print_summary(Formatter
*f
, ostream
*out
) const override
{
33 digest
.print_summary(f
, out
);
35 void dump_info(Formatter
*f
) const override
{
38 void dump_fs_stats(stringstream
*ss
,
40 bool verbose
) const override
{
41 digest
.dump_fs_stats(ss
, f
, verbose
);
43 void dump_pool_stats(const OSDMap
& osdm
, stringstream
*ss
, Formatter
*f
,
44 bool verbose
) const override
{
45 digest
.dump_pool_stats_full(osdm
, ss
, f
, verbose
);
50 #define dout_subsys ceph_subsys_mon
52 #define dout_prefix _prefix(_dout, mon)
53 static ostream
& _prefix(std::ostream
*_dout
, Monitor
*mon
) {
54 return *_dout
<< "mon." << mon
->name
<< "@" << mon
->rank
55 << "(" << mon
->get_state_name()
59 MgrStatMonitor::MgrStatMonitor(Monitor
*mn
, Paxos
*p
, const string
& service_name
)
60 : PaxosService(mn
, p
, service_name
),
61 pgservice(new MgrPGStatService(digest
))
65 MgrStatMonitor::~MgrStatMonitor() = default;
67 MonPGStatService
*MgrStatMonitor::get_pg_stat_service()
69 return pgservice
.get();
72 void MgrStatMonitor::create_initial()
74 dout(10) << __func__
<< dendl
;
76 service_map
.epoch
= 1;
77 ::encode(service_map
, pending_service_map_bl
, CEPH_FEATURES_ALL
);
80 void MgrStatMonitor::update_from_paxos(bool *need_bootstrap
)
82 version
= get_last_committed();
83 dout(10) << " " << version
<< dendl
;
86 get_version(version
, bl
);
92 ::decode(service_map
, p
);
93 dout(10) << __func__
<< " v" << version
94 << " service_map e" << service_map
.epoch
<< dendl
;
96 catch (buffer::error
& e
) {
97 derr
<< "failed to decode mgrstat state; luminous dev version?" << dendl
;
104 void MgrStatMonitor::update_logger()
106 dout(20) << __func__
<< dendl
;
107 if (mon
->osdmon()->osdmap
.require_osd_release
< CEPH_RELEASE_LUMINOUS
) {
108 dout(20) << "yielding cluster perfcounter updates to pgmon" << dendl
;
112 mon
->cluster_logger
->set(l_cluster_osd_bytes
, digest
.osd_sum
.kb
* 1024ull);
113 mon
->cluster_logger
->set(l_cluster_osd_bytes_used
,
114 digest
.osd_sum
.kb_used
* 1024ull);
115 mon
->cluster_logger
->set(l_cluster_osd_bytes_avail
,
116 digest
.osd_sum
.kb_avail
* 1024ull);
118 mon
->cluster_logger
->set(l_cluster_num_pool
, digest
.pg_pool_sum
.size());
120 for (auto i
: digest
.num_pg_by_pool
) {
123 mon
->cluster_logger
->set(l_cluster_num_pg
, num_pg
);
125 unsigned active
= 0, active_clean
= 0, peering
= 0;
126 for (auto p
= digest
.num_pg_by_state
.begin();
127 p
!= digest
.num_pg_by_state
.end();
129 if (p
->first
& PG_STATE_ACTIVE
) {
131 if (p
->first
& PG_STATE_CLEAN
)
132 active_clean
+= p
->second
;
134 if (p
->first
& PG_STATE_PEERING
)
135 peering
+= p
->second
;
137 mon
->cluster_logger
->set(l_cluster_num_pg_active_clean
, active_clean
);
138 mon
->cluster_logger
->set(l_cluster_num_pg_active
, active
);
139 mon
->cluster_logger
->set(l_cluster_num_pg_peering
, peering
);
141 mon
->cluster_logger
->set(l_cluster_num_object
, digest
.pg_sum
.stats
.sum
.num_objects
);
142 mon
->cluster_logger
->set(l_cluster_num_object_degraded
, digest
.pg_sum
.stats
.sum
.num_objects_degraded
);
143 mon
->cluster_logger
->set(l_cluster_num_object_misplaced
, digest
.pg_sum
.stats
.sum
.num_objects_misplaced
);
144 mon
->cluster_logger
->set(l_cluster_num_object_unfound
, digest
.pg_sum
.stats
.sum
.num_objects_unfound
);
145 mon
->cluster_logger
->set(l_cluster_num_bytes
, digest
.pg_sum
.stats
.sum
.num_bytes
);
149 void MgrStatMonitor::create_pending()
151 dout(10) << " " << version
<< dendl
;
152 pending_digest
= digest
;
153 pending_health_checks
= get_health_checks();
154 pending_service_map_bl
.clear();
155 ::encode(service_map
, pending_service_map_bl
, mon
->get_quorum_con_features());
158 void MgrStatMonitor::encode_pending(MonitorDBStore::TransactionRef t
)
161 if (version
< mon
->pgmon()->get_last_committed()) {
162 // fast-forward to pgmon version to ensure clients don't see a
163 // jump back in time for MGetPoolStats and MStatFs.
164 version
= mon
->pgmon()->get_last_committed() + 1;
166 dout(10) << " " << version
<< dendl
;
168 ::encode(pending_digest
, bl
, mon
->get_quorum_con_features());
169 assert(pending_service_map_bl
.length());
170 bl
.append(pending_service_map_bl
);
171 put_version(t
, version
, bl
);
172 put_last_committed(t
, version
);
174 encode_health(pending_health_checks
, t
);
177 version_t
MgrStatMonitor::get_trim_to()
179 // we don't actually need *any* old states, but keep a few.
186 void MgrStatMonitor::on_active()
191 void MgrStatMonitor::get_health(list
<pair
<health_status_t
,string
> >& summary
,
192 list
<pair
<health_status_t
,string
> > *detail
,
193 CephContext
*cct
) const
197 void MgrStatMonitor::tick()
201 void MgrStatMonitor::print_summary(Formatter
*f
, std::ostream
*ss
) const
203 pgservice
->print_summary(f
, ss
);
206 bool MgrStatMonitor::preprocess_query(MonOpRequestRef op
)
208 auto m
= static_cast<PaxosServiceMessage
*>(op
->get_req());
209 switch (m
->get_type()) {
210 case CEPH_MSG_STATFS
:
211 return preprocess_statfs(op
);
212 case MSG_MON_MGR_REPORT
:
213 return preprocess_report(op
);
214 case MSG_GETPOOLSTATS
:
215 return preprocess_getpoolstats(op
);
218 derr
<< "Unhandled message type " << m
->get_type() << dendl
;
223 bool MgrStatMonitor::prepare_update(MonOpRequestRef op
)
225 auto m
= static_cast<PaxosServiceMessage
*>(op
->get_req());
226 switch (m
->get_type()) {
227 case MSG_MON_MGR_REPORT
:
228 return prepare_report(op
);
231 derr
<< "Unhandled message type " << m
->get_type() << dendl
;
236 bool MgrStatMonitor::preprocess_report(MonOpRequestRef op
)
241 bool MgrStatMonitor::prepare_report(MonOpRequestRef op
)
243 auto m
= static_cast<MMonMgrReport
*>(op
->get_req());
244 bufferlist bl
= m
->get_data();
246 ::decode(pending_digest
, p
);
247 pending_health_checks
.swap(m
->health_checks
);
248 if (m
->service_map_bl
.length()) {
249 pending_service_map_bl
.swap(m
->service_map_bl
);
251 dout(10) << __func__
<< " " << pending_digest
<< ", "
252 << pending_health_checks
.checks
.size() << " health checks" << dendl
;
256 bool MgrStatMonitor::preprocess_getpoolstats(MonOpRequestRef op
)
258 op
->mark_pgmon_event(__func__
);
259 auto m
= static_cast<MGetPoolStats
*>(op
->get_req());
260 auto session
= m
->get_session();
263 if (!session
->is_capable("pg", MON_CAP_R
)) {
264 dout(0) << "MGetPoolStats received from entity with insufficient caps "
265 << session
->caps
<< dendl
;
268 if (m
->fsid
!= mon
->monmap
->fsid
) {
269 dout(0) << __func__
<< " on fsid "
270 << m
->fsid
<< " != " << mon
->monmap
->fsid
<< dendl
;
274 if (mon
->pgservice
== get_pg_stat_service()) {
275 ver
= get_last_committed();
277 ver
= mon
->pgmon()->get_last_committed();
279 auto reply
= new MGetPoolStatsReply(m
->fsid
, m
->get_tid(), ver
);
280 for (const auto& pool_name
: m
->pools
) {
281 const auto pool_id
= mon
->osdmon()->osdmap
.lookup_pg_pool_name(pool_name
);
282 if (pool_id
== -ENOENT
)
284 auto pool_stat
= mon
->pgservice
->get_pool_stat(pool_id
);
287 reply
->pool_stats
[pool_name
] = *pool_stat
;
289 mon
->send_reply(op
, reply
);
293 bool MgrStatMonitor::preprocess_statfs(MonOpRequestRef op
)
295 op
->mark_pgmon_event(__func__
);
296 auto statfs
= static_cast<MStatfs
*>(op
->get_req());
297 auto session
= statfs
->get_session();
300 if (!session
->is_capable("pg", MON_CAP_R
)) {
301 dout(0) << "MStatfs received from entity with insufficient privileges "
302 << session
->caps
<< dendl
;
305 if (statfs
->fsid
!= mon
->monmap
->fsid
) {
306 dout(0) << __func__
<< " on fsid " << statfs
->fsid
307 << " != " << mon
->monmap
->fsid
<< dendl
;
310 dout(10) << __func__
<< " " << *statfs
311 << " from " << statfs
->get_orig_source() << dendl
;
313 if (mon
->pgservice
== get_pg_stat_service()) {
314 ver
= get_last_committed();
316 ver
= mon
->pgmon()->get_last_committed();
318 auto reply
= new MStatfsReply(statfs
->fsid
, statfs
->get_tid(), ver
);
319 reply
->h
.st
= mon
->pgservice
->get_statfs();
320 mon
->send_reply(op
, reply
);
324 void MgrStatMonitor::check_sub(Subscription
*sub
)
326 const auto epoch
= mon
->monmap
->get_epoch();
328 << " next " << sub
->next
329 << " have " << epoch
<< dendl
;
330 if (sub
->next
<= service_map
.epoch
) {
331 auto m
= new MServiceMap(service_map
);
332 sub
->session
->con
->send_message(m
);
334 mon
->with_session_map([this, sub
](MonSessionMap
& session_map
) {
335 session_map
.remove_sub(sub
);
338 sub
->next
= epoch
+ 1;
343 void MgrStatMonitor::check_subs()
345 dout(10) << __func__
<< dendl
;
346 if (!service_map
.epoch
) {
349 auto subs
= mon
->session_map
.subs
.find("servicemap");
350 if (subs
== mon
->session_map
.subs
.end()) {
353 auto p
= subs
->second
->begin();