|
|
|
@ -14,96 +14,22 @@ namespace llarp
|
|
|
|
|
{
|
|
|
|
|
namespace metrics
|
|
|
|
|
{
|
|
|
|
|
class IntCollector
|
|
|
|
|
template < typename Type >
|
|
|
|
|
class Collector
|
|
|
|
|
{
|
|
|
|
|
const Id m_id;
|
|
|
|
|
size_t m_count GUARDED_BY(m_mutex);
|
|
|
|
|
int64_t m_total GUARDED_BY(m_mutex);
|
|
|
|
|
int m_min GUARDED_BY(m_mutex);
|
|
|
|
|
int m_max GUARDED_BY(m_mutex);
|
|
|
|
|
mutable util::Mutex m_mutex;
|
|
|
|
|
|
|
|
|
|
IntCollector(const IntCollector &) = delete;
|
|
|
|
|
IntCollector &
|
|
|
|
|
operator=(const IntCollector &) = delete;
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
static constexpr int DEFAULT_MIN = std::numeric_limits< int >::max();
|
|
|
|
|
static constexpr int DEFAULT_MAX = std::numeric_limits< int >::min();
|
|
|
|
|
|
|
|
|
|
IntCollector(const Id &id)
|
|
|
|
|
: m_id(id)
|
|
|
|
|
, m_count(0)
|
|
|
|
|
, m_total(0)
|
|
|
|
|
, m_min(DEFAULT_MIN)
|
|
|
|
|
, m_max(DEFAULT_MAX)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const Id &
|
|
|
|
|
id() const
|
|
|
|
|
{
|
|
|
|
|
return m_id;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
clear()
|
|
|
|
|
{
|
|
|
|
|
absl::WriterMutexLock l(&m_mutex);
|
|
|
|
|
m_count = 0;
|
|
|
|
|
m_total = 0;
|
|
|
|
|
m_min = DEFAULT_MIN;
|
|
|
|
|
m_max = DEFAULT_MAX;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Record
|
|
|
|
|
loadAndClear();
|
|
|
|
|
|
|
|
|
|
Record
|
|
|
|
|
load();
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
tick(int value)
|
|
|
|
|
{
|
|
|
|
|
absl::WriterMutexLock l(&m_mutex);
|
|
|
|
|
m_count++;
|
|
|
|
|
m_total += value;
|
|
|
|
|
m_min = std::min(m_min, value);
|
|
|
|
|
m_max = std::max(m_max, value);
|
|
|
|
|
}
|
|
|
|
|
using RecordType = Record< Type >;
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
accumulate(size_t count, int total, int min, int max)
|
|
|
|
|
{
|
|
|
|
|
absl::WriterMutexLock l(&m_mutex);
|
|
|
|
|
m_count += count;
|
|
|
|
|
m_total += total;
|
|
|
|
|
m_min = std::min(m_min, min);
|
|
|
|
|
m_max = std::max(m_max, max);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
set(size_t count, int total, int min, int max)
|
|
|
|
|
{
|
|
|
|
|
absl::WriterMutexLock l(&m_mutex);
|
|
|
|
|
m_count = count;
|
|
|
|
|
m_total = total;
|
|
|
|
|
m_min = min;
|
|
|
|
|
m_max = max;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class DoubleCollector
|
|
|
|
|
{
|
|
|
|
|
Record m_record GUARDED_BY(m_mutex);
|
|
|
|
|
private:
|
|
|
|
|
RecordType m_record GUARDED_BY(m_mutex);
|
|
|
|
|
mutable util::Mutex m_mutex;
|
|
|
|
|
|
|
|
|
|
DoubleCollector(const DoubleCollector &) = delete;
|
|
|
|
|
DoubleCollector &
|
|
|
|
|
operator=(const DoubleCollector &) = delete;
|
|
|
|
|
Collector(const Collector &) = delete;
|
|
|
|
|
Collector &
|
|
|
|
|
operator=(const Collector &) = delete;
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
DoubleCollector(const Id &id) : m_record(id)
|
|
|
|
|
Collector(const Id &id) : m_record(id)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -111,26 +37,20 @@ namespace llarp
|
|
|
|
|
clear()
|
|
|
|
|
{
|
|
|
|
|
absl::WriterMutexLock l(&m_mutex);
|
|
|
|
|
m_record.count() = 0;
|
|
|
|
|
m_record.total() = 0.0;
|
|
|
|
|
m_record.min() = Record::DEFAULT_MIN;
|
|
|
|
|
m_record.max() = Record::DEFAULT_MAX;
|
|
|
|
|
m_record.clear();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Record
|
|
|
|
|
RecordType
|
|
|
|
|
loadAndClear()
|
|
|
|
|
{
|
|
|
|
|
absl::WriterMutexLock l(&m_mutex);
|
|
|
|
|
Record rec = m_record;
|
|
|
|
|
m_record.count() = 0;
|
|
|
|
|
m_record.total() = 0.0;
|
|
|
|
|
m_record.min() = Record::DEFAULT_MIN;
|
|
|
|
|
m_record.max() = Record::DEFAULT_MAX;
|
|
|
|
|
RecordType rec = m_record;
|
|
|
|
|
m_record.clear();
|
|
|
|
|
|
|
|
|
|
return rec;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Record
|
|
|
|
|
RecordType
|
|
|
|
|
load()
|
|
|
|
|
{
|
|
|
|
|
absl::ReaderMutexLock l(&m_mutex);
|
|
|
|
@ -138,7 +58,7 @@ namespace llarp
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
tick(double value)
|
|
|
|
|
tick(Type value)
|
|
|
|
|
{
|
|
|
|
|
absl::WriterMutexLock l(&m_mutex);
|
|
|
|
|
m_record.count()++;
|
|
|
|
@ -148,7 +68,7 @@ namespace llarp
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
accumulate(size_t count, double total, double min, double max)
|
|
|
|
|
accumulate(size_t count, Type total, Type min, Type max)
|
|
|
|
|
{
|
|
|
|
|
absl::WriterMutexLock l(&m_mutex);
|
|
|
|
|
m_record.count() += count;
|
|
|
|
@ -158,7 +78,7 @@ namespace llarp
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
set(size_t count, double total, double min, double max)
|
|
|
|
|
set(size_t count, Type total, Type min, Type max)
|
|
|
|
|
{
|
|
|
|
|
absl::WriterMutexLock l(&m_mutex);
|
|
|
|
|
m_record.count() = count;
|
|
|
|
@ -175,36 +95,38 @@ namespace llarp
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
using IntCollector = Collector< int >;
|
|
|
|
|
using DoubleCollector = Collector< double >;
|
|
|
|
|
|
|
|
|
|
class Publisher
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
virtual ~Publisher() = 0;
|
|
|
|
|
virtual ~Publisher() = default;
|
|
|
|
|
|
|
|
|
|
virtual void
|
|
|
|
|
publish(const Sample &sample) = 0;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
inline Publisher::~Publisher()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template < typename LhsType, typename RhsType >
|
|
|
|
|
static inline void
|
|
|
|
|
combine(Record &record, const Record &toAdd)
|
|
|
|
|
combine(Record< LhsType > &record, const Record< RhsType > &toAdd)
|
|
|
|
|
{
|
|
|
|
|
static_assert(std::is_convertible< RhsType, LhsType >::value, "");
|
|
|
|
|
record.id() = toAdd.id();
|
|
|
|
|
record.count() += toAdd.count();
|
|
|
|
|
record.total() += toAdd.total();
|
|
|
|
|
record.min() = std::min(record.min(), toAdd.min());
|
|
|
|
|
record.max() = std::max(record.max(), toAdd.max());
|
|
|
|
|
record.min() = std::min(record.min(), LhsType(toAdd.min()));
|
|
|
|
|
record.max() = std::max(record.max(), LhsType(toAdd.max()));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template < typename Collector >
|
|
|
|
|
template < typename Type >
|
|
|
|
|
class Collectors
|
|
|
|
|
{
|
|
|
|
|
using CollectorPtr = std::shared_ptr< Collector >;
|
|
|
|
|
using CollectorSet = std::set< CollectorPtr >;
|
|
|
|
|
using CollectorType = Collector< Type >;
|
|
|
|
|
using CollectorPtr = std::shared_ptr< CollectorType >;
|
|
|
|
|
using CollectorSet = std::set< CollectorPtr >;
|
|
|
|
|
|
|
|
|
|
Collector m_default;
|
|
|
|
|
CollectorType m_default;
|
|
|
|
|
CollectorSet m_collectors;
|
|
|
|
|
|
|
|
|
|
Collectors(const Collectors &) = delete;
|
|
|
|
@ -216,32 +138,32 @@ namespace llarp
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Collector *
|
|
|
|
|
CollectorType *
|
|
|
|
|
defaultCollector()
|
|
|
|
|
{
|
|
|
|
|
return &m_default;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::shared_ptr< Collector >
|
|
|
|
|
std::shared_ptr< CollectorType >
|
|
|
|
|
add()
|
|
|
|
|
{
|
|
|
|
|
auto ptr = std::make_shared< Collector >(m_default.id());
|
|
|
|
|
auto ptr = std::make_shared< CollectorType >(m_default.id());
|
|
|
|
|
m_collectors.insert(ptr);
|
|
|
|
|
return ptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
remove(Collector *collector)
|
|
|
|
|
remove(CollectorType *collector)
|
|
|
|
|
{
|
|
|
|
|
std::shared_ptr< Collector > ptr(collector, [](Collector *) {});
|
|
|
|
|
std::shared_ptr< CollectorType > ptr(collector, [](CollectorType *) {});
|
|
|
|
|
size_t count = m_collectors.erase(ptr);
|
|
|
|
|
return count > 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Record
|
|
|
|
|
Record< Type >
|
|
|
|
|
combineAndClear()
|
|
|
|
|
{
|
|
|
|
|
Record rec = m_default.loadAndClear();
|
|
|
|
|
Record< Type > rec = m_default.loadAndClear();
|
|
|
|
|
|
|
|
|
|
for(auto &ptr : m_collectors)
|
|
|
|
|
{
|
|
|
|
@ -251,10 +173,10 @@ namespace llarp
|
|
|
|
|
return rec;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Record
|
|
|
|
|
Record< Type >
|
|
|
|
|
combine()
|
|
|
|
|
{
|
|
|
|
|
Record rec = m_default.load();
|
|
|
|
|
Record< Type > rec = m_default.load();
|
|
|
|
|
|
|
|
|
|
for(auto &ptr : m_collectors)
|
|
|
|
|
{
|
|
|
|
@ -263,11 +185,11 @@ namespace llarp
|
|
|
|
|
return rec;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::vector< std::shared_ptr< Collector > >
|
|
|
|
|
std::vector< std::shared_ptr< CollectorType > >
|
|
|
|
|
collectors() const
|
|
|
|
|
{
|
|
|
|
|
return std::vector< std::shared_ptr< Collector > >(m_collectors.begin(),
|
|
|
|
|
m_collectors.end());
|
|
|
|
|
return std::vector< std::shared_ptr< CollectorType > >(
|
|
|
|
|
m_collectors.begin(), m_collectors.end());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const Id &
|
|
|
|
@ -277,70 +199,8 @@ namespace llarp
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class MetricCollectors
|
|
|
|
|
{
|
|
|
|
|
using DoubleCollectors = Collectors< DoubleCollector >;
|
|
|
|
|
using IntCollectors = Collectors< IntCollector >;
|
|
|
|
|
|
|
|
|
|
DoubleCollectors m_doubleCollectors;
|
|
|
|
|
IntCollectors m_intCollectors;
|
|
|
|
|
|
|
|
|
|
MetricCollectors(const MetricCollectors &) = delete;
|
|
|
|
|
MetricCollectors &
|
|
|
|
|
operator=(const MetricCollectors &) = delete;
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
MetricCollectors(const Id &id)
|
|
|
|
|
: m_doubleCollectors(id), m_intCollectors(id)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Collectors< DoubleCollector > &
|
|
|
|
|
doubleCollectors()
|
|
|
|
|
{
|
|
|
|
|
return m_doubleCollectors;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Collectors< IntCollector > &
|
|
|
|
|
intCollectors()
|
|
|
|
|
{
|
|
|
|
|
return m_intCollectors;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const Collectors< DoubleCollector > &
|
|
|
|
|
doubleCollectors() const
|
|
|
|
|
{
|
|
|
|
|
return m_doubleCollectors;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const Collectors< IntCollector > &
|
|
|
|
|
intCollectors() const
|
|
|
|
|
{
|
|
|
|
|
return m_intCollectors;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Record
|
|
|
|
|
combineAndClear()
|
|
|
|
|
{
|
|
|
|
|
Record res = m_doubleCollectors.combineAndClear();
|
|
|
|
|
metrics::combine(res, m_intCollectors.combineAndClear());
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Record
|
|
|
|
|
combine()
|
|
|
|
|
{
|
|
|
|
|
Record res = m_doubleCollectors.combine();
|
|
|
|
|
metrics::combine(res, m_intCollectors.combine());
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const Id &
|
|
|
|
|
id() const
|
|
|
|
|
{
|
|
|
|
|
return m_intCollectors.id();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
using DoubleCollectors = Collectors< double >;
|
|
|
|
|
using IntCollectors = Collectors< int >;
|
|
|
|
|
|
|
|
|
|
class Registry
|
|
|
|
|
{
|
|
|
|
@ -436,83 +296,163 @@ namespace llarp
|
|
|
|
|
getAll() const;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
using DoubleRecords = std::vector< Record< double > >;
|
|
|
|
|
using IntRecords = std::vector< Record< int > >;
|
|
|
|
|
|
|
|
|
|
struct Records
|
|
|
|
|
{
|
|
|
|
|
DoubleRecords doubleRecords;
|
|
|
|
|
IntRecords intRecords;
|
|
|
|
|
|
|
|
|
|
Records()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Records(const DoubleRecords &d, const IntRecords &i)
|
|
|
|
|
: doubleRecords(d), intRecords(i)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
inline bool
|
|
|
|
|
operator==(const Records &lhs, const Records &rhs)
|
|
|
|
|
{
|
|
|
|
|
return std::tie(lhs.doubleRecords, lhs.intRecords)
|
|
|
|
|
== std::tie(rhs.doubleRecords, rhs.intRecords);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template < typename Type >
|
|
|
|
|
class CollectorRepo
|
|
|
|
|
{
|
|
|
|
|
using MetricCollectorsPtr = std::shared_ptr< MetricCollectors >;
|
|
|
|
|
using IdCollectors = std::map< Id, MetricCollectorsPtr >;
|
|
|
|
|
using CollectorsPtr = std::shared_ptr< Collectors< Type > >;
|
|
|
|
|
using IdCollectors = std::map< Id, CollectorsPtr >;
|
|
|
|
|
using CategoryCollectors =
|
|
|
|
|
std::map< const Category *, std::vector< MetricCollectors * > >;
|
|
|
|
|
std::map< const Category *, std::vector< Collectors< Type > * > >;
|
|
|
|
|
|
|
|
|
|
Registry *m_registry;
|
|
|
|
|
IdCollectors m_collectors;
|
|
|
|
|
CategoryCollectors m_categories;
|
|
|
|
|
|
|
|
|
|
mutable util::Mutex m_mutex;
|
|
|
|
|
|
|
|
|
|
CollectorRepo(const CollectorRepo &) = delete;
|
|
|
|
|
CollectorRepo &
|
|
|
|
|
operator=(const CollectorRepo &) = delete;
|
|
|
|
|
|
|
|
|
|
MetricCollectors &
|
|
|
|
|
getCollectors(const Id &id);
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
CollectorRepo(Registry *registry) : m_registry(registry)
|
|
|
|
|
Collectors< Type > &
|
|
|
|
|
getCollectors(const Id &id)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
auto it = m_collectors.find(id);
|
|
|
|
|
|
|
|
|
|
if(it == m_collectors.end())
|
|
|
|
|
{
|
|
|
|
|
assert(id.valid());
|
|
|
|
|
|
|
|
|
|
std::vector< Record >
|
|
|
|
|
collectAndClear(const Category *category);
|
|
|
|
|
const Category *cat = id.category();
|
|
|
|
|
|
|
|
|
|
std::vector< Record >
|
|
|
|
|
collect(const Category *category);
|
|
|
|
|
auto ptr = std::make_shared< Collectors< Type > >(id);
|
|
|
|
|
auto &vec = m_categories[cat];
|
|
|
|
|
vec.reserve(vec.size() + 1);
|
|
|
|
|
|
|
|
|
|
DoubleCollector *
|
|
|
|
|
defaultDoubleCollector(const char *category, const char *name)
|
|
|
|
|
it = m_collectors.emplace(id, ptr).first;
|
|
|
|
|
vec.push_back(ptr.get());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return *it->second.get();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template < Record< Type > (Collectors< Type >::*func)() >
|
|
|
|
|
std::vector< Record< Type > >
|
|
|
|
|
collectOp(const Category *category)
|
|
|
|
|
{
|
|
|
|
|
return defaultDoubleCollector(m_registry->get(category, name));
|
|
|
|
|
absl::WriterMutexLock l(&m_mutex);
|
|
|
|
|
|
|
|
|
|
auto it = m_categories.find(category);
|
|
|
|
|
|
|
|
|
|
if(it == m_categories.end())
|
|
|
|
|
{
|
|
|
|
|
return {};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::vector< Record< Type > > result;
|
|
|
|
|
auto &collectors = it->second;
|
|
|
|
|
result.reserve(collectors.size());
|
|
|
|
|
|
|
|
|
|
std::transform(collectors.begin(), collectors.end(),
|
|
|
|
|
std::back_inserter(result),
|
|
|
|
|
[](auto &collector) { return (collector->*func)(); });
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DoubleCollector *
|
|
|
|
|
defaultDoubleCollector(const Id &id);
|
|
|
|
|
public:
|
|
|
|
|
explicit CollectorRepo(Registry *registry) : m_registry(registry)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
IntCollector *
|
|
|
|
|
defaultIntCollector(const char *category, const char *name)
|
|
|
|
|
std::vector< Record< Type > >
|
|
|
|
|
collectAndClear(const Category *category)
|
|
|
|
|
{
|
|
|
|
|
return defaultIntCollector(m_registry->get(category, name));
|
|
|
|
|
return collectOp< &Collectors< Type >::combineAndClear >(category);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
IntCollector *
|
|
|
|
|
defaultIntCollector(const Id &id);
|
|
|
|
|
std::vector< Record< Type > >
|
|
|
|
|
collect(const Category *category)
|
|
|
|
|
{
|
|
|
|
|
return collectOp< &Collectors< Type >::combine >(category);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::shared_ptr< DoubleCollector >
|
|
|
|
|
addDoubleCollector(const char *category, const char *name)
|
|
|
|
|
Collector< Type > *
|
|
|
|
|
defaultCollector(const char *category, const char *name)
|
|
|
|
|
{
|
|
|
|
|
return addDoubleCollector(m_registry->get(category, name));
|
|
|
|
|
return defaultCollector(m_registry->get(category, name));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::shared_ptr< DoubleCollector >
|
|
|
|
|
addDoubleCollector(const Id &id)
|
|
|
|
|
Collector< Type > *
|
|
|
|
|
defaultCollector(const Id &id)
|
|
|
|
|
{
|
|
|
|
|
absl::WriterMutexLock l(&m_mutex);
|
|
|
|
|
return getCollectors(id).doubleCollectors().add();
|
|
|
|
|
{
|
|
|
|
|
absl::ReaderMutexLock l(&m_mutex);
|
|
|
|
|
auto it = m_collectors.find(id);
|
|
|
|
|
if(it != m_collectors.end())
|
|
|
|
|
{
|
|
|
|
|
return it->second->defaultCollector();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
absl::WriterMutexLock l(&m_mutex);
|
|
|
|
|
return getCollectors(id).defaultCollector();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::shared_ptr< IntCollector >
|
|
|
|
|
addIntCollector(const char *category, const char *name)
|
|
|
|
|
std::shared_ptr< Collector< Type > >
|
|
|
|
|
addCollector(const char *category, const char *name)
|
|
|
|
|
{
|
|
|
|
|
return addIntCollector(m_registry->get(category, name));
|
|
|
|
|
return addCollector(m_registry->get(category, name));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::shared_ptr< IntCollector >
|
|
|
|
|
addIntCollector(const Id &id)
|
|
|
|
|
std::shared_ptr< Collector< Type > >
|
|
|
|
|
addCollector(const Id &id)
|
|
|
|
|
{
|
|
|
|
|
absl::WriterMutexLock l(&m_mutex);
|
|
|
|
|
return getCollectors(id).intCollectors().add();
|
|
|
|
|
return getCollectors(id).add();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::pair< std::vector< std::shared_ptr< DoubleCollector > >,
|
|
|
|
|
std::vector< std::shared_ptr< IntCollector > > >
|
|
|
|
|
allCollectors(const Id &id);
|
|
|
|
|
std::vector< std::shared_ptr< Collector< Type > > >
|
|
|
|
|
allCollectors(const Id &id)
|
|
|
|
|
{
|
|
|
|
|
absl::ReaderMutexLock l(&m_mutex);
|
|
|
|
|
|
|
|
|
|
auto it = m_collectors.find(id);
|
|
|
|
|
|
|
|
|
|
if(it == m_collectors.end())
|
|
|
|
|
{
|
|
|
|
|
return {};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return it->second->collectors();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Registry &
|
|
|
|
|
registry()
|
|
|
|
@ -677,91 +617,6 @@ namespace llarp
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class CallbackRegistry
|
|
|
|
|
{
|
|
|
|
|
using Handle = uint64_t;
|
|
|
|
|
using RecordCallback = std::function< std::vector< Record >(bool) >;
|
|
|
|
|
using CallbackMap = std::multimap< const Category *, RecordCallback >;
|
|
|
|
|
using HandleMap = std::map< Handle, CallbackMap::iterator >;
|
|
|
|
|
|
|
|
|
|
Handle m_next;
|
|
|
|
|
CallbackMap m_callbackMap;
|
|
|
|
|
HandleMap m_handleMap;
|
|
|
|
|
|
|
|
|
|
CallbackRegistry(const CallbackRegistry &) = delete;
|
|
|
|
|
CallbackRegistry &
|
|
|
|
|
operator=(const CallbackRegistry &) = delete;
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
using iterator = CallbackMap::iterator;
|
|
|
|
|
|
|
|
|
|
CallbackRegistry() : m_next(1)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Handle
|
|
|
|
|
registerCallback(const Category *category, const RecordCallback &callback)
|
|
|
|
|
{
|
|
|
|
|
Handle handle = m_next++;
|
|
|
|
|
|
|
|
|
|
auto it = m_callbackMap.emplace(category, callback);
|
|
|
|
|
m_handleMap.emplace(handle, it);
|
|
|
|
|
|
|
|
|
|
return handle;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
removeCallback(Handle handle)
|
|
|
|
|
{
|
|
|
|
|
auto it = m_handleMap.find(handle);
|
|
|
|
|
|
|
|
|
|
if(it == m_handleMap.end())
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m_callbackMap.erase(it->second);
|
|
|
|
|
m_handleMap.erase(it);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
iterator
|
|
|
|
|
begin()
|
|
|
|
|
{
|
|
|
|
|
return m_callbackMap.begin();
|
|
|
|
|
}
|
|
|
|
|
iterator
|
|
|
|
|
end()
|
|
|
|
|
{
|
|
|
|
|
return m_callbackMap.end();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
iterator
|
|
|
|
|
lowerBound(const Category *category)
|
|
|
|
|
{
|
|
|
|
|
return m_callbackMap.lower_bound(category);
|
|
|
|
|
}
|
|
|
|
|
iterator
|
|
|
|
|
upperBound(const Category *category)
|
|
|
|
|
{
|
|
|
|
|
return m_callbackMap.upper_bound(category);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::vector< const RecordCallback * >
|
|
|
|
|
callbacksFor(const Category *category) const
|
|
|
|
|
{
|
|
|
|
|
std::vector< const RecordCallback * > result;
|
|
|
|
|
auto beg = m_callbackMap.lower_bound(category);
|
|
|
|
|
auto end = m_callbackMap.upper_bound(category);
|
|
|
|
|
|
|
|
|
|
result.reserve(std::distance(beg, end));
|
|
|
|
|
std::transform(beg, end, std::back_inserter(result),
|
|
|
|
|
[](const auto &x) { return &x.second; });
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct PublisherHelper;
|
|
|
|
|
|
|
|
|
|
/// The big dog.
|
|
|
|
@ -772,8 +627,6 @@ namespace llarp
|
|
|
|
|
public:
|
|
|
|
|
// Public callback. If the bool flag is true, clear the metrics back to
|
|
|
|
|
// their default state.
|
|
|
|
|
using RecordCallback = std::function< std::vector< Record >(bool) >;
|
|
|
|
|
|
|
|
|
|
using Handle = uint64_t;
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
@ -783,8 +636,8 @@ namespace llarp
|
|
|
|
|
friend struct PublisherHelper;
|
|
|
|
|
|
|
|
|
|
Registry m_registry;
|
|
|
|
|
CollectorRepo m_repo;
|
|
|
|
|
CallbackRegistry m_callbacks GUARDED_BY(m_mutex);
|
|
|
|
|
CollectorRepo< double > m_doubleRepo;
|
|
|
|
|
CollectorRepo< int > m_intRepo;
|
|
|
|
|
PublisherRegistry m_publishers GUARDED_BY(m_mutex);
|
|
|
|
|
|
|
|
|
|
const absl::Duration m_createTime;
|
|
|
|
@ -798,30 +651,12 @@ namespace llarp
|
|
|
|
|
std::numeric_limits< Handle >::max();
|
|
|
|
|
|
|
|
|
|
Manager()
|
|
|
|
|
: m_repo(&m_registry), m_createTime(absl::Now() - absl::UnixEpoch())
|
|
|
|
|
: m_doubleRepo(&m_registry)
|
|
|
|
|
, m_intRepo(&m_registry)
|
|
|
|
|
, m_createTime(absl::Now() - absl::UnixEpoch())
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Register a callback for
|
|
|
|
|
Handle
|
|
|
|
|
registerCallback(const char *categoryName, const RecordCallback &callback)
|
|
|
|
|
{
|
|
|
|
|
return registerCallback(m_registry.get(categoryName), callback);
|
|
|
|
|
}
|
|
|
|
|
Handle
|
|
|
|
|
registerCallback(const Category *category, const RecordCallback &callback)
|
|
|
|
|
{
|
|
|
|
|
absl::WriterMutexLock l(&m_mutex);
|
|
|
|
|
return m_callbacks.registerCallback(category, callback);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
removeCallback(Handle handle)
|
|
|
|
|
{
|
|
|
|
|
absl::WriterMutexLock l(&m_mutex);
|
|
|
|
|
return m_callbacks.removeCallback(handle);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Add a `publisher` which will receive all events
|
|
|
|
|
bool
|
|
|
|
|
addGlobalPublisher(const std::shared_ptr< Publisher > &publisher)
|
|
|
|
@ -862,23 +697,23 @@ namespace llarp
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// clang-format off
|
|
|
|
|
CollectorRepo& collectorRepo() { return m_repo; }
|
|
|
|
|
const CollectorRepo& collectorRepo() const { return m_repo; }
|
|
|
|
|
CollectorRepo<double>& doubleCollectorRepo() { return m_doubleRepo; }
|
|
|
|
|
CollectorRepo<int>& intCollectorRepo() { return m_intRepo; }
|
|
|
|
|
Registry& registry() { return m_registry; }
|
|
|
|
|
const Registry& registry() const { return m_registry; }
|
|
|
|
|
// clang-format on
|
|
|
|
|
|
|
|
|
|
/// Publish specific categories of metric matching the category/categories
|
|
|
|
|
Sample
|
|
|
|
|
collectSample(std::vector< Record > &records, bool clear = false)
|
|
|
|
|
collectSample(Records &records, bool clear = false)
|
|
|
|
|
{
|
|
|
|
|
std::vector< const Category * > allCategories = m_registry.getAll();
|
|
|
|
|
return collectSample(
|
|
|
|
|
records, absl::Span< const Category * >{allCategories}, clear);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Sample
|
|
|
|
|
collectSample(std::vector< Record > &records,
|
|
|
|
|
absl::Span< const Category * > categories,
|
|
|
|
|
collectSample(Records &records, absl::Span< const Category * > categories,
|
|
|
|
|
bool clear = false);
|
|
|
|
|
|
|
|
|
|
/// Publish specific categories of metric matching the category/categories
|
|
|
|
@ -1026,8 +861,7 @@ namespace llarp
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template < typename Collector, typename Value,
|
|
|
|
|
Collector *(CollectorRepo::*catFunc)(const char *, const char *),
|
|
|
|
|
Collector *(CollectorRepo::*idFunc)(const Id &) >
|
|
|
|
|
CollectorRepo< Value > &(Manager::*repoFunc)() >
|
|
|
|
|
class Metric
|
|
|
|
|
{
|
|
|
|
|
Collector *m_collector; // can be null
|
|
|
|
@ -1038,7 +872,7 @@ namespace llarp
|
|
|
|
|
lookup(const char *category, const char *name, Manager *manager = nullptr)
|
|
|
|
|
{
|
|
|
|
|
manager = DefaultManager::manager(manager);
|
|
|
|
|
return manager ? (manager->collectorRepo().*catFunc)(category, name)
|
|
|
|
|
return manager ? (manager->*repoFunc)().defaultCollector(category, name)
|
|
|
|
|
: 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -1046,7 +880,7 @@ namespace llarp
|
|
|
|
|
lookup(const Id &id, Manager *manager = nullptr)
|
|
|
|
|
{
|
|
|
|
|
manager = DefaultManager::manager(manager);
|
|
|
|
|
return manager ? (manager->collectorRepo().*idFunc)(id) : 0;
|
|
|
|
|
return manager ? (manager->*repoFunc)().defaultCollector(id) : 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Metric(const char *category, const char *name, Manager *manager)
|
|
|
|
@ -1135,7 +969,7 @@ namespace llarp
|
|
|
|
|
const char *category, const char *metric)
|
|
|
|
|
{
|
|
|
|
|
Manager *manager = DefaultManager::instance();
|
|
|
|
|
*collector = manager->collectorRepo().*catFunc(category, metric);
|
|
|
|
|
*collector = (manager->*repoFunc().defaultCollector)(category, metric);
|
|
|
|
|
manager->registry().registerContainer((*collector)->id().category(),
|
|
|
|
|
container);
|
|
|
|
|
}
|
|
|
|
@ -1146,7 +980,7 @@ namespace llarp
|
|
|
|
|
Publication::Type type)
|
|
|
|
|
{
|
|
|
|
|
Manager *manager = DefaultManager::instance();
|
|
|
|
|
*collector = manager->collectorRepo().*catFunc(category, metric);
|
|
|
|
|
*collector = (manager->*repoFunc().defaultCollector)(category, metric);
|
|
|
|
|
manager->registry().registerContainer((*collector)->id().category(),
|
|
|
|
|
container);
|
|
|
|
|
manager->registry().publicationType((*collector)->id(), type);
|
|
|
|
@ -1154,12 +988,9 @@ namespace llarp
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
using DoubleMetric =
|
|
|
|
|
Metric< DoubleCollector, double, &CollectorRepo::defaultDoubleCollector,
|
|
|
|
|
&CollectorRepo::defaultDoubleCollector >;
|
|
|
|
|
Metric< DoubleCollector, double, &Manager::doubleCollectorRepo >;
|
|
|
|
|
|
|
|
|
|
using IntMetric =
|
|
|
|
|
Metric< IntCollector, int, &CollectorRepo::defaultIntCollector,
|
|
|
|
|
&CollectorRepo::defaultIntCollector >;
|
|
|
|
|
using IntMetric = Metric< IntCollector, int, &Manager::intCollectorRepo >;
|
|
|
|
|
|
|
|
|
|
class TimerGuard
|
|
|
|
|
{
|
|
|
|
|