@@ -877,6 +877,76 @@ PyObject* ActivePyModules::with_unlabled_perf_counters(
877877 return f.get ();
878878}
879879
880+ // Holds a list of label pairs for a counter, [(level, shallow), (pooltype, replicated)]
881+ typedef std::vector<pair<std::string_view, std::string_view>> perf_counter_label_pairs;
882+
883+ PyObject* ActivePyModules::with_perf_counters (
884+ std::function<void (
885+ PerfCounterInstance &counter_instance,
886+ PerfCounterType &counter_type,
887+ PyFormatter& f)> fct,
888+ const std::string& svc_name,
889+ const std::string& svc_id,
890+ std::string_view counter_name,
891+ std::string_view sub_counter_name,
892+ const perf_counter_label_pairs& labels) const
893+ {
894+ PyFormatter f;
895+ /*
896+ The resolved counter path, they are of the format
897+ <counter_name>.<sub_counter_name> If the counter name has labels, then they
898+ are segregated via NULL delimters.
899+
900+ Eg:
901+ - labeled counter:
902+ "osd_scrub_sh_repl^@level^@shallow^@pooltype^@replicated^@.successful_scrubs_elapsed"
903+ - unlabeled counter: "osd.stat_bytes"
904+ */
905+ std::string resolved_path;
906+ Formatter::ArraySection perf_counter_value_section (f, counter_name);
907+
908+ // Construct the resolved path
909+ if (labels.empty ()) {
910+ resolved_path =
911+ std::string (counter_name) + " ." + std::string (sub_counter_name);
912+ } else {
913+ perf_counter_label_pairs perf_counter_labels = labels;
914+ std::string counter_name_with_labels = ceph::perf_counters::detail::create (
915+ counter_name.data (), perf_counter_labels.data (),
916+ perf_counter_labels.data () + perf_counter_labels.size ());
917+ resolved_path = std::string (counter_name_with_labels) + " ." +
918+ std::string (sub_counter_name);
919+ }
920+
921+ {
922+ without_gil_t no_gil;
923+ std::lock_guard l (lock);
924+ auto metadata = daemon_state.get (DaemonKey{svc_name, svc_id});
925+ if (metadata) {
926+ std::lock_guard l2 (metadata->lock );
927+ if (metadata->perf_counters .instances .count (resolved_path)) {
928+ auto counter_instance =
929+ metadata->perf_counters .instances .at (resolved_path);
930+ auto counter_type = metadata->perf_counters .types .at (resolved_path);
931+ with_gil (no_gil, [&] { fct (counter_instance, counter_type, f); });
932+ } else {
933+ dout (4 ) << fmt::format (
934+ " Missing counter: '{}' ({}.{})" , resolved_path, svc_name,
935+ svc_id)
936+ << dendl;
937+ dout (20 ) << " Paths are:" << dendl;
938+ for (const auto & i : metadata->perf_counters .instances ) {
939+ dout (20 ) << i.first << dendl;
940+ }
941+ }
942+ } else {
943+ dout (4 ) << fmt::format (" No daemon state for {}.{}" , svc_name, svc_id)
944+ << dendl;
945+ }
946+ }
947+ return f.get ();
948+ }
949+
880950PyObject* ActivePyModules::get_unlabeled_counter_python (
881951 const std::string &svc_name,
882952 const std::string &svc_id,
@@ -933,6 +1003,32 @@ PyObject* ActivePyModules::get_latest_unlabeled_counter_python(
9331003 return with_unlabled_perf_counters (extract_latest_counters, svc_name, svc_id, path);
9341004}
9351005
1006+ PyObject* ActivePyModules::get_latest_counter_python (
1007+ const std::string& svc_name,
1008+ const std::string& svc_id,
1009+ std::string_view counter_name,
1010+ std::string_view sub_counter_name,
1011+ const perf_counter_label_pairs& labels)
1012+ {
1013+ auto extract_latest_counters = [](PerfCounterInstance& counter_instance,
1014+ PerfCounterType& counter_type,
1015+ PyFormatter& f) {
1016+ if (counter_type.type & PERFCOUNTER_LONGRUNAVG) {
1017+ const auto & datapoint = counter_instance.get_latest_data_avg ();
1018+ f.dump_float (" t" , datapoint.t );
1019+ f.dump_unsigned (" s" , datapoint.s );
1020+ f.dump_unsigned (" c" , datapoint.c );
1021+ } else {
1022+ const auto & datapoint = counter_instance.get_latest_data ();
1023+ f.dump_float (" t" , datapoint.t );
1024+ f.dump_unsigned (" v" , datapoint.v );
1025+ }
1026+ };
1027+ return with_perf_counters (
1028+ extract_latest_counters, svc_name, svc_id, counter_name, sub_counter_name,
1029+ labels);
1030+ }
1031+
9361032PyObject* ActivePyModules::get_unlabeled_perf_schema_python (
9371033 const std::string &svc_type,
9381034 const std::string &svc_id)
@@ -995,9 +1091,6 @@ PyObject* ActivePyModules::get_unlabeled_perf_schema_python(
9951091 return f.get ();
9961092}
9971093
998- // Holds a list of label pairs for a counter, [(level, shallow), (pooltype, replicated)]
999- typedef std::vector<pair<std::string_view, std::string_view>> perf_counter_label_pairs;
1000-
10011094PyObject* ActivePyModules::get_perf_schema_python (
10021095 const std::string& svc_type,
10031096 const std::string& svc_id)
0 commit comments