mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 14:48:21 +00:00
Add handle types for histogram metrics
This commit is contained in:
parent
0b665ee130
commit
d4466db5ce
8 changed files with 884 additions and 172 deletions
|
@ -8,6 +8,7 @@ include_directories(BEFORE
|
|||
set(telemetry_SRCS
|
||||
Counter.cc
|
||||
Gauge.cc
|
||||
Histogram.cc
|
||||
Manager.cc
|
||||
MetricFamily.cc
|
||||
)
|
||||
|
|
|
@ -12,44 +12,6 @@ namespace ct = caf::telemetry;
|
|||
|
||||
namespace zeek::telemetry {
|
||||
|
||||
// -- bindings to private utility functions ------------------------------------
|
||||
|
||||
template <>
|
||||
struct PimplTrait<IntCounter::Impl>
|
||||
{
|
||||
using Native = ct::int_counter;
|
||||
using Oqaque = IntCounter::Impl;
|
||||
using NativeFamily = ct::metric_family_impl<Native>;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct PimplTrait<ct::int_counter> : PimplTrait<IntCounter::Impl> { };
|
||||
|
||||
template <>
|
||||
struct PimplTrait<IntCounterFamily::Impl>
|
||||
{
|
||||
using Native = typename PimplTrait<IntCounter::Impl>::NativeFamily;
|
||||
using Oqaque = IntCounterFamily::Impl;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct PimplTrait<DblCounter::Impl>
|
||||
{
|
||||
using Native = ct::dbl_counter;
|
||||
using Oqaque = DblCounter::Impl;
|
||||
using NativeFamily = ct::metric_family_impl<Native>;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct PimplTrait<ct::dbl_counter> : PimplTrait<DblCounter::Impl> { };
|
||||
|
||||
template <>
|
||||
struct PimplTrait<DblCounterFamily::Impl>
|
||||
{
|
||||
using Native = typename PimplTrait<DblCounter::Impl>::NativeFamily;
|
||||
using Oqaque = DblCounterFamily::Impl;
|
||||
};
|
||||
|
||||
// -- IntCounter ---------------------------------------------------------------
|
||||
|
||||
void IntCounter::Inc() noexcept
|
||||
|
|
|
@ -10,6 +10,10 @@
|
|||
#include <type_traits>
|
||||
|
||||
#include "zeek/Span.h"
|
||||
#include "zeek/telemetry/Counter.h"
|
||||
#include "zeek/telemetry/Gauge.h"
|
||||
#include "zeek/telemetry/Histogram.h"
|
||||
#include "zeek/telemetry/Manager.h"
|
||||
#include "zeek/telemetry/MetricFamily.h"
|
||||
|
||||
#include "caf/telemetry/label_view.hpp"
|
||||
|
@ -17,6 +21,8 @@
|
|||
|
||||
namespace zeek::telemetry {
|
||||
|
||||
// -- traits for converting between opaque handles and native pointers ---------
|
||||
|
||||
/**
|
||||
* This trait must provide the member types @c Native for referring to the CAF
|
||||
* type, @c Opaque for referring to the @c Impl type. For instance types such as
|
||||
|
@ -25,6 +31,155 @@ namespace zeek::telemetry {
|
|||
template <class T>
|
||||
struct PimplTrait;
|
||||
|
||||
template <>
|
||||
struct PimplTrait<IntCounter::Impl>
|
||||
{
|
||||
using Native = caf::telemetry::int_counter;
|
||||
using Oqaque = IntCounter::Impl;
|
||||
using NativeFamily = caf::telemetry::metric_family_impl<Native>;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct PimplTrait<caf::telemetry::int_counter>
|
||||
: PimplTrait<IntCounter::Impl> { };
|
||||
|
||||
template <>
|
||||
struct PimplTrait<IntCounterFamily::Impl>
|
||||
{
|
||||
using Native = typename PimplTrait<IntCounter::Impl>::NativeFamily;
|
||||
using Oqaque = IntCounterFamily::Impl;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct PimplTrait<typename PimplTrait<IntCounter::Impl>::NativeFamily>
|
||||
: PimplTrait<IntCounterFamily::Impl> { };
|
||||
|
||||
template <>
|
||||
struct PimplTrait<DblCounter::Impl>
|
||||
{
|
||||
using Native = caf::telemetry::dbl_counter;
|
||||
using Oqaque = DblCounter::Impl;
|
||||
using NativeFamily = caf::telemetry::metric_family_impl<Native>;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct PimplTrait<caf::telemetry::dbl_counter>
|
||||
: PimplTrait<DblCounter::Impl> { };
|
||||
|
||||
template <>
|
||||
struct PimplTrait<DblCounterFamily::Impl>
|
||||
{
|
||||
using Native = typename PimplTrait<DblCounter::Impl>::NativeFamily;
|
||||
using Oqaque = DblCounterFamily::Impl;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct PimplTrait<typename PimplTrait<DblCounter::Impl>::NativeFamily>
|
||||
: PimplTrait<DblCounterFamily::Impl> { };
|
||||
|
||||
template <>
|
||||
struct PimplTrait<IntGauge::Impl>
|
||||
{
|
||||
using Native = caf::telemetry::int_gauge;
|
||||
using Oqaque = IntGauge::Impl;
|
||||
using NativeFamily = caf::telemetry::metric_family_impl<Native>;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct PimplTrait<caf::telemetry::int_gauge> : PimplTrait<IntGauge::Impl> { };
|
||||
|
||||
template <>
|
||||
struct PimplTrait<IntGaugeFamily::Impl>
|
||||
{
|
||||
using Native = typename PimplTrait<IntGauge::Impl>::NativeFamily;
|
||||
using Oqaque = IntGaugeFamily::Impl;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct PimplTrait<typename PimplTrait<IntGauge::Impl>::NativeFamily>
|
||||
: PimplTrait<IntGaugeFamily::Impl> { };
|
||||
|
||||
template <>
|
||||
struct PimplTrait<DblGauge::Impl>
|
||||
{
|
||||
using Native = caf::telemetry::dbl_gauge;
|
||||
using Oqaque = DblGauge::Impl;
|
||||
using NativeFamily = caf::telemetry::metric_family_impl<Native>;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct PimplTrait<caf::telemetry::dbl_gauge> : PimplTrait<DblGauge::Impl> { };
|
||||
|
||||
template <>
|
||||
struct PimplTrait<DblGaugeFamily::Impl>
|
||||
{
|
||||
using Native = typename PimplTrait<DblGauge::Impl>::NativeFamily;
|
||||
using Oqaque = DblGaugeFamily::Impl;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct PimplTrait<typename PimplTrait<DblGauge::Impl>::NativeFamily>
|
||||
: PimplTrait<DblGaugeFamily::Impl> { };
|
||||
|
||||
template <>
|
||||
struct PimplTrait<IntHistogram::Impl>
|
||||
{
|
||||
using Native = caf::telemetry::int_histogram;
|
||||
using Oqaque = IntHistogram::Impl;
|
||||
using NativeFamily = caf::telemetry::metric_family_impl<Native>;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct PimplTrait<caf::telemetry::int_histogram>
|
||||
: PimplTrait<IntHistogram::Impl> { };
|
||||
|
||||
template <>
|
||||
struct PimplTrait<IntHistogramFamily::Impl>
|
||||
{
|
||||
using Native = typename PimplTrait<IntHistogram::Impl>::NativeFamily;
|
||||
using Oqaque = IntHistogramFamily::Impl;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct PimplTrait<typename PimplTrait<IntHistogram::Impl>::NativeFamily>
|
||||
: PimplTrait<IntHistogramFamily::Impl> { };
|
||||
|
||||
template <>
|
||||
struct PimplTrait<DblHistogram::Impl>
|
||||
{
|
||||
using Native = caf::telemetry::dbl_histogram;
|
||||
using Oqaque = DblHistogram::Impl;
|
||||
using NativeFamily = caf::telemetry::metric_family_impl<Native>;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct PimplTrait<caf::telemetry::dbl_histogram>
|
||||
: PimplTrait<DblHistogram::Impl> { };
|
||||
|
||||
template <>
|
||||
struct PimplTrait<DblHistogramFamily::Impl>
|
||||
{
|
||||
using Native = typename PimplTrait<DblHistogram::Impl>::NativeFamily;
|
||||
using Oqaque = DblHistogramFamily::Impl;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct PimplTrait<typename PimplTrait<DblHistogram::Impl>::NativeFamily>
|
||||
: PimplTrait<DblHistogramFamily::Impl> { };
|
||||
|
||||
template <>
|
||||
struct PimplTrait<Manager::Impl>
|
||||
{
|
||||
using Native = caf::telemetry::metric_registry;
|
||||
using Oqaque = Manager::Impl;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct PimplTrait<typename PimplTrait<Manager::Impl>::Native>
|
||||
: PimplTrait<Manager::Impl> { };
|
||||
|
||||
// -- free functions -----------------------------------------------------------
|
||||
|
||||
template <class T, class NativeType = typename PimplTrait<T>::Native>
|
||||
auto& deref(T* ptr)
|
||||
{
|
||||
|
@ -87,4 +242,23 @@ auto with_native_labels(Span<const LabelView> xs, F continuation)
|
|||
}
|
||||
}
|
||||
|
||||
template <class F>
|
||||
auto with_native_labels(Span<const std::string_view> xs, F continuation)
|
||||
{
|
||||
if ( xs.size() <= 10 )
|
||||
{
|
||||
caf::string_view buf[10];
|
||||
for ( size_t index = 0; index < xs.size(); ++index )
|
||||
buf[index] = xs[index];
|
||||
return continuation(Span{buf, xs.size()});
|
||||
}
|
||||
else
|
||||
{
|
||||
std::vector<caf::string_view> buf;
|
||||
for ( auto x : xs )
|
||||
buf.emplace_back(x);
|
||||
return continuation(Span{buf});
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace zeek::telemetry
|
||||
|
|
|
@ -8,48 +8,8 @@
|
|||
|
||||
#include "zeek/telemetry/Detail.h"
|
||||
|
||||
namespace ct = caf::telemetry;
|
||||
|
||||
namespace zeek::telemetry {
|
||||
|
||||
// -- bindings to private utility functions ------------------------------------
|
||||
|
||||
template <>
|
||||
struct PimplTrait<IntGauge::Impl>
|
||||
{
|
||||
using Native = ct::int_gauge;
|
||||
using Oqaque = IntGauge::Impl;
|
||||
using NativeFamily = ct::metric_family_impl<Native>;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct PimplTrait<ct::int_gauge> : PimplTrait<IntGauge::Impl> { };
|
||||
|
||||
template <>
|
||||
struct PimplTrait<IntGaugeFamily::Impl>
|
||||
{
|
||||
using Native = typename PimplTrait<IntGauge::Impl>::NativeFamily;
|
||||
using Oqaque = IntGaugeFamily::Impl;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct PimplTrait<DblGauge::Impl>
|
||||
{
|
||||
using Native = ct::dbl_gauge;
|
||||
using Oqaque = DblGauge::Impl;
|
||||
using NativeFamily = ct::metric_family_impl<Native>;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct PimplTrait<ct::dbl_gauge> : PimplTrait<DblGauge::Impl> { };
|
||||
|
||||
template <>
|
||||
struct PimplTrait<DblGaugeFamily::Impl>
|
||||
{
|
||||
using Native = typename PimplTrait<DblGauge::Impl>::NativeFamily;
|
||||
using Oqaque = DblGaugeFamily::Impl;
|
||||
};
|
||||
|
||||
// -- IntGauge ---------------------------------------------------------------
|
||||
|
||||
void IntGauge::Inc() noexcept
|
||||
|
|
103
src/telemetry/Histogram.cc
Normal file
103
src/telemetry/Histogram.cc
Normal file
|
@ -0,0 +1,103 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#include "zeek/telemetry/Histogram.h"
|
||||
|
||||
#include "caf/telemetry/histogram.hpp"
|
||||
#include "caf/telemetry/metric_family.hpp"
|
||||
#include "caf/telemetry/metric_family_impl.hpp"
|
||||
|
||||
#include "zeek/telemetry/Detail.h"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
namespace zeek::telemetry {
|
||||
|
||||
// -- IntHistogram ---------------------------------------------------------------
|
||||
|
||||
void IntHistogram::Observe(int64_t value) noexcept
|
||||
{
|
||||
deref(pimpl).observe(value);
|
||||
}
|
||||
|
||||
int64_t IntHistogram::Sum() const noexcept
|
||||
{
|
||||
return deref(pimpl).sum();
|
||||
}
|
||||
|
||||
size_t IntHistogram::NumBuckets() const noexcept
|
||||
{
|
||||
return deref(pimpl).buckets().size();
|
||||
}
|
||||
|
||||
int64_t IntHistogram::CountAt(size_t index) const noexcept
|
||||
{
|
||||
auto xs = deref(pimpl).buckets();
|
||||
assert(index < xs.size());
|
||||
return xs[index].count.value();
|
||||
}
|
||||
|
||||
int64_t IntHistogram::UpperBoundAt(size_t index) const noexcept
|
||||
{
|
||||
auto xs = deref(pimpl).buckets();
|
||||
assert(index < xs.size());
|
||||
return xs[index].upper_bound;
|
||||
}
|
||||
|
||||
IntHistogramFamily::IntHistogramFamily(Impl* ptr) : MetricFamily(upcast(ptr))
|
||||
{
|
||||
}
|
||||
|
||||
IntHistogram IntHistogramFamily::GetOrAdd(Span<const LabelView> labels)
|
||||
{
|
||||
return with_native_labels(labels, [this](auto nativeLabels)
|
||||
{
|
||||
auto hdl = opaque(deref(this, pimpl).get_or_add(nativeLabels));
|
||||
return IntHistogram{hdl};
|
||||
});
|
||||
}
|
||||
|
||||
// -- DblHistogram ---------------------------------------------------------------
|
||||
|
||||
void DblHistogram::Observe(double amount) noexcept
|
||||
{
|
||||
deref(pimpl).observe(amount);
|
||||
}
|
||||
|
||||
double DblHistogram::Sum() const noexcept
|
||||
{
|
||||
return deref(pimpl).sum();
|
||||
}
|
||||
|
||||
size_t DblHistogram::NumBuckets() const noexcept
|
||||
{
|
||||
return deref(pimpl).buckets().size();
|
||||
}
|
||||
|
||||
int64_t DblHistogram::CountAt(size_t index) const noexcept
|
||||
{
|
||||
auto xs = deref(pimpl).buckets();
|
||||
assert(index < xs.size());
|
||||
return xs[index].count.value();
|
||||
}
|
||||
|
||||
double DblHistogram::UpperBoundAt(size_t index) const noexcept
|
||||
{
|
||||
auto xs = deref(pimpl).buckets();
|
||||
assert(index < xs.size());
|
||||
return xs[index].upper_bound;
|
||||
}
|
||||
|
||||
DblHistogramFamily::DblHistogramFamily(Impl* ptr) : MetricFamily(upcast(ptr))
|
||||
{
|
||||
}
|
||||
|
||||
DblHistogram DblHistogramFamily::GetOrAdd(Span<const LabelView> labels)
|
||||
{
|
||||
return with_native_labels(labels, [this](auto nativeLabels)
|
||||
{
|
||||
auto hdl = opaque(deref(this, pimpl).get_or_add(nativeLabels));
|
||||
return DblHistogram{hdl};
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace zeek::telemetry
|
234
src/telemetry/Histogram.h
Normal file
234
src/telemetry/Histogram.h
Normal file
|
@ -0,0 +1,234 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <initializer_list>
|
||||
#include <type_traits>
|
||||
|
||||
#include "zeek/Span.h"
|
||||
#include "zeek/telemetry/MetricFamily.h"
|
||||
|
||||
namespace zeek::telemetry {
|
||||
|
||||
class DblHistogramFamily;
|
||||
class IntHistogramFamily;
|
||||
class Manager;
|
||||
|
||||
/**
|
||||
* A handle to a metric that represents an aggregatable distribution of observed
|
||||
* measurements with integer precision. Sorts individual measurements into
|
||||
* configurable buckets.
|
||||
*/
|
||||
class IntHistogram {
|
||||
public:
|
||||
friend class IntHistogramFamily;
|
||||
|
||||
struct Impl;
|
||||
|
||||
IntHistogram() = delete;
|
||||
IntHistogram(const IntHistogram&) noexcept = default;
|
||||
IntHistogram& operator=(const IntHistogram&) noexcept = default;
|
||||
|
||||
/**
|
||||
* Increments all buckets with an upper bound less than or equal to @p value
|
||||
* by one and adds @p value to the total sum of all observed values.
|
||||
*/
|
||||
void Observe(int64_t value) noexcept;
|
||||
|
||||
/// @return The sum of all observed values.
|
||||
int64_t Sum() const noexcept;
|
||||
|
||||
/// @return The number of buckets, including the implicit "infinite" bucket.
|
||||
size_t NumBuckets() const noexcept;
|
||||
|
||||
/// @return The number of observations in the bucket at @p index.
|
||||
/// @pre index < NumBuckets()
|
||||
int64_t CountAt(size_t index) const noexcept;
|
||||
|
||||
/// @return The upper bound of the bucket at @p index.
|
||||
/// @pre index < NumBuckets()
|
||||
int64_t UpperBoundAt(size_t index) const noexcept;
|
||||
|
||||
/**
|
||||
* @return Whether @c this and @p other refer to the same histogram.
|
||||
*/
|
||||
constexpr bool IsSameAs(IntHistogram other) const noexcept
|
||||
{
|
||||
return pimpl == other.pimpl;
|
||||
}
|
||||
|
||||
private:
|
||||
explicit IntHistogram(Impl* ptr) noexcept : pimpl(ptr)
|
||||
{
|
||||
}
|
||||
|
||||
Impl* pimpl;
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks whether two @ref IntHistogram handles are identical.
|
||||
* @return Whether @p lhs and @p rhs refer to the same object.
|
||||
*/
|
||||
constexpr bool operator==(IntHistogram lhs, IntHistogram rhs) noexcept
|
||||
{
|
||||
return lhs.IsSameAs(rhs);
|
||||
}
|
||||
|
||||
/// @relates IntHistogram
|
||||
constexpr bool operator!=(IntHistogram lhs, IntHistogram rhs) noexcept
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Manages a collection of IntHistogram metrics.
|
||||
*/
|
||||
class IntHistogramFamily : public MetricFamily {
|
||||
public:
|
||||
friend class Manager;
|
||||
|
||||
class Impl;
|
||||
|
||||
using InstanceType = IntHistogram;
|
||||
|
||||
IntHistogramFamily(const IntHistogramFamily&) noexcept = default;
|
||||
IntHistogramFamily& operator=(const IntHistogramFamily&) noexcept = default;
|
||||
|
||||
/**
|
||||
* Returns the metrics handle for given labels, creating a new instance
|
||||
* lazily if necessary.
|
||||
*/
|
||||
IntHistogram GetOrAdd(Span<const LabelView> labels);
|
||||
|
||||
/**
|
||||
* @copydoc GetOrAdd
|
||||
*/
|
||||
IntHistogram GetOrAdd(std::initializer_list<LabelView> labels)
|
||||
{
|
||||
return GetOrAdd(Span{labels.begin(), labels.size()});
|
||||
}
|
||||
|
||||
private:
|
||||
explicit IntHistogramFamily(Impl* ptr);
|
||||
};
|
||||
|
||||
/**
|
||||
* A handle to a metric that represents an aggregatable distribution of observed
|
||||
* measurements with floating point precision. Sorts individual measurements
|
||||
* into configurable buckets.
|
||||
*/
|
||||
class DblHistogram {
|
||||
public:
|
||||
friend class DblHistogramFamily;
|
||||
|
||||
struct Impl;
|
||||
|
||||
DblHistogram() = delete;
|
||||
DblHistogram(const DblHistogram&) noexcept = default;
|
||||
DblHistogram& operator=(const DblHistogram&) noexcept = default;
|
||||
|
||||
/**
|
||||
* Increments all buckets with an upper bound less than or equal to @p value
|
||||
* by one and adds @p value to the total sum of all observed values.
|
||||
*/
|
||||
void Observe(double value) noexcept;
|
||||
|
||||
/// @return The sum of all observed values.
|
||||
double Sum() const noexcept;
|
||||
|
||||
/// @return The number of buckets, including the implicit "infinite" bucket.
|
||||
size_t NumBuckets() const noexcept;
|
||||
|
||||
/// @return The number of observations in the bucket at @p index.
|
||||
/// @pre index < NumBuckets()
|
||||
int64_t CountAt(size_t index) const noexcept;
|
||||
|
||||
/// @return The upper bound of the bucket at @p index.
|
||||
/// @pre index < NumBuckets()
|
||||
double UpperBoundAt(size_t index) const noexcept;
|
||||
|
||||
/**
|
||||
* @return Whether @c this and @p other refer to the same histogram.
|
||||
*/
|
||||
constexpr bool IsSameAs(DblHistogram other) const noexcept
|
||||
{
|
||||
return pimpl == other.pimpl;
|
||||
}
|
||||
|
||||
private:
|
||||
explicit DblHistogram(Impl* ptr) noexcept : pimpl(ptr)
|
||||
{
|
||||
}
|
||||
|
||||
Impl* pimpl;
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks whether two @ref DblHistogram handles are identical.
|
||||
* @return Whether @p lhs and @p rhs refer to the same object.
|
||||
*/
|
||||
constexpr bool operator==(DblHistogram lhs, DblHistogram rhs) noexcept
|
||||
{
|
||||
return lhs.IsSameAs(rhs);
|
||||
}
|
||||
|
||||
/// @relates DblHistogram
|
||||
constexpr bool operator!=(DblHistogram lhs, DblHistogram rhs) noexcept
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Manages a collection of DblHistogram metrics.
|
||||
*/
|
||||
class DblHistogramFamily : public MetricFamily {
|
||||
public:
|
||||
friend class Manager;
|
||||
|
||||
class Impl;
|
||||
|
||||
using InstanceType = DblHistogram;
|
||||
|
||||
DblHistogramFamily(const DblHistogramFamily&) noexcept = default;
|
||||
DblHistogramFamily& operator=(const DblHistogramFamily&) noexcept = default;
|
||||
|
||||
/**
|
||||
* Returns the metrics handle for given labels, creating a new instance
|
||||
* lazily if necessary.
|
||||
*/
|
||||
DblHistogram GetOrAdd(Span<const LabelView> labels);
|
||||
|
||||
/**
|
||||
* @copydoc GetOrAdd
|
||||
*/
|
||||
DblHistogram GetOrAdd(std::initializer_list<LabelView> labels)
|
||||
{
|
||||
return GetOrAdd(Span{labels.begin(), labels.size()});
|
||||
}
|
||||
|
||||
private:
|
||||
explicit DblHistogramFamily(Impl* ptr);
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <class T>
|
||||
struct HistogramOracle {
|
||||
static_assert(std::is_same<T, int64_t>::value,
|
||||
"Histogram<T> only supports int64_t and double");
|
||||
|
||||
using type = IntHistogram;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct HistogramOracle<double> {
|
||||
using type = DblHistogram;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class T>
|
||||
using Histogram = typename detail::HistogramOracle<T>::type;
|
||||
|
||||
} // namespace zeek::telemetry
|
|
@ -6,81 +6,10 @@
|
|||
|
||||
#include "zeek/3rdparty/doctest.h"
|
||||
|
||||
#include "zeek/telemetry/Detail.h"
|
||||
|
||||
namespace zeek::telemetry {
|
||||
|
||||
namespace {
|
||||
|
||||
namespace ct = caf::telemetry;
|
||||
|
||||
using NativeManager = ct::metric_registry;
|
||||
|
||||
using NativeIntCounter = ct::int_counter;
|
||||
|
||||
using NativeIntCounterFamily = ct::metric_family_impl<NativeIntCounter>;
|
||||
|
||||
using NativeDblCounter = ct::dbl_counter;
|
||||
|
||||
using NativeDblCounterFamily = ct::metric_family_impl<NativeDblCounter>;
|
||||
|
||||
using NativeIntGauge = ct::int_gauge;
|
||||
|
||||
using NativeIntGaugeFamily = ct::metric_family_impl<NativeIntGauge>;
|
||||
|
||||
using NativeDblGauge = ct::dbl_gauge;
|
||||
|
||||
using NativeDblGaugeFamily = ct::metric_family_impl<NativeDblGauge>;
|
||||
|
||||
auto& deref(Manager::Impl* ptr)
|
||||
{
|
||||
return *reinterpret_cast<NativeManager*>(ptr);
|
||||
}
|
||||
|
||||
auto opaque(NativeManager* ptr)
|
||||
{
|
||||
return reinterpret_cast<Manager::Impl*>(ptr);
|
||||
}
|
||||
|
||||
auto opaque(NativeIntCounterFamily* ptr)
|
||||
{
|
||||
return reinterpret_cast<IntCounterFamily::Impl*>(ptr);
|
||||
}
|
||||
|
||||
auto opaque(NativeDblCounterFamily* ptr)
|
||||
{
|
||||
return reinterpret_cast<DblCounterFamily::Impl*>(ptr);
|
||||
}
|
||||
|
||||
auto opaque(NativeIntGaugeFamily* ptr)
|
||||
{
|
||||
return reinterpret_cast<IntGaugeFamily::Impl*>(ptr);
|
||||
}
|
||||
|
||||
auto opaque(NativeDblGaugeFamily* ptr)
|
||||
{
|
||||
return reinterpret_cast<DblGaugeFamily::Impl*>(ptr);
|
||||
}
|
||||
|
||||
template <class F>
|
||||
auto with_native(Span<const std::string_view> xs, F continuation)
|
||||
{
|
||||
if ( xs.size() <= 10 )
|
||||
{
|
||||
caf::string_view buf[10];
|
||||
for ( size_t index = 0; index < xs.size(); ++index )
|
||||
buf[index] = xs[index];
|
||||
return continuation(Span{buf, xs.size()});
|
||||
}
|
||||
else
|
||||
{
|
||||
std::vector<caf::string_view> buf;
|
||||
for ( auto x : xs )
|
||||
buf.emplace_back(x);
|
||||
return continuation(Span{buf});
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Manager::~Manager()
|
||||
{
|
||||
}
|
||||
|
@ -91,7 +20,7 @@ IntCounterFamily Manager::IntCounterFam(std::string_view prefix,
|
|||
std::string_view helptext,
|
||||
std::string_view unit, bool is_sum)
|
||||
{
|
||||
return with_native(labels, [&, this](auto xs)
|
||||
return with_native_labels(labels, [&, this](auto xs)
|
||||
{
|
||||
auto ptr = deref(pimpl).counter_family(prefix, name, xs,
|
||||
helptext, unit, is_sum);
|
||||
|
@ -105,7 +34,7 @@ DblCounterFamily Manager::DblCounterFam(std::string_view prefix,
|
|||
std::string_view helptext,
|
||||
std::string_view unit, bool is_sum)
|
||||
{
|
||||
return with_native(labels, [&, this](auto xs)
|
||||
return with_native_labels(labels, [&, this](auto xs)
|
||||
{
|
||||
auto ptr = deref(pimpl).counter_family<double>(prefix, name, xs,
|
||||
helptext, unit, is_sum);
|
||||
|
@ -119,7 +48,7 @@ IntGaugeFamily Manager::IntGaugeFam(std::string_view prefix,
|
|||
std::string_view helptext,
|
||||
std::string_view unit, bool is_sum)
|
||||
{
|
||||
return with_native(labels, [&, this](auto xs)
|
||||
return with_native_labels(labels, [&, this](auto xs)
|
||||
{
|
||||
auto ptr = deref(pimpl).gauge_family(prefix, name, xs,
|
||||
helptext, unit, is_sum);
|
||||
|
@ -133,7 +62,7 @@ DblGaugeFamily Manager::DblGaugeFam(std::string_view prefix,
|
|||
std::string_view helptext,
|
||||
std::string_view unit, bool is_sum)
|
||||
{
|
||||
return with_native(labels, [&, this](auto xs)
|
||||
return with_native_labels(labels, [&, this](auto xs)
|
||||
{
|
||||
auto ptr = deref(pimpl).gauge_family<double>(prefix, name, xs,
|
||||
helptext, unit, is_sum);
|
||||
|
@ -141,6 +70,39 @@ DblGaugeFamily Manager::DblGaugeFam(std::string_view prefix,
|
|||
});
|
||||
}
|
||||
|
||||
IntHistogramFamily Manager::IntHistoFam(std::string_view prefix,
|
||||
std::string_view name,
|
||||
Span<const std::string_view> labels,
|
||||
Span<const int64_t> ubounds,
|
||||
std::string_view helptext,
|
||||
std::string_view unit, bool is_sum)
|
||||
{
|
||||
return with_native_labels(labels, [&, this](auto xs)
|
||||
{
|
||||
auto bounds = caf::span<const int64_t>{ubounds.data(), ubounds.size()};
|
||||
auto ptr = deref(pimpl).histogram_family(prefix, name, xs, bounds,
|
||||
helptext, unit, is_sum);
|
||||
return IntHistogramFamily{opaque(ptr)};
|
||||
});
|
||||
}
|
||||
|
||||
DblHistogramFamily Manager::DblHistoFam(std::string_view prefix,
|
||||
std::string_view name,
|
||||
Span<const std::string_view> labels,
|
||||
Span<const double> ubounds,
|
||||
std::string_view helptext,
|
||||
std::string_view unit, bool is_sum)
|
||||
{
|
||||
return with_native_labels(labels, [&, this](auto xs)
|
||||
{
|
||||
auto bounds = caf::span<const double>{ubounds.data(), ubounds.size()};
|
||||
auto ptr = deref(pimpl).histogram_family<double>(prefix, name, xs,
|
||||
bounds, helptext,
|
||||
unit, is_sum);
|
||||
return DblHistogramFamily{opaque(ptr)};
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace zeek::telemetry
|
||||
|
||||
// -- unit tests ---------------------------------------------------------------
|
||||
|
@ -148,6 +110,8 @@ DblGaugeFamily Manager::DblGaugeFam(std::string_view prefix,
|
|||
using namespace std::literals;
|
||||
using namespace zeek::telemetry;
|
||||
|
||||
using NativeManager = caf::telemetry::metric_registry;
|
||||
|
||||
namespace {
|
||||
|
||||
template <class T>
|
||||
|
@ -241,13 +205,13 @@ SCENARIO("telemetry managers provide access to counter families")
|
|||
CHECK_EQ(family.Unit(), "1"sv);
|
||||
CHECK_EQ(family.IsSum(), true);
|
||||
}
|
||||
AND_THEN("getOrAdd returns the same metric for the same labels")
|
||||
AND_THEN("GetOrAdd returns the same metric for the same labels")
|
||||
{
|
||||
auto first = family.GetOrAdd({{"method", "get"}});
|
||||
auto second = family.GetOrAdd({{"method", "get"}});
|
||||
CHECK_EQ(first, second);
|
||||
}
|
||||
AND_THEN("getOrAdd returns different metric for the disjoint labels")
|
||||
AND_THEN("GetOrAdd returns different metric for the disjoint labels")
|
||||
{
|
||||
auto first = family.GetOrAdd({{"method", "get"}});
|
||||
auto second = family.GetOrAdd({{"method", "put"}});
|
||||
|
@ -266,13 +230,13 @@ SCENARIO("telemetry managers provide access to counter families")
|
|||
CHECK_EQ(family.Unit(), "seconds"sv);
|
||||
CHECK_EQ(family.IsSum(), true);
|
||||
}
|
||||
AND_THEN("getOrAdd returns the same metric for the same labels")
|
||||
AND_THEN("GetOrAdd returns the same metric for the same labels")
|
||||
{
|
||||
auto first = family.GetOrAdd({{"query", "foo"}});
|
||||
auto second = family.GetOrAdd({{"query", "foo"}});
|
||||
CHECK_EQ(first, second);
|
||||
}
|
||||
AND_THEN("getOrAdd returns different metric for the disjoint labels")
|
||||
AND_THEN("GetOrAdd returns different metric for the disjoint labels")
|
||||
{
|
||||
auto first = family.GetOrAdd({{"query", "foo"}});
|
||||
auto second = family.GetOrAdd({{"query", "bar"}});
|
||||
|
@ -371,13 +335,13 @@ SCENARIO("telemetry managers provide access to gauge families")
|
|||
CHECK_EQ(family.Unit(), "1"sv);
|
||||
CHECK_EQ(family.IsSum(), false);
|
||||
}
|
||||
AND_THEN("getOrAdd returns the same metric for the same labels")
|
||||
AND_THEN("GetOrAdd returns the same metric for the same labels")
|
||||
{
|
||||
auto first = family.GetOrAdd({{"protocol", "tcp"}});
|
||||
auto second = family.GetOrAdd({{"protocol", "tcp"}});
|
||||
CHECK_EQ(first, second);
|
||||
}
|
||||
AND_THEN("getOrAdd returns different metric for the disjoint labels")
|
||||
AND_THEN("GetOrAdd returns different metric for the disjoint labels")
|
||||
{
|
||||
auto first = family.GetOrAdd({{"protocol", "tcp"}});
|
||||
auto second = family.GetOrAdd({{"protocol", "quic"}});
|
||||
|
@ -396,13 +360,13 @@ SCENARIO("telemetry managers provide access to gauge families")
|
|||
CHECK_EQ(family.Unit(), "meters"sv);
|
||||
CHECK_EQ(family.IsSum(), false);
|
||||
}
|
||||
AND_THEN("getOrAdd returns the same metric for the same labels")
|
||||
AND_THEN("GetOrAdd returns the same metric for the same labels")
|
||||
{
|
||||
auto first = family.GetOrAdd({{"river", "Sacramento"}});
|
||||
auto second = family.GetOrAdd({{"river", "Sacramento"}});
|
||||
CHECK_EQ(first, second);
|
||||
}
|
||||
AND_THEN("getOrAdd returns different metric for the disjoint labels")
|
||||
AND_THEN("GetOrAdd returns different metric for the disjoint labels")
|
||||
{
|
||||
auto first = family.GetOrAdd({{"query", "Sacramento"}});
|
||||
auto second = family.GetOrAdd({{"query", "San Joaquin"}});
|
||||
|
@ -411,3 +375,151 @@ SCENARIO("telemetry managers provide access to gauge families")
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
SCENARIO("telemetry managers provide access to histogram singletons")
|
||||
{
|
||||
GIVEN("a telemetry manager")
|
||||
{
|
||||
NativeManager native_mgr;
|
||||
Manager mgr{opaque(&native_mgr)};
|
||||
WHEN("retrieving an IntHistogram singleton")
|
||||
{
|
||||
const auto max_int = std::numeric_limits<int64_t>::max();
|
||||
int64_t buckets [] = { 10, 20 };
|
||||
auto first = mgr.HistogramSingleton("zeek", "int-hist", buckets, "test");
|
||||
THEN("it initially has no observations")
|
||||
{
|
||||
REQUIRE_EQ(first.NumBuckets(), 3u);
|
||||
CHECK_EQ(first.Sum(), 0);
|
||||
CHECK_EQ(first.CountAt(0), 0);
|
||||
CHECK_EQ(first.CountAt(1), 0);
|
||||
CHECK_EQ(first.CountAt(2), 0);
|
||||
CHECK_EQ(first.UpperBoundAt(0), 10);
|
||||
CHECK_EQ(first.UpperBoundAt(1), 20);
|
||||
CHECK_EQ(first.UpperBoundAt(2), max_int);
|
||||
}
|
||||
AND_THEN("calling Observe() increments bucket counters")
|
||||
{
|
||||
first.Observe(1);
|
||||
first.Observe(9);
|
||||
first.Observe(10);
|
||||
first.Observe(11);
|
||||
first.Observe(19);
|
||||
first.Observe(20);
|
||||
first.Observe(21);
|
||||
CHECK_EQ(first.Sum(), 91);
|
||||
CHECK_EQ(first.CountAt(0), 3);
|
||||
CHECK_EQ(first.CountAt(1), 3);
|
||||
CHECK_EQ(first.CountAt(2), 1);
|
||||
}
|
||||
AND_THEN("calling HistogramSingleton again for the same name returns the same handle")
|
||||
{
|
||||
auto second = mgr.HistogramSingleton("zeek", "int-hist", buckets, "test");
|
||||
CHECK_EQ(first, second);
|
||||
}
|
||||
AND_THEN("calling HistogramSingleton for a different name returns another handle")
|
||||
{
|
||||
auto third = mgr.HistogramSingleton("zeek", "int-hist-2", buckets, "test");
|
||||
CHECK_NE(first, third);
|
||||
}
|
||||
}
|
||||
WHEN("retrieving a DblHistogram singleton")
|
||||
{
|
||||
double buckets [] = { 10.0, 20.0 };
|
||||
auto first = mgr.HistogramSingleton<double>("zeek", "dbl-count", buckets, "test");
|
||||
THEN("it initially has no observations")
|
||||
{
|
||||
REQUIRE_EQ(first.NumBuckets(), 3u);
|
||||
CHECK_EQ(first.Sum(), 0.0);
|
||||
CHECK_EQ(first.CountAt(0), 0);
|
||||
CHECK_EQ(first.CountAt(1), 0);
|
||||
CHECK_EQ(first.CountAt(2), 0);
|
||||
CHECK_EQ(first.UpperBoundAt(0), 10.0);
|
||||
CHECK_EQ(first.UpperBoundAt(1), 20.0);
|
||||
}
|
||||
AND_THEN("calling Observe() increments bucket counters")
|
||||
{
|
||||
first.Observe(2.0);
|
||||
first.Observe(4.0);
|
||||
first.Observe(8.0);
|
||||
first.Observe(16.0);
|
||||
first.Observe(32.0);
|
||||
CHECK_EQ(first.Sum(), 62.0);
|
||||
CHECK_EQ(first.CountAt(0), 3);
|
||||
CHECK_EQ(first.CountAt(1), 1);
|
||||
CHECK_EQ(first.CountAt(2), 1);
|
||||
}
|
||||
AND_THEN("calling histogramSingleton again for the same name returns the same handle")
|
||||
{
|
||||
auto second = mgr.HistogramSingleton<double>("zeek", "dbl-count", buckets, "test");
|
||||
CHECK_EQ(first, second);
|
||||
}
|
||||
AND_THEN("calling histogramSingleton for a different name returns another handle")
|
||||
{
|
||||
auto third = mgr.HistogramSingleton<double>("zeek", "dbl-count-2", buckets, "test");
|
||||
CHECK_NE(first, third);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SCENARIO("telemetry managers provide access to histogram families")
|
||||
{
|
||||
GIVEN("a telemetry manager")
|
||||
{
|
||||
NativeManager native_mgr;
|
||||
Manager mgr{opaque(&native_mgr)};
|
||||
WHEN("retrieving an IntHistogram family")
|
||||
{
|
||||
int64_t buckets [] = { 10, 20 };
|
||||
auto family = mgr.HistogramFamily("zeek", "payload-size", {"protocol"}, buckets, "test", "bytes");
|
||||
THEN("the family object stores the parameters")
|
||||
{
|
||||
CHECK_EQ(family.Prefix(), "zeek"sv);
|
||||
CHECK_EQ(family.Name(), "payload-size"sv);
|
||||
CHECK_EQ(toVector(family.LabelNames()), std::vector{"protocol"s});
|
||||
CHECK_EQ(family.Helptext(), "test"sv);
|
||||
CHECK_EQ(family.Unit(), "bytes"sv);
|
||||
CHECK_EQ(family.IsSum(), false);
|
||||
}
|
||||
AND_THEN("GetOrAdd returns the same metric for the same labels")
|
||||
{
|
||||
auto first = family.GetOrAdd({{"protocol", "tcp"}});
|
||||
auto second = family.GetOrAdd({{"protocol", "tcp"}});
|
||||
CHECK_EQ(first, second);
|
||||
}
|
||||
AND_THEN("GetOrAdd returns different metric for the disjoint labels")
|
||||
{
|
||||
auto first = family.GetOrAdd({{"protocol", "tcp"}});
|
||||
auto second = family.GetOrAdd({{"protocol", "udp"}});
|
||||
CHECK_NE(first, second);
|
||||
}
|
||||
}
|
||||
WHEN("retrieving a DblHistogram family")
|
||||
{
|
||||
double buckets [] = { 10.0, 20.0 };
|
||||
auto family = mgr.HistogramFamily<double>("zeek", "parse-time", {"protocol"}, buckets, "test", "seconds");
|
||||
THEN("the family object stores the parameters")
|
||||
{
|
||||
CHECK_EQ(family.Prefix(), "zeek"sv);
|
||||
CHECK_EQ(family.Name(), "parse-time"sv);
|
||||
CHECK_EQ(toVector(family.LabelNames()), std::vector{"protocol"s});
|
||||
CHECK_EQ(family.Helptext(), "test"sv);
|
||||
CHECK_EQ(family.Unit(), "seconds"sv);
|
||||
CHECK_EQ(family.IsSum(), false);
|
||||
}
|
||||
AND_THEN("GetOrAdd returns the same metric for the same labels")
|
||||
{
|
||||
auto first = family.GetOrAdd({{"protocol", "tcp"}});
|
||||
auto second = family.GetOrAdd({{"protocol", "tcp"}});
|
||||
CHECK_EQ(first, second);
|
||||
}
|
||||
AND_THEN("GetOrAdd returns different metric for the disjoint labels")
|
||||
{
|
||||
auto first = family.GetOrAdd({{"protocol", "tcp"}});
|
||||
auto second = family.GetOrAdd({{"protocol", "udp"}});
|
||||
CHECK_NE(first, second);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "zeek/Span.h"
|
||||
#include "zeek/telemetry/Counter.h"
|
||||
#include "zeek/telemetry/Gauge.h"
|
||||
#include "zeek/telemetry/Histogram.h"
|
||||
|
||||
namespace zeek::telemetry {
|
||||
|
||||
|
@ -143,7 +144,8 @@ public:
|
|||
auto GaugeFamily(std::string_view prefix, std::string_view name,
|
||||
Span<const std::string_view> labels,
|
||||
std::string_view helptext,
|
||||
std::string_view unit = "1", bool is_sum = false) {
|
||||
std::string_view unit = "1", bool is_sum = false)
|
||||
{
|
||||
if constexpr (std::is_same<ValueType, int64_t>::value)
|
||||
{
|
||||
return IntGaugeFam(prefix, name, labels, helptext, unit, is_sum);
|
||||
|
@ -154,7 +156,7 @@ public:
|
|||
"metrics only support int64_t and double values");
|
||||
return DblGaugeFam(prefix, name, labels, helptext, unit, is_sum);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// @copydoc GaugeFamily
|
||||
template <class ValueType = int64_t>
|
||||
|
@ -162,11 +164,11 @@ public:
|
|||
std::initializer_list<std::string_view> labels,
|
||||
std::string_view helptext, std::string_view unit = "1",
|
||||
bool is_sum = false)
|
||||
{
|
||||
auto lbl_span = Span{labels.begin(), labels.size()};
|
||||
return GaugeFamily<ValueType>(prefix, name, lbl_span, helptext,
|
||||
unit, is_sum);
|
||||
}
|
||||
{
|
||||
auto lbl_span = Span{labels.begin(), labels.size()};
|
||||
return GaugeFamily<ValueType>(prefix, name, lbl_span, helptext,
|
||||
unit, is_sum);
|
||||
}
|
||||
|
||||
/**
|
||||
* Accesses a gauge instance. Creates the hosting metric family as well
|
||||
|
@ -228,6 +230,160 @@ public:
|
|||
return fam.GetOrAdd({});
|
||||
}
|
||||
|
||||
// Forces the compiler to use the type `Span<const T>` instead of trying to
|
||||
// match paremeters to a `span`.
|
||||
template <class T>
|
||||
struct ConstSpanOracle
|
||||
{
|
||||
using Type = Span<const T>;
|
||||
};
|
||||
|
||||
// Convenience alias to safe some typing.
|
||||
template <class T>
|
||||
using ConstSpan = typename ConstSpanOracle<T>::Type;
|
||||
|
||||
/**
|
||||
* Returns a histogram metric family. Creates the family lazily if
|
||||
* necessary.
|
||||
* @param prefix The prefix (namespace) this family belongs to. Usually the
|
||||
* application or protocol name, e.g., `http`. The prefix `caf`
|
||||
* as well as prefixes starting with an underscore are
|
||||
* reserved.
|
||||
* @param name The human-readable name of the metric, e.g., `requests`.
|
||||
* @param labels Names for all label dimensions of the metric.
|
||||
* @param default_upper_bounds Upper bounds for the metric buckets.
|
||||
* @param helptext Short explanation of the metric.
|
||||
* @param unit Unit of measurement. Please use base units such as `bytes` or
|
||||
* `seconds` (prefer lowercase). The pseudo-unit `1` identifies
|
||||
* dimensionless counts.
|
||||
* @param is_sum Setting this to `true` indicates that this metric adds
|
||||
* something up to a total, where only the total value is of
|
||||
* interest. For example, the total number of HTTP requests.
|
||||
* @note The first call wins when calling this function multiple times with
|
||||
* different bucket settings. Users may also override
|
||||
* @p default_upper_bounds via run-time configuration.
|
||||
*/
|
||||
template <class ValueType = int64_t>
|
||||
auto HistogramFamily(std::string_view prefix, std::string_view name,
|
||||
Span<const std::string_view> labels,
|
||||
ConstSpan<ValueType> default_upper_bounds,
|
||||
std::string_view helptext, std::string_view unit = "1",
|
||||
bool is_sum = false)
|
||||
{
|
||||
if constexpr (std::is_same<ValueType, int64_t>::value)
|
||||
{
|
||||
return IntHistoFam(prefix, name, labels, default_upper_bounds,
|
||||
helptext, unit, is_sum);
|
||||
}
|
||||
else
|
||||
{
|
||||
static_assert(std::is_same<ValueType, double>::value,
|
||||
"metrics only support int64_t and double values");
|
||||
return DblHistoFam(prefix, name, labels, default_upper_bounds,
|
||||
helptext, unit, is_sum);
|
||||
}
|
||||
}
|
||||
|
||||
/// @copydoc HistogramFamily
|
||||
template <class ValueType = int64_t>
|
||||
auto HistogramFamily(std::string_view prefix, std::string_view name,
|
||||
std::initializer_list<std::string_view> labels,
|
||||
ConstSpan<ValueType> default_upper_bounds,
|
||||
std::string_view helptext, std::string_view unit = "1",
|
||||
bool is_sum = false)
|
||||
{
|
||||
auto lbl_span = Span{labels.begin(), labels.size()};
|
||||
return HistogramFamily<ValueType>(prefix, name, lbl_span,
|
||||
default_upper_bounds, helptext,
|
||||
unit, is_sum);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a histogram. Creates the family lazily if necessary.
|
||||
* @param prefix The prefix (namespace) this family belongs to. Usually the
|
||||
* application or protocol name, e.g., `http`. The prefix `caf`
|
||||
* as well as prefixes starting with an underscore are
|
||||
* reserved.
|
||||
* @param name The human-readable name of the metric, e.g., `requests`.
|
||||
* @param labels Names for all label dimensions of the metric.
|
||||
* @param default_upper_bounds Upper bounds for the metric buckets.
|
||||
* @param helptext Short explanation of the metric.
|
||||
* @param unit Unit of measurement. Please use base units such as `bytes` or
|
||||
* `seconds` (prefer lowercase). The pseudo-unit `1` identifies
|
||||
* dimensionless counts.
|
||||
* @param is_sum Setting this to `true` indicates that this metric adds
|
||||
* something up to a total, where only the total value is of
|
||||
* interest. For example, the total number of HTTP requests.
|
||||
* @note The first call wins when calling this function multiple times with
|
||||
* different bucket settings. Users may also override
|
||||
* @p default_upper_bounds via run-time configuration.
|
||||
*/
|
||||
template <class ValueType = int64_t>
|
||||
Histogram<ValueType>
|
||||
HistogramInstance(std::string_view prefix, std::string_view name,
|
||||
Span<const LabelView> labels,
|
||||
ConstSpan<ValueType> default_upper_bounds,
|
||||
std::string_view helptext, std::string_view unit = "1",
|
||||
bool is_sum = false)
|
||||
{
|
||||
return WithLabelNames(labels, [&, this](auto labelNames)
|
||||
{
|
||||
auto family = HistogramFamily<ValueType>(prefix, name, labelNames,
|
||||
default_upper_bounds,
|
||||
helptext, unit, is_sum);
|
||||
return family.getOrAdd(labels);
|
||||
});
|
||||
}
|
||||
|
||||
/// @copdoc HistogramInstance
|
||||
template <class ValueType = int64_t>
|
||||
Histogram<ValueType>
|
||||
HistogramInstance(std::string_view prefix, std::string_view name,
|
||||
std::initializer_list<LabelView> labels,
|
||||
ConstSpan<ValueType> default_upper_bounds,
|
||||
std::string_view helptext, std::string_view unit = "1",
|
||||
bool is_sum = false)
|
||||
{
|
||||
auto lbls = Span{labels.begin(), labels.size()};
|
||||
return HistogramInstance(prefix, name, lbls, default_upper_bounds,
|
||||
helptext, unit, is_sum);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a histogram metric singleton, i.e., the single instance of a
|
||||
* family without label dimensions. Creates all objects lazily if necessary,
|
||||
* but fails if the full name already belongs to a different family.
|
||||
* @param prefix The prefix (namespace) this family belongs to. Usually the
|
||||
* application or protocol name, e.g., `http`. The prefix `caf`
|
||||
* as well as prefixes starting with an underscore are
|
||||
* reserved.
|
||||
* @param name The human-readable name of the metric, e.g., `requests`.
|
||||
* @param default_upper_bounds Upper bounds for the metric buckets.
|
||||
* @param helptext Short explanation of the metric.
|
||||
* @param unit Unit of measurement. Please use base units such as `bytes` or
|
||||
* `seconds` (prefer lowercase). The pseudo-unit `1` identifies
|
||||
* dimensionless counts.
|
||||
* @param is_sum Setting this to `true` indicates that this metric adds
|
||||
* something up to a total, where only the total value is of
|
||||
* interest. For example, the total number of HTTP requests.
|
||||
* @note The first call wins when calling this function multiple times with
|
||||
* different bucket settings. Users may also override
|
||||
* @p default_upper_bounds via run-time configuration.
|
||||
*/
|
||||
template <class ValueType = int64_t>
|
||||
Histogram<ValueType>
|
||||
HistogramSingleton(std::string_view prefix, std::string_view name,
|
||||
ConstSpan<ValueType> default_upper_bounds,
|
||||
std::string_view helptext, std::string_view unit = "1",
|
||||
bool is_sum = false)
|
||||
{
|
||||
auto lbls = Span<const std::string_view>{};
|
||||
auto fam = HistogramFamily<ValueType>(prefix, name, lbls,
|
||||
default_upper_bounds, helptext,
|
||||
unit, is_sum);
|
||||
return fam.GetOrAdd({});
|
||||
}
|
||||
|
||||
private:
|
||||
IntCounterFamily
|
||||
IntCounterFam(std::string_view prefix, std::string_view name,
|
||||
|
@ -253,6 +409,18 @@ private:
|
|||
std::string_view helptext, std::string_view unit,
|
||||
bool is_sum);
|
||||
|
||||
IntHistogramFamily
|
||||
IntHistoFam(std::string_view prefix, std::string_view name,
|
||||
Span<const std::string_view> labels,
|
||||
Span<const int64_t> ubounds, std::string_view helptext,
|
||||
std::string_view unit, bool is_sum);
|
||||
|
||||
DblHistogramFamily
|
||||
DblHistoFam(std::string_view prefix, std::string_view name,
|
||||
Span<const std::string_view> labels,
|
||||
Span<const double> ubounds, std::string_view helptext,
|
||||
std::string_view unit, bool is_sum);
|
||||
|
||||
template <class F>
|
||||
static void WithLabelNames(Span<const LabelView> xs, F continuation)
|
||||
{
|
||||
|
@ -276,8 +444,6 @@ private:
|
|||
|
||||
namespace zeek {
|
||||
|
||||
// @note for technically reasons (CAF dependency), this variable gets
|
||||
// initialized in broker/Manager.cc.
|
||||
extern telemetry::Manager* telemetry_mgr;
|
||||
|
||||
} // namespace zeek
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue