Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Synchronous Gauge #2341

Closed
wants to merge 16 commits into from
24 changes: 24 additions & 0 deletions api/include/opentelemetry/metrics/meter.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ class Histogram;
template <typename T>
class UpDownCounter;

template <typename T>
class Gauge;

class ObservableInstrument;

/**
Expand Down Expand Up @@ -91,6 +94,27 @@ class Meter
nostd::string_view description = "",
nostd::string_view unit = "") noexcept = 0;

#if OPENTELEMETRY_ABI_VERSION_NO >= 2
/**
* Creates a Gauge with the passed characteristics and returns a
* unique_ptr to that Gauge
* @since ABI_VERSION 2
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Align with below @param?

*
* @param name the name of the new Gauge.
* @param description a brief description of what the Gauge is used for.
* @param unit the unit of metric values following https://unitsofmeasure.org/ucum.html.
*/
virtual nostd::unique_ptr<Gauge<uint64_t>> CreateInt64Gauge(
nostd::string_view name,
nostd::string_view description = "",
nostd::string_view unit = "") noexcept = 0;

virtual nostd::unique_ptr<Gauge<double>> CreateDoubleGauge(
nostd::string_view name,
nostd::string_view description = "",
nostd::string_view unit = "") noexcept = 0;
#endif

/**
* Creates a Asynchronouse (Observable) Gauge with the passed characteristics and returns a
* shared_ptr to that Observable Gauge
Expand Down
46 changes: 46 additions & 0 deletions api/include/opentelemetry/metrics/noop.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@ class NoopHistogram : public Histogram<T>
const common::KeyValueIterable & /* attributes */,
const context::Context & /* context */) noexcept override
{}
#if OPENTELEMETRY_ABI_VERSION_NO >= 2
void Record(T value, const opentelemetry::common::KeyValueIterable &attributes) noexcept override
{}

void Record(T value) noexcept override {}
#endif
};

template <class T>
Expand All @@ -64,6 +70,27 @@ class NoopUpDownCounter : public UpDownCounter<T>
{}
};

#if OPENTELEMETRY_ABI_VERSION_NO >= 2

template <class T>
class NoopGauge : public Gauge<T>
{
public:
NoopGauge(nostd::string_view /* name */,
nostd::string_view /* description */,
nostd::string_view /* unit */) noexcept
{}
void Record(T /* value */, const context::Context & /* context */) noexcept override {}
void Record(T /* value */,
const common::KeyValueIterable & /* attributes */,
const context::Context & /* context */) noexcept override
{}
void Record(T value) noexcept override {}
void Record(T value, const opentelemetry::common::KeyValueIterable &attributes) noexcept override
{}
};
#endif

class NoopObservableInstrument : public ObservableInstrument
{
public:
Expand Down Expand Up @@ -133,6 +160,25 @@ class NoopMeter final : public Meter
return nostd::unique_ptr<Histogram<double>>{new NoopHistogram<double>(name, description, unit)};
}

#if OPENTELEMETRY_ABI_VERSION_NO >= 2

nostd::unique_ptr<Gauge<uint64_t>> CreateInt64Gauge(
nostd::string_view name,
nostd::string_view description = "",
nostd::string_view unit = "") noexcept override
{
return nostd::unique_ptr<Gauge<uint64_t>>(new NoopGauge<uint64_t>(name, description, unit));
}

nostd::unique_ptr<Gauge<double>> CreateDoubleGauge(nostd::string_view name,
nostd::string_view description = "",
nostd::string_view unit = "") noexcept override
{
return nostd::unique_ptr<Gauge<double>>(new NoopGauge<double>(name, description, unit));
}

#endif

nostd::shared_ptr<ObservableInstrument> CreateInt64ObservableGauge(
nostd::string_view name,
nostd::string_view description = "",
Expand Down
180 changes: 157 additions & 23 deletions api/include/opentelemetry/metrics/sync_instruments.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,31 +22,44 @@ class SynchronousInstrument
virtual ~SynchronousInstrument() = default;
};

/* A Counter instrument that adds values. */

