Add scaffold for new metrics API with counters

This commit is contained in:
Dominik Charousset 2021-02-27 12:38:16 +01:00
parent a5e7b2fec7
commit 617e4137c6
9 changed files with 1049 additions and 0 deletions

View file

@ -159,6 +159,7 @@ set(bro_PLUGIN_DEPS CACHE INTERNAL "plugin dependencies" FORCE)
add_subdirectory(analyzer) add_subdirectory(analyzer)
add_subdirectory(packet_analysis) add_subdirectory(packet_analysis)
add_subdirectory(broker) add_subdirectory(broker)
add_subdirectory(telemetry)
add_subdirectory(zeekygen) add_subdirectory(zeekygen)
add_subdirectory(file_analysis) add_subdirectory(file_analysis)
add_subdirectory(input) add_subdirectory(input)

224
src/Span.h Normal file
View file

@ -0,0 +1,224 @@
// See the file "COPYING" in the main distribution directory for copyright.
#pragma once
#include <array>
#include <cstddef>
#include <iterator>
#include <type_traits>
namespace zeek {
/**
* Drop-in replacement for C++20's @c std::span with dynamic extent only:
* https://en.cppreference.com/w/cpp/container/span. After upgrading to C++20,
* this class may get replaced with a type alias instead and/or deprecated.
*/
template <class T>
class Span {
public:
// -- member types ---------------------------------------------------------
using element_type = T;
using value_type = typename std::remove_cv<T>::type;
using index_type = size_t;
using difference_type = ptrdiff_t;
using pointer = T*;
using const_pointer = const T*;
using reference = T&;
using const_reference = T&;
using iterator = pointer;
using const_iterator = const_pointer;
using reverse_iterator = std::reverse_iterator<iterator>;
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
// -- constructors, destructors, and assignment operators ------------------
constexpr Span() noexcept : memoryBlock(nullptr), numElements(0)
{
// nop
}
constexpr Span(pointer ptr, size_t size)
: memoryBlock(ptr), numElements(size)
{
// nop
}
constexpr Span(pointer first, pointer last)
: memoryBlock(first), numElements(static_cast<size_t>(last - first))
{
// nop
}
template <size_t Size>
constexpr Span(element_type (&arr)[Size]) noexcept
: memoryBlock(arr), numElements(Size)
{
// nop
}
template <class Container,
class Data = typename Container::value_type,
class = std::enable_if_t<std::is_convertible_v<Data*, T*>>>
Span(Container& xs) noexcept
: memoryBlock(xs.data()), numElements(xs.size())
{
// nop
}
template <class Container,
class Data = typename Container::value_type,
class = std::enable_if_t<std::is_convertible_v<const Data*, T*>>>
Span(const Container& xs) noexcept
: memoryBlock(xs.data()), numElements(xs.size())
{
// nop
}
constexpr Span(const Span&) noexcept = default;
Span& operator=(const Span&) noexcept = default;
// -- iterators ------------------------------------------------------------
constexpr iterator begin() const noexcept
{
return memoryBlock;
}
constexpr const_iterator cbegin() const noexcept
{
return memoryBlock;
}
constexpr iterator end() const noexcept
{
return begin() + numElements;
}
constexpr const_iterator cend() const noexcept
{
return cbegin() + numElements;
}
constexpr reverse_iterator rbegin() const noexcept
{
return reverse_iterator{end()};
}
constexpr const_reverse_iterator crbegin() const noexcept
{
return const_reverse_iterator{end()};
}
constexpr reverse_iterator rend() const noexcept
{
return reverse_iterator{begin()};
}
constexpr const_reverse_iterator crend() const noexcept
{
return const_reverse_iterator{begin()};
}
// -- element access -------------------------------------------------------
constexpr reference operator[](size_t index) const noexcept
{
return memoryBlock[index];
}
constexpr reference front() const noexcept
{
return *memoryBlock;
}
constexpr reference back() const noexcept
{
return (*this)[numElements - 1];
}
// -- properties -----------------------------------------------------------
constexpr size_t size() const noexcept
{
return numElements;
}
constexpr size_t numElementsbytes() const noexcept
{
return numElements * sizeof(element_type);
}
constexpr bool empty() const noexcept
{
return numElements == 0;
}
constexpr pointer data() const noexcept
{
return memoryBlock;
}
// -- subviews -------------------------------------------------------------
constexpr Span subspan(size_t offset, size_t num_bytes) const
{
return {memoryBlock + offset, num_bytes};
}
constexpr Span subspan(size_t offset) const
{
return {memoryBlock + offset, numElements - offset};
}
constexpr Span first(size_t num_bytes) const
{
return {memoryBlock, num_bytes};
}
constexpr Span last(size_t num_bytes) const
{
return subspan(numElements - num_bytes, num_bytes);
}
private:
// -- member variables -----------------------------------------------------
/// Points to the first element in the contiguous memory block.
pointer memoryBlock;
/// Stores the number of elements in the contiguous memory block.
size_t numElements;
};
// -- deduction guides ---------------------------------------------------------
template <class T>
Span(T*, size_t) -> Span<T>;
template <class Iter>
Span(Iter, Iter) -> Span<typename std::iterator_traits<Iter>::value_type>;
template <class T, size_t N>
Span(T (&)[N]) -> Span<T>;
template <class Container>
Span(Container&) -> Span<typename Container::value_type>;
template <class Container>
Span(const Container&) -> Span<const typename Container::value_type>;
} // namespace zeek

View file

@ -0,0 +1,20 @@
include(ZeekSubdir)
include_directories(BEFORE
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_BINARY_DIR}
)
set(telemetry_SRCS
Counter.cc
Manager.cc
MetricFamily.cc
)
# bif_target(comm.bif)
# bif_target(data.bif)
# bif_target(messaging.bif)
# bif_target(store.bif)
bro_add_subdir_library(telemetry ${telemetry_SRCS})

164
src/telemetry/Counter.cc Normal file
View file

@ -0,0 +1,164 @@
// See the file "COPYING" in the main distribution directory for copyright.
#include "zeek/telemetry/Counter.h"
#include "caf/telemetry/counter.hpp"
#include "caf/telemetry/metric_family.hpp"
#include "caf/telemetry/metric_family_impl.hpp"
namespace zeek::telemetry {
// -- private utilities --------------------------------------------------------
namespace {
namespace ct = caf::telemetry;
using NativeMetricFamily = ct::metric_family;
using NativeIntCounter = ct::int_counter;
using NativeIntCounterFamily = ct::metric_family_impl<NativeIntCounter>;
using NativeDblCounter = ct::dbl_counter;
using NativeDblCounterFamily = ct::metric_family_impl<NativeDblCounter>;
auto& deref(IntCounter::Impl* ptr)
{
return *reinterpret_cast<NativeIntCounter*>(ptr);
}
auto& deref(IntCounterFamily*, MetricFamily::Impl* ptr)
{
auto basePtr = reinterpret_cast<NativeMetricFamily*>(ptr);
return *static_cast<NativeIntCounterFamily*>(basePtr);
}
auto upcast(IntCounterFamily::Impl* ptr)
{
auto native = reinterpret_cast<NativeIntCounterFamily*>(ptr);
auto basePtr = static_cast<NativeMetricFamily*>(native);
return reinterpret_cast<MetricFamily::Impl*>(basePtr);
}
auto opaque(NativeIntCounter* ptr)
{
return reinterpret_cast<IntCounter::Impl*>(ptr);
}
auto& deref(DblCounter::Impl* ptr)
{
return *reinterpret_cast<ct::dbl_counter*>(ptr);
}
auto& deref(DblCounterFamily*, MetricFamily::Impl* ptr)
{
auto basePtr = reinterpret_cast<NativeMetricFamily*>(ptr);
return *static_cast<NativeDblCounterFamily*>(basePtr);
}
auto upcast(DblCounterFamily::Impl* ptr)
{
auto native = reinterpret_cast<NativeDblCounterFamily*>(ptr);
auto basePtr = static_cast<NativeMetricFamily*>(native);
return reinterpret_cast<MetricFamily::Impl*>(basePtr);
}
auto opaque(NativeDblCounter* ptr)
{
return reinterpret_cast<DblCounter::Impl*>(ptr);
}
template <class F>
auto withNativeLabels(Span<const LabelView> xs, F continuation)
{
if (xs.size() <= 10)
{
ct::label_view buf[10]={
{{},{}}, {{},{}}, {{},{}}, {{},{}}, {{},{}},
{{},{}}, {{},{}}, {{},{}}, {{},{}}, {{},{}},
};
for (size_t index = 0; index < xs.size(); ++index)
buf[index] = ct::label_view{xs[index].first, xs[index].second};
return continuation(Span{buf, xs.size()});
}
else
{
std::vector<ct::label_view> buf;
for (auto x : xs)
buf.emplace_back(x.first, x.second);
return continuation(Span{buf});
}
}
} // namespace
// -- IntCounter ---------------------------------------------------------------
void IntCounter::inc() noexcept
{
deref(pimpl).inc();
}
void IntCounter::inc(int64_t amount) noexcept
{
deref(pimpl).inc(amount);
}
int64_t IntCounter::operator++() noexcept
{
return ++deref(pimpl);
}
int64_t IntCounter::value() const noexcept
{
return deref(pimpl).value();
}
IntCounterFamily::IntCounterFamily(Impl* ptr) : MetricFamily(upcast(ptr))
{
// nop
}
IntCounter IntCounterFamily::getOrAdd(Span<const LabelView> labels)
{
return withNativeLabels(labels, [this](auto nativeLabels)
{
auto hdl = opaque(deref(this, pimpl).get_or_add(nativeLabels));
return IntCounter{hdl};
});
}
// -- DblCounter ---------------------------------------------------------------
void DblCounter::inc() noexcept
{
deref(pimpl).inc();
}
void DblCounter::inc(double amount) noexcept
{
deref(pimpl).inc(amount);
}
double DblCounter::value() const noexcept
{
return deref(pimpl).value();
}
DblCounterFamily::DblCounterFamily(Impl* ptr) : MetricFamily(upcast(ptr))
{
// nop
}
DblCounter DblCounterFamily::getOrAdd(Span<const LabelView> labels)
{
return withNativeLabels(labels, [this](auto nativeLabels)
{
auto hdl = opaque(deref(this, pimpl).get_or_add(nativeLabels));
return DblCounter{hdl};
});
}
} // namespace zeek::telemetry

