Repository: kumahq/kuma
Pull request #2264 (2021-06-30 23:58:28)

chore(kuma-cp) refactor xDS metadata to store a generic resource
### Summary

Rather than keeping separate typed fields in the Dataplane metadata
for the Dataplane and ZoneIngress resources, store a generic Resource
interface and return the underlying type through the accessors.

### Full changelog

N/A

### Issues resolved

N/A

### Documentation

N/A

### Testing

- [x] Unit tests
- [x] E2E tests
- [ ] Manual testing on Universal
- [ ] Manual testing on Kubernetes 



Patch:
diff --git a/DEVELOPER.md b/DEVELOPER.md
index 53d0dd4f1..f74472b76 100644
--- a/DEVELOPER.md
+++ b/DEVELOPER.md
@@ -50,7 +50,7 @@ docker run --name kuma-build -ti \
   --volume `pwd`:/go/src/github.com/kumahq/kuma \
   --workdir /go/src/github.com/kumahq/kuma \
   --env GO111MODULE=on \
-  golang:1.12.12 \
+  golang:1.16 \
   bash -c 'apt update && apt install -y unzip && export PATH=$HOME/bin:$PATH && bash'
 ```
 
diff --git a/api/DEVELOPER.md b/api/DEVELOPER.md
index 93338dbcc..4ca4195ec 100644
--- a/api/DEVELOPER.md
+++ b/api/DEVELOPER.md
@@ -16,7 +16,7 @@ docker run --rm -ti \
   --workdir /go/src/github.com/kumahq/kuma/api \
   --env HOME=/tmp/home \
   --env GO111MODULE=on \
-  golang:1.12.12 bash
+  golang:1.16 bash
 export PATH=$HOME/bin:$PATH
 apt update && apt install unzip
 ```
