xref: /aosp_15_r20/external/grpc-grpc/test/core/channel/metrics_test.cc (revision cc02d7e222339f7a4f6ba5f422e6413f4bd931f2)
1 // Copyright 2024 The gRPC Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "src/core/lib/channel/metrics.h"
16 
17 #include <memory>
18 
19 #include "absl/container/flat_hash_map.h"
20 #include "absl/strings/match.h"
21 #include "absl/strings/str_cat.h"
22 #include "absl/strings/str_join.h"
23 #include "gmock/gmock.h"
24 #include "gtest/gtest.h"
25 
26 #include "test/core/util/fake_stats_plugin.h"
27 #include "test/core/util/test_config.h"
28 
29 namespace grpc_core {
30 namespace {
31 
32 using experimental::StatsPluginChannelScope;
33 
34 class MetricsTest : public ::testing::Test {
35  public:
TearDown()36   void TearDown() override {
37     GlobalInstrumentsRegistryTestPeer::ResetGlobalInstrumentsRegistry();
38     GlobalStatsPluginRegistryTestPeer::ResetGlobalStatsPluginRegistry();
39   }
40 };
41 
TEST_F(MetricsTest,UInt64Counter)42 TEST_F(MetricsTest, UInt64Counter) {
43   const absl::string_view kLabelKeys[] = {"label_key_1", "label_key_2"};
44   const absl::string_view kOptionalLabelKeys[] = {"optional_label_key_1",
45                                                   "optional_label_key_2"};
46   auto uint64_counter_handle = GlobalInstrumentsRegistry::RegisterUInt64Counter(
47       "uint64_counter", "A simple uint64 counter.", "unit", kLabelKeys,
48       kOptionalLabelKeys, true);
49   constexpr absl::string_view kLabelValues[] = {"label_value_1",
50                                                 "label_value_2"};
51   constexpr absl::string_view kOptionalLabelValues[] = {
52       "optional_label_value_1", "optional_label_value_2"};
53   constexpr absl::string_view kDomain1To4 = "domain1.domain2.domain3.domain4";
54   constexpr absl::string_view kDomain2To4 = "domain2.domain3.domain4";
55   constexpr absl::string_view kDomain3To4 = "domain3.domain4";
56   auto plugin1 = MakeStatsPluginForTarget(kDomain1To4);
57   auto plugin2 = MakeStatsPluginForTarget(kDomain2To4);
58   auto plugin3 = MakeStatsPluginForTarget(kDomain3To4);
59   GlobalStatsPluginRegistry::GetStatsPluginsForChannel(
60       StatsPluginChannelScope(kDomain1To4, ""))
61       .AddCounter(uint64_counter_handle, 1, kLabelValues, kOptionalLabelValues);
62   GlobalStatsPluginRegistry::GetStatsPluginsForChannel(
63       StatsPluginChannelScope(kDomain2To4, ""))
64       .AddCounter(uint64_counter_handle, 2, kLabelValues, kOptionalLabelValues);
65   GlobalStatsPluginRegistry::GetStatsPluginsForChannel(
66       StatsPluginChannelScope(kDomain3To4, ""))
67       .AddCounter(uint64_counter_handle, 3, kLabelValues, kOptionalLabelValues);
68   EXPECT_THAT(plugin1->GetCounterValue(uint64_counter_handle, kLabelValues,
69                                        kOptionalLabelValues),
70               ::testing::Optional(1));
71   EXPECT_THAT(plugin2->GetCounterValue(uint64_counter_handle, kLabelValues,
72                                        kOptionalLabelValues),
73               ::testing::Optional(3));
74   EXPECT_THAT(plugin3->GetCounterValue(uint64_counter_handle, kLabelValues,
75                                        kOptionalLabelValues),
76               ::testing::Optional(6));
77 }
78 
TEST_F(MetricsTest,DoubleCounter)79 TEST_F(MetricsTest, DoubleCounter) {
80   const absl::string_view kLabelKeys[] = {"label_key_1", "label_key_2"};
81   const absl::string_view kOptionalLabelKeys[] = {"optional_label_key_1",
82                                                   "optional_label_key_2"};
83   auto double_counter_handle = GlobalInstrumentsRegistry::RegisterDoubleCounter(
84       "double_counter", "A simple double counter.", "unit", kLabelKeys,
85       kOptionalLabelKeys, true);
86   constexpr absl::string_view kLabelValues[] = {"label_value_1",
87                                                 "label_value_2"};
88   constexpr absl::string_view kOptionalLabelValues[] = {
89       "optional_label_value_1", "optional_label_value_2"};
90   constexpr absl::string_view kDomain1To4 = "domain1.domain2.domain3.domain4";
91   constexpr absl::string_view kDomain2To4 = "domain2.domain3.domain4";
92   constexpr absl::string_view kDomain3To4 = "domain3.domain4";
93   auto plugin1 = MakeStatsPluginForTarget(kDomain1To4);
94   auto plugin2 = MakeStatsPluginForTarget(kDomain2To4);
95   auto plugin3 = MakeStatsPluginForTarget(kDomain3To4);
96   GlobalStatsPluginRegistry::GetStatsPluginsForChannel(
97       StatsPluginChannelScope(kDomain1To4, ""))
98       .AddCounter(double_counter_handle, 1.23, kLabelValues,
99                   kOptionalLabelValues);
100   GlobalStatsPluginRegistry::GetStatsPluginsForChannel(
101       StatsPluginChannelScope(kDomain2To4, ""))
102       .AddCounter(double_counter_handle, 2.34, kLabelValues,
103                   kOptionalLabelValues);
104   GlobalStatsPluginRegistry::GetStatsPluginsForChannel(
105       StatsPluginChannelScope(kDomain3To4, ""))
106       .AddCounter(double_counter_handle, 3.45, kLabelValues,
107                   kOptionalLabelValues);
108   EXPECT_THAT(plugin1->GetCounterValue(double_counter_handle, kLabelValues,
109                                        kOptionalLabelValues),
110               ::testing::Optional(1.23));
111   EXPECT_THAT(plugin2->GetCounterValue(double_counter_handle, kLabelValues,
112                                        kOptionalLabelValues),
113               ::testing::Optional(3.57));
114   EXPECT_THAT(plugin3->GetCounterValue(double_counter_handle, kLabelValues,
115                                        kOptionalLabelValues),
116               ::testing::Optional(7.02));
117 }
118 
TEST_F(MetricsTest,UInt64Histogram)119 TEST_F(MetricsTest, UInt64Histogram) {
120   const absl::string_view kLabelKeys[] = {"label_key_1", "label_key_2"};
121   const absl::string_view kOptionalLabelKeys[] = {"optional_label_key_1",
122                                                   "optional_label_key_2"};
123   auto uint64_histogram_handle =
124       GlobalInstrumentsRegistry::RegisterUInt64Histogram(
125           "uint64_histogram", "A simple uint64 histogram.", "unit", kLabelKeys,
126           kOptionalLabelKeys, true);
127   constexpr absl::string_view kLabelValues[] = {"label_value_1",
128                                                 "label_value_2"};
129   constexpr absl::string_view kOptionalLabelValues[] = {
130       "optional_label_value_1", "optional_label_value_2"};
131   constexpr absl::string_view kDomain1To4 = "domain1.domain2.domain3.domain4";
132   constexpr absl::string_view kDomain2To4 = "domain2.domain3.domain4";
133   constexpr absl::string_view kDomain3To4 = "domain3.domain4";
134   auto plugin1 = MakeStatsPluginForTarget(kDomain1To4);
135   auto plugin2 = MakeStatsPluginForTarget(kDomain2To4);
136   auto plugin3 = MakeStatsPluginForTarget(kDomain3To4);
137   GlobalStatsPluginRegistry::GetStatsPluginsForChannel(
138       StatsPluginChannelScope(kDomain1To4, ""))
139       .RecordHistogram(uint64_histogram_handle, 1, kLabelValues,
140                        kOptionalLabelValues);
141   GlobalStatsPluginRegistry::GetStatsPluginsForChannel(
142       StatsPluginChannelScope(kDomain2To4, ""))
143       .RecordHistogram(uint64_histogram_handle, 2, kLabelValues,
144                        kOptionalLabelValues);
145   GlobalStatsPluginRegistry::GetStatsPluginsForChannel(
146       StatsPluginChannelScope(kDomain3To4, ""))
147       .RecordHistogram(uint64_histogram_handle, 3, kLabelValues,
148                        kOptionalLabelValues);
149   EXPECT_THAT(plugin1->GetHistogramValue(uint64_histogram_handle, kLabelValues,
150                                          kOptionalLabelValues),
151               ::testing::Optional(::testing::UnorderedElementsAre(1)));
152   EXPECT_THAT(plugin2->GetHistogramValue(uint64_histogram_handle, kLabelValues,
153                                          kOptionalLabelValues),
154               ::testing::Optional(::testing::UnorderedElementsAre(1, 2)));
155   EXPECT_THAT(plugin3->GetHistogramValue(uint64_histogram_handle, kLabelValues,
156                                          kOptionalLabelValues),
157               ::testing::Optional(::testing::UnorderedElementsAre(1, 2, 3)));
158 }
159 
TEST_F(MetricsTest,DoubleHistogram)160 TEST_F(MetricsTest, DoubleHistogram) {
161   const absl::string_view kLabelKeys[] = {"label_key_1", "label_key_2"};
162   const absl::string_view kOptionalLabelKeys[] = {"optional_label_key_1",
163                                                   "optional_label_key_2"};
164   auto double_histogram_handle =
165       GlobalInstrumentsRegistry::RegisterDoubleHistogram(
166           "double_histogram", "A simple double histogram.", "unit", kLabelKeys,
167           kOptionalLabelKeys, true);
168   constexpr absl::string_view kLabelValues[] = {"label_value_1",
169                                                 "label_value_2"};
170   constexpr absl::string_view kOptionalLabelValues[] = {
171       "optional_label_value_1", "optional_label_value_2"};
172   constexpr absl::string_view kDomain1To4 = "domain1.domain2.domain3.domain4";
173   constexpr absl::string_view kDomain2To4 = "domain2.domain3.domain4";
174   constexpr absl::string_view kDomain3To4 = "domain3.domain4";
175   auto plugin1 = MakeStatsPluginForTarget(kDomain1To4);
176   auto plugin2 = MakeStatsPluginForTarget(kDomain2To4);
177   auto plugin3 = MakeStatsPluginForTarget(kDomain3To4);
178   GlobalStatsPluginRegistry::GetStatsPluginsForChannel(
179       StatsPluginChannelScope(kDomain1To4, ""))
180       .RecordHistogram(double_histogram_handle, 1.23, kLabelValues,
181                        kOptionalLabelValues);
182   GlobalStatsPluginRegistry::GetStatsPluginsForChannel(
183       StatsPluginChannelScope(kDomain2To4, ""))
184       .RecordHistogram(double_histogram_handle, 2.34, kLabelValues,
185                        kOptionalLabelValues);
186   GlobalStatsPluginRegistry::GetStatsPluginsForChannel(
187       StatsPluginChannelScope(kDomain3To4, ""))
188       .RecordHistogram(double_histogram_handle, 3.45, kLabelValues,
189                        kOptionalLabelValues);
190   EXPECT_THAT(plugin1->GetHistogramValue(double_histogram_handle, kLabelValues,
191                                          kOptionalLabelValues),
192               ::testing::Optional(::testing::UnorderedElementsAre(1.23)));
193   EXPECT_THAT(plugin2->GetHistogramValue(double_histogram_handle, kLabelValues,
194                                          kOptionalLabelValues),
195               ::testing::Optional(::testing::UnorderedElementsAre(1.23, 2.34)));
196   EXPECT_THAT(
197       plugin3->GetHistogramValue(double_histogram_handle, kLabelValues,
198                                  kOptionalLabelValues),
199       ::testing::Optional(::testing::UnorderedElementsAre(1.23, 2.34, 3.45)));
200 }
201 
TEST_F(MetricsTest,Int64Gauge)202 TEST_F(MetricsTest, Int64Gauge) {
203   const absl::string_view kLabelKeys[] = {"label_key_1", "label_key_2"};
204   const absl::string_view kOptionalLabelKeys[] = {"optional_label_key_1",
205                                                   "optional_label_key_2"};
206   auto int64_gauge_handle = GlobalInstrumentsRegistry::RegisterInt64Gauge(
207       "int64_gauge", "A simple int64 gauge.", "unit", kLabelKeys,
208       kOptionalLabelKeys, true);
209   constexpr absl::string_view kLabelValues[] = {"label_value_1",
210                                                 "label_value_2"};
211   constexpr absl::string_view kOptionalLabelValues[] = {
212       "optional_label_value_1", "optional_label_value_2"};
213   constexpr absl::string_view kDomain1To4 = "domain1.domain2.domain3.domain4";
214   constexpr absl::string_view kDomain2To4 = "domain2.domain3.domain4";
215   constexpr absl::string_view kDomain3To4 = "domain3.domain4";
216   auto plugin1 = MakeStatsPluginForTarget(kDomain1To4);
217   auto plugin2 = MakeStatsPluginForTarget(kDomain2To4);
218   auto plugin3 = MakeStatsPluginForTarget(kDomain3To4);
219   GlobalStatsPluginRegistry::GetStatsPluginsForChannel(
220       StatsPluginChannelScope(kDomain1To4, ""))
221       .SetGauge(int64_gauge_handle, 1, kLabelValues, kOptionalLabelValues);
222   GlobalStatsPluginRegistry::GetStatsPluginsForChannel(
223       StatsPluginChannelScope(kDomain2To4, ""))
224       .SetGauge(int64_gauge_handle, 2, kLabelValues, kOptionalLabelValues);
225   GlobalStatsPluginRegistry::GetStatsPluginsForChannel(
226       StatsPluginChannelScope(kDomain3To4, ""))
227       .SetGauge(int64_gauge_handle, 3, kLabelValues, kOptionalLabelValues);
228   EXPECT_THAT(plugin1->GetGaugeValue(int64_gauge_handle, kLabelValues,
229                                      kOptionalLabelValues),
230               ::testing::Optional(1));
231   EXPECT_THAT(plugin2->GetGaugeValue(int64_gauge_handle, kLabelValues,
232                                      kOptionalLabelValues),
233               ::testing::Optional(2));
234   EXPECT_THAT(plugin3->GetGaugeValue(int64_gauge_handle, kLabelValues,
235                                      kOptionalLabelValues),
236               ::testing::Optional(3));
237 }
238 
TEST_F(MetricsTest,DoubleGauge)239 TEST_F(MetricsTest, DoubleGauge) {
240   const absl::string_view kLabelKeys[] = {"label_key_1", "label_key_2"};
241   const absl::string_view kOptionalLabelKeys[] = {"optional_label_key_1",
242                                                   "optional_label_key_2"};
243   auto double_gauge_handle = GlobalInstrumentsRegistry::RegisterDoubleGauge(
244       "double_gauge", "A simple double gauge.", "unit", kLabelKeys,
245       kOptionalLabelKeys, true);
246   constexpr absl::string_view kLabelValues[] = {"label_value_1",
247                                                 "label_value_2"};
248   constexpr absl::string_view kOptionalLabelValues[] = {
249       "optional_label_value_1", "optional_label_value_2"};
250   constexpr absl::string_view kDomain1To4 = "domain1.domain2.domain3.domain4";
251   constexpr absl::string_view kDomain2To4 = "domain2.domain3.domain4";
252   constexpr absl::string_view kDomain3To4 = "domain3.domain4";
253   auto plugin1 = MakeStatsPluginForTarget(kDomain1To4);
254   auto plugin2 = MakeStatsPluginForTarget(kDomain2To4);
255   auto plugin3 = MakeStatsPluginForTarget(kDomain3To4);
256   GlobalStatsPluginRegistry::GetStatsPluginsForChannel(
257       StatsPluginChannelScope(kDomain1To4, ""))
258       .SetGauge(double_gauge_handle, 1.23, kLabelValues, kOptionalLabelValues);
259   GlobalStatsPluginRegistry::GetStatsPluginsForChannel(
260       StatsPluginChannelScope(kDomain2To4, ""))
261       .SetGauge(double_gauge_handle, 2.34, kLabelValues, kOptionalLabelValues);
262   GlobalStatsPluginRegistry::GetStatsPluginsForChannel(
263       StatsPluginChannelScope(kDomain3To4, ""))
264       .SetGauge(double_gauge_handle, 3.45, kLabelValues, kOptionalLabelValues);
265   EXPECT_THAT(plugin1->GetGaugeValue(double_gauge_handle, kLabelValues,
266                                      kOptionalLabelValues),
267               ::testing::Optional(1.23));
268   EXPECT_THAT(plugin2->GetGaugeValue(double_gauge_handle, kLabelValues,
269                                      kOptionalLabelValues),
270               ::testing::Optional(2.34));
271   EXPECT_THAT(plugin3->GetGaugeValue(double_gauge_handle, kLabelValues,
272                                      kOptionalLabelValues),
273               ::testing::Optional(3.45));
274 }
275 
TEST_F(MetricsTest,Int64CallbackGauge)276 TEST_F(MetricsTest, Int64CallbackGauge) {
277   const absl::string_view kLabelKeys[] = {"label_key_1", "label_key_2"};
278   const absl::string_view kOptionalLabelKeys[] = {"optional_label_key_1",
279                                                   "optional_label_key_2"};
280   auto int64_gauge_handle =
281       GlobalInstrumentsRegistry::RegisterCallbackInt64Gauge(
282           "int64_gauge", "A simple int64 gauge.", "unit", kLabelKeys,
283           kOptionalLabelKeys, true);
284   constexpr absl::string_view kLabelValues[] = {"label_value_1",
285                                                 "label_value_2"};
286   constexpr absl::string_view kLabelValues2[] = {"label_value_3",
287                                                  "label_value_2"};
288   constexpr absl::string_view kOptionalLabelValues[] = {
289       "optional_label_value_1", "optional_label_value_2"};
290   constexpr absl::string_view kDomain1To4 = "domain1.domain2.domain3.domain4";
291   constexpr absl::string_view kDomain2To4 = "domain2.domain3.domain4";
292   constexpr absl::string_view kDomain3To4 = "domain3.domain4";
293   auto plugin1 = MakeStatsPluginForTarget(kDomain3To4);
294   auto plugin2 = MakeStatsPluginForTarget(kDomain2To4);
295   auto plugin3 = MakeStatsPluginForTarget(kDomain1To4);
296   // Register two callbacks that set the same metric but with different
297   // label values.  The callbacks get used only by plugin1.
298   gpr_log(GPR_INFO, "testing callbacks for: plugin1");
299   auto group1 = GlobalStatsPluginRegistry::GetStatsPluginsForChannel(
300       StatsPluginChannelScope(kDomain3To4, ""));
301   auto callback1 = group1.RegisterCallback(
302       [&](CallbackMetricReporter& reporter) {
303         reporter.Report(int64_gauge_handle, 1, kLabelValues,
304                         kOptionalLabelValues);
305       },
306       {int64_gauge_handle});
307   auto callback2 = group1.RegisterCallback(
308       [&](CallbackMetricReporter& reporter) {
309         reporter.Report(int64_gauge_handle, 2, kLabelValues2,
310                         kOptionalLabelValues);
311       },
312       {int64_gauge_handle});
313   // No plugins have data yet.
314   EXPECT_EQ(plugin1->GetCallbackGaugeValue(int64_gauge_handle, kLabelValues,
315                                            kOptionalLabelValues),
316             absl::nullopt);
317   EXPECT_EQ(plugin1->GetCallbackGaugeValue(int64_gauge_handle, kLabelValues2,
318                                            kOptionalLabelValues),
319             absl::nullopt);
320   EXPECT_EQ(plugin2->GetCallbackGaugeValue(int64_gauge_handle, kLabelValues,
321                                            kOptionalLabelValues),
322             absl::nullopt);
323   EXPECT_EQ(plugin2->GetCallbackGaugeValue(int64_gauge_handle, kLabelValues2,
324                                            kOptionalLabelValues),
325             absl::nullopt);
326   EXPECT_EQ(plugin3->GetCallbackGaugeValue(int64_gauge_handle, kLabelValues,
327                                            kOptionalLabelValues),
328             absl::nullopt);
329   EXPECT_EQ(plugin3->GetCallbackGaugeValue(int64_gauge_handle, kLabelValues2,
330                                            kOptionalLabelValues),
331             absl::nullopt);
332   // Now invoke the callbacks.
333   plugin1->TriggerCallbacks();
334   plugin2->TriggerCallbacks();
335   plugin3->TriggerCallbacks();
336   // Now plugin1 should have data, but the others should not.
337   EXPECT_THAT(plugin1->GetCallbackGaugeValue(int64_gauge_handle, kLabelValues,
338                                              kOptionalLabelValues),
339               ::testing::Optional(1));
340   EXPECT_THAT(plugin1->GetCallbackGaugeValue(int64_gauge_handle, kLabelValues2,
341                                              kOptionalLabelValues),
342               ::testing::Optional(2));
343   EXPECT_EQ(plugin2->GetCallbackGaugeValue(int64_gauge_handle, kLabelValues,
344                                            kOptionalLabelValues),
345             absl::nullopt);
346   EXPECT_EQ(plugin2->GetCallbackGaugeValue(int64_gauge_handle, kLabelValues2,
347                                            kOptionalLabelValues),
348             absl::nullopt);
349   EXPECT_EQ(plugin3->GetCallbackGaugeValue(int64_gauge_handle, kLabelValues,
350                                            kOptionalLabelValues),
351             absl::nullopt);
352   EXPECT_EQ(plugin3->GetCallbackGaugeValue(int64_gauge_handle, kLabelValues2,
353                                            kOptionalLabelValues),
354             absl::nullopt);
355   // De-register the callbacks.
356   callback1.reset();
357   callback2.reset();
358   // Now register callbacks that hit both plugin1 and plugin2.
359   gpr_log(GPR_INFO, "testing callbacks for: plugin1, plugin2");
360   auto group2 = GlobalStatsPluginRegistry::GetStatsPluginsForChannel(
361       StatsPluginChannelScope(kDomain2To4, ""));
362   callback1 = group2.RegisterCallback(
363       [&](CallbackMetricReporter& reporter) {
364         reporter.Report(int64_gauge_handle, 3, kLabelValues,
365                         kOptionalLabelValues);
366       },
367       {int64_gauge_handle});
368   callback2 = group2.RegisterCallback(
369       [&](CallbackMetricReporter& reporter) {
370         reporter.Report(int64_gauge_handle, 4, kLabelValues2,
371                         kOptionalLabelValues);
372       },
373       {int64_gauge_handle});
374   // Plugin1 still has data from before, but the others have none.
375   EXPECT_THAT(plugin1->GetCallbackGaugeValue(int64_gauge_handle, kLabelValues,
376                                              kOptionalLabelValues),
377               ::testing::Optional(1));
378   EXPECT_THAT(plugin1->GetCallbackGaugeValue(int64_gauge_handle, kLabelValues2,
379                                              kOptionalLabelValues),
380               ::testing::Optional(2));
381   EXPECT_EQ(plugin2->GetCallbackGaugeValue(int64_gauge_handle, kLabelValues,
382                                            kOptionalLabelValues),
383             absl::nullopt);
384   EXPECT_EQ(plugin2->GetCallbackGaugeValue(int64_gauge_handle, kLabelValues2,
385                                            kOptionalLabelValues),
386             absl::nullopt);
387   EXPECT_EQ(plugin3->GetCallbackGaugeValue(int64_gauge_handle, kLabelValues,
388                                            kOptionalLabelValues),
389             absl::nullopt);
390   EXPECT_EQ(plugin3->GetCallbackGaugeValue(int64_gauge_handle, kLabelValues2,
391                                            kOptionalLabelValues),
392             absl::nullopt);
393   // Now invoke the callbacks.
394   plugin1->TriggerCallbacks();
395   plugin2->TriggerCallbacks();
396   plugin3->TriggerCallbacks();
397   // Now plugin1 and plugin2 should have data, but plugin3 should not.
398   EXPECT_THAT(plugin1->GetCallbackGaugeValue(int64_gauge_handle, kLabelValues,
399                                              kOptionalLabelValues),
400               ::testing::Optional(3));
401   EXPECT_THAT(plugin1->GetCallbackGaugeValue(int64_gauge_handle, kLabelValues2,
402                                              kOptionalLabelValues),
403               ::testing::Optional(4));
404   EXPECT_THAT(plugin2->GetCallbackGaugeValue(int64_gauge_handle, kLabelValues,
405                                              kOptionalLabelValues),
406               ::testing::Optional(3));
407   EXPECT_THAT(plugin2->GetCallbackGaugeValue(int64_gauge_handle, kLabelValues2,
408                                              kOptionalLabelValues),
409               ::testing::Optional(4));
410   EXPECT_EQ(plugin3->GetCallbackGaugeValue(int64_gauge_handle, kLabelValues,
411                                            kOptionalLabelValues),
412             absl::nullopt);
413   EXPECT_EQ(plugin3->GetCallbackGaugeValue(int64_gauge_handle, kLabelValues2,
414                                            kOptionalLabelValues),
415             absl::nullopt);
416   // De-register the callbacks.
417   callback1.reset();
418   callback2.reset();
419   // Now register callbacks that hit all three plugins.
420   gpr_log(GPR_INFO, "testing callbacks for: plugin1, plugin2, plugin3");
421   auto group3 = GlobalStatsPluginRegistry::GetStatsPluginsForChannel(
422       StatsPluginChannelScope(kDomain1To4, ""));
423   callback1 = group3.RegisterCallback(
424       [&](CallbackMetricReporter& reporter) {
425         reporter.Report(int64_gauge_handle, 5, kLabelValues,
426                         kOptionalLabelValues);
427       },
428       {int64_gauge_handle});
429   callback2 = group3.RegisterCallback(
430       [&](CallbackMetricReporter& reporter) {
431         reporter.Report(int64_gauge_handle, 6, kLabelValues2,
432                         kOptionalLabelValues);
433       },
434       {int64_gauge_handle});
435   // Plugin1 and plugin2 still has data from before, but plugin3 has none.
436   EXPECT_THAT(plugin1->GetCallbackGaugeValue(int64_gauge_handle, kLabelValues,
437                                              kOptionalLabelValues),
438               ::testing::Optional(3));
439   EXPECT_THAT(plugin1->GetCallbackGaugeValue(int64_gauge_handle, kLabelValues2,
440                                              kOptionalLabelValues),
441               ::testing::Optional(4));
442   EXPECT_THAT(plugin2->GetCallbackGaugeValue(int64_gauge_handle, kLabelValues,
443                                              kOptionalLabelValues),
444               ::testing::Optional(3));
445   EXPECT_THAT(plugin2->GetCallbackGaugeValue(int64_gauge_handle, kLabelValues2,
446                                              kOptionalLabelValues),
447               ::testing::Optional(4));
448   EXPECT_EQ(plugin3->GetCallbackGaugeValue(int64_gauge_handle, kLabelValues,
449                                            kOptionalLabelValues),
450             absl::nullopt);
451   EXPECT_EQ(plugin3->GetCallbackGaugeValue(int64_gauge_handle, kLabelValues2,
452                                            kOptionalLabelValues),
453             absl::nullopt);
454   // Now invoke the callbacks.
455   plugin1->TriggerCallbacks();
456   plugin2->TriggerCallbacks();
457   plugin3->TriggerCallbacks();
458   // Now plugin1 and plugin2 should have data, but plugin3 should not.
459   EXPECT_THAT(plugin1->GetCallbackGaugeValue(int64_gauge_handle, kLabelValues,
460                                              kOptionalLabelValues),
461               ::testing::Optional(5));
462   EXPECT_THAT(plugin1->GetCallbackGaugeValue(int64_gauge_handle, kLabelValues2,
463                                              kOptionalLabelValues),
464               ::testing::Optional(6));
465   EXPECT_THAT(plugin2->GetCallbackGaugeValue(int64_gauge_handle, kLabelValues,
466                                              kOptionalLabelValues),
467               ::testing::Optional(5));
468   EXPECT_THAT(plugin2->GetCallbackGaugeValue(int64_gauge_handle, kLabelValues2,
469                                              kOptionalLabelValues),
470               ::testing::Optional(6));
471   EXPECT_THAT(plugin3->GetCallbackGaugeValue(int64_gauge_handle, kLabelValues,
472                                              kOptionalLabelValues),
473               ::testing::Optional(5));
474   EXPECT_THAT(plugin3->GetCallbackGaugeValue(int64_gauge_handle, kLabelValues2,
475                                              kOptionalLabelValues),
476               ::testing::Optional(6));
477   // Need to destroy callbacks before the plugin group that created them.
478   callback1.reset();
479   callback2.reset();
480 }
481 
TEST_F(MetricsTest,DoubleCallbackGauge)482 TEST_F(MetricsTest, DoubleCallbackGauge) {
483   const absl::string_view kLabelKeys[] = {"label_key_1", "label_key_2"};
484   const absl::string_view kOptionalLabelKeys[] = {"optional_label_key_1",
485                                                   "optional_label_key_2"};
486   auto double_gauge_handle =
487       GlobalInstrumentsRegistry::RegisterCallbackDoubleGauge(
488           "double_gauge", "A simple double gauge.", "unit", kLabelKeys,
489           kOptionalLabelKeys, true);
490   constexpr absl::string_view kLabelValues[] = {"label_value_1",
491                                                 "label_value_2"};
492   constexpr absl::string_view kLabelValues2[] = {"label_value_3",
493                                                  "label_value_2"};
494   constexpr absl::string_view kOptionalLabelValues[] = {
495       "optional_label_value_1", "optional_label_value_2"};
496   constexpr absl::string_view kDomain1To4 = "domain1.domain2.domain3.domain4";
497   constexpr absl::string_view kDomain2To4 = "domain2.domain3.domain4";
498   constexpr absl::string_view kDomain3To4 = "domain3.domain4";
499   auto plugin1 = MakeStatsPluginForTarget(kDomain3To4);
500   auto plugin2 = MakeStatsPluginForTarget(kDomain2To4);
501   auto plugin3 = MakeStatsPluginForTarget(kDomain1To4);
502   // Register two callbacks that set the same metric but with different
503   // label values.  The callbacks get used only by plugin1.
504   gpr_log(GPR_INFO, "testing callbacks for: plugin1");
505   auto group1 = GlobalStatsPluginRegistry::GetStatsPluginsForChannel(
506       StatsPluginChannelScope(kDomain3To4, ""));
507   auto callback1 = group1.RegisterCallback(
508       [&](CallbackMetricReporter& reporter) {
509         reporter.Report(double_gauge_handle, 1.23, kLabelValues,
510                         kOptionalLabelValues);
511       },
512       {double_gauge_handle});
513   auto callback2 = group1.RegisterCallback(
514       [&](CallbackMetricReporter& reporter) {
515         reporter.Report(double_gauge_handle, 2.34, kLabelValues2,
516                         kOptionalLabelValues);
517       },
518       {double_gauge_handle});
519   // No plugins have data yet.
520   EXPECT_EQ(plugin1->GetCallbackGaugeValue(double_gauge_handle, kLabelValues,
521                                            kOptionalLabelValues),
522             absl::nullopt);
523   EXPECT_EQ(plugin1->GetCallbackGaugeValue(double_gauge_handle, kLabelValues2,
524                                            kOptionalLabelValues),
525             absl::nullopt);
526   EXPECT_EQ(plugin2->GetCallbackGaugeValue(double_gauge_handle, kLabelValues,
527                                            kOptionalLabelValues),
528             absl::nullopt);
529   EXPECT_EQ(plugin2->GetCallbackGaugeValue(double_gauge_handle, kLabelValues2,
530                                            kOptionalLabelValues),
531             absl::nullopt);
532   EXPECT_EQ(plugin3->GetCallbackGaugeValue(double_gauge_handle, kLabelValues,
533                                            kOptionalLabelValues),
534             absl::nullopt);
535   EXPECT_EQ(plugin3->GetCallbackGaugeValue(double_gauge_handle, kLabelValues2,
536                                            kOptionalLabelValues),
537             absl::nullopt);
538   // Now invoke the callbacks.
539   plugin1->TriggerCallbacks();
540   plugin2->TriggerCallbacks();
541   plugin3->TriggerCallbacks();
542   // Now plugin1 should have data, but the others should not.
543   EXPECT_THAT(plugin1->GetCallbackGaugeValue(double_gauge_handle, kLabelValues,
544                                              kOptionalLabelValues),
545               ::testing::Optional(1.23));
546   EXPECT_THAT(plugin1->GetCallbackGaugeValue(double_gauge_handle, kLabelValues2,
547                                              kOptionalLabelValues),
548               ::testing::Optional(2.34));
549   EXPECT_EQ(plugin2->GetCallbackGaugeValue(double_gauge_handle, kLabelValues,
550                                            kOptionalLabelValues),
551             absl::nullopt);
552   EXPECT_EQ(plugin2->GetCallbackGaugeValue(double_gauge_handle, kLabelValues2,
553                                            kOptionalLabelValues),
554             absl::nullopt);
555   EXPECT_EQ(plugin3->GetCallbackGaugeValue(double_gauge_handle, kLabelValues,
556                                            kOptionalLabelValues),
557             absl::nullopt);
558   EXPECT_EQ(plugin3->GetCallbackGaugeValue(double_gauge_handle, kLabelValues2,
559                                            kOptionalLabelValues),
560             absl::nullopt);
561   // De-register the callbacks.
562   callback1.reset();
563   callback2.reset();
564   // Now register callbacks that hit both plugin1 and plugin2.
565   gpr_log(GPR_INFO, "testing callbacks for: plugin1, plugin2");
566   auto group2 = GlobalStatsPluginRegistry::GetStatsPluginsForChannel(
567       StatsPluginChannelScope(kDomain2To4, ""));
568   callback1 = group2.RegisterCallback(
569       [&](CallbackMetricReporter& reporter) {
570         reporter.Report(double_gauge_handle, 3.45, kLabelValues,
571                         kOptionalLabelValues);
572       },
573       {double_gauge_handle});
574   callback2 = group2.RegisterCallback(
575       [&](CallbackMetricReporter& reporter) {
576         reporter.Report(double_gauge_handle, 4.56, kLabelValues2,
577                         kOptionalLabelValues);
578       },
579       {double_gauge_handle});
580   // Plugin1 still has data from before, but the others have none.
581   EXPECT_THAT(plugin1->GetCallbackGaugeValue(double_gauge_handle, kLabelValues,
582                                              kOptionalLabelValues),
583               ::testing::Optional(1.23));
584   EXPECT_THAT(plugin1->GetCallbackGaugeValue(double_gauge_handle, kLabelValues2,
585                                              kOptionalLabelValues),
586               ::testing::Optional(2.34));
587   EXPECT_EQ(plugin2->GetCallbackGaugeValue(double_gauge_handle, kLabelValues,
588                                            kOptionalLabelValues),
589             absl::nullopt);
590   EXPECT_EQ(plugin2->GetCallbackGaugeValue(double_gauge_handle, kLabelValues2,
591                                            kOptionalLabelValues),
592             absl::nullopt);
593   EXPECT_EQ(plugin3->GetCallbackGaugeValue(double_gauge_handle, kLabelValues,
594                                            kOptionalLabelValues),
595             absl::nullopt);
596   EXPECT_EQ(plugin3->GetCallbackGaugeValue(double_gauge_handle, kLabelValues2,
597                                            kOptionalLabelValues),
598             absl::nullopt);
599   // Now invoke the callbacks.
600   plugin1->TriggerCallbacks();
601   plugin2->TriggerCallbacks();
602   plugin3->TriggerCallbacks();
603   // Now plugin1 and plugin2 should have data, but plugin3 should not.
604   EXPECT_THAT(plugin1->GetCallbackGaugeValue(double_gauge_handle, kLabelValues,
605                                              kOptionalLabelValues),
606               ::testing::Optional(3.45));
607   EXPECT_THAT(plugin1->GetCallbackGaugeValue(double_gauge_handle, kLabelValues2,
608                                              kOptionalLabelValues),
609               ::testing::Optional(4.56));
610   EXPECT_THAT(plugin2->GetCallbackGaugeValue(double_gauge_handle, kLabelValues,
611                                              kOptionalLabelValues),
612               ::testing::Optional(3.45));
613   EXPECT_THAT(plugin2->GetCallbackGaugeValue(double_gauge_handle, kLabelValues2,
614                                              kOptionalLabelValues),
615               ::testing::Optional(4.56));
616   EXPECT_EQ(plugin3->GetCallbackGaugeValue(double_gauge_handle, kLabelValues,
617                                            kOptionalLabelValues),
618             absl::nullopt);
619   EXPECT_EQ(plugin3->GetCallbackGaugeValue(double_gauge_handle, kLabelValues2,
620                                            kOptionalLabelValues),
621             absl::nullopt);
622   // De-register the callbacks.
623   callback1.reset();
624   callback2.reset();
625   // Now register callbacks that hit all three plugins.
626   gpr_log(GPR_INFO, "testing callbacks for: plugin1, plugin2, plugin3");
627   auto group3 = GlobalStatsPluginRegistry::GetStatsPluginsForChannel(
628       StatsPluginChannelScope(kDomain1To4, ""));
629   callback1 = group3.RegisterCallback(
630       [&](CallbackMetricReporter& reporter) {
631         reporter.Report(double_gauge_handle, 5.67, kLabelValues,
632                         kOptionalLabelValues);
633       },
634       {double_gauge_handle});
635   callback2 = group3.RegisterCallback(
636       [&](CallbackMetricReporter& reporter) {
637         reporter.Report(double_gauge_handle, 6.78, kLabelValues2,
638                         kOptionalLabelValues);
639       },
640       {double_gauge_handle});
641   // Plugin1 and plugin2 still has data from before, but plugin3 has none.
642   EXPECT_THAT(plugin1->GetCallbackGaugeValue(double_gauge_handle, kLabelValues,
643                                              kOptionalLabelValues),
644               ::testing::Optional(3.45));
645   EXPECT_THAT(plugin1->GetCallbackGaugeValue(double_gauge_handle, kLabelValues2,
646                                              kOptionalLabelValues),
647               ::testing::Optional(4.56));
648   EXPECT_THAT(plugin2->GetCallbackGaugeValue(double_gauge_handle, kLabelValues,
649                                              kOptionalLabelValues),
650               ::testing::Optional(3.45));
651   EXPECT_THAT(plugin2->GetCallbackGaugeValue(double_gauge_handle, kLabelValues2,
652                                              kOptionalLabelValues),
653               ::testing::Optional(4.56));
654   EXPECT_EQ(plugin3->GetCallbackGaugeValue(double_gauge_handle, kLabelValues,
655                                            kOptionalLabelValues),
656             absl::nullopt);
657   EXPECT_EQ(plugin3->GetCallbackGaugeValue(double_gauge_handle, kLabelValues2,
658                                            kOptionalLabelValues),
659             absl::nullopt);
660   // Now invoke the callbacks.
661   plugin1->TriggerCallbacks();
662   plugin2->TriggerCallbacks();
663   plugin3->TriggerCallbacks();
664   // Now plugin1 and plugin2 should have data, but plugin3 should not.
665   EXPECT_THAT(plugin1->GetCallbackGaugeValue(double_gauge_handle, kLabelValues,
666                                              kOptionalLabelValues),
667               ::testing::Optional(5.67));
668   EXPECT_THAT(plugin1->GetCallbackGaugeValue(double_gauge_handle, kLabelValues2,
669                                              kOptionalLabelValues),
670               ::testing::Optional(6.78));
671   EXPECT_THAT(plugin2->GetCallbackGaugeValue(double_gauge_handle, kLabelValues,
672                                              kOptionalLabelValues),
673               ::testing::Optional(5.67));
674   EXPECT_THAT(plugin2->GetCallbackGaugeValue(double_gauge_handle, kLabelValues2,
675                                              kOptionalLabelValues),
676               ::testing::Optional(6.78));
677   EXPECT_THAT(plugin3->GetCallbackGaugeValue(double_gauge_handle, kLabelValues,
678                                              kOptionalLabelValues),
679               ::testing::Optional(5.67));
680   EXPECT_THAT(plugin3->GetCallbackGaugeValue(double_gauge_handle, kLabelValues2,
681                                              kOptionalLabelValues),
682               ::testing::Optional(6.78));
683   // Need to destroy callbacks before the plugin group that created them.
684   callback1.reset();
685   callback2.reset();
686 }
687 
TEST_F(MetricsTest,DisableByDefaultMetricIsNotRecordedByFakeStatsPlugin)688 TEST_F(MetricsTest, DisableByDefaultMetricIsNotRecordedByFakeStatsPlugin) {
689   const absl::string_view kLabelKeys[] = {"label_key_1", "label_key_2"};
690   const absl::string_view kOptionalLabelKeys[] = {"optional_label_key_1",
691                                                   "optional_label_key_2"};
692   auto double_histogram_handle =
693       GlobalInstrumentsRegistry::RegisterDoubleHistogram(
694           "double_histogram", "A simple double histogram.", "unit", kLabelKeys,
695           kOptionalLabelKeys, /*enable_by_default=*/false);
696   constexpr absl::string_view kLabelValues[] = {"label_value_1",
697                                                 "label_value_2"};
698   constexpr absl::string_view kOptionalLabelValues[] = {
699       "optional_label_value_1", "optional_label_value_2"};
700   constexpr absl::string_view kDomain1To4 = "domain1.domain2.domain3.domain4";
701   auto plugin = MakeStatsPluginForTarget(kDomain1To4);
702   GlobalStatsPluginRegistry::GetStatsPluginsForChannel(
703       StatsPluginChannelScope(kDomain1To4, ""))
704       .RecordHistogram(double_histogram_handle, 1.23, kLabelValues,
705                        kOptionalLabelValues);
706   EXPECT_EQ(plugin->GetHistogramValue(double_histogram_handle, kLabelValues,
707                                       kOptionalLabelValues),
708             absl::nullopt);
709 }
710 
711 using MetricsDeathTest = MetricsTest;
712 
TEST_F(MetricsDeathTest,RegisterTheSameMetricNameWouldCrash)713 TEST_F(MetricsDeathTest, RegisterTheSameMetricNameWouldCrash) {
714   const absl::string_view kLabelKeys[] = {"label_key_1", "label_key_2"};
715   const absl::string_view kOptionalLabelKeys[] = {"optional_label_key_1",
716                                                   "optional_label_key_2"};
717   (void)GlobalInstrumentsRegistry::RegisterDoubleHistogram(
718       "double_histogram", "A simple double histogram.", "unit", kLabelKeys,
719       kOptionalLabelKeys, true);
720   EXPECT_DEATH(GlobalInstrumentsRegistry::RegisterDoubleHistogram(
721                    "double_histogram", "A simple double histogram.", "unit",
722                    kLabelKeys, kOptionalLabelKeys, true),
723                "Metric name double_histogram has already been registered.");
724 }
725 
726 }  // namespace
727 }  // namespace grpc_core
728 
main(int argc,char ** argv)729 int main(int argc, char** argv) {
730   grpc::testing::TestEnvironment env(&argc, argv);
731   ::testing::InitGoogleTest(&argc, argv);
732   int ret = RUN_ALL_TESTS();
733   return ret;
734 }
735