236
src/telemetry/Counter.h Normal file
View file

@ -0,0 +1,236 @@
// 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 DblCounterFamily;
class IntCounterFamily;
class Manager;
/**
* A handle to a metric that represents an integer value that can only go up.
*/
class IntCounter {
public:
friend class IntCounterFamily;
struct Impl;
IntCounter() = delete;
IntCounter(const IntCounter&) noexcept = default;
IntCounter& operator=(const IntCounter&) noexcept = default;
/**
* Increments the value by 1.
*/
void inc() noexcept;
/**
* Increments the value by @p amount.
* @pre `amount >= 0`
*/
void inc(int64_t amount) noexcept;
/**
* Increments the value by 1.
* @returns the new value.
*/
int64_t operator++() noexcept;
/**
* @returns the current value.
*/
int64_t value() const noexcept;
/**
* @returns whether @c this and @p other refer to the same counter.
*/
constexpr bool isSameAs(IntCounter other) const noexcept
{
return pimpl == other.pimpl;
}
private:
explicit IntCounter(Impl* ptr) noexcept : pimpl(ptr)
{
// nop
}
Impl* pimpl;
};
/**
* Checks whether two @ref IntCounter handles are identical.
* @returns whether @p lhs and @p rhs refer to the same object.
* @note compare their @c value instead to check for equality.
*/
constexpr bool operator==(IntCounter lhs, IntCounter rhs) noexcept
{
return lhs.isSameAs(rhs);
}
/// @relates IntCounter
constexpr bool operator!=(IntCounter lhs, IntCounter rhs) noexcept
{
return !(lhs == rhs);
}
/**
* Manages a collection of IntCounter metrics.
*/
class IntCounterFamily : public MetricFamily {
public:
friend class Manager;
class Impl;
IntCounterFamily(const IntCounterFamily&) noexcept = default;
IntCounterFamily& operator=(const IntCounterFamily&) noexcept = default;
/**
* Returns the metrics handle for given labels, creating a new instance
* lazily if necessary.
*/
IntCounter getOrAdd(Span<const LabelView> labels);
/**
* @copydoc getOrAdd
*/
IntCounter getOrAdd(std::initializer_list<LabelView> labels)
{
return getOrAdd(Span{labels.begin(), labels.size()});
}
private:
explicit IntCounterFamily(Impl* ptr);
};
/**
* A handle to a metric that represents a floating point value that can only go
* up.
*/
class DblCounter {
public:
friend class DblCounterFamily;
struct Impl;
DblCounter() = delete;
DblCounter(const DblCounter&) noexcept = default;
DblCounter& operator=(const DblCounter&) noexcept = default;
/**
* Increments the value by 1.
*/
void inc() noexcept;
/**
* Increments the value by @p amount.
* @pre `amount >= 0`
*/
void inc(double amount) noexcept;
/**
* @returns the current value.
*/
double value() const noexcept;
/**
* @returns whether @c this and @p other refer to the same counter.
*/
constexpr bool isSameAs(DblCounter other) const noexcept
{
return pimpl == other.pimpl;
}
private:
explicit DblCounter(Impl* ptr) noexcept : pimpl(ptr)
{
// nop
}
Impl* pimpl;
};
/**
* Checks whether two @ref DblCounter handles are identical.
* @returns whether @p lhs and @p rhs refer to the same object.
* @note compare their @c value instead to check for equality.
*/
constexpr bool operator==(DblCounter lhs, DblCounter rhs) noexcept
{
return lhs.isSameAs(rhs);
}
/// @relates DblCounter
constexpr bool operator!=(DblCounter lhs, DblCounter rhs) noexcept
{
return !(lhs == rhs);
}
/**
* Manages a collection of DblCounter metrics.
*/
class DblCounterFamily : public MetricFamily {
public:
friend class Manager;
class Impl;
DblCounterFamily(const DblCounterFamily&) noexcept = default;
DblCounterFamily& operator=(const DblCounterFamily&) noexcept = default;
/**
* Returns the metrics handle for given labels, creating a new instance
* lazily if necessary.
*/
DblCounter getOrAdd(Span<const LabelView> labels);
/**
* @copydoc getOrAdd
*/
DblCounter getOrAdd(std::initializer_list<LabelView> labels)
{
return getOrAdd(Span{labels.begin(), labels.size()});
}
private:
explicit DblCounterFamily(Impl* ptr);
};
namespace detail {
template <class T>
struct CounterOracle {
static_assert(std::is_same<T, int64_t>::value,
"Counter<T> only supports int64_t and double");
using type = IntCounter;
using family_type = IntCounterFamily;
};
template <>
struct CounterOracle<double> {
using type = DblCounter;
using family_type = DblCounterFamily;
};
} // namespace detail
template <class T>
using Counter = typename detail::CounterOracle<T>::type;
template <class T>
using CounterFamily = typename detail::CounterOracle<T>::family_type;
} // namespace zeek::telemetry

