Program Listing for File register_with_sink.hpp
↰ Return to documentation for file (rcppsw/metrics/register_with_sink.hpp)
#pragma once
/*******************************************************************************
* Includes
******************************************************************************/
#include <string>
#include <utility>
#include <tuple>
#include "rcppsw/rcppsw.hpp"
#include "rcppsw/er/client.hpp"
#include "rcppsw/metrics/base_manager.hpp"
#include "rcppsw/metrics/creatable_collector_set.hpp"
#include "rcppsw/abi/abi.hpp"
/*******************************************************************************
* Namespaces/Decls
******************************************************************************/
namespace rcppsw::metrics {
/*******************************************************************************
* Class Definitions
******************************************************************************/
template <typename TMetricsManager,
typename TSinkMixin,
typename TExtraArgsType = void>
class register_with_sink : public rer::client<
register_with_sink<TMetricsManager,
TSinkMixin,
TExtraArgsType>
>,
public TSinkMixin {
public:
template<typename T>
using no_extra_args = typename std::is_same<T, void>;
using extra_args_type = typename std::conditional<
std::is_same<TExtraArgsType, void>::value,
std::tuple<int>,
TExtraArgsType>::type;
register_with_sink(TMetricsManager* const manager,
const creatable_collector_set& set,
const extra_args_type& extra_args = {})
: ER_CLIENT_INIT(),
mc_create_set(set),
m_extra_args(extra_args),
m_manager(manager) {}
register_with_sink& operator=(const register_with_sink&) = default;
register_with_sink(const register_with_sink&) = default;
template <typename TSinkTypeWrapped, typename TConfig>
void operator()(const TSinkTypeWrapped&, const TConfig* config) {
using TSinkType = typename TSinkTypeWrapped::type;
using TCollectorType = typename TSinkType::collector_type;
std::type_index collector_id(typeid(TCollectorType));
std::type_index sink_id(typeid(TSinkType));
auto key = creatable_collector_spec{ collector_id };
auto range = creatable_set().equal_range(key);
ER_ASSERT(std::distance(range.first, range.second) > 0,
"Unknown collector %s: not in creatable set?",
rabi::demangle(collector_id.name()));
ER_DEBUG("%zu %s instances configured",
std::distance(range.first, range.second),
rabi::demangle(collector_id.name()));
/*
* Multiple collectors of the same type can be registered as different
* scoped/runtime names, so we need to iterate.
*/
for (auto it = range.first; it != range.second; ++it) {
/*
* Avoid duplicate registration if the same collector is used with
* multiple sinks.
*/
if (it->sink_id != sink_id) {
continue;
}
auto spec = this->template calc_registration_spec<TSinkType>(
m_manager,
config,
it->input_name,
it->valid_modes);
if (!spec.is_enabled) {
ER_DEBUG("Metrics with xml_name='%s' disabled",
it->input_name.c_str());
continue;
}
this->template emit_diagnostic(it, spec);
auto ret = this->template do_register<TCollectorType, TSinkType>(
it->scoped_name,
std::move(spec));
if (!ret) {
ER_WARN("Collector with scoped_name='%s' already exists!",
it->scoped_name.c_str());
}
} /* for(it..) */
}
protected:
TMetricsManager* manager(void) const { return m_manager; }
const creatable_collector_set& creatable_set(void) const {
return mc_create_set;
}
template <typename TCollector,
typename TSink,
typename U = TExtraArgsType,
RCPPSW_SFINAE_DECLDEF(!no_extra_args<U>::value)>
bool do_register(const std::string& scoped_name,
collector_registration_spec<TSink>&& spec) {
m_manager->collector_preregister(scoped_name, spec.sink->output_mode());
auto extra_args = m_extra_args;
auto lambda = [&](auto&&... args) {
return m_manager->template collector_register<TCollector>(
scoped_name,
std::move(spec.sink),
std::forward<decltype(args)>(args)...);
};
/*
* The std::move() is 100% necessary here, because (I think) types in the
* extra arguments tuple are rvalues, but the values are (probably) lvalues,
* and if you don't do this you get an error regarding rvalue->lvalue
* binding.
*/
return std::apply(lambda, std::move(extra_args));
}
template <typename TCollector,
typename TSink,
typename U = TExtraArgsType,
RCPPSW_SFINAE_DECLDEF(no_extra_args<U>::value)>
bool do_register(const std::string& scoped_name,
collector_registration_spec<TSink>&& spec) {
m_manager->collector_preregister(scoped_name, spec.sink->output_mode());
return m_manager->template collector_register<TCollector>(scoped_name,
std::move(spec.sink));
}
private:
/* clang-format off */
const creatable_collector_set mc_create_set;
extra_args_type m_extra_args;
TMetricsManager* const m_manager;
/* clang-format on */
};
} /* namespace rcppsw::metrics */