template <class T>
class Counter : public SynchronousInstrument
{

public:
/**
* Add adds the value to the counter's sum
* Record a value
*
* @param value The increment amount. MUST be non-negative.
*/
virtual void Add(T value) noexcept = 0;

/**
* Record a value
*
* @param value The increment amount. MUST be non-negative.
* @param context The explicit context to associate with this measurement.
*/
virtual void Add(T value, const context::Context &context) noexcept = 0;

/**
* Add adds the value to the counter's sum. The attributes should contain
* the keys and values to be associated with this value. Counters only
* accept positive valued updates.
* Record a value with a set of attributes.
*
* @param value The increment amount. MUST be non-negative.
* @param attributes the set of attributes, as key-value pairs
* @param attributes A set of attributes to associate with the value.
*/

virtual void Add(T value, const common::KeyValueIterable &attributes) noexcept = 0;

/**
* Record a value with a set of attributes.
*
* @param value The increment amount. MUST be non-negative.
* @param attributes A set of attributes to associate with the value.
* @param context The explicit context to associate with this measurement.
*/
virtual void Add(T value,
const common::KeyValueIterable &attributes,
const context::Context &context) noexcept = 0;
Expand All @@ -55,8 +68,7 @@ class Counter : public SynchronousInstrument
nostd::enable_if_t<common::detail::is_key_value_iterable<U>::value> * = nullptr>
void Add(T value, const U &attributes) noexcept
{
auto context = context::Context{};
this->Add(value, common::KeyValueIterableView<U>{attributes}, context);
this->Add(value, common::KeyValueIterableView<U>{attributes});
}

template <class U,
Expand All @@ -70,11 +82,8 @@ class Counter : public SynchronousInstrument
std::initializer_list<std::pair<nostd::string_view, common::AttributeValue>>
attributes) noexcept
{
auto context = context::Context{};
this->Add(value,
nostd::span<const std::pair<nostd::string_view, common::AttributeValue>>{
attributes.begin(), attributes.end()},
context);
this->Add(value, nostd::span<const std::pair<nostd::string_view, common::AttributeValue>>{
attributes.begin(), attributes.end()});
}

