From 617e4137c6d22032a1c3d09239a73c121885c71e Mon Sep 17 00:00:00 2001 From: Dominik Charousset Date: Sat, 27 Feb 2021 12:38:16 +0100 Subject: [PATCH 01/13] Add scaffold for new metrics API with counters --- src/CMakeLists.txt | 1 + src/Span.h | 224 ++++++++++++++++++++++++++++++++ src/telemetry/CMakeLists.txt | 20 +++ src/telemetry/Counter.cc | 164 +++++++++++++++++++++++ src/telemetry/Counter.h | 236 ++++++++++++++++++++++++++++++++++ src/telemetry/Manager.cc | 159 +++++++++++++++++++++++ src/telemetry/Manager.h | 168 ++++++++++++++++++++++++ src/telemetry/MetricFamily.cc | 0 src/telemetry/MetricFamily.h | 77 +++++++++++ 9 files changed, 1049 insertions(+) create mode 100644 src/Span.h create mode 100644 src/telemetry/CMakeLists.txt create mode 100644 src/telemetry/Counter.cc create mode 100644 src/telemetry/Counter.h create mode 100644 src/telemetry/Manager.cc create mode 100644 src/telemetry/Manager.h create mode 100644 src/telemetry/MetricFamily.cc create mode 100644 src/telemetry/MetricFamily.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 93d25c63ea..94cacbd5ea 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -159,6 +159,7 @@ set(bro_PLUGIN_DEPS CACHE INTERNAL "plugin dependencies" FORCE) add_subdirectory(analyzer) add_subdirectory(packet_analysis) add_subdirectory(broker) +add_subdirectory(telemetry) add_subdirectory(zeekygen) add_subdirectory(file_analysis) add_subdirectory(input) diff --git a/src/Span.h b/src/Span.h new file mode 100644 index 0000000000..e78af1ab11 --- /dev/null +++ b/src/Span.h @@ -0,0 +1,224 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#pragma once + +#include +#include +#include +#include + +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 Span { +public: + // -- member types --------------------------------------------------------- + + using element_type = T; + + using value_type = typename std::remove_cv::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; + + using const_reverse_iterator = std::reverse_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(last - first)) + { + // nop + } + + template + constexpr Span(element_type (&arr)[Size]) noexcept + : memoryBlock(arr), numElements(Size) + { + // nop + } + + template >> + Span(Container& xs) noexcept + : memoryBlock(xs.data()), numElements(xs.size()) + { + // nop + } + + template >> + 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 +Span(T*, size_t) -> Span; + +template +Span(Iter, Iter) -> Span::value_type>; + +template +Span(T (&)[N]) -> Span; + +template +Span(Container&) -> Span; + +template +Span(const Container&) -> Span; + +} // namespace zeek diff --git a/src/telemetry/CMakeLists.txt b/src/telemetry/CMakeLists.txt new file mode 100644 index 0000000000..867805aa38 --- /dev/null +++ b/src/telemetry/CMakeLists.txt @@ -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}) + diff --git a/src/telemetry/Counter.cc b/src/telemetry/Counter.cc new file mode 100644 index 0000000000..88f9ec74c2 --- /dev/null +++ b/src/telemetry/Counter.cc @@ -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; + +using NativeDblCounter = ct::dbl_counter; + +using NativeDblCounterFamily = ct::metric_family_impl; + +auto& deref(IntCounter::Impl* ptr) + { + return *reinterpret_cast(ptr); + } + +auto& deref(IntCounterFamily*, MetricFamily::Impl* ptr) + { + auto basePtr = reinterpret_cast(ptr); + return *static_cast(basePtr); + } + +auto upcast(IntCounterFamily::Impl* ptr) + { + auto native = reinterpret_cast(ptr); + auto basePtr = static_cast(native); + return reinterpret_cast(basePtr); + } + +auto opaque(NativeIntCounter* ptr) + { + return reinterpret_cast(ptr); + } + +auto& deref(DblCounter::Impl* ptr) + { + return *reinterpret_cast(ptr); + } + +auto& deref(DblCounterFamily*, MetricFamily::Impl* ptr) + { + auto basePtr = reinterpret_cast(ptr); + return *static_cast(basePtr); + } + +auto upcast(DblCounterFamily::Impl* ptr) + { + auto native = reinterpret_cast(ptr); + auto basePtr = static_cast(native); + return reinterpret_cast(basePtr); + } + +auto opaque(NativeDblCounter* ptr) + { + return reinterpret_cast(ptr); + } + +template +auto withNativeLabels(Span 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 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 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 labels) + { + return withNativeLabels(labels, [this](auto nativeLabels) + { + auto hdl = opaque(deref(this, pimpl).get_or_add(nativeLabels)); + return DblCounter{hdl}; + }); + } + +} // namespace zeek::telemetry diff --git a/src/telemetry/Counter.h b/src/telemetry/Counter.h new file mode 100644 index 0000000000..259726b6ac --- /dev/null +++ b/src/telemetry/Counter.h @@ -0,0 +1,236 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#pragma once + +#include +#include +#include + +#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 labels); + + /** + * @copydoc getOrAdd + */ + IntCounter getOrAdd(std::initializer_list 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 labels); + + /** + * @copydoc getOrAdd + */ + DblCounter getOrAdd(std::initializer_list labels) + { + return getOrAdd(Span{labels.begin(), labels.size()}); + } + +private: + explicit DblCounterFamily(Impl* ptr); +}; + +namespace detail { + +template +struct CounterOracle { + static_assert(std::is_same::value, + "Counter only supports int64_t and double"); + + using type = IntCounter; + + using family_type = IntCounterFamily; +}; + +template <> +struct CounterOracle { + using type = DblCounter; + + using family_type = DblCounterFamily; +}; + +} // namespace detail + +template +using Counter = typename detail::CounterOracle::type; + +template +using CounterFamily = typename detail::CounterOracle::family_type; + +} // namespace zeek::telemetry diff --git a/src/telemetry/Manager.cc b/src/telemetry/Manager.cc new file mode 100644 index 0000000000..f9765bef85 --- /dev/null +++ b/src/telemetry/Manager.cc @@ -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; + +using NativeDblCounter = ct::dbl_counter; + +using NativeDblCounterFamily = ct::metric_family_impl; + +auto& deref(Manager::Impl* ptr) + { + return *reinterpret_cast(ptr); + } + +auto opaque(NativeManager* ptr) + { + return reinterpret_cast(ptr); + } + +auto opaque(NativeIntCounterFamily* ptr) + { + return reinterpret_cast(ptr); + } + +auto opaque(NativeDblCounterFamily* ptr) + { + return reinterpret_cast(ptr); + } + +template +auto withNative(Span 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 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 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 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 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("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("zeek", "dbl-count", "test"); + CHECK_EQ(first, second); + } + AND_THEN("calling counterSingleton for a different name returns another handle") + { + auto third = mgr.counterSingleton("zeek", "dbl-count-2", "test"); + CHECK_NE(first, third); + } + } + } + } diff --git a/src/telemetry/Manager.h b/src/telemetry/Manager.h new file mode 100644 index 0000000000..3206b3ed25 --- /dev/null +++ b/src/telemetry/Manager.h @@ -0,0 +1,168 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#pragma once + +#include +#include +#include +#include + +#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 + CounterFamily + counterFamily(std::string_view prefix, std::string_view name, + Span labels, + std::string_view helptext, + std::string_view unit = "1", bool isSum = false) { + if constexpr (std::is_same::value) + { + return intCounterFam(prefix, name, labels, helptext, unit, isSum); + } + else + { + static_assert(std::is_same::value, + "metrics only support int64_t and double values"); + return dblCounterFam(prefix, name, labels, helptext, unit, isSum); + } + } + + /// @copydoc counterFamily + template + CounterFamily + counterFamily(std::string_view prefix, std::string_view name, + std::initializer_list labels, + std::string_view helptext, std::string_view unit = "1", + bool isSum = false) + { + auto lblSpan = Span{labels.begin(), labels.size()}; + return counterFamily(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 + Counter + counterInstance(std::string_view prefix, std::string_view name, + Span labels, std::string_view helptext, + std::string_view unit = "1", bool isSum = false) + { + return withLabelNames(labels, [&, this](auto labelNames) + { + auto family = counterFamily(prefix, name, labelNames, + helptext, unit, isSum); + return family.getOrAdd(labels); + }); + } + + /// @copydoc counterInstance + template + Counter + counterInstance(std::string_view prefix, std::string_view name, + std::initializer_list 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 + Counter + counterSingleton(std::string_view prefix, std::string_view name, + std::string_view helptext, std::string_view unit = "1", + bool isSum = false) + { + auto labels = Span{}; + auto fam = counterFamily(prefix, name, labels, helptext, + unit, isSum); + return fam.getOrAdd({}); + } + +private: + IntCounterFamily + intCounterFam(std::string_view prefix, std::string_view name, + Span labels, + std::string_view helptext, std::string_view unit, bool isSum); + + DblCounterFamily + dblCounterFam(std::string_view prefix, std::string_view name, + Span labels, + std::string_view helptext, std::string_view unit, bool isSum); + + template + static void withLabelNames(Span 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 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 diff --git a/src/telemetry/MetricFamily.cc b/src/telemetry/MetricFamily.cc new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/telemetry/MetricFamily.h b/src/telemetry/MetricFamily.h new file mode 100644 index 0000000000..efac9a33ed --- /dev/null +++ b/src/telemetry/MetricFamily.h @@ -0,0 +1,77 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#pragma once + +#include +#include +#include + +#include "Span.h" + +namespace zeek::telemetry { + +/** + * A key-value pair for a single label dimension. + */ +using LabelView = std::pair; + +/** + * 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 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 From 59d114005ec130df5efaaf3681ecf50f1af3c0ae Mon Sep 17 00:00:00 2001 From: Dominik Charousset Date: Sat, 27 Feb 2021 14:40:13 +0100 Subject: [PATCH 02/13] Add gauge metric types --- src/telemetry/CMakeLists.txt | 1 + src/telemetry/Gauge.cc | 189 ++++++++++++++++++++++++ src/telemetry/Gauge.h | 262 ++++++++++++++++++++++++++++++++++ src/telemetry/Manager.cc | 250 +++++++++++++++++++++++++++++++- src/telemetry/Manager.h | 112 +++++++++++++++ src/telemetry/MetricFamily.cc | 52 +++++++ src/telemetry/MetricFamily.h | 2 +- 7 files changed, 866 insertions(+), 2 deletions(-) create mode 100644 src/telemetry/Gauge.cc create mode 100644 src/telemetry/Gauge.h diff --git a/src/telemetry/CMakeLists.txt b/src/telemetry/CMakeLists.txt index 867805aa38..004ab29b42 100644 --- a/src/telemetry/CMakeLists.txt +++ b/src/telemetry/CMakeLists.txt @@ -7,6 +7,7 @@ include_directories(BEFORE set(telemetry_SRCS Counter.cc + Gauge.cc Manager.cc MetricFamily.cc ) diff --git a/src/telemetry/Gauge.cc b/src/telemetry/Gauge.cc new file mode 100644 index 0000000000..2d9616b10c --- /dev/null +++ b/src/telemetry/Gauge.cc @@ -0,0 +1,189 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#include "zeek/telemetry/Gauge.h" + +#include "caf/telemetry/gauge.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 NativeIntGauge = ct::int_gauge; + +using NativeIntGaugeFamily = ct::metric_family_impl; + +using NativeDblGauge = ct::dbl_gauge; + +using NativeDblGaugeFamily = ct::metric_family_impl; + +auto& deref(IntGauge::Impl* ptr) + { + return *reinterpret_cast(ptr); + } + +auto& deref(IntGaugeFamily*, MetricFamily::Impl* ptr) + { + auto basePtr = reinterpret_cast(ptr); + return *static_cast(basePtr); + } + +auto upcast(IntGaugeFamily::Impl* ptr) + { + auto native = reinterpret_cast(ptr); + auto basePtr = static_cast(native); + return reinterpret_cast(basePtr); + } + +auto opaque(NativeIntGauge* ptr) + { + return reinterpret_cast(ptr); + } + +auto& deref(DblGauge::Impl* ptr) + { + return *reinterpret_cast(ptr); + } + +auto& deref(DblGaugeFamily*, MetricFamily::Impl* ptr) + { + auto basePtr = reinterpret_cast(ptr); + return *static_cast(basePtr); + } + +auto upcast(DblGaugeFamily::Impl* ptr) + { + auto native = reinterpret_cast(ptr); + auto basePtr = static_cast(native); + return reinterpret_cast(basePtr); + } + +auto opaque(NativeDblGauge* ptr) + { + return reinterpret_cast(ptr); + } + +template +auto withNativeLabels(Span 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 buf; + for (auto x : xs) + buf.emplace_back(x.first, x.second); + return continuation(Span{buf}); + } + } + +} // namespace + +// -- IntGauge --------------------------------------------------------------- + +void IntGauge::inc() noexcept + { + deref(pimpl).inc(); + } + +void IntGauge::inc(int64_t amount) noexcept + { + deref(pimpl).inc(amount); + } + +void IntGauge::dec() noexcept + { + deref(pimpl).dec(); + } + +void IntGauge::dec(int64_t amount) noexcept + { + deref(pimpl).dec(amount); + } + +int64_t IntGauge::operator++() noexcept + { + return ++deref(pimpl); + } + +int64_t IntGauge::operator--() noexcept + { + return --deref(pimpl); + } + +int64_t IntGauge::value() const noexcept + { + return deref(pimpl).value(); + } + +IntGaugeFamily::IntGaugeFamily(Impl* ptr) : MetricFamily(upcast(ptr)) + { + // nop + } + +IntGauge IntGaugeFamily::getOrAdd(Span labels) + { + return withNativeLabels(labels, [this](auto nativeLabels) + { + auto hdl = opaque(deref(this, pimpl).get_or_add(nativeLabels)); + return IntGauge{hdl}; + }); + } + +// -- DblGauge --------------------------------------------------------------- + +void DblGauge::inc() noexcept + { + deref(pimpl).inc(); + } + +void DblGauge::inc(double amount) noexcept + { + deref(pimpl).inc(amount); + } + +void DblGauge::dec() noexcept + { + deref(pimpl).dec(); + } + +void DblGauge::dec(double amount) noexcept + { + deref(pimpl).dec(amount); + } + +double DblGauge::value() const noexcept + { + return deref(pimpl).value(); + } + +DblGaugeFamily::DblGaugeFamily(Impl* ptr) : MetricFamily(upcast(ptr)) + { + // nop + } + +DblGauge DblGaugeFamily::getOrAdd(Span labels) + { + return withNativeLabels(labels, [this](auto nativeLabels) + { + auto hdl = opaque(deref(this, pimpl).get_or_add(nativeLabels)); + return DblGauge{hdl}; + }); + } + +} // namespace zeek::telemetry diff --git a/src/telemetry/Gauge.h b/src/telemetry/Gauge.h new file mode 100644 index 0000000000..2f83b75462 --- /dev/null +++ b/src/telemetry/Gauge.h @@ -0,0 +1,262 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#pragma once + +#include +#include +#include + +#include "zeek/Span.h" +#include "zeek/telemetry/MetricFamily.h" + +namespace zeek::telemetry { + +class DblGaugeFamily; +class IntGaugeFamily; +class Manager; + +/** + * A handle to a metric that represents an integer value. Gauges are less + * permissive than counters and also allow decrementing the value. + */ +class IntGauge { +public: + friend class IntGaugeFamily; + + struct Impl; + + IntGauge() = delete; + IntGauge(const IntGauge&) noexcept = default; + IntGauge& operator=(const IntGauge&) noexcept = default; + + /** + * Increments the value by 1. + */ + void inc() noexcept; + + /** + * Increments the value by @p amount. + */ + void inc(int64_t amount) noexcept; + + /** + * Increments the value by 1. + * @returns the new value. + */ + int64_t operator++() noexcept; + + /** + * Decrements the value by 1. + */ + void dec() noexcept; + + /** + * Decrements the value by @p amount. + */ + void dec(int64_t amount) noexcept; + + /** + * Decrements 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(IntGauge other) const noexcept + { + return pimpl == other.pimpl; + } + +private: + explicit IntGauge(Impl* ptr) noexcept : pimpl(ptr) + { + // nop + } + + Impl* pimpl; +}; + +/** + * Checks whether two @ref IntGauge 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==(IntGauge lhs, IntGauge rhs) noexcept + { + return lhs.isSameAs(rhs); + } + +/// @relates IntGauge +constexpr bool operator!=(IntGauge lhs, IntGauge rhs) noexcept + { + return !(lhs == rhs); + } + +/** + * Manages a collection of IntGauge metrics. + */ +class IntGaugeFamily : public MetricFamily { +public: + friend class Manager; + + class Impl; + + IntGaugeFamily(const IntGaugeFamily&) noexcept = default; + IntGaugeFamily& operator=(const IntGaugeFamily&) noexcept = default; + + /** + * Returns the metrics handle for given labels, creating a new instance + * lazily if necessary. + */ + IntGauge getOrAdd(Span labels); + + /** + * @copydoc getOrAdd + */ + IntGauge getOrAdd(std::initializer_list labels) + { + return getOrAdd(Span{labels.begin(), labels.size()}); + } + +private: + explicit IntGaugeFamily(Impl* ptr); +}; + +/** + * A handle to a metric that represents a floating point value. Gauges are less + * permissive than counters and also allow decrementing the value. + * up. + */ +class DblGauge { +public: + friend class DblGaugeFamily; + + struct Impl; + + DblGauge() = delete; + DblGauge(const DblGauge&) noexcept = default; + DblGauge& operator=(const DblGauge&) noexcept = default; + + /** + * Increments the value by 1. + */ + void inc() noexcept; + + /** + * Increments the value by @p amount. + */ + void inc(double amount) noexcept; + + /** + * Increments the value by 1. + */ + void dec() noexcept; + + /** + * Increments the value by @p amount. + */ + void dec(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(DblGauge other) const noexcept + { + return pimpl == other.pimpl; + } + +private: + explicit DblGauge(Impl* ptr) noexcept : pimpl(ptr) + { + // nop + } + + Impl* pimpl; +}; + +/** + * Checks whether two @ref DblGauge 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==(DblGauge lhs, DblGauge rhs) noexcept + { + return lhs.isSameAs(rhs); + } + +/// @relates DblGauge +constexpr bool operator!=(DblGauge lhs, DblGauge rhs) noexcept + { + return !(lhs == rhs); + } + +/** + * Manages a collection of DblGauge metrics. + */ +class DblGaugeFamily : public MetricFamily { +public: + friend class Manager; + + class Impl; + + DblGaugeFamily(const DblGaugeFamily&) noexcept = default; + DblGaugeFamily& operator=(const DblGaugeFamily&) noexcept = default; + + /** + * Returns the metrics handle for given labels, creating a new instance + * lazily if necessary. + */ + DblGauge getOrAdd(Span labels); + + /** + * @copydoc getOrAdd + */ + DblGauge getOrAdd(std::initializer_list labels) + { + return getOrAdd(Span{labels.begin(), labels.size()}); + } + +private: + explicit DblGaugeFamily(Impl* ptr); +}; + +namespace detail { + +template +struct GaugeOracle { + static_assert(std::is_same::value, + "Gauge only supports int64_t and double"); + + using type = IntGauge; + + using family_type = IntGaugeFamily; +}; + +template <> +struct GaugeOracle { + using type = DblGauge; + + using family_type = DblGaugeFamily; +}; + +} // namespace detail + +template +using Gauge = typename detail::GaugeOracle::type; + +template +using GaugeFamily = typename detail::GaugeOracle::family_type; + +} // namespace zeek::telemetry diff --git a/src/telemetry/Manager.cc b/src/telemetry/Manager.cc index f9765bef85..4ba9535ca1 100644 --- a/src/telemetry/Manager.cc +++ b/src/telemetry/Manager.cc @@ -22,6 +22,14 @@ using NativeDblCounter = ct::dbl_counter; using NativeDblCounterFamily = ct::metric_family_impl; +using NativeIntGauge = ct::int_gauge; + +using NativeIntGaugeFamily = ct::metric_family_impl; + +using NativeDblGauge = ct::dbl_gauge; + +using NativeDblGaugeFamily = ct::metric_family_impl; + auto& deref(Manager::Impl* ptr) { return *reinterpret_cast(ptr); @@ -42,6 +50,16 @@ auto opaque(NativeDblCounterFamily* ptr) return reinterpret_cast(ptr); } +auto opaque(NativeIntGaugeFamily* ptr) + { + return reinterpret_cast(ptr); + } + +auto opaque(NativeDblGaugeFamily* ptr) + { + return reinterpret_cast(ptr); + } + template auto withNative(Span xs, F continuation) { @@ -91,13 +109,56 @@ DblCounterFamily Manager::dblCounterFam(std::string_view prefix, }); } +IntGaugeFamily Manager::intGaugeFam(std::string_view prefix, + std::string_view name, + Span labels, + std::string_view helptext, + std::string_view unit, bool isSum) + { + return withNative(labels, [&, this](auto xs) + { + auto ptr = deref(pimpl).gauge_family(prefix, name, xs, + helptext, unit, isSum); + return IntGaugeFamily{opaque(ptr)}; + }); + } + +DblGaugeFamily Manager::dblGaugeFam(std::string_view prefix, + std::string_view name, + Span labels, + std::string_view helptext, + std::string_view unit, bool isSum) + { + return withNative(labels, [&, this](auto xs) + { + auto ptr = deref(pimpl).gauge_family(prefix, name, xs, + helptext, unit, isSum); + return DblGaugeFamily{opaque(ptr)}; + }); + } + } // namespace zeek::telemetry // -- unit tests --------------------------------------------------------------- +using namespace std::literals; using namespace zeek::telemetry; -SCENARIO("telemetry managers provide access to counters") +namespace { + +template +auto toVector(zeek::Span xs) + { + std::vector> result; + for (auto&& x : xs) + result.emplace_back(x); + return result; + } + + +} // namespace + +SCENARIO("telemetry managers provide access to counter singletons") { GIVEN("a telemetry manager") { @@ -157,3 +218,190 @@ SCENARIO("telemetry managers provide access to counters") } } } + +SCENARIO("telemetry managers provide access to counter families") + { + GIVEN("a telemetry manager") + { + NativeManager nativeMgr; + Manager mgr{opaque(&nativeMgr)}; + WHEN("retrieving an IntCounter family") + { + auto family = mgr.counterFamily("zeek", "requests", {"method"}, "test", "1", true); + THEN("the family object stores the parameters") + { + CHECK_EQ(family.prefix(), "zeek"sv); + CHECK_EQ(family.name(), "requests"sv); + CHECK_EQ(toVector(family.labelNames()), std::vector{"method"s}); + CHECK_EQ(family.helptext(), "test"sv); + CHECK_EQ(family.unit(), "1"sv); + CHECK_EQ(family.isSum(), true); + } + 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") + { + auto first = family.getOrAdd({{"method", "get"}}); + auto second = family.getOrAdd({{"method", "put"}}); + CHECK_NE(first, second); + } + } + WHEN("retrieving a DblCounter family") + { + auto family = mgr.counterFamily("zeek", "runtime", {"query"}, "test", "seconds", true); + THEN("the family object stores the parameters") + { + CHECK_EQ(family.prefix(), "zeek"sv); + CHECK_EQ(family.name(), "runtime"sv); + CHECK_EQ(toVector(family.labelNames()), std::vector{"query"s}); + CHECK_EQ(family.helptext(), "test"sv); + CHECK_EQ(family.unit(), "seconds"sv); + CHECK_EQ(family.isSum(), true); + } + 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") + { + auto first = family.getOrAdd({{"query", "foo"}}); + auto second = family.getOrAdd({{"query", "bar"}}); + CHECK_NE(first, second); + } + } + } + } + +SCENARIO("telemetry managers provide access to gauge singletons") + { + GIVEN("a telemetry manager") + { + NativeManager nativeMgr; + Manager mgr{opaque(&nativeMgr)}; + WHEN("retrieving an IntGauge singleton") + { + auto first = mgr.gaugeSingleton("zeek", "int-gauge", "test"); + THEN("its initial value is zero") + { + CHECK_EQ(first.value(), 0); + } + AND_THEN("calling inc(), dec(), operator++ or operator-- changes the value") + { + first.inc(); + CHECK_EQ(first.value(), 1); + first.inc(2); + CHECK_EQ(first.value(), 3); + first.dec(); + CHECK_EQ(first.value(), 2); + CHECK_EQ(++first, 3); + CHECK_EQ(first.value(), 3); + CHECK_EQ(--first, 2); + CHECK_EQ(first.value(), 2); + } + AND_THEN("calling gaugeSingleton again for the same name returns the same handle") + { + auto second = mgr.gaugeSingleton("zeek", "int-gauge", "test"); + CHECK_EQ(first, second); + } + AND_THEN("calling gaugeSingleton for a different name returns another handle") + { + auto third = mgr.gaugeSingleton("zeek", "int-gauge-2", "test"); + CHECK_NE(first, third); + } + } + WHEN("retrieving a DblGauge singleton") + { + auto first = mgr.gaugeSingleton("zeek", "dbl-gauge", "test"); + THEN("its initial value is zero") + { + CHECK_EQ(first.value(), 0.0); + } + AND_THEN("calling inc() or dec() changes the value") + { + first.inc(); + CHECK_EQ(first.value(), 1.0); + first.inc(3.0); + CHECK_EQ(first.value(), 4.0); + first.dec(2.0); + CHECK_EQ(first.value(), 2.0); + first.dec(); + CHECK_EQ(first.value(), 1.0); + } + AND_THEN("calling gaugeSingleton again for the same name returns the same handle") + { + auto second = mgr.gaugeSingleton("zeek", "dbl-gauge", "test"); + CHECK_EQ(first, second); + } + AND_THEN("calling gaugeSingleton for a different name returns another handle") + { + auto third = mgr.gaugeSingleton("zeek", "dbl-gauge-2", "test"); + CHECK_NE(first, third); + } + } + } + } + +SCENARIO("telemetry managers provide access to gauge families") + { + GIVEN("a telemetry manager") + { + NativeManager nativeMgr; + Manager mgr{opaque(&nativeMgr)}; + WHEN("retrieving an IntGauge family") + { + auto family = mgr.gaugeFamily("zeek", "open-connections", {"protocol"}, "test"); + THEN("the family object stores the parameters") + { + CHECK_EQ(family.prefix(), "zeek"sv); + CHECK_EQ(family.name(), "open-connections"sv); + CHECK_EQ(toVector(family.labelNames()), std::vector{"protocol"s}); + CHECK_EQ(family.helptext(), "test"sv); + CHECK_EQ(family.unit(), "1"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", "quic"}}); + CHECK_NE(first, second); + } + } + WHEN("retrieving a DblGauge family") + { + auto family = mgr.gaugeFamily("zeek", "water-level", {"river"}, "test", "meters"); + THEN("the family object stores the parameters") + { + CHECK_EQ(family.prefix(), "zeek"sv); + CHECK_EQ(family.name(), "water-level"sv); + CHECK_EQ(toVector(family.labelNames()), std::vector{"river"s}); + CHECK_EQ(family.helptext(), "test"sv); + CHECK_EQ(family.unit(), "meters"sv); + CHECK_EQ(family.isSum(), false); + } + 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") + { + auto first = family.getOrAdd({{"query", "Sacramento"}}); + auto second = family.getOrAdd({{"query", "San Joaquin"}}); + CHECK_NE(first, second); + } + } + } + } diff --git a/src/telemetry/Manager.h b/src/telemetry/Manager.h index 3206b3ed25..32f08f89b2 100644 --- a/src/telemetry/Manager.h +++ b/src/telemetry/Manager.h @@ -9,6 +9,7 @@ #include "zeek/Span.h" #include "zeek/telemetry/Counter.h" +#include "zeek/telemetry/Gauge.h" namespace zeek::telemetry { @@ -129,6 +130,107 @@ public: return fam.getOrAdd({}); } + /** + * @returns a gauge 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 + GaugeFamily + gaugeFamily(std::string_view prefix, std::string_view name, + Span labels, + std::string_view helptext, + std::string_view unit = "1", bool isSum = false) { + if constexpr (std::is_same::value) + { + return intGaugeFam(prefix, name, labels, helptext, unit, isSum); + } + else + { + static_assert(std::is_same::value, + "metrics only support int64_t and double values"); + return dblGaugeFam(prefix, name, labels, helptext, unit, isSum); + } + } + + /// @copydoc gaugeFamily + template + GaugeFamily + gaugeFamily(std::string_view prefix, std::string_view name, + std::initializer_list labels, + std::string_view helptext, std::string_view unit = "1", + bool isSum = false) + { + auto lblSpan = Span{labels.begin(), labels.size()}; + return gaugeFamily(prefix, name, lblSpan, helptext, + unit, isSum); + } + + /** + * Accesses a gauge instance. Creates the hosting metric family as well + * as the gauge 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 + Gauge + gaugeInstance(std::string_view prefix, std::string_view name, + Span labels, std::string_view helptext, + std::string_view unit = "1", bool isSum = false) + { + return withLabelNames(labels, [&, this](auto labelNames) + { + auto family = gaugeFamily(prefix, name, labelNames, + helptext, unit, isSum); + return family.getOrAdd(labels); + }); + } + + /// @copydoc gaugeInstance + template + Gauge + gaugeInstance(std::string_view prefix, std::string_view name, + std::initializer_list labels, + std::string_view helptext, std::string_view unit = "1", + bool isSum = false) + { + auto lblSpan = Span{labels.begin(), labels.size()}; + return gaugeInstance(prefix, name, lblSpan, helptext, unit, isSum); + } + + /** + * Accesses a gauge singleton, i.e., a gauge that belongs to a family + * without label dimensions (which thus only has a single member). Creates + * the hosting metric family as well as the gauge 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 + Gauge + gaugeSingleton(std::string_view prefix, std::string_view name, + std::string_view helptext, std::string_view unit = "1", + bool isSum = false) + { + auto labels = Span{}; + auto fam = gaugeFamily(prefix, name, labels, helptext, + unit, isSum); + return fam.getOrAdd({}); + } + private: IntCounterFamily intCounterFam(std::string_view prefix, std::string_view name, @@ -140,6 +242,16 @@ private: Span labels, std::string_view helptext, std::string_view unit, bool isSum); + IntGaugeFamily + intGaugeFam(std::string_view prefix, std::string_view name, + Span labels, + std::string_view helptext, std::string_view unit, bool isSum); + + DblGaugeFamily + dblGaugeFam(std::string_view prefix, std::string_view name, + Span labels, + std::string_view helptext, std::string_view unit, bool isSum); + template static void withLabelNames(Span xs, F continuation) { diff --git a/src/telemetry/MetricFamily.cc b/src/telemetry/MetricFamily.cc index e69de29bb2..dbece54de3 100644 --- a/src/telemetry/MetricFamily.cc +++ b/src/telemetry/MetricFamily.cc @@ -0,0 +1,52 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#include "zeek/telemetry/MetricFamily.h" + +#include "caf/telemetry/metric_family.hpp" + +namespace zeek::telemetry { + +namespace { + +namespace ct = caf::telemetry; + +using NativeMetricFamily = ct::metric_family; + +auto& deref(MetricFamily::Impl* ptr) + { + return *reinterpret_cast(ptr); + } + +} // namespace + +std::string_view MetricFamily::prefix() const noexcept + { + return deref(pimpl).prefix(); + } + +std::string_view MetricFamily::name() const noexcept + { + return deref(pimpl).name(); + } + +Span MetricFamily::labelNames() const noexcept + { + return deref(pimpl).label_names(); + } + +std::string_view MetricFamily::helptext() const noexcept + { + return deref(pimpl).helptext(); + } + +std::string_view MetricFamily::unit() const noexcept + { + return deref(pimpl).unit(); + } + +bool MetricFamily::isSum() const noexcept + { + return deref(pimpl).is_sum(); + } + +} // namespace zeek::telemetry diff --git a/src/telemetry/MetricFamily.h b/src/telemetry/MetricFamily.h index efac9a33ed..1f79d73907 100644 --- a/src/telemetry/MetricFamily.h +++ b/src/telemetry/MetricFamily.h @@ -44,7 +44,7 @@ public: /** * @returns the names for all label dimensions. */ - Span label_names() const noexcept; + Span labelNames() const noexcept; /** * @returns a short explanation of the metric. From 83d7d2da4c21f70eaab127c962868ee128e00fad Mon Sep 17 00:00:00 2001 From: Dominik Charousset Date: Mon, 1 Mar 2021 16:43:34 +0100 Subject: [PATCH 03/13] Add missing whitespaces for Zeek coding style --- src/telemetry/Counter.cc | 8 +++----- src/telemetry/Counter.h | 2 -- src/telemetry/Gauge.cc | 8 +++----- src/telemetry/Gauge.h | 2 -- src/telemetry/Manager.cc | 12 ++++++++---- src/telemetry/Manager.h | 11 +++++++---- src/telemetry/MetricFamily.h | 1 - 7 files changed, 21 insertions(+), 23 deletions(-) diff --git a/src/telemetry/Counter.cc b/src/telemetry/Counter.cc index 88f9ec74c2..9a8aa5e5bb 100644 --- a/src/telemetry/Counter.cc +++ b/src/telemetry/Counter.cc @@ -73,20 +73,20 @@ auto opaque(NativeDblCounter* ptr) template auto withNativeLabels(Span xs, F continuation) { - if (xs.size() <= 10) + if ( xs.size() <= 10 ) { ct::label_view buf[10]={ {{},{}}, {{},{}}, {{},{}}, {{},{}}, {{},{}}, {{},{}}, {{},{}}, {{},{}}, {{},{}}, {{},{}}, }; - for (size_t index = 0; index < xs.size(); ++index) + 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 buf; - for (auto x : xs) + for ( auto x : xs ) buf.emplace_back(x.first, x.second); return continuation(Span{buf}); } @@ -118,7 +118,6 @@ int64_t IntCounter::value() const noexcept IntCounterFamily::IntCounterFamily(Impl* ptr) : MetricFamily(upcast(ptr)) { - // nop } IntCounter IntCounterFamily::getOrAdd(Span labels) @@ -149,7 +148,6 @@ double DblCounter::value() const noexcept DblCounterFamily::DblCounterFamily(Impl* ptr) : MetricFamily(upcast(ptr)) { - // nop } DblCounter DblCounterFamily::getOrAdd(Span labels) diff --git a/src/telemetry/Counter.h b/src/telemetry/Counter.h index 259726b6ac..57d2ef38e7 100644 --- a/src/telemetry/Counter.h +++ b/src/telemetry/Counter.h @@ -61,7 +61,6 @@ public: private: explicit IntCounter(Impl* ptr) noexcept : pimpl(ptr) { - // nop } Impl* pimpl; @@ -154,7 +153,6 @@ public: private: explicit DblCounter(Impl* ptr) noexcept : pimpl(ptr) { - // nop } Impl* pimpl; diff --git a/src/telemetry/Gauge.cc b/src/telemetry/Gauge.cc index 2d9616b10c..e7a4322634 100644 --- a/src/telemetry/Gauge.cc +++ b/src/telemetry/Gauge.cc @@ -73,20 +73,20 @@ auto opaque(NativeDblGauge* ptr) template auto withNativeLabels(Span xs, F continuation) { - if (xs.size() <= 10) + if ( xs.size() <= 10 ) { ct::label_view buf[10]={ {{},{}}, {{},{}}, {{},{}}, {{},{}}, {{},{}}, {{},{}}, {{},{}}, {{},{}}, {{},{}}, {{},{}}, }; - for (size_t index = 0; index < xs.size(); ++index) + 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 buf; - for (auto x : xs) + for ( auto x : xs ) buf.emplace_back(x.first, x.second); return continuation(Span{buf}); } @@ -133,7 +133,6 @@ int64_t IntGauge::value() const noexcept IntGaugeFamily::IntGaugeFamily(Impl* ptr) : MetricFamily(upcast(ptr)) { - // nop } IntGauge IntGaugeFamily::getOrAdd(Span labels) @@ -174,7 +173,6 @@ double DblGauge::value() const noexcept DblGaugeFamily::DblGaugeFamily(Impl* ptr) : MetricFamily(upcast(ptr)) { - // nop } DblGauge DblGaugeFamily::getOrAdd(Span labels) diff --git a/src/telemetry/Gauge.h b/src/telemetry/Gauge.h index 2f83b75462..36b0d5855c 100644 --- a/src/telemetry/Gauge.h +++ b/src/telemetry/Gauge.h @@ -77,7 +77,6 @@ public: private: explicit IntGauge(Impl* ptr) noexcept : pimpl(ptr) { - // nop } Impl* pimpl; @@ -180,7 +179,6 @@ public: private: explicit DblGauge(Impl* ptr) noexcept : pimpl(ptr) { - // nop } Impl* pimpl; diff --git a/src/telemetry/Manager.cc b/src/telemetry/Manager.cc index 4ba9535ca1..1830a36146 100644 --- a/src/telemetry/Manager.cc +++ b/src/telemetry/Manager.cc @@ -63,17 +63,17 @@ auto opaque(NativeDblGaugeFamily* ptr) template auto withNative(Span xs, F continuation) { - if (xs.size() <= 10) + if ( xs.size() <= 10 ) { caf::string_view buf[10]; - for (size_t index = 0; index < xs.size(); ++index) + for ( size_t index = 0; index < xs.size(); ++index ) buf[index] = xs[index]; return continuation(Span{buf, xs.size()}); } else { std::vector buf; - for (auto x : xs) + for ( auto x : xs ) buf.emplace_back(x); return continuation(Span{buf}); } @@ -81,6 +81,10 @@ auto withNative(Span xs, F continuation) } // namespace +Manager::~Manager() + { + } + IntCounterFamily Manager::intCounterFam(std::string_view prefix, std::string_view name, Span labels, @@ -150,7 +154,7 @@ template auto toVector(zeek::Span xs) { std::vector> result; - for (auto&& x : xs) + for ( auto&& x : xs ) result.emplace_back(x); return result; } diff --git a/src/telemetry/Manager.h b/src/telemetry/Manager.h index 32f08f89b2..9c9783878b 100644 --- a/src/telemetry/Manager.h +++ b/src/telemetry/Manager.h @@ -22,13 +22,14 @@ public: explicit Manager(Impl* ptr) : pimpl(ptr) { - //nop } Manager(const Manager&) = delete; Manager& operator=(const Manager&) = delete; + virtual ~Manager(); + /** * @returns a counter metric family. Creates the family lazily if necessary. * @param prefix The prefix (namespace) this family belongs to. @@ -255,14 +256,14 @@ private: template static void withLabelNames(Span xs, F continuation) { - if (xs.size() <= 10) { + if ( xs.size() <= 10 ) { std::string_view buf[10]; - for (size_t index = 0; index < xs.size(); ++index) + for ( size_t index = 0; index < xs.size(); ++index ) buf[index] = xs[index].first; return continuation(Span{buf, xs.size()}); } else { std::vector buf; - for (auto x : xs) + for ( auto x : xs ) buf.emplace_back(x.first, x.second); return continuation(Span{buf}); } @@ -275,6 +276,8 @@ private: namespace zeek { +// @note for technically reasons (CAF dependency), this variable gets +// initialized in broker/Manager.cc. extern telemetry::Manager* telemetry_mgr; } // namespace zeek diff --git a/src/telemetry/MetricFamily.h b/src/telemetry/MetricFamily.h index 1f79d73907..403e1aa90d 100644 --- a/src/telemetry/MetricFamily.h +++ b/src/telemetry/MetricFamily.h @@ -68,7 +68,6 @@ public: protected: explicit MetricFamily(Impl* ptr) : pimpl(ptr) { - // nop } Impl* pimpl; From 443f7f0a18bbbe16adfe74ef705c39e7d7c08cb9 Mon Sep 17 00:00:00 2001 From: Dominik Charousset Date: Mon, 1 Mar 2021 16:47:19 +0100 Subject: [PATCH 04/13] Add telemetry Manager to Zeek setup / teardown --- src/broker/Manager.cc | 28 ++++++++++++++++++++++++++++ src/broker/Manager.h | 7 +++++++ src/zeek-setup.cc | 4 ++++ 3 files changed, 39 insertions(+) diff --git a/src/broker/Manager.cc b/src/broker/Manager.cc index 0ce23d9508..41f2282ab7 100644 --- a/src/broker/Manager.cc +++ b/src/broker/Manager.cc @@ -10,6 +10,7 @@ #include "zeek/Func.h" #include "zeek/broker/Data.h" #include "zeek/broker/Store.h" +#include "zeek/telemetry/Manager.h" #include "zeek/util.h" #include "zeek/Var.h" #include "zeek/Desc.h" @@ -1806,4 +1807,31 @@ void Manager::PrepareForwarding(const std::string &name) DBG_LOG(DBG_BROKER, "Resolved table forward for data store %s", name.c_str()); } +std::unique_ptr Manager::NewTelemetryManager() + { + // The telemetry Manager actually only has a dependency on the actor system, + // not to the Broker Manager. By having the telemetry Manager hold on to a + // shared_ptr to our Broker state, we make sure the Broker endpoint, which + // owns the CAF actor system, lives for as long as necessary. This also + // makes sure that the Broker Manager may even get destroyed before the + // telemetry Manager. + struct TM : public telemetry::Manager + { + static auto getPimpl(BrokerState& st) + { + auto registry = std::addressof(st.endpoint.system().metrics()); + return reinterpret_cast(registry); + } + + explicit TM(const std::shared_ptr& bsptr) + : telemetry::Manager(getPimpl(*bsptr)), ptr(bsptr) + { + } + + std::shared_ptr ptr; + }; + + return std::make_unique(bstate); + } + } // namespace zeek::Broker diff --git a/src/broker/Manager.h b/src/broker/Manager.h index af09855c6b..670a9bcd79 100644 --- a/src/broker/Manager.h +++ b/src/broker/Manager.h @@ -30,6 +30,8 @@ class TableVal; using VectorTypePtr = IntrusivePtr; using TableValPtr = IntrusivePtr; +namespace telemetry { class Manager; } + namespace detail { class Frame; } namespace Broker { @@ -357,6 +359,11 @@ public: ~ScriptScopeGuard() { --script_scope; } }; + /** + * Allocates a new manager for telemetry data. + */ + std::unique_ptr NewTelemetryManager(); + private: void DispatchMessage(const broker::topic& topic, broker::data msg); diff --git a/src/zeek-setup.cc b/src/zeek-setup.cc index 51e3162c2b..f01294b00f 100644 --- a/src/zeek-setup.cc +++ b/src/zeek-setup.cc @@ -69,6 +69,7 @@ extern "C" { #include "zeek/zeekygen/Manager.h" #include "zeek/iosource/Manager.h" #include "zeek/broker/Manager.h" +#include "zeek/telemetry/Manager.h" #include "zeek/binpac_zeek.h" #include "zeek/module_util.h" @@ -107,6 +108,7 @@ zeek::file_analysis::Manager* zeek::file_mgr = nullptr; zeek::zeekygen::detail::Manager* zeek::detail::zeekygen_mgr = nullptr; zeek::iosource::Manager* zeek::iosource_mgr = nullptr; zeek::Broker::Manager* zeek::broker_mgr = nullptr; +zeek::telemetry::Manager* zeek::telemetry_mgr = nullptr; zeek::Supervisor* zeek::supervisor_mgr = nullptr; zeek::detail::trigger::Manager* zeek::detail::trigger_mgr = nullptr; @@ -327,6 +329,7 @@ static void terminate_bro() delete plugin_mgr; delete val_mgr; delete fragment_mgr; + delete telemetry_mgr; // free the global scope pop_scope(); @@ -576,6 +579,7 @@ SetupResult setup(int argc, char** argv, Options* zopts) file_mgr = new file_analysis::Manager(); auto broker_real_time = ! options.pcap_file && ! options.deterministic_mode; broker_mgr = new Broker::Manager(broker_real_time); + telemetry_mgr = broker_mgr->NewTelemetryManager().release(); trigger_mgr = new trigger::Manager(); plugin_mgr->InitPreScript(); From 7c5c36959f58cc3cd324583bd51f5d0498f6711d Mon Sep 17 00:00:00 2001 From: Dominik Charousset Date: Tue, 2 Mar 2021 08:20:49 +0100 Subject: [PATCH 05/13] Apply suggestions from code review Co-authored-by: Jon Siwek --- src/Span.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Span.h b/src/Span.h index e78af1ab11..903b0c0c8b 100644 --- a/src/Span.h +++ b/src/Span.h @@ -157,7 +157,7 @@ public: return numElements; } - constexpr size_t numElementsbytes() const noexcept + constexpr size_t size_bytes() const noexcept { return numElements * sizeof(element_type); } @@ -174,9 +174,9 @@ public: // -- subviews ------------------------------------------------------------- - constexpr Span subspan(size_t offset, size_t num_bytes) const + constexpr Span subspan(size_t offset, size_t num_elements) const { - return {memoryBlock + offset, num_bytes}; + return {memoryBlock + offset, num_elements}; } constexpr Span subspan(size_t offset) const @@ -184,14 +184,14 @@ public: return {memoryBlock + offset, numElements - offset}; } - constexpr Span first(size_t num_bytes) const + constexpr Span first(size_t num_elements) const { - return {memoryBlock, num_bytes}; + return {memoryBlock, num_elements}; } - constexpr Span last(size_t num_bytes) const + constexpr Span last(size_t num_elements) const { - return subspan(numElements - num_bytes, num_bytes); + return subspan(numElements - num_elements, num_elements); } private: From 2a21f2903a1f3f5ce68ac4cb37a3975e1c1d2622 Mon Sep 17 00:00:00 2001 From: Dominik Charousset Date: Tue, 2 Mar 2021 08:59:09 +0100 Subject: [PATCH 06/13] Adhere to Zeek coding style --- src/Span.h | 52 ++++---- src/telemetry/Counter.cc | 16 +-- src/telemetry/Counter.h | 57 ++++----- src/telemetry/Gauge.cc | 24 ++-- src/telemetry/Gauge.h | 67 +++++----- src/telemetry/Manager.cc | 230 +++++++++++++++++----------------- src/telemetry/Manager.h | 172 ++++++++++++------------- src/telemetry/MetricFamily.cc | 12 +- src/telemetry/MetricFamily.h | 38 +++--- 9 files changed, 325 insertions(+), 343 deletions(-) diff --git a/src/Span.h b/src/Span.h index 903b0c0c8b..86b1411a94 100644 --- a/src/Span.h +++ b/src/Span.h @@ -45,46 +45,40 @@ public: // -- constructors, destructors, and assignment operators ------------------ - constexpr Span() noexcept : memoryBlock(nullptr), numElements(0) + constexpr Span() noexcept : memory_block(nullptr), num_elements(0) { - // nop } constexpr Span(pointer ptr, size_t size) - : memoryBlock(ptr), numElements(size) + : memory_block(ptr), num_elements(size) { - // nop } constexpr Span(pointer first, pointer last) - : memoryBlock(first), numElements(static_cast(last - first)) + : memory_block(first), num_elements(static_cast(last - first)) { - // nop } template constexpr Span(element_type (&arr)[Size]) noexcept - : memoryBlock(arr), numElements(Size) + : memory_block(arr), num_elements(Size) { - // nop } template >> Span(Container& xs) noexcept - : memoryBlock(xs.data()), numElements(xs.size()) + : memory_block(xs.data()), num_elements(xs.size()) { - // nop } template >> Span(const Container& xs) noexcept - : memoryBlock(xs.data()), numElements(xs.size()) + : memory_block(xs.data()), num_elements(xs.size()) { - // nop } constexpr Span(const Span&) noexcept = default; @@ -95,22 +89,22 @@ public: constexpr iterator begin() const noexcept { - return memoryBlock; + return memory_block; } constexpr const_iterator cbegin() const noexcept { - return memoryBlock; + return memory_block; } constexpr iterator end() const noexcept { - return begin() + numElements; + return begin() + num_elements; } constexpr const_iterator cend() const noexcept { - return cbegin() + numElements; + return cbegin() + num_elements; } constexpr reverse_iterator rbegin() const noexcept @@ -137,71 +131,71 @@ public: constexpr reference operator[](size_t index) const noexcept { - return memoryBlock[index]; + return memory_block[index]; } constexpr reference front() const noexcept { - return *memoryBlock; + return *memory_block; } constexpr reference back() const noexcept { - return (*this)[numElements - 1]; + return (*this)[num_elements - 1]; } // -- properties ----------------------------------------------------------- constexpr size_t size() const noexcept { - return numElements; + return num_elements; } constexpr size_t size_bytes() const noexcept { - return numElements * sizeof(element_type); + return num_elements * sizeof(element_type); } constexpr bool empty() const noexcept { - return numElements == 0; + return num_elements == 0; } constexpr pointer data() const noexcept { - return memoryBlock; + return memory_block; } // -- subviews ------------------------------------------------------------- constexpr Span subspan(size_t offset, size_t num_elements) const { - return {memoryBlock + offset, num_elements}; + return {memory_block + offset, num_elements}; } constexpr Span subspan(size_t offset) const { - return {memoryBlock + offset, numElements - offset}; + return {memory_block + offset, num_elements - offset}; } constexpr Span first(size_t num_elements) const { - return {memoryBlock, num_elements}; + return {memory_block, num_elements}; } constexpr Span last(size_t num_elements) const { - return subspan(numElements - num_elements, num_elements); + return subspan(num_elements - num_elements, num_elements); } private: // -- member variables ----------------------------------------------------- /// Points to the first element in the contiguous memory block. - pointer memoryBlock; + pointer memory_block; /// Stores the number of elements in the contiguous memory block. - size_t numElements; + size_t num_elements; }; // -- deduction guides --------------------------------------------------------- diff --git a/src/telemetry/Counter.cc b/src/telemetry/Counter.cc index 9a8aa5e5bb..1b2e0aefae 100644 --- a/src/telemetry/Counter.cc +++ b/src/telemetry/Counter.cc @@ -96,12 +96,12 @@ auto withNativeLabels(Span xs, F continuation) // -- IntCounter --------------------------------------------------------------- -void IntCounter::inc() noexcept +void IntCounter::Inc() noexcept { deref(pimpl).inc(); } -void IntCounter::inc(int64_t amount) noexcept +void IntCounter::Inc(int64_t amount) noexcept { deref(pimpl).inc(amount); } @@ -111,7 +111,7 @@ int64_t IntCounter::operator++() noexcept return ++deref(pimpl); } -int64_t IntCounter::value() const noexcept +int64_t IntCounter::Value() const noexcept { return deref(pimpl).value(); } @@ -120,7 +120,7 @@ IntCounterFamily::IntCounterFamily(Impl* ptr) : MetricFamily(upcast(ptr)) { } -IntCounter IntCounterFamily::getOrAdd(Span labels) +IntCounter IntCounterFamily::GetOrAdd(Span labels) { return withNativeLabels(labels, [this](auto nativeLabels) { @@ -131,17 +131,17 @@ IntCounter IntCounterFamily::getOrAdd(Span labels) // -- DblCounter --------------------------------------------------------------- -void DblCounter::inc() noexcept +void DblCounter::Inc() noexcept { deref(pimpl).inc(); } -void DblCounter::inc(double amount) noexcept +void DblCounter::Inc(double amount) noexcept { deref(pimpl).inc(amount); } -double DblCounter::value() const noexcept +double DblCounter::Value() const noexcept { return deref(pimpl).value(); } @@ -150,7 +150,7 @@ DblCounterFamily::DblCounterFamily(Impl* ptr) : MetricFamily(upcast(ptr)) { } -DblCounter DblCounterFamily::getOrAdd(Span labels) +DblCounter DblCounterFamily::GetOrAdd(Span labels) { return withNativeLabels(labels, [this](auto nativeLabels) { diff --git a/src/telemetry/Counter.h b/src/telemetry/Counter.h index 57d2ef38e7..6c4d88ce0a 100644 --- a/src/telemetry/Counter.h +++ b/src/telemetry/Counter.h @@ -31,29 +31,29 @@ public: /** * Increments the value by 1. */ - void inc() noexcept; + void Inc() noexcept; /** * Increments the value by @p amount. * @pre `amount >= 0` */ - void inc(int64_t amount) noexcept; + void Inc(int64_t amount) noexcept; /** * Increments the value by 1. - * @returns the new value. + * @return The new value. */ int64_t operator++() noexcept; /** - * @returns the current value. + * @return The current value. */ - int64_t value() const noexcept; + int64_t Value() const noexcept; /** - * @returns whether @c this and @p other refer to the same counter. + * @return Whether @c this and @p other refer to the same counter. */ - constexpr bool isSameAs(IntCounter other) const noexcept + constexpr bool IsSameAs(IntCounter other) const noexcept { return pimpl == other.pimpl; } @@ -68,12 +68,12 @@ private: /** * Checks whether two @ref IntCounter handles are identical. - * @returns whether @p lhs and @p rhs refer to the same object. + * @return 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); + return lhs.IsSameAs(rhs); } /// @relates IntCounter @@ -98,14 +98,14 @@ public: * Returns the metrics handle for given labels, creating a new instance * lazily if necessary. */ - IntCounter getOrAdd(Span labels); + IntCounter GetOrAdd(Span labels); /** - * @copydoc getOrAdd + * @copydoc GetOrAdd */ - IntCounter getOrAdd(std::initializer_list labels) + IntCounter GetOrAdd(std::initializer_list labels) { - return getOrAdd(Span{labels.begin(), labels.size()}); + return GetOrAdd(Span{labels.begin(), labels.size()}); } private: @@ -129,23 +129,23 @@ public: /** * Increments the value by 1. */ - void inc() noexcept; + void Inc() noexcept; /** * Increments the value by @p amount. * @pre `amount >= 0` */ - void inc(double amount) noexcept; + void Inc(double amount) noexcept; /** - * @returns the current value. + * @return The current value. */ - double value() const noexcept; + double Value() const noexcept; /** - * @returns whether @c this and @p other refer to the same counter. + * @return Whether @c this and @p other refer to the same counter. */ - constexpr bool isSameAs(DblCounter other) const noexcept + constexpr bool IsSameAs(DblCounter other) const noexcept { return pimpl == other.pimpl; } @@ -160,12 +160,12 @@ private: /** * Checks whether two @ref DblCounter handles are identical. - * @returns whether @p lhs and @p rhs refer to the same object. + * @return 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); + return lhs.IsSameAs(rhs); } /// @relates DblCounter @@ -190,14 +190,14 @@ public: * Returns the metrics handle for given labels, creating a new instance * lazily if necessary. */ - DblCounter getOrAdd(Span labels); + DblCounter GetOrAdd(Span labels); /** - * @copydoc getOrAdd + * @copydoc GetOrAdd */ - DblCounter getOrAdd(std::initializer_list labels) + DblCounter GetOrAdd(std::initializer_list labels) { - return getOrAdd(Span{labels.begin(), labels.size()}); + return GetOrAdd(Span{labels.begin(), labels.size()}); } private: @@ -212,15 +212,11 @@ struct CounterOracle { "Counter only supports int64_t and double"); using type = IntCounter; - - using family_type = IntCounterFamily; }; template <> struct CounterOracle { using type = DblCounter; - - using family_type = DblCounterFamily; }; } // namespace detail @@ -228,7 +224,4 @@ struct CounterOracle { template using Counter = typename detail::CounterOracle::type; -template -using CounterFamily = typename detail::CounterOracle::family_type; - } // namespace zeek::telemetry diff --git a/src/telemetry/Gauge.cc b/src/telemetry/Gauge.cc index e7a4322634..4c12477f32 100644 --- a/src/telemetry/Gauge.cc +++ b/src/telemetry/Gauge.cc @@ -96,22 +96,22 @@ auto withNativeLabels(Span xs, F continuation) // -- IntGauge --------------------------------------------------------------- -void IntGauge::inc() noexcept +void IntGauge::Inc() noexcept { deref(pimpl).inc(); } -void IntGauge::inc(int64_t amount) noexcept +void IntGauge::Inc(int64_t amount) noexcept { deref(pimpl).inc(amount); } -void IntGauge::dec() noexcept +void IntGauge::Dec() noexcept { deref(pimpl).dec(); } -void IntGauge::dec(int64_t amount) noexcept +void IntGauge::Dec(int64_t amount) noexcept { deref(pimpl).dec(amount); } @@ -126,7 +126,7 @@ int64_t IntGauge::operator--() noexcept return --deref(pimpl); } -int64_t IntGauge::value() const noexcept +int64_t IntGauge::Value() const noexcept { return deref(pimpl).value(); } @@ -135,7 +135,7 @@ IntGaugeFamily::IntGaugeFamily(Impl* ptr) : MetricFamily(upcast(ptr)) { } -IntGauge IntGaugeFamily::getOrAdd(Span labels) +IntGauge IntGaugeFamily::GetOrAdd(Span labels) { return withNativeLabels(labels, [this](auto nativeLabels) { @@ -146,27 +146,27 @@ IntGauge IntGaugeFamily::getOrAdd(Span labels) // -- DblGauge --------------------------------------------------------------- -void DblGauge::inc() noexcept +void DblGauge::Inc() noexcept { deref(pimpl).inc(); } -void DblGauge::inc(double amount) noexcept +void DblGauge::Inc(double amount) noexcept { deref(pimpl).inc(amount); } -void DblGauge::dec() noexcept +void DblGauge::Dec() noexcept { deref(pimpl).dec(); } -void DblGauge::dec(double amount) noexcept +void DblGauge::Dec(double amount) noexcept { deref(pimpl).dec(amount); } -double DblGauge::value() const noexcept +double DblGauge::Value() const noexcept { return deref(pimpl).value(); } @@ -175,7 +175,7 @@ DblGaugeFamily::DblGaugeFamily(Impl* ptr) : MetricFamily(upcast(ptr)) { } -DblGauge DblGaugeFamily::getOrAdd(Span labels) +DblGauge DblGaugeFamily::GetOrAdd(Span labels) { return withNativeLabels(labels, [this](auto nativeLabels) { diff --git a/src/telemetry/Gauge.h b/src/telemetry/Gauge.h index 36b0d5855c..8d4121f301 100644 --- a/src/telemetry/Gauge.h +++ b/src/telemetry/Gauge.h @@ -32,44 +32,44 @@ public: /** * Increments the value by 1. */ - void inc() noexcept; + void Inc() noexcept; /** * Increments the value by @p amount. */ - void inc(int64_t amount) noexcept; + void Inc(int64_t amount) noexcept; /** * Increments the value by 1. - * @returns the new value. + * @return The new value. */ int64_t operator++() noexcept; /** * Decrements the value by 1. */ - void dec() noexcept; + void Dec() noexcept; /** * Decrements the value by @p amount. */ - void dec(int64_t amount) noexcept; + void Dec(int64_t amount) noexcept; /** * Decrements the value by 1. - * @returns the new value. + * @return The new value. */ int64_t operator--() noexcept; /** - * @returns the current value. + * @return The current value. */ - int64_t value() const noexcept; + int64_t Value() const noexcept; /** - * @returns whether @c this and @p other refer to the same counter. + * @return Whether @c this and @p other refer to the same counter. */ - constexpr bool isSameAs(IntGauge other) const noexcept + constexpr bool IsSameAs(IntGauge other) const noexcept { return pimpl == other.pimpl; } @@ -84,12 +84,12 @@ private: /** * Checks whether two @ref IntGauge handles are identical. - * @returns whether @p lhs and @p rhs refer to the same object. + * @return Whether @p lhs and @p rhs refer to the same object. * @note compare their @c value instead to check for equality. */ constexpr bool operator==(IntGauge lhs, IntGauge rhs) noexcept { - return lhs.isSameAs(rhs); + return lhs.IsSameAs(rhs); } /// @relates IntGauge @@ -114,14 +114,14 @@ public: * Returns the metrics handle for given labels, creating a new instance * lazily if necessary. */ - IntGauge getOrAdd(Span labels); + IntGauge GetOrAdd(Span labels); /** - * @copydoc getOrAdd + * @copydoc GetOrAdd */ - IntGauge getOrAdd(std::initializer_list labels) + IntGauge GetOrAdd(std::initializer_list labels) { - return getOrAdd(Span{labels.begin(), labels.size()}); + return GetOrAdd(Span{labels.begin(), labels.size()}); } private: @@ -146,32 +146,32 @@ public: /** * Increments the value by 1. */ - void inc() noexcept; + void Inc() noexcept; /** * Increments the value by @p amount. */ - void inc(double amount) noexcept; + void Inc(double amount) noexcept; /** * Increments the value by 1. */ - void dec() noexcept; + void Dec() noexcept; /** * Increments the value by @p amount. */ - void dec(double amount) noexcept; + void Dec(double amount) noexcept; /** - * @returns the current value. + * @return The current value. */ - double value() const noexcept; + double Value() const noexcept; /** - * @returns whether @c this and @p other refer to the same counter. + * @return Whether @c this and @p other refer to the same counter. */ - constexpr bool isSameAs(DblGauge other) const noexcept + constexpr bool IsSameAs(DblGauge other) const noexcept { return pimpl == other.pimpl; } @@ -186,12 +186,12 @@ private: /** * Checks whether two @ref DblGauge handles are identical. - * @returns whether @p lhs and @p rhs refer to the same object. + * @return Whether @p lhs and @p rhs refer to the same object. * @note compare their @c value instead to check for equality. */ constexpr bool operator==(DblGauge lhs, DblGauge rhs) noexcept { - return lhs.isSameAs(rhs); + return lhs.IsSameAs(rhs); } /// @relates DblGauge @@ -216,14 +216,14 @@ public: * Returns the metrics handle for given labels, creating a new instance * lazily if necessary. */ - DblGauge getOrAdd(Span labels); + DblGauge GetOrAdd(Span labels); /** - * @copydoc getOrAdd + * @copydoc GetOrAdd */ - DblGauge getOrAdd(std::initializer_list labels) + DblGauge GetOrAdd(std::initializer_list labels) { - return getOrAdd(Span{labels.begin(), labels.size()}); + return GetOrAdd(Span{labels.begin(), labels.size()}); } private: @@ -238,15 +238,11 @@ struct GaugeOracle { "Gauge only supports int64_t and double"); using type = IntGauge; - - using family_type = IntGaugeFamily; }; template <> struct GaugeOracle { using type = DblGauge; - - using family_type = DblGaugeFamily; }; } // namespace detail @@ -254,7 +250,4 @@ struct GaugeOracle { template using Gauge = typename detail::GaugeOracle::type; -template -using GaugeFamily = typename detail::GaugeOracle::family_type; - } // namespace zeek::telemetry diff --git a/src/telemetry/Manager.cc b/src/telemetry/Manager.cc index 1830a36146..2c006d1def 100644 --- a/src/telemetry/Manager.cc +++ b/src/telemetry/Manager.cc @@ -61,7 +61,7 @@ auto opaque(NativeDblGaugeFamily* ptr) } template -auto withNative(Span xs, F continuation) +auto with_native(Span xs, F continuation) { if ( xs.size() <= 10 ) { @@ -85,58 +85,58 @@ Manager::~Manager() { } -IntCounterFamily Manager::intCounterFam(std::string_view prefix, +IntCounterFamily Manager::IntCounterFam(std::string_view prefix, std::string_view name, Span labels, std::string_view helptext, - std::string_view unit, bool isSum) + std::string_view unit, bool is_sum) { - return withNative(labels, [&, this](auto xs) + return with_native(labels, [&, this](auto xs) { auto ptr = deref(pimpl).counter_family(prefix, name, xs, - helptext, unit, isSum); + helptext, unit, is_sum); return IntCounterFamily{opaque(ptr)}; }); } -DblCounterFamily Manager::dblCounterFam(std::string_view prefix, +DblCounterFamily Manager::DblCounterFam(std::string_view prefix, std::string_view name, Span labels, std::string_view helptext, - std::string_view unit, bool isSum) + std::string_view unit, bool is_sum) { - return withNative(labels, [&, this](auto xs) + return with_native(labels, [&, this](auto xs) { auto ptr = deref(pimpl).counter_family(prefix, name, xs, - helptext, unit, isSum); + helptext, unit, is_sum); return DblCounterFamily{opaque(ptr)}; }); } -IntGaugeFamily Manager::intGaugeFam(std::string_view prefix, +IntGaugeFamily Manager::IntGaugeFam(std::string_view prefix, std::string_view name, Span labels, std::string_view helptext, - std::string_view unit, bool isSum) + std::string_view unit, bool is_sum) { - return withNative(labels, [&, this](auto xs) + return with_native(labels, [&, this](auto xs) { auto ptr = deref(pimpl).gauge_family(prefix, name, xs, - helptext, unit, isSum); + helptext, unit, is_sum); return IntGaugeFamily{opaque(ptr)}; }); } -DblGaugeFamily Manager::dblGaugeFam(std::string_view prefix, +DblGaugeFamily Manager::DblGaugeFam(std::string_view prefix, std::string_view name, Span labels, std::string_view helptext, - std::string_view unit, bool isSum) + std::string_view unit, bool is_sum) { - return withNative(labels, [&, this](auto xs) + return with_native(labels, [&, this](auto xs) { auto ptr = deref(pimpl).gauge_family(prefix, name, xs, - helptext, unit, isSum); + helptext, unit, is_sum); return DblGaugeFamily{opaque(ptr)}; }); } @@ -166,57 +166,57 @@ SCENARIO("telemetry managers provide access to counter singletons") { GIVEN("a telemetry manager") { - NativeManager nativeMgr; - Manager mgr{opaque(&nativeMgr)}; + NativeManager native_mgr; + Manager mgr{opaque(&native_mgr)}; WHEN("retrieving an IntCounter singleton") { - auto first = mgr.counterSingleton("zeek", "int-count", "test"); + auto first = mgr.CounterSingleton("zeek", "int-count", "test"); THEN("its initial value is zero") { - CHECK_EQ(first.value(), 0); + CHECK_EQ(first.Value(), 0); } - AND_THEN("calling inc() or operator++ changes the value") + AND_THEN("calling Inc() or operator++ changes the value") { - first.inc(); - CHECK_EQ(first.value(), 1); - first.inc(2); - CHECK_EQ(first.value(), 3); + first.Inc(); + CHECK_EQ(first.Value(), 1); + first.Inc(2); + CHECK_EQ(first.Value(), 3); CHECK_EQ(++first, 4); - CHECK_EQ(first.value(), 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"); + 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"); + auto third = mgr.CounterSingleton("zeek", "int-count-2", "test"); CHECK_NE(first, third); } } WHEN("retrieving a DblCounter singleton") { - auto first = mgr.counterSingleton("zeek", "dbl-count", "test"); + auto first = mgr.CounterSingleton("zeek", "dbl-count", "test"); THEN("its initial value is zero") { - CHECK_EQ(first.value(), 0.0); + CHECK_EQ(first.Value(), 0.0); } - AND_THEN("calling inc() changes the value") + 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); + 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("zeek", "dbl-count", "test"); + auto second = mgr.CounterSingleton("zeek", "dbl-count", "test"); CHECK_EQ(first, second); } AND_THEN("calling counterSingleton for a different name returns another handle") { - auto third = mgr.counterSingleton("zeek", "dbl-count-2", "test"); + auto third = mgr.CounterSingleton("zeek", "dbl-count-2", "test"); CHECK_NE(first, third); } } @@ -227,55 +227,55 @@ SCENARIO("telemetry managers provide access to counter families") { GIVEN("a telemetry manager") { - NativeManager nativeMgr; - Manager mgr{opaque(&nativeMgr)}; + NativeManager native_mgr; + Manager mgr{opaque(&native_mgr)}; WHEN("retrieving an IntCounter family") { - auto family = mgr.counterFamily("zeek", "requests", {"method"}, "test", "1", true); + auto family = mgr.CounterFamily("zeek", "requests", {"method"}, "test", "1", true); THEN("the family object stores the parameters") { - CHECK_EQ(family.prefix(), "zeek"sv); - CHECK_EQ(family.name(), "requests"sv); - CHECK_EQ(toVector(family.labelNames()), std::vector{"method"s}); - CHECK_EQ(family.helptext(), "test"sv); - CHECK_EQ(family.unit(), "1"sv); - CHECK_EQ(family.isSum(), true); + CHECK_EQ(family.Prefix(), "zeek"sv); + CHECK_EQ(family.Name(), "requests"sv); + CHECK_EQ(toVector(family.LabelNames()), std::vector{"method"s}); + CHECK_EQ(family.Helptext(), "test"sv); + CHECK_EQ(family.Unit(), "1"sv); + CHECK_EQ(family.IsSum(), true); } AND_THEN("getOrAdd returns the same metric for the same labels") { - auto first = family.getOrAdd({{"method", "get"}}); - auto second = family.getOrAdd({{"method", "get"}}); + 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") { - auto first = family.getOrAdd({{"method", "get"}}); - auto second = family.getOrAdd({{"method", "put"}}); + auto first = family.GetOrAdd({{"method", "get"}}); + auto second = family.GetOrAdd({{"method", "put"}}); CHECK_NE(first, second); } } WHEN("retrieving a DblCounter family") { - auto family = mgr.counterFamily("zeek", "runtime", {"query"}, "test", "seconds", true); + auto family = mgr.CounterFamily("zeek", "runtime", {"query"}, "test", "seconds", true); THEN("the family object stores the parameters") { - CHECK_EQ(family.prefix(), "zeek"sv); - CHECK_EQ(family.name(), "runtime"sv); - CHECK_EQ(toVector(family.labelNames()), std::vector{"query"s}); - CHECK_EQ(family.helptext(), "test"sv); - CHECK_EQ(family.unit(), "seconds"sv); - CHECK_EQ(family.isSum(), true); + CHECK_EQ(family.Prefix(), "zeek"sv); + CHECK_EQ(family.Name(), "runtime"sv); + CHECK_EQ(toVector(family.LabelNames()), std::vector{"query"s}); + CHECK_EQ(family.Helptext(), "test"sv); + CHECK_EQ(family.Unit(), "seconds"sv); + CHECK_EQ(family.IsSum(), true); } AND_THEN("getOrAdd returns the same metric for the same labels") { - auto first = family.getOrAdd({{"query", "foo"}}); - auto second = family.getOrAdd({{"query", "foo"}}); + 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") { - auto first = family.getOrAdd({{"query", "foo"}}); - auto second = family.getOrAdd({{"query", "bar"}}); + auto first = family.GetOrAdd({{"query", "foo"}}); + auto second = family.GetOrAdd({{"query", "bar"}}); CHECK_NE(first, second); } } @@ -286,65 +286,67 @@ SCENARIO("telemetry managers provide access to gauge singletons") { GIVEN("a telemetry manager") { - NativeManager nativeMgr; - Manager mgr{opaque(&nativeMgr)}; + NativeManager native_mgr; + Manager mgr{opaque(&native_mgr)}; WHEN("retrieving an IntGauge singleton") { - auto first = mgr.gaugeSingleton("zeek", "int-gauge", "test"); + auto first = mgr.GaugeSingleton("zeek", "int-gauge", "test"); THEN("its initial value is zero") { - CHECK_EQ(first.value(), 0); + CHECK_EQ(first.Value(), 0); } - AND_THEN("calling inc(), dec(), operator++ or operator-- changes the value") + AND_THEN("calling Inc(), Dec(), operator++ or operator-- changes the value") { - first.inc(); - CHECK_EQ(first.value(), 1); - first.inc(2); - CHECK_EQ(first.value(), 3); - first.dec(); - CHECK_EQ(first.value(), 2); + first.Inc(); + CHECK_EQ(first.Value(), 1); + first.Inc(2); + CHECK_EQ(first.Value(), 3); + first.Dec(); + CHECK_EQ(first.Value(), 2); CHECK_EQ(++first, 3); - CHECK_EQ(first.value(), 3); + CHECK_EQ(first.Value(), 3); CHECK_EQ(--first, 2); - CHECK_EQ(first.value(), 2); + CHECK_EQ(first.Value(), 2); + first.Dec(2); + CHECK_EQ(first.Value(), 0); } AND_THEN("calling gaugeSingleton again for the same name returns the same handle") { - auto second = mgr.gaugeSingleton("zeek", "int-gauge", "test"); + auto second = mgr.GaugeSingleton("zeek", "int-gauge", "test"); CHECK_EQ(first, second); } AND_THEN("calling gaugeSingleton for a different name returns another handle") { - auto third = mgr.gaugeSingleton("zeek", "int-gauge-2", "test"); + auto third = mgr.GaugeSingleton("zeek", "int-gauge-2", "test"); CHECK_NE(first, third); } } WHEN("retrieving a DblGauge singleton") { - auto first = mgr.gaugeSingleton("zeek", "dbl-gauge", "test"); + auto first = mgr.GaugeSingleton("zeek", "dbl-gauge", "test"); THEN("its initial value is zero") { - CHECK_EQ(first.value(), 0.0); + CHECK_EQ(first.Value(), 0.0); } - AND_THEN("calling inc() or dec() changes the value") + AND_THEN("calling Inc() or Dec() changes the value") { - first.inc(); - CHECK_EQ(first.value(), 1.0); - first.inc(3.0); - CHECK_EQ(first.value(), 4.0); - first.dec(2.0); - CHECK_EQ(first.value(), 2.0); - first.dec(); - CHECK_EQ(first.value(), 1.0); + first.Inc(); + CHECK_EQ(first.Value(), 1.0); + first.Inc(3.0); + CHECK_EQ(first.Value(), 4.0); + first.Dec(2.0); + CHECK_EQ(first.Value(), 2.0); + first.Dec(); + CHECK_EQ(first.Value(), 1.0); } AND_THEN("calling gaugeSingleton again for the same name returns the same handle") { - auto second = mgr.gaugeSingleton("zeek", "dbl-gauge", "test"); + auto second = mgr.GaugeSingleton("zeek", "dbl-gauge", "test"); CHECK_EQ(first, second); } AND_THEN("calling gaugeSingleton for a different name returns another handle") { - auto third = mgr.gaugeSingleton("zeek", "dbl-gauge-2", "test"); + auto third = mgr.GaugeSingleton("zeek", "dbl-gauge-2", "test"); CHECK_NE(first, third); } } @@ -355,55 +357,55 @@ SCENARIO("telemetry managers provide access to gauge families") { GIVEN("a telemetry manager") { - NativeManager nativeMgr; - Manager mgr{opaque(&nativeMgr)}; + NativeManager native_mgr; + Manager mgr{opaque(&native_mgr)}; WHEN("retrieving an IntGauge family") { - auto family = mgr.gaugeFamily("zeek", "open-connections", {"protocol"}, "test"); + auto family = mgr.GaugeFamily("zeek", "open-connections", {"protocol"}, "test"); THEN("the family object stores the parameters") { - CHECK_EQ(family.prefix(), "zeek"sv); - CHECK_EQ(family.name(), "open-connections"sv); - CHECK_EQ(toVector(family.labelNames()), std::vector{"protocol"s}); - CHECK_EQ(family.helptext(), "test"sv); - CHECK_EQ(family.unit(), "1"sv); - CHECK_EQ(family.isSum(), false); + CHECK_EQ(family.Prefix(), "zeek"sv); + CHECK_EQ(family.Name(), "open-connections"sv); + CHECK_EQ(toVector(family.LabelNames()), std::vector{"protocol"s}); + CHECK_EQ(family.Helptext(), "test"sv); + CHECK_EQ(family.Unit(), "1"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"}}); + 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", "quic"}}); + auto first = family.GetOrAdd({{"protocol", "tcp"}}); + auto second = family.GetOrAdd({{"protocol", "quic"}}); CHECK_NE(first, second); } } WHEN("retrieving a DblGauge family") { - auto family = mgr.gaugeFamily("zeek", "water-level", {"river"}, "test", "meters"); + auto family = mgr.GaugeFamily("zeek", "water-level", {"river"}, "test", "meters"); THEN("the family object stores the parameters") { - CHECK_EQ(family.prefix(), "zeek"sv); - CHECK_EQ(family.name(), "water-level"sv); - CHECK_EQ(toVector(family.labelNames()), std::vector{"river"s}); - CHECK_EQ(family.helptext(), "test"sv); - CHECK_EQ(family.unit(), "meters"sv); - CHECK_EQ(family.isSum(), false); + CHECK_EQ(family.Prefix(), "zeek"sv); + CHECK_EQ(family.Name(), "water-level"sv); + CHECK_EQ(toVector(family.LabelNames()), std::vector{"river"s}); + CHECK_EQ(family.Helptext(), "test"sv); + CHECK_EQ(family.Unit(), "meters"sv); + CHECK_EQ(family.IsSum(), false); } AND_THEN("getOrAdd returns the same metric for the same labels") { - auto first = family.getOrAdd({{"river", "Sacramento"}}); - auto second = family.getOrAdd({{"river", "Sacramento"}}); + 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") { - auto first = family.getOrAdd({{"query", "Sacramento"}}); - auto second = family.getOrAdd({{"query", "San Joaquin"}}); + auto first = family.GetOrAdd({{"query", "Sacramento"}}); + auto second = family.GetOrAdd({{"query", "San Joaquin"}}); CHECK_NE(first, second); } } diff --git a/src/telemetry/Manager.h b/src/telemetry/Manager.h index 9c9783878b..a6844885db 100644 --- a/src/telemetry/Manager.h +++ b/src/telemetry/Manager.h @@ -31,44 +31,42 @@ public: virtual ~Manager(); /** - * @returns a counter metric family. Creates the family lazily if necessary. + * @return 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. + * @param is_sum Indicates whether this metric accumulates something, where + * only the total value is of interest. */ template - CounterFamily - counterFamily(std::string_view prefix, std::string_view name, - Span labels, - std::string_view helptext, - std::string_view unit = "1", bool isSum = false) { + auto CounterFamily(std::string_view prefix, std::string_view name, + Span labels, + std::string_view helptext, + std::string_view unit = "1", bool is_sum = false) { if constexpr (std::is_same::value) { - return intCounterFam(prefix, name, labels, helptext, unit, isSum); + return IntCounterFam(prefix, name, labels, helptext, unit, is_sum); } else { static_assert(std::is_same::value, "metrics only support int64_t and double values"); - return dblCounterFam(prefix, name, labels, helptext, unit, isSum); + return DblCounterFam(prefix, name, labels, helptext, unit, is_sum); } } - /// @copydoc counterFamily + /// @copydoc CounterFamily template - CounterFamily - counterFamily(std::string_view prefix, std::string_view name, - std::initializer_list labels, - std::string_view helptext, std::string_view unit = "1", - bool isSum = false) + auto CounterFamily(std::string_view prefix, std::string_view name, + std::initializer_list labels, + std::string_view helptext, std::string_view unit = "1", + bool is_sum = false) { - auto lblSpan = Span{labels.begin(), labels.size()}; - return counterFamily(prefix, name, lblSpan, helptext, - unit, isSum); + auto lbl_span = Span{labels.begin(), labels.size()}; + return CounterFamily(prefix, name, lbl_span, helptext, + unit, is_sum); } /** @@ -79,19 +77,19 @@ public: * @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. + * @param is_sum Indicates whether this metric accumulates something, where + * only the total value is of interest. */ template Counter - counterInstance(std::string_view prefix, std::string_view name, + CounterInstance(std::string_view prefix, std::string_view name, Span labels, std::string_view helptext, - std::string_view unit = "1", bool isSum = false) + std::string_view unit = "1", bool is_sum = false) { - return withLabelNames(labels, [&, this](auto labelNames) + return WithLabelNames(labels, [&, this](auto labelNames) { - auto family = counterFamily(prefix, name, labelNames, - helptext, unit, isSum); + auto family = CounterFamily(prefix, name, labelNames, + helptext, unit, is_sum); return family.getOrAdd(labels); }); } @@ -99,13 +97,13 @@ public: /// @copydoc counterInstance template Counter - counterInstance(std::string_view prefix, std::string_view name, + CounterInstance(std::string_view prefix, std::string_view name, std::initializer_list labels, std::string_view helptext, std::string_view unit = "1", - bool isSum = false) + bool is_sum = false) { - auto lblSpan = Span{labels.begin(), labels.size()}; - return counterInstance(prefix, name, lblSpan, helptext, unit, isSum); + auto lbl_span = Span{labels.begin(), labels.size()}; + return CounterInstance(prefix, name, lbl_span, helptext, unit, is_sum); } /** @@ -116,60 +114,58 @@ public: * @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. + * @param is_sum Indicates whether this metric accumulates something, where + * only the total value is of interest. */ template Counter - counterSingleton(std::string_view prefix, std::string_view name, + CounterSingleton(std::string_view prefix, std::string_view name, std::string_view helptext, std::string_view unit = "1", - bool isSum = false) + bool is_sum = false) { auto labels = Span{}; - auto fam = counterFamily(prefix, name, labels, helptext, - unit, isSum); - return fam.getOrAdd({}); + auto fam = CounterFamily(prefix, name, labels, helptext, + unit, is_sum); + return fam.GetOrAdd({}); } /** - * @returns a gauge metric family. Creates the family lazily if necessary. + * @return A gauge 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. + * @param is_sum Indicates whether this metric accumulates something, where + * only the total value is of interest. */ template - GaugeFamily - gaugeFamily(std::string_view prefix, std::string_view name, - Span labels, - std::string_view helptext, - std::string_view unit = "1", bool isSum = false) { + auto GaugeFamily(std::string_view prefix, std::string_view name, + Span labels, + std::string_view helptext, + std::string_view unit = "1", bool is_sum = false) { if constexpr (std::is_same::value) { - return intGaugeFam(prefix, name, labels, helptext, unit, isSum); + return IntGaugeFam(prefix, name, labels, helptext, unit, is_sum); } else { static_assert(std::is_same::value, "metrics only support int64_t and double values"); - return dblGaugeFam(prefix, name, labels, helptext, unit, isSum); + return DblGaugeFam(prefix, name, labels, helptext, unit, is_sum); } } - /// @copydoc gaugeFamily + /// @copydoc GaugeFamily template - GaugeFamily - gaugeFamily(std::string_view prefix, std::string_view name, - std::initializer_list labels, - std::string_view helptext, std::string_view unit = "1", - bool isSum = false) + auto GaugeFamily(std::string_view prefix, std::string_view name, + std::initializer_list labels, + std::string_view helptext, std::string_view unit = "1", + bool is_sum = false) { - auto lblSpan = Span{labels.begin(), labels.size()}; - return gaugeFamily(prefix, name, lblSpan, helptext, - unit, isSum); + auto lbl_span = Span{labels.begin(), labels.size()}; + return GaugeFamily(prefix, name, lbl_span, helptext, + unit, is_sum); } /** @@ -180,33 +176,33 @@ public: * @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. + * @param is_sum Indicates whether this metric accumulates something, where + * only the total value is of interest. */ template Gauge - gaugeInstance(std::string_view prefix, std::string_view name, - Span labels, std::string_view helptext, - std::string_view unit = "1", bool isSum = false) + GaugeInstance(std::string_view prefix, std::string_view name, + Span labels, std::string_view helptext, + std::string_view unit = "1", bool is_sum = false) { - return withLabelNames(labels, [&, this](auto labelNames) + return WithLabelNames(labels, [&, this](auto labelNames) { - auto family = gaugeFamily(prefix, name, labelNames, - helptext, unit, isSum); + auto family = GaugeFamily(prefix, name, labelNames, + helptext, unit, is_sum); return family.getOrAdd(labels); }); } - /// @copydoc gaugeInstance + /// @copydoc GaugeInstance template Gauge - gaugeInstance(std::string_view prefix, std::string_view name, + GaugeInstance(std::string_view prefix, std::string_view name, std::initializer_list labels, std::string_view helptext, std::string_view unit = "1", - bool isSum = false) + bool is_sum = false) { - auto lblSpan = Span{labels.begin(), labels.size()}; - return gaugeInstance(prefix, name, lblSpan, helptext, unit, isSum); + auto lbl_span = Span{labels.begin(), labels.size()}; + return GaugeInstance(prefix, name, lbl_span, helptext, unit, is_sum); } /** @@ -217,44 +213,48 @@ public: * @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. + * @param is_sum Indicates whether this metric accumulates something, where + * only the total value is of interest. */ template Gauge - gaugeSingleton(std::string_view prefix, std::string_view name, - std::string_view helptext, std::string_view unit = "1", - bool isSum = false) + GaugeSingleton(std::string_view prefix, std::string_view name, + std::string_view helptext, std::string_view unit = "1", + bool is_sum = false) { auto labels = Span{}; - auto fam = gaugeFamily(prefix, name, labels, helptext, - unit, isSum); - return fam.getOrAdd({}); + auto fam = GaugeFamily(prefix, name, labels, helptext, + unit, is_sum); + return fam.GetOrAdd({}); } private: IntCounterFamily - intCounterFam(std::string_view prefix, std::string_view name, + IntCounterFam(std::string_view prefix, std::string_view name, Span labels, - std::string_view helptext, std::string_view unit, bool isSum); + std::string_view helptext, std::string_view unit, + bool is_sum); DblCounterFamily - dblCounterFam(std::string_view prefix, std::string_view name, + DblCounterFam(std::string_view prefix, std::string_view name, Span labels, - std::string_view helptext, std::string_view unit, bool isSum); + std::string_view helptext, std::string_view unit, + bool is_sum); IntGaugeFamily - intGaugeFam(std::string_view prefix, std::string_view name, + IntGaugeFam(std::string_view prefix, std::string_view name, Span labels, - std::string_view helptext, std::string_view unit, bool isSum); + std::string_view helptext, std::string_view unit, + bool is_sum); DblGaugeFamily - dblGaugeFam(std::string_view prefix, std::string_view name, + DblGaugeFam(std::string_view prefix, std::string_view name, Span labels, - std::string_view helptext, std::string_view unit, bool isSum); + std::string_view helptext, std::string_view unit, + bool is_sum); template - static void withLabelNames(Span xs, F continuation) + static void WithLabelNames(Span xs, F continuation) { if ( xs.size() <= 10 ) { std::string_view buf[10]; diff --git a/src/telemetry/MetricFamily.cc b/src/telemetry/MetricFamily.cc index dbece54de3..f3660fbdbc 100644 --- a/src/telemetry/MetricFamily.cc +++ b/src/telemetry/MetricFamily.cc @@ -19,32 +19,32 @@ auto& deref(MetricFamily::Impl* ptr) } // namespace -std::string_view MetricFamily::prefix() const noexcept +std::string_view MetricFamily::Prefix() const noexcept { return deref(pimpl).prefix(); } -std::string_view MetricFamily::name() const noexcept +std::string_view MetricFamily::Name() const noexcept { return deref(pimpl).name(); } -Span MetricFamily::labelNames() const noexcept +Span MetricFamily::LabelNames() const noexcept { return deref(pimpl).label_names(); } -std::string_view MetricFamily::helptext() const noexcept +std::string_view MetricFamily::Helptext() const noexcept { return deref(pimpl).helptext(); } -std::string_view MetricFamily::unit() const noexcept +std::string_view MetricFamily::Unit() const noexcept { return deref(pimpl).unit(); } -bool MetricFamily::isSum() const noexcept +bool MetricFamily::IsSum() const noexcept { return deref(pimpl).is_sum(); } diff --git a/src/telemetry/MetricFamily.h b/src/telemetry/MetricFamily.h index 403e1aa90d..50e59b22e4 100644 --- a/src/telemetry/MetricFamily.h +++ b/src/telemetry/MetricFamily.h @@ -28,42 +28,42 @@ public: 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. + * @return 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; + std::string_view Prefix() const noexcept; /** - * @returns the human-readable name of the metric, e.g., + * @return The human-readable name of the metric, e.g., * @p open-connections. */ - std::string_view name() const noexcept; + std::string_view Name() const noexcept; /** - * @returns the names for all label dimensions. + * @return The names for all label dimensions. */ - Span labelNames() const noexcept; + Span LabelNames() const noexcept; /** - * @returns a short explanation of the metric. + * @return A short explanation of the metric. */ - std::string_view helptext() const noexcept; + 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. + * @return 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; + 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. + * @return 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; + bool IsSum() const noexcept; protected: explicit MetricFamily(Impl* ptr) : pimpl(ptr) From 0b665ee130e52c024be1a2031b35c6b329323d04 Mon Sep 17 00:00:00 2001 From: Dominik Charousset Date: Tue, 2 Mar 2021 10:49:59 +0100 Subject: [PATCH 07/13] Move duplicated code to detail header --- src/telemetry/Counter.cc | 110 ++++++++++++--------------------------- src/telemetry/Counter.h | 4 ++ src/telemetry/Detail.h | 90 ++++++++++++++++++++++++++++++++ src/telemetry/Gauge.cc | 110 ++++++++++++--------------------------- src/telemetry/Gauge.h | 4 ++ 5 files changed, 164 insertions(+), 154 deletions(-) create mode 100644 src/telemetry/Detail.h diff --git a/src/telemetry/Counter.cc b/src/telemetry/Counter.cc index 1b2e0aefae..e8f8841ce2 100644 --- a/src/telemetry/Counter.cc +++ b/src/telemetry/Counter.cc @@ -6,93 +6,49 @@ #include "caf/telemetry/metric_family.hpp" #include "caf/telemetry/metric_family_impl.hpp" -namespace zeek::telemetry { - -// -- private utilities -------------------------------------------------------- - -namespace { +#include "zeek/telemetry/Detail.h" namespace ct = caf::telemetry; -using NativeMetricFamily = ct::metric_family; +namespace zeek::telemetry { -using NativeIntCounter = ct::int_counter; +// -- bindings to private utility functions ------------------------------------ -using NativeIntCounterFamily = ct::metric_family_impl; - -using NativeDblCounter = ct::dbl_counter; - -using NativeDblCounterFamily = ct::metric_family_impl; - -auto& deref(IntCounter::Impl* ptr) +template <> +struct PimplTrait { - return *reinterpret_cast(ptr); - } + using Native = ct::int_counter; + using Oqaque = IntCounter::Impl; + using NativeFamily = ct::metric_family_impl; + }; -auto& deref(IntCounterFamily*, MetricFamily::Impl* ptr) +template <> +struct PimplTrait : PimplTrait { }; + +template <> +struct PimplTrait { - auto basePtr = reinterpret_cast(ptr); - return *static_cast(basePtr); - } + using Native = typename PimplTrait::NativeFamily; + using Oqaque = IntCounterFamily::Impl; + }; -auto upcast(IntCounterFamily::Impl* ptr) +template <> +struct PimplTrait { - auto native = reinterpret_cast(ptr); - auto basePtr = static_cast(native); - return reinterpret_cast(basePtr); - } + using Native = ct::dbl_counter; + using Oqaque = DblCounter::Impl; + using NativeFamily = ct::metric_family_impl; + }; -auto opaque(NativeIntCounter* ptr) +template <> +struct PimplTrait : PimplTrait { }; + +template <> +struct PimplTrait { - return reinterpret_cast(ptr); - } - -auto& deref(DblCounter::Impl* ptr) - { - return *reinterpret_cast(ptr); - } - -auto& deref(DblCounterFamily*, MetricFamily::Impl* ptr) - { - auto basePtr = reinterpret_cast(ptr); - return *static_cast(basePtr); - } - -auto upcast(DblCounterFamily::Impl* ptr) - { - auto native = reinterpret_cast(ptr); - auto basePtr = static_cast(native); - return reinterpret_cast(basePtr); - } - -auto opaque(NativeDblCounter* ptr) - { - return reinterpret_cast(ptr); - } - -template -auto withNativeLabels(Span 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 buf; - for ( auto x : xs ) - buf.emplace_back(x.first, x.second); - return continuation(Span{buf}); - } - } - -} // namespace + using Native = typename PimplTrait::NativeFamily; + using Oqaque = DblCounterFamily::Impl; + }; // -- IntCounter --------------------------------------------------------------- @@ -122,7 +78,7 @@ IntCounterFamily::IntCounterFamily(Impl* ptr) : MetricFamily(upcast(ptr)) IntCounter IntCounterFamily::GetOrAdd(Span labels) { - return withNativeLabels(labels, [this](auto nativeLabels) + return with_native_labels(labels, [this](auto nativeLabels) { auto hdl = opaque(deref(this, pimpl).get_or_add(nativeLabels)); return IntCounter{hdl}; @@ -152,7 +108,7 @@ DblCounterFamily::DblCounterFamily(Impl* ptr) : MetricFamily(upcast(ptr)) DblCounter DblCounterFamily::GetOrAdd(Span labels) { - return withNativeLabels(labels, [this](auto nativeLabels) + return with_native_labels(labels, [this](auto nativeLabels) { auto hdl = opaque(deref(this, pimpl).get_or_add(nativeLabels)); return DblCounter{hdl}; diff --git a/src/telemetry/Counter.h b/src/telemetry/Counter.h index 6c4d88ce0a..885a0f20f3 100644 --- a/src/telemetry/Counter.h +++ b/src/telemetry/Counter.h @@ -91,6 +91,8 @@ public: class Impl; + using InstanceType = IntCounter; + IntCounterFamily(const IntCounterFamily&) noexcept = default; IntCounterFamily& operator=(const IntCounterFamily&) noexcept = default; @@ -183,6 +185,8 @@ public: class Impl; + using InstanceType = DblCounter; + DblCounterFamily(const DblCounterFamily&) noexcept = default; DblCounterFamily& operator=(const DblCounterFamily&) noexcept = default; diff --git a/src/telemetry/Detail.h b/src/telemetry/Detail.h new file mode 100644 index 0000000000..15a3d867f3 --- /dev/null +++ b/src/telemetry/Detail.h @@ -0,0 +1,90 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +// This header contains private implementation details for telemetry classes +// and should not get included outside of .cc files. + +#pragma once + +#include +#include +#include + +#include "zeek/Span.h" +#include "zeek/telemetry/MetricFamily.h" + +#include "caf/telemetry/label_view.hpp" +#include "caf/telemetry/metric_family.hpp" + +namespace zeek::telemetry { + +/** + * 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 + * @c IntCounter, the trait must also provide the member type @c NativeFamily. + */ +template +struct PimplTrait; + +template ::Native> +auto& deref(T* ptr) + { + return *reinterpret_cast(ptr); + } + +template +auto& deref(Family*, MetricFamily::Impl* ptr) + { + using InstanceType = typename Family::InstanceType; + using ImplType = typename InstanceType::Impl; + using NativeType = typename PimplTrait::NativeFamily; + return *reinterpret_cast(ptr); + } + +template ::Oqaque> +auto opaque(T* ptr) + { + return reinterpret_cast(ptr); + } + +template +auto opaque(const Family*, MetricFamily::Impl* ptr) + { + using InstanceType = typename Family::InstanceType; + using ImplType = typename InstanceType::Impl; + using OpaqueType = typename PimplTrait::NativeFamily; + return reinterpret_cast(ptr); + } + +template ::Native> +auto upcast(T* ptr) + { + auto native = reinterpret_cast(ptr); + auto base_ptr = static_cast(native); + return reinterpret_cast(base_ptr); + } + +template +auto with_native_labels(Span xs, F continuation) + { + namespace ct = caf::telemetry; + + 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 buf; + for ( auto x : xs ) + buf.emplace_back(x.first, x.second); + return continuation(Span{buf}); + } + } + +} // namespace zeek::telemetry diff --git a/src/telemetry/Gauge.cc b/src/telemetry/Gauge.cc index 4c12477f32..0cd4a1a91e 100644 --- a/src/telemetry/Gauge.cc +++ b/src/telemetry/Gauge.cc @@ -6,93 +6,49 @@ #include "caf/telemetry/metric_family.hpp" #include "caf/telemetry/metric_family_impl.hpp" -namespace zeek::telemetry { - -// -- private utilities -------------------------------------------------------- - -namespace { +#include "zeek/telemetry/Detail.h" namespace ct = caf::telemetry; -using NativeMetricFamily = ct::metric_family; +namespace zeek::telemetry { -using NativeIntGauge = ct::int_gauge; +// -- bindings to private utility functions ------------------------------------ -using NativeIntGaugeFamily = ct::metric_family_impl; - -using NativeDblGauge = ct::dbl_gauge; - -using NativeDblGaugeFamily = ct::metric_family_impl; - -auto& deref(IntGauge::Impl* ptr) +template <> +struct PimplTrait { - return *reinterpret_cast(ptr); - } + using Native = ct::int_gauge; + using Oqaque = IntGauge::Impl; + using NativeFamily = ct::metric_family_impl; + }; -auto& deref(IntGaugeFamily*, MetricFamily::Impl* ptr) +template <> +struct PimplTrait : PimplTrait { }; + +template <> +struct PimplTrait { - auto basePtr = reinterpret_cast(ptr); - return *static_cast(basePtr); - } + using Native = typename PimplTrait::NativeFamily; + using Oqaque = IntGaugeFamily::Impl; + }; -auto upcast(IntGaugeFamily::Impl* ptr) +template <> +struct PimplTrait { - auto native = reinterpret_cast(ptr); - auto basePtr = static_cast(native); - return reinterpret_cast(basePtr); - } + using Native = ct::dbl_gauge; + using Oqaque = DblGauge::Impl; + using NativeFamily = ct::metric_family_impl; + }; -auto opaque(NativeIntGauge* ptr) +template <> +struct PimplTrait : PimplTrait { }; + +template <> +struct PimplTrait { - return reinterpret_cast(ptr); - } - -auto& deref(DblGauge::Impl* ptr) - { - return *reinterpret_cast(ptr); - } - -auto& deref(DblGaugeFamily*, MetricFamily::Impl* ptr) - { - auto basePtr = reinterpret_cast(ptr); - return *static_cast(basePtr); - } - -auto upcast(DblGaugeFamily::Impl* ptr) - { - auto native = reinterpret_cast(ptr); - auto basePtr = static_cast(native); - return reinterpret_cast(basePtr); - } - -auto opaque(NativeDblGauge* ptr) - { - return reinterpret_cast(ptr); - } - -template -auto withNativeLabels(Span 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 buf; - for ( auto x : xs ) - buf.emplace_back(x.first, x.second); - return continuation(Span{buf}); - } - } - -} // namespace + using Native = typename PimplTrait::NativeFamily; + using Oqaque = DblGaugeFamily::Impl; + }; // -- IntGauge --------------------------------------------------------------- @@ -137,7 +93,7 @@ IntGaugeFamily::IntGaugeFamily(Impl* ptr) : MetricFamily(upcast(ptr)) IntGauge IntGaugeFamily::GetOrAdd(Span labels) { - return withNativeLabels(labels, [this](auto nativeLabels) + return with_native_labels(labels, [this](auto nativeLabels) { auto hdl = opaque(deref(this, pimpl).get_or_add(nativeLabels)); return IntGauge{hdl}; @@ -177,7 +133,7 @@ DblGaugeFamily::DblGaugeFamily(Impl* ptr) : MetricFamily(upcast(ptr)) DblGauge DblGaugeFamily::GetOrAdd(Span labels) { - return withNativeLabels(labels, [this](auto nativeLabels) + return with_native_labels(labels, [this](auto nativeLabels) { auto hdl = opaque(deref(this, pimpl).get_or_add(nativeLabels)); return DblGauge{hdl}; diff --git a/src/telemetry/Gauge.h b/src/telemetry/Gauge.h index 8d4121f301..25ba22ee0b 100644 --- a/src/telemetry/Gauge.h +++ b/src/telemetry/Gauge.h @@ -107,6 +107,8 @@ public: class Impl; + using InstanceType = IntGauge; + IntGaugeFamily(const IntGaugeFamily&) noexcept = default; IntGaugeFamily& operator=(const IntGaugeFamily&) noexcept = default; @@ -209,6 +211,8 @@ public: class Impl; + using InstanceType = DblGauge; + DblGaugeFamily(const DblGaugeFamily&) noexcept = default; DblGaugeFamily& operator=(const DblGaugeFamily&) noexcept = default; From d4466db5ce50c3ad8be2f980d6d55e84ac967886 Mon Sep 17 00:00:00 2001 From: Dominik Charousset Date: Tue, 2 Mar 2021 12:54:20 +0100 Subject: [PATCH 08/13] Add handle types for histogram metrics --- src/telemetry/CMakeLists.txt | 1 + src/telemetry/Counter.cc | 38 ----- src/telemetry/Detail.h | 174 +++++++++++++++++++++ src/telemetry/Gauge.cc | 40 ----- src/telemetry/Histogram.cc | 103 +++++++++++++ src/telemetry/Histogram.h | 234 +++++++++++++++++++++++++++++ src/telemetry/Manager.cc | 282 ++++++++++++++++++++++++----------- src/telemetry/Manager.h | 184 +++++++++++++++++++++-- 8 files changed, 884 insertions(+), 172 deletions(-) create mode 100644 src/telemetry/Histogram.cc create mode 100644 src/telemetry/Histogram.h diff --git a/src/telemetry/CMakeLists.txt b/src/telemetry/CMakeLists.txt index 004ab29b42..14b59d3c36 100644 --- a/src/telemetry/CMakeLists.txt +++ b/src/telemetry/CMakeLists.txt @@ -8,6 +8,7 @@ include_directories(BEFORE set(telemetry_SRCS Counter.cc Gauge.cc + Histogram.cc Manager.cc MetricFamily.cc ) diff --git a/src/telemetry/Counter.cc b/src/telemetry/Counter.cc index e8f8841ce2..6b4f76adc3 100644 --- a/src/telemetry/Counter.cc +++ b/src/telemetry/Counter.cc @@ -12,44 +12,6 @@ namespace ct = caf::telemetry; namespace zeek::telemetry { -// -- bindings to private utility functions ------------------------------------ - -template <> -struct PimplTrait - { - using Native = ct::int_counter; - using Oqaque = IntCounter::Impl; - using NativeFamily = ct::metric_family_impl; - }; - -template <> -struct PimplTrait : PimplTrait { }; - -template <> -struct PimplTrait - { - using Native = typename PimplTrait::NativeFamily; - using Oqaque = IntCounterFamily::Impl; - }; - -template <> -struct PimplTrait - { - using Native = ct::dbl_counter; - using Oqaque = DblCounter::Impl; - using NativeFamily = ct::metric_family_impl; - }; - -template <> -struct PimplTrait : PimplTrait { }; - -template <> -struct PimplTrait - { - using Native = typename PimplTrait::NativeFamily; - using Oqaque = DblCounterFamily::Impl; - }; - // -- IntCounter --------------------------------------------------------------- void IntCounter::Inc() noexcept diff --git a/src/telemetry/Detail.h b/src/telemetry/Detail.h index 15a3d867f3..0a235df868 100644 --- a/src/telemetry/Detail.h +++ b/src/telemetry/Detail.h @@ -10,6 +10,10 @@ #include #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 struct PimplTrait; +template <> +struct PimplTrait + { + using Native = caf::telemetry::int_counter; + using Oqaque = IntCounter::Impl; + using NativeFamily = caf::telemetry::metric_family_impl; + }; + +template <> +struct PimplTrait +: PimplTrait { }; + +template <> +struct PimplTrait + { + using Native = typename PimplTrait::NativeFamily; + using Oqaque = IntCounterFamily::Impl; + }; + +template <> +struct PimplTrait::NativeFamily> +: PimplTrait { }; + +template <> +struct PimplTrait + { + using Native = caf::telemetry::dbl_counter; + using Oqaque = DblCounter::Impl; + using NativeFamily = caf::telemetry::metric_family_impl; + }; + +template <> +struct PimplTrait +: PimplTrait { }; + +template <> +struct PimplTrait + { + using Native = typename PimplTrait::NativeFamily; + using Oqaque = DblCounterFamily::Impl; + }; + +template <> +struct PimplTrait::NativeFamily> +: PimplTrait { }; + +template <> +struct PimplTrait + { + using Native = caf::telemetry::int_gauge; + using Oqaque = IntGauge::Impl; + using NativeFamily = caf::telemetry::metric_family_impl; + }; + +template <> +struct PimplTrait : PimplTrait { }; + +template <> +struct PimplTrait + { + using Native = typename PimplTrait::NativeFamily; + using Oqaque = IntGaugeFamily::Impl; + }; + +template <> +struct PimplTrait::NativeFamily> +: PimplTrait { }; + +template <> +struct PimplTrait + { + using Native = caf::telemetry::dbl_gauge; + using Oqaque = DblGauge::Impl; + using NativeFamily = caf::telemetry::metric_family_impl; + }; + +template <> +struct PimplTrait : PimplTrait { }; + +template <> +struct PimplTrait + { + using Native = typename PimplTrait::NativeFamily; + using Oqaque = DblGaugeFamily::Impl; + }; + +template <> +struct PimplTrait::NativeFamily> +: PimplTrait { }; + +template <> +struct PimplTrait + { + using Native = caf::telemetry::int_histogram; + using Oqaque = IntHistogram::Impl; + using NativeFamily = caf::telemetry::metric_family_impl; + }; + +template <> +struct PimplTrait +: PimplTrait { }; + +template <> +struct PimplTrait + { + using Native = typename PimplTrait::NativeFamily; + using Oqaque = IntHistogramFamily::Impl; + }; + +template <> +struct PimplTrait::NativeFamily> +: PimplTrait { }; + +template <> +struct PimplTrait + { + using Native = caf::telemetry::dbl_histogram; + using Oqaque = DblHistogram::Impl; + using NativeFamily = caf::telemetry::metric_family_impl; + }; + +template <> +struct PimplTrait +: PimplTrait { }; + +template <> +struct PimplTrait + { + using Native = typename PimplTrait::NativeFamily; + using Oqaque = DblHistogramFamily::Impl; + }; + +template <> +struct PimplTrait::NativeFamily> +: PimplTrait { }; + +template <> +struct PimplTrait + { + using Native = caf::telemetry::metric_registry; + using Oqaque = Manager::Impl; + }; + +template <> +struct PimplTrait::Native> +: PimplTrait { }; + +// -- free functions ----------------------------------------------------------- + template ::Native> auto& deref(T* ptr) { @@ -87,4 +242,23 @@ auto with_native_labels(Span xs, F continuation) } } +template +auto with_native_labels(Span 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 buf; + for ( auto x : xs ) + buf.emplace_back(x); + return continuation(Span{buf}); + } + } + } // namespace zeek::telemetry diff --git a/src/telemetry/Gauge.cc b/src/telemetry/Gauge.cc index 0cd4a1a91e..2db5311cdb 100644 --- a/src/telemetry/Gauge.cc +++ b/src/telemetry/Gauge.cc @@ -8,48 +8,8 @@ #include "zeek/telemetry/Detail.h" -namespace ct = caf::telemetry; - namespace zeek::telemetry { -// -- bindings to private utility functions ------------------------------------ - -template <> -struct PimplTrait - { - using Native = ct::int_gauge; - using Oqaque = IntGauge::Impl; - using NativeFamily = ct::metric_family_impl; - }; - -template <> -struct PimplTrait : PimplTrait { }; - -template <> -struct PimplTrait - { - using Native = typename PimplTrait::NativeFamily; - using Oqaque = IntGaugeFamily::Impl; - }; - -template <> -struct PimplTrait - { - using Native = ct::dbl_gauge; - using Oqaque = DblGauge::Impl; - using NativeFamily = ct::metric_family_impl; - }; - -template <> -struct PimplTrait : PimplTrait { }; - -template <> -struct PimplTrait - { - using Native = typename PimplTrait::NativeFamily; - using Oqaque = DblGaugeFamily::Impl; - }; - // -- IntGauge --------------------------------------------------------------- void IntGauge::Inc() noexcept diff --git a/src/telemetry/Histogram.cc b/src/telemetry/Histogram.cc new file mode 100644 index 0000000000..b02fe88bd1 --- /dev/null +++ b/src/telemetry/Histogram.cc @@ -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 + +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 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 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 diff --git a/src/telemetry/Histogram.h b/src/telemetry/Histogram.h new file mode 100644 index 0000000000..93a0189e18 --- /dev/null +++ b/src/telemetry/Histogram.h @@ -0,0 +1,234 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#pragma once + +#include +#include +#include + +#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 labels); + + /** + * @copydoc GetOrAdd + */ + IntHistogram GetOrAdd(std::initializer_list 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 labels); + + /** + * @copydoc GetOrAdd + */ + DblHistogram GetOrAdd(std::initializer_list labels) + { + return GetOrAdd(Span{labels.begin(), labels.size()}); + } + +private: + explicit DblHistogramFamily(Impl* ptr); +}; + +namespace detail { + +template +struct HistogramOracle { + static_assert(std::is_same::value, + "Histogram only supports int64_t and double"); + + using type = IntHistogram; +}; + +template <> +struct HistogramOracle { + using type = DblHistogram; +}; + +} // namespace detail + +template +using Histogram = typename detail::HistogramOracle::type; + +} // namespace zeek::telemetry diff --git a/src/telemetry/Manager.cc b/src/telemetry/Manager.cc index 2c006d1def..3670cd9cdf 100644 --- a/src/telemetry/Manager.cc +++ b/src/telemetry/Manager.cc @@ -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; - -using NativeDblCounter = ct::dbl_counter; - -using NativeDblCounterFamily = ct::metric_family_impl; - -using NativeIntGauge = ct::int_gauge; - -using NativeIntGaugeFamily = ct::metric_family_impl; - -using NativeDblGauge = ct::dbl_gauge; - -using NativeDblGaugeFamily = ct::metric_family_impl; - -auto& deref(Manager::Impl* ptr) - { - return *reinterpret_cast(ptr); - } - -auto opaque(NativeManager* ptr) - { - return reinterpret_cast(ptr); - } - -auto opaque(NativeIntCounterFamily* ptr) - { - return reinterpret_cast(ptr); - } - -auto opaque(NativeDblCounterFamily* ptr) - { - return reinterpret_cast(ptr); - } - -auto opaque(NativeIntGaugeFamily* ptr) - { - return reinterpret_cast(ptr); - } - -auto opaque(NativeDblGaugeFamily* ptr) - { - return reinterpret_cast(ptr); - } - -template -auto with_native(Span 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 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(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(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 labels, + Span ubounds, + std::string_view helptext, + std::string_view unit, bool is_sum) + { + return with_native_labels(labels, [&, this](auto xs) + { + auto bounds = caf::span{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 labels, + Span ubounds, + std::string_view helptext, + std::string_view unit, bool is_sum) + { + return with_native_labels(labels, [&, this](auto xs) + { + auto bounds = caf::span{ubounds.data(), ubounds.size()}; + auto ptr = deref(pimpl).histogram_family(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 @@ -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::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("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("zeek", "dbl-count", buckets, "test"); + CHECK_EQ(first, second); + } + AND_THEN("calling histogramSingleton for a different name returns another handle") + { + auto third = mgr.HistogramSingleton("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("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); + } + } + } + } diff --git a/src/telemetry/Manager.h b/src/telemetry/Manager.h index a6844885db..9c8aa08427 100644 --- a/src/telemetry/Manager.h +++ b/src/telemetry/Manager.h @@ -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 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::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 @@ -162,11 +164,11 @@ public: std::initializer_list labels, std::string_view helptext, std::string_view unit = "1", bool is_sum = false) - { - auto lbl_span = Span{labels.begin(), labels.size()}; - return GaugeFamily(prefix, name, lbl_span, helptext, - unit, is_sum); - } + { + auto lbl_span = Span{labels.begin(), labels.size()}; + return GaugeFamily(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` instead of trying to + // match paremeters to a `span`. + template + struct ConstSpanOracle + { + using Type = Span; + }; + + // Convenience alias to safe some typing. + template + using ConstSpan = typename ConstSpanOracle::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 + auto HistogramFamily(std::string_view prefix, std::string_view name, + Span labels, + ConstSpan default_upper_bounds, + std::string_view helptext, std::string_view unit = "1", + bool is_sum = false) + { + if constexpr (std::is_same::value) + { + return IntHistoFam(prefix, name, labels, default_upper_bounds, + helptext, unit, is_sum); + } + else + { + static_assert(std::is_same::value, + "metrics only support int64_t and double values"); + return DblHistoFam(prefix, name, labels, default_upper_bounds, + helptext, unit, is_sum); + } + } + + /// @copydoc HistogramFamily + template + auto HistogramFamily(std::string_view prefix, std::string_view name, + std::initializer_list labels, + ConstSpan 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(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 + Histogram + HistogramInstance(std::string_view prefix, std::string_view name, + Span labels, + ConstSpan 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(prefix, name, labelNames, + default_upper_bounds, + helptext, unit, is_sum); + return family.getOrAdd(labels); + }); + } + + /// @copdoc HistogramInstance + template + Histogram + HistogramInstance(std::string_view prefix, std::string_view name, + std::initializer_list labels, + ConstSpan 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 + Histogram + HistogramSingleton(std::string_view prefix, std::string_view name, + ConstSpan default_upper_bounds, + std::string_view helptext, std::string_view unit = "1", + bool is_sum = false) + { + auto lbls = Span{}; + auto fam = HistogramFamily(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 labels, + Span ubounds, std::string_view helptext, + std::string_view unit, bool is_sum); + + DblHistogramFamily + DblHistoFam(std::string_view prefix, std::string_view name, + Span labels, + Span ubounds, std::string_view helptext, + std::string_view unit, bool is_sum); + template static void WithLabelNames(Span 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 From 2bac354e4300266292879c8f0b04883b992401f8 Mon Sep 17 00:00:00 2001 From: Dominik Charousset Date: Thu, 4 Mar 2021 17:23:44 +0100 Subject: [PATCH 09/13] Expose telemetry API to scripting land --- scripts/base/init-bare.zeek | 16 +- src/OpaqueVal.cc | 59 ++ src/OpaqueVal.h | 65 +++ src/Type.h | 12 + src/broker/Manager.cc | 30 +- src/telemetry/CMakeLists.txt | 5 +- src/telemetry/Counter.h | 8 + src/telemetry/Gauge.h | 8 + src/telemetry/Histogram.h | 8 + src/telemetry/Manager.cc | 4 + src/telemetry/Manager.h | 8 +- src/telemetry/telemetry.bif | 550 ++++++++++++++++++ src/zeek-setup.cc | 25 + .../btest/Baseline/telemetry.counter/output | 5 + testing/btest/Baseline/telemetry.gauge/output | 5 + .../btest/Baseline/telemetry.histogram/output | 5 + testing/btest/btest.cfg | 2 +- testing/btest/telemetry/counter.zeek | 25 + testing/btest/telemetry/gauge.zeek | 30 + testing/btest/telemetry/histogram.zeek | 28 + 20 files changed, 887 insertions(+), 11 deletions(-) create mode 100644 src/telemetry/telemetry.bif create mode 100644 testing/btest/Baseline/telemetry.counter/output create mode 100644 testing/btest/Baseline/telemetry.gauge/output create mode 100644 testing/btest/Baseline/telemetry.histogram/output create mode 100644 testing/btest/telemetry/counter.zeek create mode 100644 testing/btest/telemetry/gauge.zeek create mode 100644 testing/btest/telemetry/histogram.zeek diff --git a/scripts/base/init-bare.zeek b/scripts/base/init-bare.zeek index d57786c74a..a4292c35cb 100644 --- a/scripts/base/init-bare.zeek +++ b/scripts/base/init-bare.zeek @@ -46,6 +46,20 @@ type count_set: set[count]; ## directly and then remove this alias. type index_vec: vector of count; +## A vector of integers, used by telemetry builtin functions to store histogram bounds. +## +## .. todo:: We need this type definition only for declaring builtin functions +## via ``bifcl``. We should extend ``bifcl`` to understand composite types +## directly and then remove this alias. +type int_vec: vector of int; + +## A vector of floating point numbers, used by telemetry builtin functions to store histogram bounds. +## +## .. todo:: We need this type definition only for declaring builtin functions +## via ``bifcl``. We should extend ``bifcl`` to understand composite types +## directly and then remove this alias. +type double_vec: vector of double; + ## A vector of subnets. ## ## .. todo:: We need this type definition only for declaring builtin functions @@ -3844,7 +3858,7 @@ type dns_loc_rr: record { vert_pre: count; ##< The vertical precision of the data, in centimeters. latitude: count; ##< The latitude of the center of the sphere. longitude: count; ##< The longitude of the center of the sphere. - altitude: count; ##< The altitude of the center of the sphere. + altitude: count; ##< The altitude of the center of the sphere. is_query: count; ##< The RR is a query/Response. }; diff --git a/src/OpaqueVal.cc b/src/OpaqueVal.cc index f4439e39eb..a0d50f569d 100644 --- a/src/OpaqueVal.cc +++ b/src/OpaqueVal.cc @@ -1033,4 +1033,63 @@ ValPtr ParaglobVal::DoClone(CloneState* state) } } +broker::expected TelemetryVal::DoSerialize() const + { + return broker::make_error(broker::ec::invalid_data, + "cannot serialize metric handles"); + } + +bool TelemetryVal::DoUnserialize(const broker::data&) + { + return false; + } + +TelemetryVal::TelemetryVal(telemetry::IntCounter) :OpaqueVal(int_counter_metric_type) + { + } + +TelemetryVal::TelemetryVal(telemetry::IntCounterFamily) :OpaqueVal(int_counter_metric_family_type) + { + } + +TelemetryVal::TelemetryVal(telemetry::DblCounter) :OpaqueVal(dbl_counter_metric_type) + { + } + +TelemetryVal::TelemetryVal(telemetry::DblCounterFamily) :OpaqueVal(dbl_counter_metric_family_type) + { + } + +TelemetryVal::TelemetryVal(telemetry::IntGauge) :OpaqueVal(int_gauge_metric_type) + { + } + +TelemetryVal::TelemetryVal(telemetry::IntGaugeFamily) :OpaqueVal(int_gauge_metric_family_type) + { + } + +TelemetryVal::TelemetryVal(telemetry::DblGauge) :OpaqueVal(dbl_gauge_metric_type) + { + } + +TelemetryVal::TelemetryVal(telemetry::DblGaugeFamily) :OpaqueVal(dbl_gauge_metric_family_type) + { + } + +TelemetryVal::TelemetryVal(telemetry::IntHistogram) :OpaqueVal(int_histogram_metric_type) + { + } + +TelemetryVal::TelemetryVal(telemetry::IntHistogramFamily) :OpaqueVal(int_histogram_metric_family_type) + { + } + +TelemetryVal::TelemetryVal(telemetry::DblHistogram) :OpaqueVal(dbl_histogram_metric_type) + { + } + +TelemetryVal::TelemetryVal(telemetry::DblHistogramFamily) :OpaqueVal(dbl_histogram_metric_family_type) + { + } + } diff --git a/src/OpaqueVal.h b/src/OpaqueVal.h index 1898618c25..3aef775712 100644 --- a/src/OpaqueVal.h +++ b/src/OpaqueVal.h @@ -10,6 +10,9 @@ #include "zeek/RandTest.h" #include "zeek/Val.h" #include "zeek/digest.h" +#include "zeek/telemetry/Counter.h" +#include "zeek/telemetry/Gauge.h" +#include "zeek/telemetry/Histogram.h" namespace broker { class data; } @@ -373,4 +376,66 @@ private: std::unique_ptr internal_paraglob; }; +/** + * Base class for metric handles. Handle types are not serializable. + */ +class TelemetryVal : public OpaqueVal { +protected: + explicit TelemetryVal(telemetry::IntCounter); + explicit TelemetryVal(telemetry::IntCounterFamily); + explicit TelemetryVal(telemetry::DblCounter); + explicit TelemetryVal(telemetry::DblCounterFamily); + explicit TelemetryVal(telemetry::IntGauge); + explicit TelemetryVal(telemetry::IntGaugeFamily); + explicit TelemetryVal(telemetry::DblGauge); + explicit TelemetryVal(telemetry::DblGaugeFamily); + explicit TelemetryVal(telemetry::IntHistogram); + explicit TelemetryVal(telemetry::IntHistogramFamily); + explicit TelemetryVal(telemetry::DblHistogram); + explicit TelemetryVal(telemetry::DblHistogramFamily); + + broker::expected DoSerialize() const override; + bool DoUnserialize(const broker::data& data) override; +}; + +template +class TelemetryValImpl : public TelemetryVal { +public: + using HandleType = Handle; + + explicit TelemetryValImpl(Handle hdl) : TelemetryVal(hdl), hdl(hdl) { } + + Handle GetHandle() const noexcept + { + return hdl; + } + +protected: + ValPtr DoClone(CloneState*) override + { + return make_intrusive(hdl); + } + + const char* OpaqueName() const override + { + return Handle::OpaqueName; + } + +private: + Handle hdl; +}; + +using IntCounterMetricVal = TelemetryValImpl; +using IntCounterMetricFamilyVal = TelemetryValImpl; +using DblCounterMetricVal = TelemetryValImpl; +using DblCounterMetricFamilyVal = TelemetryValImpl; +using IntGaugeMetricVal = TelemetryValImpl; +using IntGaugeMetricFamilyVal = TelemetryValImpl; +using DblGaugeMetricVal = TelemetryValImpl; +using DblGaugeMetricFamilyVal = TelemetryValImpl; +using IntHistogramMetricVal = TelemetryValImpl; +using IntHistogramMetricFamilyVal = TelemetryValImpl; +using DblHistogramMetricVal = TelemetryValImpl; +using DblHistogramMetricFamilyVal = TelemetryValImpl; + } // namespace zeek diff --git a/src/Type.h b/src/Type.h index 5a16463263..b1648e2714 100644 --- a/src/Type.h +++ b/src/Type.h @@ -913,3 +913,15 @@ extern zeek::OpaqueTypePtr bloomfilter_type; extern zeek::OpaqueTypePtr x509_opaque_type; extern zeek::OpaqueTypePtr ocsp_resp_opaque_type; extern zeek::OpaqueTypePtr paraglob_type; +extern zeek::OpaqueTypePtr int_counter_metric_type; +extern zeek::OpaqueTypePtr int_counter_metric_family_type; +extern zeek::OpaqueTypePtr dbl_counter_metric_type; +extern zeek::OpaqueTypePtr dbl_counter_metric_family_type; +extern zeek::OpaqueTypePtr int_gauge_metric_type; +extern zeek::OpaqueTypePtr int_gauge_metric_family_type; +extern zeek::OpaqueTypePtr dbl_gauge_metric_type; +extern zeek::OpaqueTypePtr dbl_gauge_metric_family_type; +extern zeek::OpaqueTypePtr int_histogram_metric_type; +extern zeek::OpaqueTypePtr int_histogram_metric_family_type; +extern zeek::OpaqueTypePtr dbl_histogram_metric_type; +extern zeek::OpaqueTypePtr dbl_histogram_metric_family_type; diff --git a/src/broker/Manager.cc b/src/broker/Manager.cc index 41f2282ab7..8128dcf8b7 100644 --- a/src/broker/Manager.cc +++ b/src/broker/Manager.cc @@ -1815,23 +1815,45 @@ std::unique_ptr Manager::NewTelemetryManager() // owns the CAF actor system, lives for as long as necessary. This also // makes sure that the Broker Manager may even get destroyed before the // telemetry Manager. - struct TM : public telemetry::Manager + struct TM final : public telemetry::Manager { + using MetricRegistryPtr = std::unique_ptr; + static auto getPimpl(BrokerState& st) { auto registry = std::addressof(st.endpoint.system().metrics()); return reinterpret_cast(registry); } - explicit TM(const std::shared_ptr& bsptr) - : telemetry::Manager(getPimpl(*bsptr)), ptr(bsptr) + static auto getPimpl(MetricRegistryPtr& ptr) { + return reinterpret_cast(ptr.get()); } + explicit TM(Broker::Manager* parent, MetricRegistryPtr ptr) + : telemetry::Manager(getPimpl(ptr)), parent(parent), tmp(std::move(ptr)) + { + assert(tmp != nullptr); + assert(parent != nullptr); + } + + void InitPostScript() override + { + assert(parent->bstate != nullptr); + ptr = parent->bstate; + auto registry = std::addressof(ptr->endpoint.system().metrics()); + registry->merge(*tmp); + tmp.reset(); + pimpl = reinterpret_cast(registry); + } + + Broker::Manager* parent; + MetricRegistryPtr tmp; std::shared_ptr ptr; }; - return std::make_unique(bstate); + auto tmp = std::make_unique(); + return std::make_unique(this, std::move(tmp)); } } // namespace zeek::Broker diff --git a/src/telemetry/CMakeLists.txt b/src/telemetry/CMakeLists.txt index 14b59d3c36..c0c2153387 100644 --- a/src/telemetry/CMakeLists.txt +++ b/src/telemetry/CMakeLists.txt @@ -13,10 +13,7 @@ set(telemetry_SRCS MetricFamily.cc ) -# bif_target(comm.bif) -# bif_target(data.bif) -# bif_target(messaging.bif) -# bif_target(store.bif) +bif_target(telemetry.bif) bro_add_subdir_library(telemetry ${telemetry_SRCS}) diff --git a/src/telemetry/Counter.h b/src/telemetry/Counter.h index 885a0f20f3..78be178efb 100644 --- a/src/telemetry/Counter.h +++ b/src/telemetry/Counter.h @@ -24,6 +24,8 @@ public: struct Impl; + static inline const char* OpaqueName = "IntCounterMetricVal"; + IntCounter() = delete; IntCounter(const IntCounter&) noexcept = default; IntCounter& operator=(const IntCounter&) noexcept = default; @@ -91,6 +93,8 @@ public: class Impl; + static inline const char* OpaqueName = "IntCounterMetricFamilyVal"; + using InstanceType = IntCounter; IntCounterFamily(const IntCounterFamily&) noexcept = default; @@ -124,6 +128,8 @@ public: struct Impl; + static inline const char* OpaqueName = "DblCounterMetricVal"; + DblCounter() = delete; DblCounter(const DblCounter&) noexcept = default; DblCounter& operator=(const DblCounter&) noexcept = default; @@ -185,6 +191,8 @@ public: class Impl; + static inline const char* OpaqueName = "DblCounterMetricFamilyVal"; + using InstanceType = DblCounter; DblCounterFamily(const DblCounterFamily&) noexcept = default; diff --git a/src/telemetry/Gauge.h b/src/telemetry/Gauge.h index 25ba22ee0b..0eda5dbf8d 100644 --- a/src/telemetry/Gauge.h +++ b/src/telemetry/Gauge.h @@ -25,6 +25,8 @@ public: struct Impl; + static inline const char* OpaqueName = "IntGaugeMetricVal"; + IntGauge() = delete; IntGauge(const IntGauge&) noexcept = default; IntGauge& operator=(const IntGauge&) noexcept = default; @@ -107,6 +109,8 @@ public: class Impl; + static inline const char* OpaqueName = "IntGaugeMetricFamilyVal"; + using InstanceType = IntGauge; IntGaugeFamily(const IntGaugeFamily&) noexcept = default; @@ -141,6 +145,8 @@ public: struct Impl; + static inline const char* OpaqueName = "DblGaugeMetricVal"; + DblGauge() = delete; DblGauge(const DblGauge&) noexcept = default; DblGauge& operator=(const DblGauge&) noexcept = default; @@ -211,6 +217,8 @@ public: class Impl; + static inline const char* OpaqueName = "DblGaugeMetricFamilyVal"; + using InstanceType = DblGauge; DblGaugeFamily(const DblGaugeFamily&) noexcept = default; diff --git a/src/telemetry/Histogram.h b/src/telemetry/Histogram.h index 93a0189e18..68f7781c3e 100644 --- a/src/telemetry/Histogram.h +++ b/src/telemetry/Histogram.h @@ -26,6 +26,8 @@ public: struct Impl; + static inline const char* OpaqueName = "IntHistogramMetricVal"; + IntHistogram() = delete; IntHistogram(const IntHistogram&) noexcept = default; IntHistogram& operator=(const IntHistogram&) noexcept = default; @@ -90,6 +92,8 @@ public: class Impl; + static inline const char* OpaqueName = "IntHistogramMetricFamilyVal"; + using InstanceType = IntHistogram; IntHistogramFamily(const IntHistogramFamily&) noexcept = default; @@ -124,6 +128,8 @@ public: struct Impl; + static inline const char* OpaqueName = "DblHistogramMetricVal"; + DblHistogram() = delete; DblHistogram(const DblHistogram&) noexcept = default; DblHistogram& operator=(const DblHistogram&) noexcept = default; @@ -188,6 +194,8 @@ public: class Impl; + static inline const char* OpaqueName = "DblHistogramMetricFamilyVal"; + using InstanceType = DblHistogram; DblHistogramFamily(const DblHistogramFamily&) noexcept = default; diff --git a/src/telemetry/Manager.cc b/src/telemetry/Manager.cc index 3670cd9cdf..f8cd56d8f2 100644 --- a/src/telemetry/Manager.cc +++ b/src/telemetry/Manager.cc @@ -14,6 +14,10 @@ Manager::~Manager() { } +void Manager::InitPostScript() + { + } + IntCounterFamily Manager::IntCounterFam(std::string_view prefix, std::string_view name, Span labels, diff --git a/src/telemetry/Manager.h b/src/telemetry/Manager.h index 9c8aa08427..9fa478e845 100644 --- a/src/telemetry/Manager.h +++ b/src/telemetry/Manager.h @@ -31,6 +31,12 @@ public: virtual ~Manager(); + /** + * Initialization of the manager. This is called late during Bro's + * initialization after any scripts are processed. + */ + virtual void InitPostScript(); + /** * @return A counter metric family. Creates the family lazily if necessary. * @param prefix The prefix (namespace) this family belongs to. @@ -384,7 +390,7 @@ public: return fam.GetOrAdd({}); } -private: +protected: IntCounterFamily IntCounterFam(std::string_view prefix, std::string_view name, Span labels, diff --git a/src/telemetry/telemetry.bif b/src/telemetry/telemetry.bif new file mode 100644 index 0000000000..3479881295 --- /dev/null +++ b/src/telemetry/telemetry.bif @@ -0,0 +1,550 @@ + +##! Functions for accessing counter metrics from script land. + +module Telemetry; + +%%{ +#include "zeek/telemetry/Counter.h" +#include "zeek/telemetry/Gauge.h" +#include "zeek/telemetry/Histogram.h" +#include "zeek/telemetry/Manager.h" + +namespace { + +template +auto with(zeek::Val* val, const char* error_msg, Fun fun) + { + if ( auto ptr = dynamic_cast(val) ) + { + fun(ptr->GetHandle()); + return zeek::val_mgr->True(); + } + else + { + zeek::reporter->Error("%s", error_msg); + return zeek::val_mgr->False(); + } + } + +std::string_view sv(const zeek::String* str) noexcept + { + auto len = static_cast(str->Len()); + return {reinterpret_cast(str->Bytes()), len}; + }; + +std::string_view sv(const zeek::StringVal* val) noexcept + { + return sv(val->AsString()); + }; + +std::vector sv_vec(zeek::VectorVal* xs) + { + std::vector result; + if ( xs ) + for ( unsigned index = 0; index < xs->Size(); ++index ) + if ( auto& ptr = xs->At(index) ) + if ( auto* str = ptr->AsString() ) + result.emplace_back(sv(str)); + return result; + } + +std::vector sv_tbl(zeek::TableVal* xs) + { + std::vector result; + if ( xs ) + { + for ( auto& val : *xs->Get() ) + { + auto val_ptr = val.GetValue()->GetVal(); + result.emplace_back(std::string_view{val.GetKey(), val.key_size}, + sv(val_ptr->AsStringVal())); + } + } + return result; + } + +bool is_valid(zeek::Span labels, + zeek::Span label_names) + { + auto key_in_label_names = [keys{label_names}](auto x) + { + return std::find(keys.begin(), keys.end(), x.first) != keys.end(); + }; + return labels.size() == label_names.size() + && std::all_of(labels.begin(), labels.end(), key_in_label_names); + } + +template +auto to_std_vec(zeek::VectorVal* xs) + { + std::vector result; + if( xs ) + for ( unsigned index = 0; index < xs->Size() ; ++index ) + { + if constexpr (std::is_same::value) + result.emplace_back(xs->At(index)->AsInt()); + else + result.emplace_back(xs->At(index)->AsDouble()); + } + return result; + } + +template +auto to_std_vec(zeek::Val* xs) + { + return to_std_vec(xs->AsVectorVal()); + } + +} +%%} + +# -- IntCounter ---------------------------------------------------------------- + +function Telemetry::int_counter_family%(prefix: string, + name: string, + labels: string_vec, + helptext: string &default = "Zeek Script Metric", + unit: string &default = "1", + is_sum: bool &default = F%): opaque of int_counter_metric_family + %{ + auto lbl_vec = sv_vec(labels->AsVectorVal()); + auto hdl = telemetry_mgr->CounterFamily(sv(prefix), sv(name), lbl_vec, + sv(helptext), sv(unit), is_sum); + return zeek::make_intrusive(hdl); + %} + +function Telemetry::int_counter_metric_get_or_add%(family: opaque of int_counter_metric_family, + labels: table_string_of_string%): opaque of int_counter_metric + %{ + using ResultType = zeek::IntrusivePtr; + if ( auto ptr = dynamic_cast(family) ) + { + auto hdl = ptr->GetHandle(); + auto lbl_map = sv_tbl(labels->AsTableVal()); + if ( is_valid(lbl_map, hdl.LabelNames()) ) + { + auto res = hdl.GetOrAdd(lbl_map); + return zeek::make_intrusive(res); + } + else + { + zeek::reporter->Error("Telemetry::int_counter_metric_get_or_add: invalid label dimensions."); + return ResultType{nullptr}; + } + } + else + { + zeek::reporter->Error("Telemetry::int_counter_metric_get_or_add: invalid handle."); + return ResultType{nullptr}; + } + %} + +function Telemetry::int_counter_singleton%(prefix: string, + name: string, + helptext: string &default = "Zeek Script Metric", + unit: string &default = "1", + is_sum: bool &default = F%): opaque of int_counter_metric + %{ + auto hdl = telemetry_mgr->CounterSingleton(sv(prefix), sv(name), + sv(helptext), sv(unit), is_sum); + return zeek::make_intrusive(hdl); + %} + +function Telemetry::int_counter_inc%(val: opaque of int_counter_metric, + amount: int &default = 1%): bool + %{ + return with(val, "Telemetry::int_counter_inc: invalid handle.", [amount](auto hdl) { hdl.Inc(amount); }); + %} + +function Telemetry::int_counter_value%(val: opaque of int_counter_metric%): int + %{ + if ( auto ptr = dynamic_cast(val) ) + { + return zeek::val_mgr->Int(ptr->GetHandle().Value()); + } + else + { + zeek::reporter->Error("Telemetry::int_counter_value: invalid handle."); + return zeek::val_mgr->Int(0); + } + %} + +# -- DblCounter ---------------------------------------------------------------- + +function Telemetry::dbl_counter_family%(prefix: string, + name: string, + labels: string_vec, + helptext: string &default = "Zeek Script Metric", + unit: string &default = "1", + is_sum: bool &default = F%): opaque of dbl_counter_metric_family + %{ + auto lbl_vec = sv_vec(labels->AsVectorVal()); + auto hdl = telemetry_mgr->CounterFamily(sv(prefix), sv(name), lbl_vec, + sv(helptext), sv(unit), is_sum); + return zeek::make_intrusive(hdl); + %} + +function Telemetry::dbl_counter_metric_get_or_add%(family: opaque of dbl_counter_metric_family, + labels: table_string_of_string%): opaque of dbl_counter_metric + %{ + using ResultType = zeek::IntrusivePtr; + if ( auto ptr = dynamic_cast(family) ) + { + auto hdl = ptr->GetHandle(); + auto lbl_map = sv_tbl(labels->AsTableVal()); + if ( is_valid(lbl_map, hdl.LabelNames()) ) + { + auto res = hdl.GetOrAdd(lbl_map); + return zeek::make_intrusive(res); + } + else + { + zeek::reporter->Error("Telemetry::dbl_counter_metric_get_or_add: invalid label dimensions."); + return ResultType{nullptr}; + } + } + else + { + zeek::reporter->Error("Telemetry::dbl_counter_metric_get_or_add: invalid handle."); + return ResultType{nullptr}; + } + %} + +function Telemetry::dbl_counter_singleton%(prefix: string, + name: string, + helptext: string &default = "Zeek Script Metric", + unit: string &default = "1", + is_sum: bool &default = F%): opaque of dbl_counter_metric + %{ + auto hdl = telemetry_mgr->CounterSingleton(sv(prefix), sv(name), + sv(helptext), sv(unit), is_sum); + return zeek::make_intrusive(hdl); + %} + +function Telemetry::dbl_counter_inc%(val: opaque of dbl_counter_metric, + amount: double &default = 1.0%): bool + %{ + return with(val, "Telemetry::dbl_counter_inc: invalid handle.", [amount](auto hdl) { hdl.Inc(amount); }); + %} + +function Telemetry::dbl_counter_value%(val: opaque of dbl_counter_metric%): double + %{ + if ( auto ptr = dynamic_cast(val) ) + { + return zeek::make_intrusive(ptr->GetHandle().Value()); + } + else + { + zeek::reporter->Error("Telemetry::dbl_counter_value: invalid handle."); + return zeek::make_intrusive(0.0); + } + %} + +# -- IntGauge ------------------------------------------------------------------ + +function Telemetry::int_gauge_family%(prefix: string, + name: string, + labels: string_vec, + helptext: string &default = "Zeek Script Metric", + unit: string &default = "1", + is_sum: bool &default = F%): opaque of int_gauge_metric_family + %{ + auto lbl_vec = sv_vec(labels->AsVectorVal()); + auto hdl = telemetry_mgr->GaugeFamily(sv(prefix), sv(name), lbl_vec, + sv(helptext), sv(unit), is_sum); + return zeek::make_intrusive(hdl); + %} + +function Telemetry::int_gauge_metric_get_or_add%(family: opaque of int_gauge_metric_family, + labels: table_string_of_string%): opaque of int_gauge_metric + %{ + using ResultType = zeek::IntrusivePtr; + if ( auto ptr = dynamic_cast(family) ) + { + auto hdl = ptr->GetHandle(); + auto lbl_map = sv_tbl(labels->AsTableVal()); + if ( is_valid(lbl_map, hdl.LabelNames()) ) + { + auto res = hdl.GetOrAdd(lbl_map); + return zeek::make_intrusive(res); + } + else + { + zeek::reporter->Error("Telemetry::int_gauge_metric_get_or_add: invalid label dimensions."); + return ResultType{nullptr}; + } + } + else + { + zeek::reporter->Error("Telemetry::int_gauge_metric_get_or_add: invalid handle."); + return ResultType{nullptr}; + } + %} + +function Telemetry::int_gauge_singleton%(prefix: string, + name: string, + helptext: string &default = "Zeek Script Metric", + unit: string &default = "1", + is_sum: bool &default = F%): opaque of int_gauge_metric + %{ + auto hdl = telemetry_mgr->GaugeSingleton(sv(prefix), sv(name), + sv(helptext), sv(unit), is_sum); + return zeek::make_intrusive(hdl); + %} + +function Telemetry::int_gauge_inc%(val: opaque of int_gauge_metric, + amount: int &default = 1%): bool + %{ + return with(val, "Telemetry::int_gauge_inc: invalid handle.", [amount](auto hdl) { hdl.Inc(amount); }); + %} + +function Telemetry::int_gauge_dec%(val: opaque of int_gauge_metric, + amount: int &default = 1%): bool + %{ + return with(val, "Telemetry::int_gauge_dec: invalid handle.", [amount](auto hdl) { hdl.Dec(amount); }); + %} + +function Telemetry::int_gauge_value%(val: opaque of int_gauge_metric%): int + %{ + if ( auto ptr = dynamic_cast(val) ) + { + return zeek::val_mgr->Int(ptr->GetHandle().Value()); + } + else + { + zeek::reporter->Error("Telemetry::int_gauge_value: invalid handle."); + return zeek::val_mgr->Int(0); + } + %} + +# -- DblGauge ------------------------------------------------------------------ + +function Telemetry::dbl_gauge_family%(prefix: string, + name: string, + labels: string_vec, + helptext: string &default = "Zeek Script Metric", + unit: string &default = "1", + is_sum: bool &default = F%): opaque of dbl_gauge_metric_family + %{ + auto lbl_vec = sv_vec(labels->AsVectorVal()); + auto hdl = telemetry_mgr->GaugeFamily(sv(prefix), sv(name), lbl_vec, + sv(helptext), sv(unit), is_sum); + return zeek::make_intrusive(hdl); + %} + +function Telemetry::dbl_gauge_metric_get_or_add%(family: opaque of dbl_gauge_metric_family, + labels: table_string_of_string%): opaque of dbl_gauge_metric + %{ + using ResultType = zeek::IntrusivePtr; + if ( auto ptr = dynamic_cast(family) ) + { + auto hdl = ptr->GetHandle(); + auto lbl_map = sv_tbl(labels->AsTableVal()); + if ( is_valid(lbl_map, hdl.LabelNames()) ) + { + auto res = hdl.GetOrAdd(lbl_map); + return zeek::make_intrusive(res); + } + else + { + zeek::reporter->Error("Telemetry::dbl_gauge_metric_get_or_add: invalid label dimensions."); + return ResultType{nullptr}; + } + } + else + { + zeek::reporter->Error("Telemetry::dbl_gauge_metric_get_or_add: invalid handle."); + return ResultType{nullptr}; + } + %} + +function Telemetry::dbl_gauge_singleton%(prefix: string, + name: string, + helptext: string &default = "Zeek Script Metric", + unit: string &default = "1", + is_sum: bool &default = F%): opaque of dbl_gauge_metric + %{ + auto hdl = telemetry_mgr->GaugeSingleton(sv(prefix), sv(name), + sv(helptext), sv(unit), is_sum); + return zeek::make_intrusive(hdl); + %} + +function Telemetry::dbl_gauge_inc%(val: opaque of dbl_gauge_metric, + amount: double &default = 1.0%): bool + %{ + return with(val, "Telemetry::dbl_gauge_inc: invalid handle.", [amount](auto hdl) { hdl.Inc(amount); }); + %} + +function Telemetry::dbl_gauge_dec%(val: opaque of dbl_gauge_metric, + amount: double &default = 1.0%): bool + %{ + return with(val, "Telemetry::dbl_gauge_dec: invalid handle.", [amount](auto hdl) { hdl.Dec(amount); }); + %} + +function Telemetry::dbl_gauge_value%(val: opaque of dbl_gauge_metric%): double + %{ + if ( auto ptr = dynamic_cast(val) ) + { + return zeek::make_intrusive(ptr->GetHandle().Value()); + } + else + { + zeek::reporter->Error("Telemetry::dbl_gauge_value: invalid handle."); + return zeek::make_intrusive(0.0); + } + %} + +# -- IntHistogram -------------------------------------------------------------- + +function Telemetry::int_histogram_family%(prefix: string, + name: string, + labels: string_vec, + bounds: int_vec, + helptext: string &default = "Zeek Script Metric", + unit: string &default = "1", + is_sum: bool &default = F%): opaque of int_histogram_metric_family + %{ + auto lbl_vec = sv_vec(labels->AsVectorVal()); + auto std_bounds = to_std_vec(bounds); + auto hdl = telemetry_mgr->HistogramFamily(sv(prefix), sv(name), lbl_vec, + std_bounds, sv(helptext), + sv(unit), is_sum); + return zeek::make_intrusive(hdl); + %} + +function Telemetry::int_histogram_metric_get_or_add%(family: opaque of int_histogram_metric_family, + labels: table_string_of_string%): opaque of int_histogram_metric + %{ + using ResultType = zeek::IntrusivePtr; + if ( auto ptr = dynamic_cast(family) ) + { + auto hdl = ptr->GetHandle(); + auto lbl_map = sv_tbl(labels->AsTableVal()); + if ( is_valid(lbl_map, hdl.LabelNames()) ) + { + auto res = hdl.GetOrAdd(lbl_map); + return zeek::make_intrusive(res); + } + else + { + zeek::reporter->Error("Telemetry::int_histogram_metric_get_or_add: invalid label dimensions."); + return ResultType{nullptr}; + } + } + else + { + zeek::reporter->Error("Telemetry::int_histogram_metric_get_or_add: invalid handle."); + return ResultType{nullptr}; + } + %} + +function Telemetry::int_histogram_singleton%(prefix: string, + name: string, + bounds: int_vec, + helptext: string &default = "Zeek Script Metric", + unit: string &default = "1", + is_sum: bool &default = F%): opaque of int_histogram_metric + %{ + auto std_bounds = to_std_vec(bounds); + auto hdl = telemetry_mgr->HistogramSingleton(sv(prefix), sv(name), + std_bounds, sv(helptext), + sv(unit), is_sum); + return zeek::make_intrusive(hdl); + %} + +function Telemetry::int_histogram_observe%(val: opaque of int_histogram_metric, + measurement: int%): bool + %{ + return with(val, "Telemetry::int_histogram_inc: invalid handle.", [measurement](auto hdl) { hdl.Observe(measurement); }); + %} + +function Telemetry::int_histogram_sum%(val: opaque of int_histogram_metric%): int + %{ + if ( auto ptr = dynamic_cast(val) ) + { + return zeek::val_mgr->Int(ptr->GetHandle().Sum()); + } + else + { + zeek::reporter->Error("Telemetry::int_histogram_sum: invalid handle."); + return zeek::val_mgr->Int(0); + } + %} + +# -- DblHistogram -------------------------------------------------------------- + +function Telemetry::dbl_histogram_family%(prefix: string, + name: string, + labels: string_vec, + bounds: double_vec, + helptext: string &default = "Zeek Script Metric", + unit: string &default = "1", + is_sum: bool &default = F%): opaque of dbl_histogram_metric_family + %{ + auto lbl_vec = sv_vec(labels->AsVectorVal()); + auto std_bounds = to_std_vec(bounds); + auto hdl = telemetry_mgr->HistogramFamily(sv(prefix), sv(name), + lbl_vec, std_bounds, + sv(helptext), sv(unit), + is_sum); + return zeek::make_intrusive(hdl); + %} + +function Telemetry::dbl_histogram_metric_get_or_add%(family: opaque of dbl_histogram_metric_family, + labels: table_string_of_string%): opaque of dbl_histogram_metric + %{ + using ResultType = zeek::IntrusivePtr; + if ( auto ptr = dynamic_cast(family) ) + { + auto hdl = ptr->GetHandle(); + auto lbl_map = sv_tbl(labels->AsTableVal()); + if ( is_valid(lbl_map, hdl.LabelNames()) ) + { + auto res = hdl.GetOrAdd(lbl_map); + return zeek::make_intrusive(res); + } + else + { + zeek::reporter->Error("Telemetry::dbl_histogram_metric_get_or_add: invalid label dimensions."); + return ResultType{nullptr}; + } + } + else + { + zeek::reporter->Error("Telemetry::dbl_histogram_metric_get_or_add: invalid handle."); + return ResultType{nullptr}; + } + %} + +function Telemetry::dbl_histogram_singleton%(prefix: string, + name: string, + bounds: double_vec, + helptext: string &default = "Zeek Script Metric", + unit: string &default = "1", + is_sum: bool &default = F%): opaque of dbl_histogram_metric + %{ + auto std_bounds = to_std_vec(bounds); + auto hdl = telemetry_mgr->HistogramSingleton(sv(prefix), sv(name), + std_bounds, sv(helptext), + sv(unit), is_sum); + return zeek::make_intrusive(hdl); + %} + +function Telemetry::dbl_histogram_observe%(val: opaque of dbl_histogram_metric, + measurement: double%): bool + %{ + return with(val, "Telemetry::dbl_histogram_inc: invalid handle.", [measurement](auto hdl) { hdl.Observe(measurement); }); + %} + +function Telemetry::dbl_histogram_sum%(val: opaque of dbl_histogram_metric%): double + %{ + if ( auto ptr = dynamic_cast(val) ) + { + return zeek::make_intrusive(ptr->GetHandle().Sum()); + } + else + { + zeek::reporter->Error("Telemetry::dbl_histogram_sum: invalid handle."); + return zeek::make_intrusive(0.0); + } + %} diff --git a/src/zeek-setup.cc b/src/zeek-setup.cc index f01294b00f..652da4c4f0 100644 --- a/src/zeek-setup.cc +++ b/src/zeek-setup.cc @@ -138,6 +138,18 @@ zeek::OpaqueTypePtr bloomfilter_type; zeek::OpaqueTypePtr x509_opaque_type; zeek::OpaqueTypePtr ocsp_resp_opaque_type; zeek::OpaqueTypePtr paraglob_type; +zeek::OpaqueTypePtr int_counter_metric_type; +zeek::OpaqueTypePtr int_counter_metric_family_type; +zeek::OpaqueTypePtr dbl_counter_metric_type; +zeek::OpaqueTypePtr dbl_counter_metric_family_type; +zeek::OpaqueTypePtr int_gauge_metric_type; +zeek::OpaqueTypePtr int_gauge_metric_family_type; +zeek::OpaqueTypePtr dbl_gauge_metric_type; +zeek::OpaqueTypePtr dbl_gauge_metric_family_type; +zeek::OpaqueTypePtr int_histogram_metric_type; +zeek::OpaqueTypePtr int_histogram_metric_family_type; +zeek::OpaqueTypePtr dbl_histogram_metric_type; +zeek::OpaqueTypePtr dbl_histogram_metric_family_type; // Keep copy of command line int zeek::detail::zeek_argc; @@ -604,6 +616,18 @@ SetupResult setup(int argc, char** argv, Options* zopts) x509_opaque_type = make_intrusive("x509"); ocsp_resp_opaque_type = make_intrusive("ocsp_resp"); paraglob_type = make_intrusive("paraglob"); + int_counter_metric_type = make_intrusive("int_counter_metric"); + int_counter_metric_family_type = make_intrusive("int_counter_metric_family"); + dbl_counter_metric_type = make_intrusive("dbl_counter_metric"); + dbl_counter_metric_family_type = make_intrusive("dbl_counter_metric_family"); + int_gauge_metric_type = make_intrusive("int_gauge_metric"); + int_gauge_metric_family_type = make_intrusive("int_gauge_metric_family"); + dbl_gauge_metric_type = make_intrusive("dbl_gauge_metric"); + dbl_gauge_metric_family_type = make_intrusive("dbl_gauge_metric_family"); + int_histogram_metric_type = make_intrusive("int_histogram_metric"); + int_histogram_metric_family_type = make_intrusive("int_histogram_metric_family"); + dbl_histogram_metric_type = make_intrusive("dbl_histogram_metric"); + dbl_histogram_metric_family_type = make_intrusive("dbl_histogram_metric_family"); // The leak-checker tends to produce some false // positives (memory which had already been @@ -671,6 +695,7 @@ SetupResult setup(int argc, char** argv, Options* zopts) plugin_mgr->InitPostScript(); zeekygen_mgr->InitPostScript(); broker_mgr->InitPostScript(); + telemetry_mgr->InitPostScript(); timer_mgr->InitPostScript(); event_mgr.InitPostScript(); diff --git a/testing/btest/Baseline/telemetry.counter/output b/testing/btest/Baseline/telemetry.counter/output new file mode 100644 index 0000000000..72ca34c137 --- /dev/null +++ b/testing/btest/Baseline/telemetry.counter/output @@ -0,0 +1,5 @@ +### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63. +cnt1_bar: 1 +cnt2_bar: 42 +cnt3_bar: 1.000000 +cnt4_bar: 42.000000 diff --git a/testing/btest/Baseline/telemetry.gauge/output b/testing/btest/Baseline/telemetry.gauge/output new file mode 100644 index 0000000000..add597e534 --- /dev/null +++ b/testing/btest/Baseline/telemetry.gauge/output @@ -0,0 +1,5 @@ +### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63. +gg1_bar: 1 +gg2_bar: 23 +gg3_bar: 1.000000 +gg4_bar: 23.000000 diff --git a/testing/btest/Baseline/telemetry.histogram/output b/testing/btest/Baseline/telemetry.histogram/output new file mode 100644 index 0000000000..59a5447d15 --- /dev/null +++ b/testing/btest/Baseline/telemetry.histogram/output @@ -0,0 +1,5 @@ +### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63. +hst1_bar: 12 +hst2_bar: 31337 +hst3_bar: 6.000000 +hst4_bar: 64.000000 diff --git a/testing/btest/btest.cfg b/testing/btest/btest.cfg index 12c5b9bd4d..48f2aaf929 100644 --- a/testing/btest/btest.cfg +++ b/testing/btest/btest.cfg @@ -1,5 +1,5 @@ [btest] -TestDirs = doc bifs language core scripts coverage signatures plugins broker supervisor +TestDirs = doc bifs language core scripts coverage signatures plugins broker supervisor telemetry TmpDir = %(testbase)s/.tmp BaselineDir = %(testbase)s/Baseline IgnoreDirs = .svn CVS .tmp diff --git a/testing/btest/telemetry/counter.zeek b/testing/btest/telemetry/counter.zeek new file mode 100644 index 0000000000..937c6760a5 --- /dev/null +++ b/testing/btest/telemetry/counter.zeek @@ -0,0 +1,25 @@ +# @TEST-GROUP: Telemetry + +# @TEST-EXEC: zeek -b %INPUT >output +# @TEST-EXEC: btest-diff output + +global cnt1 = Telemetry::int_counter_family("cnt1", "bar", vector("dim1", "dim2")); +global cnt2_bar = Telemetry::int_counter_singleton("cnt2", "bar"); +global cnt3 = Telemetry::dbl_counter_family("cnt3", "bar", vector("dim1", "dim2")); +global cnt4_bar = Telemetry::dbl_counter_singleton("cnt4", "bar"); + +event zeek_init() + { + local cnt1_bar = Telemetry::int_counter_metric_get_or_add(cnt1, table(["dim1"] = "val1", ["dim2"] = "val2")); + Telemetry::int_counter_inc(cnt1_bar); + Telemetry::int_counter_inc(cnt2_bar); + Telemetry::int_counter_inc(cnt2_bar, 41); + print fmt("cnt1_bar: %d", Telemetry::int_counter_value(cnt1_bar)); + print fmt("cnt2_bar: %d", Telemetry::int_counter_value(cnt2_bar)); + local cnt3_bar = Telemetry::dbl_counter_metric_get_or_add(cnt3, table(["dim1"] = "val1", ["dim2"] = "val2")); + Telemetry::dbl_counter_inc(cnt3_bar); + Telemetry::dbl_counter_inc(cnt4_bar); + Telemetry::dbl_counter_inc(cnt4_bar, 41.0); + print fmt("cnt3_bar: %f", Telemetry::dbl_counter_value(cnt3_bar)); + print fmt("cnt4_bar: %f", Telemetry::dbl_counter_value(cnt4_bar)); + } diff --git a/testing/btest/telemetry/gauge.zeek b/testing/btest/telemetry/gauge.zeek new file mode 100644 index 0000000000..812ef0b524 --- /dev/null +++ b/testing/btest/telemetry/gauge.zeek @@ -0,0 +1,30 @@ +# @TEST-GROUP: Telemetry + +# @TEST-EXEC: zeek -b %INPUT >output +# @TEST-EXEC: btest-diff output + +global gg1 = Telemetry::int_gauge_family("gg1", "bar", vector("dim1", "dim2")); +global gg2_bar = Telemetry::int_gauge_singleton("gg2", "bar"); +global gg3 = Telemetry::dbl_gauge_family("gg3", "bar", vector("dim1", "dim2")); +global gg4_bar = Telemetry::dbl_gauge_singleton("gg4", "bar"); + +event zeek_init() + { + local gg1_bar = Telemetry::int_gauge_metric_get_or_add(gg1, table(["dim1"] = "val1", ["dim2"] = "val2")); + Telemetry::int_gauge_inc(gg1_bar); + Telemetry::int_gauge_inc(gg2_bar); + Telemetry::int_gauge_inc(gg2_bar, 41); + Telemetry::int_gauge_dec(gg2_bar); + Telemetry::int_gauge_dec(gg2_bar, 18); + print fmt("gg1_bar: %d", Telemetry::int_gauge_value(gg1_bar)); + print fmt("gg2_bar: %d", Telemetry::int_gauge_value(gg2_bar)); + local gg3_bar = Telemetry::dbl_gauge_metric_get_or_add(gg3, table(["dim1"] = "val1", ["dim2"] = "val2")); + Telemetry::dbl_gauge_inc(gg3_bar); + Telemetry::dbl_gauge_inc(gg4_bar); + Telemetry::dbl_gauge_inc(gg4_bar, 41.0); + Telemetry::dbl_gauge_dec(gg4_bar); + Telemetry::dbl_gauge_dec(gg4_bar, 18.0); + print fmt("gg3_bar: %f", Telemetry::dbl_gauge_value(gg3_bar)); + print fmt("gg4_bar: %f", Telemetry::dbl_gauge_value(gg4_bar)); + } + diff --git a/testing/btest/telemetry/histogram.zeek b/testing/btest/telemetry/histogram.zeek new file mode 100644 index 0000000000..2dc5a9e751 --- /dev/null +++ b/testing/btest/telemetry/histogram.zeek @@ -0,0 +1,28 @@ +# @TEST-GROUP: Telemetry + +# @TEST-EXEC: zeek -b %INPUT >output +# @TEST-EXEC: btest-diff output + +const int_bounds = vector(+10, +20); +const dbl_bounds = vector(10.0, 20.0); + +global hst1 = Telemetry::int_histogram_family("hst1", "bar", vector("dim1", "dim2"), int_bounds); +global hst2_bar = Telemetry::int_histogram_singleton("hst2", "bar", int_bounds); +global hst3 = Telemetry::dbl_histogram_family("hst3", "bar", vector("dim1", "dim2"), dbl_bounds); +global hst4_bar = Telemetry::dbl_histogram_singleton("hst4", "bar", dbl_bounds); + +event zeek_init() + { + local hst1_bar = Telemetry::int_histogram_metric_get_or_add(hst1, table(["dim1"] = "val1", ["dim2"] = "val2")); + Telemetry::int_histogram_observe(hst1_bar, 1); + Telemetry::int_histogram_observe(hst1_bar, 11); + Telemetry::int_histogram_observe(hst2_bar, 31337); + print fmt("hst1_bar: %d", Telemetry::int_histogram_sum(hst1_bar)); + print fmt("hst2_bar: %d", Telemetry::int_histogram_sum(hst2_bar)); + local hst3_bar = Telemetry::dbl_histogram_metric_get_or_add(hst3, table(["dim1"] = "val1", ["dim2"] = "val2")); + Telemetry::dbl_histogram_observe(hst3_bar, 2.0); + Telemetry::dbl_histogram_observe(hst3_bar, 4.0); + Telemetry::dbl_histogram_observe(hst4_bar, 64.0); + print fmt("hst3_bar: %f", Telemetry::dbl_histogram_sum(hst3_bar)); + print fmt("hst4_bar: %f", Telemetry::dbl_histogram_sum(hst4_bar)); + } From e476911075d2643844e714153339f698d5064fd8 Mon Sep 17 00:00:00 2001 From: Dominik Charousset Date: Thu, 11 Mar 2021 15:20:59 +0100 Subject: [PATCH 10/13] Prefix telemetry BIFs with __ --- src/telemetry/telemetry.bif | 208 ++++++++++++------------- testing/btest/telemetry/counter.zeek | 32 ++-- testing/btest/telemetry/gauge.zeek | 40 ++--- testing/btest/telemetry/histogram.zeek | 32 ++-- 4 files changed, 156 insertions(+), 156 deletions(-) diff --git a/src/telemetry/telemetry.bif b/src/telemetry/telemetry.bif index 3479881295..a4b7eea8d5 100644 --- a/src/telemetry/telemetry.bif +++ b/src/telemetry/telemetry.bif @@ -100,12 +100,12 @@ auto to_std_vec(zeek::Val* xs) # -- IntCounter ---------------------------------------------------------------- -function Telemetry::int_counter_family%(prefix: string, - name: string, - labels: string_vec, - helptext: string &default = "Zeek Script Metric", - unit: string &default = "1", - is_sum: bool &default = F%): opaque of int_counter_metric_family +function Telemetry::__int_counter_family%(prefix: string, + name: string, + labels: string_vec, + helptext: string &default = "Zeek Script Metric", + unit: string &default = "1", + is_sum: bool &default = F%): opaque of int_counter_metric_family %{ auto lbl_vec = sv_vec(labels->AsVectorVal()); auto hdl = telemetry_mgr->CounterFamily(sv(prefix), sv(name), lbl_vec, @@ -113,8 +113,8 @@ function Telemetry::int_counter_family%(prefix: string, return zeek::make_intrusive(hdl); %} -function Telemetry::int_counter_metric_get_or_add%(family: opaque of int_counter_metric_family, - labels: table_string_of_string%): opaque of int_counter_metric +function Telemetry::__int_counter_metric_get_or_add%(family: opaque of int_counter_metric_family, + labels: table_string_of_string%): opaque of int_counter_metric %{ using ResultType = zeek::IntrusivePtr; if ( auto ptr = dynamic_cast(family) ) @@ -139,24 +139,24 @@ function Telemetry::int_counter_metric_get_or_add%(family: opaque of int_counter } %} -function Telemetry::int_counter_singleton%(prefix: string, - name: string, - helptext: string &default = "Zeek Script Metric", - unit: string &default = "1", - is_sum: bool &default = F%): opaque of int_counter_metric +function Telemetry::__int_counter_singleton%(prefix: string, + name: string, + helptext: string &default = "Zeek Script Metric", + unit: string &default = "1", + is_sum: bool &default = F%): opaque of int_counter_metric %{ auto hdl = telemetry_mgr->CounterSingleton(sv(prefix), sv(name), sv(helptext), sv(unit), is_sum); return zeek::make_intrusive(hdl); %} -function Telemetry::int_counter_inc%(val: opaque of int_counter_metric, - amount: int &default = 1%): bool +function Telemetry::__int_counter_inc%(val: opaque of int_counter_metric, + amount: int &default = 1%): bool %{ return with(val, "Telemetry::int_counter_inc: invalid handle.", [amount](auto hdl) { hdl.Inc(amount); }); %} -function Telemetry::int_counter_value%(val: opaque of int_counter_metric%): int +function Telemetry::__int_counter_value%(val: opaque of int_counter_metric%): int %{ if ( auto ptr = dynamic_cast(val) ) { @@ -171,12 +171,12 @@ function Telemetry::int_counter_value%(val: opaque of int_counter_metric%): int # -- DblCounter ---------------------------------------------------------------- -function Telemetry::dbl_counter_family%(prefix: string, - name: string, - labels: string_vec, - helptext: string &default = "Zeek Script Metric", - unit: string &default = "1", - is_sum: bool &default = F%): opaque of dbl_counter_metric_family +function Telemetry::__dbl_counter_family%(prefix: string, + name: string, + labels: string_vec, + helptext: string &default = "Zeek Script Metric", + unit: string &default = "1", + is_sum: bool &default = F%): opaque of dbl_counter_metric_family %{ auto lbl_vec = sv_vec(labels->AsVectorVal()); auto hdl = telemetry_mgr->CounterFamily(sv(prefix), sv(name), lbl_vec, @@ -184,8 +184,8 @@ function Telemetry::dbl_counter_family%(prefix: string, return zeek::make_intrusive(hdl); %} -function Telemetry::dbl_counter_metric_get_or_add%(family: opaque of dbl_counter_metric_family, - labels: table_string_of_string%): opaque of dbl_counter_metric +function Telemetry::__dbl_counter_metric_get_or_add%(family: opaque of dbl_counter_metric_family, + labels: table_string_of_string%): opaque of dbl_counter_metric %{ using ResultType = zeek::IntrusivePtr; if ( auto ptr = dynamic_cast(family) ) @@ -210,24 +210,24 @@ function Telemetry::dbl_counter_metric_get_or_add%(family: opaque of dbl_counter } %} -function Telemetry::dbl_counter_singleton%(prefix: string, - name: string, - helptext: string &default = "Zeek Script Metric", - unit: string &default = "1", - is_sum: bool &default = F%): opaque of dbl_counter_metric +function Telemetry::__dbl_counter_singleton%(prefix: string, + name: string, + helptext: string &default = "Zeek Script Metric", + unit: string &default = "1", + is_sum: bool &default = F%): opaque of dbl_counter_metric %{ auto hdl = telemetry_mgr->CounterSingleton(sv(prefix), sv(name), sv(helptext), sv(unit), is_sum); return zeek::make_intrusive(hdl); %} -function Telemetry::dbl_counter_inc%(val: opaque of dbl_counter_metric, - amount: double &default = 1.0%): bool +function Telemetry::__dbl_counter_inc%(val: opaque of dbl_counter_metric, + amount: double &default = 1.0%): bool %{ return with(val, "Telemetry::dbl_counter_inc: invalid handle.", [amount](auto hdl) { hdl.Inc(amount); }); %} -function Telemetry::dbl_counter_value%(val: opaque of dbl_counter_metric%): double +function Telemetry::__dbl_counter_value%(val: opaque of dbl_counter_metric%): double %{ if ( auto ptr = dynamic_cast(val) ) { @@ -242,12 +242,12 @@ function Telemetry::dbl_counter_value%(val: opaque of dbl_counter_metric%): doub # -- IntGauge ------------------------------------------------------------------ -function Telemetry::int_gauge_family%(prefix: string, - name: string, - labels: string_vec, - helptext: string &default = "Zeek Script Metric", - unit: string &default = "1", - is_sum: bool &default = F%): opaque of int_gauge_metric_family +function Telemetry::__int_gauge_family%(prefix: string, + name: string, + labels: string_vec, + helptext: string &default = "Zeek Script Metric", + unit: string &default = "1", + is_sum: bool &default = F%): opaque of int_gauge_metric_family %{ auto lbl_vec = sv_vec(labels->AsVectorVal()); auto hdl = telemetry_mgr->GaugeFamily(sv(prefix), sv(name), lbl_vec, @@ -255,8 +255,8 @@ function Telemetry::int_gauge_family%(prefix: string, return zeek::make_intrusive(hdl); %} -function Telemetry::int_gauge_metric_get_or_add%(family: opaque of int_gauge_metric_family, - labels: table_string_of_string%): opaque of int_gauge_metric +function Telemetry::__int_gauge_metric_get_or_add%(family: opaque of int_gauge_metric_family, + labels: table_string_of_string%): opaque of int_gauge_metric %{ using ResultType = zeek::IntrusivePtr; if ( auto ptr = dynamic_cast(family) ) @@ -281,30 +281,30 @@ function Telemetry::int_gauge_metric_get_or_add%(family: opaque of int_gauge_met } %} -function Telemetry::int_gauge_singleton%(prefix: string, - name: string, - helptext: string &default = "Zeek Script Metric", - unit: string &default = "1", - is_sum: bool &default = F%): opaque of int_gauge_metric +function Telemetry::__int_gauge_singleton%(prefix: string, + name: string, + helptext: string &default = "Zeek Script Metric", + unit: string &default = "1", + is_sum: bool &default = F%): opaque of int_gauge_metric %{ auto hdl = telemetry_mgr->GaugeSingleton(sv(prefix), sv(name), sv(helptext), sv(unit), is_sum); return zeek::make_intrusive(hdl); %} -function Telemetry::int_gauge_inc%(val: opaque of int_gauge_metric, - amount: int &default = 1%): bool +function Telemetry::__int_gauge_inc%(val: opaque of int_gauge_metric, + amount: int &default = 1%): bool %{ return with(val, "Telemetry::int_gauge_inc: invalid handle.", [amount](auto hdl) { hdl.Inc(amount); }); %} -function Telemetry::int_gauge_dec%(val: opaque of int_gauge_metric, - amount: int &default = 1%): bool +function Telemetry::__int_gauge_dec%(val: opaque of int_gauge_metric, + amount: int &default = 1%): bool %{ return with(val, "Telemetry::int_gauge_dec: invalid handle.", [amount](auto hdl) { hdl.Dec(amount); }); %} -function Telemetry::int_gauge_value%(val: opaque of int_gauge_metric%): int +function Telemetry::__int_gauge_value%(val: opaque of int_gauge_metric%): int %{ if ( auto ptr = dynamic_cast(val) ) { @@ -319,12 +319,12 @@ function Telemetry::int_gauge_value%(val: opaque of int_gauge_metric%): int # -- DblGauge ------------------------------------------------------------------ -function Telemetry::dbl_gauge_family%(prefix: string, - name: string, - labels: string_vec, - helptext: string &default = "Zeek Script Metric", - unit: string &default = "1", - is_sum: bool &default = F%): opaque of dbl_gauge_metric_family +function Telemetry::__dbl_gauge_family%(prefix: string, + name: string, + labels: string_vec, + helptext: string &default = "Zeek Script Metric", + unit: string &default = "1", + is_sum: bool &default = F%): opaque of dbl_gauge_metric_family %{ auto lbl_vec = sv_vec(labels->AsVectorVal()); auto hdl = telemetry_mgr->GaugeFamily(sv(prefix), sv(name), lbl_vec, @@ -332,8 +332,8 @@ function Telemetry::dbl_gauge_family%(prefix: string, return zeek::make_intrusive(hdl); %} -function Telemetry::dbl_gauge_metric_get_or_add%(family: opaque of dbl_gauge_metric_family, - labels: table_string_of_string%): opaque of dbl_gauge_metric +function Telemetry::__dbl_gauge_metric_get_or_add%(family: opaque of dbl_gauge_metric_family, + labels: table_string_of_string%): opaque of dbl_gauge_metric %{ using ResultType = zeek::IntrusivePtr; if ( auto ptr = dynamic_cast(family) ) @@ -358,30 +358,30 @@ function Telemetry::dbl_gauge_metric_get_or_add%(family: opaque of dbl_gauge_met } %} -function Telemetry::dbl_gauge_singleton%(prefix: string, - name: string, - helptext: string &default = "Zeek Script Metric", - unit: string &default = "1", - is_sum: bool &default = F%): opaque of dbl_gauge_metric +function Telemetry::__dbl_gauge_singleton%(prefix: string, + name: string, + helptext: string &default = "Zeek Script Metric", + unit: string &default = "1", + is_sum: bool &default = F%): opaque of dbl_gauge_metric %{ auto hdl = telemetry_mgr->GaugeSingleton(sv(prefix), sv(name), sv(helptext), sv(unit), is_sum); return zeek::make_intrusive(hdl); %} -function Telemetry::dbl_gauge_inc%(val: opaque of dbl_gauge_metric, - amount: double &default = 1.0%): bool +function Telemetry::__dbl_gauge_inc%(val: opaque of dbl_gauge_metric, + amount: double &default = 1.0%): bool %{ return with(val, "Telemetry::dbl_gauge_inc: invalid handle.", [amount](auto hdl) { hdl.Inc(amount); }); %} -function Telemetry::dbl_gauge_dec%(val: opaque of dbl_gauge_metric, - amount: double &default = 1.0%): bool +function Telemetry::__dbl_gauge_dec%(val: opaque of dbl_gauge_metric, + amount: double &default = 1.0%): bool %{ return with(val, "Telemetry::dbl_gauge_dec: invalid handle.", [amount](auto hdl) { hdl.Dec(amount); }); %} -function Telemetry::dbl_gauge_value%(val: opaque of dbl_gauge_metric%): double +function Telemetry::__dbl_gauge_value%(val: opaque of dbl_gauge_metric%): double %{ if ( auto ptr = dynamic_cast(val) ) { @@ -396,13 +396,13 @@ function Telemetry::dbl_gauge_value%(val: opaque of dbl_gauge_metric%): double # -- IntHistogram -------------------------------------------------------------- -function Telemetry::int_histogram_family%(prefix: string, - name: string, - labels: string_vec, - bounds: int_vec, - helptext: string &default = "Zeek Script Metric", - unit: string &default = "1", - is_sum: bool &default = F%): opaque of int_histogram_metric_family +function Telemetry::__int_histogram_family%(prefix: string, + name: string, + labels: string_vec, + bounds: int_vec, + helptext: string &default = "Zeek Script Metric", + unit: string &default = "1", + is_sum: bool &default = F%): opaque of int_histogram_metric_family %{ auto lbl_vec = sv_vec(labels->AsVectorVal()); auto std_bounds = to_std_vec(bounds); @@ -412,8 +412,8 @@ function Telemetry::int_histogram_family%(prefix: string, return zeek::make_intrusive(hdl); %} -function Telemetry::int_histogram_metric_get_or_add%(family: opaque of int_histogram_metric_family, - labels: table_string_of_string%): opaque of int_histogram_metric +function Telemetry::__int_histogram_metric_get_or_add%(family: opaque of int_histogram_metric_family, + labels: table_string_of_string%): opaque of int_histogram_metric %{ using ResultType = zeek::IntrusivePtr; if ( auto ptr = dynamic_cast(family) ) @@ -438,12 +438,12 @@ function Telemetry::int_histogram_metric_get_or_add%(family: opaque of int_histo } %} -function Telemetry::int_histogram_singleton%(prefix: string, - name: string, - bounds: int_vec, - helptext: string &default = "Zeek Script Metric", - unit: string &default = "1", - is_sum: bool &default = F%): opaque of int_histogram_metric +function Telemetry::__int_histogram_singleton%(prefix: string, + name: string, + bounds: int_vec, + helptext: string &default = "Zeek Script Metric", + unit: string &default = "1", + is_sum: bool &default = F%): opaque of int_histogram_metric %{ auto std_bounds = to_std_vec(bounds); auto hdl = telemetry_mgr->HistogramSingleton(sv(prefix), sv(name), @@ -452,13 +452,13 @@ function Telemetry::int_histogram_singleton%(prefix: string, return zeek::make_intrusive(hdl); %} -function Telemetry::int_histogram_observe%(val: opaque of int_histogram_metric, - measurement: int%): bool +function Telemetry::__int_histogram_observe%(val: opaque of int_histogram_metric, + measurement: int%): bool %{ return with(val, "Telemetry::int_histogram_inc: invalid handle.", [measurement](auto hdl) { hdl.Observe(measurement); }); %} -function Telemetry::int_histogram_sum%(val: opaque of int_histogram_metric%): int +function Telemetry::__int_histogram_sum%(val: opaque of int_histogram_metric%): int %{ if ( auto ptr = dynamic_cast(val) ) { @@ -473,13 +473,13 @@ function Telemetry::int_histogram_sum%(val: opaque of int_histogram_metric%): in # -- DblHistogram -------------------------------------------------------------- -function Telemetry::dbl_histogram_family%(prefix: string, - name: string, - labels: string_vec, - bounds: double_vec, - helptext: string &default = "Zeek Script Metric", - unit: string &default = "1", - is_sum: bool &default = F%): opaque of dbl_histogram_metric_family +function Telemetry::__dbl_histogram_family%(prefix: string, + name: string, + labels: string_vec, + bounds: double_vec, + helptext: string &default = "Zeek Script Metric", + unit: string &default = "1", + is_sum: bool &default = F%): opaque of dbl_histogram_metric_family %{ auto lbl_vec = sv_vec(labels->AsVectorVal()); auto std_bounds = to_std_vec(bounds); @@ -490,8 +490,8 @@ function Telemetry::dbl_histogram_family%(prefix: string, return zeek::make_intrusive(hdl); %} -function Telemetry::dbl_histogram_metric_get_or_add%(family: opaque of dbl_histogram_metric_family, - labels: table_string_of_string%): opaque of dbl_histogram_metric +function Telemetry::__dbl_histogram_metric_get_or_add%(family: opaque of dbl_histogram_metric_family, + labels: table_string_of_string%): opaque of dbl_histogram_metric %{ using ResultType = zeek::IntrusivePtr; if ( auto ptr = dynamic_cast(family) ) @@ -516,12 +516,12 @@ function Telemetry::dbl_histogram_metric_get_or_add%(family: opaque of dbl_histo } %} -function Telemetry::dbl_histogram_singleton%(prefix: string, - name: string, - bounds: double_vec, - helptext: string &default = "Zeek Script Metric", - unit: string &default = "1", - is_sum: bool &default = F%): opaque of dbl_histogram_metric +function Telemetry::__dbl_histogram_singleton%(prefix: string, + name: string, + bounds: double_vec, + helptext: string &default = "Zeek Script Metric", + unit: string &default = "1", + is_sum: bool &default = F%): opaque of dbl_histogram_metric %{ auto std_bounds = to_std_vec(bounds); auto hdl = telemetry_mgr->HistogramSingleton(sv(prefix), sv(name), @@ -530,13 +530,13 @@ function Telemetry::dbl_histogram_singleton%(prefix: string, return zeek::make_intrusive(hdl); %} -function Telemetry::dbl_histogram_observe%(val: opaque of dbl_histogram_metric, - measurement: double%): bool +function Telemetry::__dbl_histogram_observe%(val: opaque of dbl_histogram_metric, + measurement: double%): bool %{ return with(val, "Telemetry::dbl_histogram_inc: invalid handle.", [measurement](auto hdl) { hdl.Observe(measurement); }); %} -function Telemetry::dbl_histogram_sum%(val: opaque of dbl_histogram_metric%): double +function Telemetry::__dbl_histogram_sum%(val: opaque of dbl_histogram_metric%): double %{ if ( auto ptr = dynamic_cast(val) ) { diff --git a/testing/btest/telemetry/counter.zeek b/testing/btest/telemetry/counter.zeek index 937c6760a5..efe062e46d 100644 --- a/testing/btest/telemetry/counter.zeek +++ b/testing/btest/telemetry/counter.zeek @@ -3,23 +3,23 @@ # @TEST-EXEC: zeek -b %INPUT >output # @TEST-EXEC: btest-diff output -global cnt1 = Telemetry::int_counter_family("cnt1", "bar", vector("dim1", "dim2")); -global cnt2_bar = Telemetry::int_counter_singleton("cnt2", "bar"); -global cnt3 = Telemetry::dbl_counter_family("cnt3", "bar", vector("dim1", "dim2")); -global cnt4_bar = Telemetry::dbl_counter_singleton("cnt4", "bar"); +global cnt1 = Telemetry::__int_counter_family("cnt1", "bar", vector("dim1", "dim2")); +global cnt2_bar = Telemetry::__int_counter_singleton("cnt2", "bar"); +global cnt3 = Telemetry::__dbl_counter_family("cnt3", "bar", vector("dim1", "dim2")); +global cnt4_bar = Telemetry::__dbl_counter_singleton("cnt4", "bar"); event zeek_init() { - local cnt1_bar = Telemetry::int_counter_metric_get_or_add(cnt1, table(["dim1"] = "val1", ["dim2"] = "val2")); - Telemetry::int_counter_inc(cnt1_bar); - Telemetry::int_counter_inc(cnt2_bar); - Telemetry::int_counter_inc(cnt2_bar, 41); - print fmt("cnt1_bar: %d", Telemetry::int_counter_value(cnt1_bar)); - print fmt("cnt2_bar: %d", Telemetry::int_counter_value(cnt2_bar)); - local cnt3_bar = Telemetry::dbl_counter_metric_get_or_add(cnt3, table(["dim1"] = "val1", ["dim2"] = "val2")); - Telemetry::dbl_counter_inc(cnt3_bar); - Telemetry::dbl_counter_inc(cnt4_bar); - Telemetry::dbl_counter_inc(cnt4_bar, 41.0); - print fmt("cnt3_bar: %f", Telemetry::dbl_counter_value(cnt3_bar)); - print fmt("cnt4_bar: %f", Telemetry::dbl_counter_value(cnt4_bar)); + local cnt1_bar = Telemetry::__int_counter_metric_get_or_add(cnt1, table(["dim1"] = "val1", ["dim2"] = "val2")); + Telemetry::__int_counter_inc(cnt1_bar); + Telemetry::__int_counter_inc(cnt2_bar); + Telemetry::__int_counter_inc(cnt2_bar, 41); + print fmt("cnt1_bar: %d", Telemetry::__int_counter_value(cnt1_bar)); + print fmt("cnt2_bar: %d", Telemetry::__int_counter_value(cnt2_bar)); + local cnt3_bar = Telemetry::__dbl_counter_metric_get_or_add(cnt3, table(["dim1"] = "val1", ["dim2"] = "val2")); + Telemetry::__dbl_counter_inc(cnt3_bar); + Telemetry::__dbl_counter_inc(cnt4_bar); + Telemetry::__dbl_counter_inc(cnt4_bar, 41.0); + print fmt("cnt3_bar: %f", Telemetry::__dbl_counter_value(cnt3_bar)); + print fmt("cnt4_bar: %f", Telemetry::__dbl_counter_value(cnt4_bar)); } diff --git a/testing/btest/telemetry/gauge.zeek b/testing/btest/telemetry/gauge.zeek index 812ef0b524..5966571dbc 100644 --- a/testing/btest/telemetry/gauge.zeek +++ b/testing/btest/telemetry/gauge.zeek @@ -3,28 +3,28 @@ # @TEST-EXEC: zeek -b %INPUT >output # @TEST-EXEC: btest-diff output -global gg1 = Telemetry::int_gauge_family("gg1", "bar", vector("dim1", "dim2")); -global gg2_bar = Telemetry::int_gauge_singleton("gg2", "bar"); -global gg3 = Telemetry::dbl_gauge_family("gg3", "bar", vector("dim1", "dim2")); -global gg4_bar = Telemetry::dbl_gauge_singleton("gg4", "bar"); +global gg1 = Telemetry::__int_gauge_family("gg1", "bar", vector("dim1", "dim2")); +global gg2_bar = Telemetry::__int_gauge_singleton("gg2", "bar"); +global gg3 = Telemetry::__dbl_gauge_family("gg3", "bar", vector("dim1", "dim2")); +global gg4_bar = Telemetry::__dbl_gauge_singleton("gg4", "bar"); event zeek_init() { - local gg1_bar = Telemetry::int_gauge_metric_get_or_add(gg1, table(["dim1"] = "val1", ["dim2"] = "val2")); - Telemetry::int_gauge_inc(gg1_bar); - Telemetry::int_gauge_inc(gg2_bar); - Telemetry::int_gauge_inc(gg2_bar, 41); - Telemetry::int_gauge_dec(gg2_bar); - Telemetry::int_gauge_dec(gg2_bar, 18); - print fmt("gg1_bar: %d", Telemetry::int_gauge_value(gg1_bar)); - print fmt("gg2_bar: %d", Telemetry::int_gauge_value(gg2_bar)); - local gg3_bar = Telemetry::dbl_gauge_metric_get_or_add(gg3, table(["dim1"] = "val1", ["dim2"] = "val2")); - Telemetry::dbl_gauge_inc(gg3_bar); - Telemetry::dbl_gauge_inc(gg4_bar); - Telemetry::dbl_gauge_inc(gg4_bar, 41.0); - Telemetry::dbl_gauge_dec(gg4_bar); - Telemetry::dbl_gauge_dec(gg4_bar, 18.0); - print fmt("gg3_bar: %f", Telemetry::dbl_gauge_value(gg3_bar)); - print fmt("gg4_bar: %f", Telemetry::dbl_gauge_value(gg4_bar)); + local gg1_bar = Telemetry::__int_gauge_metric_get_or_add(gg1, table(["dim1"] = "val1", ["dim2"] = "val2")); + Telemetry::__int_gauge_inc(gg1_bar); + Telemetry::__int_gauge_inc(gg2_bar); + Telemetry::__int_gauge_inc(gg2_bar, 41); + Telemetry::__int_gauge_dec(gg2_bar); + Telemetry::__int_gauge_dec(gg2_bar, 18); + print fmt("gg1_bar: %d", Telemetry::__int_gauge_value(gg1_bar)); + print fmt("gg2_bar: %d", Telemetry::__int_gauge_value(gg2_bar)); + local gg3_bar = Telemetry::__dbl_gauge_metric_get_or_add(gg3, table(["dim1"] = "val1", ["dim2"] = "val2")); + Telemetry::__dbl_gauge_inc(gg3_bar); + Telemetry::__dbl_gauge_inc(gg4_bar); + Telemetry::__dbl_gauge_inc(gg4_bar, 41.0); + Telemetry::__dbl_gauge_dec(gg4_bar); + Telemetry::__dbl_gauge_dec(gg4_bar, 18.0); + print fmt("gg3_bar: %f", Telemetry::__dbl_gauge_value(gg3_bar)); + print fmt("gg4_bar: %f", Telemetry::__dbl_gauge_value(gg4_bar)); } diff --git a/testing/btest/telemetry/histogram.zeek b/testing/btest/telemetry/histogram.zeek index 2dc5a9e751..de183872b0 100644 --- a/testing/btest/telemetry/histogram.zeek +++ b/testing/btest/telemetry/histogram.zeek @@ -6,23 +6,23 @@ const int_bounds = vector(+10, +20); const dbl_bounds = vector(10.0, 20.0); -global hst1 = Telemetry::int_histogram_family("hst1", "bar", vector("dim1", "dim2"), int_bounds); -global hst2_bar = Telemetry::int_histogram_singleton("hst2", "bar", int_bounds); -global hst3 = Telemetry::dbl_histogram_family("hst3", "bar", vector("dim1", "dim2"), dbl_bounds); -global hst4_bar = Telemetry::dbl_histogram_singleton("hst4", "bar", dbl_bounds); +global hst1 = Telemetry::__int_histogram_family("hst1", "bar", vector("dim1", "dim2"), int_bounds); +global hst2_bar = Telemetry::__int_histogram_singleton("hst2", "bar", int_bounds); +global hst3 = Telemetry::__dbl_histogram_family("hst3", "bar", vector("dim1", "dim2"), dbl_bounds); +global hst4_bar = Telemetry::__dbl_histogram_singleton("hst4", "bar", dbl_bounds); event zeek_init() { - local hst1_bar = Telemetry::int_histogram_metric_get_or_add(hst1, table(["dim1"] = "val1", ["dim2"] = "val2")); - Telemetry::int_histogram_observe(hst1_bar, 1); - Telemetry::int_histogram_observe(hst1_bar, 11); - Telemetry::int_histogram_observe(hst2_bar, 31337); - print fmt("hst1_bar: %d", Telemetry::int_histogram_sum(hst1_bar)); - print fmt("hst2_bar: %d", Telemetry::int_histogram_sum(hst2_bar)); - local hst3_bar = Telemetry::dbl_histogram_metric_get_or_add(hst3, table(["dim1"] = "val1", ["dim2"] = "val2")); - Telemetry::dbl_histogram_observe(hst3_bar, 2.0); - Telemetry::dbl_histogram_observe(hst3_bar, 4.0); - Telemetry::dbl_histogram_observe(hst4_bar, 64.0); - print fmt("hst3_bar: %f", Telemetry::dbl_histogram_sum(hst3_bar)); - print fmt("hst4_bar: %f", Telemetry::dbl_histogram_sum(hst4_bar)); + local hst1_bar = Telemetry::__int_histogram_metric_get_or_add(hst1, table(["dim1"] = "val1", ["dim2"] = "val2")); + Telemetry::__int_histogram_observe(hst1_bar, 1); + Telemetry::__int_histogram_observe(hst1_bar, 11); + Telemetry::__int_histogram_observe(hst2_bar, 31337); + print fmt("hst1_bar: %d", Telemetry::__int_histogram_sum(hst1_bar)); + print fmt("hst2_bar: %d", Telemetry::__int_histogram_sum(hst2_bar)); + local hst3_bar = Telemetry::__dbl_histogram_metric_get_or_add(hst3, table(["dim1"] = "val1", ["dim2"] = "val2")); + Telemetry::__dbl_histogram_observe(hst3_bar, 2.0); + Telemetry::__dbl_histogram_observe(hst3_bar, 4.0); + Telemetry::__dbl_histogram_observe(hst4_bar, 64.0); + print fmt("hst3_bar: %f", Telemetry::__dbl_histogram_sum(hst3_bar)); + print fmt("hst4_bar: %f", Telemetry::__dbl_histogram_sum(hst4_bar)); } From 600d1118cd6b047f72b148b3c5d2f026e78c9830 Mon Sep 17 00:00:00 2001 From: Dominik Charousset Date: Thu, 11 Mar 2021 15:21:11 +0100 Subject: [PATCH 11/13] Update baselines --- .../coverage.bare-load-baseline/canonified_loaded_scripts.log | 1 + .../canonified_loaded_scripts.log | 1 + testing/btest/Baseline/plugins.hooks/output | 3 +++ 3 files changed, 5 insertions(+) diff --git a/testing/btest/Baseline/coverage.bare-load-baseline/canonified_loaded_scripts.log b/testing/btest/Baseline/coverage.bare-load-baseline/canonified_loaded_scripts.log index 43222b07e4..813ba4354b 100644 --- a/testing/btest/Baseline/coverage.bare-load-baseline/canonified_loaded_scripts.log +++ b/testing/btest/Baseline/coverage.bare-load-baseline/canonified_loaded_scripts.log @@ -97,6 +97,7 @@ scripts/base/init-frameworks-and-bifs.zeek scripts/base/utils/patterns.zeek scripts/base/frameworks/files/magic/__load__.zeek build/scripts/base/bif/__load__.zeek + build/scripts/base/bif/telemetry.bif.zeek build/scripts/base/bif/zeekygen.bif.zeek build/scripts/base/bif/pcap.bif.zeek build/scripts/base/bif/bloom-filter.bif.zeek diff --git a/testing/btest/Baseline/coverage.default-load-baseline/canonified_loaded_scripts.log b/testing/btest/Baseline/coverage.default-load-baseline/canonified_loaded_scripts.log index e65e4dd62e..7be8032039 100644 --- a/testing/btest/Baseline/coverage.default-load-baseline/canonified_loaded_scripts.log +++ b/testing/btest/Baseline/coverage.default-load-baseline/canonified_loaded_scripts.log @@ -97,6 +97,7 @@ scripts/base/init-frameworks-and-bifs.zeek scripts/base/utils/patterns.zeek scripts/base/frameworks/files/magic/__load__.zeek build/scripts/base/bif/__load__.zeek + build/scripts/base/bif/telemetry.bif.zeek build/scripts/base/bif/zeekygen.bif.zeek build/scripts/base/bif/pcap.bif.zeek build/scripts/base/bif/bloom-filter.bif.zeek diff --git a/testing/btest/Baseline/plugins.hooks/output b/testing/btest/Baseline/plugins.hooks/output index 700c195e39..aafea1436e 100644 --- a/testing/btest/Baseline/plugins.hooks/output +++ b/testing/btest/Baseline/plugins.hooks/output @@ -837,6 +837,7 @@ 0.000000 MetaHookPost LoadFile(0, ./strings.bif.zeek, <...>/strings.bif.zeek) -> -1 0.000000 MetaHookPost LoadFile(0, ./sum, <...>/sum.zeek) -> -1 0.000000 MetaHookPost LoadFile(0, ./supervisor.bif.zeek, <...>/supervisor.bif.zeek) -> -1 +0.000000 MetaHookPost LoadFile(0, ./telemetry.bif.zeek, <...>/telemetry.bif.zeek) -> -1 0.000000 MetaHookPost LoadFile(0, ./thresholds, <...>/thresholds.zeek) -> -1 0.000000 MetaHookPost LoadFile(0, ./top-k.bif.zeek, <...>/top-k.bif.zeek) -> -1 0.000000 MetaHookPost LoadFile(0, ./topk, <...>/topk.zeek) -> -1 @@ -1840,6 +1841,7 @@ 0.000000 MetaHookPre LoadFile(0, ./strings.bif.zeek, <...>/strings.bif.zeek) 0.000000 MetaHookPre LoadFile(0, ./sum, <...>/sum.zeek) 0.000000 MetaHookPre LoadFile(0, ./supervisor.bif.zeek, <...>/supervisor.bif.zeek) +0.000000 MetaHookPre LoadFile(0, ./telemetry.bif.zeek, <...>/telemetry.bif.zeek) 0.000000 MetaHookPre LoadFile(0, ./thresholds, <...>/thresholds.zeek) 0.000000 MetaHookPre LoadFile(0, ./top-k.bif.zeek, <...>/top-k.bif.zeek) 0.000000 MetaHookPre LoadFile(0, ./topk, <...>/topk.zeek) @@ -2853,6 +2855,7 @@ 0.000000 | HookLoadFile ./strings.bif.zeek <...>/strings.bif.zeek 0.000000 | HookLoadFile ./sum <...>/sum.zeek 0.000000 | HookLoadFile ./supervisor.bif.zeek <...>/supervisor.bif.zeek +0.000000 | HookLoadFile ./telemetry.bif.zeek <...>/telemetry.bif.zeek 0.000000 | HookLoadFile ./thresholds <...>/thresholds.zeek 0.000000 | HookLoadFile ./top-k.bif.zeek <...>/top-k.bif.zeek 0.000000 | HookLoadFile ./topk <...>/topk.zeek From 6e6b83bd9654cb8bec210e47084f9135f50ec551 Mon Sep 17 00:00:00 2001 From: Dominik Charousset Date: Mon, 29 Mar 2021 11:18:38 +0200 Subject: [PATCH 12/13] Fix build with latest VectorVal API --- src/telemetry/telemetry.bif | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/telemetry/telemetry.bif b/src/telemetry/telemetry.bif index a4b7eea8d5..3c4d6d2d1b 100644 --- a/src/telemetry/telemetry.bif +++ b/src/telemetry/telemetry.bif @@ -42,7 +42,7 @@ std::vector sv_vec(zeek::VectorVal* xs) std::vector result; if ( xs ) for ( unsigned index = 0; index < xs->Size(); ++index ) - if ( auto& ptr = xs->At(index) ) + if ( auto ptr = xs->ValAt(index) ) if ( auto* str = ptr->AsString() ) result.emplace_back(sv(str)); return result; @@ -82,9 +82,9 @@ auto to_std_vec(zeek::VectorVal* xs) for ( unsigned index = 0; index < xs->Size() ; ++index ) { if constexpr (std::is_same::value) - result.emplace_back(xs->At(index)->AsInt()); + result.emplace_back(xs->ValAt(index)->AsInt()); else - result.emplace_back(xs->At(index)->AsDouble()); + result.emplace_back(xs->ValAt(index)->AsDouble()); } return result; } From 27a39941db648dec04dc744cf3ff2e9aaaefa241 Mon Sep 17 00:00:00 2001 From: Dominik Charousset Date: Mon, 29 Mar 2021 12:02:13 +0200 Subject: [PATCH 13/13] Add new Timer class to the telemetry API --- src/telemetry/Manager.cc | 13 ++++++++++ src/telemetry/Timer.h | 55 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+) create mode 100644 src/telemetry/Timer.h diff --git a/src/telemetry/Manager.cc b/src/telemetry/Manager.cc index f8cd56d8f2..5bee940a25 100644 --- a/src/telemetry/Manager.cc +++ b/src/telemetry/Manager.cc @@ -4,9 +4,12 @@ #include "caf/telemetry/metric_registry.hpp" +#include + #include "zeek/3rdparty/doctest.h" #include "zeek/telemetry/Detail.h" +#include "zeek/telemetry/Timer.h" namespace zeek::telemetry { @@ -524,6 +527,16 @@ SCENARIO("telemetry managers provide access to histogram families") auto second = family.GetOrAdd({{"protocol", "udp"}}); CHECK_NE(first, second); } + AND_THEN("Timers add observations to histograms") + { + auto hg = family.GetOrAdd({{"protocol", "tst"}}); + CHECK_EQ(hg.Sum(), 0.0); + { + Timer observer{hg}; + std::this_thread::sleep_for(1ms); + } + CHECK_NE(hg.Sum(), 0.0); + } } } } diff --git a/src/telemetry/Timer.h b/src/telemetry/Timer.h new file mode 100644 index 0000000000..ad02a4c09c --- /dev/null +++ b/src/telemetry/Timer.h @@ -0,0 +1,55 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#pragma once + +#include + +namespace zeek::telemetry { + +/// Convenience helper for measuring durations such as latency using a histogram +/// with second resolution. The measurement starts when creating the objects and +/// finishes when the Timer goes out of scope. +class Timer { +public: + using Clock = std::chrono::steady_clock; + + [[nodiscard]] explicit Timer(DblHistogram h) : h_(h) + { + start_ = Clock::now(); + } + + Timer(const Timer&) = delete; + + Timer&operator=(const Timer&) = delete; + + ~Timer() + { + Observe(h_, start_); + } + + /// @return The histogram handle. + auto Handle() const noexcept + { + return h_; + } + + /// @return The recorded start time. + auto Started() const noexcept + { + return start_; + } + + /// Calls `h.Observe` with the time passed since `start`. + static void Observe(DblHistogram h, Clock::time_point start) + { + using DblSec = std::chrono::duration; + if ( auto end = Clock::now(); end > start ) + h.Observe(std::chrono::duration_cast(end - start).count()); + } + +private: + DblHistogram h_; + Clock::time_point start_; +}; + +} // namespace zeek::telemetry