Skip to content

Commit

Permalink
[API] Add synchronous gauge (#3029)
Browse files Browse the repository at this point in the history
* Add synchronous gauge

* Add ABI Version macro, update tests

* Fix function description

* Fix formatting

* Remove ABI macros from SDK.

* Add error log for gauge delta temporality.

* Fix formatting

* Apply suggestions from code review

Move kGauge to the end, for better ABI compatibility.

---------

Co-authored-by: Lalit Kumar Bhasin <lalit_fin@yahoo.com>
Co-authored-by: Marc Alff <marc.alff@free.fr>
  • Loading branch information
3 people authored Oct 30, 2024
1 parent 6292a6a commit f30ab92
Show file tree
Hide file tree
Showing 20 changed files with 664 additions and 2 deletions.
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.
*
* @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.
* @return a unique pointer to the created Gauge.
*/

virtual nostd::unique_ptr<Gauge<int64_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 Asynchronous (Observable) Gauge with the passed characteristics and returns a
* shared_ptr to that Observable Gauge
Expand Down
36 changes: 36 additions & 0 deletions api/include/opentelemetry/metrics/noop.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,26 @@ 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
{}
~NoopGauge() override = default;
void Record(T /* value */) noexcept override {}
void Record(T /* value */, const context::Context & /* context */) noexcept override {}
void Record(T /* value */, const common::KeyValueIterable & /* attributes */) noexcept override {}
void Record(T /* value */,
const common::KeyValueIterable & /* attributes */,
const context::Context & /* context */) noexcept override
{}
};
#endif