159
src/telemetry/Manager.cc Normal file
View file

@ -0,0 +1,159 @@
// See the file "COPYING" in the main distribution directory for copyright.
#include "zeek/telemetry/Manager.h"
#include "caf/telemetry/metric_registry.hpp"
#include "zeek/3rdparty/doctest.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>;
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);
}
template <class F>
auto withNative(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
IntCounterFamily Manager::intCounterFam(std::string_view prefix,
std::string_view name,
Span<const std::string_view> labels,
std::string_view helptext,
std::string_view unit, bool isSum)
{
return withNative(labels, [&, this](auto xs)
{
auto ptr = deref(pimpl).counter_family(prefix, name, xs,
helptext, unit, isSum);
return IntCounterFamily{opaque(ptr)};
});
}
DblCounterFamily Manager::dblCounterFam(std::string_view prefix,
std::string_view name,
Span<const std::string_view> labels,
std::string_view helptext,
std::string_view unit, bool isSum)
{
return withNative(labels, [&, this](auto xs)
{
auto ptr = deref(pimpl).counter_family<double>(prefix, name, xs,
helptext, unit, isSum);
return DblCounterFamily{opaque(ptr)};
});
}
} // namespace zeek::telemetry
// -- unit tests ---------------------------------------------------------------
using namespace zeek::telemetry;
SCENARIO("telemetry managers provide access to counters")
{
GIVEN("a telemetry manager")
{
NativeManager nativeMgr;
Manager mgr{opaque(&nativeMgr)};
WHEN("retrieving an IntCounter singleton")
{
auto first = mgr.counterSingleton("zeek", "int-count", "test");
THEN("its initial value is zero")
{
CHECK_EQ(first.value(), 0);
}
AND_THEN("calling inc() or operator++ changes the value")
{
first.inc();
CHECK_EQ(first.value(), 1);
first.inc(2);
CHECK_EQ(first.value(), 3);
CHECK_EQ(++first, 4);
CHECK_EQ(first.value(), 4);
}
AND_THEN("calling counterSingleton again for the same name returns the same handle")
{
auto second = mgr.counterSingleton("zeek", "int-count", "test");
CHECK_EQ(first, second);
}
AND_THEN("calling counterSingleton for a different name returns another handle")
{
auto third = mgr.counterSingleton("zeek", "int-count-2", "test");
CHECK_NE(first, third);
}
}
WHEN("retrieving a DblCounter singleton")
{
auto first = mgr.counterSingleton<double>("zeek", "dbl-count", "test");
THEN("its initial value is zero")
{
CHECK_EQ(first.value(), 0.0);
}
AND_THEN("calling inc() changes the value")
{
first.inc();
CHECK_EQ(first.value(), 1.0);
first.inc(3.0);
CHECK_EQ(first.value(), 4.0);
}
AND_THEN("calling counterSingleton again for the same name returns the same handle")
{
auto second = mgr.counterSingleton<double>("zeek", "dbl-count", "test");
CHECK_EQ(first, second);
}
AND_THEN("calling counterSingleton for a different name returns another handle")
{
auto third = mgr.counterSingleton<double>("zeek", "dbl-count-2", "test");
CHECK_NE(first, third);
}
}
}
}

