Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions core/benchmarks/registry_bench.cc
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,37 @@ static void BM_Registry_CreateCounter(benchmark::State& state) {
}
}
BENCHMARK(BM_Registry_CreateCounter)->Range(0, 4096);

static void BM_Registry_CreateCounter_WithLabelValues(benchmark::State& state) {
using prometheus::BuildCounter;
using prometheus::Counter;
using prometheus::Registry;
Registry registry;

const auto& labels = GenerateRandomLabels(state.range(0));
std::vector<std::string> label_names;
std::vector<std::string> label_values;
std::for_each(labels.begin(), labels.end(),
[&](const std::pair<std::string,std::string>& p){
label_names.push_back(p.first);
label_values.push_back(p.second);
});

auto& counter_family = BuildCounter()
.Labels(GenerateRandomLabels(10))
.Name("benchmark_counter")
.Help("")
.LabelNamesVec(label_names)
.Register(registry);

while (state.KeepRunning()) {
auto start = std::chrono::high_resolution_clock::now();
counter_family.WithLabelValues(label_values);
auto end = std::chrono::high_resolution_clock::now();

auto elapsed_seconds =
std::chrono::duration_cast<std::chrono::duration<double>>(end - start);
state.SetIterationTime(elapsed_seconds.count());
}
}
BENCHMARK(BM_Registry_CreateCounter_WithLabelValues)->Range(0, 4096);
24 changes: 24 additions & 0 deletions core/include/prometheus/counter.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "prometheus/detail/core_export.h"
#include "prometheus/gauge.h"
#include "prometheus/metric_type.h"
#include "prometheus/family.h"

