Commit e892fcf5 authored by Dominik Charousset's avatar Dominik Charousset

Add initial scaffold for new telemetry API

Data model and concepts were moslty adapted from [Prometheus]. However,
the new telemetry API integrates directly into CAF and generalizes a few
concepts when compared to the Prometheus API.

By not bundling CAF directly with a third-party API, we also retain
better capabilities to integrate with other monitoring solutions in the
future, e.g., via [OpenTelemetry] (currently a CNCF sandbox project).

[Prometheus]: https://prometheus.io/
[OpenTelemetry]: https://opentelemetry.io/
parent e3f7e64c
...@@ -162,6 +162,11 @@ add_library(libcaf_core_obj OBJECT ${CAF_CORE_HEADERS} ...@@ -162,6 +162,11 @@ add_library(libcaf_core_obj OBJECT ${CAF_CORE_HEADERS}
src/stream_priority_strings.cpp src/stream_priority_strings.cpp
src/string_algorithms.cpp src/string_algorithms.cpp
src/string_view.cpp src/string_view.cpp
src/telemetry/label.cpp
src/telemetry/label_view.cpp
src/telemetry/metric.cpp
src/telemetry/metric_family.cpp
src/telemetry/metric_registry.cpp
src/term.cpp src/term.cpp
src/test_credit_controller.cpp src/test_credit_controller.cpp
src/thread_hook.cpp src/thread_hook.cpp
...@@ -302,6 +307,9 @@ caf_add_test_suites(caf-core-test ...@@ -302,6 +307,9 @@ caf_add_test_suites(caf-core-test
string_algorithms string_algorithms
string_view string_view
sum_type sum_type
telemetry.int_gauge
telemetry.label
telemetry.metric_registry
thread_hook thread_hook
tracing_data tracing_data
type_id_list type_id_list
......
...@@ -229,6 +229,28 @@ struct subscriber_base; ...@@ -229,6 +229,28 @@ struct subscriber_base;
} // namespace mixin } // namespace mixin
// -- telemetry API ------------------------------------------------------------
namespace telemetry {
class component;
class int_gauge;
class label;
class label_view;
class metric;
class metric_family;
class metric_registry;
enum class metric_type : uint8_t;
template <class Type>
class metric_family_impl;
template <class Type>
class metric_impl;
} // namespace telemetry
// -- I/O classes -------------------------------------------------------------- // -- I/O classes --------------------------------------------------------------
namespace io { namespace io {
......
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2020 Dominik Charousset *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#pragma once
#include "caf/detail/core_export.hpp"
#include <atomic>
#include <cstdint>
namespace caf::telemetry {
/// A metric that represents a single integer value that can arbitrarily go up
/// and down.
class CAF_CORE_EXPORT int_gauge {
public:
int_gauge() noexcept : value_(0) {
// nop
}
explicit int_gauge(int64_t value) noexcept : value_(value) {
// nop
}
/// Increments the gauge by 1.
void increment() noexcept {
++value_;
}
/// Increments the gauge by `amount`.
void increment(int64_t amount) noexcept {
value_.fetch_add(amount);
}
/// Decrements the gauge by 1.
void decrement() noexcept {
--value_;
}
/// Decrements the gauge by `amount`.
void decrement(int64_t amount) noexcept {
value_.fetch_sub(amount);
}
/// Sets the gauge to `x`.
void value(int64_t x) noexcept {
value_.store(x);
}
/// Returns the current value of the gauge.
int64_t value() const noexcept {
return value_.load();
}
private:
std::atomic<int64_t> value_;
};
} // namespace caf::telemetry
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2020 Dominik Charousset *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#pragma once
#include <string>
#include "caf/detail/comparable.hpp"
#include "caf/detail/core_export.hpp"
#include "caf/fwd.hpp"
#include "caf/hash/fnv.hpp"
#include "caf/string_view.hpp"
namespace caf::telemetry {
/// An (immutable) key-value pair for adding extra dimensions to metrics.
class CAF_CORE_EXPORT label : detail::comparable<label> {
public:
// -- constructors, destructors, and assignment operators --------------------
label() = delete;
label(label&&) = default;
label(const label&) = default;
label& operator=(label&&) = default;
label& operator=(const label&) = default;
/// @pre `name` matches the regex `[a-zA-Z_:][a-zA-Z0-9_:]*`
label(string_view name, string_view value);
explicit label(const label_view& view);
// -- properties -------------------------------------------------------------
string_view name() const noexcept {
return string_view{str_.data(), name_length_};
}
string_view value() const noexcept {
return string_view{str_.data() + name_length_ + 1,
str_.size() - name_length_ - 1};
}
/// Returns the label in `name=value` notation.
const std::string& str() const noexcept {
return str_;
}
// -- comparison -------------------------------------------------------------
int compare(const label& x) const noexcept;
private:
size_t name_length_;
std::string str_;
};
/// Returns the @ref label in `name=value` notation.
/// @relates label
CAF_CORE_EXPORT std::string to_string(const label& x);
} // namespace caf::telemetry
namespace std {
template <>
struct hash<caf::telemetry::label> {
size_t operator()(const caf::telemetry::label& x) const noexcept {
return caf::hash::fnv<size_t>::compute(x.str());
}
};
} // namespace std
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2020 Dominik Charousset *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#pragma once
#include "caf/detail/comparable.hpp"
#include "caf/detail/core_export.hpp"
#include "caf/fwd.hpp"
#include "caf/hash/fnv.hpp"
#include "caf/string_view.hpp"
namespace caf::telemetry {
class CAF_CORE_EXPORT label_view : detail::comparable<label_view>,
detail::comparable<label_view, label> {
public:
// -- constructors, destructors, and assignment operators --------------------
label_view() = delete;
label_view(const label_view&) = default;
label_view& operator=(const label_view&) = default;
/// @pre `key` matches the regex `[a-zA-Z_:][a-zA-Z0-9_:]*`
label_view(string_view name, string_view value) : name_(name), value_(value) {
// nop
}
// -- properties -------------------------------------------------------------
string_view name() const noexcept {
return name_;
}
string_view value() const noexcept {
return value_;
}
// -- comparison -------------------------------------------------------------
int compare(const label& x) const noexcept;
int compare(const label_view& x) const noexcept;
private:
string_view name_;
string_view value_;
};
/// Returns the @ref label_view in `name=value` notation.
/// @relates label_view
CAF_CORE_EXPORT std::string to_string(const label_view& x);
} // namespace caf::telemetry
namespace std {
template <>
struct hash<caf::telemetry::label_view> {
size_t operator()(const caf::telemetry::label_view& x) const noexcept {
return caf::hash::fnv<size_t>::compute(x.name(), '=', x.value());
}
};
} // namespace std
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2020 Dominik Charousset *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#pragma once
#include <string>
#include <utility>
#include <vector>
#include "caf/fwd.hpp"
#include "caf/string_view.hpp"
#include "caf/telemetry/label.hpp"
namespace caf::telemetry {
/// A single metric, identified by the values it sets for the label dimensions.
class CAF_CORE_EXPORT metric {
public:
// -- constructors, destructors, and assignment operators --------------------
metric(std::vector<label> labels) : labels_(std::move(labels)) {
// nop
}
virtual ~metric();
// -- properties -------------------------------------------------------------
const auto& labels() const noexcept {
return labels_;
}
private:
// -- member variables -------------------------------------------------------
std::vector<label> labels_;
};
} // namespace caf::telemetry
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2020 Dominik Charousset *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#pragma once
#include <memory>
#include <string>
#include <vector>
#include "caf/detail/core_export.hpp"
#include "caf/fwd.hpp"
namespace caf::telemetry {
/// Manages a collection (family) of metrics. All children share the same
/// prefix, name, and label dimensions.
class CAF_CORE_EXPORT metric_family {
public:
// -- constructors, destructors, and assignment operators --------------------
metric_family(std::string prefix, std::string name,
std::vector<std::string> label_names, std::string helptext)
: prefix_(std::move(prefix)),
name_(std::move(name)),
label_names_(std::move(label_names)),
helptext_(std::move(helptext)) {
// nop
}
virtual ~metric_family();
// -- properties -------------------------------------------------------------
const auto& prefix() const noexcept {
return prefix_;
}
const auto& name() const noexcept {
return name_;
}
const auto& label_names() const noexcept {
return label_names_;
}
const auto& helptext() const noexcept {
return helptext_;
}
virtual void scrape() = 0;
private:
std::string prefix_;
std::string name_;
std::vector<std::string> label_names_;
std::string helptext_;
};
} // namespace caf::telemetry
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2020 Dominik Charousset *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#pragma once
#include <algorithm>
#include <memory>
#include <mutex>
#include "caf/telemetry/label.hpp"
#include "caf/telemetry/label_view.hpp"
#include "caf/telemetry/metric.hpp"
#include "caf/telemetry/metric_family.hpp"
#include "caf/telemetry/metric_impl.hpp"
namespace caf::telemetry {
template <class Type>
class metric_family_impl : public metric_family {
public:
using metric_type = metric_impl<Type>;
using metric_family::metric_family;
Type* get_or_add(const std::vector<label_view>& labels) {
auto has_label_values = [&labels](const auto& metric_ptr) {
const auto& metric_labels = metric_ptr->labels();
for (size_t index = 0; index < labels.size(); ++index)
if (labels[index].value() != metric_labels[index].value())
return false;
return true;
};
std::unique_lock<std::mutex> guard{mx_};
auto m = std::find_if(metrics_.begin(), metrics_.end(), has_label_values);
if (m == metrics_.end()) {
std::vector<label> cpy{labels.begin(), labels.end()};
m = metrics_.emplace(m, std::make_unique<metric_type>(std::move(cpy)));
}
return std::addressof(m->get()->impl());
}
void scrape() override {
// nop
}
private:
std::mutex mx_;
std::vector<std::unique_ptr<metric_type>> metrics_;
};
} // namespace caf::telemetry
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2020 Dominik Charousset *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#pragma once
#include <string>
#include <utility>
#include <vector>
#include "caf/fwd.hpp"
#include "caf/telemetry/label.hpp"
#include "caf/telemetry/metric.hpp"
namespace caf::telemetry {
template <class Type>
class metric_impl : public metric {
public:
template <class... Ts>
metric_impl(std::vector<label> labels, Ts&&... xs)
: metric(std::move(labels)), impl_(std::forward<Ts>(xs)...) {
// nop
}
Type& impl() noexcept {
return impl_;
}
const Type& impl() const noexcept {
return impl_;
}
private:
Type impl_;
};
} // namespace caf::telemetry
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2020 Dominik Charousset *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#pragma once
#include <map>
#include <memory>
#include <mutex>
#include "caf/detail/core_export.hpp"
#include "caf/fwd.hpp"
#include "caf/string_view.hpp"
namespace caf::telemetry {
/// Manages a collection of metric families.
class CAF_CORE_EXPORT metric_registry {
public:
metric_registry();
~metric_registry();
void add_family(metric_type type, std::string prefix, std::string name,
std::vector<std::string> label_names, std::string helptext);
telemetry::int_gauge* int_gauge(string_view prefix, string_view name,
std::vector<label_view> labels);
private:
void add_int_gauge_family(std::string prefix, std::string name,
std::vector<std::string> label_names,
std::string helptext);
template <class Type>
using metric_family_ptr = std::unique_ptr<metric_family_impl<Type>>;
std::vector<metric_family_ptr<telemetry::int_gauge>> int_gauges;
};
} // namespace caf::telemetry
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2020 Dominik Charousset *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#pragma once
namespace caf::telemetry {
enum class metric_type : uint8_t {
int_gauge,
};
} // namespace caf::telemetry
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2020 Dominik Charousset *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#include "caf/telemetry/label.hpp"
#include "caf/telemetry/label_view.hpp"
namespace caf::telemetry {
label::label(string_view name, string_view value) : name_length_(name.size()) {
str_.reserve(name.size() + value.size() + 1);
str_.insert(str_.end(), name.begin(), name.end());
str_ += '=';
str_.insert(str_.end(), value.begin(), value.end());
}
label::label(const label_view& view) : label(view.name(), view.value()) {
// nop
}
int label::compare(const label& x) const noexcept {
return str_.compare(x.str());
}
std::string to_string(const label& x) {
return x.str();
}
} // namespace caf::telemetry
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2020 Dominik Charousset *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#include "caf/telemetry/label_view.hpp"
#include "caf/telemetry/label.hpp"
namespace caf::telemetry {
int label_view::compare(const label_view& x) const noexcept {
auto cmp1 = name().compare(x.name());
return cmp1 != 0 ? cmp1 : value().compare(x.value());
}
int label_view::compare(const label& x) const noexcept {
auto cmp1 = name().compare(x.name());
return cmp1 != 0 ? cmp1 : value().compare(x.value());
}
std::string to_string(const label_view& x) {
std::string result;
result.reserve(x.name().size() + 1 + x.value().size());
result.insert(result.end(), x.name().begin(), x.name().end());
result += '=';
result.insert(result.end(), x.value().begin(), x.value().end());
return result;
}
} // namespace caf::telemetry
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2020 Dominik Charousset *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#include "caf/telemetry/metric.hpp"
#include "caf/config.hpp"
#include "caf/telemetry/metric_family.hpp"
namespace caf::telemetry {
metric::~metric() {
// nop
}
} // namespace caf::telemetry
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2020 Dominik Charousset *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#include "caf/telemetry/metric_family.hpp"
namespace caf::telemetry {
metric_family::~metric_family() {
// nop
}
} // namespace caf::telemetry
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2020 Dominik Charousset *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#include "caf/telemetry/metric_registry.hpp"
#include "caf/config.hpp"
#include "caf/telemetry/int_gauge.hpp"
#include "caf/telemetry/metric_family_impl.hpp"
#include "caf/telemetry/metric_impl.hpp"
#include "caf/telemetry/metric_type.hpp"
namespace caf::telemetry {
metric_registry::metric_registry() {
// nop
}
metric_registry::~metric_registry() {
// nop
}
telemetry::int_gauge*
metric_registry::int_gauge(string_view prefix, string_view name,
std::vector<label_view> labels) {
// Make sure labels are sorted by name.
auto cmp = [](const label_view& x, const label_view& y) {
return x.name() < y.name();
};
std::sort(labels.begin(), labels.end(), cmp);
// Fetch the family.
auto matches = [&](const auto& family) {
auto lbl_cmp = [](const label_view& lbl, string_view name) {
return lbl.name() == name;
};
return family->prefix() == prefix && family->name() == name
&& std::equal(labels.begin(), labels.end(),
family->label_names().begin(),
family->label_names().end(), lbl_cmp);
};
auto i = std::find_if(int_gauges.begin(), int_gauges.end(), matches);
if (i == int_gauges.end()) {
return nullptr;
}
return (*i)->get_or_add(labels);
}
void metric_registry::add_int_gauge_family(std::string prefix, std::string name,
std::vector<std::string> label_names,
std::string helptext) {
using family_type = metric_family_impl<telemetry::int_gauge>;
std::sort(label_names.begin(), label_names.end());
auto ptr = std::make_unique<family_type>(std::move(prefix), std::move(name),
std::move(label_names),
std::move(helptext));
int_gauges.emplace_back(std::move(ptr));
}
void metric_registry::add_family(metric_type type, std::string prefix,
std::string name,
std::vector<std::string> label_names,
std::string helptext) {
switch (type) {
case metric_type::int_gauge:
return add_int_gauge_family(std::move(prefix), std::move(name),
std::move(label_names), std::move(helptext));
default:
break;
}
}
} // namespace caf::telemetry
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2020 Dominik Charousset *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#define CAF_SUITE telemetry.int_gauge
#include "caf/telemetry/int_gauge.hpp"
#include "caf/test/dsl.hpp"
using namespace caf;
CAF_TEST(integer gauges can increment and decrement) {
telemetry::int_gauge g;
CAF_MESSAGE("gauges start at 0");
CAF_CHECK_EQUAL(g.value(), 0);
CAF_MESSAGE("gauges are incrementable");
g.increment();
g.increment(2);
CAF_CHECK_EQUAL(g.value(), 3);
CAF_MESSAGE("gauges are decrementable");
g.decrement();
g.decrement(5);
CAF_CHECK_EQUAL(g.value(), -3);
CAF_MESSAGE("gauges allow setting values");
g.value(42);
CAF_CHECK_EQUAL(g.value(), 42);
CAF_MESSAGE("users can create gauges with custom start values");
CAF_CHECK_EQUAL(telemetry::int_gauge{42}.value(), 42);
}
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2020 Dominik Charousset *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#define CAF_SUITE telemetry.label
#include "caf/telemetry/label.hpp"
#include "caf/test/dsl.hpp"
#include "caf/telemetry/label_view.hpp"
using namespace caf;
using namespace caf::telemetry;
namespace {
template <class T>
size_t hash(const T& x) {
std::hash<T> f;
return f(x);
}
} // namespace
CAF_TEST(labels wrap name and value) {
CAF_CHECK_EQUAL(to_string(label{"foo", "bar"}), "foo=bar");
label foobar{"foo", "bar"};
CAF_CHECK_EQUAL(foobar.name(), "foo");
CAF_CHECK_EQUAL(foobar.value(), "bar");
CAF_CHECK_EQUAL(foobar.str(), "foo=bar");
CAF_CHECK_EQUAL(to_string(foobar), "foo=bar");
CAF_CHECK_EQUAL(foobar, label("foo", "bar"));
CAF_CHECK_EQUAL(hash(foobar), hash(label("foo", "bar")));
}
CAF_TEST(labels are convertible from views) {
label foobar{"foo", "bar"};
label_view foobar_view{"foo", "bar"};
CAF_CHECK_EQUAL(foobar, foobar_view);
CAF_CHECK_EQUAL(foobar, label{foobar_view});
CAF_CHECK_EQUAL(foobar.name(), foobar_view.name());
CAF_CHECK_EQUAL(foobar.value(), foobar_view.value());
CAF_CHECK_EQUAL(to_string(foobar), to_string(foobar_view));
CAF_CHECK_EQUAL(hash(foobar), hash(foobar_view));
CAF_CHECK_EQUAL(hash(foobar), hash(label{foobar_view}));
}
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2020 Dominik Charousset *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#define CAF_SUITE telemetry.metric_registry
#include "caf/telemetry/metric_registry.hpp"
#include "caf/test/dsl.hpp"
#include "caf/string_view.hpp"
#include "caf/telemetry/int_gauge.hpp"
#include "caf/telemetry/label_view.hpp"
#include "caf/telemetry/metric_type.hpp"
using namespace caf;
using namespace caf::telemetry;
namespace {
struct fixture {
metric_registry registry;
auto bind(string_view prefix, string_view name) {
struct bound {
fixture* self_;
string_view prefix_;
string_view name_;
auto int_gauge(std::vector<label_view> labels) {
return self_->registry.int_gauge(prefix_, name_, std::move(labels));
}
};
return bound{this, prefix, name};
}
};
} // namespace
CAF_TEST_FIXTURE_SCOPE(metric_registry_tests, fixture)
CAF_TEST(registries lazily create metrics) {
registry.add_family(metric_type::int_gauge, "caf", "running_actors",
{"var1", "var2"},
"How many actors are currently running?");
auto var = bind("caf", "running_actors");
std::vector<label_view> v1{{"var1", "foo"}, {"var2", "bar"}};
std::vector<label_view> v1_reversed{{"var2", "bar"}, {"var1", "foo"}};
std::vector<label_view> v2{{"var1", "bar"}, {"var2", "foo"}};
std::vector<label_view> v2_reversed{{"var2", "foo"}, {"var1", "bar"}};
var.int_gauge(v1)->value(42);
var.int_gauge(v2)->value(23);
CAF_CHECK_EQUAL(var.int_gauge(v1)->value(), 42);
CAF_CHECK_EQUAL(var.int_gauge(v1_reversed)->value(), 42);
CAF_CHECK_EQUAL(var.int_gauge(v2)->value(), 23);
CAF_CHECK_EQUAL(var.int_gauge(v2_reversed)->value(), 23);
}
CAF_TEST_FIXTURE_SCOPE_END()
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment