diff --git a/api/envoy/config/metrics/v2/stats.proto b/api/envoy/config/metrics/v2/stats.proto index f3471643c93bb..c8d2c7985bd32 100644 --- a/api/envoy/config/metrics/v2/stats.proto +++ b/api/envoy/config/metrics/v2/stats.proto @@ -200,6 +200,10 @@ message DogStatsdSink { } reserved 2; + + // Optional custom metric name prefix. See :ref:`StatsdSink's prefix field + // ` for more details. + string prefix = 3; } // Stats configuration proto schema for built-in *envoy.stat_sinks.hystrix* sink. diff --git a/docs/root/intro/version_history.rst b/docs/root/intro/version_history.rst index 3a63233400c4a..952fac8dd51fa 100644 --- a/docs/root/intro/version_history.rst +++ b/docs/root/intro/version_history.rst @@ -84,6 +84,7 @@ Version history * rest-api: added ability to set the :ref:`request timeout ` for REST API requests. * route checker: Added v2 config support and removed support for v1 configs. * router: added ability to set request/response headers at the :ref:`envoy_api_msg_route.Route` level. +* stats: added :ref:`option to configure the DogStatsD metric name prefix` to DogStatsdSink. * tcp_proxy: added support for :ref:`weighted clusters `. * thrift_proxy: introduced thrift routing, moved configuration to correct location * thrift_proxy: introduced thrift configurable decoder filters diff --git a/source/extensions/stat_sinks/dog_statsd/config.cc b/source/extensions/stat_sinks/dog_statsd/config.cc index 9ae4436ba5eae..fc05fb67aa73b 100644 --- a/source/extensions/stat_sinks/dog_statsd/config.cc +++ b/source/extensions/stat_sinks/dog_statsd/config.cc @@ -22,7 +22,7 @@ Stats::SinkPtr DogStatsdSinkFactory::createStatsSink(const Protobuf::Message& co Network::Address::resolveProtoAddress(sink_config.address()); ENVOY_LOG(debug, "dog_statsd UDP ip address: {}", address->asString()); return std::make_unique(server.threadLocal(), std::move(address), - true); + true, sink_config.prefix()); } ProtobufTypes::MessagePtr DogStatsdSinkFactory::createEmptyConfigProto() { diff --git a/test/extensions/stats_sinks/common/statsd/statsd_test.cc b/test/extensions/stats_sinks/common/statsd/statsd_test.cc index 36503764de5f0..ac9b5afcd034a 100644 --- a/test/extensions/stats_sinks/common/statsd/statsd_test.cc +++ b/test/extensions/stats_sinks/common/statsd/statsd_test.cc @@ -101,6 +101,22 @@ TEST_F(TcpStatsdSinkTest, BasicFlow) { tls_.shutdownThread(); } +TEST_F(TcpStatsdSinkTest, WithCustomPrefix) { + sink_.reset(new TcpStatsdSink(local_info_, "fake_cluster", tls_, cluster_manager_, + cluster_manager_.thread_local_cluster_.cluster_.info_->stats_store_, + "test_prefix")); + + auto counter = std::make_shared>(); + counter->name_ = "test_counter"; + counter->latch_ = 1; + counter->used_ = true; + source_.counters_.push_back(counter); + + expectCreateConnection(); + EXPECT_CALL(*connection_, write(BufferStringEqual("test_prefix.test_counter:1|c\n"), _)); + sink_->flush(source_); +} + TEST_F(TcpStatsdSinkTest, BufferReallocate) { InSequence s; diff --git a/test/extensions/stats_sinks/common/statsd/udp_statsd_test.cc b/test/extensions/stats_sinks/common/statsd/udp_statsd_test.cc index e3eeb2f788fff..ef6a6e29723a3 100644 --- a/test/extensions/stats_sinks/common/statsd/udp_statsd_test.cc +++ b/test/extensions/stats_sinks/common/statsd/udp_statsd_test.cc @@ -157,6 +157,26 @@ TEST(UdpStatsdSinkTest, CheckActualStats) { tls_.shutdownThread(); } +TEST(UdpStatsdSinkTest, CheckActualStatsWithCustomPrefix) { + NiceMock source; + auto writer_ptr = std::make_shared>(); + NiceMock tls_; + UdpStatsdSink sink(tls_, writer_ptr, false, "test_prefix"); + + auto counter = std::make_shared>(); + counter->name_ = "test_counter"; + counter->used_ = true; + counter->latch_ = 1; + source.counters_.push_back(counter); + + EXPECT_CALL(*std::dynamic_pointer_cast>(writer_ptr), + write("test_prefix.test_counter:1|c")); + sink.flush(source); + counter->used_ = false; + + tls_.shutdownThread(); +} + TEST(UdpStatsdSinkWithTagsTest, CheckActualStats) { NiceMock source; auto writer_ptr = std::make_shared>(); diff --git a/test/extensions/stats_sinks/dog_statsd/config_test.cc b/test/extensions/stats_sinks/dog_statsd/config_test.cc index a8abc7f8205e4..d83055034d1ea 100644 --- a/test/extensions/stats_sinks/dog_statsd/config_test.cc +++ b/test/extensions/stats_sinks/dog_statsd/config_test.cc @@ -52,8 +52,10 @@ TEST_P(DogStatsdConfigLoopbackTest, ValidUdpIp) { NiceMock server; Stats::SinkPtr sink = factory->createStatsSink(*message, server); EXPECT_NE(sink, nullptr); - EXPECT_NE(dynamic_cast(sink.get()), nullptr); - EXPECT_EQ(dynamic_cast(sink.get())->getUseTagForTest(), true); + auto udp_sink = dynamic_cast(sink.get()); + EXPECT_NE(udp_sink, nullptr); + EXPECT_EQ(udp_sink->getUseTagForTest(), true); + EXPECT_EQ(udp_sink->getPrefix(), Common::Statsd::getDefaultPrefix()); } // Negative test for protoc-gen-validate constraints for dog_statsd. @@ -64,6 +66,35 @@ TEST(DogStatsdConfigTest, ValidateFail) { ProtoValidationException); } +TEST_P(DogStatsdConfigLoopbackTest, WithCustomPrefix) { + const std::string name = StatsSinkNames::get().DogStatsd; + + envoy::config::metrics::v2::DogStatsdSink sink_config; + envoy::api::v2::core::Address& address = *sink_config.mutable_address(); + envoy::api::v2::core::SocketAddress& socket_address = *address.mutable_socket_address(); + socket_address.set_protocol(envoy::api::v2::core::SocketAddress::UDP); + auto loopback_flavor = Network::Test::getCanonicalLoopbackAddress(GetParam()); + socket_address.set_address(loopback_flavor->ip()->addressAsString()); + socket_address.set_port_value(8125); + + const std::string customPrefix = "prefix.test"; + sink_config.set_prefix(customPrefix); + + Server::Configuration::StatsSinkFactory* factory = + Registry::FactoryRegistry::getFactory(name); + ASSERT_NE(factory, nullptr); + + ProtobufTypes::MessagePtr message = factory->createEmptyConfigProto(); + MessageUtil::jsonConvert(sink_config, *message); + + NiceMock server; + Stats::SinkPtr sink = factory->createStatsSink(*message, server); + ASSERT_NE(sink, nullptr); + auto udp_sink = dynamic_cast(sink.get()); + ASSERT_NE(udp_sink, nullptr); + EXPECT_EQ(udp_sink->getPrefix(), customPrefix); +} + } // namespace DogStatsd } // namespace StatSinks } // namespace Extensions