github-actions[bot] commented on code in PR #30875: URL: https://github.com/apache/doris/pull/30875#discussion_r1495931380
########## be/src/util/bvar_metrics.cpp: ########## @@ -0,0 +1,296 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +#include "util/bvar_metrics.h" + +namespace doris { + +std::ostream& operator<<(std::ostream& os, BvarMetricType type) { + switch (type) { + case BvarMetricType::COUNTER: + os << "counter"; + break; + case BvarMetricType::GAUGE: + os << "gauge"; + break; + case BvarMetricType::HISTOGRAM: + os << "histogram"; + break; + case BvarMetricType::SUMMARY: + os << "summary"; + break; + case BvarMetricType::UNTYPED: + os << "untyped"; + break; + default: + os << "unknown"; + break; + } + return os; +} + +const char* unit_name(BvarMetricUnit unit) { + switch (unit) { + case BvarMetricUnit::NANOSECONDS: + return "nanoseconds"; + case BvarMetricUnit::MICROSECONDS: + return "microseconds"; + case BvarMetricUnit::MILLISECONDS: + return "milliseconds"; + case BvarMetricUnit::SECONDS: + return "seconds"; + case BvarMetricUnit::BYTES: + return "bytes"; + case BvarMetricUnit::ROWS: + return "rows"; + case BvarMetricUnit::PERCENT: + return "percent"; + case BvarMetricUnit::REQUESTS: + return "requests"; + case BvarMetricUnit::OPERATIONS: + return "operations"; + case BvarMetricUnit::BLOCKS: + return "blocks"; + case BvarMetricUnit::ROWSETS: + return "rowsets"; + case BvarMetricUnit::CONNECTIONS: + return "rowsets"; + default: + return "nounit"; + } +} + +std::string BvarMetric::simple_name() const { + return group_name_.empty() ? name_ : group_name_; +} + +std::string BvarMetric::combine_name(const std::string& registry_name) const { + return (registry_name.empty() ? std::string() : registry_name + "_") + simple_name(); +} + +template <typename T> +T BvarAdderMetric<T>::get_value() const { + return adder_->get_value(); +} + +template <typename T> +void BvarAdderMetric<T>::increment(T value) { + (*adder_) << value; +} + +template <typename T> +void BvarAdderMetric<T>::set_value(T value) { + adder_->reset(); + (*adder_) << value; +} + +template <typename T> +std::string BvarAdderMetric<T>::to_prometheus(const std::string& registry_name, const Labels& entity_labels) const { + std::stringstream ss; + ss << combine_name(registry_name) // metrics name + << labels_to_string({&entity_labels, &labels_}) // metrics lables + << value_string() << "\n"; // metrics value + return ss.str(); +} + +template <typename T> +std::string BvarAdderMetric<T>::value_string() const { + return std::to_string(adder_->get_value()); +} + +template <typename T> +void BvarMetricEntity::register_metric(const std::string& name, T metric) { + { + std::lock_guard<bthread::Mutex> l(mutex_); + auto it = metrics_.find(name); + if (it == metrics_.end()) { + metrics_[name] = std::make_shared<T>(metric); + } + } +} + +void BvarMetricEntity::deregister_metric(const std::string& name) { + { + std::lock_guard<bthread::Mutex> l(mutex_); + auto it = metrics_.find(name); + if (it != metrics_.end()) { + metrics_.erase(it); + } + } +} + +std::shared_ptr<BvarMetric> BvarMetricEntity::get_metric(const std::string& name) { + { + std::lock_guard<bthread::Mutex> l(mutex_); + auto it = metrics_.find(name); + if (it == metrics_.end()) { + return nullptr; + } + return it->second; + } +} + +void BvarMetricEntity::register_hook(const std::string& name, const std::function<void()>& hook) { + std::lock_guard<bthread::Mutex> l(mutex_); +#ifndef BE_TEST + DCHECK(hooks_.find(name) == hooks_.end()) << "hook is already exist! " << entity_name_ << ":" << name; +#endif + hooks_.emplace(name, hook); +} + +void BvarMetricEntity::deregister_hook(const std::string& name) { + std::lock_guard<bthread::Mutex> l(mutex_); + hooks_.erase(name); +} + +void BvarMetricEntity::trigger_hook_unlocked(bool force) const { Review Comment: warning: method 'trigger_hook_unlocked' can be made static [readability-convert-member-functions-to-static] be/src/util/bvar_metrics.h:174: ```diff - void trigger_hook_unlocked(bool force) const; + static void trigger_hook_unlocked(bool force) ; ``` ```suggestion void BvarMetricEntity::trigger_hook_unlocked(bool force) { ``` ########## be/src/util/bvar_metrics.cpp: ########## @@ -0,0 +1,296 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +#include "util/bvar_metrics.h" + +namespace doris { + +std::ostream& operator<<(std::ostream& os, BvarMetricType type) { + switch (type) { + case BvarMetricType::COUNTER: + os << "counter"; + break; + case BvarMetricType::GAUGE: + os << "gauge"; + break; + case BvarMetricType::HISTOGRAM: + os << "histogram"; + break; + case BvarMetricType::SUMMARY: + os << "summary"; + break; + case BvarMetricType::UNTYPED: + os << "untyped"; + break; + default: + os << "unknown"; + break; + } + return os; +} + +const char* unit_name(BvarMetricUnit unit) { + switch (unit) { + case BvarMetricUnit::NANOSECONDS: + return "nanoseconds"; + case BvarMetricUnit::MICROSECONDS: + return "microseconds"; + case BvarMetricUnit::MILLISECONDS: + return "milliseconds"; + case BvarMetricUnit::SECONDS: + return "seconds"; + case BvarMetricUnit::BYTES: + return "bytes"; + case BvarMetricUnit::ROWS: + return "rows"; + case BvarMetricUnit::PERCENT: + return "percent"; + case BvarMetricUnit::REQUESTS: + return "requests"; + case BvarMetricUnit::OPERATIONS: + return "operations"; + case BvarMetricUnit::BLOCKS: + return "blocks"; + case BvarMetricUnit::ROWSETS: + return "rowsets"; + case BvarMetricUnit::CONNECTIONS: + return "rowsets"; + default: + return "nounit"; + } +} + +std::string BvarMetric::simple_name() const { + return group_name_.empty() ? name_ : group_name_; +} + +std::string BvarMetric::combine_name(const std::string& registry_name) const { + return (registry_name.empty() ? std::string() : registry_name + "_") + simple_name(); +} + +template <typename T> +T BvarAdderMetric<T>::get_value() const { + return adder_->get_value(); +} + +template <typename T> +void BvarAdderMetric<T>::increment(T value) { + (*adder_) << value; +} + +template <typename T> +void BvarAdderMetric<T>::set_value(T value) { + adder_->reset(); + (*adder_) << value; +} + +template <typename T> +std::string BvarAdderMetric<T>::to_prometheus(const std::string& registry_name, const Labels& entity_labels) const { + std::stringstream ss; + ss << combine_name(registry_name) // metrics name + << labels_to_string({&entity_labels, &labels_}) // metrics lables + << value_string() << "\n"; // metrics value + return ss.str(); +} + +template <typename T> +std::string BvarAdderMetric<T>::value_string() const { + return std::to_string(adder_->get_value()); +} + +template <typename T> +void BvarMetricEntity::register_metric(const std::string& name, T metric) { + { + std::lock_guard<bthread::Mutex> l(mutex_); + auto it = metrics_.find(name); + if (it == metrics_.end()) { + metrics_[name] = std::make_shared<T>(metric); + } + } +} + +void BvarMetricEntity::deregister_metric(const std::string& name) { + { + std::lock_guard<bthread::Mutex> l(mutex_); + auto it = metrics_.find(name); + if (it != metrics_.end()) { + metrics_.erase(it); + } + } +} + +std::shared_ptr<BvarMetric> BvarMetricEntity::get_metric(const std::string& name) { + { + std::lock_guard<bthread::Mutex> l(mutex_); + auto it = metrics_.find(name); + if (it == metrics_.end()) { + return nullptr; + } + return it->second; + } +} + +void BvarMetricEntity::register_hook(const std::string& name, const std::function<void()>& hook) { + std::lock_guard<bthread::Mutex> l(mutex_); +#ifndef BE_TEST + DCHECK(hooks_.find(name) == hooks_.end()) << "hook is already exist! " << entity_name_ << ":" << name; +#endif + hooks_.emplace(name, hook); +} + +void BvarMetricEntity::deregister_hook(const std::string& name) { + std::lock_guard<bthread::Mutex> l(mutex_); + hooks_.erase(name); +} + +void BvarMetricEntity::trigger_hook_unlocked(bool force) const { + // When 'enable_metric_calculator' is true, hooks will be triggered by a background thread, + // see 'calculate_metrics' in daemon.cpp for more details. + if (!force && config::enable_metric_calculator) { + return; + } + for (const auto& hook : hooks_) { + hook.second(); + } +} + +void BvarMetricRegistry::register_entity(BvarMetricEntity entity) {} + +void BvarMetricRegistry::trigger_all_hooks(bool force) { + std::lock_guard<bthread::Mutex> l(mutex_); + for (const auto& entity : entities_) { + std::lock_guard<bthread::Mutex> l(entity.first->mutex_); + entity.first->trigger_hook_unlocked(force); + } +} + +const std::string BvarMetricRegistry::to_prometheus(bool with_tablet_metrics) { Review Comment: warning: return type 'const int' is 'const'-qualified at the top level, which may reduce code readability without improving const correctness [readability-const-return-type] ```suggestion std::string BvarMetricRegistry::to_prometheus(bool with_tablet_metrics) { ``` ########## be/src/util/bvar_metrics.cpp: ########## @@ -0,0 +1,296 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +#include "util/bvar_metrics.h" + +namespace doris { + +std::ostream& operator<<(std::ostream& os, BvarMetricType type) { + switch (type) { + case BvarMetricType::COUNTER: + os << "counter"; + break; + case BvarMetricType::GAUGE: + os << "gauge"; + break; + case BvarMetricType::HISTOGRAM: + os << "histogram"; + break; + case BvarMetricType::SUMMARY: + os << "summary"; + break; + case BvarMetricType::UNTYPED: + os << "untyped"; + break; + default: + os << "unknown"; + break; + } + return os; +} + +const char* unit_name(BvarMetricUnit unit) { + switch (unit) { + case BvarMetricUnit::NANOSECONDS: + return "nanoseconds"; + case BvarMetricUnit::MICROSECONDS: + return "microseconds"; + case BvarMetricUnit::MILLISECONDS: + return "milliseconds"; + case BvarMetricUnit::SECONDS: + return "seconds"; + case BvarMetricUnit::BYTES: + return "bytes"; + case BvarMetricUnit::ROWS: + return "rows"; + case BvarMetricUnit::PERCENT: + return "percent"; + case BvarMetricUnit::REQUESTS: + return "requests"; + case BvarMetricUnit::OPERATIONS: + return "operations"; + case BvarMetricUnit::BLOCKS: + return "blocks"; + case BvarMetricUnit::ROWSETS: + return "rowsets"; + case BvarMetricUnit::CONNECTIONS: + return "rowsets"; + default: + return "nounit"; + } +} + +std::string BvarMetric::simple_name() const { + return group_name_.empty() ? name_ : group_name_; +} + +std::string BvarMetric::combine_name(const std::string& registry_name) const { + return (registry_name.empty() ? std::string() : registry_name + "_") + simple_name(); +} + +template <typename T> +T BvarAdderMetric<T>::get_value() const { + return adder_->get_value(); +} + +template <typename T> +void BvarAdderMetric<T>::increment(T value) { + (*adder_) << value; +} + +template <typename T> +void BvarAdderMetric<T>::set_value(T value) { + adder_->reset(); + (*adder_) << value; +} + +template <typename T> +std::string BvarAdderMetric<T>::to_prometheus(const std::string& registry_name, const Labels& entity_labels) const { + std::stringstream ss; + ss << combine_name(registry_name) // metrics name + << labels_to_string({&entity_labels, &labels_}) // metrics lables + << value_string() << "\n"; // metrics value + return ss.str(); +} + +template <typename T> +std::string BvarAdderMetric<T>::value_string() const { + return std::to_string(adder_->get_value()); +} + +template <typename T> +void BvarMetricEntity::register_metric(const std::string& name, T metric) { + { + std::lock_guard<bthread::Mutex> l(mutex_); + auto it = metrics_.find(name); + if (it == metrics_.end()) { + metrics_[name] = std::make_shared<T>(metric); + } + } +} + +void BvarMetricEntity::deregister_metric(const std::string& name) { + { + std::lock_guard<bthread::Mutex> l(mutex_); + auto it = metrics_.find(name); + if (it != metrics_.end()) { + metrics_.erase(it); + } + } +} + +std::shared_ptr<BvarMetric> BvarMetricEntity::get_metric(const std::string& name) { + { + std::lock_guard<bthread::Mutex> l(mutex_); + auto it = metrics_.find(name); + if (it == metrics_.end()) { + return nullptr; + } + return it->second; + } +} + +void BvarMetricEntity::register_hook(const std::string& name, const std::function<void()>& hook) { + std::lock_guard<bthread::Mutex> l(mutex_); +#ifndef BE_TEST + DCHECK(hooks_.find(name) == hooks_.end()) << "hook is already exist! " << entity_name_ << ":" << name; +#endif + hooks_.emplace(name, hook); +} + +void BvarMetricEntity::deregister_hook(const std::string& name) { + std::lock_guard<bthread::Mutex> l(mutex_); + hooks_.erase(name); +} + +void BvarMetricEntity::trigger_hook_unlocked(bool force) const { + // When 'enable_metric_calculator' is true, hooks will be triggered by a background thread, + // see 'calculate_metrics' in daemon.cpp for more details. + if (!force && config::enable_metric_calculator) { + return; + } + for (const auto& hook : hooks_) { + hook.second(); + } +} + +void BvarMetricRegistry::register_entity(BvarMetricEntity entity) {} + +void BvarMetricRegistry::trigger_all_hooks(bool force) { + std::lock_guard<bthread::Mutex> l(mutex_); + for (const auto& entity : entities_) { + std::lock_guard<bthread::Mutex> l(entity.first->mutex_); + entity.first->trigger_hook_unlocked(force); + } +} + +const std::string BvarMetricRegistry::to_prometheus(bool with_tablet_metrics) { + BvarEntityMetricsByType entity_metrics_by_types; + std::lock_guard<bthread::Mutex> l(mutex_); + + for (auto& entity : entities_) { + if (entity.first->type_ == BvarMetricEntityType::kTablet && !with_tablet_metrics) { + continue; + } + std::lock_guard<bthread::Mutex> l(entity->mutex_); + entity.first->trigger_hook_unlocked(false); + for(const auto& metric : entity.first->metrics_){ + std::pair<BvarMetricEntity*, BvarMetric*> new_elem = + std::make_pair(entity.first.get(), metric.second.get()); + auto found = entity_metrics_by_types.find(metric.second.get()); + if(found == entity_metrics_by_types.end()) { + entity_metrics_by_typess.emplace( + metric.second.get(), std::vector<std::pair<BvarMetricEntity*, BvarMetric*>>({new_elem})); + } else { + found->second.emplace_back(new_elem); + } + } + } + + // Output + std::stringstream ss; + std::string last_group_name; + for (const auto& entity_metrics_by_type : entity_metrics_by_types) { + + const auto metric = entity_metrics_by_type.first; + std::string display_name = metric->combine_name(name_); + + if (last_group_name.empty() || + last_group_name != metric->group_name_) { + ss << "# TYPE " << display_name << " " << metric->type_ << "\n"; // metric TYPE line + } + + last_group_name = metric->group_name_; + + for (const auto& entity_metric : entity_metrics_by_type.second) { + ss << entity_metric.second->to_prometheus(display_name, // metric key-value line + entity_metric.first->lables_); + } + } + + return ss.str(); +} + +const std::string BvarMetricRegistry::to_json(bool with_tablet_metrics) { + rj::Document doc {rj::kArrayType}; + rj::Document::AllocatorType& allocator = doc.GetAllocator(); + std::lock_guard<bthread::Mutex> l(mutex_); + for (const auto& entity : entities_) { + if (entity.first->type_ == BvarMetricEntityType::kTablet && !with_tablet_metrics) { + continue; + } + std::lock_guard<bthread::Mutex> l(entity->mutex_); + entity.first->trigger_hook_unlocked(false); + for (const auto& metric : entity.first->metrics_) { + rj::Value metric_obj(rj::kObjectType); + // tags + rj::Value tag_obj(rj::kObjectType); + tag_obj.AddMember("metric", rj::Value(metric.second->simple_name().c_str(), allocator), + allocator); + // MetricPrototype's labels + for (auto& label : metric.second->labels_) { + tag_obj.AddMember(rj::Value(label.first.c_str(), allocator), + rj::Value(label.second.c_str(), allocator), allocator); + } + // MetricEntity's labels + for (auto& label : entity.first->lables_) { + tag_obj.AddMember(rj::Value(label.first.c_str(), allocator), + rj::Value(label.second.c_str(), allocator), allocator); + } + metric_obj.AddMember("tags", tag_obj, allocator); + // unit + rj::Value unit_val(unit_name(metric.second->unit_), allocator); + metric_obj.AddMember("unit", unit_val, allocator); + // value + metric_obj.AddMember("value", metric.second->to_json_value(allocator), allocator); + doc.PushBack(metric_obj, allocator); + } + } + + rj::StringBuffer strBuf; + rj::Writer<rj::StringBuffer> writer(strBuf); + doc.Accept(writer); + return strBuf.GetString(); +} + +const std::string BvarMetricRegistry::to_core_string(){ Review Comment: warning: return type 'const int' is 'const'-qualified at the top level, which may reduce code readability without improving const correctness [readability-const-return-type] ```suggestion std::string BvarMetricRegistry::to_core_string(){ ``` ########## be/src/util/bvar_metrics.cpp: ########## @@ -0,0 +1,296 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +#include "util/bvar_metrics.h" + +namespace doris { + +std::ostream& operator<<(std::ostream& os, BvarMetricType type) { + switch (type) { + case BvarMetricType::COUNTER: + os << "counter"; + break; + case BvarMetricType::GAUGE: + os << "gauge"; + break; + case BvarMetricType::HISTOGRAM: + os << "histogram"; + break; + case BvarMetricType::SUMMARY: + os << "summary"; + break; + case BvarMetricType::UNTYPED: + os << "untyped"; + break; + default: + os << "unknown"; + break; + } + return os; +} + +const char* unit_name(BvarMetricUnit unit) { + switch (unit) { + case BvarMetricUnit::NANOSECONDS: + return "nanoseconds"; + case BvarMetricUnit::MICROSECONDS: + return "microseconds"; + case BvarMetricUnit::MILLISECONDS: + return "milliseconds"; + case BvarMetricUnit::SECONDS: + return "seconds"; + case BvarMetricUnit::BYTES: + return "bytes"; + case BvarMetricUnit::ROWS: + return "rows"; + case BvarMetricUnit::PERCENT: + return "percent"; + case BvarMetricUnit::REQUESTS: + return "requests"; + case BvarMetricUnit::OPERATIONS: + return "operations"; + case BvarMetricUnit::BLOCKS: + return "blocks"; + case BvarMetricUnit::ROWSETS: + return "rowsets"; + case BvarMetricUnit::CONNECTIONS: + return "rowsets"; + default: + return "nounit"; + } +} + +std::string BvarMetric::simple_name() const { + return group_name_.empty() ? name_ : group_name_; +} + +std::string BvarMetric::combine_name(const std::string& registry_name) const { + return (registry_name.empty() ? std::string() : registry_name + "_") + simple_name(); +} + +template <typename T> +T BvarAdderMetric<T>::get_value() const { + return adder_->get_value(); +} + +template <typename T> +void BvarAdderMetric<T>::increment(T value) { + (*adder_) << value; +} + +template <typename T> +void BvarAdderMetric<T>::set_value(T value) { + adder_->reset(); + (*adder_) << value; +} + +template <typename T> +std::string BvarAdderMetric<T>::to_prometheus(const std::string& registry_name, const Labels& entity_labels) const { + std::stringstream ss; + ss << combine_name(registry_name) // metrics name + << labels_to_string({&entity_labels, &labels_}) // metrics lables + << value_string() << "\n"; // metrics value + return ss.str(); +} + +template <typename T> +std::string BvarAdderMetric<T>::value_string() const { + return std::to_string(adder_->get_value()); +} + +template <typename T> +void BvarMetricEntity::register_metric(const std::string& name, T metric) { + { + std::lock_guard<bthread::Mutex> l(mutex_); + auto it = metrics_.find(name); + if (it == metrics_.end()) { + metrics_[name] = std::make_shared<T>(metric); + } + } +} + +void BvarMetricEntity::deregister_metric(const std::string& name) { + { + std::lock_guard<bthread::Mutex> l(mutex_); + auto it = metrics_.find(name); + if (it != metrics_.end()) { + metrics_.erase(it); + } + } +} + +std::shared_ptr<BvarMetric> BvarMetricEntity::get_metric(const std::string& name) { + { + std::lock_guard<bthread::Mutex> l(mutex_); + auto it = metrics_.find(name); + if (it == metrics_.end()) { + return nullptr; + } + return it->second; + } +} + +void BvarMetricEntity::register_hook(const std::string& name, const std::function<void()>& hook) { + std::lock_guard<bthread::Mutex> l(mutex_); +#ifndef BE_TEST + DCHECK(hooks_.find(name) == hooks_.end()) << "hook is already exist! " << entity_name_ << ":" << name; +#endif + hooks_.emplace(name, hook); +} + +void BvarMetricEntity::deregister_hook(const std::string& name) { + std::lock_guard<bthread::Mutex> l(mutex_); + hooks_.erase(name); +} + +void BvarMetricEntity::trigger_hook_unlocked(bool force) const { + // When 'enable_metric_calculator' is true, hooks will be triggered by a background thread, + // see 'calculate_metrics' in daemon.cpp for more details. + if (!force && config::enable_metric_calculator) { + return; + } + for (const auto& hook : hooks_) { + hook.second(); + } +} + +void BvarMetricRegistry::register_entity(BvarMetricEntity entity) {} + +void BvarMetricRegistry::trigger_all_hooks(bool force) { + std::lock_guard<bthread::Mutex> l(mutex_); + for (const auto& entity : entities_) { + std::lock_guard<bthread::Mutex> l(entity.first->mutex_); + entity.first->trigger_hook_unlocked(force); + } +} + +const std::string BvarMetricRegistry::to_prometheus(bool with_tablet_metrics) { + BvarEntityMetricsByType entity_metrics_by_types; + std::lock_guard<bthread::Mutex> l(mutex_); + + for (auto& entity : entities_) { + if (entity.first->type_ == BvarMetricEntityType::kTablet && !with_tablet_metrics) { + continue; + } + std::lock_guard<bthread::Mutex> l(entity->mutex_); + entity.first->trigger_hook_unlocked(false); + for(const auto& metric : entity.first->metrics_){ + std::pair<BvarMetricEntity*, BvarMetric*> new_elem = + std::make_pair(entity.first.get(), metric.second.get()); + auto found = entity_metrics_by_types.find(metric.second.get()); + if(found == entity_metrics_by_types.end()) { + entity_metrics_by_typess.emplace( + metric.second.get(), std::vector<std::pair<BvarMetricEntity*, BvarMetric*>>({new_elem})); + } else { + found->second.emplace_back(new_elem); + } + } + } + + // Output + std::stringstream ss; + std::string last_group_name; + for (const auto& entity_metrics_by_type : entity_metrics_by_types) { + + const auto metric = entity_metrics_by_type.first; + std::string display_name = metric->combine_name(name_); + + if (last_group_name.empty() || + last_group_name != metric->group_name_) { + ss << "# TYPE " << display_name << " " << metric->type_ << "\n"; // metric TYPE line + } + + last_group_name = metric->group_name_; + + for (const auto& entity_metric : entity_metrics_by_type.second) { + ss << entity_metric.second->to_prometheus(display_name, // metric key-value line + entity_metric.first->lables_); + } + } + + return ss.str(); +} + +const std::string BvarMetricRegistry::to_json(bool with_tablet_metrics) { Review Comment: warning: return type 'const int' is 'const'-qualified at the top level, which may reduce code readability without improving const correctness [readability-const-return-type] ```suggestion std::string BvarMetricRegistry::to_json(bool with_tablet_metrics) { ``` ########## be/src/util/bvar_metrics.h: ########## @@ -0,0 +1,236 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +#pragma once + +#include <bthread/mutex.h> +#include <bvar/latency_recorder.h> +#include <bvar/reducer.h> +#include <bvar/status.h> +#include <rapidjson/document.h> +#include <rapidjson/rapidjson.h> +#include <stddef.h> +#include <stdint.h> + +#include <atomic> +#include <functional> +#include <map> +#include <memory> +#include <mutex> +#include <sstream> +#include <string> +#include <unordered_map> +#include <utility> +#include <vector> + +#include "util/core_local.h" + +namespace doris { + +namespace rj = RAPIDJSON_NAMESPACE; + +enum class BvarMetricType { COUNTER, GAUGE, HISTOGRAM, SUMMARY, UNTYPED }; + +enum class BvarMetricUnit { + NANOSECONDS, + MICROSECONDS, + MILLISECONDS, + SECONDS, + BYTES, + ROWS, + PERCENT, + REQUESTS, + OPERATIONS, + BLOCKS, + ROWSETS, + CONNECTIONS, + PACKETS, + NOUNIT, + FILESYSTEM +}; + +std::ostream& operator<<(std::ostream& os, BvarMetricType type); +const char* unit_name(BvarMetricUnit unit); + + +class BvarMetric { +public: + using Labels = std::unordered_map<std::string, std::string>; + BvarMetric() = default; + virtual ~BvarMetric() = default; + BvarMetric(BvarMetric&) = default; + BvarMetric(BvarMetricType type, BvarMetricUnit unit, std::string name, + std::string description = "", std::string group_name = "", Labels labels = Labels(), + bool is_core_metric = false) + : is_core_metric_(is_core_metric), + type_(type), + unit_(unit), + group_name_(group_name), + name_(name), + description_(description), + labels_(labels) {} + + std::string simple_name() const; + std::string combine_name(const std::string& registry_name) const; + virtual std::string to_prometheus(const std::string& registry_name, const Labels& entity_labels) const = 0; + virtual rj::Value to_json_value(rj::Document::AllocatorType& allocator) const = 0; + virtual value_string() const = 0; + +protected: + friend class MetricRegistry; + friend struct BvarMetircHash; + friend struct BvarMetricEqualTo; + + bool is_core_metric_; + + BvarMetricType type_; + BvarMetricUnit unit_; + + // use for expose + std::string group_name_; // prefix + std::string name_; + std::string description_; + + Labels labels_; +}; + +// For 'bvar_metrics' in BvarMetricEntity. +struct BvarMetircHash { + size_t operator()(const BvarMetric* metric) const { + return std::hash<std::string>()(metric->group_name_.empty() + ? metric->name_ + : metric->group_name_); + } +}; + +struct BvarMetricEqualTo { + bool operator()(const BvarMetric* first, const BvarMetric* second) const { + return first->group_name_ == second->group_name_ && first->name_ == second->name_; + } +}; + +// bvar::Adder which support the operation of commutative and associative laws +template <typename T> +class BvarAdderMetric : public BvarMetric { +public: + BvarAdderMetric(BvarMetricType type, BvarMetricUnit unit, std::string name, + std::string description = "", std::string group_name = "", + Labels labels = Labels(), bool is_core_metric = false) + : BvarMetric(type, unit, name, description, group_name, labels, is_core_metric) { + //construct without expose information, just use bvar + adder_ = std::make_shared<bvar::Adder<T>>(); + } + ~BvarAdderMetric() override = default; + + T get_value() const; + void increment(T value); + void set_value(T value); + void reset() { adder_->reset(); } + + std::string to_prometheus(const std::string& registry_name, const Labels& entity_labels) const override; + rj::Value to_json_value(rj::Document::AllocatorType& allocator) const override { + return rj::Value(get_value()); + } + std::string value_string() const; + +private: + std::shared_ptr<bvar::Adder<T>> adder_; +}; + +enum class BvarMetricEntityType { kServer, kTablet }; + +class BvarMetricEntity { +public: + using Labels = std::unordered_map<std::string, std::string>; + BvarMetricEntity() = default; + BvarMetricEntity(std::string entity_name, BvarMetricEntityType type, const Labels& labels) + : name_(entity_name), type_(type), lables_(labels) {} + BvarMetricEntity(const BvarMetricEntity& entity) + : name_(entity.name_), type_(entity.type_), metrics_(entity.metrics_), lables_(entity.lables_) {} + + template <typename T> + void register_metric(const std::string& name, T metric); + + void deregister_metric(const std::string& name); + + std::shared_ptr<BvarMetric> get_metric(const std::string& name); + + // Register a hook, this hook will called before get_metric is called + void register_hook(const std::string& name, const std::function<void()>& hook); + void deregister_hook(const std::string& name); + void trigger_hook_unlocked(bool force) const; + +private: + friend class BvarMetricRegistry; + friend struct BvarMetricEntityHash; + friend struct BvarMetricEntityEqualTo; + + std::string name_; + + BvarMetricEntityType type_; + + Labels lables_; + + std::unordered_map<std::string, std::shared_ptr<BvarMetric>> metrics_; + + std::map<std::string, std::function<void()>> hooks_; + + bthread::Mutex mutex_; +}; + +struct BvarMetricEntityHash { + size_t operator()(const std::shared_ptr<BvarMetricEntity> metric_entity) const { + return std::hash<std::string>()(metric_entity->name_); + } +}; + +struct BvarMetricEntityEqualTo { + bool operator()(const std::shared_ptr<BvarMetricEntity> first, + const std::shared_ptr<BvarMetricEntity> second) const { + return first->type_ == second->type_ && first->name_ == second->name_ && + first->lables_ == second->lables_; + } +}; + +using BvarEntityMetricsByType = + std::unordered_map<const BvarMetric*, std::vector<std::pair<BvarMetricEntity*, BvarMetric*>>, + BvarMetircHash, BvarMetricEqualTo>; + +class BvarMetricRegistry { +public: + BvarMetricRegistry(const std::string name) : name_(name) {} + ~BvarMetricRegistry() {} Review Comment: warning: use '= default' to define a trivial destructor [modernize-use-equals-default] ```suggestion ~BvarMetricRegistry() = default; ``` -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org For queries about this service, please contact Infrastructure at: us...@infra.apache.org --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org For additional commands, e-mail: commits-h...@doris.apache.org