@@ -49,4 +49,4 @@ Run:
 
 ```bash
 make build
-```
\ No newline at end of file
+```
diff --git a/api/mesh/v1alpha1/known_backends.go b/api/mesh/v1alpha1/known_backends.go
index cfdc23be8..54cd87ecc 100644
--- a/api/mesh/v1alpha1/known_backends.go
+++ b/api/mesh/v1alpha1/known_backends.go
@@ -4,7 +4,8 @@ const (
 	LoggingTcpType  = "tcp"
 	LoggingFileType = "file"
 
-	TracingZipkinType = "zipkin"
+	TracingZipkinType  = "zipkin"
+	TracingDatadogType = "datadog"
 
 	MetricsPrometheusType = "prometheus"
 )
diff --git a/api/mesh/v1alpha1/mesh.pb.go b/api/mesh/v1alpha1/mesh.pb.go
index 57e3e6a30..9663c0d4f 100644
--- a/api/mesh/v1alpha1/mesh.pb.go
+++ b/api/mesh/v1alpha1/mesh.pb.go
@@ -393,6 +393,63 @@ func (x *TracingBackend) GetConf() *_struct.Struct {
 	return nil
 }
 
+type DatadogTracingBackendConfig struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	// Address of datadog collector.
+	Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"`
+	// Port of datadog collector
+	Port uint32 `protobuf:"varint,2,opt,name=port,proto3" json:"port,omitempty"`
+}
+
+func (x *DatadogTracingBackendConfig) Reset() {
+	*x = DatadogTracingBackendConfig{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_mesh_v1alpha1_mesh_proto_msgTypes[5]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *DatadogTracingBackendConfig) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*DatadogTracingBackendConfig) ProtoMessage() {}
+
+func (x *DatadogTracingBackendConfig) ProtoReflect() protoreflect.Message {
+	mi := &file_mesh_v1alpha1_mesh_proto_msgTypes[5]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use DatadogTracingBackendConfig.ProtoReflect.Descriptor instead.
+func (*DatadogTracingBackendConfig) Descriptor() ([]byte, []int) {
+	return file_mesh_v1alpha1_mesh_proto_rawDescGZIP(), []int{5}
+}
+
+func (x *DatadogTracingBackendConfig) GetAddress() string {
+	if x != nil {
+		return x.Address
+	}
+	return ""
+}
+
+func (x *DatadogTracingBackendConfig) GetPort() uint32 {
+	if x != nil {
+		return x.Port
+	}
+	return 0
+}
+
 type ZipkinTracingBackendConfig struct {
 	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
@@ -415,7 +472,7 @@ type ZipkinTracingBackendConfig struct {
 func (x *ZipkinTracingBackendConfig) Reset() {
 	*x = ZipkinTracingBackendConfig{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_mesh_v1alpha1_mesh_proto_msgTypes[5]
+		mi := &file_mesh_v1alpha1_mesh_proto_msgTypes[6]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -428,7 +485,7 @@ func (x *ZipkinTracingBackendConfig) String() string {
 func (*ZipkinTracingBackendConfig) ProtoMessage() {}
 
 func (x *ZipkinTracingBackendConfig) ProtoReflect() protoreflect.Message {
-	mi := &file_mesh_v1alpha1_mesh_proto_msgTypes[5]
+	mi := &file_mesh_v1alpha1_mesh_proto_msgTypes[6]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -441,7 +498,7 @@ func (x *ZipkinTracingBackendConfig) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use ZipkinTracingBackendConfig.ProtoReflect.Descriptor instead.
 func (*ZipkinTracingBackendConfig) Descriptor() ([]byte, []int) {
-	return file_mesh_v1alpha1_mesh_proto_rawDescGZIP(), []int{5}
+	return file_mesh_v1alpha1_mesh_proto_rawDescGZIP(), []int{6}
 }
 
 func (x *ZipkinTracingBackendConfig) GetUrl() string {
@@ -486,7 +543,7 @@ type Logging struct {
 func (x *Logging) Reset() {
 	*x = Logging{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_mesh_v1alpha1_mesh_proto_msgTypes[6]
+		mi := &file_mesh_v1alpha1_mesh_proto_msgTypes[7]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -499,7 +556,7 @@ func (x *Logging) String() string {
 func (*Logging) ProtoMessage() {}
 
 func (x *Logging) ProtoReflect() protoreflect.Message {
-	mi := &file_mesh_v1alpha1_mesh_proto_msgTypes[6]
+	mi := &file_mesh_v1alpha1_mesh_proto_msgTypes[7]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -512,7 +569,7 @@ func (x *Logging) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use Logging.ProtoReflect.Descriptor instead.
 func (*Logging) Descriptor() ([]byte, []int) {
-	return file_mesh_v1alpha1_mesh_proto_rawDescGZIP(), []int{6}
+	return file_mesh_v1alpha1_mesh_proto_rawDescGZIP(), []int{7}
 }
 
 func (x *Logging) GetDefaultBackend() string {
@@ -551,7 +608,7 @@ type LoggingBackend struct {
 func (x *LoggingBackend) Reset() {
 	*x = LoggingBackend{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_mesh_v1alpha1_mesh_proto_msgTypes[7]
+		mi := &file_mesh_v1alpha1_mesh_proto_msgTypes[8]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -564,7 +621,7 @@ func (x *LoggingBackend) String() string {
 func (*LoggingBackend) ProtoMessage() {}
 
 func (x *LoggingBackend) ProtoReflect() protoreflect.Message {
-	mi := &file_mesh_v1alpha1_mesh_proto_msgTypes[7]
+	mi := &file_mesh_v1alpha1_mesh_proto_msgTypes[8]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -577,7 +634,7 @@ func (x *LoggingBackend) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use LoggingBackend.ProtoReflect.Descriptor instead.
 func (*LoggingBackend) Descriptor() ([]byte, []int) {
-	return file_mesh_v1alpha1_mesh_proto_rawDescGZIP(), []int{7}
+	return file_mesh_v1alpha1_mesh_proto_rawDescGZIP(), []int{8}
 }
 
 func (x *LoggingBackend) GetName() string {
@@ -621,7 +678,7 @@ type FileLoggingBackendConfig struct {
 func (x *FileLoggingBackendConfig) Reset() {
 	*x = FileLoggingBackendConfig{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_mesh_v1alpha1_mesh_proto_msgTypes[8]
+		mi := &file_mesh_v1alpha1_mesh_proto_msgTypes[9]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -634,7 +691,7 @@ func (x *FileLoggingBackendConfig) String() string {
 func (*FileLoggingBackendConfig) ProtoMessage() {}
 
 func (x *FileLoggingBackendConfig) ProtoReflect() protoreflect.Message {
-	mi := &file_mesh_v1alpha1_mesh_proto_msgTypes[8]
+	mi := &file_mesh_v1alpha1_mesh_proto_msgTypes[9]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -647,7 +704,7 @@ func (x *FileLoggingBackendConfig) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use FileLoggingBackendConfig.ProtoReflect.Descriptor instead.
 func (*FileLoggingBackendConfig) Descriptor() ([]byte, []int) {
-	return file_mesh_v1alpha1_mesh_proto_rawDescGZIP(), []int{8}
+	return file_mesh_v1alpha1_mesh_proto_rawDescGZIP(), []int{9}
 }
 
 func (x *FileLoggingBackendConfig) GetPath() string {
@@ -670,7 +727,7 @@ type TcpLoggingBackendConfig struct {
 func (x *TcpLoggingBackendConfig) Reset() {
 	*x = TcpLoggingBackendConfig{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_mesh_v1alpha1_mesh_proto_msgTypes[9]
+		mi := &file_mesh_v1alpha1_mesh_proto_msgTypes[10]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -683,7 +740,7 @@ func (x *TcpLoggingBackendConfig) String() string {
 func (*TcpLoggingBackendConfig) ProtoMessage() {}
 
 func (x *TcpLoggingBackendConfig) ProtoReflect() protoreflect.Message {
-	mi := &file_mesh_v1alpha1_mesh_proto_msgTypes[9]
+	mi := &file_mesh_v1alpha1_mesh_proto_msgTypes[10]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -696,7 +753,7 @@ func (x *TcpLoggingBackendConfig) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use TcpLoggingBackendConfig.ProtoReflect.Descriptor instead.
 func (*TcpLoggingBackendConfig) Descriptor() ([]byte, []int) {
-	return file_mesh_v1alpha1_mesh_proto_rawDescGZIP(), []int{9}
+	return file_mesh_v1alpha1_mesh_proto_rawDescGZIP(), []int{10}
 }
 
 func (x *TcpLoggingBackendConfig) GetAddress() string {
@@ -719,7 +776,7 @@ type Routing struct {
 func (x *Routing) Reset() {
 	*x = Routing{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_mesh_v1alpha1_mesh_proto_msgTypes[10]
+		mi := &file_mesh_v1alpha1_mesh_proto_msgTypes[11]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -732,7 +789,7 @@ func (x *Routing) String() string {
 func (*Routing) ProtoMessage() {}
 
 func (x *Routing) ProtoReflect() protoreflect.Message {
-	mi := &file_mesh_v1alpha1_mesh_proto_msgTypes[10]
+	mi := &file_mesh_v1alpha1_mesh_proto_msgTypes[11]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -745,7 +802,7 @@ func (x *Routing) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use Routing.ProtoReflect.Descriptor instead.
 func (*Routing) Descriptor() ([]byte, []int) {
-	return file_mesh_v1alpha1_mesh_proto_rawDescGZIP(), []int{10}
+	return file_mesh_v1alpha1_mesh_proto_rawDescGZIP(), []int{11}
 }
 
 func (x *Routing) GetLocalityAwareLoadBalancing() bool {
@@ -770,7 +827,7 @@ type Mesh_Mtls struct {
 func (x *Mesh_Mtls) Reset() {
 	*x = Mesh_Mtls{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_mesh_v1alpha1_mesh_proto_msgTypes[11]
+		mi := &file_mesh_v1alpha1_mesh_proto_msgTypes[12]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -783,7 +840,7 @@ func (x *Mesh_Mtls) String() string {
 func (*Mesh_Mtls) ProtoMessage() {}
 
 func (x *Mesh_Mtls) ProtoReflect() protoreflect.Message {
-	mi := &file_mesh_v1alpha1_mesh_proto_msgTypes[11]
+	mi := &file_mesh_v1alpha1_mesh_proto_msgTypes[12]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -826,7 +883,7 @@ type CertificateAuthorityBackend_DpCert struct {
 func (x *CertificateAuthorityBackend_DpCert) Reset() {
 	*x = CertificateAuthorityBackend_DpCert{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_mesh_v1alpha1_mesh_proto_msgTypes[12]
+		mi := &file_mesh_v1alpha1_mesh_proto_msgTypes[13]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -839,7 +896,7 @@ func (x *CertificateAuthorityBackend_DpCert) String() string {
 func (*CertificateAuthorityBackend_DpCert) ProtoMessage() {}
 
 func (x *CertificateAuthorityBackend_DpCert) ProtoReflect() protoreflect.Message {
-	mi := &file_mesh_v1alpha1_mesh_proto_msgTypes[12]
+	mi := &file_mesh_v1alpha1_mesh_proto_msgTypes[13]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -875,7 +932,7 @@ type CertificateAuthorityBackend_DpCert_Rotation struct {
 func (x *CertificateAuthorityBackend_DpCert_Rotation) Reset() {
 	*x = CertificateAuthorityBackend_DpCert_Rotation{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_mesh_v1alpha1_mesh_proto_msgTypes[13]
+		mi := &file_mesh_v1alpha1_mesh_proto_msgTypes[14]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -888,7 +945,7 @@ func (x *CertificateAuthorityBackend_DpCert_Rotation) String() string {
 func (*CertificateAuthorityBackend_DpCert_Rotation) ProtoMessage() {}
 
 func (x *CertificateAuthorityBackend_DpCert_Rotation) ProtoReflect() protoreflect.Message {
-	mi := &file_mesh_v1alpha1_mesh_proto_msgTypes[13]
+	mi := &file_mesh_v1alpha1_mesh_proto_msgTypes[14]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -924,7 +981,7 @@ type Networking_Outbound struct {
 func (x *Networking_Outbound) Reset() {
 	*x = Networking_Outbound{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_mesh_v1alpha1_mesh_proto_msgTypes[14]
+		mi := &file_mesh_v1alpha1_mesh_proto_msgTypes[15]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -937,7 +994,7 @@ func (x *Networking_Outbound) String() string {
 func (*Networking_Outbound) ProtoMessage() {}
 
 func (x *Networking_Outbound) ProtoReflect() protoreflect.Message {
-	mi := &file_mesh_v1alpha1_mesh_proto_msgTypes[14]
+	mi := &file_mesh_v1alpha1_mesh_proto_msgTypes[15]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -1054,48 +1111,53 @@ var file_mesh_v1alpha1_mesh_proto_rawDesc = []byte{
 	0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x2b, 0x0a, 0x04, 0x63, 0x6f, 0x6e, 0x66, 0x18,
 	0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70,
 	0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x04,
-	0x63, 0x6f, 0x6e, 0x66, 0x22, 0xbe, 0x01, 0x0a, 0x1a, 0x5a, 0x69, 0x70, 0x6b, 0x69, 0x6e, 0x54,
+	0x63, 0x6f, 0x6e, 0x66, 0x22, 0x4b, 0x0a, 0x1b, 0x44, 0x61, 0x74, 0x61, 0x64, 0x6f, 0x67, 0x54,
 	0x72, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x43, 0x6f, 0x6e,
-	0x66, 0x69, 0x67, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
-	0x52, 0x03, 0x75, 0x72, 0x6c, 0x12, 0x24, 0x0a, 0x0d, 0x74, 0x72, 0x61, 0x63, 0x65, 0x49, 0x64,
-	0x31, 0x32, 0x38, 0x62, 0x69, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x74, 0x72,
-	0x61, 0x63, 0x65, 0x49, 0x64, 0x31, 0x32, 0x38, 0x62, 0x69, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x61,
-	0x70, 0x69, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52,
-	0x0a, 0x61, 0x70, 0x69, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x48, 0x0a, 0x11, 0x73,
-	0x68, 0x61, 0x72, 0x65, 0x64, 0x53, 0x70, 0x61, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74,
-	0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
-	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c,
-	0x75, 0x65, 0x52, 0x11, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x53, 0x70, 0x61, 0x6e, 0x43, 0x6f,
-	0x6e, 0x74, 0x65, 0x78, 0x74, 0x22, 0x71, 0x0a, 0x07, 0x4c, 0x6f, 0x67, 0x67, 0x69, 0x6e, 0x67,
-	0x12, 0x26, 0x0a, 0x0e, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x42, 0x61, 0x63, 0x6b, 0x65,
-	0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c,
-	0x74, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x12, 0x3e, 0x0a, 0x08, 0x62, 0x61, 0x63, 0x6b,
-	0x65, 0x6e, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x6b, 0x75, 0x6d,
-	0x61, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e,
-	0x4c, 0x6f, 0x67, 0x67, 0x69, 0x6e, 0x67, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x52, 0x08,
-	0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x73, 0x22, 0x7d, 0x0a, 0x0e, 0x4c, 0x6f, 0x67, 0x67,
-	0x69, 0x6e, 0x67, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61,
-	0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16,
-	0x0a, 0x06, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06,
-	0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03,
-	0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x2b, 0x0a, 0x04, 0x63, 0x6f,
-	0x6e, 0x66, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
-	0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63,
-	0x74, 0x52, 0x04, 0x63, 0x6f, 0x6e, 0x66, 0x22, 0x2e, 0x0a, 0x18, 0x46, 0x69, 0x6c, 0x65, 0x4c,
-	0x6f, 0x67, 0x67, 0x69, 0x6e, 0x67, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x43, 0x6f, 0x6e,
-	0x66, 0x69, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28,
-	0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x22, 0x33, 0x0a, 0x17, 0x54, 0x63, 0x70, 0x4c, 0x6f,
-	0x67, 0x67, 0x69, 0x6e, 0x67, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x66,
-	0x69, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20,
-	0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x49, 0x0a, 0x07,
-	0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x12, 0x3e, 0x0a, 0x1a, 0x6c, 0x6f, 0x63, 0x61, 0x6c,
-	0x69, 0x74, 0x79, 0x41, 0x77, 0x61, 0x72, 0x65, 0x4c, 0x6f, 0x61, 0x64, 0x42, 0x61, 0x6c, 0x61,
-	0x6e, 0x63, 0x69, 0x6e, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1a, 0x6c, 0x6f, 0x63,
-	0x61, 0x6c, 0x69, 0x74, 0x79, 0x41, 0x77, 0x61, 0x72, 0x65, 0x4c, 0x6f, 0x61, 0x64, 0x42, 0x61,
-	0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x42, 0x2a, 0x5a, 0x28, 0x67, 0x69, 0x74, 0x68, 0x75,
-	0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6b, 0x75, 0x6d, 0x61, 0x68, 0x71, 0x2f, 0x6b, 0x75, 0x6d,
-	0x61, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70,
-	0x68, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+	0x66, 0x69, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01,
+	0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x12, 0x0a,
+	0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x70, 0x6f, 0x72,
+	0x74, 0x22, 0xbe, 0x01, 0x0a, 0x1a, 0x5a, 0x69, 0x70, 0x6b, 0x69, 0x6e, 0x54, 0x72, 0x61, 0x63,
+	0x69, 0x6e, 0x67, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
+	0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75,
+	0x72, 0x6c, 0x12, 0x24, 0x0a, 0x0d, 0x74, 0x72, 0x61, 0x63, 0x65, 0x49, 0x64, 0x31, 0x32, 0x38,
+	0x62, 0x69, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x74, 0x72, 0x61, 0x63, 0x65,
+	0x49, 0x64, 0x31, 0x32, 0x38, 0x62, 0x69, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x61, 0x70, 0x69, 0x56,
+	0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x61, 0x70,
+	0x69, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x48, 0x0a, 0x11, 0x73, 0x68, 0x61, 0x72,
+	0x65, 0x64, 0x53, 0x70, 0x61, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x04, 0x20,
+	0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f,
+	0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52,
+	0x11, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x53, 0x70, 0x61, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x65,
+	0x78, 0x74, 0x22, 0x71, 0x0a, 0x07, 0x4c, 0x6f, 0x67, 0x67, 0x69, 0x6e, 0x67, 0x12, 0x26, 0x0a,
+	0x0e, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x18,
+	0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x42, 0x61,
+	0x63, 0x6b, 0x65, 0x6e, 0x64, 0x12, 0x3e, 0x0a, 0x08, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64,
+	0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x6b, 0x75, 0x6d, 0x61, 0x2e, 0x6d,
+	0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4c, 0x6f, 0x67,
+	0x67, 0x69, 0x6e, 0x67, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x52, 0x08, 0x62, 0x61, 0x63,
+	0x6b, 0x65, 0x6e, 0x64, 0x73, 0x22, 0x7d, 0x0a, 0x0e, 0x4c, 0x6f, 0x67, 0x67, 0x69, 0x6e, 0x67,
+	0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18,
+	0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x66,
+	0x6f, 0x72, 0x6d, 0x61, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x66, 0x6f, 0x72,
+	0x6d, 0x61, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28,
+	0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x2b, 0x0a, 0x04, 0x63, 0x6f, 0x6e, 0x66, 0x18,
+	0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70,
+	0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x04,
+	0x63, 0x6f, 0x6e, 0x66, 0x22, 0x2e, 0x0a, 0x18, 0x46, 0x69, 0x6c, 0x65, 0x4c, 0x6f, 0x67, 0x67,
+	0x69, 0x6e, 0x67, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
+	0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04,
+	0x70, 0x61, 0x74, 0x68, 0x22, 0x33, 0x0a, 0x17, 0x54, 0x63, 0x70, 0x4c, 0x6f, 0x67, 0x67, 0x69,
+	0x6e, 0x67, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12,
+	0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
+	0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x49, 0x0a, 0x07, 0x52, 0x6f, 0x75,
+	0x74, 0x69, 0x6e, 0x67, 0x12, 0x3e, 0x0a, 0x1a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x69, 0x74, 0x79,
+	0x41, 0x77, 0x61, 0x72, 0x65, 0x4c, 0x6f, 0x61, 0x64, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69,
+	0x6e, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x69,
+	0x74, 0x79, 0x41, 0x77, 0x61, 0x72, 0x65, 0x4c, 0x6f, 0x61, 0x64, 0x42, 0x61, 0x6c, 0x61, 0x6e,
+	0x63, 0x69, 0x6e, 0x67, 0x42, 0x2a, 0x5a, 0x28, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63,
+	0x6f, 0x6d, 0x2f, 0x6b, 0x75, 0x6d, 0x61, 0x68, 0x71, 0x2f, 0x6b, 0x75, 0x6d, 0x61, 0x2f, 0x61,
+	0x70, 0x69, 0x2f, 0x6d, 0x65, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31,
+	0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
 }
 
 var (
@@ -1110,47 +1172,48 @@ func file_mesh_v1alpha1_mesh_proto_rawDescGZIP() []byte {
 	return file_mesh_v1alpha1_mesh_proto_rawDescData
 }
 
-var file_mesh_v1alpha1_mesh_proto_msgTypes = make([]protoimpl.MessageInfo, 15)
+var file_mesh_v1alpha1_mesh_proto_msgTypes = make([]protoimpl.MessageInfo, 16)
 var file_mesh_v1alpha1_mesh_proto_goTypes = []interface{}{
 	(*Mesh)(nil),                                        // 0: kuma.mesh.v1alpha1.Mesh
 	(*CertificateAuthorityBackend)(nil),                 // 1: kuma.mesh.v1alpha1.CertificateAuthorityBackend
 	(*Networking)(nil),                                  // 2: kuma.mesh.v1alpha1.Networking
 	(*Tracing)(nil),                                     // 3: kuma.mesh.v1alpha1.Tracing
 	(*TracingBackend)(nil),                              // 4: kuma.mesh.v1alpha1.TracingBackend
-	(*ZipkinTracingBackendConfig)(nil),                  // 5: kuma.mesh.v1alpha1.ZipkinTracingBackendConfig
-	(*Logging)(nil),                                     // 6: kuma.mesh.v1alpha1.Logging
-	(*LoggingBackend)(nil),                              // 7: kuma.mesh.v1alpha1.LoggingBackend
-	(*FileLoggingBackendConfig)(nil),                    // 8: kuma.mesh.v1alpha1.FileLoggingBackendConfig
-	(*TcpLoggingBackendConfig)(nil),                     // 9: kuma.mesh.v1alpha1.TcpLoggingBackendConfig
-	(*Routing)(nil),                                     // 10: kuma.mesh.v1alpha1.Routing
-	(*Mesh_Mtls)(nil),                                   // 11: kuma.mesh.v1alpha1.Mesh.Mtls
-	(*CertificateAuthorityBackend_DpCert)(nil),          // 12: kuma.mesh.v1alpha1.CertificateAuthorityBackend.DpCert
-	(*CertificateAuthorityBackend_DpCert_Rotation)(nil), // 13: kuma.mesh.v1alpha1.CertificateAuthorityBackend.DpCert.Rotation
-	(*Networking_Outbound)(nil),                         // 14: kuma.mesh.v1alpha1.Networking.Outbound
-	(*Metrics)(nil),                                     // 15: kuma.mesh.v1alpha1.Metrics
-	(*_struct.Struct)(nil),                              // 16: google.protobuf.Struct
-	(*wrappers.DoubleValue)(nil),                        // 17: google.protobuf.DoubleValue
-	(*wrappers.BoolValue)(nil),                          // 18: google.protobuf.BoolValue
+	(*DatadogTracingBackendConfig)(nil),                 // 5: kuma.mesh.v1alpha1.DatadogTracingBackendConfig
+	(*ZipkinTracingBackendConfig)(nil),                  // 6: kuma.mesh.v1alpha1.ZipkinTracingBackendConfig
+	(*Logging)(nil),                                     // 7: kuma.mesh.v1alpha1.Logging
+	(*LoggingBackend)(nil),                              // 8: kuma.mesh.v1alpha1.LoggingBackend
+	(*FileLoggingBackendConfig)(nil),                    // 9: kuma.mesh.v1alpha1.FileLoggingBackendConfig
+	(*TcpLoggingBackendConfig)(nil),                     // 10: kuma.mesh.v1alpha1.TcpLoggingBackendConfig
+	(*Routing)(nil),                                     // 11: kuma.mesh.v1alpha1.Routing
+	(*Mesh_Mtls)(nil),                                   // 12: kuma.mesh.v1alpha1.Mesh.Mtls
+	(*CertificateAuthorityBackend_DpCert)(nil),          // 13: kuma.mesh.v1alpha1.CertificateAuthorityBackend.DpCert
+	(*CertificateAuthorityBackend_DpCert_Rotation)(nil), // 14: kuma.mesh.v1alpha1.CertificateAuthorityBackend.DpCert.Rotation
+	(*Networking_Outbound)(nil),                         // 15: kuma.mesh.v1alpha1.Networking.Outbound
+	(*Metrics)(nil),                                     // 16: kuma.mesh.v1alpha1.Metrics
+	(*_struct.Struct)(nil),                              // 17: google.protobuf.Struct
+	(*wrappers.DoubleValue)(nil),                        // 18: google.protobuf.DoubleValue
+	(*wrappers.BoolValue)(nil),                          // 19: google.protobuf.BoolValue
 }
 var file_mesh_v1alpha1_mesh_proto_depIdxs = []int32{
-	11, // 0: kuma.mesh.v1alpha1.Mesh.mtls:type_name -> kuma.mesh.v1alpha1.Mesh.Mtls
+	12, // 0: kuma.mesh.v1alpha1.Mesh.mtls:type_name -> kuma.mesh.v1alpha1.Mesh.Mtls
 	3,  // 1: kuma.mesh.v1alpha1.Mesh.tracing:type_name -> kuma.mesh.v1alpha1.Tracing
-	6,  // 2: kuma.mesh.v1alpha1.Mesh.logging:type_name -> kuma.mesh.v1alpha1.Logging
-	15, // 3: kuma.mesh.v1alpha1.Mesh.metrics:type_name -> kuma.mesh.v1alpha1.Metrics
+	7,  // 2: kuma.mesh.v1alpha1.Mesh.logging:type_name -> kuma.mesh.v1alpha1.Logging
+	16, // 3: kuma.mesh.v1alpha1.Mesh.metrics:type_name -> kuma.mesh.v1alpha1.Metrics
 	2,  // 4: kuma.mesh.v1alpha1.Mesh.networking:type_name -> kuma.mesh.v1alpha1.Networking
-	10, // 5: kuma.mesh.v1alpha1.Mesh.routing:type_name -> kuma.mesh.v1alpha1.Routing
-	12, // 6: kuma.mesh.v1alpha1.CertificateAuthorityBackend.dpCert:type_name -> kuma.mesh.v1alpha1.CertificateAuthorityBackend.DpCert
-	16, // 7: kuma.mesh.v1alpha1.CertificateAuthorityBackend.conf:type_name -> google.protobuf.Struct
-	14, // 8: kuma.mesh.v1alpha1.Networking.outbound:type_name -> kuma.mesh.v1alpha1.Networking.Outbound
+	11, // 5: kuma.mesh.v1alpha1.Mesh.routing:type_name -> kuma.mesh.v1alpha1.Routing
+	13, // 6: kuma.mesh.v1alpha1.CertificateAuthorityBackend.dpCert:type_name -> kuma.mesh.v1alpha1.CertificateAuthorityBackend.DpCert
+	17, // 7: kuma.mesh.v1alpha1.CertificateAuthorityBackend.conf:type_name -> google.protobuf.Struct
+	15, // 8: kuma.mesh.v1alpha1.Networking.outbound:type_name -> kuma.mesh.v1alpha1.Networking.Outbound
 	4,  // 9: kuma.mesh.v1alpha1.Tracing.backends:type_name -> kuma.mesh.v1alpha1.TracingBackend
-	17, // 10: kuma.mesh.v1alpha1.TracingBackend.sampling:type_name -> google.protobuf.DoubleValue
-	16, // 11: kuma.mesh.v1alpha1.TracingBackend.conf:type_name -> google.protobuf.Struct
-	18, // 12: kuma.mesh.v1alpha1.ZipkinTracingBackendConfig.sharedSpanContext:type_name -> google.protobuf.BoolValue
-	7,  // 13: kuma.mesh.v1alpha1.Logging.backends:type_name -> kuma.mesh.v1alpha1.LoggingBackend
-	16, // 14: kuma.mesh.v1alpha1.LoggingBackend.conf:type_name -> google.protobuf.Struct
+	18, // 10: kuma.mesh.v1alpha1.TracingBackend.sampling:type_name -> google.protobuf.DoubleValue
+	17, // 11: kuma.mesh.v1alpha1.TracingBackend.conf:type_name -> google.protobuf.Struct
+	19, // 12: kuma.mesh.v1alpha1.ZipkinTracingBackendConfig.sharedSpanContext:type_name -> google.protobuf.BoolValue
+	8,  // 13: kuma.mesh.v1alpha1.Logging.backends:type_name -> kuma.mesh.v1alpha1.LoggingBackend
+	17, // 14: kuma.mesh.v1alpha1.LoggingBackend.conf:type_name -> google.protobuf.Struct
 	1,  // 15: kuma.mesh.v1alpha1.Mesh.Mtls.backends:type_name -> kuma.mesh.v1alpha1.CertificateAuthorityBackend
-	13, // 16: kuma.mesh.v1alpha1.CertificateAuthorityBackend.DpCert.rotation:type_name -> kuma.mesh.v1alpha1.CertificateAuthorityBackend.DpCert.Rotation
-	18, // 17: kuma.mesh.v1alpha1.Networking.Outbound.passthrough:type_name -> google.protobuf.BoolValue
+	14, // 16: kuma.mesh.v1alpha1.CertificateAuthorityBackend.DpCert.rotation:type_name -> kuma.mesh.v1alpha1.CertificateAuthorityBackend.DpCert.Rotation
+	19, // 17: kuma.mesh.v1alpha1.Networking.Outbound.passthrough:type_name -> google.protobuf.BoolValue
 	18, // [18:18] is the sub-list for method output_type
 	18, // [18:18] is the sub-list for method input_type
 	18, // [18:18] is the sub-list for extension type_name
@@ -1226,7 +1289,7 @@ func file_mesh_v1alpha1_mesh_proto_init() {
 			}
 		}
 		file_mesh_v1alpha1_mesh_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*ZipkinTracingBackendConfig); i {
+			switch v := v.(*DatadogTracingBackendConfig); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -1238,7 +1301,7 @@ func file_mesh_v1alpha1_mesh_proto_init() {
 			}
 		}
 		file_mesh_v1alpha1_mesh_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*Logging); i {
+			switch v := v.(*ZipkinTracingBackendConfig); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -1250,7 +1313,7 @@ func file_mesh_v1alpha1_mesh_proto_init() {
 			}
 		}
 		file_mesh_v1alpha1_mesh_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*LoggingBackend); i {
+			switch v := v.(*Logging); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -1262,7 +1325,7 @@ func file_mesh_v1alpha1_mesh_proto_init() {
 			}
 		}
 		file_mesh_v1alpha1_mesh_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*FileLoggingBackendConfig); i {
+			switch v := v.(*LoggingBackend); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -1274,7 +1337,7 @@ func file_mesh_v1alpha1_mesh_proto_init() {
 			}
 		}
 		file_mesh_v1alpha1_mesh_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*TcpLoggingBackendConfig); i {
+			switch v := v.(*FileLoggingBackendConfig); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -1286,7 +1349,7 @@ func file_mesh_v1alpha1_mesh_proto_init() {
 			}
 		}
 		file_mesh_v1alpha1_mesh_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*Routing); i {
+			switch v := v.(*TcpLoggingBackendConfig); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -1298,7 +1361,7 @@ func file_mesh_v1alpha1_mesh_proto_init() {
 			}
 		}
 		file_mesh_v1alpha1_mesh_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*Mesh_Mtls); i {
+			switch v := v.(*Routing); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -1310,7 +1373,7 @@ func file_mesh_v1alpha1_mesh_proto_init() {
 			}
 		}
 		file_mesh_v1alpha1_mesh_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*CertificateAuthorityBackend_DpCert); i {
+			switch v := v.(*Mesh_Mtls); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -1322,7 +1385,7 @@ func file_mesh_v1alpha1_mesh_proto_init() {
 			}
 		}
 		file_mesh_v1alpha1_mesh_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*CertificateAuthorityBackend_DpCert_Rotation); i {
+			switch v := v.(*CertificateAuthorityBackend_DpCert); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -1334,6 +1397,18 @@ func file_mesh_v1alpha1_mesh_proto_init() {
 			}
 		}
 		file_mesh_v1alpha1_mesh_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*CertificateAuthorityBackend_DpCert_Rotation); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_mesh_v1alpha1_mesh_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} {
 			switch v := v.(*Networking_Outbound); i {
 			case 0:
 				return &v.state
@@ -1352,7 +1427,7 @@ func file_mesh_v1alpha1_mesh_proto_init() {
 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
 			RawDescriptor: file_mesh_v1alpha1_mesh_proto_rawDesc,
 			NumEnums:      0,
-			NumMessages:   15,
+			NumMessages:   16,
 			NumExtensions: 0,
 			NumServices:   0,
 		},
diff --git a/api/mesh/v1alpha1/mesh.proto b/api/mesh/v1alpha1/mesh.proto
index 90c16ecb1..6c6c7ef13 100644
--- a/api/mesh/v1alpha1/mesh.proto
+++ b/api/mesh/v1alpha1/mesh.proto
@@ -123,6 +123,14 @@ message TracingBackend {
   google.protobuf.Struct conf = 4;
 }
 
+message DatadogTracingBackendConfig {
+  // Address of datadog collector.
+  string address = 1;
+
+  // Port of datadog collector
+  uint32 port = 2;
+}
+
 message ZipkinTracingBackendConfig {
   // Address of Zipkin collector.
   string url = 1;
diff --git a/pkg/config/app/kuma-cp/kuma-cp.defaults.yaml b/pkg/config/app/kuma-cp/kuma-cp.defaults.yaml
index 047365b18..ef0c1ed44 100644
--- a/pkg/config/app/kuma-cp/kuma-cp.defaults.yaml
+++ b/pkg/config/app/kuma-cp/kuma-cp.defaults.yaml
@@ -313,8 +313,6 @@ dnsServer:
 # Multizone mode
 multizone:
   global:
-    # The Zone status poller timeout
-    pollTimeout: 500ms # ENV: KUMA_MULTIZONE_GLOBAL_POLL_TIMEOUT
     kds:
       # Port of a gRPC server that serves Kuma Discovery Service (KDS).
       grpcPort: 5685 # ENV: KUMA_MULTIZONE_GLOBAL_KDS_GRPC_PORT
@@ -326,6 +324,9 @@ multizone:
       tlsCertFile: # ENV: KUMA_MULTIZONE_GLOBAL_KDS_TLS_CERT_FILE
       # TTlsKeyFile defines a path to a file with PEM-encoded TLS key.
       tlsKeyFile: # ENV: KUMA_MULTIZONE_GLOBAL_KDS_TLS_KEY_FILE
+      # MaxMsgSize defines a maximum size of the message in bytes that is exchanged using KDS.
+      # In practice this means a limit on full list of one resource type.
+      maxMsgSize: 10485760 # ENV: KUMA_MULTIZONE_GLOBAL_KDS_MAX_MSG_SIZE
   zone:
     # Kuma Zone name used to mark the zone dataplane resources
     name: "" # ENV: KUMA_MULTIZONE_ZONE_NAME
@@ -336,6 +337,9 @@ multizone:
       refreshInterval: 1s # ENV: KUMA_MULTIZONE_ZONE_KDS_REFRESH_INTERVAL
       # RootCAFile defines a path to a file with PEM-encoded Root CA. Client will verify server by using it.
       rootCaFile: # ENV: KUMA_MULTIZONE_ZONE_KDS_ROOT_CA_FILE
+      # MaxMsgSize defines a maximum size of the message in bytes that is exchanged using KDS.
+      # In practice this means a limit on full list of one resource type.
+      maxMsgSize: 10485760 # ENV: KUMA_MULTIZONE_ZONE_KDS_MAX_MSG_SIZE
 
 # Diagnostics configuration
 diagnostics:
diff --git a/pkg/config/multizone/kds.go b/pkg/config/multizone/kds.go
index b21ac4eca..edeb700a4 100644
--- a/pkg/config/multizone/kds.go
+++ b/pkg/config/multizone/kds.go
@@ -20,6 +20,9 @@ type KdsServerConfig struct {
 	TlsCertFile string `yaml:"tlsCertFile" envconfig:"kuma_multizone_global_kds_tls_cert_file"`
 	// TlsKeyFile defines a path to a file with PEM-encoded TLS key.
 	TlsKeyFile string `yaml:"tlsKeyFile" envconfig:"kuma_multizone_global_kds_tls_key_file"`
+	// MaxMsgSize defines a maximum size of the message that is exchanged using KDS.
+	// In practice this means a limit on full list of one resource type.
+	MaxMsgSize uint32 `yaml:"maxMsgSize" envconfig:"kuma_multizone_global_kds_max_msg_size"`
 }
 
 var _ config.Config = &KdsServerConfig{}
@@ -51,6 +54,9 @@ type KdsClientConfig struct {
 	RefreshInterval time.Duration `yaml:"refreshInterval" envconfig:"kuma_multizone_zone_kds_refresh_interval"`
 	// RootCAFile defines a path to a file with PEM-encoded Root CA. Client will verify the server by using it.
 	RootCAFile string `yaml:"rootCaFile" envconfig:"kuma_multizone_zone_kds_root_ca_file"`
+	// MaxMsgSize defines a maximum size of the message that is exchanged using KDS.
+	// In practice this means a limit on full list of one resource type.
+	MaxMsgSize uint32 `yaml:"maxMsgSize" envconfig:"kuma_multizone_zone_kds_max_msg_size"`
 }
 
 var _ config.Config = &KdsClientConfig{}
diff --git a/pkg/config/multizone/multicluster.go b/pkg/config/multizone/multicluster.go
index 9aeb65567..bd17b5d76 100644
--- a/pkg/config/multizone/multicluster.go
+++ b/pkg/config/multizone/multicluster.go
@@ -16,7 +16,6 @@ var _ config.Config = &MultizoneConfig{}
 
 // Global configuration
 type GlobalConfig struct {
-	PollTimeout time.Duration `yaml:"pollTimeout,omitempty" envconfig:"kuma_multizone_global_poll_timeout"`
 	// KDS Configuration
 	KDS *KdsServerConfig `yaml:"kds,omitempty"`
 }
@@ -31,11 +30,11 @@ func (g *GlobalConfig) Validate() error {
 
 func DefaultGlobalConfig() *GlobalConfig {
 	return &GlobalConfig{
-		PollTimeout: 500 * time.Millisecond,
 		KDS: &KdsServerConfig{
 			GrpcPort:                 5685,
 			RefreshInterval:          1 * time.Second,
 			ZoneInsightFlushInterval: 10 * time.Second,
+			MaxMsgSize:               10 * 1024 * 1024,
 		},
 	}
 }
@@ -94,6 +93,7 @@ func DefaultZoneConfig() *ZoneConfig {
 		Name:          "",
 		KDS: &KdsClientConfig{
 			RefreshInterval: 1 * time.Second,
+			MaxMsgSize:      10 * 1024 * 1024,
 		},
 	}
 }
diff --git a/pkg/core/resources/apis/mesh/mesh_validator.go b/pkg/core/resources/apis/mesh/mesh_validator.go
index fe1fd8e5e..9d70063a0 100644
--- a/pkg/core/resources/apis/mesh/mesh_validator.go
+++ b/pkg/core/resources/apis/mesh/mesh_validator.go
@@ -139,15 +139,36 @@ func validateTracingBackend(backend *mesh_proto.TracingBackend) validators.Valid
 	if backend.Name == "" {
 		verr.AddViolation("name", "cannot be empty")
 	}
-	if backend.GetType() != mesh_proto.TracingZipkinType {
-		verr.AddViolation("type", fmt.Sprintf("unknown backend type. Available backends: %q", mesh_proto.TracingZipkinType))
-	}
 	if backend.Sampling.GetValue() < 0.0 || backend.Sampling.GetValue() > 100.0 {
 		verr.AddViolation("sampling", "has to be in [0.0 - 100.0] range")
 	}
-	if backend.GetType() == mesh_proto.TracingZipkinType {
+	switch backend.GetType() {
+	case mesh_proto.TracingZipkinType:
 		verr.AddError("config", validateZipkin(backend.Conf))
+	case mesh_proto.TracingDatadogType:
+		verr.AddError("config", validateDatadog(backend.Conf))
+	default:
+		verr.AddViolation("type", fmt.Sprintf("unknown backend type. Available backends: %q, %q", mesh_proto.TracingZipkinType, mesh_proto.TracingDatadogType))
+	}
+	return verr
+}
+
+func validateDatadog(cfgStr *structpb.Struct) validators.ValidationError {
+	var verr validators.ValidationError
+	cfg := mesh_proto.DatadogTracingBackendConfig{}
+	if err := proto.ToTyped(cfgStr, &cfg); err != nil {
+		verr.AddViolation("", fmt.Sprintf("could not parse config: %s", err.Error()))
+		return verr
 	}
+
+	if cfg.Address == "" {
+		verr.AddViolation("address", "cannot be empty")
+	}
+
+	if cfg.Port > 0xFFFF || cfg.Port < 1 {
+		verr.AddViolation("port", "must be in the range 1 to 65535")
+	}
+
 	return verr
 }
 
diff --git a/pkg/core/xds/metadata.go b/pkg/core/xds/metadata.go
index 2b2543202..4a3b0c767 100644
--- a/pkg/core/xds/metadata.go
+++ b/pkg/core/xds/metadata.go
@@ -6,12 +6,11 @@ import (
 	_struct "github.com/golang/protobuf/ptypes/struct"
 
 	mesh_proto "github.com/kumahq/kuma/api/mesh/v1alpha1"
-	util_proto "github.com/kumahq/kuma/pkg/util/proto"
-
+	"github.com/kumahq/kuma/pkg/core"
 	core_mesh "github.com/kumahq/kuma/pkg/core/resources/apis/mesh"
+	"github.com/kumahq/kuma/pkg/core/resources/model"
 	"github.com/kumahq/kuma/pkg/core/resources/model/rest"
-
-	"github.com/kumahq/kuma/pkg/core"
+	util_proto "github.com/kumahq/kuma/pkg/util/proto"
 )
 
 var metadataLog = core.Log.WithName("xds-server").WithName("metadata-tracker")
@@ -45,16 +44,15 @@ const (
 // This way, xDS server will be able to use Envoy node metadata
 // to generate xDS resources that depend on environment-specific configuration.
 type DataplaneMetadata struct {
-	DataplaneTokenPath  string
-	DataplaneToken      string
-	DataplaneResource   *core_mesh.DataplaneResource
-	ZoneIngressResource *core_mesh.ZoneIngressResource
-	AdminPort           uint32
-	DNSPort             uint32
-	EmptyDNSPort        uint32
-	DynamicMetadata     map[string]string
-	ProxyType           mesh_proto.ProxyType
-	Version             *mesh_proto.Version
+	DataplaneTokenPath string
+	DataplaneToken     string
+	Resource           model.Resource
+	AdminPort          uint32
+	DNSPort            uint32
+	EmptyDNSPort       uint32
+	DynamicMetadata    map[string]string
+	ProxyType          mesh_proto.ProxyType
+	Version            *mesh_proto.Version
 }
 
 func (m *DataplaneMetadata) GetDataplaneTokenPath() string {
@@ -71,18 +69,28 @@ func (m *DataplaneMetadata) GetDataplaneToken() string {
 	return m.DataplaneToken
 }
 
+// GetDataplaneResource returns the underlying DataplaneResource, if present.
+// If the resource is of a different type, it returns nil.
 func (m *DataplaneMetadata) GetDataplaneResource() *core_mesh.DataplaneResource {
-	if m == nil {
-		return nil
+	if m != nil {
+		if d, ok := m.Resource.(*core_mesh.DataplaneResource); ok {
+			return d
+		}
 	}
-	return m.DataplaneResource
+
+	return nil
 }
 
+// GetZoneIngressResource returns the underlying ZoneIngressResource, if present.
+// If the resource is of a different type, it returns nil.
 func (m *DataplaneMetadata) GetZoneIngressResource() *core_mesh.ZoneIngressResource {
-	if m == nil {
-		return nil
+	if m != nil {
+		if z, ok := m.Resource.(*core_mesh.ZoneIngressResource); ok {
+			return z
+		}
 	}
-	return m.ZoneIngressResource
+
+	return nil
 }
 
 func (m *DataplaneMetadata) GetProxyType() mesh_proto.ProxyType {
@@ -150,12 +158,14 @@ func DataplaneMetadataFromXdsMetadata(xdsMetadata *_struct.Struct) *DataplaneMet
 			metadataLog.Error(err, "invalid value in dataplane metadata", "field", fieldDataplaneDataplaneResource, "value", value)
 		}
 		switch r := res.(type) {
-		case *core_mesh.DataplaneResource:
-			metadata.DataplaneResource = r
-		case *core_mesh.ZoneIngressResource:
-			metadata.ZoneIngressResource = r
+		case *core_mesh.DataplaneResource,
+			*core_mesh.ZoneIngressResource:
+			metadata.Resource = r
 		default:
-			metadataLog.Error(err, "invalid value in dataplane metadata", "field", fieldDataplaneDataplaneResource, "value", value)
+			metadataLog.Error(err, "invalid dataplane resource type",
+				"resource", r.GetType(),
+				"field", fieldDataplaneDataplaneResource,
+				"value", value)
 		}
 	}
 	if value := xdsMetadata.Fields[fieldDynamicMetadata]; value != nil {
diff --git a/pkg/kds/global/components.go b/pkg/kds/global/components.go
index 84a049f28..94b91024d 100644
--- a/pkg/kds/global/components.go
+++ b/pkg/kds/global/components.go
@@ -30,11 +30,13 @@ import (
 )
 
 var (
-	kdsGlobalLog  = core.Log.WithName("kds-global")
+	kdsGlobalLog = core.Log.WithName("kds-global")
+
+	// ProvidedTypes lists the resource types provided by the Global
+	// CP to the Zone CP.
 	ProvidedTypes = []model.ResourceType{
 		core_mesh.CircuitBreakerType,
 		core_mesh.DataplaneType,
-		core_mesh.ZoneIngressType,
 		core_mesh.ExternalServiceType,
 		core_mesh.FaultInjectionType,
 		core_mesh.HealthCheckType,
@@ -47,15 +49,19 @@ var (
 		core_mesh.TrafficPermissionType,
 		core_mesh.TrafficRouteType,
 		core_mesh.TrafficTraceType,
-		system.SecretType,
-		system.GlobalSecretType,
+		core_mesh.ZoneIngressType,
 		system.ConfigType,
+		system.GlobalSecretType,
+		system.SecretType,
 	}
+
+	// ConsumedTypes lists the resource types consumed from the Zone
+	// CP by the Global CP.
 	ConsumedTypes = []model.ResourceType{
-		core_mesh.DataplaneType,
 		core_mesh.DataplaneInsightType,
-		core_mesh.ZoneIngressType,
+		core_mesh.DataplaneType,
 		core_mesh.ZoneIngressInsightType,
+		core_mesh.ZoneIngressType,
 	}
 )
 
diff --git a/pkg/kds/mux/client.go b/pkg/kds/mux/client.go
index 0142f7547..0c63d6397 100644
--- a/pkg/kds/mux/client.go
+++ b/pkg/kds/mux/client.go
@@ -44,6 +44,10 @@ func (c *client) Start(stop <-chan struct{}) (errs error) {
 		return err
 	}
 	dialOpts := c.metrics.GRPCClientInterceptors()
+	dialOpts = append(dialOpts, grpc.WithDefaultCallOptions(
+		grpc.MaxCallSendMsgSize(int(c.config.MaxMsgSize)),
+		grpc.MaxCallRecvMsgSize(int(c.config.MaxMsgSize))),
+	)
 	switch u.Scheme {
 	case "grpc":
 		dialOpts = append(dialOpts, grpc.WithInsecure())
diff --git a/pkg/kds/mux/server.go b/pkg/kds/mux/server.go
index e1c11ed5f..e065b46b9 100644
--- a/pkg/kds/mux/server.go
+++ b/pkg/kds/mux/server.go
@@ -66,6 +66,8 @@ func (s *server) Start(stop <-chan struct{}) error {
 			MinTime:             grpcKeepAliveTime,
 			PermitWithoutStream: true,
 		}),
+		grpc.MaxRecvMsgSize(int(s.config.MaxMsgSize)),
+		grpc.MaxSendMsgSize(int(s.config.MaxMsgSize)),
 	}
 	grpcOptions = append(grpcOptions, s.metrics.GRPCServerInterceptors()...)
 	useTLS := s.config.TlsCertFile != ""
diff --git a/pkg/kds/types.go b/pkg/kds/types.go
index 43d4732ef..6382892cb 100644
--- a/pkg/kds/types.go
+++ b/pkg/kds/types.go
@@ -8,17 +8,18 @@ import (
 )
 
 const (
-	googleApis   = "type.googleapis.com/"
+	googleApis = "type.googleapis.com/"
+
+	// KumaResource is the type URL of the KumaResource protobuf.
 	KumaResource = googleApis + "kuma.mesh.v1alpha1.KumaResource"
 )
 
 var (
+	// SupportedTypes is a list of Kuma types that may be exchanged by KDS peers.
 	SupportedTypes = []model.ResourceType{
 		mesh.CircuitBreakerType,
-		mesh.DataplaneType,
-		mesh.ZoneIngressType,
-		mesh.ZoneIngressInsightType,
 		mesh.DataplaneInsightType,
+		mesh.DataplaneType,
 		mesh.ExternalServiceType,
 		mesh.FaultInjectionType,
 		mesh.HealthCheckType,
@@ -31,8 +32,10 @@ var (
 		mesh.TrafficPermissionType,
 		mesh.TrafficRouteType,
 		mesh.TrafficTraceType,
-		system.SecretType,
-		system.GlobalSecretType,
+		mesh.ZoneIngressInsightType,
+		mesh.ZoneIngressType,
 		system.ConfigType,
+		system.GlobalSecretType,
+		system.SecretType,
 	}
 )
diff --git a/pkg/kds/zone/components.go b/pkg/kds/zone/components.go
index 7be4948c5..0867ed994 100644
--- a/pkg/kds/zone/components.go
+++ b/pkg/kds/zone/components.go
@@ -24,17 +24,22 @@ import (
 )
 
 var (
-	kdsZoneLog    = core.Log.WithName("kds-zone")
+	kdsZoneLog = core.Log.WithName("kds-zone")
+
+	// ProvidedTypes lists the resource types provided by the Zone
+	// CP to the Global CP.
 	ProvidedTypes = []model.ResourceType{
-		mesh.ZoneIngressType,
-		mesh.ZoneIngressInsightType,
-		mesh.DataplaneType,
 		mesh.DataplaneInsightType,
+		mesh.DataplaneType,
+		mesh.ZoneIngressInsightType,
+		mesh.ZoneIngressType,
 	}
+
+	// ConsumedTypes lists the resource types consumed from the
+	// Global CP by the Zone CP.
 	ConsumedTypes = []model.ResourceType{
 		mesh.CircuitBreakerType,
 		mesh.DataplaneType,
-		mesh.ZoneIngressType,
 		mesh.ExternalServiceType,
 		mesh.FaultInjectionType,
 		mesh.HealthCheckType,
@@ -47,9 +52,10 @@ var (
 		mesh.TrafficPermissionType,
 		mesh.TrafficRouteType,
 		mesh.TrafficTraceType,
-		system.SecretType,
-		system.GlobalSecretType,
+		mesh.ZoneIngressType,
 		system.ConfigType,
+		system.GlobalSecretType,
+		system.SecretType,
 	}
 )
 
diff --git a/pkg/sds/server/v3/server.go b/pkg/sds/server/v3/server.go
index cfa7c9c44..834807eaa 100644
--- a/pkg/sds/server/v3/server.go
+++ b/pkg/sds/server/v3/server.go
@@ -40,7 +40,7 @@ func RegisterSDS(rt core_runtime.Runtime, sdsMetrics *sds_metrics.Metrics) error
 	if err != nil {
 		return err
 	}
-	authCallbacks := xds_auth.NewCallbacks(rt.ResourceManager(), authenticator, xds_auth.DPNotFoundRetry{}) // no need to retry on DP Not Found because we are creating DP in ADS before we initiate SDS
+	authCallbacks := xds_auth.NewCallbacks(rt.ReadOnlyResourceManager(), authenticator, xds_auth.DPNotFoundRetry{}) // no need to retry on DP Not Found because we are creating DP in ADS before we initiate SDS
 
 	reconciler := DataplaneReconciler{
 		resManager:         rt.ResourceManager(),
diff --git a/pkg/xds/auth/callbacks.go b/pkg/xds/auth/callbacks.go
index 7c228553e..9a9232229 100644
--- a/pkg/xds/auth/callbacks.go
+++ b/pkg/xds/auth/callbacks.go
@@ -28,7 +28,7 @@ type DPNotFoundRetry struct {
 	MaxTimes uint
 }
 
-func NewCallbacks(resManager core_manager.ResourceManager, authenticator Authenticator, dpNotFoundRetry DPNotFoundRetry) util_xds.Callbacks {
+func NewCallbacks(resManager core_manager.ReadOnlyResourceManager, authenticator Authenticator, dpNotFoundRetry DPNotFoundRetry) util_xds.Callbacks {
 	if dpNotFoundRetry.Backoff == 0 { // backoff cannot be 0
 		dpNotFoundRetry.Backoff = 1 * time.Millisecond
 	}
@@ -44,7 +44,7 @@ func NewCallbacks(resManager core_manager.ResourceManager, authenticator Authent
 // authCallback checks if the DiscoveryRequest is authorized, ie. if it has a valid Dataplane Token/Service Account Token.
 type authCallbacks struct {
 	util_xds.NoopCallbacks
-	resManager      core_manager.ResourceManager
+	resManager      core_manager.ReadOnlyResourceManager
 	authenticator   Authenticator
 	dpNotFoundRetry DPNotFoundRetry
 
diff --git a/pkg/xds/envoy/listeners/configurers.go b/pkg/xds/envoy/listeners/configurers.go
index 1beb6e05f..e9bfaf9d9 100644
--- a/pkg/xds/envoy/listeners/configurers.go
+++ b/pkg/xds/envoy/listeners/configurers.go
@@ -25,10 +25,11 @@ func Kafka(statsName string) FilterChainBuilderOpt {
 	})
 }
 
-func Tracing(backend *mesh_proto.TracingBackend) FilterChainBuilderOpt {
+func Tracing(backend *mesh_proto.TracingBackend, service string) FilterChainBuilderOpt {
 	return FilterChainBuilderOptFunc(func(config *FilterChainBuilderConfig) {
 		config.AddV3(&v3.TracingConfigurer{
 			Backend: backend,
+			Service: service,
 		})
 	})
 }
diff --git a/pkg/xds/envoy/listeners/v3/tracing_configurer.go b/pkg/xds/envoy/listeners/v3/tracing_configurer.go
index c16b19707..53486464f 100644
--- a/pkg/xds/envoy/listeners/v3/tracing_configurer.go
+++ b/pkg/xds/envoy/listeners/v3/tracing_configurer.go
@@ -18,6 +18,10 @@ import (
 
 type TracingConfigurer struct {
 	Backend *mesh_proto.TracingBackend
+
+	// Opaque string which envoy will assign to tracer collector cluster, on those
+	// which support association of named "service" tags on traces. Consumed by datadog.
+	Service string
 }
 
 var _ FilterChainConfigurer = &TracingConfigurer{}
@@ -41,11 +45,40 @@ func (c *TracingConfigurer) Configure(filterChain *envoy_listener.FilterChain) e
 				return err
 			}
 			hcm.Tracing.Provider = tracing
+		case mesh_proto.TracingDatadogType:
+			tracing, err := datadogConfig(c.Backend.Conf, c.Backend.Name, c.Service)
+			if err != nil {
+				return err
+			}
+			hcm.Tracing.Provider = tracing
 		}
 		return nil
 	})
 }
 
+func datadogConfig(cfgStr *structpb.Struct, backendName string, serviceName string) (*envoy_trace.Tracing_Http, error) {
+	cfg := mesh_proto.DatadogTracingBackendConfig{}
+	if err := proto.ToTyped(cfgStr, &cfg); err != nil {
+		return nil, errors.Wrap(err, "could not convert backend")
+	}
+
+	datadogConfig := envoy_trace.DatadogConfig{
+		CollectorCluster: names.GetTracingClusterName(backendName),
+		ServiceName:      serviceName,
+	}
+	datadogConfigAny, err := proto.MarshalAnyDeterministic(&datadogConfig)
+	if err != nil {
+		return nil, err
+	}
+	tracingConfig := &envoy_trace.Tracing_Http{
+		Name: "envoy.datadog",
+		ConfigType: &envoy_trace.Tracing_Http_TypedConfig{
+			TypedConfig: datadogConfigAny,
+		},
+	}
+	return tracingConfig, nil
+}
+
 func zipkinConfig(cfgStr *structpb.Struct, backendName string) (*envoy_trace.Tracing_Http, error) {
 	cfg := mesh_proto.ZipkinTracingBackendConfig{}
 	if err := proto.ToTyped(cfgStr, &cfg); err != nil {
diff --git a/pkg/xds/generator/inbound_proxy_generator.go b/pkg/xds/generator/inbound_proxy_generator.go
index 1b98ce35b..4154c8699 100644
--- a/pkg/xds/generator/inbound_proxy_generator.go
+++ b/pkg/xds/generator/inbound_proxy_generator.go
@@ -76,7 +76,7 @@ func (g InboundProxyGenerator) Generate(ctx xds_context.Context, proxy *model.Pr
 					Configure(envoy_listeners.HttpConnectionManager(localClusterName, true)).
 					Configure(envoy_listeners.FaultInjection(proxy.Policies.FaultInjections[endpoint])).
 					Configure(envoy_listeners.RateLimit(proxy.Policies.RateLimits[endpoint])).
-					Configure(envoy_listeners.Tracing(proxy.Policies.TracingBackend)).
+					Configure(envoy_listeners.Tracing(proxy.Policies.TracingBackend, service)).
 					Configure(envoy_listeners.HttpInboundRoutes(service, routes))
 			case mesh_core.ProtocolGRPC:
 				filterChainBuilder.
@@ -84,7 +84,7 @@ func (g InboundProxyGenerator) Generate(ctx xds_context.Context, proxy *model.Pr
 					Configure(envoy_listeners.GrpcStats()).
 					Configure(envoy_listeners.FaultInjection(proxy.Policies.FaultInjections[endpoint])).
 					Configure(envoy_listeners.RateLimit(proxy.Policies.RateLimits[endpoint])).
-					Configure(envoy_listeners.Tracing(proxy.Policies.TracingBackend)).
+					Configure(envoy_listeners.Tracing(proxy.Policies.TracingBackend, service)).
 					Configure(envoy_listeners.HttpInboundRoutes(service, routes))
 			case mesh_core.ProtocolKafka:
 				filterChainBuilder.
diff --git a/pkg/xds/generator/outbound_proxy_generator.go b/pkg/xds/generator/outbound_proxy_generator.go
index a7d56b5d8..947307993 100644
--- a/pkg/xds/generator/outbound_proxy_generator.go
+++ b/pkg/xds/generator/outbound_proxy_generator.go
@@ -105,7 +105,7 @@ func (_ OutboundProxyGenerator) generateLDS(proxy *model.Proxy, routes envoy_com
 		case mesh_core.ProtocolGRPC:
 			filterChainBuilder.
 				Configure(envoy_listeners.HttpConnectionManager(serviceName, false)).
-				Configure(envoy_listeners.Tracing(proxy.Policies.TracingBackend)).
+				Configure(envoy_listeners.Tracing(proxy.Policies.TracingBackend, sourceService)).
 				Configure(envoy_listeners.HttpAccessLog(meshName, envoy_common.TrafficDirectionOutbound, sourceService, serviceName, proxy.Policies.Logs[serviceName], proxy)).
 				Configure(envoy_listeners.HttpOutboundRoute(serviceName, routes, proxy.Dataplane.Spec.TagSet())).
 				Configure(envoy_listeners.Retry(retryPolicy, protocol)).
@@ -113,7 +113,7 @@ func (_ OutboundProxyGenerator) generateLDS(proxy *model.Proxy, routes envoy_com
 		case mesh_core.ProtocolHTTP, mesh_core.ProtocolHTTP2:
 			filterChainBuilder.
 				Configure(envoy_listeners.HttpConnectionManager(serviceName, false)).
-				Configure(envoy_listeners.Tracing(proxy.Policies.TracingBackend)).
+				Configure(envoy_listeners.Tracing(proxy.Policies.TracingBackend, sourceService)).
 				Configure(envoy_listeners.HttpAccessLog(
 					meshName,
 					envoy_common.TrafficDirectionOutbound,
diff --git a/pkg/xds/generator/tracing_proxy_generator.go b/pkg/xds/generator/tracing_proxy_generator.go
index 6225d13c2..fdc5e941c 100644
--- a/pkg/xds/generator/tracing_proxy_generator.go
+++ b/pkg/xds/generator/tracing_proxy_generator.go
@@ -35,7 +35,14 @@ func (t TracingProxyGenerator) Generate(_ xds_context.Context, proxy *core_xds.P
 			return nil, errors.Wrap(err, "could not generate zipkin cluster")
 		}
 		resources.Add(res)
+	case mesh_proto.TracingDatadogType:
+		res, err := t.datadogCluster(proxy.Policies.TracingBackend, proxy.APIVersion)
+		if err != nil {
+			return nil, errors.Wrap(err, "could not generate datadog cluster")
+		}
+		resources.Add(res)
 	}
+
 	return resources, nil
 }
 
@@ -67,3 +74,28 @@ func (t TracingProxyGenerator) zipkinCluster(backend *mesh_proto.TracingBackend,
 		Resource: cluster,
 	}, nil
 }
+
+func (t TracingProxyGenerator) datadogCluster(backend *mesh_proto.TracingBackend, apiVersion envoy.APIVersion) (*core_xds.Resource, error) {
+	cfg := mesh_proto.DatadogTracingBackendConfig{}
+	if err := proto.ToTyped(backend.Conf, &cfg); err != nil {
+		return nil, errors.Wrap(err, "could not convert backend")
+	}
+
+	if cfg.Port > 0xFFFF || cfg.Port < 1 {
+		return nil, errors.Errorf("invalid Datadog port number %d. Must be in range 1-65535", cfg.Port)
+	}
+
+	clusterName := names.GetTracingClusterName(backend.Name)
+	cluster, err := clusters.NewClusterBuilder(apiVersion).
+		Configure(clusters.DNSCluster(clusterName, cfg.Address, cfg.Port)).
+		Build()
+	if err != nil {
+		return nil, err
+	}
+
+	return &core_xds.Resource{
+		Name:     clusterName,
+		Origin:   OriginTracing,
+		Resource: cluster,
+	}, nil
+}
diff --git a/pkg/xds/server/callbacks/dataplane_lifecycle.go b/pkg/xds/server/callbacks/dataplane_lifecycle.go
index e1c253d89..8d06e1baf 100644
--- a/pkg/xds/server/callbacks/dataplane_lifecycle.go
+++ b/pkg/xds/server/callbacks/dataplane_lifecycle.go
@@ -105,22 +105,24 @@ func (d *DataplaneLifecycle) OnStreamRequest(streamID int64, request util_xds.Di
 	md := xds.DataplaneMetadataFromXdsMetadata(request.Metadata())
 
 	if md.GetProxyType() == mesh_proto.DataplaneProxyType && md.GetDataplaneResource() != nil {
-		lifecycleLog.Info("registering dataplane", "dataplane", md.GetDataplaneResource(), "streamID", streamID, "nodeID", request.NodeId())
-		if err := d.registerDataplane(md.GetDataplaneResource()); err != nil {
+		dp := md.GetDataplaneResource()
+		lifecycleLog.Info("registering dataplane", "dataplane", dp, "streamID", streamID, "nodeID", request.NodeId())
+		if err := d.registerDataplane(dp); err != nil {
 			return errors.Wrap(err, "could not register dataplane passed in kuma-dp run")
 		}
-		key := model.MetaToResourceKey(md.GetDataplaneResource().GetMeta())
+		key := model.MetaToResourceKey(dp.GetMeta())
 		d.createdDpForStream[streamID] = &key
 		d.proxyTypeForStream[streamID] = mesh_proto.DataplaneProxyType
 		return nil
 	}
 
-	if md.GetProxyType() == mesh_proto.IngressProxyType && md.ZoneIngressResource != nil {
-		lifecycleLog.Info("registering zone ingress", "zoneIngress", md.ZoneIngressResource, "streamID", streamID, "nodeID", request.NodeId())
-		if err := d.registerZoneIngress(md.ZoneIngressResource); err != nil {
+	if md.GetProxyType() == mesh_proto.IngressProxyType && md.GetZoneIngressResource() != nil {
+		zi := md.GetZoneIngressResource()
+		lifecycleLog.Info("registering zone ingress", "zoneIngress", zi, "streamID", streamID, "nodeID", request.NodeId())
+		if err := d.registerZoneIngress(zi); err != nil {
 			return errors.Wrap(err, "could not register zone ingress passed in kuma-dp run")
 		}
-		key := model.MetaToResourceKey(md.ZoneIngressResource.GetMeta())
+		key := model.MetaToResourceKey(zi.GetMeta())
 		d.createdDpForStream[streamID] = &key
 		d.proxyTypeForStream[streamID] = mesh_proto.IngressProxyType
 		return nil
diff --git a/pkg/xds/server/v3/components.go b/pkg/xds/server/v3/components.go
index 41cb7f147..43e120565 100644
--- a/pkg/xds/server/v3/components.go
+++ b/pkg/xds/server/v3/components.go
@@ -38,7 +38,7 @@ func RegisterXDS(
 	if err != nil {
 		return err
 	}
-	authCallbacks := auth.NewCallbacks(rt.ResourceManager(), authenticator, auth.DPNotFoundRetry{}) // no need to retry on DP Not Found because we are creating DP in DataplaneLifecycle callback
+	authCallbacks := auth.NewCallbacks(rt.ReadOnlyResourceManager(), authenticator, auth.DPNotFoundRetry{}) // no need to retry on DP Not Found because we are creating DP in DataplaneLifecycle callback
 
 	metadataTracker := xds_callbacks.NewDataplaneMetadataTracker()
 	connectionInfoTracker := xds_callbacks.NewConnectionInfoTracker()


Test patch:
diff --git a/pkg/api-server/config_ws_test.go b/pkg/api-server/config_ws_test.go
index 952817bc2..1a915725a 100644
--- a/pkg/api-server/config_ws_test.go
+++ b/pkg/api-server/config_ws_test.go
@@ -157,14 +157,15 @@ var _ = Describe("Config WS", func() {
 				"refreshInterval": "1s",
 				"tlsCertFile": "",
 				"tlsKeyFile": "",
-				"zoneInsightFlushInterval": "10s"
-			  },
-			  "pollTimeout": "500ms"
+				"zoneInsightFlushInterval": "10s",
+				"maxMsgSize": 10485760
+			  }
 			},
 			"zone": {
 			  "kds": {
 				"refreshInterval": "1s",
-				"rootCaFile": ""
+				"rootCaFile": "",
+				"maxMsgSize": 10485760
 			  }
 			}
 		  },
diff --git a/pkg/config/loader_test.go b/pkg/config/loader_test.go
index f6224eef7..33646abb5 100644
--- a/pkg/config/loader_test.go
+++ b/pkg/config/loader_test.go
@@ -192,16 +192,17 @@ var _ = Describe("Config loader", func() {
 			Expect(cfg.Mode).To(Equal(config_core.Zone))
 			Expect(cfg.Multizone.Zone.Name).To(Equal("zone-1"))
 
-			Expect(cfg.Multizone.Global.PollTimeout).To(Equal(750 * time.Millisecond))
 			Expect(cfg.Multizone.Global.KDS.GrpcPort).To(Equal(uint32(1234)))
 			Expect(cfg.Multizone.Global.KDS.RefreshInterval).To(Equal(time.Second * 2))
 			Expect(cfg.Multizone.Global.KDS.ZoneInsightFlushInterval).To(Equal(time.Second * 5))
 			Expect(cfg.Multizone.Global.KDS.TlsCertFile).To(Equal("/cert"))
 			Expect(cfg.Multizone.Global.KDS.TlsKeyFile).To(Equal("/key"))
+			Expect(cfg.Multizone.Global.KDS.MaxMsgSize).To(Equal(uint32(1)))
 			Expect(cfg.Multizone.Zone.GlobalAddress).To(Equal("grpc://1.1.1.1:5685"))
 			Expect(cfg.Multizone.Zone.Name).To(Equal("zone-1"))
 			Expect(cfg.Multizone.Zone.KDS.RootCAFile).To(Equal("/rootCa"))
 			Expect(cfg.Multizone.Zone.KDS.RefreshInterval).To(Equal(9 * time.Second))
+			Expect(cfg.Multizone.Zone.KDS.MaxMsgSize).To(Equal(uint32(2)))
 
 			Expect(cfg.Defaults.SkipMeshCreation).To(BeTrue())
 
@@ -374,19 +375,20 @@ guiServer:
 mode: zone
 multizone:
   global:
-    pollTimeout: 750ms
     kds:
       grpcPort: 1234
       refreshInterval: 2s
       zoneInsightFlushInterval: 5s
       tlsCertFile: /cert
       tlsKeyFile: /key
+      maxMsgSize: 1
   zone:
     globalAddress: "grpc://1.1.1.1:5685"
     name: "zone-1"
     kds:
       refreshInterval: 9s
       rootCaFile: /rootCa
+      maxMsgSize: 2
 dnsServer:
   domain: test-domain
   port: 15653
@@ -525,15 +527,16 @@ sdsServer:
 				"KUMA_DNS_SERVER_PORT":                                                                     "15653",
 				"KUMA_DNS_SERVER_CIDR":                                                                     "127.1.0.0/16",
 				"KUMA_MODE":                                                                                "zone",
-				"KUMA_MULTIZONE_GLOBAL_POLL_TIMEOUT":                                                       "750ms",
 				"KUMA_MULTIZONE_GLOBAL_KDS_GRPC_PORT":                                                      "1234",
 				"KUMA_MULTIZONE_GLOBAL_KDS_REFRESH_INTERVAL":                                               "2s",
 				"KUMA_MULTIZONE_GLOBAL_KDS_TLS_CERT_FILE":                                                  "/cert",
 				"KUMA_MULTIZONE_GLOBAL_KDS_TLS_KEY_FILE":                                                   "/key",
+				"KUMA_MULTIZONE_GLOBAL_KDS_MAX_MSG_SIZE":                                                   "1",
 				"KUMA_MULTIZONE_ZONE_GLOBAL_ADDRESS":                                                       "grpc://1.1.1.1:5685",
 				"KUMA_MULTIZONE_ZONE_NAME":                                                                 "zone-1",
 				"KUMA_MULTIZONE_ZONE_KDS_ROOT_CA_FILE":                                                     "/rootCa",
 				"KUMA_MULTIZONE_ZONE_KDS_REFRESH_INTERVAL":                                                 "9s",
+				"KUMA_MULTIZONE_ZONE_KDS_MAX_MSG_SIZE":                                                     "2",
 				"KUMA_MULTIZONE_GLOBAL_KDS_ZONE_INSIGHT_FLUSH_INTERVAL":                                    "5s",
 				"KUMA_DEFAULTS_SKIP_MESH_CREATION":                                                         "true",
 				"KUMA_DIAGNOSTICS_SERVER_PORT":                                                             "5003",
diff --git a/pkg/core/resources/apis/mesh/mesh_validator_test.go b/pkg/core/resources/apis/mesh/mesh_validator_test.go
index c76a6c562..3163a9f60 100644
--- a/pkg/core/resources/apis/mesh/mesh_validator_test.go
+++ b/pkg/core/resources/apis/mesh/mesh_validator_test.go
@@ -404,7 +404,7 @@ var _ = Describe("Mesh", func() {
                 - field: logging.backends[0].type
                   message: 'unknown backend type. Available backends: "tcp", "file"'
                 - field: tracing.backends[0].type
-                  message: 'unknown backend type. Available backends: "zipkin"'
+                  message: 'unknown backend type. Available backends: "zipkin", "datadog"'
                 - field: metrics.backends[0].type
                   message: 'unknown backend type. Available backends: "prometheus"'`,
 			}),
diff --git a/pkg/kds/server/server_test.go b/pkg/kds/server/server_test.go
index 1ab266083..5dd3f342e 100644
--- a/pkg/kds/server/server_test.go
+++ b/pkg/kds/server/server_test.go
@@ -64,32 +64,38 @@ var _ = Describe("KDS Server", func() {
 		// Do not forget to update this test after updating 'kds.SupportedTypes
 		Expect([]proto.Message{
 			kds_samples.CircuitBreaker,
-			kds_samples.Ingress, // mesh.DataplaneType
-			kds_samples.ZoneIngress,
-			kds_samples.ZoneIngressInsight,
 			kds_samples.DataplaneInsight,
 			kds_samples.ExternalService,
 			kds_samples.FaultInjection,
+			kds_samples.GlobalSecret,
 			kds_samples.HealthCheck,
+			kds_samples.Ingress, // mesh.DataplaneType
 			kds_samples.Mesh1,
 			kds_samples.ProxyTemplate,
 			kds_samples.RateLimit,
 			kds_samples.Retry,
+			kds_samples.Secret,
 			kds_samples.Timeout,
 			kds_samples.TrafficLog,
 			kds_samples.TrafficPermission,
 			kds_samples.TrafficRoute,
 			kds_samples.TrafficTrace,
-			kds_samples.Secret,
-			kds_samples.GlobalSecret,
+			kds_samples.ZoneIngress,
+			kds_samples.ZoneIngressInsight,
 			kds_samples.Config,
 		}).
 			To(HaveLen(len(kds.SupportedTypes)))
 
 		vrf := kds_verifier.New().
+			// NOTE: The resources all have to be created before any DiscoveryRequests are made.
+			// This is because in the initial state, there are no snapshots. The first DiscoveryRequest
+			// won't get a response until the first snapshot is generated after the reconciliation
+			// period expires. Then all the subsequent DiscoveryRequests will be served from the
+			// same snapshot, so resources that aren't already present won't be reported.
+
 			Exec(kds_verifier.Create(ctx, &mesh.CircuitBreakerResource{Spec: kds_samples.CircuitBreaker}, store.CreateByKey("cb-1", "mesh-1"))).
-			Exec(kds_verifier.Create(ctx, &mesh.DataplaneResource{Spec: kds_samples.Ingress}, store.CreateByKey("Ingress-1", "mesh-1"))).
 			Exec(kds_verifier.Create(ctx, &mesh.DataplaneInsightResource{Spec: kds_samples.DataplaneInsight}, store.CreateByKey("insight-1", "mesh-1"))).
+			Exec(kds_verifier.Create(ctx, &mesh.DataplaneResource{Spec: kds_samples.Ingress}, store.CreateByKey("Ingress-1", "mesh-1"))).
 			Exec(kds_verifier.Create(ctx, &mesh.ExternalServiceResource{Spec: kds_samples.ExternalService}, store.CreateByKey("es-1", "mesh-1"))).
 			Exec(kds_verifier.Create(ctx, &mesh.FaultInjectionResource{Spec: kds_samples.FaultInjection}, store.CreateByKey("fi-1", "mesh-1"))).
 			Exec(kds_verifier.Create(ctx, &mesh.HealthCheckResource{Spec: kds_samples.HealthCheck}, store.CreateByKey("hc-1", "mesh-1"))).
@@ -272,10 +278,7 @@ var _ = Describe("KDS Server", func() {
 					return err
 				}
 				meshRes.Spec = kds_samples.Mesh2
-				if err := tc.Store().Update(ctx, meshRes); err != nil {
-					return err
-				}
-				return nil
+				return tc.Store().Update(ctx, meshRes)
 			}).
 			Exec(kds_verifier.WaitResponse(defaultTimeout, func(rs []model.Resource) {
 				Expect(rs).To(HaveLen(1))
diff --git a/pkg/xds/envoy/listeners/v3/tracing_configurer_test.go b/pkg/xds/envoy/listeners/v3/tracing_configurer_test.go
index 6fb913b73..7c4d9a25b 100644
--- a/pkg/xds/envoy/listeners/v3/tracing_configurer_test.go
+++ b/pkg/xds/envoy/listeners/v3/tracing_configurer_test.go
@@ -29,7 +29,7 @@ var _ = Describe("TracingConfigurer", func() {
 				Configure(InboundListener("inbound:192.168.0.1:8080", "192.168.0.1", 8080, xds.SocketAddressProtocolTCP)).
 				Configure(FilterChain(NewFilterChainBuilder(envoy.APIV3).
 					Configure(HttpConnectionManager("localhost:8080", false)).
-					Configure(Tracing(given.backend)))).
+					Configure(Tracing(given.backend, "service")))).
 				Build()
 			// then
 			Expect(err).ToNot(HaveOccurred())
@@ -40,7 +40,7 @@ var _ = Describe("TracingConfigurer", func() {
 			// and
 			Expect(actual).To(MatchYAML(given.expected))
 		},
-		Entry("backend specified with sampling", testCase{
+		Entry("zipkin backend specified with sampling", testCase{
 			backend: &mesh_proto.TracingBackend{
 				Name:     "zipkin",
 				Sampling: &wrappers.DoubleValue{Value: 30.5},
@@ -76,7 +76,7 @@ var _ = Describe("TracingConfigurer", func() {
             name: inbound:192.168.0.1:8080
             trafficDirection: INBOUND`,
 		}),
-		Entry("backend specified without sampling", testCase{
+		Entry("zipkin backend specified without sampling", testCase{
 			backend: &mesh_proto.TracingBackend{
 				Name: "zipkin",
 				Type: mesh_proto.TracingZipkinType,
@@ -109,6 +109,39 @@ var _ = Describe("TracingConfigurer", func() {
             name: inbound:192.168.0.1:8080
             trafficDirection: INBOUND`,
 		}),
+		Entry("datadog backend specified", testCase{
+			backend: &mesh_proto.TracingBackend{
+				Name: "datadog",
+				Type: mesh_proto.TracingDatadogType,
+				Conf: util_proto.MustToStruct(&mesh_proto.DatadogTracingBackendConfig{
+					Address: "1.1.1.1",
+					Port:    1111,
+				}),
+			},
+			expected: `
+        address:
+          socketAddress:
+            address: 192.168.0.1
+            portValue: 8080
+        filterChains:
+        - filters:
+          - name: envoy.filters.network.http_connection_manager
+            typedConfig:
+              '@type': type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
+              httpFilters:
+              - name: envoy.filters.http.router
+              statPrefix: localhost_8080
+              tracing:
+                provider:
+                  name: envoy.datadog
+                  typedConfig:
+                    '@type': type.googleapis.com/envoy.config.trace.v3.DatadogConfig
+                    collectorCluster: tracing:datadog
+                    serviceName: service
+        name: inbound:192.168.0.1:8080
+        trafficDirection: INBOUND`,
+		}),
+
 		Entry("no backend specified", testCase{
 			backend: nil,
 			expected: `