Rework everything to access the prometheus-cpp objects more directly

This commit is contained in:
Tim Wojtulewicz 2024-03-26 11:19:25 -07:00
parent ec3e68928f
commit 84aa308527
17 changed files with 469 additions and 606 deletions

View file

@ -4,10 +4,11 @@
#include <cstdint>
#include <initializer_list>
#include <type_traits>
#include <memory>
#include "zeek/Span.h"
#include "zeek/telemetry/MetricFamily.h"
#include "zeek/telemetry/Utils.h"
#include "zeek/telemetry/telemetry.bif.h"
#include "prometheus/counter.h"
@ -30,7 +31,7 @@ public:
* Increments the value by @p amount.
* @pre `amount >= 0`
*/
void Inc(BaseType amount) noexcept { handle.Increment(amount); }
void Inc(BaseType amount) noexcept { handle->Increment(amount); }
/**
* Increments the value by 1.
@ -44,7 +45,7 @@ public:
BaseType Value() const noexcept {
// Use Collect() here instead of Value() to correctly handle metrics with
// callbacks.
auto metric = handle.Collect();
auto metric = handle->Collect();
return static_cast<BaseType>(metric.counter.value);
}
@ -54,25 +55,24 @@ public:
bool CompareLabels(const prometheus::Labels& lbls) const { return labels == lbls; }
protected:
explicit BaseCounter(FamilyType& family, const prometheus::Labels& labels,
explicit BaseCounter(FamilyType* family, const prometheus::Labels& labels,
prometheus::CollectCallbackPtr callback = nullptr) noexcept
: handle(family.Add(labels)), labels(labels) {
: handle(&(family->Add(labels))), labels(labels) {
if ( callback )
handle.AddCollectCallback(callback);
handle->AddCollectCallback(callback);
}
Handle& handle;
Handle* handle;
prometheus::Labels labels;
BaseType last_value = 0;
};
/**
* A handle to a metric that represents an integer value that can only go up.
*/
class IntCounter : public BaseCounter<uint64_t> {
class IntCounter final : public BaseCounter<uint64_t> {
public:
static inline const char* OpaqueName = "IntCounterMetricVal";
explicit IntCounter(FamilyType& family, const prometheus::Labels& labels,
explicit IntCounter(FamilyType* family, const prometheus::Labels& labels,
prometheus::CollectCallbackPtr callback = nullptr) noexcept
: BaseCounter(family, labels, callback) {}
};
@ -80,10 +80,10 @@ public:
/**
* A handle to a metric that represents a double value that can only go up.
*/
class DblCounter : public BaseCounter<double> {
class DblCounter final : public BaseCounter<double> {
public:
static inline const char* OpaqueName = "DblCounterMetricVal";
explicit DblCounter(FamilyType& family, const prometheus::Labels& labels,
explicit DblCounter(FamilyType* family, const prometheus::Labels& labels,
prometheus::CollectCallbackPtr callback = nullptr) noexcept
: BaseCounter(family, labels, callback) {}
};
@ -92,19 +92,13 @@ template<class CounterType, typename BaseType>
class BaseCounterFamily : public MetricFamily,
public std::enable_shared_from_this<BaseCounterFamily<CounterType, BaseType>> {
public:
BaseCounterFamily(std::string_view prefix, std::string_view name, Span<const std::string_view> labels,
std::string_view helptext, std::shared_ptr<prometheus::Registry> registry,
std::string_view unit = "", bool is_sum = false)
: MetricFamily(prefix, name, labels, helptext, unit, is_sum),
family(prometheus::BuildCounter().Name(full_name).Help(std::string{helptext}).Register(*registry)) {}
/**
* Returns the metrics handle for given labels, creating a new instance
* lazily if necessary.
*/
std::shared_ptr<CounterType> GetOrAdd(Span<const LabelView> labels,
prometheus::CollectCallbackPtr callback = nullptr) {
prometheus::Labels p_labels = BuildPrometheusLabels(labels);
prometheus::Labels p_labels = detail::BuildPrometheusLabels(labels);
auto check = [&](const std::shared_ptr<CounterType>& counter) { return counter->CompareLabels(p_labels); };
@ -124,63 +118,23 @@ public:
return GetOrAdd(Span{labels.begin(), labels.size()}, callback);
}
std::vector<std::shared_ptr<CounterType>>& GetAllCounters() { return counters; }
std::vector<RecordValPtr> Collect() const override {
static auto string_vec_type = zeek::id::find_type<zeek::VectorType>("string_vec");
static auto metric_record_type = zeek::id::find_type<zeek::RecordType>("Telemetry::Metric");
static auto opts_idx = metric_record_type->FieldOffset("opts");
static auto labels_idx = metric_record_type->FieldOffset("labels");
static auto value_idx = metric_record_type->FieldOffset("value");
static auto count_value_idx = metric_record_type->FieldOffset("count_value");
RecordValPtr opts_record = GetMetricOptsRecord();
std::vector<RecordValPtr> records;
for ( const auto& ctr : counters ) {
auto label_values_vec = make_intrusive<VectorVal>(string_vec_type);
for ( const auto& [label_key, label] : ctr->Labels() ) {
// We don't include the endpoint key/value unless it's a prometheus request
if ( label_key != "endpoint" )
label_values_vec->Append(make_intrusive<StringVal>(label));
}
auto r = make_intrusive<zeek::RecordVal>(metric_record_type);
r->Assign(labels_idx, label_values_vec);
r->Assign(opts_idx, opts_record);
if constexpr ( std::is_same_v<BaseType, double> )
r->Assign(value_idx, zeek::make_intrusive<DoubleVal>(ctr->Value()));
else {
r->Assign(value_idx, zeek::make_intrusive<DoubleVal>(static_cast<double>(ctr->Value())));
r->Assign(count_value_idx, val_mgr->Count(ctr->Value()));
}
records.push_back(std::move(r));
}
return records;
}
protected:
prometheus::Family<prometheus::Counter>& family;
BaseCounterFamily(prometheus::Family<prometheus::Counter>* family, Span<const std::string_view> labels)
: MetricFamily(labels), family(family) {}
prometheus::Family<prometheus::Counter>* family;
std::vector<std::shared_ptr<CounterType>> counters;
};
/**
* Manages a collection of IntCounter metrics.
*/
class IntCounterFamily : public BaseCounterFamily<IntCounter, uint64_t> {
class IntCounterFamily final : public BaseCounterFamily<IntCounter, uint64_t> {
public:
static inline const char* OpaqueName = "IntCounterMetricFamilyVal";
explicit IntCounterFamily(std::string_view prefix, std::string_view name, Span<const std::string_view> labels,
std::string_view helptext, std::shared_ptr<prometheus::Registry> registry,
std::string_view unit = "", bool is_sum = false)
: BaseCounterFamily(prefix, name, labels, helptext, std::move(registry), unit, is_sum) {}
IntCounterFamily(const IntCounterFamily&) noexcept = default;
IntCounterFamily& operator=(const IntCounterFamily&) noexcept = delete;
explicit IntCounterFamily(prometheus::Family<prometheus::Counter>* family, Span<const std::string_view> labels)
: BaseCounterFamily(family, labels) {}
zeek_int_t MetricType() const noexcept override { return BifEnum::Telemetry::MetricType::INT_COUNTER; }
};
@ -188,17 +142,12 @@ public:
/**
* Manages a collection of DblCounter metrics.
*/
class DblCounterFamily : public BaseCounterFamily<DblCounter, double> {
class DblCounterFamily final : public BaseCounterFamily<DblCounter, double> {
public:
static inline const char* OpaqueName = "DblCounterMetricFamilyVal";
explicit DblCounterFamily(std::string_view prefix, std::string_view name, Span<const std::string_view> labels,
std::string_view helptext, std::shared_ptr<prometheus::Registry> registry,
std::string_view unit = "", bool is_sum = false)
: BaseCounterFamily(prefix, name, labels, helptext, std::move(registry), unit, is_sum) {}
DblCounterFamily(const DblCounterFamily&) noexcept = default;
DblCounterFamily& operator=(const DblCounterFamily&) noexcept = delete;
explicit DblCounterFamily(prometheus::Family<prometheus::Counter>* family, Span<const std::string_view> labels)
: BaseCounterFamily(family, labels) {}
zeek_int_t MetricType() const noexcept override { return BifEnum::Telemetry::MetricType::DOUBLE_COUNTER; }
};