| // 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 "util/metrics.h" |
| |
| #include <string> |
| #include <vector> |
| #include <set> |
| #include <boost/algorithm/string/join.hpp> |
| #include <boost/accumulators/accumulators.hpp> |
| #include <boost/accumulators/statistics/count.hpp> |
| #include <boost/accumulators/statistics/mean.hpp> |
| #include <boost/accumulators/statistics/min.hpp> |
| #include <boost/accumulators/statistics/max.hpp> |
| #include <boost/accumulators/statistics/variance.hpp> |
| |
| namespace impala { |
| |
| /// Collection metrics are those whose values have more structure than simple |
| /// scalar types. Therefore they need specialised ToJson() methods, and |
| /// typically a specialised API for updating the values they contain. |
| |
| /// Metric whose value is a set of items |
| template <typename T> |
| class SetMetric : public Metric { |
| public: |
| static SetMetric* CreateAndRegister(MetricGroup* metrics, const std::string& key, |
| const std::set<T>& value) { |
| return metrics->RegisterMetric(new SetMetric(MetricDefs::Get(key), value)); |
| } |
| |
| SetMetric(const TMetricDef& def, const std::set<T>& value) |
| : Metric(def), value_(value) { |
| DCHECK_EQ(def.kind, TMetricKind::SET); |
| } |
| |
| /// Put an item in this set. |
| void Add(const T& item) { |
| boost::lock_guard<boost::mutex> l(lock_); |
| value_.insert(item); |
| } |
| |
| /// Remove an item from this set by value. |
| void Remove(const T& item) { |
| boost::lock_guard<boost::mutex> l(lock_); |
| value_.erase(item); |
| } |
| |
| /// Copy out value. |
| std::set<T> value() { |
| boost::lock_guard<boost::mutex> l(lock_); |
| return value_; |
| } |
| |
| void Reset() { value_.clear(); } |
| |
| virtual TMetricKind::type ToPrometheus( |
| std::string name, std::stringstream* val, std::stringstream* metric_kind) override { |
| // this is not supported type in prometheus, so ignore |
| return TMetricKind::SET; |
| } |
| |
| virtual void ToJson(rapidjson::Document* document, rapidjson::Value* value) override; |
| |
| virtual void ToLegacyJson(rapidjson::Document* document) override; |
| |
| virtual std::string ToHumanReadable() override; |
| |
| private: |
| /// Lock protecting the set |
| boost::mutex lock_; |
| |
| /// The set of items |
| std::set<T> value_; |
| }; |
| |
| /// Metric which accumulates min, max and mean of all values, plus a count of samples |
| /// seen. The output can be controlled by passing a bitmask as a template parameter to |
| /// indicate which values should be printed or returned as JSON. |
| /// |
| /// Printed output looks like: name: count: |
| /// 4, last: 0.0141, min: 4.546e-06, max: 0.0243, mean: 0.0336, stddev: 0.0336 |
| /// |
| /// After construction, all statistics are ill-defined, but count will be 0. The first call |
| /// to Update() will initialise all stats. |
| template <typename T, int StatsSelection> |
| class StatsMetric : public Metric { |
| public: |
| static StatsMetric* CreateAndRegister(MetricGroup* metrics, const std::string& key, |
| const std::string& arg = "") { |
| return metrics->RegisterMetric(new StatsMetric(MetricDefs::Get(key, arg))); |
| } |
| |
| StatsMetric(const TMetricDef& def) : Metric(def), unit_(def.units) { |
| DCHECK_EQ(def.kind, TMetricKind::STATS); |
| } |
| |
| void Update(const T& value) { |
| boost::lock_guard<boost::mutex> l(lock_); |
| value_ = value; |
| acc_(value); |
| } |
| |
| void Reset() { |
| boost::lock_guard<boost::mutex> l(lock_); |
| acc_ = Accumulator(); |
| } |
| |
| virtual TMetricKind::type ToPrometheus( |
| std::string name, std::stringstream* val, std::stringstream* metric_kind) override; |
| |
| virtual void ToJson(rapidjson::Document* document, rapidjson::Value* val) override; |
| |
| virtual void ToLegacyJson(rapidjson::Document* document) override; |
| |
| virtual std::string ToHumanReadable() override; |
| |
| private: |
| /// The units of the values captured in this metric, used when pretty-printing. |
| TUnit::type unit_; |
| |
| /// Lock protecting the value and the accumulator_set |
| boost::mutex lock_; |
| |
| /// The last value |
| T value_; |
| |
| /// The set of accumulators that update the statistics on each Update() |
| typedef boost::accumulators::accumulator_set<T, |
| boost::accumulators::features<boost::accumulators::tag::mean, |
| boost::accumulators::tag::count, |
| boost::accumulators::tag::min, |
| boost::accumulators::tag::max, |
| boost::accumulators::tag::variance>> Accumulator; |
| Accumulator acc_; |
| |
| }; |
| |
| // These template classes are instantiated in the .cc file. |
| extern template class SetMetric<int32_t>; |
| extern template class SetMetric<string>; |
| extern template class StatsMetric<uint64_t, StatsType::ALL>; |
| extern template class StatsMetric<double, StatsType::ALL>; |
| extern template class StatsMetric<uint64_t, StatsType::MEAN>; |
| extern template class StatsMetric<uint64_t, StatsType::MAX | StatsType::MEAN>; |
| } |