diff --git a/source/extensions/stat_sinks/metrics_service/grpc_metrics_service_impl.cc b/source/extensions/stat_sinks/metrics_service/grpc_metrics_service_impl.cc index 14d0d2043bb48..a9042ca77d5da 100644 --- a/source/extensions/stat_sinks/metrics_service/grpc_metrics_service_impl.cc +++ b/source/extensions/stat_sinks/metrics_service/grpc_metrics_service_impl.cc @@ -59,19 +59,19 @@ MetricsPtr MetricsFlusher::flush(Stats::MetricSnapshot& snapshot) const { snapshot.snapshotTime().time_since_epoch()) .count(); for (const auto& counter : snapshot.counters()) { - if (counter.counter_.get().used()) { + if (predicate_(counter.counter_.get())) { flushCounter(*metrics->Add(), counter, snapshot_time_ms); } } for (const auto& gauge : snapshot.gauges()) { - if (gauge.get().used()) { + if (predicate_(gauge)) { flushGauge(*metrics->Add(), gauge.get(), snapshot_time_ms); } } for (const auto& histogram : snapshot.histograms()) { - if (histogram.get().used()) { + if (predicate_(histogram.get())) { flushHistogram(*metrics->Add(), *metrics->Add(), histogram.get(), snapshot_time_ms); } } diff --git a/source/extensions/stat_sinks/metrics_service/grpc_metrics_service_impl.h b/source/extensions/stat_sinks/metrics_service/grpc_metrics_service_impl.h index 7baef22c5bc07..97161641306f2 100644 --- a/source/extensions/stat_sinks/metrics_service/grpc_metrics_service_impl.h +++ b/source/extensions/stat_sinks/metrics_service/grpc_metrics_service_impl.h @@ -82,8 +82,12 @@ using GrpcMetricsStreamerImplPtr = std::unique_ptr; class MetricsFlusher { public: - MetricsFlusher(bool report_counters_as_deltas, bool emit_labels) - : report_counters_as_deltas_(report_counters_as_deltas), emit_labels_(emit_labels) {} + MetricsFlusher( + bool report_counters_as_deltas, bool emit_labels, + std::function predicate = + [](const auto& metric) { return metric.used(); }) + : report_counters_as_deltas_(report_counters_as_deltas), emit_labels_(emit_labels), + predicate_(predicate) {} MetricsPtr flush(Stats::MetricSnapshot& snapshot) const; @@ -105,6 +109,7 @@ class MetricsFlusher { const bool report_counters_as_deltas_; const bool emit_labels_; + const std::function predicate_; }; /** diff --git a/test/extensions/stats_sinks/metrics_service/grpc_metrics_service_impl_test.cc b/test/extensions/stats_sinks/metrics_service/grpc_metrics_service_impl_test.cc index 3b77c71ceaed2..1ccf1bacdb59b 100644 --- a/test/extensions/stats_sinks/metrics_service/grpc_metrics_service_impl_test.cc +++ b/test/extensions/stats_sinks/metrics_service/grpc_metrics_service_impl_test.cc @@ -101,9 +101,35 @@ class MockGrpcMetricsStreamer class MetricsServiceSinkTest : public testing::Test { public: - MetricsServiceSinkTest() = default; + void addCounterToSnapshot(const std::string& name, uint64_t delta, uint64_t value, + bool used = true) { + counter_storage_.emplace_back(std::make_unique>()); + counter_storage_.back()->name_ = name; + counter_storage_.back()->value_ = value; + counter_storage_.back()->used_ = used; + + snapshot_.counters_.push_back({delta, *counter_storage_.back()}); + } + void addGaugeToSnapshot(const std::string& name, uint64_t value, bool used = true) { + gauge_storage_.emplace_back(std::make_unique>()); + gauge_storage_.back()->name_ = name; + gauge_storage_.back()->value_ = value; + gauge_storage_.back()->used_ = used; + + snapshot_.gauges_.push_back(*gauge_storage_.back()); + } + void addHistogramToSnapshot(const std::string& name, bool used = true) { + histogram_storage_.emplace_back(std::make_unique>()); + histogram_storage_.back()->name_ = name; + histogram_storage_.back()->used_ = used; + + snapshot_.histograms_.push_back(*histogram_storage_.back()); + } NiceMock snapshot_; + std::vector>> counter_storage_; + std::vector>> gauge_storage_; + std::vector>> histogram_storage_; std::shared_ptr streamer_{new MockGrpcMetricsStreamer( Grpc::AsyncClientFactoryPtr{new NiceMock()})}; }; @@ -113,21 +139,9 @@ TEST_F(MetricsServiceSinkTest, CheckSendCall) { envoy::service::metrics::v3::StreamMetricsResponse> sink(streamer_, false, false); - auto counter = std::make_shared>(); - counter->name_ = "test_counter"; - counter->latch_ = 1; - counter->used_ = true; - snapshot_.counters_.push_back({1, *counter}); - - auto gauge = std::make_shared>(); - gauge->name_ = "test_gauge"; - gauge->value_ = 1; - gauge->used_ = true; - snapshot_.gauges_.push_back(*gauge); - - auto histogram = std::make_shared>(); - histogram->name_ = "test_histogram"; - histogram->used_ = true; + addCounterToSnapshot("test_counter", 1, 1); + addGaugeToSnapshot("test_gauge", 1); + addHistogramToSnapshot("test_histogram"); EXPECT_CALL(*streamer_, send(_)); @@ -139,17 +153,8 @@ TEST_F(MetricsServiceSinkTest, CheckStatsCount) { envoy::service::metrics::v3::StreamMetricsResponse> sink(streamer_, false, false); - auto counter = std::make_shared>(); - counter->name_ = "test_counter"; - counter->value_ = 100; - counter->used_ = true; - snapshot_.counters_.push_back({1, *counter}); - - auto gauge = std::make_shared>(); - gauge->name_ = "test_gauge"; - gauge->value_ = 1; - gauge->used_ = true; - snapshot_.gauges_.push_back(*gauge); + addCounterToSnapshot("test_counter", 1, 100); + addGaugeToSnapshot("test_gauge", 1); EXPECT_CALL(*streamer_, send(_)).WillOnce(Invoke([](MetricsPtr&& metrics) { EXPECT_EQ(2, metrics->size()); @@ -157,7 +162,7 @@ TEST_F(MetricsServiceSinkTest, CheckStatsCount) { sink.flush(snapshot_); // Verify only newly added metrics come after endFlush call. - gauge->used_ = false; + gauge_storage_.back()->used_ = false; EXPECT_CALL(*streamer_, send(_)).WillOnce(Invoke([](MetricsPtr&& metrics) { EXPECT_EQ(1, metrics->size()); })); @@ -170,11 +175,7 @@ TEST_F(MetricsServiceSinkTest, ReportCountersValues) { envoy::service::metrics::v3::StreamMetricsResponse> sink(streamer_, false, false); - auto counter = std::make_shared>(); - counter->name_ = "test_counter"; - counter->value_ = 100; - counter->used_ = true; - snapshot_.counters_.push_back({1, *counter}); + addCounterToSnapshot("test_counter", 1, 100); EXPECT_CALL(*streamer_, send(_)).WillOnce(Invoke([](MetricsPtr&& metrics) { EXPECT_EQ(1, metrics->size()); @@ -189,11 +190,7 @@ TEST_F(MetricsServiceSinkTest, ReportCountersAsDeltas) { envoy::service::metrics::v3::StreamMetricsResponse> sink(streamer_, true, false); - auto counter = std::make_shared>(); - counter->name_ = "test_counter"; - counter->value_ = 100; - counter->used_ = true; - snapshot_.counters_.push_back({1, *counter}); + addCounterToSnapshot("test_counter", 1, 100); EXPECT_CALL(*streamer_, send(_)).WillOnce(Invoke([](MetricsPtr&& metrics) { EXPECT_EQ(1, metrics->size()); @@ -204,28 +201,17 @@ TEST_F(MetricsServiceSinkTest, ReportCountersAsDeltas) { // Test the behavior of tag emission based on the emit_tags_as_label flag. TEST_F(MetricsServiceSinkTest, ReportMetricsWithTags) { - auto counter = std::make_shared>(); - counter->name_ = "full-counter-name"; - counter->value_ = 100; - counter->used_ = true; - counter->setTagExtractedName("tag-counter-name"); - counter->setTags({{"a", "b"}}); - snapshot_.counters_.push_back({1, *counter}); - - auto gauge = std::make_shared>(); - gauge->name_ = "full-gauge-name"; - gauge->value_ = 100; - gauge->used_ = true; - gauge->setTagExtractedName("tag-gauge-name"); - gauge->setTags({{"a", "b"}}); - snapshot_.gauges_.push_back({*gauge}); - - auto histogram = std::make_shared>(); - histogram->name_ = "full-histogram-name"; - histogram->used_ = true; - histogram->setTagExtractedName("tag-histogram-name"); - histogram->setTags({{"a", "b"}}); - snapshot_.histograms_.push_back({*histogram}); + addCounterToSnapshot("full-counter-name", 1, 100); + counter_storage_.back()->setTagExtractedName("tag-counter-name"); + counter_storage_.back()->setTags({{"a", "b"}}); + + addGaugeToSnapshot("full-gauge-name", 100); + gauge_storage_.back()->setTagExtractedName("tag-gauge-name"); + gauge_storage_.back()->setTags({{"a", "b"}}); + + addHistogramToSnapshot("full-histogram-name"); + histogram_storage_.back()->setTagExtractedName("tag-histogram-name"); + histogram_storage_.back()->setTags({{"a", "b"}}); { // When the emit_tags flag is false, we don't emit the tags and use the full name. @@ -282,6 +268,30 @@ TEST_F(MetricsServiceSinkTest, ReportMetricsWithTags) { sink.flush(snapshot_); } +TEST_F(MetricsServiceSinkTest, FlushPredicate) { + addCounterToSnapshot("used_counter", 100, 1); + addCounterToSnapshot("unused_counter", 100, 1, false); + + // Default predicate only accepts used metrics. + { + MetricsFlusher flusher(true, true); + auto metrics = flusher.flush(snapshot_); + EXPECT_EQ(1, metrics->size()); + } + + // Using a predicate that accepts all metrics, we'd flush both metrics. + { + MetricsFlusher flusher(true, true, [](const auto&) { return true; }); + auto metrics = flusher.flush(snapshot_); + EXPECT_EQ(2, metrics->size()); + } + + // Using a predicate that rejects all metrics, we'd flush no metrics. + MetricsFlusher flusher(true, true, [](const auto&) { return false; }); + auto metrics = flusher.flush(snapshot_); + EXPECT_EQ(0, metrics->size()); +} + } // namespace } // namespace MetricsService } // namespace StatSinks