mirror of https://github.com/grpc/grpc.git
The C based gRPC (C++, Python, Ruby, Objective-C, PHP, C#)
https://grpc.io/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
677 lines
33 KiB
677 lines
33 KiB
// Copyright 2024 The gRPC Authors. |
|
// |
|
// Licensed under the Apache License, Version 2.0 (the "License"); |
|
// you may not use this file except in compliance with the License. |
|
// You may obtain a copy of the License at |
|
// |
|
// http://www.apache.org/licenses/LICENSE-2.0 |
|
// |
|
// Unless required by applicable law or agreed to in writing, software |
|
// distributed under the License is distributed on an "AS IS" BASIS, |
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
// See the License for the specific language governing permissions and |
|
// limitations under the License. |
|
|
|
#include "src/core/telemetry/metrics.h" |
|
|
|
#include <memory> |
|
|
|
#include "absl/log/log.h" |
|
#include "gmock/gmock.h" |
|
#include "gtest/gtest.h" |
|
|
|
#include "src/core/lib/event_engine/channel_args_endpoint_config.h" |
|
#include "test/core/test_util/fake_stats_plugin.h" |
|
#include "test/core/test_util/test_config.h" |
|
|
|
namespace grpc_core { |
|
namespace { |
|
|
|
using experimental::StatsPluginChannelScope; |
|
|
|
class MetricsTest : public ::testing::Test { |
|
protected: |
|
MetricsTest() : endpoint_config_(ChannelArgs()) {} |
|
|
|
void TearDown() override { |
|
GlobalInstrumentsRegistryTestPeer::ResetGlobalInstrumentsRegistry(); |
|
GlobalStatsPluginRegistryTestPeer::ResetGlobalStatsPluginRegistry(); |
|
} |
|
|
|
grpc_event_engine::experimental::ChannelArgsEndpointConfig endpoint_config_; |
|
}; |
|
|
|
TEST_F(MetricsTest, UInt64Counter) { |
|
auto uint64_counter_handle = |
|
GlobalInstrumentsRegistry::RegisterUInt64Counter( |
|
"uint64_counter", "A simple uint64 counter.", "unit", true) |
|
.Labels("label_key_1", "label_key_2") |
|
.OptionalLabels("optional_label_key_1", "optional_label_key_2") |
|
.Build(); |
|
std::array<absl::string_view, 2> kLabelValues = {"label_value_1", |
|
"label_value_2"}; |
|
std::array<absl::string_view, 2> kOptionalLabelValues = { |
|
"optional_label_value_1", "optional_label_value_2"}; |
|
constexpr absl::string_view kDomain1To4 = "domain1.domain2.domain3.domain4"; |
|
constexpr absl::string_view kDomain2To4 = "domain2.domain3.domain4"; |
|
constexpr absl::string_view kDomain3To4 = "domain3.domain4"; |
|
auto plugin1 = MakeStatsPluginForTarget(kDomain1To4); |
|
auto plugin2 = MakeStatsPluginForTarget(kDomain2To4); |
|
auto plugin3 = MakeStatsPluginForTarget(kDomain3To4); |
|
GlobalStatsPluginRegistry::GetStatsPluginsForChannel( |
|
StatsPluginChannelScope(kDomain1To4, "", endpoint_config_)) |
|
.AddCounter(uint64_counter_handle, uint64_t(1), kLabelValues, |
|
kOptionalLabelValues); |
|
GlobalStatsPluginRegistry::GetStatsPluginsForChannel( |
|
StatsPluginChannelScope(kDomain2To4, "", endpoint_config_)) |
|
.AddCounter(uint64_counter_handle, uint64_t(2), kLabelValues, |
|
kOptionalLabelValues); |
|
GlobalStatsPluginRegistry::GetStatsPluginsForChannel( |
|
StatsPluginChannelScope(kDomain3To4, "", endpoint_config_)) |
|
.AddCounter(uint64_counter_handle, uint64_t(3), kLabelValues, |
|
kOptionalLabelValues); |
|
EXPECT_THAT(plugin1->GetUInt64CounterValue( |
|
uint64_counter_handle, kLabelValues, kOptionalLabelValues), |
|
::testing::Optional(1)); |
|
EXPECT_THAT(plugin2->GetUInt64CounterValue( |
|
uint64_counter_handle, kLabelValues, kOptionalLabelValues), |
|
::testing::Optional(3)); |
|
EXPECT_THAT(plugin3->GetUInt64CounterValue( |
|
uint64_counter_handle, kLabelValues, kOptionalLabelValues), |
|
::testing::Optional(6)); |
|
} |
|
|
|
TEST_F(MetricsTest, DoubleCounter) { |
|
auto double_counter_handle = |
|
GlobalInstrumentsRegistry::RegisterDoubleCounter( |
|
"double_counter", "A simple double counter.", "unit", true) |
|
.Labels("label_key_1", "label_key_2") |
|
.OptionalLabels("optional_label_key_1", "optional_label_key_2") |
|
.Build(); |
|
std::array<absl::string_view, 2> kLabelValues = {"label_value_1", |
|
"label_value_2"}; |
|
std::array<absl::string_view, 2> kOptionalLabelValues = { |
|
"optional_label_value_1", "optional_label_value_2"}; |
|
constexpr absl::string_view kDomain1To4 = "domain1.domain2.domain3.domain4"; |
|
constexpr absl::string_view kDomain2To4 = "domain2.domain3.domain4"; |
|
constexpr absl::string_view kDomain3To4 = "domain3.domain4"; |
|
auto plugin1 = MakeStatsPluginForTarget(kDomain1To4); |
|
auto plugin2 = MakeStatsPluginForTarget(kDomain2To4); |
|
auto plugin3 = MakeStatsPluginForTarget(kDomain3To4); |
|
GlobalStatsPluginRegistry::GetStatsPluginsForChannel( |
|
StatsPluginChannelScope(kDomain1To4, "", endpoint_config_)) |
|
.AddCounter(double_counter_handle, 1.23, kLabelValues, |
|
kOptionalLabelValues); |
|
GlobalStatsPluginRegistry::GetStatsPluginsForChannel( |
|
StatsPluginChannelScope(kDomain2To4, "", endpoint_config_)) |
|
.AddCounter(double_counter_handle, 2.34, kLabelValues, |
|
kOptionalLabelValues); |
|
GlobalStatsPluginRegistry::GetStatsPluginsForChannel( |
|
StatsPluginChannelScope(kDomain3To4, "", endpoint_config_)) |
|
.AddCounter(double_counter_handle, 3.45, kLabelValues, |
|
kOptionalLabelValues); |
|
EXPECT_THAT(plugin1->GetDoubleCounterValue( |
|
double_counter_handle, kLabelValues, kOptionalLabelValues), |
|
::testing::Optional(1.23)); |
|
EXPECT_THAT(plugin2->GetDoubleCounterValue( |
|
double_counter_handle, kLabelValues, kOptionalLabelValues), |
|
::testing::Optional(3.57)); |
|
EXPECT_THAT(plugin3->GetDoubleCounterValue( |
|
double_counter_handle, kLabelValues, kOptionalLabelValues), |
|
::testing::Optional(7.02)); |
|
} |
|
|
|
TEST_F(MetricsTest, UInt64Histogram) { |
|
auto uint64_histogram_handle = |
|
GlobalInstrumentsRegistry::RegisterUInt64Histogram( |
|
"uint64_histogram", "A simple uint64 histogram.", "unit", true) |
|
.Labels("label_key_1", "label_key_2") |
|
.OptionalLabels("optional_label_key_1", "optional_label_key_2") |
|
.Build(); |
|
std::array<absl::string_view, 2> kLabelValues = {"label_value_1", |
|
"label_value_2"}; |
|
std::array<absl::string_view, 2> kOptionalLabelValues = { |
|
"optional_label_value_1", "optional_label_value_2"}; |
|
constexpr absl::string_view kDomain1To4 = "domain1.domain2.domain3.domain4"; |
|
constexpr absl::string_view kDomain2To4 = "domain2.domain3.domain4"; |
|
constexpr absl::string_view kDomain3To4 = "domain3.domain4"; |
|
auto plugin1 = MakeStatsPluginForTarget(kDomain1To4); |
|
auto plugin2 = MakeStatsPluginForTarget(kDomain2To4); |
|
auto plugin3 = MakeStatsPluginForTarget(kDomain3To4); |
|
GlobalStatsPluginRegistry::GetStatsPluginsForChannel( |
|
StatsPluginChannelScope(kDomain1To4, "", endpoint_config_)) |
|
.RecordHistogram(uint64_histogram_handle, uint64_t(1), kLabelValues, |
|
kOptionalLabelValues); |
|
GlobalStatsPluginRegistry::GetStatsPluginsForChannel( |
|
StatsPluginChannelScope(kDomain2To4, "", endpoint_config_)) |
|
.RecordHistogram(uint64_histogram_handle, uint64_t(2), kLabelValues, |
|
kOptionalLabelValues); |
|
GlobalStatsPluginRegistry::GetStatsPluginsForChannel( |
|
StatsPluginChannelScope(kDomain3To4, "", endpoint_config_)) |
|
.RecordHistogram(uint64_histogram_handle, uint64_t(3), kLabelValues, |
|
kOptionalLabelValues); |
|
EXPECT_THAT(plugin1->GetUInt64HistogramValue( |
|
uint64_histogram_handle, kLabelValues, kOptionalLabelValues), |
|
::testing::Optional(::testing::UnorderedElementsAre(1))); |
|
EXPECT_THAT(plugin2->GetUInt64HistogramValue( |
|
uint64_histogram_handle, kLabelValues, kOptionalLabelValues), |
|
::testing::Optional(::testing::UnorderedElementsAre(1, 2))); |
|
EXPECT_THAT(plugin3->GetUInt64HistogramValue( |
|
uint64_histogram_handle, kLabelValues, kOptionalLabelValues), |
|
::testing::Optional(::testing::UnorderedElementsAre(1, 2, 3))); |
|
} |
|
|
|
TEST_F(MetricsTest, DoubleHistogram) { |
|
auto double_histogram_handle = |
|
GlobalInstrumentsRegistry::RegisterDoubleHistogram( |
|
"double_histogram", "A simple double histogram.", "unit", true) |
|
.Labels("label_key_1", "label_key_2") |
|
.OptionalLabels("optional_label_key_1", "optional_label_key_2") |
|
.Build(); |
|
std::array<absl::string_view, 2> kLabelValues = {"label_value_1", |
|
"label_value_2"}; |
|
std::array<absl::string_view, 2> kOptionalLabelValues = { |
|
"optional_label_value_1", "optional_label_value_2"}; |
|
constexpr absl::string_view kDomain1To4 = "domain1.domain2.domain3.domain4"; |
|
constexpr absl::string_view kDomain2To4 = "domain2.domain3.domain4"; |
|
constexpr absl::string_view kDomain3To4 = "domain3.domain4"; |
|
auto plugin1 = MakeStatsPluginForTarget(kDomain1To4); |
|
auto plugin2 = MakeStatsPluginForTarget(kDomain2To4); |
|
auto plugin3 = MakeStatsPluginForTarget(kDomain3To4); |
|
GlobalStatsPluginRegistry::GetStatsPluginsForChannel( |
|
StatsPluginChannelScope(kDomain1To4, "", endpoint_config_)) |
|
.RecordHistogram(double_histogram_handle, 1.23, kLabelValues, |
|
kOptionalLabelValues); |
|
GlobalStatsPluginRegistry::GetStatsPluginsForChannel( |
|
StatsPluginChannelScope(kDomain2To4, "", endpoint_config_)) |
|
.RecordHistogram(double_histogram_handle, 2.34, kLabelValues, |
|
kOptionalLabelValues); |
|
GlobalStatsPluginRegistry::GetStatsPluginsForChannel( |
|
StatsPluginChannelScope(kDomain3To4, "", endpoint_config_)) |
|
.RecordHistogram(double_histogram_handle, 3.45, kLabelValues, |
|
kOptionalLabelValues); |
|
EXPECT_THAT(plugin1->GetDoubleHistogramValue( |
|
double_histogram_handle, kLabelValues, kOptionalLabelValues), |
|
::testing::Optional(::testing::UnorderedElementsAre(1.23))); |
|
EXPECT_THAT(plugin2->GetDoubleHistogramValue( |
|
double_histogram_handle, kLabelValues, kOptionalLabelValues), |
|
::testing::Optional(::testing::UnorderedElementsAre(1.23, 2.34))); |
|
EXPECT_THAT( |
|
plugin3->GetDoubleHistogramValue(double_histogram_handle, kLabelValues, |
|
kOptionalLabelValues), |
|
::testing::Optional(::testing::UnorderedElementsAre(1.23, 2.34, 3.45))); |
|
} |
|
|
|
TEST_F(MetricsTest, Int64CallbackGauge) { |
|
auto int64_gauge_handle = |
|
GlobalInstrumentsRegistry::RegisterCallbackInt64Gauge( |
|
"int64_gauge", "A simple int64 gauge.", "unit", true) |
|
.Labels("label_key_1", "label_key_2") |
|
.OptionalLabels("optional_label_key_1", "optional_label_key_2") |
|
.Build(); |
|
std::array<absl::string_view, 2> kLabelValues = {"label_value_1", |
|
"label_value_2"}; |
|
std::array<absl::string_view, 2> kLabelValues2 = {"label_value_3", |
|
"label_value_2"}; |
|
std::array<absl::string_view, 2> kOptionalLabelValues = { |
|
"optional_label_value_1", "optional_label_value_2"}; |
|
constexpr absl::string_view kDomain1To4 = "domain1.domain2.domain3.domain4"; |
|
constexpr absl::string_view kDomain2To4 = "domain2.domain3.domain4"; |
|
constexpr absl::string_view kDomain3To4 = "domain3.domain4"; |
|
auto plugin1 = MakeStatsPluginForTarget(kDomain3To4); |
|
auto plugin2 = MakeStatsPluginForTarget(kDomain2To4); |
|
auto plugin3 = MakeStatsPluginForTarget(kDomain1To4); |
|
// Register two callbacks that set the same metric but with different |
|
// label values. The callbacks get used only by plugin1. |
|
LOG(INFO) << "testing callbacks for: plugin1"; |
|
auto group1 = GlobalStatsPluginRegistry::GetStatsPluginsForChannel( |
|
StatsPluginChannelScope(kDomain3To4, "", endpoint_config_)); |
|
auto callback1 = group1.RegisterCallback( |
|
[&](CallbackMetricReporter& reporter) { |
|
reporter.Report(int64_gauge_handle, int64_t(1), kLabelValues, |
|
kOptionalLabelValues); |
|
}, |
|
Duration::Seconds(5), int64_gauge_handle); |
|
auto callback2 = group1.RegisterCallback( |
|
[&](CallbackMetricReporter& reporter) { |
|
reporter.Report(int64_gauge_handle, int64_t(2), kLabelValues2, |
|
kOptionalLabelValues); |
|
}, |
|
Duration::Seconds(5), int64_gauge_handle); |
|
// No plugins have data yet. |
|
EXPECT_EQ(plugin1->GetInt64CallbackGaugeValue( |
|
int64_gauge_handle, kLabelValues, kOptionalLabelValues), |
|
absl::nullopt); |
|
EXPECT_EQ(plugin1->GetInt64CallbackGaugeValue( |
|
int64_gauge_handle, kLabelValues2, kOptionalLabelValues), |
|
absl::nullopt); |
|
EXPECT_EQ(plugin2->GetInt64CallbackGaugeValue( |
|
int64_gauge_handle, kLabelValues, kOptionalLabelValues), |
|
absl::nullopt); |
|
EXPECT_EQ(plugin2->GetInt64CallbackGaugeValue( |
|
int64_gauge_handle, kLabelValues2, kOptionalLabelValues), |
|
absl::nullopt); |
|
EXPECT_EQ(plugin3->GetInt64CallbackGaugeValue( |
|
int64_gauge_handle, kLabelValues, kOptionalLabelValues), |
|
absl::nullopt); |
|
EXPECT_EQ(plugin3->GetInt64CallbackGaugeValue( |
|
int64_gauge_handle, kLabelValues2, kOptionalLabelValues), |
|
absl::nullopt); |
|
// Now invoke the callbacks. |
|
plugin1->TriggerCallbacks(); |
|
plugin2->TriggerCallbacks(); |
|
plugin3->TriggerCallbacks(); |
|
// Now plugin1 should have data, but the others should not. |
|
EXPECT_THAT(plugin1->GetInt64CallbackGaugeValue( |
|
int64_gauge_handle, kLabelValues, kOptionalLabelValues), |
|
::testing::Optional(1)); |
|
EXPECT_THAT(plugin1->GetInt64CallbackGaugeValue( |
|
int64_gauge_handle, kLabelValues2, kOptionalLabelValues), |
|
::testing::Optional(2)); |
|
EXPECT_EQ(plugin2->GetInt64CallbackGaugeValue( |
|
int64_gauge_handle, kLabelValues, kOptionalLabelValues), |
|
absl::nullopt); |
|
EXPECT_EQ(plugin2->GetInt64CallbackGaugeValue( |
|
int64_gauge_handle, kLabelValues2, kOptionalLabelValues), |
|
absl::nullopt); |
|
EXPECT_EQ(plugin3->GetInt64CallbackGaugeValue( |
|
int64_gauge_handle, kLabelValues, kOptionalLabelValues), |
|
absl::nullopt); |
|
EXPECT_EQ(plugin3->GetInt64CallbackGaugeValue( |
|
int64_gauge_handle, kLabelValues2, kOptionalLabelValues), |
|
absl::nullopt); |
|
// De-register the callbacks. |
|
callback1.reset(); |
|
callback2.reset(); |
|
// Now register callbacks that hit both plugin1 and plugin2. |
|
LOG(INFO) << "testing callbacks for: plugin1, plugin2"; |
|
auto group2 = GlobalStatsPluginRegistry::GetStatsPluginsForChannel( |
|
StatsPluginChannelScope(kDomain2To4, "", endpoint_config_)); |
|
callback1 = group2.RegisterCallback( |
|
[&](CallbackMetricReporter& reporter) { |
|
reporter.Report(int64_gauge_handle, int64_t(3), kLabelValues, |
|
kOptionalLabelValues); |
|
}, |
|
Duration::Seconds(5), int64_gauge_handle); |
|
callback2 = group2.RegisterCallback( |
|
[&](CallbackMetricReporter& reporter) { |
|
reporter.Report(int64_gauge_handle, int64_t(4), kLabelValues2, |
|
kOptionalLabelValues); |
|
}, |
|
Duration::Seconds(5), int64_gauge_handle); |
|
// Plugin1 still has data from before, but the others have none. |
|
EXPECT_THAT(plugin1->GetInt64CallbackGaugeValue( |
|
int64_gauge_handle, kLabelValues, kOptionalLabelValues), |
|
::testing::Optional(1)); |
|
EXPECT_THAT(plugin1->GetInt64CallbackGaugeValue( |
|
int64_gauge_handle, kLabelValues2, kOptionalLabelValues), |
|
::testing::Optional(2)); |
|
EXPECT_EQ(plugin2->GetInt64CallbackGaugeValue( |
|
int64_gauge_handle, kLabelValues, kOptionalLabelValues), |
|
absl::nullopt); |
|
EXPECT_EQ(plugin2->GetInt64CallbackGaugeValue( |
|
int64_gauge_handle, kLabelValues2, kOptionalLabelValues), |
|
absl::nullopt); |
|
EXPECT_EQ(plugin3->GetInt64CallbackGaugeValue( |
|
int64_gauge_handle, kLabelValues, kOptionalLabelValues), |
|
absl::nullopt); |
|
EXPECT_EQ(plugin3->GetInt64CallbackGaugeValue( |
|
int64_gauge_handle, kLabelValues2, kOptionalLabelValues), |
|
absl::nullopt); |
|
// Now invoke the callbacks. |
|
plugin1->TriggerCallbacks(); |
|
plugin2->TriggerCallbacks(); |
|
plugin3->TriggerCallbacks(); |
|
// Now plugin1 and plugin2 should have data, but plugin3 should not. |
|
EXPECT_THAT(plugin1->GetInt64CallbackGaugeValue( |
|
int64_gauge_handle, kLabelValues, kOptionalLabelValues), |
|
::testing::Optional(3)); |
|
EXPECT_THAT(plugin1->GetInt64CallbackGaugeValue( |
|
int64_gauge_handle, kLabelValues2, kOptionalLabelValues), |
|
::testing::Optional(4)); |
|
EXPECT_THAT(plugin2->GetInt64CallbackGaugeValue( |
|
int64_gauge_handle, kLabelValues, kOptionalLabelValues), |
|
::testing::Optional(3)); |
|
EXPECT_THAT(plugin2->GetInt64CallbackGaugeValue( |
|
int64_gauge_handle, kLabelValues2, kOptionalLabelValues), |
|
::testing::Optional(4)); |
|
EXPECT_EQ(plugin3->GetInt64CallbackGaugeValue( |
|
int64_gauge_handle, kLabelValues, kOptionalLabelValues), |
|
absl::nullopt); |
|
EXPECT_EQ(plugin3->GetInt64CallbackGaugeValue( |
|
int64_gauge_handle, kLabelValues2, kOptionalLabelValues), |
|
absl::nullopt); |
|
// De-register the callbacks. |
|
callback1.reset(); |
|
callback2.reset(); |
|
// Now register callbacks that hit all three plugins. |
|
LOG(INFO) << "testing callbacks for: plugin1, plugin2, plugin3"; |
|
auto group3 = GlobalStatsPluginRegistry::GetStatsPluginsForChannel( |
|
StatsPluginChannelScope(kDomain1To4, "", endpoint_config_)); |
|
callback1 = group3.RegisterCallback( |
|
[&](CallbackMetricReporter& reporter) { |
|
reporter.Report(int64_gauge_handle, int64_t(5), kLabelValues, |
|
kOptionalLabelValues); |
|
}, |
|
Duration::Seconds(5), int64_gauge_handle); |
|
callback2 = group3.RegisterCallback( |
|
[&](CallbackMetricReporter& reporter) { |
|
reporter.Report(int64_gauge_handle, int64_t(6), kLabelValues2, |
|
kOptionalLabelValues); |
|
}, |
|
Duration::Seconds(5), int64_gauge_handle); |
|
// Plugin1 and plugin2 still has data from before, but plugin3 has none. |
|
EXPECT_THAT(plugin1->GetInt64CallbackGaugeValue( |
|
int64_gauge_handle, kLabelValues, kOptionalLabelValues), |
|
::testing::Optional(3)); |
|
EXPECT_THAT(plugin1->GetInt64CallbackGaugeValue( |
|
int64_gauge_handle, kLabelValues2, kOptionalLabelValues), |
|
::testing::Optional(4)); |
|
EXPECT_THAT(plugin2->GetInt64CallbackGaugeValue( |
|
int64_gauge_handle, kLabelValues, kOptionalLabelValues), |
|
::testing::Optional(3)); |
|
EXPECT_THAT(plugin2->GetInt64CallbackGaugeValue( |
|
int64_gauge_handle, kLabelValues2, kOptionalLabelValues), |
|
::testing::Optional(4)); |
|
EXPECT_EQ(plugin3->GetInt64CallbackGaugeValue( |
|
int64_gauge_handle, kLabelValues, kOptionalLabelValues), |
|
absl::nullopt); |
|
EXPECT_EQ(plugin3->GetInt64CallbackGaugeValue( |
|
int64_gauge_handle, kLabelValues2, kOptionalLabelValues), |
|
absl::nullopt); |
|
// Now invoke the callbacks. |
|
plugin1->TriggerCallbacks(); |
|
plugin2->TriggerCallbacks(); |
|
plugin3->TriggerCallbacks(); |
|
// Now plugin1 and plugin2 should have data, but plugin3 should not. |
|
EXPECT_THAT(plugin1->GetInt64CallbackGaugeValue( |
|
int64_gauge_handle, kLabelValues, kOptionalLabelValues), |
|
::testing::Optional(5)); |
|
EXPECT_THAT(plugin1->GetInt64CallbackGaugeValue( |
|
int64_gauge_handle, kLabelValues2, kOptionalLabelValues), |
|
::testing::Optional(6)); |
|
EXPECT_THAT(plugin2->GetInt64CallbackGaugeValue( |
|
int64_gauge_handle, kLabelValues, kOptionalLabelValues), |
|
::testing::Optional(5)); |
|
EXPECT_THAT(plugin2->GetInt64CallbackGaugeValue( |
|
int64_gauge_handle, kLabelValues2, kOptionalLabelValues), |
|
::testing::Optional(6)); |
|
EXPECT_THAT(plugin3->GetInt64CallbackGaugeValue( |
|
int64_gauge_handle, kLabelValues, kOptionalLabelValues), |
|
::testing::Optional(5)); |
|
EXPECT_THAT(plugin3->GetInt64CallbackGaugeValue( |
|
int64_gauge_handle, kLabelValues2, kOptionalLabelValues), |
|
::testing::Optional(6)); |
|
// Need to destroy callbacks before the plugin group that created them. |
|
callback1.reset(); |
|
callback2.reset(); |
|
} |
|
|
|
TEST_F(MetricsTest, DoubleCallbackGauge) { |
|
auto double_gauge_handle = |
|
GlobalInstrumentsRegistry::RegisterCallbackDoubleGauge( |
|
"double_gauge", "A simple double gauge.", "unit", true) |
|
.Labels("label_key_1", "label_key_2") |
|
.OptionalLabels("optional_label_key_1", "optional_label_key_2") |
|
.Build(); |
|
std::array<absl::string_view, 2> kLabelValues = {"label_value_1", |
|
"label_value_2"}; |
|
std::array<absl::string_view, 2> kLabelValues2 = {"label_value_3", |
|
"label_value_2"}; |
|
std::array<absl::string_view, 2> kOptionalLabelValues = { |
|
"optional_label_value_1", "optional_label_value_2"}; |
|
constexpr absl::string_view kDomain1To4 = "domain1.domain2.domain3.domain4"; |
|
constexpr absl::string_view kDomain2To4 = "domain2.domain3.domain4"; |
|
constexpr absl::string_view kDomain3To4 = "domain3.domain4"; |
|
auto plugin1 = MakeStatsPluginForTarget(kDomain3To4); |
|
auto plugin2 = MakeStatsPluginForTarget(kDomain2To4); |
|
auto plugin3 = MakeStatsPluginForTarget(kDomain1To4); |
|
// Register two callbacks that set the same metric but with different |
|
// label values. The callbacks get used only by plugin1. |
|
LOG(INFO) << "testing callbacks for: plugin1"; |
|
auto group1 = GlobalStatsPluginRegistry::GetStatsPluginsForChannel( |
|
StatsPluginChannelScope(kDomain3To4, "", endpoint_config_)); |
|
auto callback1 = group1.RegisterCallback( |
|
[&](CallbackMetricReporter& reporter) { |
|
reporter.Report(double_gauge_handle, 1.23, kLabelValues, |
|
kOptionalLabelValues); |
|
}, |
|
Duration::Seconds(5), double_gauge_handle); |
|
auto callback2 = group1.RegisterCallback( |
|
[&](CallbackMetricReporter& reporter) { |
|
reporter.Report(double_gauge_handle, 2.34, kLabelValues2, |
|
kOptionalLabelValues); |
|
}, |
|
Duration::Seconds(5), double_gauge_handle); |
|
// No plugins have data yet. |
|
EXPECT_EQ(plugin1->GetDoubleCallbackGaugeValue( |
|
double_gauge_handle, kLabelValues, kOptionalLabelValues), |
|
absl::nullopt); |
|
EXPECT_EQ(plugin1->GetDoubleCallbackGaugeValue( |
|
double_gauge_handle, kLabelValues2, kOptionalLabelValues), |
|
absl::nullopt); |
|
EXPECT_EQ(plugin2->GetDoubleCallbackGaugeValue( |
|
double_gauge_handle, kLabelValues, kOptionalLabelValues), |
|
absl::nullopt); |
|
EXPECT_EQ(plugin2->GetDoubleCallbackGaugeValue( |
|
double_gauge_handle, kLabelValues2, kOptionalLabelValues), |
|
absl::nullopt); |
|
EXPECT_EQ(plugin3->GetDoubleCallbackGaugeValue( |
|
double_gauge_handle, kLabelValues, kOptionalLabelValues), |
|
absl::nullopt); |
|
EXPECT_EQ(plugin3->GetDoubleCallbackGaugeValue( |
|
double_gauge_handle, kLabelValues2, kOptionalLabelValues), |
|
absl::nullopt); |
|
// Now invoke the callbacks. |
|
plugin1->TriggerCallbacks(); |
|
plugin2->TriggerCallbacks(); |
|
plugin3->TriggerCallbacks(); |
|
// Now plugin1 should have data, but the others should not. |
|
EXPECT_THAT(plugin1->GetDoubleCallbackGaugeValue( |
|
double_gauge_handle, kLabelValues, kOptionalLabelValues), |
|
::testing::Optional(1.23)); |
|
EXPECT_THAT(plugin1->GetDoubleCallbackGaugeValue( |
|
double_gauge_handle, kLabelValues2, kOptionalLabelValues), |
|
::testing::Optional(2.34)); |
|
EXPECT_EQ(plugin2->GetDoubleCallbackGaugeValue( |
|
double_gauge_handle, kLabelValues, kOptionalLabelValues), |
|
absl::nullopt); |
|
EXPECT_EQ(plugin2->GetDoubleCallbackGaugeValue( |
|
double_gauge_handle, kLabelValues2, kOptionalLabelValues), |
|
absl::nullopt); |
|
EXPECT_EQ(plugin3->GetDoubleCallbackGaugeValue( |
|
double_gauge_handle, kLabelValues, kOptionalLabelValues), |
|
absl::nullopt); |
|
EXPECT_EQ(plugin3->GetDoubleCallbackGaugeValue( |
|
double_gauge_handle, kLabelValues2, kOptionalLabelValues), |
|
absl::nullopt); |
|
// De-register the callbacks. |
|
callback1.reset(); |
|
callback2.reset(); |
|
// Now register callbacks that hit both plugin1 and plugin2. |
|
LOG(INFO) << "testing callbacks for: plugin1, plugin2"; |
|
auto group2 = GlobalStatsPluginRegistry::GetStatsPluginsForChannel( |
|
StatsPluginChannelScope(kDomain2To4, "", endpoint_config_)); |
|
callback1 = group2.RegisterCallback( |
|
[&](CallbackMetricReporter& reporter) { |
|
reporter.Report(double_gauge_handle, 3.45, kLabelValues, |
|
kOptionalLabelValues); |
|
}, |
|
Duration::Seconds(5), double_gauge_handle); |
|
callback2 = group2.RegisterCallback( |
|
[&](CallbackMetricReporter& reporter) { |
|
reporter.Report(double_gauge_handle, 4.56, kLabelValues2, |
|
kOptionalLabelValues); |
|
}, |
|
Duration::Seconds(5), double_gauge_handle); |
|
// Plugin1 still has data from before, but the others have none. |
|
EXPECT_THAT(plugin1->GetDoubleCallbackGaugeValue( |
|
double_gauge_handle, kLabelValues, kOptionalLabelValues), |
|
::testing::Optional(1.23)); |
|
EXPECT_THAT(plugin1->GetDoubleCallbackGaugeValue( |
|
double_gauge_handle, kLabelValues2, kOptionalLabelValues), |
|
::testing::Optional(2.34)); |
|
EXPECT_EQ(plugin2->GetDoubleCallbackGaugeValue( |
|
double_gauge_handle, kLabelValues, kOptionalLabelValues), |
|
absl::nullopt); |
|
EXPECT_EQ(plugin2->GetDoubleCallbackGaugeValue( |
|
double_gauge_handle, kLabelValues2, kOptionalLabelValues), |
|
absl::nullopt); |
|
EXPECT_EQ(plugin3->GetDoubleCallbackGaugeValue( |
|
double_gauge_handle, kLabelValues, kOptionalLabelValues), |
|
absl::nullopt); |
|
EXPECT_EQ(plugin3->GetDoubleCallbackGaugeValue( |
|
double_gauge_handle, kLabelValues2, kOptionalLabelValues), |
|
absl::nullopt); |
|
// Now invoke the callbacks. |
|
plugin1->TriggerCallbacks(); |
|
plugin2->TriggerCallbacks(); |
|
plugin3->TriggerCallbacks(); |
|
// Now plugin1 and plugin2 should have data, but plugin3 should not. |
|
EXPECT_THAT(plugin1->GetDoubleCallbackGaugeValue( |
|
double_gauge_handle, kLabelValues, kOptionalLabelValues), |
|
::testing::Optional(3.45)); |
|
EXPECT_THAT(plugin1->GetDoubleCallbackGaugeValue( |
|
double_gauge_handle, kLabelValues2, kOptionalLabelValues), |
|
::testing::Optional(4.56)); |
|
EXPECT_THAT(plugin2->GetDoubleCallbackGaugeValue( |
|
double_gauge_handle, kLabelValues, kOptionalLabelValues), |
|
::testing::Optional(3.45)); |
|
EXPECT_THAT(plugin2->GetDoubleCallbackGaugeValue( |
|
double_gauge_handle, kLabelValues2, kOptionalLabelValues), |
|
::testing::Optional(4.56)); |
|
EXPECT_EQ(plugin3->GetDoubleCallbackGaugeValue( |
|
double_gauge_handle, kLabelValues, kOptionalLabelValues), |
|
absl::nullopt); |
|
EXPECT_EQ(plugin3->GetDoubleCallbackGaugeValue( |
|
double_gauge_handle, kLabelValues2, kOptionalLabelValues), |
|
absl::nullopt); |
|
// De-register the callbacks. |
|
callback1.reset(); |
|
callback2.reset(); |
|
// Now register callbacks that hit all three plugins. |
|
LOG(INFO) << "testing callbacks for: plugin1, plugin2, plugin3"; |
|
auto group3 = GlobalStatsPluginRegistry::GetStatsPluginsForChannel( |
|
StatsPluginChannelScope(kDomain1To4, "", endpoint_config_)); |
|
callback1 = group3.RegisterCallback( |
|
[&](CallbackMetricReporter& reporter) { |
|
reporter.Report(double_gauge_handle, 5.67, kLabelValues, |
|
kOptionalLabelValues); |
|
}, |
|
Duration::Seconds(5), double_gauge_handle); |
|
callback2 = group3.RegisterCallback( |
|
[&](CallbackMetricReporter& reporter) { |
|
reporter.Report(double_gauge_handle, 6.78, kLabelValues2, |
|
kOptionalLabelValues); |
|
}, |
|
Duration::Seconds(5), double_gauge_handle); |
|
// Plugin1 and plugin2 still has data from before, but plugin3 has none. |
|
EXPECT_THAT(plugin1->GetDoubleCallbackGaugeValue( |
|
double_gauge_handle, kLabelValues, kOptionalLabelValues), |
|
::testing::Optional(3.45)); |
|
EXPECT_THAT(plugin1->GetDoubleCallbackGaugeValue( |
|
double_gauge_handle, kLabelValues2, kOptionalLabelValues), |
|
::testing::Optional(4.56)); |
|
EXPECT_THAT(plugin2->GetDoubleCallbackGaugeValue( |
|
double_gauge_handle, kLabelValues, kOptionalLabelValues), |
|
::testing::Optional(3.45)); |
|
EXPECT_THAT(plugin2->GetDoubleCallbackGaugeValue( |
|
double_gauge_handle, kLabelValues2, kOptionalLabelValues), |
|
::testing::Optional(4.56)); |
|
EXPECT_EQ(plugin3->GetDoubleCallbackGaugeValue( |
|
double_gauge_handle, kLabelValues, kOptionalLabelValues), |
|
absl::nullopt); |
|
EXPECT_EQ(plugin3->GetDoubleCallbackGaugeValue( |
|
double_gauge_handle, kLabelValues2, kOptionalLabelValues), |
|
absl::nullopt); |
|
// Now invoke the callbacks. |
|
plugin1->TriggerCallbacks(); |
|
plugin2->TriggerCallbacks(); |
|
plugin3->TriggerCallbacks(); |
|
// Now plugin1 and plugin2 should have data, but plugin3 should not. |
|
EXPECT_THAT(plugin1->GetDoubleCallbackGaugeValue( |
|
double_gauge_handle, kLabelValues, kOptionalLabelValues), |
|
::testing::Optional(5.67)); |
|
EXPECT_THAT(plugin1->GetDoubleCallbackGaugeValue( |
|
double_gauge_handle, kLabelValues2, kOptionalLabelValues), |
|
::testing::Optional(6.78)); |
|
EXPECT_THAT(plugin2->GetDoubleCallbackGaugeValue( |
|
double_gauge_handle, kLabelValues, kOptionalLabelValues), |
|
::testing::Optional(5.67)); |
|
EXPECT_THAT(plugin2->GetDoubleCallbackGaugeValue( |
|
double_gauge_handle, kLabelValues2, kOptionalLabelValues), |
|
::testing::Optional(6.78)); |
|
EXPECT_THAT(plugin3->GetDoubleCallbackGaugeValue( |
|
double_gauge_handle, kLabelValues, kOptionalLabelValues), |
|
::testing::Optional(5.67)); |
|
EXPECT_THAT(plugin3->GetDoubleCallbackGaugeValue( |
|
double_gauge_handle, kLabelValues2, kOptionalLabelValues), |
|
::testing::Optional(6.78)); |
|
// Need to destroy callbacks before the plugin group that created them. |
|
callback1.reset(); |
|
callback2.reset(); |
|
} |
|
|
|
TEST_F(MetricsTest, DisableByDefaultMetricIsNotRecordedByFakeStatsPlugin) { |
|
auto double_histogram_handle = |
|
GlobalInstrumentsRegistry::RegisterDoubleHistogram( |
|
"double_histogram", "A simple double histogram.", "unit", false) |
|
.Labels("label_key_1", "label_key_2") |
|
.OptionalLabels("optional_label_key_1", "optional_label_key_2") |
|
.Build(); |
|
std::array<absl::string_view, 2> kLabelValues = {"label_value_1", |
|
"label_value_2"}; |
|
std::array<absl::string_view, 2> kOptionalLabelValues = { |
|
"optional_label_value_1", "optional_label_value_2"}; |
|
constexpr absl::string_view kDomain1To4 = "domain1.domain2.domain3.domain4"; |
|
auto plugin = MakeStatsPluginForTarget(kDomain1To4); |
|
GlobalStatsPluginRegistry::GetStatsPluginsForChannel( |
|
StatsPluginChannelScope(kDomain1To4, "", endpoint_config_)) |
|
.RecordHistogram(double_histogram_handle, 1.23, kLabelValues, |
|
kOptionalLabelValues); |
|
EXPECT_EQ(plugin->GetDoubleHistogramValue(double_histogram_handle, |
|
kLabelValues, kOptionalLabelValues), |
|
absl::nullopt); |
|
} |
|
|
|
TEST_F(MetricsTest, FindInstrumentByName) { |
|
auto uint64_counter_handle = |
|
GlobalInstrumentsRegistry::RegisterUInt64Counter( |
|
"uint64_counter", "A simple uint64 counter.", "unit", true) |
|
.Labels("label_key_1", "label_key_2") |
|
.OptionalLabels("optional_label_key_1", "optional_label_key_2") |
|
.Build(); |
|
auto instrument = |
|
GlobalInstrumentsRegistry::FindInstrumentByName("uint64_counter"); |
|
EXPECT_THAT(instrument, |
|
::testing::Optional(::testing::Field( |
|
&GlobalInstrumentsRegistry::GlobalInstrumentHandle::index, |
|
::testing::Eq(uint64_counter_handle.index)))); |
|
} |
|
|
|
using MetricsDeathTest = MetricsTest; |
|
|
|
TEST_F(MetricsDeathTest, RegisterTheSameMetricNameWouldCrash) { |
|
(void)GlobalInstrumentsRegistry::RegisterDoubleHistogram( |
|
"double_histogram", "A simple double histogram.", "unit", true) |
|
.Labels("label_key_1", "label_key_2") |
|
.OptionalLabels("optional_label_key_1", "optional_label_key_2") |
|
.Build(); |
|
EXPECT_DEATH( |
|
GlobalInstrumentsRegistry::RegisterDoubleHistogram( |
|
"double_histogram", "A simple double histogram.", "unit", true) |
|
.Labels("label_key_1", "label_key_2") |
|
.OptionalLabels("optional_label_key_1", "optional_label_key_2") |
|
.Build(), |
|
"Metric name double_histogram has already been registered."); |
|
} |
|
|
|
} // namespace |
|
} // namespace grpc_core |
|
|
|
int main(int argc, char** argv) { |
|
grpc::testing::TestEnvironment env(&argc, argv); |
|
::testing::InitGoogleTest(&argc, argv); |
|
int ret = RUN_ALL_TESTS(); |
|
return ret; |
|
}
|
|
|