class NoopObservableInstrument : public ObservableInstrument
{
public:
Expand Down Expand Up @@ -140,6 +160,22 @@ 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<int64_t>> CreateInt64Gauge(nostd::string_view name,
nostd::string_view description = "",
nostd::string_view unit = "") noexcept override
{
return nostd::unique_ptr<Gauge<int64_t>>{new NoopGauge<int64_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
77 changes: 77 additions & 0 deletions api/include/opentelemetry/metrics/sync_instruments.h
Original file line number Diff line number Diff line change
Expand Up @@ -247,5 +247,82 @@ class UpDownCounter : public SynchronousInstrument
}
};

#if OPENTELEMETRY_ABI_VERSION_NO >= 2
/* A Gauge instrument that records values. */
template <class T>
class Gauge : public SynchronousInstrument
{

public:
/**
* Record a value
*
* @param value The measurement value. May be positive, negative or zero.
*/
virtual void Record(T value) noexcept = 0;

/**
* Record a value
*
* @param value The measurement value. May be positive, negative or zero.
* @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 measurement value. May be positive, negative or zero.
* @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 measurement value. May be positive, negative or zero.
* @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;

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
19 changes: 19 additions & 0 deletions examples/common/metrics_foo_library/foo_library.cc
Original file line number Diff line number Diff line change
Expand Up @@ -107,3 +107,22 @@ void foo_library::histogram_example(const std::string &name)
std::this_thread::sleep_for(std::chrono::milliseconds(250));
}
}

#if OPENTELEMETRY_ABI_VERSION_NO >= 2
void foo_library::gauge_example(const std::string &name)
{
std::string gauge_name = name + "_gauge";
auto provider = metrics_api::Provider::GetMeterProvider();
opentelemetry::nostd::shared_ptr<metrics_api::Meter> meter = provider->GetMeter(name, "1.2.0");
auto gauge = meter->CreateInt64Gauge(gauge_name, "des", "unit");
auto context = opentelemetry::context::Context{};
for (uint32_t i = 0; i < 20; ++i)
{
int64_t val = (rand() % 100) + 100;
std::map<std::string, std::string> labels = get_random_attr();
auto labelkv = opentelemetry::common::KeyValueIterableView<decltype(labels)>{labels};
gauge->Record(val, labelkv, context);
std::this_thread::sleep_for(std::chrono::milliseconds(250));
}
}
#endif
3 changes: 3 additions & 0 deletions examples/common/metrics_foo_library/foo_library.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,7 @@ class foo_library
static void counter_example(const std::string &name);
static void histogram_example(const std::string &name);
static void observable_counter_example(const std::string &name);
#if OPENTELEMETRY_ABI_VERSION_NO >= 2
static void gauge_example(const std::string &name);
#endif
};
12 changes: 12 additions & 0 deletions examples/metrics_simple/metrics_ostream.cc
Original file line number Diff line number Diff line change
Expand Up @@ -148,15 +148,27 @@ int main(int argc, char **argv)
{
foo_library::histogram_example(name);
}
#if OPENTELEMETRY_ABI_VERSION_NO >= 2
else if (example_type == "gauge")
{
foo_library::gauge_example(name);
}
#endif
else
{
std::thread counter_example{&foo_library::counter_example, name};
std::thread observable_counter_example{&foo_library::observable_counter_example, name};
std::thread histogram_example{&foo_library::histogram_example, name};
#if OPENTELEMETRY_ABI_VERSION_NO >= 2
std::thread gauge_example{&foo_library::gauge_example, name};
#endif

counter_example.join();
observable_counter_example.join();
histogram_example.join();
#if OPENTELEMETRY_ABI_VERSION_NO >= 2
gauge_example.join();
#endif
}

CleanupMetrics();
Expand Down
12 changes: 12 additions & 0 deletions examples/otlp/file_metric_main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -98,15 +98,27 @@ int main(int argc, char *argv[])
{
foo_library::histogram_example(name);
}
#if OPENTELEMETRY_ABI_VERSION_NO >= 2
else if (example_type == "gauge")
{
foo_library::gauge_example(name);
}
#endif
else
{
std::thread counter_example{&foo_library::counter_example, name};
std::thread observable_counter_example{&foo_library::observable_counter_example, name};
std::thread histogram_example{&foo_library::histogram_example, name};
#if OPENTELEMETRY_ABI_VERSION_NO >= 2
std::thread gauge_example{&foo_library::gauge_example, name};
#endif

counter_example.join();
observable_counter_example.join();
histogram_example.join();
#if OPENTELEMETRY_ABI_VERSION_NO >= 2
gauge_example.join();
#endif
}

CleanupMetrics();
Expand Down
12 changes: 12 additions & 0 deletions examples/otlp/grpc_metric_main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -93,15 +93,27 @@ int main(int argc, char *argv[])
{
foo_library::histogram_example(name);
}
#if OPENTELEMETRY_ABI_VERSION_NO >= 2
else if (example_type == "gauge")
{
foo_library::gauge_example(name);
}
#endif
else
{
std::thread counter_example{&foo_library::counter_example, name};
std::thread observable_counter_example{&foo_library::observable_counter_example, name};
std::thread histogram_example{&foo_library::histogram_example, name};
#if OPENTELEMETRY_ABI_VERSION_NO >= 2
std::thread gauge_example{&foo_library::gauge_example, name};
#endif

counter_example.join();
observable_counter_example.join();
histogram_example.join();
#if OPENTELEMETRY_ABI_VERSION_NO >= 2
gauge_example.join();
#endif
}

CleanupMetrics();
Expand Down
12 changes: 12 additions & 0 deletions examples/otlp/http_metric_main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -133,15 +133,27 @@ int main(int argc, char *argv[])
{
foo_library::histogram_example(name);
}
#if OPENTELEMETRY_ABI_VERSION_NO >= 2
else if (example_type == "gauge")
{
foo_library::gauge_example(name);
}
#endif
else
{
std::thread counter_example{&foo_library::counter_example, name};
std::thread observable_counter_example{&foo_library::observable_counter_example, name};
std::thread histogram_example{&foo_library::histogram_example, name};
#if OPENTELEMETRY_ABI_VERSION_NO >= 2
std::thread gauge_example{&foo_library::gauge_example, name};
#endif

counter_example.join();
observable_counter_example.join();
histogram_example.join();
#if OPENTELEMETRY_ABI_VERSION_NO >= 2
gauge_example.join();
#endif
}

CleanupMetrics();
Expand Down
2 changes: 2 additions & 0 deletions exporters/otlp/src/otlp_metric_utils.cc
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,7 @@ sdk::metrics::AggregationTemporality OtlpMetricUtils::DeltaTemporalitySelector(
case sdk::metrics::InstrumentType::kObservableCounter:
case sdk::metrics::InstrumentType::kHistogram:
case sdk::metrics::InstrumentType::kObservableGauge:
case sdk::metrics::InstrumentType::kGauge:
return sdk::metrics::AggregationTemporality::kDelta;
case sdk::metrics::InstrumentType::kUpDownCounter:
case sdk::metrics::InstrumentType::kObservableUpDownCounter:
Expand All @@ -320,6 +321,7 @@ sdk::metrics::AggregationTemporality OtlpMetricUtils::LowMemoryTemporalitySelect
case sdk::metrics::InstrumentType::kHistogram:
return sdk::metrics::AggregationTemporality::kDelta;
case sdk::metrics::InstrumentType::kObservableCounter:
case sdk::metrics::InstrumentType::kGauge:
case sdk::metrics::InstrumentType::kObservableGauge:
case sdk::metrics::InstrumentType::kUpDownCounter:
case sdk::metrics::InstrumentType::kObservableUpDownCounter:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ class DefaultAggregation
return AggregationType::kSum;
case InstrumentType::kHistogram:
return AggregationType::kHistogram;
case InstrumentType::kGauge:
case InstrumentType::kObservableGauge:
return AggregationType::kLastValue;
default:
Expand Down
3 changes: 2 additions & 1 deletion sdk/include/opentelemetry/sdk/metrics/instruments.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ enum class InstrumentType
kUpDownCounter,
kObservableCounter,
kObservableGauge,
kObservableUpDownCounter
kObservableUpDownCounter,
kGauge
};

enum class InstrumentClass
Expand Down
12 changes: 12 additions & 0 deletions sdk/include/opentelemetry/sdk/metrics/meter.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,18 @@ class Meter final : public opentelemetry::metrics::Meter
nostd::string_view description = "",
nostd::string_view unit = "") noexcept override;

#if OPENTELEMETRY_ABI_VERSION_NO >= 2
nostd::unique_ptr<opentelemetry::metrics::Gauge<int64_t>> CreateInt64Gauge(
nostd::string_view name,
nostd::string_view description = "",
nostd::string_view unit = "") noexcept override;

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

nostd::shared_ptr<opentelemetry::metrics::ObservableInstrument> CreateInt64ObservableGauge(
nostd::string_view name,
nostd::string_view description = "",
Expand Down
Loading

1 comment on commit f30ab92

@github-actions
Copy link

Choose a reason for hiding this comment

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

⚠️ Performance Alert ⚠️

Possible performance regression was detected for benchmark 'OpenTelemetry-cpp api Benchmark'.
Benchmark result of this commit is worse than the previous benchmark result exceeding threshold 2.

Benchmark suite Current: f30ab92 Previous: 6292a6a Ratio
BM_SpinLockThrashing/4/process_time/real_time 2.2646093368530273 ms/iter 0.61578245206912 ms/iter 3.68
BM_ProcYieldSpinLockThrashing/1/process_time/real_time 0.18673910061360355 ms/iter 0.07807681573688655 ms/iter 2.39
BM_ProcYieldSpinLockThrashing/2/process_time/real_time 1.0947751998901367 ms/iter 0.1601686487689254 ms/iter 6.84
BM_ProcYieldSpinLockThrashing/4/process_time/real_time 2.2829488704079077 ms/iter 0.6495152831708313 ms/iter 3.51

This comment was automatically generated by workflow using github-action-benchmark.

Please sign in to comment.