3434
3535namespace couchbase ::core
3636{
37+ struct node_labels {
38+ std::string node;
39+ std::optional<std::string> alt_node;
40+ };
41+
3742class app_telemetry_meter_impl
3843{
3944public:
4045 app_telemetry_meter_impl () = default ;
41- app_telemetry_meter_impl (app_telemetry_meter_impl&&) = default ;
46+ app_telemetry_meter_impl (app_telemetry_meter_impl&&) = delete ;
4247 app_telemetry_meter_impl (const app_telemetry_meter_impl&) = delete ;
43- auto operator =(app_telemetry_meter_impl&&) -> app_telemetry_meter_impl& = default ;
48+ auto operator =(app_telemetry_meter_impl&&) -> app_telemetry_meter_impl& = delete ;
4449 auto operator =(const app_telemetry_meter_impl&) -> app_telemetry_meter_impl& = delete ;
4550 virtual ~app_telemetry_meter_impl () = default ;
4651
4752 virtual auto enabled () -> bool = 0;
53+ [[nodiscard]] virtual auto current_node_labels () const -> std::map<std::string, node_labels> = 0;
54+ virtual void set_node_labels_cache (std::map<std::string, node_labels>) = 0;
4855 virtual auto nothing_to_report () -> bool = 0;
4956 virtual void update_config (const topology::configuration& config) = 0;
5057 virtual auto value_recorder (const std::string& node_uuid, const std::string& bucket_name)
@@ -101,11 +108,6 @@ namespace couchbase::core
101108{
102109namespace
103110{
104- struct node_labels {
105- std::string node;
106- std::optional<std::string> alt_node;
107- };
108-
109111struct kv_non_durable_histogram {
110112 const char * name;
111113 std::atomic_uint64_t le_1ms{};
@@ -349,6 +351,16 @@ class null_app_telemetry_meter_impl : public app_telemetry_meter_impl
349351 {
350352 /* do nothing */
351353 }
354+
355+ [[nodiscard]] auto current_node_labels () const -> std::map<std::string, node_labels> override
356+ {
357+ return {};
358+ }
359+
360+ void set_node_labels_cache (std::map<std::string, node_labels>) override
361+ {
362+ /* do nothing */
363+ }
352364};
353365
354366class default_app_telemetry_value_recorder : public app_telemetry_value_recorder
@@ -600,6 +612,7 @@ class default_app_telemetry_meter_impl : public app_telemetry_meter_impl
600612
601613 void update_config (const topology::configuration& config) override
602614 {
615+ node_uuids_in_last_config_.clear ();
603616 for (const auto & node : config.nodes ) {
604617 std::optional<std::string> alt_node{};
605618 if (auto it = node.alt .find (" external" ); it != node.alt .end ()) {
@@ -611,6 +624,7 @@ class default_app_telemetry_meter_impl : public app_telemetry_meter_impl
611624 node.hostname ,
612625 alt_node,
613626 };
627+ node_uuids_in_last_config_.push_back (node.node_uuid );
614628 }
615629 }
616630
@@ -625,6 +639,23 @@ class default_app_telemetry_meter_impl : public app_telemetry_meter_impl
625639 return recorders_.empty ();
626640 }
627641
642+ [[nodiscard]] auto current_node_labels () const -> std::map<std::string, node_labels> override
643+ {
644+ std::map<std::string, node_labels> labels{};
645+ for (const auto & node_uuid : node_uuids_in_last_config_) {
646+ labels[node_uuid] = labels_cache_.at (node_uuid);
647+ }
648+ return labels;
649+ }
650+
651+ void set_node_labels_cache (std::map<std::string, node_labels> labels) override
652+ {
653+ for (const auto & [node_uuid, _] : labels) {
654+ node_uuids_in_last_config_.push_back (node_uuid);
655+ }
656+ labels_cache_ = std::move (labels);
657+ }
658+
628659 void generate_to (std::vector<std::byte>& buffer, const std::string& agent) override
629660 {
630661 auto now = std::chrono::duration_cast<std::chrono::milliseconds>(
@@ -677,6 +708,7 @@ class default_app_telemetry_meter_impl : public app_telemetry_meter_impl
677708 std::map<std::string, std::shared_ptr<default_app_telemetry_value_recorder>>>
678709 recorders_{};
679710 std::map<std::string, node_labels> labels_cache_{};
711+ std::vector<std::string> node_uuids_in_last_config_{};
680712};
681713
682714auto
@@ -699,6 +731,7 @@ app_telemetry_meter::app_telemetry_meter()
699731void
700732app_telemetry_meter::disable ()
701733{
734+ const std::scoped_lock lock{ impl_mutex_ };
702735 if (!impl_->enabled ()) {
703736 return ;
704737 }
@@ -712,6 +745,7 @@ app_telemetry_meter::disable()
712745void
713746app_telemetry_meter::enable ()
714747{
748+ const std::scoped_lock lock{ impl_mutex_ };
715749 if (impl_->enabled ()) {
716750 return ;
717751 }
@@ -730,24 +764,28 @@ app_telemetry_meter::~app_telemetry_meter() = default;
730764void
731765app_telemetry_meter::update_config (const topology::configuration& config)
732766{
767+ const std::shared_lock lock{ impl_mutex_ };
733768 return impl_->update_config (config);
734769}
735770
736771auto
737772app_telemetry_meter::value_recorder (const std::string& node_uuid, const std::string& bucket_name)
738773 -> std::shared_ptr<app_telemetry_value_recorder>
739774{
775+ const std::shared_lock lock{ impl_mutex_ };
740776 return impl_->value_recorder (node_uuid, bucket_name);
741777}
742778
743779void
744780app_telemetry_meter::generate_report (std::vector<std::byte>& output_buffer)
745781{
782+ const std::scoped_lock lock{ impl_mutex_ };
746783 if (impl_->nothing_to_report ()) {
747784 return ;
748785 }
749- auto old_impl = std::move (impl_);
786+ const auto old_impl = std::move (impl_);
750787 impl_ = std::make_unique<default_app_telemetry_meter_impl>();
788+ impl_->set_node_labels_cache (old_impl->current_node_labels ());
751789 old_impl->generate_to (output_buffer, agent_);
752790}
753791} // namespace couchbase::core
0 commit comments