diff options
author | Ali Maredia <amaredia@redhat.com> | 2022-07-19 23:39:02 +0200 |
---|---|---|
committer | Ali Maredia <amaredia@redhat.com> | 2023-02-23 18:05:36 +0100 |
commit | 56e2a1006f975829c0f00db31c745f32da24676b (patch) | |
tree | 8198d3223ed815fabd76f708d5ed64bb29c13a6b /src/test | |
parent | common: add abstraction for label-aware perf counter keys (diff) | |
download | ceph-56e2a1006f975829c0f00db31c745f32da24676b.tar.xz ceph-56e2a1006f975829c0f00db31c745f32da24676b.zip |
common: Add labeled perf counters
Add the ability to dump labeled perf counters
for a daemon. Labeled perf counters are stored
in a CephContext's PerfCountersCollection.
Labeled and unlabeled perf counters are dumped
to the admin socket via `counters dump` command.
The schema for labeled and unlabeled perf
counters are dumped to the admin socket via
`counters schema` command.
This commit includes docs and additional unit tests
Signed-off-by: Ali Maredia <amaredia@redhat.com>
Diffstat (limited to 'src/test')
-rw-r--r-- | src/test/fio/fio_ceph_messenger.cc | 2 | ||||
-rw-r--r-- | src/test/fio/fio_ceph_objectstore.cc | 2 | ||||
-rw-r--r-- | src/test/perf_counters.cc | 368 |
3 files changed, 370 insertions, 2 deletions
diff --git a/src/test/fio/fio_ceph_messenger.cc b/src/test/fio/fio_ceph_messenger.cc index 8c962af5df7..2e18c7c6330 100644 --- a/src/test/fio/fio_ceph_messenger.cc +++ b/src/test/fio/fio_ceph_messenger.cc @@ -132,7 +132,7 @@ static void put_ceph_context(void) Formatter* f; f = Formatter::create("json-pretty"); - g_ceph_context->get_perfcounters_collection()->dump_formatted(f, false); + g_ceph_context->get_perfcounters_collection()->dump_formatted(f, false, false); ostr << ">>>>>>>>>>>>> PERFCOUNTERS BEGIN <<<<<<<<<<<<" << std::endl; f->flush(ostr); ostr << ">>>>>>>>>>>>> PERFCOUNTERS END <<<<<<<<<<<<" << std::endl; diff --git a/src/test/fio/fio_ceph_objectstore.cc b/src/test/fio/fio_ceph_objectstore.cc index fe9c793ab12..ade043f0cd1 100644 --- a/src/test/fio/fio_ceph_objectstore.cc +++ b/src/test/fio/fio_ceph_objectstore.cc @@ -338,7 +338,7 @@ struct Engine { Formatter* f = Formatter::create( "json-pretty", "json-pretty", "json-pretty"); f->open_object_section("perf_output"); - cct->get_perfcounters_collection()->dump_formatted(f, false); + cct->get_perfcounters_collection()->dump_formatted(f, false, false); if (g_conf()->rocksdb_perf) { f->open_object_section("rocksdb_perf"); os->get_db_statistics(f); diff --git a/src/test/perf_counters.cc b/src/test/perf_counters.cc index a4dfe48d1e7..31b10fff167 100644 --- a/src/test/perf_counters.cc +++ b/src/test/perf_counters.cc @@ -16,6 +16,7 @@ // now, this include has to come before the others. +#include "common/perf_counters_key.h" #include "common/perf_counters_collection.h" #include "common/admin_socket_client.h" #include "common/ceph_context.h" @@ -182,6 +183,7 @@ TEST(PerfCounters, MultiplePerfCounters) { "{\"avgcount\":0,\"sum\":0.000000000,\"avgtime\":0.000000000}},\"test_perfcounter_2\":{\"foo\":0,\"bar\":0.000000000}}"), msg); coll->remove(fake_pf2); + delete fake_pf2; ASSERT_EQ("", client.do_request("{ \"prefix\": \"perf dump\", \"format\": \"json\" }", &msg)); ASSERT_EQ(sd("{\"test_perfcounter_1\":{\"element1\":13,\"element2\":0.000000000," "\"element3\":{\"avgcount\":0,\"sum\":0.000000000,\"avgtime\":0.000000000}}}"), msg); @@ -255,3 +257,369 @@ TEST(PerfCounters, read_avg) { t2.join(); t1.join(); } + +static PerfCounters* setup_test_perfcounter4(std::string name, CephContext *cct) +{ + PerfCountersBuilder bld(cct, name, + TEST_PERFCOUNTERS2_ELEMENT_FIRST, TEST_PERFCOUNTERS2_ELEMENT_LAST); + bld.add_u64(TEST_PERFCOUNTERS2_ELEMENT_FOO, "foo"); + bld.add_time(TEST_PERFCOUNTERS2_ELEMENT_BAR, "bar"); + + PerfCounters* counters = bld.create_perf_counters(); + cct->get_perfcounters_collection()->add(counters); + return counters; +} + +TEST(PerfCounters, TestLabeledCountersOnly) { + constexpr std::string_view empty_dump_format_raw = R"({} +)"; + std::string counter_key1 = ceph::perf_counters::key_create("name1", {{"label1", "val1"}}); + std::string counter_key2 = ceph::perf_counters::key_create("name2", {{"label2", "val2"}}); + + PerfCounters* counters1 = setup_test_perfcounter4(counter_key1, g_ceph_context); + PerfCounters* counters2 = setup_test_perfcounter4(counter_key2, g_ceph_context); + + counters1->inc(TEST_PERFCOUNTERS2_ELEMENT_FOO, 3); + counters1->dec(TEST_PERFCOUNTERS2_ELEMENT_FOO, 1); + counters2->set(TEST_PERFCOUNTERS2_ELEMENT_FOO, 4); + + AdminSocketClient client(get_rand_socket_path()); + std::string message; + ASSERT_EQ("", client.do_request(R"({ "prefix": "counter dump", "format": "raw" })", &message)); + ASSERT_EQ(R"({ + "name1": { + "labels": { + "label1": "val1" + }, + "counters": { + "foo": 2, + "bar": 0.000000000 + } + }, + "name2": { + "labels": { + "label2": "val2" + }, + "counters": { + "foo": 4, + "bar": 0.000000000 + } + } +} +)", message); + + // make sure labeled counters are not in normal perf dump + ASSERT_EQ("", client.do_request(R"({ "prefix": "perf dump", "format": "raw" })", &message)); + ASSERT_EQ(empty_dump_format_raw, message); + + ASSERT_EQ("", client.do_request(R"({ "prefix": "counter schema", "format": "raw" })", &message)); + ASSERT_EQ(R"({ + "name1": { + "labels": { + "label1": "val1" + }, + "counters": { + "foo": { + "type": 2, + "metric_type": "gauge", + "value_type": "integer", + "description": "", + "nick": "", + "priority": 0, + "units": "none" + }, + "bar": { + "type": 1, + "metric_type": "gauge", + "value_type": "real", + "description": "", + "nick": "", + "priority": 0, + "units": "none" + } + } + }, + "name2": { + "labels": { + "label2": "val2" + }, + "counters": { + "foo": { + "type": 2, + "metric_type": "gauge", + "value_type": "integer", + "description": "", + "nick": "", + "priority": 0, + "units": "none" + }, + "bar": { + "type": 1, + "metric_type": "gauge", + "value_type": "real", + "description": "", + "nick": "", + "priority": 0, + "units": "none" + } + } + } +} +)", message); + + // make sure labeled counters are not in normal perf schema + ASSERT_EQ("", client.do_request(R"({ "prefix": "perf schema", "format": "raw" })", &message)); + ASSERT_EQ(empty_dump_format_raw, message); + + g_ceph_context->get_perfcounters_collection()->clear(); +} + +TEST(PerfCounters, TestLabelStrings) { + AdminSocketClient client(get_rand_socket_path()); + std::string message; + + // test empty val in a label pair will get the label pair added but empty key will not + std::string counter_key1 = ceph::perf_counters::key_create("good_ctrs", {{"label3", "val4"}, {"label1", ""}}); + PerfCounters* counters1 = setup_test_perfcounter4(counter_key1, g_ceph_context); + + std::string counter_key2 = ceph::perf_counters::key_create("bad_ctrs", {{"", "val4"}, {"label1", "val1"}}); + PerfCounters* counters2 = setup_test_perfcounter4(counter_key2, g_ceph_context); + + counters1->set(TEST_PERFCOUNTERS2_ELEMENT_FOO, 2); + counters2->set(TEST_PERFCOUNTERS2_ELEMENT_FOO, 4); + + // test empty keys in each of the label pairs will get only the labels section added + std::string counter_key3 = ceph::perf_counters::key_create("bad_ctrs2", {{"", "val2"}, {"", "val33"}}); + PerfCounters* counters3 = setup_test_perfcounter4(counter_key3, g_ceph_context); + counters3->set(TEST_PERFCOUNTERS2_ELEMENT_FOO, 6); + + // a key with a somehow odd number of entries after the the key name will omit final unfinished label pair + std::string counter_key4 = "too_many_delimiters"; + counter_key4 += '\0'; + counter_key4 += "label1"; + counter_key4 += '\0'; + counter_key4 += "val1"; + counter_key4 += '\0'; + counter_key4 += "label2"; + counter_key4 += '\0'; + PerfCounters* counters4 = setup_test_perfcounter4(counter_key4, g_ceph_context); + counters4->set(TEST_PERFCOUNTERS2_ELEMENT_FOO, 8); + + // test unlabeled perf counters are in the counter dump with labels and counters sections + std::string counter_key5 = "only_key"; + PerfCounters* no_label_counters = setup_test_perfcounter4(counter_key5, g_ceph_context); + no_label_counters->set(TEST_PERFCOUNTERS2_ELEMENT_FOO, 4); + + ASSERT_EQ("", client.do_request(R"({ "prefix": "counter dump", "format": "raw" })", &message)); + ASSERT_EQ(R"({ + "bad_ctrs": { + "labels": { + "label1": "val1" + }, + "counters": { + "foo": 4, + "bar": 0.000000000 + } + }, + "bad_ctrs2": { + "labels": {}, + "counters": { + "foo": 6, + "bar": 0.000000000 + } + }, + "good_ctrs": { + "labels": { + "label1": "", + "label3": "val4" + }, + "counters": { + "foo": 2, + "bar": 0.000000000 + } + }, + "only_key": { + "labels": {}, + "counters": { + "foo": 4, + "bar": 0.000000000 + } + }, + "too_many_delimiters": { + "labels": { + "label1": "val1" + }, + "counters": { + "foo": 8, + "bar": 0.000000000 + } + } +} +)", message); + + // test unlabeled perf counters are in the schema dump with labels and counters sections + ASSERT_EQ("", client.do_request(R"({ "prefix": "counter schema", "format": "raw" })", &message)); + ASSERT_EQ(R"({ + "bad_ctrs": { + "labels": { + "label1": "val1" + }, + "counters": { + "foo": { + "type": 2, + "metric_type": "gauge", + "value_type": "integer", + "description": "", + "nick": "", + "priority": 0, + "units": "none" + }, + "bar": { + "type": 1, + "metric_type": "gauge", + "value_type": "real", + "description": "", + "nick": "", + "priority": 0, + "units": "none" + } + } + }, + "bad_ctrs2": { + "labels": {}, + "counters": { + "foo": { + "type": 2, + "metric_type": "gauge", + "value_type": "integer", + "description": "", + "nick": "", + "priority": 0, + "units": "none" + }, + "bar": { + "type": 1, + "metric_type": "gauge", + "value_type": "real", + "description": "", + "nick": "", + "priority": 0, + "units": "none" + } + } + }, + "good_ctrs": { + "labels": { + "label1": "", + "label3": "val4" + }, + "counters": { + "foo": { + "type": 2, + "metric_type": "gauge", + "value_type": "integer", + "description": "", + "nick": "", + "priority": 0, + "units": "none" + }, + "bar": { + "type": 1, + "metric_type": "gauge", + "value_type": "real", + "description": "", + "nick": "", + "priority": 0, + "units": "none" + } + } + }, + "only_key": { + "labels": {}, + "counters": { + "foo": { + "type": 2, + "metric_type": "gauge", + "value_type": "integer", + "description": "", + "nick": "", + "priority": 0, + "units": "none" + }, + "bar": { + "type": 1, + "metric_type": "gauge", + "value_type": "real", + "description": "", + "nick": "", + "priority": 0, + "units": "none" + } + } + }, + "too_many_delimiters": { + "labels": { + "label1": "val1" + }, + "counters": { + "foo": { + "type": 2, + "metric_type": "gauge", + "value_type": "integer", + "description": "", + "nick": "", + "priority": 0, + "units": "none" + }, + "bar": { + "type": 1, + "metric_type": "gauge", + "value_type": "real", + "description": "", + "nick": "", + "priority": 0, + "units": "none" + } + } + } +} +)", message); + + // test unlabeled perf counters are in the perf dump without the labels and counters section + ASSERT_EQ("", client.do_request(R"({ "prefix": "perf dump", "format": "raw" })", &message)); + ASSERT_EQ(R"({ + "only_key": { + "foo": 4, + "bar": 0.000000000 + } +} +)", message); + + // test unlabeled perf counters are in the perf schema without the labels and counters section + ASSERT_EQ("", client.do_request(R"({ "prefix": "perf schema", "format": "raw" })", &message)); + ASSERT_EQ(R"({ + "only_key": { + "foo": { + "type": 2, + "metric_type": "gauge", + "value_type": "integer", + "description": "", + "nick": "", + "priority": 0, + "units": "none" + }, + "bar": { + "type": 1, + "metric_type": "gauge", + "value_type": "real", + "description": "", + "nick": "", + "priority": 0, + "units": "none" + } + } +} +)", message); + + g_ceph_context->get_perfcounters_collection()->clear(); +} |