168
src/telemetry/Manager.h Normal file
View file

@ -0,0 +1,168 @@
// See the file "COPYING" in the main distribution directory for copyright.
#pragma once
#include <cstdint>
#include <initializer_list>
#include <string_view>
#include <vector>
#include "zeek/Span.h"
#include "zeek/telemetry/Counter.h"
namespace zeek::telemetry {
/**
* Manages a collection of metric families.
*/
class Manager {
public:
class Impl;
explicit Manager(Impl* ptr) : pimpl(ptr)
{
//nop
}
Manager(const Manager&) = delete;
Manager& operator=(const Manager&) = delete;
/**
* @returns a counter metric family. Creates the family lazily if necessary.
* @param prefix The prefix (namespace) this family belongs to.
* @param name The human-readable name of the metric, e.g., `requests`.
* @param labels Names for all label dimensions of the metric.
* @param helptext Short explanation of the metric.
* @param unit Unit of measurement.
* @param isSum Indicates whether this metric accumulates something, where
* only the total value is of interest.
*/
template <class ValueType = int64_t>
CounterFamily<ValueType>
counterFamily(std::string_view prefix, std::string_view name,
Span<const std::string_view> labels,
std::string_view helptext,
std::string_view unit = "1", bool isSum = false) {
if constexpr (std::is_same<ValueType, int64_t>::value)
{
return intCounterFam(prefix, name, labels, helptext, unit, isSum);
}
else
{
static_assert(std::is_same<ValueType, double>::value,
"metrics only support int64_t and double values");
return dblCounterFam(prefix, name, labels, helptext, unit, isSum);
}
}
/// @copydoc counterFamily
template <class ValueType = int64_t>
CounterFamily<ValueType>
counterFamily(std::string_view prefix, std::string_view name,
std::initializer_list<std::string_view> labels,
std::string_view helptext, std::string_view unit = "1",
bool isSum = false)
{
auto lblSpan = Span{labels.begin(), labels.size()};
return counterFamily<ValueType>(prefix, name, lblSpan, helptext,
unit, isSum);
}
/**
* Accesses a counter instance. Creates the hosting metric family as well
* as the counter lazily if necessary.
* @param prefix The prefix (namespace) this family belongs to.
* @param name The human-readable name of the metric, e.g., `requests`.
* @param labels Values for all label dimensions of the metric.
* @param helptext Short explanation of the metric.
* @param unit Unit of measurement.
* @param isSum Indicates whether this metric accumulates something, where
* only the total value is of interest.
*/
template <class ValueType = int64_t>
Counter<ValueType>
counterInstance(std::string_view prefix, std::string_view name,
Span<const LabelView> labels, std::string_view helptext,
std::string_view unit = "1", bool isSum = false)
{
return withLabelNames(labels, [&, this](auto labelNames)
{
auto family = counterFamily<ValueType>(prefix, name, labelNames,
helptext, unit, isSum);
return family.getOrAdd(labels);
});
}
/// @copydoc counterInstance
template <class ValueType = int64_t>
Counter<ValueType>
counterInstance(std::string_view prefix, std::string_view name,
std::initializer_list<LabelView> labels,
std::string_view helptext, std::string_view unit = "1",
bool isSum = false)
{
auto lblSpan = Span{labels.begin(), labels.size()};
return counterInstance(prefix, name, lblSpan, helptext, unit, isSum);
}
/**
* Accesses a counter singleton, i.e., a counter that belongs to a family
* without label dimensions (which thus only has a single member). Creates
* the hosting metric family as well as the counter lazily if necessary.
* @param prefix The prefix (namespace) this family belongs to.
* @param name The human-readable name of the metric, e.g., `requests`.
* @param helptext Short explanation of the metric.
* @param unit Unit of measurement.
* @param isSum Indicates whether this metric accumulates something, where
* only the total value is of interest.
*/
template <class ValueType = int64_t>
Counter<ValueType>
counterSingleton(std::string_view prefix, std::string_view name,
std::string_view helptext, std::string_view unit = "1",
bool isSum = false)
{
auto labels = Span<const std::string_view>{};
auto fam = counterFamily<ValueType>(prefix, name, labels, helptext,
unit, isSum);
return fam.getOrAdd({});
}
private:
IntCounterFamily
intCounterFam(std::string_view prefix, std::string_view name,
Span<const std::string_view> labels,
std::string_view helptext, std::string_view unit, bool isSum);
DblCounterFamily
dblCounterFam(std::string_view prefix, std::string_view name,
Span<const std::string_view> labels,
std::string_view helptext, std::string_view unit, bool isSum);
template <class F>
static void withLabelNames(Span<const LabelView> xs, F continuation)
{
if (xs.size() <= 10) {
std::string_view buf[10];
for (size_t index = 0; index < xs.size(); ++index)
buf[index] = xs[index].first;
return continuation(Span{buf, xs.size()});
} else {
std::vector<std::string_view> buf;
for (auto x : xs)
buf.emplace_back(x.first, x.second);
return continuation(Span{buf});
}
}
Impl* pimpl;
};
} // namespace zeek::telemetry
namespace zeek {
extern telemetry::Manager* telemetry_mgr;
} // namespace zeek

