// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- // vim: ts=8 sw=2 smarttab #include "common/debug.h" #include "common/errno.h" #include "mgr/MetricCollector.h" #include "mgr/OSDPerfMetricTypes.h" #include "mgr/MDSPerfMetricTypes.h" #define dout_context g_ceph_context #define dout_subsys ceph_subsys_mgr #undef dout_prefix #define dout_prefix *_dout << "mgr.metric_collector " << __func__ << ": " template MetricCollector::MetricCollector(MetricListener &listener) : listener(listener) { } template MetricQueryID MetricCollector::add_query( const Query &query, const std::optional &limit) { dout(20) << "query=" << query << ", limit=" << limit << dendl; uint64_t query_id; bool notify = false; { std::lock_guard locker(lock); query_id = next_query_id++; auto it = queries.find(query); if (it == queries.end()) { it = queries.emplace(query, std::map{}).first; notify = true; } else if (is_limited(it->second)) { notify = true; } it->second.emplace(query_id, limit); counters.emplace(query_id, std::map{}); } dout(10) << query << " " << (limit ? stringify(*limit) : "unlimited") << " query_id=" << query_id << dendl; if (notify) { listener.handle_query_updated(); } return query_id; } template int MetricCollector::remove_query(MetricQueryID query_id) { dout(20) << "query_id=" << query_id << dendl; bool found = false; bool notify = false; { std::lock_guard locker(lock); for (auto it = queries.begin() ; it != queries.end();) { auto iter = it->second.find(query_id); if (iter == it->second.end()) { ++it; continue; } it->second.erase(iter); if (it->second.empty()) { it = queries.erase(it); notify = true; } else if (is_limited(it->second)) { ++it; notify = true; } found = true; break; } counters.erase(query_id); } if (!found) { dout(10) << query_id << " not found" << dendl; return -ENOENT; } dout(10) << query_id << dendl; if (notify) { listener.handle_query_updated(); } return 0; } template void MetricCollector::remove_all_queries() { dout(20) << dendl; bool notify; { std::lock_guard locker(lock); notify = !queries.empty(); queries.clear(); } if (notify) { listener.handle_query_updated(); } } template void MetricCollector::reregister_queries() { dout(20) << dendl; listener.handle_query_updated(); } template int MetricCollector::get_counters_generic( MetricQueryID query_id, std::map *c) { dout(20) << dendl; ceph_assert(ceph_mutex_is_locked(lock)); auto it = counters.find(query_id); if (it == counters.end()) { dout(10) << "counters for " << query_id << " not found" << dendl; return -ENOENT; } *c = std::move(it->second); it->second.clear(); return 0; } template void MetricCollector::process_reports_generic( const std::map &reports, UpdateCallback callback) { ceph_assert(ceph_mutex_is_locked(lock)); if (reports.empty()) { return; } for (auto& [query, report] : reports) { dout(10) << "report for " << query << " query: " << report.group_packed_performance_counters.size() << " records" << dendl; for (auto& [key, bl] : report.group_packed_performance_counters) { auto bl_it = bl.cbegin(); for (auto& p : queries[query]) { auto &key_counters = counters[p.first][key]; if (key_counters.empty()) { key_counters.resize(query.performance_counter_descriptors.size(), {0, 0}); } } auto desc_it = report.performance_counter_descriptors.begin(); for (size_t i = 0; i < query.performance_counter_descriptors.size(); i++) { if (desc_it == report.performance_counter_descriptors.end()) { break; } if (*desc_it != query.performance_counter_descriptors[i]) { continue; } PerformanceCounter c; desc_it->unpack_counter(bl_it, &c); dout(20) << "counter " << key << " " << *desc_it << ": " << c << dendl; for (auto& p : queries[query]) { auto &key_counters = counters[p.first][key]; callback(&key_counters[i], c); } desc_it++; } } } } template class MetricCollector; template class MetricCollector;