namespace prometheus {

Expand Down Expand Up @@ -64,6 +65,22 @@ class PROMETHEUS_CPP_CORE_EXPORT Counter {
/// .Labels({{"key", "value"}})
/// .Register(*registry);
///
/// counter_family.Add({{"key2","value2"}}).Increment();
/// ...
/// \endcode
///
/// Example usage2:
///
/// \code
/// auto registry = std::make_shared<Registry>();
/// auto& counter_family = prometheus::BuildCounter()
/// .Name("some_name")
/// .Help("Additional description.")
/// .Labels({{"key", "value"}})
/// .LabelNamesVec({"key2","key3"})
/// .Register(*registry);
///
/// counter_family.WithLabelValues({"value2","value3"}).Increment();
/// ...
/// \endcode
///
Expand All @@ -74,9 +91,16 @@ class PROMETHEUS_CPP_CORE_EXPORT Counter {
/// - Help(const std::string&) to set an additional description.
/// - Label(const std::map<std::string, std::string>&) to assign a set of
/// key-value pairs (= labels) to the metric.
/// - LabelNamesVec(const std::vector<std::string&) to pre-affirmation pairs(= labels)'s
/// key; and you and use family.WithLabelValues({"value1","value1"}) to get the T;
/// note than: vector<names>.size() == vector<values>.size()
///
/// To finish the configuration of the Counter metric, register it with
/// Register(Registry&).
PROMETHEUS_CPP_CORE_EXPORT detail::Builder<Counter> BuildCounter();

/// \brief Specialization of WithLabelValues<Counter>.
PROMETHEUS_CPP_CORE_EXPORT template <>
Counter& Family<Counter>::WithLabelValues(const std::vector<std::string>& values);

} // namespace prometheus
31 changes: 30 additions & 1 deletion core/include/prometheus/detail/builder.h
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
#pragma once

#include <map>
#include <vector>
#include <string>
#include "prometheus/detail/ckms_quantiles.h"

// IWYU pragma: private
// IWYU pragma: no_include "prometheus/family.h"

namespace prometheus {

class Counter;
class Summary;
class Histogram;
template <typename T>
class Family; // IWYU pragma: keep
class Registry; // IWYU pragma: keep
Expand All @@ -18,15 +23,39 @@ template <typename T>
class Builder {
public:
Builder& Labels(const std::map<std::string, std::string>& labels);
Builder& LabelNamesVec(const std::vector<std::string>& labels);
Builder& Name(const std::string&);
Builder& Help(const std::string&);
Family<T>& Register(Registry&);

private:
template <typename U= T, typename = typename std::enable_if<std::is_same<U, Summary>::value,Summary>::type>
Builder& Quantiles(const std::vector<detail::CKMSQuantiles::Quantile>&);

template <typename U= T, typename = typename std::enable_if<std::is_same<U, Histogram>::value,Histogram>::type>
Builder& BucketBoundaries(const std::vector<double>&);

private:
std::map<std::string, std::string> labels_;
std::vector<std::string> variable_labels_;
std::vector<detail::CKMSQuantiles::Quantile> quantiles_;
std::vector<double> bucket_boundaries_;
std::string name_;
std::string help_;
};

template<typename T>
template<typename U, typename>
Builder<T>& Builder<T>::Quantiles(const std::vector<detail::CKMSQuantiles::Quantile>& quantiles) {
quantiles_ = quantiles;
return *this;
}

template<typename T>
template<typename U, typename>
Builder<T>& Builder<T>::BucketBoundaries(const std::vector<double>& bucket_boundaries) {
bucket_boundaries_ = bucket_boundaries;
return *this;
}

} // namespace detail
} // namespace prometheus
8 changes: 4 additions & 4 deletions core/include/prometheus/detail/ckms_quantiles.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ namespace detail {
class PROMETHEUS_CPP_CORE_EXPORT CKMSQuantiles {
public:
struct PROMETHEUS_CPP_CORE_EXPORT Quantile {
const double quantile;
const double error;
const double u;
const double v;
double quantile;
double error;
double u;
double v;

Quantile(double quantile, double error);
};
Expand Down
48 changes: 48 additions & 0 deletions core/include/prometheus/family.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
#include "prometheus/collectable.h"
#include "prometheus/detail/core_export.h"
#include "prometheus/detail/future_std.h"
#include "prometheus/detail/utils.h"
#include "prometheus/detail/ckms_quantiles.h"
#include "prometheus/metric_family.h"

// IWYU pragma: no_include "prometheus/counter.h"
Expand All @@ -21,6 +23,9 @@

namespace prometheus {

class Summary;
class Histogram;

/// \brief A metric of type T with a set of labeled dimensions.
///
/// One of Prometheus main feature is a multi-dimensional data model with time
Expand Down Expand Up @@ -91,6 +96,10 @@ class PROMETHEUS_CPP_CORE_EXPORT Family : public Collectable {
Family(const std::string& name, const std::string& help,
const std::map<std::string, std::string>& constant_labels);

Family(const std::string& name, const std::string& help,
const std::vector<std::string>& variable_labels,
const std::map<std::string, std::string>& constant_labels);

/// \brief Add a new dimensional data.
///
/// Each new set of labels adds a new dimensional data and is exposed in
Expand All @@ -112,6 +121,23 @@ class PROMETHEUS_CPP_CORE_EXPORT Family : public Collectable {
T& Add(const std::map<std::string, std::string>& labels, Args&&... args) {
return Add(labels, detail::make_unique<T>(args...));
}
/// \brief Add a new dimensional data.
/// different with Add, this method call only when build<T>.LavelVec(...)
/// is call before.
/// then this method call Add
T& WithLabelValues(const std::vector<std::string>& values);

/// \brief when T is Summary, set the Quantiles.
/// should be call before call WithLabelValues
template <typename U = T>
typename std::enable_if<(std::is_same<U, Summary>::value), Family<T>&>::type
SetQuantiles(std::vector<detail::CKMSQuantiles::Quantile>& quantiles);

/// \brief when T is Summary, set the BucketBoundaries.
/// should be call before call WithLabelValues
template <typename U = T>
typename std::enable_if<(std::is_same<U, Histogram>::value), Family<T>&>::type
SetBucketBoundaries(std::vector<double>& bucket_boundaries);

/// \brief Remove the given dimensional data.
///
Expand Down Expand Up @@ -143,12 +169,34 @@ class PROMETHEUS_CPP_CORE_EXPORT Family : public Collectable {

const std::string name_;
const std::string help_;
std::vector<std::string> variable_labels_;
const std::map<std::string, std::string> constant_labels_;
std::vector<detail::CKMSQuantiles::Quantile> quantiles_;
std::vector<double> bucket_boundaries_;
mutable std::mutex mutex_;

ClientMetric CollectMetric(std::size_t hash, T* metric) const;
T& Add(const std::map<std::string, std::string>& labels,
std::unique_ptr<T> object);
std::map<std::string, std::string> VariableLabels(
const std::vector<std::string>& values);
};

template <typename T>
template <typename U>
typename std::enable_if<(std::is_same<U, Summary>::value), Family<T>&>::type
Family<T>::SetQuantiles(std::vector<detail::CKMSQuantiles::Quantile>& quantiles){
quantiles_ = quantiles;
return *this;
}

template <typename T>
template <typename U>
typename std::enable_if<(std::is_same<U, Histogram>::value), Family<T>&>::type
Family<T>::SetBucketBoundaries(std::vector<double>& bucket_boundaries){
bucket_boundaries_ = bucket_boundaries;
return *this;
}


} // namespace prometheus
24 changes: 24 additions & 0 deletions core/include/prometheus/gauge.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "prometheus/detail/builder.h" // IWYU pragma: export
#include "prometheus/detail/core_export.h"
#include "prometheus/metric_type.h"
#include "prometheus/family.h"

namespace prometheus {

Expand Down Expand Up @@ -76,6 +77,22 @@ class PROMETHEUS_CPP_CORE_EXPORT Gauge {
/// .Labels({{"key", "value"}})
/// .Register(*registry);
///
/// gauge_family.Add({{"key2","value2"}}).Increment();
/// ...
/// \endcode
///
/// Example usage:
///
/// \code
/// auto registry = std::make_shared<Registry>();
/// auto& gauge_family = prometheus::BuildGauge()
/// .Name("some_name")
/// .Help("Additional description.")
/// .Labels({{"key", "value"}})
/// .LabelNamesVec({"key2","key3"})
/// .Register(*registry);
///
/// gauge_family.WithLabelValues({"value2","value3"}).Increment();
/// ...
/// \endcode
///
Expand All @@ -86,9 +103,16 @@ class PROMETHEUS_CPP_CORE_EXPORT Gauge {
/// - Help(const std::string&) to set an additional description.
/// - Label(const std::map<std::string, std::string>&) to assign a set of
/// key-value pairs (= labels) to the metric.
/// - LabelNamesVec(const std::vector<std::string&) to pre-affirmation pairs(= labels)'s
/// key; and you and use family.WithLabelValues({"value1","value1"}) to get the T;
/// note than: vector<names>.size() == vector<values>.size()
///
/// To finish the configuration of the Gauge metric register it with
/// Register(Registry&).
PROMETHEUS_CPP_CORE_EXPORT detail::Builder<Gauge> BuildGauge();

/// \brief Specialization of WithLabelValues<Gauge>.
PROMETHEUS_CPP_CORE_EXPORT template <>
Gauge& Family<Gauge>::WithLabelValues(const std::vector<std::string>& values);

} // namespace prometheus
45 changes: 45 additions & 0 deletions core/include/prometheus/histogram.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "prometheus/detail/core_export.h"
#include "prometheus/gauge.h"
#include "prometheus/metric_type.h"
#include "prometheus/family.h"

namespace prometheus {

Expand All @@ -28,6 +29,18 @@ namespace prometheus {
/// The class is thread-safe. No concurrent call to any API of this type causes
/// a data race.
class PROMETHEUS_CPP_CORE_EXPORT Histogram {
public:

/// \brief ExponentialBuckets creates 'count' buckets, where the lowest bucket has an
/// upper bound of 'start' and each following bucket's upper bound is 'factor'
/// times the previous bucket's upper bound. The final +Inf bucket is not counted
/// and not included in the returned vector. The returned vector is meant to be
/// used for the Buckets field of Histogram.
///
/// The function assert if 'count' is 0 or negative, if 'start' is 0 or negative,
/// or if 'factor' is less than or equal 1.
static std::vector<double> ExponentialBuckets(double start,
double factor, int count);
public:
using BucketBoundaries = std::vector<double>;

Expand Down Expand Up @@ -86,6 +99,23 @@ class PROMETHEUS_CPP_CORE_EXPORT Histogram {
/// .Labels({{"key", "value"}})
/// .Register(*registry);
///
/// histogram_family.Add({{"key1","value1"}}, Histogram::BucketBoundaries{1, 2}).Observe(1.0);
/// ...
/// \endcode
///
/// Example usage2:
///
/// \code
/// auto registry = std::make_shared<Registry>();
/// auto& histogram_family = prometheus::BuildHistogram()
/// .Name("some_name")
/// .Help("Additional description.")
/// .Labels({{"key", "value"}})
/// .LabelNamesVec({"key2","key3"})
/// .BucketBoundaries({Histogram::BucketBoundaries{1, 2}})
/// .Register(*registry);
///
/// histogram_family.WithLabelValues({"value2","value3"}).Observe(1.0);
/// ...
/// \endcode
///
Expand All @@ -96,9 +126,24 @@ class PROMETHEUS_CPP_CORE_EXPORT Histogram {
/// - Help(const std::string&) to set an additional description.
/// - Label(const std::map<std::string, std::string>&) to assign a set of
/// key-value pairs (= labels) to the metric.
/// - LabelNamesVec(const std::vector<std::string&) to pre-affirmation pairs(= labels)'s
/// key; and you and use family.WithLabelValues({"value1","value1"}) to get the T;
/// note than: vector<names>.size() == vector<values>.size()
/// - BucketBoundaries(const std::vector<double>&) to pre-affirmation bucketBoundaries
/// when use WithLabelValues()
///
/// To finish the configuration of the Histogram metric register it with
/// Register(Registry&).
PROMETHEUS_CPP_CORE_EXPORT detail::Builder<Histogram> BuildHistogram();

/// \brief Specialization of WithLabelValues<Histogram>.
PROMETHEUS_CPP_CORE_EXPORT template <>
Histogram& Family<Histogram>::WithLabelValues(const std::vector<std::string>& values);

namespace detail {
/// \brief Specialization of Register<Histogram>.
PROMETHEUS_CPP_CORE_EXPORT template<>
Family <Histogram> &Builder<Histogram>::Register(Registry &registry);
} // namespace detail

} // namespace prometheus
1 change: 1 addition & 0 deletions core/include/prometheus/registry.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ class PROMETHEUS_CPP_CORE_EXPORT Registry : public Collectable {

template <typename T>
Family<T>& Add(const std::string& name, const std::string& help,
const std::vector<std::string>& variable_labels,
const std::map<std::string, std::string>& labels);

const InsertBehavior insert_behavior_;
Expand Down
Loading