View file

View file

@ -0,0 +1,77 @@
// See the file "COPYING" in the main distribution directory for copyright.
#pragma once
#include <string>
#include <string_view>
#include <utility>
#include "Span.h"
namespace zeek::telemetry {
/**
* A key-value pair for a single label dimension.
*/
using LabelView = std::pair<std::string_view, std::string_view>;
/**
* Manages a collection (family) of metrics. All members of the family share
* the same prefix (namespace), name, and label dimensions.
*/
class MetricFamily {
public:
struct Impl;
MetricFamily() = delete;
MetricFamily(const MetricFamily&) noexcept = default;
MetricFamily& operator=(const MetricFamily&) noexcept = default;
/**
* @returns the prefix (namespace) this family belongs to. Builtin metrics
* of Zeek return @c zeek. Custom metrics, e.g., created in a
* script, may use a prefix that represents the application/script
* or protocol (e.g. @c http) name.
*/
std::string_view prefix() const noexcept;
/**
* @returns the human-readable name of the metric, e.g.,
* @p open-connections.
*/
std::string_view name() const noexcept;
/**
* @returns the names for all label dimensions.
*/
Span<const std::string> label_names() const noexcept;
/**
* @returns a short explanation of the metric.
*/
std::string_view helptext() const noexcept;
/**
* @returns the unit of measurement, preferably a base unit such as
* @c bytes or @c seconds. Dimensionless counts return the
* pseudo-unit @c 1.
*/
std::string_view unit() const noexcept;
/**
* @returns whether metrics of this family accumulate values, where only the
* total value is of interest. For example, the total number of
* HTTP requests.
*/
bool isSum() const noexcept;
protected:
explicit MetricFamily(Impl* ptr) : pimpl(ptr)
{
// nop
}
Impl* pimpl;
};
} // namespace zeek::telemetry