From 5a7e3a6d49563bf10da98e3f760e41cf46883b92 Mon Sep 17 00:00:00 2001 From: Yingxin Cheng Date: Fri, 24 May 2024 14:20:49 +0800 Subject: [PATCH] crimson/os/seastore: implement disk and writer level stats reporting At SeaStore level, to understand the device balances: * IOPS * per-writer depth * bandwidth * IO size Picking a particular SeaStore shard, to understand: * Per device tier write status * Per writer status in a device tier * Per transaction type status * How each type of transactions write through the writers Signed-off-by: Yingxin Cheng (cherry picked from commit 8f67346015f0917cf56f0534fc316af8560921de) --- src/crimson/os/futurized_store.h | 2 + .../os/seastore/extent_placement_manager.cc | 150 ++++++++++++++++++ .../os/seastore/extent_placement_manager.h | 52 +++++- src/crimson/os/seastore/journal.h | 3 + .../journal/circular_bounded_journal.h | 4 + .../os/seastore/journal/record_submitter.cc | 9 ++ .../os/seastore/journal/record_submitter.h | 4 + .../os/seastore/journal/segmented_journal.h | 4 + src/crimson/os/seastore/seastore.cc | 68 ++++++++ src/crimson/os/seastore/seastore.h | 15 +- src/crimson/os/seastore/seastore_types.cc | 42 +++++ src/crimson/os/seastore/seastore_types.h | 111 ++++++++++++- src/crimson/os/seastore/transaction_manager.h | 5 + src/crimson/osd/osd.cc | 3 + 14 files changed, 466 insertions(+), 6 deletions(-) diff --git a/src/crimson/os/futurized_store.h b/src/crimson/os/futurized_store.h index 95d0d9b2d29..fe09cc54510 100644 --- a/src/crimson/os/futurized_store.h +++ b/src/crimson/os/futurized_store.h @@ -186,6 +186,8 @@ public: virtual seastar::future pool_statfs(int64_t pool_id) const = 0; + virtual seastar::future<> report_stats() { return seastar::now(); } + virtual uuid_d get_fsid() const = 0; virtual seastar::future<> write_meta(const std::string& key, diff --git a/src/crimson/os/seastore/extent_placement_manager.cc b/src/crimson/os/seastore/extent_placement_manager.cc index 9b01e24c8a8..9b814555b45 100644 --- a/src/crimson/os/seastore/extent_placement_manager.cc +++ b/src/crimson/os/seastore/extent_placement_manager.cc @@ -270,6 +270,156 @@ void ExtentPlacementManager::set_primary_device(Device *device) ceph_assert(devices_by_id[device->get_device_id()] == device); } +device_stats_t +ExtentPlacementManager::get_device_stats( + const writer_stats_t &journal_stats, + bool report_detail) const +{ + LOG_PREFIX(ExtentPlacementManager::get_device_stats); + + /* + * RecordSubmitter::get_stats() isn't reentrant. + * And refer to EPM::init() for the writers. + */ + + writer_stats_t main_stats = journal_stats; + std::vector main_writer_stats; + using enum data_category_t; + if (get_main_backend_type() == backend_type_t::SEGMENTED) { + // 0. oolmdat + main_writer_stats.emplace_back( + get_writer(METADATA, OOL_GENERATION)->get_stats()); + main_stats.add(main_writer_stats.back()); + // 1. ooldata + main_writer_stats.emplace_back( + get_writer(DATA, OOL_GENERATION)->get_stats()); + main_stats.add(main_writer_stats.back()); + // 2. mainmdat + main_writer_stats.emplace_back(); + for (rewrite_gen_t gen = MIN_REWRITE_GENERATION; gen < MIN_COLD_GENERATION; ++gen) { + const auto &writer = get_writer(METADATA, gen); + ceph_assert(writer->get_type() == backend_type_t::SEGMENTED); + main_writer_stats.back().add(writer->get_stats()); + } + main_stats.add(main_writer_stats.back()); + // 3. maindata + main_writer_stats.emplace_back(); + for (rewrite_gen_t gen = MIN_REWRITE_GENERATION; gen < MIN_COLD_GENERATION; ++gen) { + const auto &writer = get_writer(DATA, gen); + ceph_assert(writer->get_type() == backend_type_t::SEGMENTED); + main_writer_stats.back().add(writer->get_stats()); + } + main_stats.add(main_writer_stats.back()); + } else { // RBM + // TODO stats from RandomBlockOolWriter + } + + writer_stats_t cold_stats = {}; + std::vector cold_writer_stats; + bool has_cold_tier = background_process.has_cold_tier(); + if (has_cold_tier) { + // 0. coldmdat + cold_writer_stats.emplace_back(); + for (rewrite_gen_t gen = MIN_COLD_GENERATION; gen < REWRITE_GENERATIONS; ++gen) { + const auto &writer = get_writer(METADATA, gen); + ceph_assert(writer->get_type() == backend_type_t::SEGMENTED); + cold_writer_stats.back().add(writer->get_stats()); + } + cold_stats.add(cold_writer_stats.back()); + // 1. colddata + cold_writer_stats.emplace_back(); + for (rewrite_gen_t gen = MIN_COLD_GENERATION; gen < REWRITE_GENERATIONS; ++gen) { + const auto &writer = get_writer(DATA, gen); + ceph_assert(writer->get_type() == backend_type_t::SEGMENTED); + cold_writer_stats.back().add(writer->get_stats()); + } + cold_stats.add(cold_writer_stats.back()); + } + + auto now = seastar::lowres_clock::now(); + if (last_tp == seastar::lowres_clock::time_point::min()) { + last_tp = now; + return {}; + } + std::chrono::duration duration_d = now - last_tp; + double seconds = duration_d.count(); + last_tp = now; + + if (report_detail) { + std::ostringstream oss; + auto report_writer_stats = [seconds, &oss]( + const char* name, + const writer_stats_t& stats) { + oss << "\n" << name << ": " << writer_stats_printer_t{seconds, stats}; + }; + report_writer_stats("tier-main", main_stats); + report_writer_stats(" inline", journal_stats); + if (get_main_backend_type() == backend_type_t::SEGMENTED) { + report_writer_stats(" oolmdat", main_writer_stats[0]); + report_writer_stats(" ooldata", main_writer_stats[1]); + report_writer_stats(" mainmdat", main_writer_stats[2]); + report_writer_stats(" maindata", main_writer_stats[3]); + } else { // RBM + // TODO stats from RandomBlockOolWriter + } + if (has_cold_tier) { + report_writer_stats("tier-cold", cold_stats); + report_writer_stats(" coldmdat", cold_writer_stats[0]); + report_writer_stats(" colddata", cold_writer_stats[1]); + } + + auto report_by_src = [seconds, has_cold_tier, &oss, + &journal_stats, + &main_writer_stats, + &cold_writer_stats](transaction_type_t src) { + auto t_stats = get_by_src(journal_stats.stats_by_src, src); + for (const auto &writer_stats : main_writer_stats) { + t_stats += get_by_src(writer_stats.stats_by_src, src); + } + for (const auto &writer_stats : cold_writer_stats) { + t_stats += get_by_src(writer_stats.stats_by_src, src); + } + if (src == transaction_type_t::READ) { + ceph_assert(t_stats.is_empty()); + return; + } + oss << "\n" << src << ": " + << tw_stats_printer_t{seconds, t_stats}; + + auto report_tw_stats = [seconds, src, &oss]( + const char* name, + const writer_stats_t& stats) { + const auto& tw_stats = get_by_src(stats.stats_by_src, src); + if (tw_stats.is_empty()) { + return; + } + oss << "\n " << name << ": " + << tw_stats_printer_t{seconds, tw_stats}; + }; + report_tw_stats("inline", journal_stats); + report_tw_stats("oolmdat", main_writer_stats[0]); + report_tw_stats("ooldata", main_writer_stats[1]); + report_tw_stats("mainmdat", main_writer_stats[2]); + report_tw_stats("maindata", main_writer_stats[3]); + if (has_cold_tier) { + report_tw_stats("coldmdat", cold_writer_stats[0]); + report_tw_stats("colddata", cold_writer_stats[1]); + } + }; + for (uint8_t _src=0; _src(_src); + report_by_src(src); + } + + INFO("{}", oss.str()); + } + + main_stats.add(cold_stats); + return {main_stats.io_depth_stats.num_io, + main_stats.io_depth_stats.num_io_grouped, + main_stats.get_total_bytes()}; +} + ExtentPlacementManager::open_ertr::future<> ExtentPlacementManager::open_for_write() { diff --git a/src/crimson/os/seastore/extent_placement_manager.h b/src/crimson/os/seastore/extent_placement_manager.h index 6c1f7939a2a..44408f2fadc 100644 --- a/src/crimson/os/seastore/extent_placement_manager.h +++ b/src/crimson/os/seastore/extent_placement_manager.h @@ -3,7 +3,8 @@ #pragma once -#include "seastar/core/gate.hh" +#include +#include #include "crimson/os/seastore/async_cleaner.h" #include "crimson/os/seastore/cached_extent.h" @@ -30,6 +31,10 @@ class ExtentOolWriter { public: virtual ~ExtentOolWriter() {} + virtual backend_type_t get_type() const = 0; + + virtual writer_stats_t get_stats() const = 0; + using open_ertr = base_ertr; virtual open_ertr::future<> open() = 0; @@ -68,6 +73,14 @@ public: SegmentProvider &sp, SegmentSeqAllocator &ssa); + backend_type_t get_type() const final { + return backend_type_t::SEGMENTED; + } + + writer_stats_t get_stats() const final { + return record_submitter.get_stats(); + } + open_ertr::future<> open() final { return record_submitter.open(false).discard_result(); } @@ -119,6 +132,15 @@ public: RandomBlockOolWriter(RBMCleaner* rb_cleaner) : rb_cleaner(rb_cleaner) {} + backend_type_t get_type() const final { + return backend_type_t::RANDOM_BLOCK; + } + + writer_stats_t get_stats() const final { + // TODO: collect stats + return {}; + } + using open_ertr = ExtentOolWriter::open_ertr; open_ertr::future<> open() final { return open_ertr::now(); @@ -268,6 +290,10 @@ public: return background_process.get_stat(); } + device_stats_t get_device_stats( + const writer_stats_t &journal_stats, + bool report_detail) const; + using mount_ertr = crimson::errorator< crimson::ct_error::input_output_error>; using mount_ret = mount_ertr::future<>; @@ -589,6 +615,27 @@ private: rewrite_gen_t gen) { assert(hint < placement_hint_t::NUM_HINTS); // TODO: might worth considering the hint + return get_writer(category, gen); + } + + ExtentOolWriter* get_writer(data_category_t category, + rewrite_gen_t gen) { + assert(is_rewrite_generation(gen)); + assert(gen != INLINE_GENERATION); + assert(gen <= dynamic_max_rewrite_generation); + ExtentOolWriter* ret = nullptr; + if (category == data_category_t::DATA) { + ret = data_writers_by_gen[generation_to_writer(gen)]; + } else { + assert(category == data_category_t::METADATA); + ret = md_writers_by_gen[generation_to_writer(gen)]; + } + assert(ret != nullptr); + return ret; + } + + const ExtentOolWriter* get_writer(data_category_t category, + rewrite_gen_t gen) const { assert(is_rewrite_generation(gen)); assert(gen != INLINE_GENERATION); assert(gen <= dynamic_max_rewrite_generation); @@ -1030,6 +1077,9 @@ private: SegmentSeqAllocatorRef ool_segment_seq_allocator; extent_len_t max_data_allocation_size = 0; + mutable seastar::lowres_clock::time_point last_tp = + seastar::lowres_clock::time_point::min(); + friend class ::transaction_manager_test_t; }; diff --git a/src/crimson/os/seastore/journal.h b/src/crimson/os/seastore/journal.h index 2012e602cd9..724b50041fd 100644 --- a/src/crimson/os/seastore/journal.h +++ b/src/crimson/os/seastore/journal.h @@ -23,6 +23,9 @@ class JournalTrimmer; class Journal { public: virtual JournalTrimmer &get_trimmer() = 0; + + virtual writer_stats_t get_writer_stats() const = 0; + /** * initializes journal for mkfs writes -- must run prior to calls * to submit_record. diff --git a/src/crimson/os/seastore/journal/circular_bounded_journal.h b/src/crimson/os/seastore/journal/circular_bounded_journal.h index d3a955ef68e..077da32c9a2 100644 --- a/src/crimson/os/seastore/journal/circular_bounded_journal.h +++ b/src/crimson/os/seastore/journal/circular_bounded_journal.h @@ -66,6 +66,10 @@ public: return trimmer; } + writer_stats_t get_writer_stats() const final { + return record_submitter.get_stats(); + } + open_for_mkfs_ret open_for_mkfs() final; open_for_mount_ret open_for_mount() final; diff --git a/src/crimson/os/seastore/journal/record_submitter.cc b/src/crimson/os/seastore/journal/record_submitter.cc index c0cbef2cb57..d7ae299d699 100644 --- a/src/crimson/os/seastore/journal/record_submitter.cc +++ b/src/crimson/os/seastore/journal/record_submitter.cc @@ -172,6 +172,14 @@ bool RecordSubmitter::is_available() const return ret; } +writer_stats_t RecordSubmitter::get_stats() const +{ + writer_stats_t ret = stats; + ret.minus(last_stats); + last_stats = stats; + return ret; +} + RecordSubmitter::wa_ertr::future<> RecordSubmitter::wait_available() { @@ -364,6 +372,7 @@ RecordSubmitter::open(bool is_mkfs) LOG_PREFIX(RecordSubmitter::open); DEBUG("{} register metrics", get_name()); stats = {}; + last_stats = {}; namespace sm = seastar::metrics; std::vector label_instances; label_instances.push_back(sm::label_instance("submitter", get_name())); diff --git a/src/crimson/os/seastore/journal/record_submitter.h b/src/crimson/os/seastore/journal/record_submitter.h index 1ca19f0457b..d69a5ac96f0 100644 --- a/src/crimson/os/seastore/journal/record_submitter.h +++ b/src/crimson/os/seastore/journal/record_submitter.h @@ -242,6 +242,9 @@ public: // whether is available to submit a record bool is_available() const; + // get the stats since last_stats + writer_stats_t get_stats() const; + // wait for available if cannot submit, should check is_available() again // when the future is resolved. using wa_ertr = base_ertr; @@ -329,6 +332,7 @@ private: std::optional > wait_unfull_flush_promise; writer_stats_t stats; + mutable writer_stats_t last_stats; seastar::metrics::metric_group metrics; }; diff --git a/src/crimson/os/seastore/journal/segmented_journal.h b/src/crimson/os/seastore/journal/segmented_journal.h index 45e44dafb03..736b8c01293 100644 --- a/src/crimson/os/seastore/journal/segmented_journal.h +++ b/src/crimson/os/seastore/journal/segmented_journal.h @@ -34,6 +34,10 @@ public: return trimmer; } + writer_stats_t get_writer_stats() const final { + return record_submitter.get_stats(); + } + open_for_mkfs_ret open_for_mkfs() final; open_for_mount_ret open_for_mount() final; diff --git a/src/crimson/os/seastore/seastore.cc b/src/crimson/os/seastore/seastore.cc index 50e7eb1d4ff..974b256342b 100644 --- a/src/crimson/os/seastore/seastore.cc +++ b/src/crimson/os/seastore/seastore.cc @@ -572,6 +572,69 @@ seastar::future SeaStore::pool_statfs(int64_t pool_id) const return SeaStore::stat(); } +seastar::future<> SeaStore::report_stats() +{ + ceph_assert(seastar::this_shard_id() == primary_core); + shard_device_stats.resize(seastar::smp::count); + return shard_stores.invoke_on_all([this](const Shard &local_store) { + bool report_detail = false; + if (seastar::this_shard_id() == 0) { + // avoid too verbose logs, only report detail in a particular shard + report_detail = true; + } + shard_device_stats[seastar::this_shard_id()] = + local_store.get_device_stats(report_detail); + }).then([this] { + LOG_PREFIX(SeaStore); + auto now = seastar::lowres_clock::now(); + if (last_tp == seastar::lowres_clock::time_point::min()) { + last_tp = now; + return seastar::now(); + } + std::chrono::duration duration_d = now - last_tp; + double seconds = duration_d.count(); + last_tp = now; + device_stats_t ts = {}; + for (const auto &s : shard_device_stats) { + ts.add(s); + } + constexpr const char* dfmt = "{:.2f}"; + auto d_ts_num_io = static_cast(ts.num_io); + std::ostringstream oss_iops; + oss_iops << "device IOPS:" + << fmt::format(dfmt, ts.num_io/seconds) + << "("; + std::ostringstream oss_depth; + oss_depth << "device per-writer depth:" + << fmt::format(dfmt, ts.total_depth/d_ts_num_io) + << "("; + std::ostringstream oss_bd; + oss_bd << "device bandwidth(MiB):" + << fmt::format(dfmt, ts.total_bytes/seconds/(1<<20)) + << "("; + std::ostringstream oss_iosz; + oss_iosz << "device IO size(B):" + << fmt::format(dfmt, ts.total_bytes/d_ts_num_io) + << "("; + for (const auto &s : shard_device_stats) { + auto d_s_num_io = static_cast(s.num_io); + oss_iops << fmt::format(dfmt, s.num_io/seconds) << ","; + oss_depth << fmt::format(dfmt, s.total_depth/d_s_num_io) << ","; + oss_bd << fmt::format(dfmt, s.total_bytes/seconds/(1<<20)) << ","; + oss_iosz << fmt::format(dfmt, s.total_bytes/d_s_num_io) << ","; + } + oss_iops << ")"; + oss_depth << ")"; + oss_bd << ")"; + oss_iosz << ")"; + INFO("{}", oss_iops.str()); + INFO("{}", oss_depth.str()); + INFO("{}", oss_bd.str()); + INFO("{}", oss_iosz.str()); + return seastar::now(); + }); +} + TransactionManager::read_extent_iertr::future> SeaStore::Shard::get_coll_bits(CollectionRef ch, Transaction &t) const { @@ -2295,6 +2358,11 @@ void SeaStore::Shard::init_managers() *transaction_manager); } +device_stats_t SeaStore::Shard::get_device_stats(bool report_detail) const +{ + return transaction_manager->get_device_stats(report_detail); +} + std::unique_ptr make_seastore( const std::string &device) { diff --git a/src/crimson/os/seastore/seastore.h b/src/crimson/os/seastore/seastore.h index 3de8a812e12..5febb1bcbee 100644 --- a/src/crimson/os/seastore/seastore.h +++ b/src/crimson/os/seastore/seastore.h @@ -3,14 +3,15 @@ #pragma once -#include -#include #include +#include +#include #include +#include #include -#include #include +#include #include #include "include/uuid.h" @@ -203,6 +204,8 @@ public: void init_managers(); + device_stats_t get_device_stats(bool report_detail) const; + private: struct internal_context_t { CollectionRef ch; @@ -495,6 +498,8 @@ public: seastar::future stat() const final; seastar::future pool_statfs(int64_t pool_id) const final; + seastar::future<> report_stats() final; + uuid_d get_fsid() const final { ceph_assert(seastar::this_shard_id() == primary_core); return shard_stores.local().get_fsid(); @@ -547,6 +552,10 @@ private: DeviceRef device; std::vector secondaries; seastar::sharded shard_stores; + + mutable seastar::lowres_clock::time_point last_tp = + seastar::lowres_clock::time_point::min(); + mutable std::vector shard_device_stats; }; std::unique_ptr make_seastore( diff --git a/src/crimson/os/seastore/seastore_types.cc b/src/crimson/os/seastore/seastore_types.cc index 9722d99da79..7699bc37367 100644 --- a/src/crimson/os/seastore/seastore_types.cc +++ b/src/crimson/os/seastore/seastore_types.cc @@ -878,4 +878,46 @@ std::ostream& operator<<(std::ostream& out, const scan_valid_records_cursor& c) << ")"; } +std::ostream& operator<<(std::ostream& out, const tw_stats_printer_t& p) +{ + constexpr const char* dfmt = "{:.2f}"; + double d_num_records = static_cast(p.stats.num_records); + out << "rps=" + << fmt::format(dfmt, d_num_records/p.seconds) + << ",bwMiB=" + << fmt::format(dfmt, p.stats.get_total_bytes()/p.seconds/(1<<20)) + << ",sizeB=" + << fmt::format(dfmt, p.stats.get_total_bytes()/d_num_records) + << "(" + << fmt::format(dfmt, p.stats.data_bytes/d_num_records) + << "," + << fmt::format(dfmt, p.stats.metadata_bytes/d_num_records) + << ")"; + return out; +} + +std::ostream& operator<<(std::ostream& out, const writer_stats_printer_t& p) +{ + constexpr const char* dfmt = "{:.2f}"; + auto d_num_io = static_cast(p.stats.io_depth_stats.num_io); + out << "iops=" + << fmt::format(dfmt, d_num_io/p.seconds) + << ",depth=" + << fmt::format(dfmt, p.stats.io_depth_stats.average()) + << ",batch=" + << fmt::format(dfmt, p.stats.record_batch_stats.average()) + << ",bwMiB=" + << fmt::format(dfmt, p.stats.get_total_bytes()/p.seconds/(1<<20)) + << ",sizeB=" + << fmt::format(dfmt, p.stats.get_total_bytes()/d_num_io) + << "(" + << fmt::format(dfmt, p.stats.record_group_data_bytes/d_num_io) + << "," + << fmt::format(dfmt, p.stats.record_group_metadata_bytes/d_num_io) + << "," + << fmt::format(dfmt, p.stats.record_group_padding_bytes/d_num_io) + << ")"; + return out; +} + } diff --git a/src/crimson/os/seastore/seastore_types.h b/src/crimson/os/seastore/seastore_types.h index cd55e425de5..14ba07b2e0b 100644 --- a/src/crimson/os/seastore/seastore_types.h +++ b/src/crimson/os/seastore/seastore_types.h @@ -2235,13 +2235,58 @@ const CounterT& get_by_src( return counters_by_src[static_cast(src)]; } +template +void add_srcs(counter_by_src_t& base, + const counter_by_src_t& by) { + for (std::size_t i=0; i +void minus_srcs(counter_by_src_t& base, + const counter_by_src_t& by) { + for (std::size_t i=0; i(num_io_grouped)/num_io; + } + + bool is_empty() const { + return num_io == 0; + } + + void add(const grouped_io_stats &o) { + num_io += o.num_io; + num_io_grouped += o.num_io_grouped; + } + + void minus(const grouped_io_stats &o) { + num_io -= o.num_io; + num_io_grouped -= o.num_io_grouped; + } + void increment(uint64_t num_grouped_io) { - ++num_io; - num_io_grouped += num_grouped_io; + add({1, num_grouped_io}); + } +}; + +struct device_stats_t { + uint64_t num_io = 0; + uint64_t total_depth = 0; + uint64_t total_bytes = 0; + + void add(const device_stats_t& other) { + num_io += other.num_io; + total_depth += other.total_depth; + total_bytes += other.total_bytes; } }; @@ -2249,7 +2294,36 @@ struct trans_writer_stats_t { uint64_t num_records = 0; uint64_t metadata_bytes = 0; uint64_t data_bytes = 0; + + bool is_empty() const { + return num_records == 0; + } + + uint64_t get_total_bytes() const { + return metadata_bytes + data_bytes; + } + + trans_writer_stats_t& + operator+=(const trans_writer_stats_t& o) { + num_records += o.num_records; + metadata_bytes += o.metadata_bytes; + data_bytes += o.data_bytes; + return *this; + } + + trans_writer_stats_t& + operator-=(const trans_writer_stats_t& o) { + num_records -= o.num_records; + metadata_bytes -= o.metadata_bytes; + data_bytes -= o.data_bytes; + return *this; + } }; +struct tw_stats_printer_t { + double seconds; + const trans_writer_stats_t &stats; +}; +std::ostream& operator<<(std::ostream&, const tw_stats_printer_t&); struct writer_stats_t { grouped_io_stats record_batch_stats; @@ -2258,7 +2332,40 @@ struct writer_stats_t { uint64_t record_group_metadata_bytes = 0; uint64_t record_group_data_bytes = 0; counter_by_src_t stats_by_src; + + bool is_empty() const { + return io_depth_stats.is_empty(); + } + + uint64_t get_total_bytes() const { + return record_group_padding_bytes + + record_group_metadata_bytes + + record_group_data_bytes; + } + + void add(const writer_stats_t &o) { + record_batch_stats.add(o.record_batch_stats); + io_depth_stats.add(o.io_depth_stats); + record_group_padding_bytes += o.record_group_padding_bytes; + record_group_metadata_bytes += o.record_group_metadata_bytes; + record_group_data_bytes += o.record_group_data_bytes; + add_srcs(stats_by_src, o.stats_by_src); + } + + void minus(const writer_stats_t &o) { + record_batch_stats.minus(o.record_batch_stats); + io_depth_stats.minus(o.io_depth_stats); + record_group_padding_bytes -= o.record_group_padding_bytes; + record_group_metadata_bytes -= o.record_group_metadata_bytes; + record_group_data_bytes -= o.record_group_data_bytes; + minus_srcs(stats_by_src, o.stats_by_src); + } +}; +struct writer_stats_printer_t { + double seconds; + const writer_stats_t &stats; }; +std::ostream& operator<<(std::ostream&, const writer_stats_printer_t&); } diff --git a/src/crimson/os/seastore/transaction_manager.h b/src/crimson/os/seastore/transaction_manager.h index 28d2529d186..3dd0bb565e5 100644 --- a/src/crimson/os/seastore/transaction_manager.h +++ b/src/crimson/os/seastore/transaction_manager.h @@ -79,6 +79,11 @@ public: using close_ertr = base_ertr; close_ertr::future<> close(); + device_stats_t get_device_stats(bool report_detail) const { + writer_stats_t journal_stats = journal->get_writer_stats(); + return epm->get_device_stats(journal_stats, report_detail); + } + /// Resets transaction void reset_transaction_preserve_handle(Transaction &t) { return cache->reset_transaction_preserve_handle(t); diff --git a/src/crimson/osd/osd.cc b/src/crimson/osd/osd.cc index 6bdda0a8cf9..8f01fb63089 100644 --- a/src/crimson/osd/osd.cc +++ b/src/crimson/osd/osd.cc @@ -413,6 +413,9 @@ seastar::future<> OSD::start() INFO("reactor_utilizations: {}", oss.str()); }); }); + gate.dispatch_in_background("stats_store", *this, [this] { + return store.report_stats(); + }); }); stats_timer.arm_periodic(std::chrono::seconds(stats_seconds)); } -- 2.39.5