diff --git a/source/extensions/stat_sinks/common/statsd/statsd.cc b/source/extensions/stat_sinks/common/statsd/statsd.cc index f40a8532ea48e..c99f4223c40cc 100644 --- a/source/extensions/stat_sinks/common/statsd/statsd.cc +++ b/source/extensions/stat_sinks/common/statsd/statsd.cc @@ -64,6 +64,13 @@ void UdpStatsdSink::flush(Stats::Source& source) { buildTagStr(gauge->tags()))); } } + + for (const Stats::BoolIndicatorSharedPtr& boolIndicator : source.cachedBoolIndicators()) { + if (boolIndicator->used()) { + writer.write(fmt::format("{}.{}:{}|g{}", prefix_, getName(*boolIndicator), boolIndicator->value(), + buildTagStr(boolIndicator->tags()))); + } + } } void UdpStatsdSink::onHistogramComplete(const Stats::Histogram& histogram, uint64_t value) { @@ -124,6 +131,13 @@ void TcpStatsdSink::flush(Stats::Source& source) { tls_sink.flushGauge(gauge->name(), gauge->value()); } } + + for (const Stats::BoolIndicatorSharedPtr& boolIndicator : source.cachedBoolIndicators()) { + if (boolIndicator->used()) { + tls_sink.flushGauge(boolIndicator->name(), static_cast(boolIndicator->value())); + } + } + tls_sink.endFlush(true); } diff --git a/source/server/http/admin.cc b/source/server/http/admin.cc index 9c7da83e0e358..d3de138687564 100644 --- a/source/server/http/admin.cc +++ b/source/server/http/admin.cc @@ -686,6 +686,12 @@ Http::Code AdminImpl::handlerStats(absl::string_view url, Http::HeaderMap& respo } } + for (const Stats::BoolIndicatorSharedPtr& boolIndicator : server_.stats().boolIndicators()) { + if (shouldShowMetric(boolIndicator, used_only, regex)) { + all_stats.emplace(boolIndicator->name(), boolIndicator->value()); + } + } + if (has_format) { const std::string format_value = params.at("format"); if (format_value == "json") { @@ -725,7 +731,7 @@ Http::Code AdminImpl::handlerPrometheusStats(absl::string_view path_and_query, H const Http::Utility::QueryParams params = Http::Utility::parseQueryString(path_and_query); const bool used_only = params.find("usedonly") != params.end(); PrometheusStatsFormatter::statsAsPrometheus(server_.stats().counters(), server_.stats().gauges(), - server_.stats().histograms(), response, used_only); + server_.stats().histograms(), server_.stats().boolIndicators(), response, used_only); return Http::Code::OK; } @@ -758,7 +764,9 @@ std::string PrometheusStatsFormatter::metricName(const std::string& extractedNam uint64_t PrometheusStatsFormatter::statsAsPrometheus( const std::vector& counters, const std::vector& gauges, - const std::vector& histograms, Buffer::Instance& response, + const std::vector& histograms, + const std::vector& boolIndicators, + Buffer::Instance& response, const bool used_only) { std::unordered_set metric_type_tracker; for (const auto& counter : counters) { @@ -789,6 +797,21 @@ uint64_t PrometheusStatsFormatter::statsAsPrometheus( response.add(fmt::format("{0}{{{1}}} {2}\n", metric_name, tags, gauge->value())); } + for (const auto& boolIndicator : boolIndicators) { + if (!shouldShowMetric(boolIndicator, used_only)) { + continue; + } + + const std::string tags = formattedTags(boolIndicator->tags()); + const std::string metric_name = metricName(boolIndicator->tagExtractedName()); + if (metric_type_tracker.find(metric_name) == metric_type_tracker.end()) { + metric_type_tracker.insert(metric_name); + response.add(fmt::format("# TYPE {0} gauge\n", metric_name)); + } + + response.add(fmt::format("{0}{{{1}}} {2}\n", metric_name, tags, static_cast(boolIndicator->value()))); + } + for (const auto& histogram : histograms) { if (!shouldShowMetric(histogram, used_only)) { continue; diff --git a/source/server/http/admin.h b/source/server/http/admin.h index 31d8511a9c579..83ccfe81baf80 100644 --- a/source/server/http/admin.h +++ b/source/server/http/admin.h @@ -377,6 +377,7 @@ class PrometheusStatsFormatter { static uint64_t statsAsPrometheus(const std::vector& counters, const std::vector& gauges, const std::vector& histograms, + const std::vector& boolIndicators, Buffer::Instance& response, const bool used_only); /** * Format the given tags, returning a string as a comma-separated list diff --git a/test/server/http/admin_test.cc b/test/server/http/admin_test.cc index 76723982e4565..bd5d95f7c71b2 100644 --- a/test/server/http/admin_test.cc +++ b/test/server/http/admin_test.cc @@ -1274,11 +1274,17 @@ class PrometheusStatsFormatterTest : public testing::Test { histograms_.push_back(histogram); } + void addBoolIndicator(const std::string& name, std::vector cluster_tags) { + std::string tname = std::string(name); + boolIndicators_.push_back(alloc_.makeBoolIndicator(name, std::move(tname), std::move(cluster_tags))); + } + Stats::StatsOptionsImpl stats_options_; Stats::HeapStatDataAllocator alloc_; std::vector counters_; std::vector gauges_; std::vector histograms_; + std::vector boolIndicators_; }; TEST_F(PrometheusStatsFormatterTest, MetricName) { @@ -1329,7 +1335,7 @@ TEST_F(PrometheusStatsFormatterTest, MetricNameCollison) { Buffer::OwnedImpl response; auto size = - PrometheusStatsFormatter::statsAsPrometheus(counters_, gauges_, histograms_, response, false); + PrometheusStatsFormatter::statsAsPrometheus(counters_, gauges_, histograms_, boolIndicators_, response, false); EXPECT_EQ(2UL, size); } @@ -1349,7 +1355,7 @@ TEST_F(PrometheusStatsFormatterTest, UniqueMetricName) { Buffer::OwnedImpl response; auto size = - PrometheusStatsFormatter::statsAsPrometheus(counters_, gauges_, histograms_, response, false); + PrometheusStatsFormatter::statsAsPrometheus(counters_, gauges_, histograms_, boolIndicators_, response, false); EXPECT_EQ(4UL, size); } @@ -1368,7 +1374,7 @@ TEST_F(PrometheusStatsFormatterTest, HistogramWithNoValuesAndNoTags) { Buffer::OwnedImpl response; auto size = - PrometheusStatsFormatter::statsAsPrometheus(counters_, gauges_, histograms_, response, false); + PrometheusStatsFormatter::statsAsPrometheus(counters_, gauges_, histograms_, boolIndicators_,response, false); EXPECT_EQ(1UL, size); const std::string expected_output = R"EOF(# TYPE envoy_histogram1 histogram @@ -1420,7 +1426,7 @@ TEST_F(PrometheusStatsFormatterTest, OutputWithAllMetricTypes) { Buffer::OwnedImpl response; auto size = - PrometheusStatsFormatter::statsAsPrometheus(counters_, gauges_, histograms_, response, false); + PrometheusStatsFormatter::statsAsPrometheus(counters_, gauges_, histograms_, boolIndicators_, response, false); EXPECT_EQ(5UL, size); const std::string expected_output = R"EOF(# TYPE envoy_cluster_test_1_upstream_cx_total counter @@ -1480,7 +1486,7 @@ TEST_F(PrometheusStatsFormatterTest, OutputWithUsedOnly) { Buffer::OwnedImpl response; auto size = - PrometheusStatsFormatter::statsAsPrometheus(counters_, gauges_, histograms_, response, true); + PrometheusStatsFormatter::statsAsPrometheus(counters_, gauges_, histograms_, boolIndicators_, response, true); EXPECT_EQ(1UL, size); const std::string expected_output = R"EOF(# TYPE envoy_cluster_test_1_upstream_rq_time histogram @@ -1529,7 +1535,7 @@ TEST_F(PrometheusStatsFormatterTest, OutputWithUsedOnlyHistogram) { Buffer::OwnedImpl response; auto size = PrometheusStatsFormatter::statsAsPrometheus(counters_, gauges_, histograms_, - response, used_only); + boolIndicators_, response, used_only); EXPECT_EQ(0UL, size); } @@ -1540,7 +1546,7 @@ TEST_F(PrometheusStatsFormatterTest, OutputWithUsedOnlyHistogram) { Buffer::OwnedImpl response; auto size = PrometheusStatsFormatter::statsAsPrometheus(counters_, gauges_, histograms_, - response, used_only); + boolIndicators_, response, used_only); EXPECT_EQ(1UL, size); } }