Procházet zdrojové kódy

Merge pull request #361 from holmes1412/master

Recent update for RPCModule
xiehan před 2 měsíci
rodič
revize
c5d27e03f6

+ 1 - 1
src/module/rpc_filter.h

@@ -102,7 +102,7 @@ public:
 		return true;
 	}
 
-	const std::string raw_var_name(const std::string& name) const
+	static const std::string raw_var_name(const std::string& name)
 	{
 		size_t pos = name.find("::");
 		if (pos != std::string::npos)

+ 127 - 17
src/module/rpc_metrics_filter.cc

@@ -116,6 +116,12 @@ SummaryVar *RPCMetricsFilter::summary(const std::string& name)
 	return RPCVarFactory::summary(name);
 }
 
+HistogramCounterVar *RPCMetricsFilter::histogram_counter(const std::string &name)
+{
+	std::string var_name = this->get_name() + name;
+	return RPCVarFactory::histogram_counter(var_name);
+}
+
 GaugeVar *RPCMetricsFilter::create_gauge(const std::string& str,
 										 const std::string& help)
 {
@@ -249,6 +255,32 @@ SummaryVar *RPCMetricsFilter::create_summary(const std::string& str,
 	return summary;
 }
 
+HistogramCounterVar *RPCMetricsFilter::create_histogram_counter(const std::string &str,
+																const std::string &help,
+																const std::vector<double> &bucket)
+{
+	if (RPCVarFactory::check_name_format(str) == false)
+	{
+		errno = EINVAL;
+		return NULL;
+	}
+
+	std::string name = this->get_name() + str;
+	this->mutex.lock();
+	const auto it = var_names.insert(name);
+	this->mutex.unlock();
+
+	if (!it.second)
+	{
+		errno = EEXIST;
+		return NULL;
+	}
+
+	HistogramCounterVar *hc = new HistogramCounterVar(name, help, bucket);
+	RPCVarLocal::get_instance()->add(name, hc);
+	return hc;
+}
+
 void RPCMetricsFilter::reduce(std::unordered_map<std::string, RPCVar *>& out)
 {
 	std::unordered_map<std::string, RPCVar *>::iterator it;
@@ -274,6 +306,26 @@ void RPCMetricsFilter::reduce(std::unordered_map<std::string, RPCVar *>& out)
 	global_var->mutex.unlock();
 }
 
+void RPCMetricsFilter::reset()
+{
+	std::unordered_map<std::string, RPCVar *>::iterator it;
+	RPCVarGlobal *global_var = RPCVarGlobal::get_instance();
+
+	global_var->mutex.lock();
+	for (RPCVarLocal *local : global_var->local_vars)
+	{
+		local->mutex.lock();
+		for (it = local->vars.begin(); it != local->vars.end(); it++)
+		{
+			if (this->var_names.find(it->first) == this->var_names.end())
+				continue;
+			it->second->reset();
+		}
+		local->mutex.unlock();
+	}
+	global_var->mutex.unlock();
+}
+
 RPCMetricsPull::RPCMetricsPull() :
 	collector(this->report_output),
 	server(std::bind(&RPCMetricsPull::pull, this, std::placeholders::_1))
@@ -557,6 +609,7 @@ bool RPCMetricsOTel::expose(google::protobuf::Message *msg)
 	std::unordered_map<std::string, RPCVar *> tmp;
 	std::unordered_map<std::string, RPCVar *>::iterator it;
 	ScopeMetrics *metrics;
+	Histogram *report_histogram;
 	metrics = static_cast<ScopeMetrics *>(msg);
 
 	this->reduce(tmp);
@@ -569,7 +622,7 @@ bool RPCMetricsOTel::expose(google::protobuf::Message *msg)
 		Metric *m = metrics->add_metrics();
 		google::protobuf::Message *current_var;
 
-		m->set_name(this->raw_var_name(var->get_name()));
+		m->set_name(RPCFilter::raw_var_name(var->get_name()));
 		m->set_description(var->get_help());
 
 		switch(var->get_type())
@@ -584,19 +637,25 @@ bool RPCMetricsOTel::expose(google::protobuf::Message *msg)
 			this->collector.collect_counter(var, current_var);
 			break;
 		case VAR_HISTOGRAM:
-			current_var = m->mutable_histogram();
+			report_histogram = m->mutable_histogram();
+			current_var = report_histogram->add_data_points();
 			this->collector.collect_histogram(var, current_var);
 			break;
 		case VAR_SUMMARY:
 			current_var = m->mutable_summary();
 			this->collector.collect_summary(var, current_var);
 			break;
+		case VAR_HISTOGRAM_COUNTER:
+			// add multiple metrics inside
+			this->collector.collect_histogram_counter(var, metrics);
+			break;
 		}
 	}
 
 	for (it = tmp.begin(); it != tmp.end(); it++)
 		delete it->second;
 
