|
|
|
@ -18,11 +18,15 @@ |
|
|
|
|
|
|
|
|
|
#include "src/cpp/ext/otel/otel_plugin.h" |
|
|
|
|
|
|
|
|
|
#include <atomic> |
|
|
|
|
#include <chrono> |
|
|
|
|
#include <ratio> |
|
|
|
|
#include <type_traits> |
|
|
|
|
|
|
|
|
|
#include "absl/functional/any_invocable.h" |
|
|
|
|
#include "gmock/gmock.h" |
|
|
|
|
#include "gtest/gtest.h" |
|
|
|
|
#include "opentelemetry/common/timestamp.h" |
|
|
|
|
#include "opentelemetry/metrics/provider.h" |
|
|
|
|
#include "opentelemetry/nostd/variant.h" |
|
|
|
|
#include "opentelemetry/sdk/common/attribute_utils.h" |
|
|
|
@ -70,46 +74,129 @@ MATCHER_P4(AttributesEq, label_keys, label_values, optional_label_keys, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
template <typename T> |
|
|
|
|
auto IntOrDoubleEq(T result) { |
|
|
|
|
return ::testing::Eq(result); |
|
|
|
|
} |
|
|
|
|
template <> |
|
|
|
|
auto IntOrDoubleEq(double result) { |
|
|
|
|
return ::testing::DoubleEq(result); |
|
|
|
|
} |
|
|
|
|
struct Extract; |
|
|
|
|
|
|
|
|
|
template <template <typename> class T, typename U> |
|
|
|
|
struct Extract<const T<U>> { |
|
|
|
|
using Type = U; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
MATCHER_P(CounterResultEq, result, "") { |
|
|
|
|
MATCHER_P(CounterResultEq, value_matcher, "") { |
|
|
|
|
return ::testing::ExplainMatchResult( |
|
|
|
|
::testing::VariantWith<opentelemetry::sdk::metrics::SumPointData>( |
|
|
|
|
::testing::Field(&opentelemetry::sdk::metrics::SumPointData::value_, |
|
|
|
|
::testing::VariantWith< |
|
|
|
|
typename Extract<decltype(value_matcher)>::Type>( |
|
|
|
|
value_matcher))), |
|
|
|
|
arg.point_data, result_listener); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
MATCHER_P4(HistogramResultEq, sum_matcher, min_matcher, max_matcher, count, |
|
|
|
|
"") { |
|
|
|
|
return ::testing::ExplainMatchResult( |
|
|
|
|
::testing::VariantWith< |
|
|
|
|
opentelemetry::sdk::metrics::HistogramPointData>(::testing::AllOf( |
|
|
|
|
::testing::Field( |
|
|
|
|
&opentelemetry::sdk::metrics::HistogramPointData::sum_, |
|
|
|
|
::testing::VariantWith< |
|
|
|
|
typename Extract<decltype(sum_matcher)>::Type>(sum_matcher)), |
|
|
|
|
::testing::Field( |
|
|
|
|
&opentelemetry::sdk::metrics::SumPointData::value_, |
|
|
|
|
::testing::VariantWith<std::remove_cv_t<decltype(result)>>( |
|
|
|
|
IntOrDoubleEq(result)))), |
|
|
|
|
&opentelemetry::sdk::metrics::HistogramPointData::min_, |
|
|
|
|
::testing::VariantWith< |
|
|
|
|
typename Extract<decltype(min_matcher)>::Type>(min_matcher)), |
|
|
|
|
::testing::Field( |
|
|
|
|
&opentelemetry::sdk::metrics::HistogramPointData::max_, |
|
|
|
|
::testing::VariantWith< |
|
|
|
|
typename Extract<decltype(max_matcher)>::Type>(max_matcher)), |
|
|
|
|
::testing::Field( |
|
|
|
|
&opentelemetry::sdk::metrics::HistogramPointData::count_, |
|
|
|
|
::testing::Eq(count)))), |
|
|
|
|
arg.point_data, result_listener); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
MATCHER_P4(HistogramResultEq, sum, min, max, count, "") { |
|
|
|
|
MATCHER_P(GaugeResultIs, value_matcher, "") { |
|
|
|
|
return ::testing::ExplainMatchResult( |
|
|
|
|
::testing::VariantWith<opentelemetry::sdk::metrics::HistogramPointData>( |
|
|
|
|
::testing::VariantWith<opentelemetry::sdk::metrics::LastValuePointData>( |
|
|
|
|
::testing::AllOf( |
|
|
|
|
::testing::Field( |
|
|
|
|
&opentelemetry::sdk::metrics::HistogramPointData::sum_, |
|
|
|
|
::testing::VariantWith<std::remove_cv_t<decltype(sum)>>( |
|
|
|
|
IntOrDoubleEq(sum))), |
|
|
|
|
::testing::Field( |
|
|
|
|
&opentelemetry::sdk::metrics::HistogramPointData::min_, |
|
|
|
|
::testing::VariantWith<std::remove_cv_t<decltype(min)>>( |
|
|
|
|
IntOrDoubleEq(min))), |
|
|
|
|
::testing::Field( |
|
|
|
|
&opentelemetry::sdk::metrics::HistogramPointData::max_, |
|
|
|
|
::testing::VariantWith<std::remove_cv_t<decltype(max)>>( |
|
|
|
|
IntOrDoubleEq(max))), |
|
|
|
|
::testing::Field( |
|
|
|
|
&opentelemetry::sdk::metrics::HistogramPointData::count_, |
|
|
|
|
::testing::Eq(count)))), |
|
|
|
|
&opentelemetry::sdk::metrics::LastValuePointData::value_, |
|
|
|
|
::testing::VariantWith< |
|
|
|
|
typename Extract<decltype(value_matcher)>::Type>( |
|
|
|
|
value_matcher)), |
|
|
|
|
::testing::Field(&opentelemetry::sdk::metrics:: |
|
|
|
|
LastValuePointData::is_lastvalue_valid_, |
|
|
|
|
::testing::IsTrue()))), |
|
|
|
|
arg.point_data, result_listener); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// This check might subject to system clock adjustment.
|
|
|
|
|
MATCHER_P(GaugeResultLaterThan, prev_timestamp, "") { |
|
|
|
|
return ::testing::ExplainMatchResult( |
|
|
|
|
::testing::VariantWith<opentelemetry::sdk::metrics::LastValuePointData>( |
|
|
|
|
::testing::Field( |
|
|
|
|
&opentelemetry::sdk::metrics::LastValuePointData::sample_ts_, |
|
|
|
|
::testing::Property( |
|
|
|
|
&opentelemetry::common::SystemTimestamp::time_since_epoch, |
|
|
|
|
::testing::Gt(prev_timestamp.time_since_epoch())))), |
|
|
|
|
arg.point_data, result_listener); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
MATCHER_P7(GaugeDataIsIncrementalForSpecificMetricAndLabelSet, metric_name, |
|
|
|
|
label_key, label_value, optional_label_key, optional_label_value, |
|
|
|
|
default_value, greater_than, "") { |
|
|
|
|
std::unordered_map<std::string, |
|
|
|
|
opentelemetry::sdk::common::OwnedAttributeValue> |
|
|
|
|
label_map; |
|
|
|
|
PopulateLabelMap(label_key, label_value, &label_map); |
|
|
|
|
PopulateLabelMap(optional_label_key, optional_label_value, &label_map); |
|
|
|
|
opentelemetry::common::SystemTimestamp prev_timestamp; |
|
|
|
|
auto prev_value = default_value; |
|
|
|
|
size_t prev_index = 0; |
|
|
|
|
auto& data = arg.at(metric_name); |
|
|
|
|
bool result = true; |
|
|
|
|
for (size_t i = 1; i < data.size(); ++i) { |
|
|
|
|
if (::testing::Matches(::testing::UnorderedElementsAreArray( |
|
|
|
|
data[i - 1].attributes.GetAttributes()))(label_map)) { |
|
|
|
|
// Update the previous value for the same associated label values.
|
|
|
|
|
prev_value = opentelemetry::nostd::get<decltype(prev_value)>( |
|
|
|
|
opentelemetry::nostd::get< |
|
|
|
|
opentelemetry::sdk::metrics::LastValuePointData>( |
|
|
|
|
data[i - 1].point_data) |
|
|
|
|
.value_); |
|
|
|
|
prev_index = i - 1; |
|
|
|
|
prev_timestamp = opentelemetry::nostd::get< |
|
|
|
|
opentelemetry::sdk::metrics::LastValuePointData>( |
|
|
|
|
data[i - 1].point_data) |
|
|
|
|
.sample_ts_; |
|
|
|
|
} |
|
|
|
|
if (!::testing::Matches(::testing::UnorderedElementsAreArray( |
|
|
|
|
data[i].attributes.GetAttributes()))(label_map)) { |
|
|
|
|
// Skip values that do not have the same associated label values.
|
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
*result_listener << " Comparing data[" << i << "] with data[" << prev_index |
|
|
|
|
<< "] "; |
|
|
|
|
if (greater_than) { |
|
|
|
|
result &= ::testing::ExplainMatchResult( |
|
|
|
|
::testing::AllOf( |
|
|
|
|
AttributesEq(label_key, label_value, optional_label_key, |
|
|
|
|
optional_label_value), |
|
|
|
|
GaugeResultIs(::testing::Gt(prev_value)), |
|
|
|
|
GaugeResultLaterThan(prev_timestamp)), |
|
|
|
|
data[i], result_listener); |
|
|
|
|
} else { |
|
|
|
|
result &= ::testing::ExplainMatchResult( |
|
|
|
|
::testing::AllOf( |
|
|
|
|
AttributesEq(label_key, label_value, optional_label_key, |
|
|
|
|
optional_label_value), |
|
|
|
|
GaugeResultIs(::testing::Ge(prev_value)), |
|
|
|
|
GaugeResultLaterThan(prev_timestamp)), |
|
|
|
|
data[i], result_listener); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return result; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
TEST(OpenTelemetryPluginBuildTest, ApiDependency) { |
|
|
|
|
opentelemetry::metrics::Provider::GetMeterProvider(); |
|
|
|
|
} |
|
|
|
@ -1049,12 +1136,13 @@ TEST_F(OpenTelemetryPluginNPCMetricsTest, RecordUInt64Counter) { |
|
|
|
|
std::string, |
|
|
|
|
std::vector<opentelemetry::sdk::metrics::PointDataAttributes>>& |
|
|
|
|
data) { return !data.contains(kMetricName); }); |
|
|
|
|
EXPECT_THAT(data, ::testing::ElementsAre(::testing::Pair( |
|
|
|
|
kMetricName, ::testing::ElementsAre(::testing::AllOf( |
|
|
|
|
AttributesEq(kLabelKeys, kLabelValues, |
|
|
|
|
kOptionalLabelKeys, |
|
|
|
|
kOptionalLabelValues), |
|
|
|
|
CounterResultEq(kCounterResult)))))); |
|
|
|
|
EXPECT_THAT(data, |
|
|
|
|
::testing::ElementsAre(::testing::Pair( |
|
|
|
|
kMetricName, |
|
|
|
|
::testing::ElementsAre(::testing::AllOf( |
|
|
|
|
AttributesEq(kLabelKeys, kLabelValues, kOptionalLabelKeys, |
|
|
|
|
kOptionalLabelValues), |
|
|
|
|
CounterResultEq(::testing::Eq(kCounterResult))))))); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
TEST_F(OpenTelemetryPluginNPCMetricsTest, RecordDoubleCounter) { |
|
|
|
@ -1094,12 +1182,13 @@ TEST_F(OpenTelemetryPluginNPCMetricsTest, RecordDoubleCounter) { |
|
|
|
|
std::string, |
|
|
|
|
std::vector<opentelemetry::sdk::metrics::PointDataAttributes>>& |
|
|
|
|
data) { return !data.contains(kMetricName); }); |
|
|
|
|
EXPECT_THAT(data, ::testing::ElementsAre(::testing::Pair( |
|
|
|
|
kMetricName, ::testing::ElementsAre(::testing::AllOf( |
|
|
|
|
AttributesEq(kLabelKeys, kLabelValues, |
|
|
|
|
kOptionalLabelKeys, |
|
|
|
|
kOptionalLabelValues), |
|
|
|
|
CounterResultEq(kCounterResult)))))); |
|
|
|
|
EXPECT_THAT(data, |
|
|
|
|
::testing::ElementsAre(::testing::Pair( |
|
|
|
|
kMetricName, |
|
|
|
|
::testing::ElementsAre(::testing::AllOf( |
|
|
|
|
AttributesEq(kLabelKeys, kLabelValues, kOptionalLabelKeys, |
|
|
|
|
kOptionalLabelValues), |
|
|
|
|
CounterResultEq(::testing::DoubleEq(kCounterResult))))))); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
TEST_F(OpenTelemetryPluginNPCMetricsTest, RecordUInt64Histogram) { |
|
|
|
@ -1142,13 +1231,14 @@ TEST_F(OpenTelemetryPluginNPCMetricsTest, RecordUInt64Histogram) { |
|
|
|
|
std::string, |
|
|
|
|
std::vector<opentelemetry::sdk::metrics::PointDataAttributes>>& |
|
|
|
|
data) { return !data.contains(kMetricName); }); |
|
|
|
|
EXPECT_THAT(data, |
|
|
|
|
::testing::ElementsAre(::testing::Pair( |
|
|
|
|
kMetricName, |
|
|
|
|
::testing::ElementsAre(::testing::AllOf( |
|
|
|
|
AttributesEq(kLabelKeys, kLabelValues, kOptionalLabelKeys, |
|
|
|
|
kOptionalLabelValues), |
|
|
|
|
HistogramResultEq(kSum, kMin, kMax, kCount)))))); |
|
|
|
|
EXPECT_THAT( |
|
|
|
|
data, ::testing::ElementsAre(::testing::Pair( |
|
|
|
|
kMetricName, |
|
|
|
|
::testing::ElementsAre(::testing::AllOf( |
|
|
|
|
AttributesEq(kLabelKeys, kLabelValues, kOptionalLabelKeys, |
|
|
|
|
kOptionalLabelValues), |
|
|
|
|
HistogramResultEq(::testing::Eq(kSum), ::testing::Eq(kMin), |
|
|
|
|
::testing::Eq(kMax), kCount)))))); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
TEST_F(OpenTelemetryPluginNPCMetricsTest, RecordDoubleHistogram) { |
|
|
|
@ -1198,7 +1288,9 @@ TEST_F(OpenTelemetryPluginNPCMetricsTest, RecordDoubleHistogram) { |
|
|
|
|
::testing::ElementsAre(::testing::AllOf( |
|
|
|
|
AttributesEq(kLabelKeys, kLabelValues, kOptionalLabelKeys, |
|
|
|
|
kOptionalLabelValues), |
|
|
|
|
HistogramResultEq(kSum, kMin, kMax, kCount)))))); |
|
|
|
|
HistogramResultEq(::testing::DoubleEq(kSum), |
|
|
|
|
::testing::DoubleEq(kMin), |
|
|
|
|
::testing::DoubleEq(kMax), kCount)))))); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
TEST_F(OpenTelemetryPluginNPCMetricsTest, |
|
|
|
@ -1254,7 +1346,9 @@ TEST_F(OpenTelemetryPluginNPCMetricsTest, |
|
|
|
|
::testing::ElementsAre(::testing::AllOf( |
|
|
|
|
AttributesEq(kLabelKeys, kLabelValues, kOptionalLabelKeys, |
|
|
|
|
kOptionalLabelValues), |
|
|
|
|
HistogramResultEq(kSum, kMin, kMax, kCount)))))); |
|
|
|
|
HistogramResultEq(::testing::DoubleEq(kSum), |
|
|
|
|
::testing::DoubleEq(kMin), |
|
|
|
|
::testing::DoubleEq(kMax), kCount)))))); |
|
|
|
|
} |
|
|
|
|
// Now build and register another OpenTelemetryPlugin using the test fixture
|
|
|
|
|
// and record histogram.
|
|
|
|
@ -1290,7 +1384,9 @@ TEST_F(OpenTelemetryPluginNPCMetricsTest, |
|
|
|
|
::testing::ElementsAre(::testing::AllOf( |
|
|
|
|
AttributesEq(kLabelKeys, kLabelValues, kOptionalLabelKeys, |
|
|
|
|
kOptionalLabelValues), |
|
|
|
|
HistogramResultEq(kSum, kMin, kMax, kCount)))))); |
|
|
|
|
HistogramResultEq(::testing::DoubleEq(kSum), |
|
|
|
|
::testing::DoubleEq(kMin), |
|
|
|
|
::testing::DoubleEq(kMax), kCount)))))); |
|
|
|
|
// Verify that the first plugin gets the data as well.
|
|
|
|
|
data = ReadCurrentMetricsData( |
|
|
|
|
[&](const absl::flat_hash_map< |
|
|
|
@ -1304,7 +1400,9 @@ TEST_F(OpenTelemetryPluginNPCMetricsTest, |
|
|
|
|
::testing::ElementsAre(::testing::AllOf( |
|
|
|
|
AttributesEq(kLabelKeys, kLabelValues, kOptionalLabelKeys, |
|
|
|
|
kOptionalLabelValues), |
|
|
|
|
HistogramResultEq(kSum, kMin, kMax, kCount)))))); |
|
|
|
|
HistogramResultEq(::testing::DoubleEq(kSum), |
|
|
|
|
::testing::DoubleEq(kMin), |
|
|
|
|
::testing::DoubleEq(kMax), kCount)))))); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
TEST_F(OpenTelemetryPluginNPCMetricsTest, |
|
|
|
@ -1322,15 +1420,16 @@ TEST_F(OpenTelemetryPluginNPCMetricsTest, |
|
|
|
|
constexpr std::array<absl::string_view, 4> kOptionalLabelKeys = { |
|
|
|
|
"optional_label_key_1", "optional_label_key_2", "optional_label_key_3", |
|
|
|
|
"optional_label_key_4"}; |
|
|
|
|
constexpr std::array<absl::string_view, 2> kActualOptionalLabelKeys = { |
|
|
|
|
"optional_label_key_1", "optional_label_key_2"}; |
|
|
|
|
constexpr std::array<absl::string_view, 3> kActualOptionalLabelKeys = { |
|
|
|
|
"optional_label_key_1", "optional_label_key_2", "optional_label_key_4"}; |
|
|
|
|
constexpr std::array<absl::string_view, 2> kLabelValues = {"label_value_1", |
|
|
|
|
"label_value_2"}; |
|
|
|
|
constexpr std::array<absl::string_view, 4> kOptionalLabelValues = { |
|
|
|
|
"optional_label_value_1", "optional_label_value_2", |
|
|
|
|
"optional_label_value_3", "optional_label_value_4"}; |
|
|
|
|
constexpr std::array<absl::string_view, 2> kActualOptionalLabelValues = { |
|
|
|
|
"optional_label_value_1", "optional_label_value_2"}; |
|
|
|
|
constexpr std::array<absl::string_view, 3> kActualOptionalLabelValues = { |
|
|
|
|
"optional_label_value_1", "optional_label_value_2", |
|
|
|
|
"optional_label_value_4"}; |
|
|
|
|
auto handle = grpc_core::GlobalInstrumentsRegistry::RegisterDoubleHistogram( |
|
|
|
|
kMetricName, "A simple double histogram.", "unit", kLabelKeys, |
|
|
|
|
kOptionalLabelKeys, /*enable_by_default=*/true); |
|
|
|
@ -1342,7 +1441,8 @@ TEST_F(OpenTelemetryPluginNPCMetricsTest, |
|
|
|
|
GRPC_ARG_SERVER_SELECTOR_VALUE; |
|
|
|
|
}) |
|
|
|
|
.add_optional_label(kOptionalLabelKeys[0]) |
|
|
|
|
.add_optional_label(kOptionalLabelKeys[1]))); |
|
|
|
|
.add_optional_label(kOptionalLabelKeys[1]) |
|
|
|
|
.add_optional_label(kOptionalLabelKeys[3]))); |
|
|
|
|
grpc_core::ChannelArgs args; |
|
|
|
|
args = args.Set(GRPC_ARG_SERVER_SELECTOR_KEY, GRPC_ARG_SERVER_SELECTOR_VALUE); |
|
|
|
|
auto stats_plugins = |
|
|
|
@ -1363,7 +1463,274 @@ TEST_F(OpenTelemetryPluginNPCMetricsTest, |
|
|
|
|
::testing::ElementsAre(::testing::AllOf( |
|
|
|
|
AttributesEq(kLabelKeys, kLabelValues, kActualOptionalLabelKeys, |
|
|
|
|
kActualOptionalLabelValues), |
|
|
|
|
HistogramResultEq(kSum, kMin, kMax, kCount)))))); |
|
|
|
|
HistogramResultEq(::testing::DoubleEq(kSum), |
|
|
|
|
::testing::DoubleEq(kMin), |
|
|
|
|
::testing::DoubleEq(kMax), kCount)))))); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
using OpenTelemetryPluginCallbackMetricsTest = OpenTelemetryPluginEnd2EndTest; |
|
|
|
|
|
|
|
|
|
// The callback minimal interval is longer than the OT reporting interval, so we
|
|
|
|
|
// expect to collect duplicated (cached) values.
|
|
|
|
|
TEST_F(OpenTelemetryPluginCallbackMetricsTest, |
|
|
|
|
ReportDurationLongerThanCollectDuration) { |
|
|
|
|
constexpr absl::string_view kInt64CallbackGaugeMetric = |
|
|
|
|
"int64_callback_gauge"; |
|
|
|
|
constexpr absl::string_view kDoubleCallbackGaugeMetric = |
|
|
|
|
"double_callback_gauge"; |
|
|
|
|
constexpr std::array<absl::string_view, 2> kLabelKeys = {"label_key_1", |
|
|
|
|
"label_key_2"}; |
|
|
|
|
constexpr std::array<absl::string_view, 2> kOptionalLabelKeys = { |
|
|
|
|
"optional_label_key_1", "optional_label_key_2"}; |
|
|
|
|
constexpr std::array<absl::string_view, 2> kLabelValuesSet1 = { |
|
|
|
|
"label_value_set_1", "label_value_set_1"}; |
|
|
|
|
constexpr std::array<absl::string_view, 2> kOptionalLabelValuesSet1 = { |
|
|
|
|
"optional_label_value_set_1", "optional_label_value_set_1"}; |
|
|
|
|
constexpr std::array<absl::string_view, 2> kLabelValuesSet2 = { |
|
|
|
|
"label_value_set_2", "label_value_set_2"}; |
|
|
|
|
constexpr std::array<absl::string_view, 2> kOptionalLabelValuesSet2 = { |
|
|
|
|
"optional_label_value_set_2", "optional_label_value_set_2"}; |
|
|
|
|
auto integer_gauge_handle = |
|
|
|
|
grpc_core::GlobalInstrumentsRegistry::RegisterCallbackInt64Gauge( |
|
|
|
|
kInt64CallbackGaugeMetric, "An int64 callback gauge.", "unit", |
|
|
|
|
kLabelKeys, kOptionalLabelKeys, |
|
|
|
|
/*enable_by_default=*/true); |
|
|
|
|
auto double_gauge_handle = |
|
|
|
|
grpc_core::GlobalInstrumentsRegistry::RegisterCallbackDoubleGauge( |
|
|
|
|
kDoubleCallbackGaugeMetric, "A double callback gauge.", "unit", |
|
|
|
|
kLabelKeys, kOptionalLabelKeys, |
|
|
|
|
/*enable_by_default=*/true); |
|
|
|
|
Init(std::move(Options() |
|
|
|
|
.set_metric_names({kInt64CallbackGaugeMetric, |
|
|
|
|
kDoubleCallbackGaugeMetric}) |
|
|
|
|
.add_optional_label(kOptionalLabelKeys[0]) |
|
|
|
|
.add_optional_label(kOptionalLabelKeys[1]))); |
|
|
|
|
auto stats_plugins = |
|
|
|
|
grpc_core::GlobalStatsPluginRegistry::GetStatsPluginsForChannel( |
|
|
|
|
grpc_core::experimental::StatsPluginChannelScope( |
|
|
|
|
"dns:///localhost:8080", "")); |
|
|
|
|
// Multiple callbacks for the same metrics, each reporting different label
|
|
|
|
|
// values.
|
|
|
|
|
int report_count_1 = 0; |
|
|
|
|
int64_t int_value_1 = 1; |
|
|
|
|
double double_value_1 = 0.5; |
|
|
|
|
auto registered_metric_callback_1 = stats_plugins.RegisterCallback( |
|
|
|
|
[&](grpc_core::CallbackMetricReporter& reporter) { |
|
|
|
|
++report_count_1; |
|
|
|
|
reporter.Report(integer_gauge_handle, int_value_1, kLabelValuesSet1, |
|
|
|
|
kOptionalLabelValuesSet1); |
|
|
|
|
reporter.Report(integer_gauge_handle, int_value_1++, kLabelValuesSet2, |
|
|
|
|
kOptionalLabelValuesSet2); |
|
|
|
|
reporter.Report(double_gauge_handle, double_value_1, kLabelValuesSet1, |
|
|
|
|
kOptionalLabelValuesSet1); |
|
|
|
|
reporter.Report(double_gauge_handle, double_value_1++, kLabelValuesSet2, |
|
|
|
|
kOptionalLabelValuesSet2); |
|
|
|
|
}, |
|
|
|
|
{integer_gauge_handle, double_gauge_handle}, |
|
|
|
|
grpc_core::Duration::Milliseconds(100) * grpc_test_slowdown_factor()); |
|
|
|
|
int report_count_2 = 0; |
|
|
|
|
int64_t int_value_2 = 1; |
|
|
|
|
double double_value_2 = 0.5; |
|
|
|
|
auto registered_metric_callback_2 = stats_plugins.RegisterCallback( |
|
|
|
|
[&](grpc_core::CallbackMetricReporter& reporter) { |
|
|
|
|
++report_count_2; |
|
|
|
|
reporter.Report(integer_gauge_handle, int_value_2, kLabelValuesSet1, |
|
|
|
|
kOptionalLabelValuesSet1); |
|
|
|
|
reporter.Report(integer_gauge_handle, int_value_2++, kLabelValuesSet2, |
|
|
|
|
kOptionalLabelValuesSet2); |
|
|
|
|
reporter.Report(double_gauge_handle, double_value_2, kLabelValuesSet1, |
|
|
|
|
kOptionalLabelValuesSet1); |
|
|
|
|
reporter.Report(double_gauge_handle, double_value_2++, kLabelValuesSet2, |
|
|
|
|
kOptionalLabelValuesSet2); |
|
|
|
|
}, |
|
|
|
|
{integer_gauge_handle, double_gauge_handle}, |
|
|
|
|
grpc_core::Duration::Milliseconds(100) * grpc_test_slowdown_factor()); |
|
|
|
|
constexpr int kIterations = 100; |
|
|
|
|
MetricsCollectorThread collector{ |
|
|
|
|
this, grpc_core::Duration::Milliseconds(10) * grpc_test_slowdown_factor(), |
|
|
|
|
kIterations, |
|
|
|
|
[&](const absl::flat_hash_map< |
|
|
|
|
std::string, |
|
|
|
|
std::vector<opentelemetry::sdk::metrics::PointDataAttributes>>& |
|
|
|
|
data) { |
|
|
|
|
return !data.contains(kInt64CallbackGaugeMetric) || |
|
|
|
|
!data.contains(kDoubleCallbackGaugeMetric); |
|
|
|
|
}}; |
|
|
|
|
absl::flat_hash_map< |
|
|
|
|
std::string, |
|
|
|
|
std::vector<opentelemetry::sdk::metrics::PointDataAttributes>> |
|
|
|
|
data = collector.Stop(); |
|
|
|
|
// Verify that data is incremental with duplications (cached values).
|
|
|
|
|
EXPECT_LT(report_count_1, kIterations); |
|
|
|
|
EXPECT_LT(report_count_2, kIterations); |
|
|
|
|
EXPECT_EQ(data[kInt64CallbackGaugeMetric].size(), |
|
|
|
|
data[kDoubleCallbackGaugeMetric].size()); |
|
|
|
|
// Verify labels.
|
|
|
|
|
ASSERT_THAT( |
|
|
|
|
data, |
|
|
|
|
::testing::UnorderedElementsAre( |
|
|
|
|
::testing::Pair( |
|
|
|
|
kInt64CallbackGaugeMetric, |
|
|
|
|
::testing::Each(::testing::AnyOf( |
|
|
|
|
AttributesEq(kLabelKeys, kLabelValuesSet1, kOptionalLabelKeys, |
|
|
|
|
kOptionalLabelValuesSet1), |
|
|
|
|
AttributesEq(kLabelKeys, kLabelValuesSet2, kOptionalLabelKeys, |
|
|
|
|
kOptionalLabelValuesSet2)))), |
|
|
|
|
::testing::Pair( |
|
|
|
|
kDoubleCallbackGaugeMetric, |
|
|
|
|
::testing::Each(::testing::AnyOf( |
|
|
|
|
AttributesEq(kLabelKeys, kLabelValuesSet1, kOptionalLabelKeys, |
|
|
|
|
kOptionalLabelValuesSet1), |
|
|
|
|
AttributesEq(kLabelKeys, kLabelValuesSet2, kOptionalLabelKeys, |
|
|
|
|
kOptionalLabelValuesSet2)))))); |
|
|
|
|
EXPECT_THAT(data, GaugeDataIsIncrementalForSpecificMetricAndLabelSet( |
|
|
|
|
kInt64CallbackGaugeMetric, kLabelKeys, kLabelValuesSet1, |
|
|
|
|
kOptionalLabelKeys, kOptionalLabelValuesSet1, |
|
|
|
|
int64_t(0), false)); |
|
|
|
|
EXPECT_THAT(data, GaugeDataIsIncrementalForSpecificMetricAndLabelSet( |
|
|
|
|
kInt64CallbackGaugeMetric, kLabelKeys, kLabelValuesSet2, |
|
|
|
|
kOptionalLabelKeys, kOptionalLabelValuesSet2, |
|
|
|
|
int64_t(0), false)); |
|
|
|
|
EXPECT_THAT(data, |
|
|
|
|
GaugeDataIsIncrementalForSpecificMetricAndLabelSet( |
|
|
|
|
kDoubleCallbackGaugeMetric, kLabelKeys, kLabelValuesSet1, |
|
|
|
|
kOptionalLabelKeys, kOptionalLabelValuesSet1, 0.0, false)); |
|
|
|
|
EXPECT_THAT(data, |
|
|
|
|
GaugeDataIsIncrementalForSpecificMetricAndLabelSet( |
|
|
|
|
kDoubleCallbackGaugeMetric, kLabelKeys, kLabelValuesSet2, |
|
|
|
|
kOptionalLabelKeys, kOptionalLabelValuesSet2, 0.0, false)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// The callback minimal interval is shorter than the OT reporting interval, so
|
|
|
|
|
// for each collect we should go update the cache and report the latest values.
|
|
|
|
|
TEST_F(OpenTelemetryPluginCallbackMetricsTest, |
|
|
|
|
ReportDurationShorterThanCollectDuration) { |
|
|
|
|
constexpr absl::string_view kInt64CallbackGaugeMetric = |
|
|
|
|
"yet_another_int64_callback_gauge"; |
|
|
|
|
constexpr absl::string_view kDoubleCallbackGaugeMetric = |
|
|
|
|
"yet_another_double_callback_gauge"; |
|
|
|
|
constexpr std::array<absl::string_view, 2> kLabelKeys = {"label_key_1", |
|
|
|
|
"label_key_2"}; |
|
|
|
|
constexpr std::array<absl::string_view, 2> kOptionalLabelKeys = { |
|
|
|
|
"optional_label_key_1", "optional_label_key_2"}; |
|
|
|
|
constexpr std::array<absl::string_view, 2> kLabelValuesSet1 = { |
|
|
|
|
"label_value_set_1", "label_value_set_1"}; |
|
|
|
|
constexpr std::array<absl::string_view, 2> kOptionalLabelValuesSet1 = { |
|
|
|
|
"optional_label_value_set_1", "optional_label_value_set_1"}; |
|
|
|
|
constexpr std::array<absl::string_view, 2> kLabelValuesSet2 = { |
|
|
|
|
"label_value_set_2", "label_value_set_2"}; |
|
|
|
|
constexpr std::array<absl::string_view, 2> kOptionalLabelValuesSet2 = { |
|
|
|
|
"optional_label_value_set_2", "optional_label_value_set_2"}; |
|
|
|
|
auto integer_gauge_handle = |
|
|
|
|
grpc_core::GlobalInstrumentsRegistry::RegisterCallbackInt64Gauge( |
|
|
|
|
kInt64CallbackGaugeMetric, "An int64 callback gauge.", "unit", |
|
|
|
|
kLabelKeys, kOptionalLabelKeys, |
|
|
|
|
/*enable_by_default=*/true); |
|
|
|
|
auto double_gauge_handle = |
|
|
|
|
grpc_core::GlobalInstrumentsRegistry::RegisterCallbackDoubleGauge( |
|
|
|
|
kDoubleCallbackGaugeMetric, "A double callback gauge.", "unit", |
|
|
|
|
kLabelKeys, kOptionalLabelKeys, |
|
|
|
|
/*enable_by_default=*/true); |
|
|
|
|
Init(std::move(Options() |
|
|
|
|
.set_metric_names({kInt64CallbackGaugeMetric, |
|
|
|
|
kDoubleCallbackGaugeMetric}) |
|
|
|
|
.add_optional_label(kOptionalLabelKeys[0]) |
|
|
|
|
.add_optional_label(kOptionalLabelKeys[1]))); |
|
|
|
|
auto stats_plugins = |
|
|
|
|
grpc_core::GlobalStatsPluginRegistry::GetStatsPluginsForChannel( |
|
|
|
|
grpc_core::experimental::StatsPluginChannelScope( |
|
|
|
|
"dns:///localhost:8080", "")); |
|
|
|
|
// Multiple callbacks for the same metrics, each reporting different label
|
|
|
|
|
// values.
|
|
|
|
|
int report_count_1 = 0; |
|
|
|
|
int64_t int_value_1 = 1; |
|
|
|
|
double double_value_1 = 0.5; |
|
|
|
|
auto registered_metric_callback_1 = stats_plugins.RegisterCallback( |
|
|
|
|
[&](grpc_core::CallbackMetricReporter& reporter) { |
|
|
|
|
++report_count_1; |
|
|
|
|
reporter.Report(integer_gauge_handle, int_value_1, kLabelValuesSet1, |
|
|
|
|
kOptionalLabelValuesSet1); |
|
|
|
|
reporter.Report(integer_gauge_handle, int_value_1++, kLabelValuesSet2, |
|
|
|
|
kOptionalLabelValuesSet2); |
|
|
|
|
reporter.Report(double_gauge_handle, double_value_1, kLabelValuesSet1, |
|
|
|
|
kOptionalLabelValuesSet1); |
|
|
|
|
reporter.Report(double_gauge_handle, double_value_1++, kLabelValuesSet2, |
|
|
|
|
kOptionalLabelValuesSet2); |
|
|
|
|
}, |
|
|
|
|
{integer_gauge_handle, double_gauge_handle}, |
|
|
|
|
grpc_core::Duration::Milliseconds(10) * grpc_test_slowdown_factor()); |
|
|
|
|
int report_count_2 = 0; |
|
|
|
|
int64_t int_value_2 = 1; |
|
|
|
|
double double_value_2 = 0.5; |
|
|
|
|
auto registered_metric_callback_2 = stats_plugins.RegisterCallback( |
|
|
|
|
[&](grpc_core::CallbackMetricReporter& reporter) { |
|
|
|
|
++report_count_2; |
|
|
|
|
reporter.Report(integer_gauge_handle, int_value_2, kLabelValuesSet1, |
|
|
|
|
kOptionalLabelValuesSet1); |
|
|
|
|
reporter.Report(integer_gauge_handle, int_value_2++, kLabelValuesSet2, |
|
|
|
|
kOptionalLabelValuesSet2); |
|
|
|
|
reporter.Report(double_gauge_handle, double_value_2, kLabelValuesSet1, |
|
|
|
|
kOptionalLabelValuesSet1); |
|
|
|
|
reporter.Report(double_gauge_handle, double_value_2++, kLabelValuesSet2, |
|
|
|
|
kOptionalLabelValuesSet2); |
|
|
|
|
}, |
|
|
|
|
{integer_gauge_handle, double_gauge_handle}, |
|
|
|
|
grpc_core::Duration::Milliseconds(10) * grpc_test_slowdown_factor()); |
|
|
|
|
constexpr int kIterations = 100; |
|
|
|
|
MetricsCollectorThread collector{ |
|
|
|
|
this, |
|
|
|
|
grpc_core::Duration::Milliseconds(100) * grpc_test_slowdown_factor(), |
|
|
|
|
kIterations, |
|
|
|
|
[&](const absl::flat_hash_map< |
|
|
|
|
std::string, |
|
|
|
|
std::vector<opentelemetry::sdk::metrics::PointDataAttributes>>& |
|
|
|
|
data) { |
|
|
|
|
return !data.contains(kInt64CallbackGaugeMetric) || |
|
|
|
|
!data.contains(kDoubleCallbackGaugeMetric); |
|
|
|
|
}}; |
|
|
|
|
absl::flat_hash_map< |
|
|
|
|
std::string, |
|
|
|
|
std::vector<opentelemetry::sdk::metrics::PointDataAttributes>> |
|
|
|
|
data = collector.Stop(); |
|
|
|
|
// Verify that data is incremental without duplications (cached values).
|
|
|
|
|
EXPECT_EQ(report_count_1, kIterations); |
|
|
|
|
EXPECT_EQ(report_count_2, kIterations); |
|
|
|
|
EXPECT_EQ(data[kInt64CallbackGaugeMetric].size(), |
|
|
|
|
data[kDoubleCallbackGaugeMetric].size()); |
|
|
|
|
// Verify labels.
|
|
|
|
|
ASSERT_THAT( |
|
|
|
|
data, |
|
|
|
|
::testing::UnorderedElementsAre( |
|
|
|
|
::testing::Pair( |
|
|
|
|
kInt64CallbackGaugeMetric, |
|
|
|
|
::testing::Each(::testing::AnyOf( |
|
|
|
|
AttributesEq(kLabelKeys, kLabelValuesSet1, kOptionalLabelKeys, |
|
|
|
|
kOptionalLabelValuesSet1), |
|
|
|
|
AttributesEq(kLabelKeys, kLabelValuesSet2, kOptionalLabelKeys, |
|
|
|
|
kOptionalLabelValuesSet2)))), |
|
|
|
|
::testing::Pair( |
|
|
|
|
kDoubleCallbackGaugeMetric, |
|
|
|
|
::testing::Each(::testing::AnyOf( |
|
|
|
|
AttributesEq(kLabelKeys, kLabelValuesSet1, kOptionalLabelKeys, |
|
|
|
|
kOptionalLabelValuesSet1), |
|
|
|
|
AttributesEq(kLabelKeys, kLabelValuesSet2, kOptionalLabelKeys, |
|
|
|
|
kOptionalLabelValuesSet2)))))); |
|
|
|
|
EXPECT_THAT(data, GaugeDataIsIncrementalForSpecificMetricAndLabelSet( |
|
|
|
|
kInt64CallbackGaugeMetric, kLabelKeys, kLabelValuesSet1, |
|
|
|
|
kOptionalLabelKeys, kOptionalLabelValuesSet1, |
|
|
|
|
int64_t(0), true)); |
|
|
|
|
EXPECT_THAT(data, GaugeDataIsIncrementalForSpecificMetricAndLabelSet( |
|
|
|
|
kInt64CallbackGaugeMetric, kLabelKeys, kLabelValuesSet2, |
|
|
|
|
kOptionalLabelKeys, kOptionalLabelValuesSet2, |
|
|
|
|
int64_t(0), true)); |
|
|
|
|
EXPECT_THAT(data, |
|
|
|
|
GaugeDataIsIncrementalForSpecificMetricAndLabelSet( |
|
|
|
|
kDoubleCallbackGaugeMetric, kLabelKeys, kLabelValuesSet1, |
|
|
|
|
kOptionalLabelKeys, kOptionalLabelValuesSet1, 0.0, true)); |
|
|
|
|
EXPECT_THAT(data, |
|
|
|
|
GaugeDataIsIncrementalForSpecificMetricAndLabelSet( |
|
|
|
|
kDoubleCallbackGaugeMetric, kLabelKeys, kLabelValuesSet2, |
|
|
|
|
kOptionalLabelKeys, kOptionalLabelValuesSet2, 0.0, true)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
TEST(OpenTelemetryPluginMetricsEnablingDisablingTest, TestEnableDisableAPIs) { |
|
|
|
|