// Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved. // // Licensed 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 #ifdef BCLOUD #include // FlatMap #include // DefaultSingletonTraits #include // BAIDU_SCOPED_LOCK #else #include // FlatMap #include // DefaultSingletonTraits #include // BAIDU_SCOPED_LOCK #endif #include // bvar #include #ifdef BCLOUD namespace butil = base; #endif namespace baidu { namespace paddle_serving { namespace predictor { static const char* WORKFLOW_METRIC_PREFIX = "workflow_"; static const char* STAGE_METRIC_PREFIX = "stage_"; static const char* OP_METRIC_PREFIX = "op_"; static const char* NAME_DELIMITER = "_"; typedef ::bvar::Window<::bvar::Adder> AdderWindow; typedef ::bvar::Window<::bvar::IntRecorder> RecorderWindow; class AdderWindowMetric { public: AdderWindowMetric() : sum_window(&sum, ::bvar::FLAGS_bvar_dump_interval) {} explicit AdderWindowMetric(const std::string& name) : sum_window( name + "_sum_window", &sum, ::bvar::FLAGS_bvar_dump_interval) {} inline AdderWindowMetric& operator<<(int count) { sum << count; return *this; } public: ::bvar::Adder sum; AdderWindow sum_window; }; static float g_get_rate(void* arg); class RateBaseMetric { public: explicit RateBaseMetric(const std::string& name) : rate_value(name + "_rate", g_get_rate, this) {} void update_lhs(int count) { lhs.sum << count; } void update_rhs(int count) { rhs.sum << count; } public: ::bvar::PassiveStatus rate_value; AdderWindowMetric lhs; AdderWindowMetric rhs; }; static float g_get_rate(void* arg) { RateBaseMetric* rate_metric = static_cast(arg); if (rate_metric->rhs.sum_window.get_value() <= 0) { return 0; } return rate_metric->lhs.sum_window.get_value() * 100 / static_cast(rate_metric->rhs.sum_window.get_value()); } // 计算平均值时取整 class AvgWindowMetric { public: AvgWindowMetric() : avg_window(&avg, ::bvar::FLAGS_bvar_dump_interval) {} explicit AvgWindowMetric(const std::string& name) : avg_window( name + "_avg_window", &avg, ::bvar::FLAGS_bvar_dump_interval) {} inline AvgWindowMetric& operator<<(int64_t value) { avg << value; return *this; } public: ::bvar::IntRecorder avg; RecorderWindow avg_window; }; // 计算平均值时不取整 static double g_get_double_avg(void* arg); class AvgDoubleWindowMetric { public: explicit AvgDoubleWindowMetric(const std::string& name) : avg_value(name + "_avg_double_window", g_get_double_avg, this) {} inline AvgDoubleWindowMetric& operator<<(int64_t value) { recorder << value; return *this; } public: ::bvar::PassiveStatus avg_value; AvgWindowMetric recorder; }; static double g_get_double_avg(void* arg) { AvgDoubleWindowMetric* avg_metric = static_cast(arg); return avg_metric->recorder.avg_window.get_value().get_average_double(); } class PredictorMetric { public: static PredictorMetric* GetInstance(); ~PredictorMetric() { for (::butil::FlatMap::iterator iter = latency_recorder_map.begin(); iter != latency_recorder_map.end(); ++iter) { delete iter->second; } for (::butil::FlatMap::iterator iter = adder_window_map.begin(); iter != adder_window_map.end(); ++iter) { delete iter->second; } for (::butil::FlatMap::iterator iter = avg_window_map.begin(); iter != avg_window_map.end(); ++iter) { delete iter->second; } for (::butil::FlatMap::iterator iter = avg_double_window_map.begin(); iter != avg_double_window_map.end(); ++iter) { delete iter->second; } for (::butil::FlatMap::iterator iter = rate_map.begin(); iter != rate_map.end(); ++iter) { delete iter->second; } } void regist_latency_metric(const std::string& metric_name) { { BAIDU_SCOPED_LOCK(_mutex); LOG(INFO) << "try to regist latency metric[" << metric_name << "]."; if (latency_recorder_map.seek(metric_name) == NULL) { bvar::LatencyRecorder* metric = new (std::nothrow) bvar::LatencyRecorder(metric_name); latency_recorder_map.insert(metric_name, metric); LOG(INFO) << "succ to regist latency metric[" << metric_name << "]."; } } } void regist_adder_window_metric(const std::string& metric_name) { { BAIDU_SCOPED_LOCK(_mutex); LOG(INFO) << "try to regist adder window metric[" << metric_name << "]."; if (adder_window_map.seek(metric_name) == NULL) { AdderWindowMetric* metric = new (std::nothrow) AdderWindowMetric(metric_name); adder_window_map.insert(metric_name, metric); LOG(INFO) << "succ to regist adder window metric[" << metric_name << "]."; } } } void regist_avg_window_metric(const std::string& metric_name) { { BAIDU_SCOPED_LOCK(_mutex); LOG(INFO) << "try to regist avg window metric[" << metric_name << "]."; if (avg_window_map.seek(metric_name) == NULL) { AvgWindowMetric* metric = new (std::nothrow) AvgWindowMetric(metric_name); avg_window_map.insert(metric_name, metric); LOG(INFO) << "succ to regist avg window metric[" << metric_name << "]."; } } } void regist_avg_double_window_metric(const std::string& metric_name) { { BAIDU_SCOPED_LOCK(_mutex); LOG(INFO) << "try to regist avg double window metric[" << metric_name << "]."; if (avg_double_window_map.seek(metric_name) == NULL) { AvgDoubleWindowMetric* metric = new (std::nothrow) AvgDoubleWindowMetric(metric_name); avg_double_window_map.insert(metric_name, metric); LOG(INFO) << "succ to regist avg double window metric[" << metric_name << "]."; } } } void regist_rate_metric(const std::string& metric_name) { { BAIDU_SCOPED_LOCK(_mutex); LOG(INFO) << "try to regist rate metric[" << metric_name << "]."; if (rate_map.seek(metric_name) == NULL) { RateBaseMetric* metric = new (std::nothrow) RateBaseMetric(metric_name); rate_map.insert(metric_name, metric); LOG(INFO) << "succ to regist rate metric[" << metric_name << "]."; } } } inline void update_latency_metric(const std::string& metric_name, int64_t latency) { bvar::LatencyRecorder** metric = latency_recorder_map.seek(metric_name); if (metric != NULL) { **metric << latency; } else { LOG(ERROR) << "impossible, check if you regist[" << metric_name << "]."; } } inline void update_adder_window_metric(const std::string& metric_name, int count) { AdderWindowMetric** metric = adder_window_map.seek(metric_name); if (metric != NULL) { **metric << count; } else { LOG(ERROR) << "impossible, check if you regist[" << metric_name << "]."; } } inline void update_avg_window_metric(const std::string& metric_name, int64_t value) { AvgWindowMetric** metric = avg_window_map.seek(metric_name); if (metric != NULL) { **metric << value; } else { LOG(ERROR) << "impossible, check if you regist[" << metric_name << "]."; } } inline void update_avg_double_window_metric(const std::string& metric_name, int64_t value) { AvgDoubleWindowMetric** metric = avg_double_window_map.seek(metric_name); if (metric != NULL) { **metric << value; } else { LOG(ERROR) << "impossible, check if you regist[" << metric_name << "]."; } } inline void update_rate_metric_lhs(const std::string& name, int count) { RateBaseMetric** metric = rate_map.seek(name); if (metric != NULL) { (*metric)->update_lhs(count); } else { LOG(ERROR) << "impossible, check if you regist[" << name << "]."; } } inline void update_rate_metric_rhs(const std::string& name, int count) { RateBaseMetric** metric = rate_map.seek(name); if (metric != NULL) { (*metric)->update_rhs(count); } else { LOG(ERROR) << "impossible, check if you regist[" << name << "]."; } } private: PredictorMetric() : bucket_count(300) { latency_recorder_map.init(bucket_count); adder_window_map.init(bucket_count); avg_window_map.init(bucket_count); avg_double_window_map.init(bucket_count); rate_map.init(bucket_count); } private: const size_t bucket_count; ::butil::FlatMap latency_recorder_map; ::butil::FlatMap adder_window_map; ::butil::FlatMap avg_window_map; ::butil::FlatMap avg_double_window_map; ::butil::FlatMap rate_map; friend struct DefaultSingletonTraits; mutable butil::Mutex _mutex; DISALLOW_COPY_AND_ASSIGN(PredictorMetric); }; } // namespace predictor } // namespace paddle_serving } // namespace baidu