+	this->reset(); // reset by report interval
 	return true;
 }
 
@@ -618,7 +677,7 @@ void RPCMetricsOTel::Collector::collect_counter(RPCVar *var,
 	CounterVar *counter = (CounterVar *)var;
 
 	std::unordered_map<std::string, GaugeVar *> *data;
-	data = (std::unordered_map<std::string, GaugeVar *> *)counter->get_data();
+	data = (std::unordered_map<std::string, GaugeVar *> *)counter->get_map();
 
 	for (auto it = data->begin(); it != data->end(); it++)
 		this->collect_counter_each(it->first, it->second->get(), msg);
@@ -661,22 +720,25 @@ void RPCMetricsOTel::Collector::collect_counter_each(const std::string& label,
 {
 	Sum *report_sum = static_cast<Sum *>(msg);
 	NumberDataPoint *data_points = report_sum->add_data_points();
-	std::map<std::string, LABEL_MAP *>::iterator it = this->label_map.find(label);
+	std::map<std::string, LABEL_MAP *>::iterator it;
 	std::string key;
 	std::string value;
 
-	if (it == this->label_map.end())
+	if (!label.empty())
 	{
-		this->add_counter_label(label);
-		it = this->label_map.find(label);
-	}
+		if (it == this->label_map.end())
+		{
+			this->add_counter_label(label);
+			it = this->label_map.find(label);
+		}
 
-	for (const auto& kv : *(it->second))
-	{
-		KeyValue *attribute = data_points->add_attributes();
-		attribute->set_key(kv.first);
-		AnyValue *value = attribute->mutable_value();
-		value->set_string_value(kv.second);
+		for (const auto& kv : *(it->second))
+		{
+			KeyValue *attribute = data_points->add_attributes();
+			attribute->set_key(kv.first);
+			AnyValue *value = attribute->mutable_value();
+			value->set_string_value(kv.second);
+		}
 	}
 
 	data_points->set_as_double(data);
@@ -687,13 +749,11 @@ void RPCMetricsOTel::Collector::collect_histogram(RPCVar *var,
 												  google::protobuf::Message *msg)
 {
 	HistogramVar *histogram = (HistogramVar *)var;
-	Histogram *report_histogram = static_cast<Histogram *>(msg);
+	HistogramDataPoint *data_points = static_cast<HistogramDataPoint *>(msg);
 
 	const std::vector<size_t> *bucket_counts = histogram->get_bucket_counts();
 	const std::vector<double> *bucket_boundaries = histogram->get_bucket_boundaries();
 
-	HistogramDataPoint *data_points = report_histogram->add_data_points();
-
 	// begin
 	data_points->set_time_unix_nano(this->current_timestamp_nano);
 
@@ -763,5 +823,55 @@ void RPCMetricsOTel::Collector::collect_summary_each(double quantile,
 	vaq->set_value(quantile_out);
 }
 
+void RPCMetricsOTel::Collector::collect_histogram_counter(RPCVar *var,
+														  google::protobuf::Message *msg)
+{
+	HistogramCounterVar *hc = (HistogramCounterVar *)var;
+	ScopeMetrics *metrics = static_cast<ScopeMetrics *>(msg);
+
+	const std::unordered_map<std::string, HistogramVar *> *data;
+	data = static_cast<const std::unordered_map<std::string,
+										HistogramVar *> *>(hc->get_map());
+
+	std::map<std::string, LABEL_MAP *>::iterator m_it;
+	std::string key;
+	std::string value;
+
+	Metric *m;
+	Histogram *report_histogram;
+	HistogramDataPoint *data_points;
+	std::string label;
+
+	for (auto it = data->begin(); it != data->end(); it++)
+	{
+		m = metrics->add_metrics();
+		m->set_name(RPCFilter::raw_var_name(hc->get_name()));
+		m->set_description(hc->get_help());
+		report_histogram = m->mutable_histogram();
+		report_histogram->set_aggregation_temporality(
+					AggregationTemporality::AGGREGATION_TEMPORALITY_DELTA);
+		data_points = report_histogram->add_data_points();
+
+		label = it->first;
+
+		m_it = this->label_map.find(label);
+		if (m_it == this->label_map.end())
+		{
+			this->add_counter_label(label);
+			m_it = this->label_map.find(label);
+		}
+
+		for (const auto &kv : *(m_it->second))
+		{
+			KeyValue *attribute = data_points->add_attributes();
+			attribute->set_key(kv.first);
+			AnyValue *value = attribute->mutable_value();
+			value->set_string_value(kv.second);
+		}
+
+		this->collect_histogram(it->second, data_points);
+	}
+}
+
 } // end namespace srpc
 

+ 16 - 4
src/module/rpc_metrics_filter.h

@@ -57,11 +57,16 @@ public:
 							   const std::vector<struct Quantile>& quantile,
 							   const std::chrono::milliseconds max_age,
 							   int age_bucket);
+
+	HistogramCounterVar *create_histogram_counter(const std::string &name,
+												  const std::string &help,
+												  const std::vector<double> &bucket);
 	// thread local api
 	GaugeVar *gauge(const std::string& name);
 	CounterVar *counter(const std::string& name);
 	HistogramVar *histogram(const std::string& name);
 	SummaryVar *summary(const std::string& name);
+	HistogramCounterVar *histogram_counter(const std::string &name);
 
 	// filter api
 	bool client_end(SubTask *task, RPCModuleData& data) override;
@@ -73,6 +78,7 @@ public:
 
 protected:
 	void reduce(std::unordered_map<std::string, RPCVar *>& out);
+	void reset();
 
 protected:
 	std::mutex mutex;
@@ -219,12 +225,16 @@ private:
 		// new api : fill var into msg
 		void collect_gauge(RPCVar *gauge, google::protobuf::Message *msg);
 		void collect_counter(RPCVar *counter, google::protobuf::Message *msg);
-		void collect_histogram(RPCVar *histogram, google::protobuf::Message *msg);
+		void collect_histogram(RPCVar *histogram,
+							   google::protobuf::Message *msg);
 		void collect_summary(RPCVar *summary, google::protobuf::Message *msg);
+		void collect_histogram_counter(RPCVar *histogram_counter,
+									   google::protobuf::Message *msg);
 
 		void collect_counter_each(const std::string &label, double data,
 								  google::protobuf::Message *msg);
-		void collect_histogram_each(double bucket_boudary, size_t current_count,
+		void collect_histogram_each(double bucket_boudary,
+									size_t current_count,
 									google::protobuf::Message *msg);
 		void collect_summary_each(double quantile, double quantile_out,
 								  google::protobuf::Message *msg);
@@ -237,12 +247,14 @@ private:
 		void collect_histogram_begin(RPCVar *histogram) override {}
 		void collect_histogram_each(RPCVar *histogram, double bucket_boudary,
 									size_t current_count) override {}
-		void collect_histogram_end(RPCVar *histogram, double sum, size_t count) override{}
+		void collect_histogram_end(RPCVar *histogram, double sum,
+								   size_t count) override{}
 
 		void collect_summary_begin(RPCVar *summary) override {}
 		void collect_summary_each(RPCVar *summary, double quantile,
 								  double quantile_out) override {}
-		void collect_summary_end(RPCVar *summary, double sum, size_t count) override {}
+		void collect_summary_end(RPCVar *summary, double sum,
+								 size_t count) override {}
 
 	private:
 		void add_counter_label(const std::string& label);

+ 170 - 23
src/var/rpc_var.cc

@@ -24,6 +24,19 @@
 namespace srpc
 {
 
+static bool label_to_str(const std::map<std::string, std::string>& labels, std::string& str)
+{
+	for (auto it = labels.begin(); it != labels.end(); it++)
+	{
+		if (it != labels.begin())
+			str += ",";
+		//TODO: check label name regex is "[a-zA-Z_:][a-zA-Z0-9_:]*"
+		str += it->first + "=\"" + it->second + "\"";
+	}
+
+	return true;
+}
+
 GaugeVar *RPCVarFactory::gauge(const std::string& name)
 {
 	return static_cast<GaugeVar *>(RPCVarFactory::var(name));
@@ -44,6 +57,11 @@ SummaryVar *RPCVarFactory::summary(const std::string& name)
 	return static_cast<SummaryVar *>(RPCVarFactory::var(name));
 }
 
+HistogramCounterVar *RPCVarFactory::histogram_counter(const std::string &name)
+{
+	return static_cast<HistogramCounterVar *>(RPCVarFactory::var(name));
+}
+
 RPCVar *RPCVarFactory::var(const std::string& name)
 {
 	RPCVar *var;
@@ -197,6 +215,12 @@ RPCVar *GaugeVar::create(bool with_data)
 	return var;
 }
 
+CounterVar::CounterVar(const std::string &name, const std::string &help)
+	: RPCVar(name, help, VAR_COUNTER)
+{
+	this->sum = 0;
+}
+
 CounterVar::~CounterVar()
 {
 	for (auto it = this->data.begin(); it != this->data.end(); it++)
@@ -204,7 +228,7 @@ CounterVar::~CounterVar()
 }
 
 // Caution :
-//    make sure local->mutex.lock() before CounterVar::create(true)
+//	make sure local->mutex.lock() before CounterVar::create(true)
 RPCVar *CounterVar::create(bool with_data)
 {
 	CounterVar *var = new CounterVar(this->name, this->help);
@@ -216,33 +240,22 @@ RPCVar *CounterVar::create(bool with_data)
 			var->data.insert(std::make_pair(it->first,
 							(GaugeVar *)it->second->create(true)));
 		}
+		var->sum = this->sum;
 	}
 
 	return var;
 }
 
-bool CounterVar::label_to_str(const LABEL_MAP& labels, std::string& str)
-{
-	for (auto it = labels.begin(); it != labels.end(); it++)
-	{
-		if (it != labels.begin())
-			str += ",";
-		//TODO: check label name regex is "[a-zA-Z_:][a-zA-Z0-9_:]*"
-		str += it->first + "=\"" + it->second + "\"";
-	}
-
-	return true;
-}
 
 // [deprecate]
-//    This cannot guarantee the GaugeVar still exists
-//    because global will counter->reset() and delete the internal GaugeVar
+//	This cannot guarantee the GaugeVar still exists
+//	because global will counter->reset() and delete the internal GaugeVar
 GaugeVar *CounterVar::add(const LABEL_MAP& labels)
 {
 	std::string label_str;
 	GaugeVar *var;
 
-	if (!this->label_to_str(labels, label_str))
+	if (!label_to_str(labels, label_str))
 		return NULL;
 
 	auto it = this->data.find(label_str);
@@ -263,7 +276,7 @@ void CounterVar::increase(const LABEL_MAP& labels)
 	std::string label_str;
 	GaugeVar *var;
 
-	if (!this->label_to_str(labels, label_str))
+	if (!label_to_str(labels, label_str))
 		return;
 
 	RPCVarLocal *local = RPCVarLocal::get_instance();
@@ -285,12 +298,43 @@ void CounterVar::increase(const LABEL_MAP& labels)
 	return;
 }
 
+void CounterVar::increase(const LABEL_MAP& labels, double value)
+{
+	std::string label_str;
+	GaugeVar *var;
+
+	if (!label_to_str(labels, label_str))
+		return;
+
+	RPCVarLocal *local = RPCVarLocal::get_instance();
+	local->mutex.lock();
+	auto it = this->data.find(label_str);
+
+	if (it == this->data.end())
+	{
+		var = new GaugeVar(label_str, "");
+		this->data.insert(std::make_pair(label_str, var));
+	}
+	else
+	{
+		var = it->second;
+	}
+
+	double current = var->get();
+	var->set(current + value);
+	this->sum += value;
+	local->mutex.unlock();
+
+	return;
+}
+
 // Caution :
-//    make sure local->mutex.lock() before CounterVar::reduce()
+//	make sure local->mutex.lock() before CounterVar::reduce()
 bool CounterVar::reduce(const void *ptr, size_t)
 {
-	std::unordered_map<std::string, GaugeVar *> *data;
-	data = (std::unordered_map<std::string, GaugeVar *> *)ptr;
+	const CounterVar *counter = (const CounterVar *)ptr;
+	const std::unordered_map<std::string, GaugeVar *> *data;
+	data = counter->get_map();
 
 	for (auto it = data->begin(); it != data->end(); it++)
 	{
@@ -305,6 +349,7 @@ bool CounterVar::reduce(const void *ptr, size_t)
 			my_it->second->reduce(it->second->get_data(),
 								  it->second->get_size());
 	}
+	this->sum += counter->get_sum();
 
 	return true;
 }
@@ -402,17 +447,20 @@ void HistogramVar::collect(RPCVarCollector *collector)
 	collector->collect_histogram_begin(this);
 	for (; i < this->bucket_boundaries.size(); i++)
 	{
-		current += this->bucket_counts[i];
+		// current += this->bucket_counts[i];
+		current = this->bucket_counts[i];
 		collector->collect_histogram_each(this, this->bucket_boundaries[i],
 										  current);
 	}
 
-	current += this->bucket_counts[i];
+	// current += this->bucket_counts[i];
+	current = this->bucket_counts[i];
 	collector->collect_histogram_each(this, DBL_MAX, current);
 	collector->collect_histogram_end(this, this->sum, this->count);
 }
 
-void HistogramVar::reset() {
+void HistogramVar::reset()
+{
 	for (size_t i = 0; i < this->bucket_boundaries.size(); i++)
 		this->bucket_counts[i] = 0;
 	this->sum = 0;
@@ -618,5 +666,104 @@ RPCVar *TimedGaugeVar::create(bool with_data)
 	return var;
 }
 
+HistogramCounterVar::HistogramCounterVar(const std::string &name,
+										 const std::string &help,
+										 const std::vector<double> &bucket)
+	: RPCVar(name, help, VAR_HISTOGRAM_COUNTER),
+	  bucket(bucket)
+{
+}
+
+HistogramCounterVar::~HistogramCounterVar()
+{
+	for (auto it = this->data.begin(); it != this->data.end(); it++)
+		delete it->second;
+}
+
+//  Caution :
+//	 make sure local->mutex.lock() before HistogramCounterVar::create(true)
+RPCVar *HistogramCounterVar::create(bool with_data)
+{
+	HistogramCounterVar *var = new HistogramCounterVar(this->name, this->help,
+													   this->bucket);
+
+	if (with_data)
+	{
+		for (auto it = this->data.begin(); it != this->data.end(); it++)
+		{
+			var->data.insert(std::make_pair(it->first,
+									(HistogramVar *)it->second->create(true)));
+		}
+	}
+
+	return var;
+}
+
+void HistogramCounterVar::observe(const LABEL_MAP &labels, double value)
+{
+	std::string label_str;
+	HistogramVar *var;
+
+	if (!label_to_str(labels, label_str))
+		return;
+
+	RPCVarLocal *local = RPCVarLocal::get_instance();
+	local->mutex.lock();
+	auto it = this->data.find(label_str);
+
+	if (it == this->data.end())
+	{
+		var = new HistogramVar(label_str, "", this->bucket);
+		this->data.insert(std::make_pair(label_str, var));
+	}
+	else
+	{
+		var = it->second;
+	}
+
+	var->observe(value);
+	local->mutex.unlock();
+
+	return;
+}
+
+//  Caution :
+//	   make sure local->mutex.lock() before HistogramCounterVar::reduce()
+bool HistogramCounterVar::reduce(const void *ptr, size_t)
+{
+	const HistogramCounterVar *counter = (const HistogramCounterVar *)ptr;
+	const std::unordered_map<std::string, HistogramVar *> *data;
+	data = counter->get_map();
+
+	for (auto it = data->begin(); it != data->end(); it++) {
+		auto my_it = this->data.find(it->first);
+
+		if (my_it == this->data.end()) {
+			HistogramVar *var = (HistogramVar *)it->second->create(true);
+			this->data.insert(std::make_pair(it->first, var));
+		}
+		else
+		{
+			my_it->second->reduce(it->second->get_data(),
+								  it->second->get_size());
+		}
+	}
+
+	return true;
+}
+
+// TODO: deprecated api available for Prometheus.
+void HistogramCounterVar::collect(RPCVarCollector *collector)
+{
+}
+
+void HistogramCounterVar::reset()
+{
+	for (auto it = this->data.begin(); it != this->data.end(); it++)
+		delete it->second;
+
+	this->data.clear();
+}
+
 } // end namespace srpc
 

+ 50 - 16
src/var/rpc_var.h

@@ -35,13 +35,15 @@ class GaugeVar;
 class CounterVar;
 class HistogramVar;
 class SummaryVar;
+class HistogramCounterVar;
 
 enum RPCVarType
 {
-	VAR_GAUGE		=	0,
-	VAR_COUNTER		=	1,
-	VAR_HISTOGRAM	=	2,
-	VAR_SUMMARY		=	3
+	VAR_GAUGE				=	0,
+	VAR_COUNTER				=	1,
+	VAR_HISTOGRAM			=	2,
+	VAR_SUMMARY				=	3,
+	VAR_HISTOGRAM_COUNTER	=	4
 };
 
 static std::string type_string(RPCVarType type)
@@ -53,6 +55,7 @@ static std::string type_string(RPCVarType type)
 	case VAR_COUNTER:
 		return "counter";
 	case VAR_HISTOGRAM:
+	case VAR_HISTOGRAM_COUNTER:
 		return "histogram";
 	case VAR_SUMMARY:
 		return "summary";
@@ -74,6 +77,8 @@ public:
 
 	static SummaryVar *summary(const std::string& name);
 
+	static HistogramCounterVar *histogram_counter(const std::string &name);
+
 	static RPCVar *var(const std::string& name);
 	static bool check_name_format(const std::string& name);
 };