void Add(T value,
Expand All @@ -94,18 +103,54 @@ template <class T>
class Histogram : public SynchronousInstrument
{
public:
#if OPENTELEMETRY_ABI_VERSION_NO >= 2
/**
* @since ABI_VERSION 2
* Records a value.
*
* @param value The measurement value. MUST be non-negative.
*/
virtual void Record(T value) noexcept = 0;

/**
* @since ABI_VERSION 2
* Records a value with a set of attributes.
*
* @param value The measurement value. MUST be non-negative.
* @param attribute A set of attributes to associate with the value.
*/
virtual void Record(T value, const common::KeyValueIterable &attribute) noexcept = 0;

template <class U,
nostd::enable_if_t<common::detail::is_key_value_iterable<U>::value> * = nullptr>
void Record(T value, const U &attributes) noexcept
{
this->Record(value, common::KeyValueIterableView<U>{attributes});
}

void Record(T value,
std::initializer_list<std::pair<nostd::string_view, common::AttributeValue>>
attributes) noexcept
{
this->Record(value, nostd::span<const std::pair<nostd::string_view, common::AttributeValue>>{
attributes.begin(), attributes.end()});
}
#endif

/**
* Records a value.
*
* @param value The measurement value. MUST be non-negative.
* @param context The explicit context to associate with this measurement.
*/
virtual void Record(T value, const context::Context &context) noexcept = 0;

/**
* Records a value with a set of attributes.
*
* @param value The measurement value. MUST be non-negative.
* @param attributes A set of attributes to associate with the count.
* @param attributes A set of attributes to associate with the value..
* @param context The explicit context to associate with this measurement.
*/
virtual void Record(T value,
const common::KeyValueIterable &attributes,
Expand Down Expand Up @@ -137,22 +182,35 @@ class UpDownCounter : public SynchronousInstrument
{
public:
/**
* Adds a value.
* Record a value.
*
* @param value The amount of the measurement.
* @param value The increment amount. May be positive, negative or zero.
*/
virtual void Add(T value) noexcept = 0;

/**
* Record a value.
*
* @param value The increment amount. May be positive, negative or zero.
* @param context The explicit context to associate with this measurement.
*/
virtual void Add(T value, const context::Context &context) noexcept = 0;

/**
* Add a value with a set of attributes.
* Record a value with a set of attributes.
*
* @param value The increment amount. May be positive, negative or zero.
* @param attributes A set of attributes to associate with the count.
*/
virtual void Add(T value, const common::KeyValueIterable &attributes) noexcept = 0;

/**
* Record a value with a set of attributes.
*
* @param value The increment amount. May be positive, negative or zero.
* @param attributes A set of attributes to associate with the count.
* @param context The explicit context to associate with this measurement.
*/
virtual void Add(T value,
const common::KeyValueIterable &attributes,
const context::Context &context) noexcept = 0;
Expand All @@ -161,8 +219,7 @@ class UpDownCounter : public SynchronousInstrument
nostd::enable_if_t<common::detail::is_key_value_iterable<U>::value> * = nullptr>
void Add(T value, const U &attributes) noexcept
{
auto context = context::Context{};
this->Add(value, common::KeyValueIterableView<U>{attributes}, context);
this->Add(value, common::KeyValueIterableView<U>{attributes});
}

template <class U,
Expand All @@ -176,11 +233,8 @@ class UpDownCounter : public SynchronousInstrument
std::initializer_list<std::pair<nostd::string_view, common::AttributeValue>>
attributes) noexcept
{
auto context = context::Context{};
this->Add(value,
nostd::span<const std::pair<nostd::string_view, common::AttributeValue>>{
attributes.begin(), attributes.end()},
context);
this->Add(value, nostd::span<const std::pair<nostd::string_view, common::AttributeValue>>{
attributes.begin(), attributes.end()});
}

void Add(T value,
Expand All @@ -194,5 +248,85 @@ class UpDownCounter : public SynchronousInstrument
}
};

#if OPENTELEMETRY_ABI_VERSION_NO >= 2

/** An Gauge instrument that records value.
* @since ABI_VERSION 2
*/

template <class T>
class Gauge : public SynchronousInstrument
{
public:
/**
* Record a value
*
* @param value The increment amount. MUST be non-negative.
*/
virtual void Record(T value) noexcept = 0;

/**
* Record a value
*
* @param value The increment amount. MUST be non-negative.
* @param context The explicit context to associate with this measurement.
*/
virtual void Record(T value, const context::Context &context) noexcept = 0;

/**
* Record a value with a set of attributes.
*
* @param value The increment amount. MUST be non-negative.
* @param attributes A set of attributes to associate with the value.
*/

virtual void Record(T value, const common::KeyValueIterable &attributes) noexcept = 0;

/**
* Record a value with a set of attributes.
*
* @param value The increment amount. MUST be non-negative.
* @param attributes A set of attributes to associate with the value.
* @param context The explicit context to associate with this measurement.
*/
virtual void Record(T value,
const common::KeyValueIterable &attributes,
const context::Context &context) noexcept = 0;
Copy link
Member

@marcalff marcalff Sep 29, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here there are 4 virtual methods for the ABI, with different parameters combinations.

An alternative is to define only one virtual method for the ABI, accepting pointers instead of references:

  virtual void Record(T value,
                      const common::KeyValueIterable *attributes,
                      const context::Context *context) noexcept = 0;

and then have all the API helpers invoke this unique entry point, passing nullptr for optional parameters.

We can still have a helper like:

  void Record(T value,
                      const common::KeyValueIterable &attributes,
                      const context::Context &context) {
    this->Record(value, &attributes, &context);
  }

so that user code pass references as usual.

Making a clear distinction between the ABI (the virtual method) and the API helpers (non virtual) will help,
because it is then easier to decide if a change is a breaking change or not.

Changes to the unique ABI virtual method is a breaking change.

Changes to the plenty of API helpers accepting combinations of parameters is not breaking the ABI,
as it always forwards to the same prototype.

Copy link
Member Author

@lalitb lalitb Sep 29, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A much cleaner method! Thanks for suggesting. I saw this approach in the GetMeter() PR but overlooked adding it here. Done now :)


template <class U,
nostd::enable_if_t<common::detail::is_key_value_iterable<U>::value> * = nullptr>
void Record(T value, const U &attributes) noexcept
{
this->Record(value, common::KeyValueIterableView<U>{attributes});
}

template <class U,
nostd::enable_if_t<common::detail::is_key_value_iterable<U>::value> * = nullptr>
void Record(T value, const U &attributes, const context::Context &context) noexcept
{
this->Record(value, common::KeyValueIterableView<U>{attributes}, context);
}

void Record(T value,
std::initializer_list<std::pair<nostd::string_view, common::AttributeValue>>
attributes) noexcept
{
this->Record(value, nostd::span<const std::pair<nostd::string_view, common::AttributeValue>>{
attributes.begin(), attributes.end()});
}

void Record(
T value,
std::initializer_list<std::pair<nostd::string_view, common::AttributeValue>> attributes,
const context::Context &context) noexcept
{
this->Record(value,
nostd::span<const std::pair<nostd::string_view, common::AttributeValue>>{
attributes.begin(), attributes.end()},
context);
}
};
#endif

} // namespace metrics
OPENTELEMETRY_END_NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,9 @@ class DefaultAggregation
return AggregationType::kSum;
case InstrumentType::kHistogram:
return AggregationType::kHistogram;
#if OPENTELEMETRY_ABI_VERSION_NO >= 2
case InstrumentType::kGauge:
#endif
case InstrumentType::kObservableGauge:
return AggregationType::kLastValue;
default:
Expand Down
Loading
Loading