-
Notifications
You must be signed in to change notification settings - Fork 438
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add Synchronous Metric Instruments SDK (#179)
- Loading branch information
1 parent
5298132
commit 3ac89eb
Showing
6 changed files
with
1,029 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,242 @@ | ||
#pragma once | ||
|
||
#include "opentelemetry/metrics/instrument.h" | ||
#include "opentelemetry/sdk/metrics/aggregator/aggregator.h" | ||
#include "opentelemetry/sdk/metrics/record.h" | ||
#include "opentelemetry/version.h" | ||
|
||
#include <iostream> | ||
#include <map> | ||
#include <memory> | ||
#include <sstream> | ||
#include <string> | ||
#include <unordered_map> | ||
#include <vector> | ||
|
||
namespace metrics_api = opentelemetry::metrics; | ||
namespace trace_api = opentelemetry::trace; | ||
|
||
OPENTELEMETRY_BEGIN_NAMESPACE | ||
namespace sdk | ||
{ | ||
namespace metrics | ||
{ | ||
|
||
class Instrument : virtual public metrics_api::Instrument | ||
{ | ||
|
||
public: | ||
Instrument() = default; | ||
|
||
Instrument(nostd::string_view name, | ||
nostd::string_view description, | ||
nostd::string_view unit, | ||
bool enabled, | ||
metrics_api::InstrumentKind kind) | ||
: name_(name), description_(description), unit_(unit), enabled_(enabled), kind_(kind) | ||
{} | ||
|
||
// Returns true if the instrument is enabled and collecting data | ||
virtual bool IsEnabled() override { return enabled_; } | ||
|
||
// Return the instrument name | ||
virtual nostd::string_view GetName() override { return name_; } | ||
|
||
// Return the instrument description | ||
virtual nostd::string_view GetDescription() override { return description_; } | ||
|
||
// Return the insrument's units of measurement | ||
virtual nostd::string_view GetUnits() override { return unit_; } | ||
|
||
virtual metrics_api::InstrumentKind GetKind() override { return this->kind_; } | ||
|
||
protected: | ||
std::string name_; | ||
std::string description_; | ||
std::string unit_; | ||
bool enabled_; | ||
std::mutex mu_; | ||
metrics_api::InstrumentKind kind_; | ||
}; | ||
|
||
template <class T> | ||
class BoundSynchronousInstrument : public Instrument, | ||
virtual public metrics_api::BoundSynchronousInstrument<T> | ||
{ | ||
|
||
public: | ||
BoundSynchronousInstrument() = default; | ||
|
||
BoundSynchronousInstrument(nostd::string_view name, | ||
nostd::string_view description, | ||
nostd::string_view unit, | ||
bool enabled, | ||
metrics_api::InstrumentKind kind, | ||
std::shared_ptr<Aggregator<T>> agg) | ||
: Instrument(name, description, unit, enabled, kind), agg_(agg) | ||
{ | ||
this->inc_ref(); // increase reference count when instantiated | ||
} | ||
|
||
/** | ||
* Frees the resources associated with this Bound Instrument. | ||
* The Metric from which this instrument was created is not impacted. | ||
* | ||
* @param none | ||
* @return void | ||
*/ | ||
virtual void unbind() override { ref_ -= 1; } | ||
|
||
/** | ||
* Increments the reference count. This function is used when binding or instantiating. | ||
* | ||
* @param none | ||
* @return void | ||
*/ | ||
virtual void inc_ref() override { ref_ += 1; } | ||
|
||
/** | ||
* Returns the current reference count of the instrument. This value is used to | ||
* later in the pipeline remove stale instruments. | ||
* | ||
* @param none | ||
* @return current ref count of the instrument | ||
*/ | ||
virtual int get_ref() override { return ref_; } | ||
|
||
/** | ||
* Records a single synchronous metric event via a call to the aggregator. | ||
* Since this is a bound synchronous instrument, labels are not required in | ||
* metric capture calls. | ||
* | ||
* @param value is the numerical representation of the metric being captured | ||
* @return void | ||
*/ | ||
virtual void update(T value) override | ||
{ | ||
this->mu_.lock(); | ||
agg_->update(value); | ||
this->mu_.unlock(); | ||
} | ||
|
||
/** | ||
* Returns the aggregator responsible for meaningfully combining update values. | ||
* | ||
* @param none | ||
* @return the aggregator assigned to this instrument | ||
*/ | ||
virtual std::shared_ptr<Aggregator<T>> GetAggregator() final { return agg_; } | ||
|
||
private: | ||
std::shared_ptr<Aggregator<T>> agg_; | ||
int ref_ = 0; | ||
}; | ||
|
||
template <class T> | ||
class SynchronousInstrument : public Instrument, | ||
virtual public metrics_api::SynchronousInstrument<T> | ||
{ | ||
|
||
public: | ||
SynchronousInstrument() = default; | ||
|
||
SynchronousInstrument(nostd::string_view name, | ||
nostd::string_view description, | ||
nostd::string_view unit, | ||
bool enabled, | ||
metrics_api::InstrumentKind kind) | ||
: Instrument(name, description, unit, enabled, kind) | ||
{} | ||
|
||
/** | ||
* Returns a Bound Instrument associated with the specified labels. Multiples requests | ||
* with the same set of labels may return the same Bound Instrument instance. | ||
* | ||
* It is recommended that callers keep a reference to the Bound Instrument | ||
* instead of repeatedly calling this operation. | ||
* | ||
* @param labels the set of labels, as key-value pairs | ||
* @return a Bound Instrument | ||
*/ | ||
virtual nostd::shared_ptr<metrics_api::BoundSynchronousInstrument<T>> bind( | ||
const trace::KeyValueIterable &labels) override | ||
{ | ||
return nostd::shared_ptr<BoundSynchronousInstrument<T>>(); | ||
} | ||
|
||
virtual void update(T value, const trace::KeyValueIterable &labels) override = 0; | ||
|
||
/** | ||
* Checkpoints instruments and returns a set of records which are ready for processing. | ||
* This method should ONLY be called by the Meter Class as part of the export pipeline | ||
* as it also prunes bound instruments with no active references. | ||
* | ||
* @param none | ||
* @return vector of Records which hold the data attached to this synchronous instrument | ||
*/ | ||
virtual std::vector<Record> GetRecords() = 0; | ||
}; | ||
|
||
// Helper functions for turning a trace::KeyValueIterable into a string | ||
inline void print_value(std::stringstream &ss, | ||
common::AttributeValue &value, | ||
bool jsonTypes = false) | ||
{ | ||
switch (value.index()) | ||
{ | ||
case common::AttributeType::TYPE_STRING: | ||
if (jsonTypes) | ||
ss << '"'; | ||
ss << nostd::get<nostd::string_view>(value); | ||
if (jsonTypes) | ||
ss << '"'; | ||
break; | ||
default: | ||
#if __EXCEPTIONS | ||
throw std::invalid_argument("Labels must be strings"); | ||
#else | ||
std::terminate(); | ||
#endif | ||
break; | ||
} | ||
}; | ||
|
||
// Utility function which converts maps to strings for better performance | ||
inline std::string mapToString(const std::map<std::string, std::string> &conv) | ||
{ | ||
std::stringstream ss; | ||
ss << "{"; | ||
for (auto i : conv) | ||
{ | ||
ss << i.first << ':' << i.second << ','; | ||
} | ||
ss << "}"; | ||
return ss.str(); | ||
} | ||
|
||
inline std::string KvToString(const trace::KeyValueIterable &kv) noexcept | ||
{ | ||
std::stringstream ss; | ||
ss << "{"; | ||
size_t size = kv.size(); | ||
if (size) | ||
{ | ||
size_t i = 1; | ||
kv.ForEachKeyValue([&](nostd::string_view key, common::AttributeValue value) noexcept { | ||
ss << "\"" << key << "\":"; | ||
print_value(ss, value, true); | ||
if (size != i) | ||
{ | ||
ss << ","; | ||
} | ||
i++; | ||
return true; | ||
}); | ||
}; | ||
ss << "}"; | ||
return ss.str(); | ||
} | ||
|
||
} // namespace metrics | ||
} // namespace sdk | ||
OPENTELEMETRY_END_NAMESPACE |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
#pragma once | ||
|
||
#include <memory> | ||
#include "opentelemetry/metrics/instrument.h" | ||
#include "opentelemetry/nostd/variant.h" | ||
#include "opentelemetry/sdk/metrics/aggregator/aggregator.h" | ||
|
||
OPENTELEMETRY_BEGIN_NAMESPACE | ||
|
||
namespace metrics_api = opentelemetry::metrics; | ||
|
||
namespace sdk | ||
{ | ||
namespace metrics | ||
{ | ||
using AggregatorVariant = nostd::variant<std::shared_ptr<Aggregator<short>>, | ||
std::shared_ptr<Aggregator<int>>, | ||
std::shared_ptr<Aggregator<float>>, | ||
std::shared_ptr<Aggregator<double>>>; | ||
class Record | ||
{ | ||
public: | ||
explicit Record(nostd::string_view name, | ||
nostd::string_view description, | ||
std::string labels, | ||
AggregatorVariant aggregator) | ||
{ | ||
name_ = std::string(name); | ||
description_ = std::string(description); | ||
labels_ = labels; | ||
aggregator_ = aggregator; | ||
} | ||
|
||
std::string GetName() { return name_; } | ||
std::string GetDescription() { return description_; } | ||
std::string GetLabels() { return labels_; } | ||
AggregatorVariant GetAggregator() { return aggregator_; } | ||
|
||
private: | ||
std::string name_; | ||
std::string description_; | ||
std::string labels_; | ||
AggregatorVariant aggregator_; | ||
}; | ||
} // namespace metrics | ||
} // namespace sdk | ||
OPENTELEMETRY_END_NAMESPACE |
Oops, something went wrong.