@@ -111,7 +116,6 @@ public:
 	std::mutex mutex;
 	std::vector<RPCVarLocal *> local_vars;
 	bool finished;
-//	friend class RPCVarFactory;
 };
 
 class RPCVarLocal
@@ -146,7 +150,6 @@ public:
 	std::mutex mutex;
 	std::unordered_map<std::string, RPCVar *> vars;
 	friend class RPCVarGlobal;
-//	friend class RPCVarFactory;
 };
 
 class RPCVarCollector
@@ -250,28 +253,30 @@ public:
 	using LABEL_MAP = std::map<std::string, std::string>;
 	GaugeVar *add(const LABEL_MAP& labels);
 	void increase(const LABEL_MAP& labels);
+	void increase(const LABEL_MAP &labels, double value);
 
 	RPCVar *create(bool with_data) override;
 	bool reduce(const void *ptr, size_t sz) override;
 	void collect(RPCVarCollector *collector) override;
 
 	size_t get_size() const override { return this->data.size(); }
-	const void *get_data() override { return &this->data; }
-
-	static bool label_to_str(const LABEL_MAP& labels, std::string& str);
+	const void *get_data() override { return this; }
+	const std::unordered_map<std::string, GaugeVar *> *get_map() const
+	{
+		return &this->data;
+	}
+	double get_sum() const { return this->sum; }
+	void increase_sum(double value) { this->sum += value; }
 
 	void reset() override;
 
 public:
-	CounterVar(const std::string& name, const std::string& help) :
-		RPCVar(name, help, VAR_COUNTER)
-	{
-	}
-
-	~CounterVar();
+	CounterVar(const std::string &name, const std::string &help);
+	virtual ~CounterVar();
 
 private:
 	std::unordered_map<std::string, GaugeVar *> data;
+	double sum;
 };
 
 class HistogramVar : public RPCVar
@@ -332,7 +337,7 @@ public:
 		return &this->quantile_values;
 	}
 
-	void reset() override { /* no TimedSummary so no reset for Summary */}
+	void reset() override { /* TODO: incorrect if reset() by report interval */ }
 
 	const std::vector<struct Quantile>& get_quantiles() const
 	{
@@ -426,6 +431,35 @@ public:
 	RPCVar *create(bool with_data) override;
 };
 
+class HistogramCounterVar : public RPCVar
+{
+public:
+	using LABEL_MAP = std::map<std::string, std::string>;
+	void observe(const LABEL_MAP &labels, double value);
+
+	RPCVar *create(bool with_data) override;
+	bool reduce(const void *ptr, size_t sz) override;
+	void collect(RPCVarCollector *collector) override;
+
+	size_t get_size() const override { return this->data.size(); }
+	const void *get_data() override { return this; }
+	const std::unordered_map<std::string, HistogramVar *> *get_map() const
+	{
+		return &this->data;
+	}
+
+	void reset() override;
+
+public:
+	HistogramCounterVar(const std::string &name, const std::string &help,
+						const std::vector<double> &bucket);
+	virtual ~HistogramCounterVar();
+
+private:
+	std::unordered_map<std::string, HistogramVar *> data;
+	std::vector<double> bucket;
+};
+
 } // end namespace srpc
 
 #endif