@@ -112,30 +112,25 @@ void PerfCountersCollectionImpl::dump_formatted_generic(
112112 const std::string &logger,
113113 const std::string &counter) const
114114{
115- f-> open_object_section ( " perfcounter_collection" );
115+ Formatter::ObjectSection collection_section (*f, " perfcounter_collection" sv );
116116
117117 if (dump_labeled == select_labeled_t ::labeled) {
118+ // dump all counters (labeled and unlabeled), using the "labeled format"
119+ std::optional<Formatter::ArraySection> array_section;
118120 std::string prev_key_name;
119121 for (auto l = m_loggers.begin (); l != m_loggers.end (); ++l) {
120122 std::string_view key_name = ceph::perf_counters::key_name ((*l)->get_name ());
121123 if (key_name != prev_key_name) {
122124 // close previous set of counters before dumping new one
123- if (!prev_key_name.empty ()) {
124- f->close_section (); // array section
125- }
125+ array_section.emplace (*f, key_name);
126126 prev_key_name = key_name;
127-
128- f->open_array_section (key_name);
129- (*l)->dump_formatted_generic (f, schema, histograms, select_labeled_t ::labeled, " " );
127+ (*l)->dump_formatted_generic (f, schema, histograms, select_labeled_t ::labeled, " " s);
130128 } else {
131- (*l)->dump_formatted_generic (f, schema, histograms, select_labeled_t ::labeled, " " );
129+ (*l)->dump_formatted_generic (f, schema, histograms, select_labeled_t ::labeled, " " s );
132130 }
133131 }
134- if (!m_loggers.empty ()) {
135- f->close_section (); // final array section
136- }
137132 } else {
138- // unlabeled
133+ // unlabeled (only unlabeled, and using the "unlabeled format")
139134 if (logger.empty ()) {
140135 // dump all loggers
141136 for (auto & l : m_loggers) {
@@ -151,7 +146,6 @@ void PerfCountersCollectionImpl::dump_formatted_generic(
151146 }
152147 }
153148 }
154- f->close_section ();
155149}
156150
157151void PerfCountersCollectionImpl::with_counters (std::function<void (
@@ -381,29 +375,44 @@ void PerfCounters::reset()
381375}
382376
383377
378+ /* Note:
379+ * This function dumps one counter. The dump format depends on
380+ * the dump request. Specifically - if the dump_labeled parameter
381+ * is set - even un-labeled counters are dumped using the "labeled
382+ * counter format".
383+ */
384384void PerfCounters::dump_formatted_generic (Formatter *f, bool schema,
385385 bool histograms, select_labeled_t dump_labeled,
386386 const std::string &counter) const
387387{
388+ // 'labeled_2nd_lvl_section' is only used in the context of dumping
389+ // labeled counters
390+ std::optional<Formatter::ObjectSection> labeled_2nd_lvl_section;
391+
392+ // the 'counters_section' is used for both labeled and unlabeled - but
393+ // have different text in the two cases.
394+ std::optional<Formatter::ObjectSection> counters_section;
395+
388396 if (dump_labeled == select_labeled_t ::labeled) {
389- f->open_object_section (" " ); // should be enclosed by array
390- f->open_object_section (" labels" );
391- for (auto label : ceph::perf_counters::key_labels (m_name)) {
397+ // we are allowed to open an object section here, as - for
398+ // labeled counters format - the caller has opened an array section
399+ labeled_2nd_lvl_section.emplace (*f, " " );
400+ for (Formatter::ObjectSection labels_section{*f, " labels" };
401+ const auto & label : ceph::perf_counters::key_labels (m_name)) {
392402 // don't dump labels with empty label names
393403 if (!label.first .empty ()) {
394- f->dump_string (label.first , label.second );
404+ f->dump_string (label.first , label.second );
395405 }
396406 }
397- f->close_section (); // labels
398- f->open_object_section (" counters" );
407+ counters_section.emplace (*f, " counters" );
399408 } else {
400409 auto labels = ceph::perf_counters::key_labels (m_name);
401410 // do not dump counters when counter instance is labeled and dump_labeled is not set
402411 if (labels.begin () != labels.end ()) {
403412 return ;
404413 }
405414
406- f-> open_object_section (m_name. c_str () );
415+ counters_section. emplace (*f, m_name );
407416 }
408417
409418 for (perf_counter_data_vec_t ::const_iterator d = m_data.begin ();
@@ -420,7 +429,7 @@ void PerfCounters::dump_formatted_generic(Formatter *f, bool schema,
420429 }
421430
422431 if (schema) {
423- f-> open_object_section ( d->name ) ;
432+ Formatter::ObjectSection schedma_section{*f, d->name } ;
424433 // we probably should not have exposed this raw field (with bit
425434 // values), but existing plugins rely on it so we're stuck with
426435 // it.
@@ -465,10 +474,9 @@ void PerfCounters::dump_formatted_generic(Formatter *f, bool schema,
465474 } else if (d->unit == UNIT_BYTES) {
466475 f->dump_string (" units" , " bytes" );
467476 }
468- f->close_section ();
469477 } else {
470478 if (d->type & PERFCOUNTER_LONGRUNAVG) {
471- f-> open_object_section ( d->name ) ;
479+ Formatter::ObjectSection longrunavg_section{*f, d->name } ;
472480 pair<uint64_t ,uint64_t > a = d->read_avg ();
473481 if (d->type & PERFCOUNTER_U64) {
474482 f->dump_unsigned (" avgcount" , a.second );
@@ -491,13 +499,11 @@ void PerfCounters::dump_formatted_generic(Formatter *f, bool schema,
491499 } else {
492500 ceph_abort ();
493501 }
494- f->close_section ();
495502 } else if (d->type & PERFCOUNTER_HISTOGRAM) {
496503 ceph_assert (d->type == (PERFCOUNTER_HISTOGRAM | PERFCOUNTER_COUNTER | PERFCOUNTER_U64));
497504 ceph_assert (d->histogram );
498- f-> open_object_section ( d->name ) ;
505+ Formatter::ObjectSection histogram_section{*f, d->name } ;
499506 d->histogram ->dump_formatted (f);
500- f->close_section ();
501507 } else {
502508 uint64_t v = d->u64 ;
503509 if (d->type & PERFCOUNTER_U64) {
@@ -512,10 +518,6 @@ void PerfCounters::dump_formatted_generic(Formatter *f, bool schema,
512518 }
513519 }
514520 }
515- if (dump_labeled == select_labeled_t ::labeled) {
516- f->close_section (); // counters
517- }
518- f->close_section ();
519521}
520522
521523const std::string &PerfCounters::get_name () const
0 commit comments