Repository: kumahq/kuma
Pull request #1397 (2021-01-08 10:16:55)

Update mesh insights with DP versions (bp #1372)
This is an automated backport of pull request #1372 done by Mergify
---


<details>
<summary>Mergify commands and options</summary>

<br />

More conditions and actions can be found in the [documentation](https://docs.mergify.io/).

You can also trigger Mergify actions by commenting on this pull request:

- `@Mergifyio refresh` will re-evaluate the rules
- `@Mergifyio rebase` will rebase this PR on its base branch
- `@Mergifyio update` will merge the base branch into this PR
- `@Mergifyio backport <destination>` will backport this PR on `<destination>` branch

Additionally, on Mergify [dashboard](https://dashboard.mergify.io/) you can:

- look at your merge queues
- generate the Mergify configuration with the config editor.

Finally, you can contact us on https://mergify.io/
</details>



Patch:
diff --git a/api/mesh/v1alpha1/mesh_insight.pb.go b/api/mesh/v1alpha1/mesh_insight.pb.go
index 088a6503d..7cc13c3cd 100644
--- a/api/mesh/v1alpha1/mesh_insight.pb.go
+++ b/api/mesh/v1alpha1/mesh_insight.pb.go
@@ -36,6 +36,7 @@ type MeshInsight struct {
 	LastSync   *timestamp.Timestamp               `protobuf:"bytes,1,opt,name=last_sync,json=lastSync,proto3" json:"last_sync,omitempty"`
 	Dataplanes *MeshInsight_DataplaneStat         `protobuf:"bytes,2,opt,name=dataplanes,proto3" json:"dataplanes,omitempty"`
 	Policies   map[string]*MeshInsight_PolicyStat `protobuf:"bytes,3,rep,name=policies,proto3" json:"policies,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
+	DpVersions *MeshInsight_DpVersions            `protobuf:"bytes,4,opt,name=dpVersions,proto3" json:"dpVersions,omitempty"`
 }
 
 func (x *MeshInsight) Reset() {
@@ -91,6 +92,13 @@ func (x *MeshInsight) GetPolicies() map[string]*MeshInsight_PolicyStat {
 	return nil
 }
 
+func (x *MeshInsight) GetDpVersions() *MeshInsight_DpVersions {
+	if x != nil {
+		return x.DpVersions
+	}
+	return nil
+}
+
 // DataplaneStat defines statistic specifically for Dataplane
 type MeshInsight_DataplaneStat struct {
 	state         protoimpl.MessageState
@@ -203,6 +211,64 @@ func (x *MeshInsight_PolicyStat) GetTotal() uint32 {
 	return 0
 }
 
+// DpVersions defines statistics grouped by dataplane versions
+type MeshInsight_DpVersions struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	// Dataplane stats grouped by KumaDP version
+	KumaDp map[string]*MeshInsight_DataplaneStat `protobuf:"bytes,1,rep,name=kumaDp,proto3" json:"kumaDp,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
+	// Dataplan stats grouped by Envoy version
+	Envoy map[string]*MeshInsight_DataplaneStat `protobuf:"bytes,2,rep,name=envoy,proto3" json:"envoy,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
+}
+
+func (x *MeshInsight_DpVersions) Reset() {
+	*x = MeshInsight_DpVersions{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_mesh_v1alpha1_mesh_insight_proto_msgTypes[4]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *MeshInsight_DpVersions) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*MeshInsight_DpVersions) ProtoMessage() {}
+
+func (x *MeshInsight_DpVersions) ProtoReflect() protoreflect.Message {
+	mi := &file_mesh_v1alpha1_mesh_insight_proto_msgTypes[4]
+	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 MeshInsight_DpVersions.ProtoReflect.Descriptor instead.
+func (*MeshInsight_DpVersions) Descriptor() ([]byte, []int) {
+	return file_mesh_v1alpha1_mesh_insight_proto_rawDescGZIP(), []int{0, 3}
+}
+
+func (x *MeshInsight_DpVersions) GetKumaDp() map[string]*MeshInsight_DataplaneStat {
+	if x != nil {
+		return x.KumaDp
+	}
+	return nil
+}
+
+func (x *MeshInsight_DpVersions) GetEnvoy() map[string]*MeshInsight_DataplaneStat {
+	if x != nil {
+		return x.Envoy
+	}
+	return nil
+}
+
 var File_mesh_v1alpha1_mesh_insight_proto protoreflect.FileDescriptor
 
 var file_mesh_v1alpha1_mesh_insight_proto_rawDesc = []byte{
@@ -211,7 +277,7 @@ var file_mesh_v1alpha1_mesh_insight_proto_rawDesc = []byte{
 	0x74, 0x6f, 0x12, 0x12, 0x6b, 0x75, 0x6d, 0x61, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31,
 	0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70,
 	0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d,
-	0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xc6, 0x03, 0x0a, 0x0b, 0x4d, 0x65, 0x73, 0x68,
+	0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x91, 0x07, 0x0a, 0x0b, 0x4d, 0x65, 0x73, 0x68,
 	0x49, 0x6e, 0x73, 0x69, 0x67, 0x68, 0x74, 0x12, 0x37, 0x0a, 0x09, 0x6c, 0x61, 0x73, 0x74, 0x5f,
 	0x73, 0x79, 0x6e, 0x63, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f,
 	0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d,
@@ -225,25 +291,53 @@ var file_mesh_v1alpha1_mesh_insight_proto_rawDesc = []byte{
 	0x0b, 0x32, 0x2d, 0x2e, 0x6b, 0x75, 0x6d, 0x61, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31,
 	0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x49, 0x6e, 0x73, 0x69, 0x67,
 	0x68, 0x74, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79,
-	0x52, 0x08, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x1a, 0x57, 0x0a, 0x0d, 0x44, 0x61,
-	0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x53, 0x74, 0x61, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x74,
-	0x6f, 0x74, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61,
-	0x6c, 0x12, 0x16, 0x0a, 0x06, 0x6f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
-	0x0d, 0x52, 0x06, 0x6f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6f, 0x66, 0x66,
-	0x6c, 0x69, 0x6e, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x6f, 0x66, 0x66, 0x6c,
-	0x69, 0x6e, 0x65, 0x1a, 0x22, 0x0a, 0x0a, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x53, 0x74, 0x61,
-	0x74, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d,
-	0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x1a, 0x67, 0x0a, 0x0d, 0x50, 0x6f, 0x6c, 0x69, 0x63,
-	0x69, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18,
-	0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x40, 0x0a, 0x05, 0x76, 0x61,
-	0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x6b, 0x75, 0x6d, 0x61,
-	0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4d,
-	0x65, 0x73, 0x68, 0x49, 0x6e, 0x73, 0x69, 0x67, 0x68, 0x74, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63,
-	0x79, 0x53, 0x74, 0x61, 0x74, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01,
-	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,
+	0x52, 0x08, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x12, 0x4a, 0x0a, 0x0a, 0x64, 0x70,
+	0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a,
+	0x2e, 0x6b, 0x75, 0x6d, 0x61, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70,
+	0x68, 0x61, 0x31, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x49, 0x6e, 0x73, 0x69, 0x67, 0x68, 0x74, 0x2e,
+	0x44, 0x70, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x0a, 0x64, 0x70, 0x56, 0x65,
+	0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x57, 0x0a, 0x0d, 0x44, 0x61, 0x74, 0x61, 0x70, 0x6c,
+	0x61, 0x6e, 0x65, 0x53, 0x74, 0x61, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c,
+	0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x12, 0x16, 0x0a,
+	0x06, 0x6f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x6f,
+	0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6f, 0x66, 0x66, 0x6c, 0x69, 0x6e, 0x65,
+	0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x6f, 0x66, 0x66, 0x6c, 0x69, 0x6e, 0x65, 0x1a,
+	0x22, 0x0a, 0x0a, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x53, 0x74, 0x61, 0x74, 0x12, 0x14, 0x0a,
+	0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x74, 0x6f,
+	0x74, 0x61, 0x6c, 0x1a, 0x67, 0x0a, 0x0d, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x45,
+	0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28,
+	0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x40, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18,
+	0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x6b, 0x75, 0x6d, 0x61, 0x2e, 0x6d, 0x65, 0x73,
+	0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x49,
+	0x6e, 0x73, 0x69, 0x67, 0x68, 0x74, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x53, 0x74, 0x61,
+	0x74, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0xfc, 0x02, 0x0a,
+	0x0a, 0x44, 0x70, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x4e, 0x0a, 0x06, 0x6b,
+	0x75, 0x6d, 0x61, 0x44, 0x70, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x6b, 0x75,
+	0x6d, 0x61, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31,
+	0x2e, 0x4d, 0x65, 0x73, 0x68, 0x49, 0x6e, 0x73, 0x69, 0x67, 0x68, 0x74, 0x2e, 0x44, 0x70, 0x56,
+	0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x4b, 0x75, 0x6d, 0x61, 0x44, 0x70, 0x45, 0x6e,
+	0x74, 0x72, 0x79, 0x52, 0x06, 0x6b, 0x75, 0x6d, 0x61, 0x44, 0x70, 0x12, 0x4b, 0x0a, 0x05, 0x65,
+	0x6e, 0x76, 0x6f, 0x79, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x6b, 0x75, 0x6d,
+	0x61, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e,
+	0x4d, 0x65, 0x73, 0x68, 0x49, 0x6e, 0x73, 0x69, 0x67, 0x68, 0x74, 0x2e, 0x44, 0x70, 0x56, 0x65,
+	0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x45, 0x6e, 0x76, 0x6f, 0x79, 0x45, 0x6e, 0x74, 0x72,
+	0x79, 0x52, 0x05, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x1a, 0x68, 0x0a, 0x0b, 0x4b, 0x75, 0x6d, 0x61,
+	0x44, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01,
+	0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x43, 0x0a, 0x05, 0x76, 0x61, 0x6c,
+	0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x6b, 0x75, 0x6d, 0x61, 0x2e,
+	0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4d, 0x65,
+	0x73, 0x68, 0x49, 0x6e, 0x73, 0x69, 0x67, 0x68, 0x74, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x70, 0x6c,
+	0x61, 0x6e, 0x65, 0x53, 0x74, 0x61, 0x74, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02,
+	0x38, 0x01, 0x1a, 0x67, 0x0a, 0x0a, 0x45, 0x6e, 0x76, 0x6f, 0x79, 0x45, 0x6e, 0x74, 0x72, 0x79,
+	0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b,
+	0x65, 0x79, 0x12, 0x43, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
+	0x0b, 0x32, 0x2d, 0x2e, 0x6b, 0x75, 0x6d, 0x61, 0x2e, 0x6d, 0x65, 0x73, 0x68, 0x2e, 0x76, 0x31,
+	0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x49, 0x6e, 0x73, 0x69, 0x67,
+	0x68, 0x74, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x53, 0x74, 0x61, 0x74,
+	0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 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 (
@@ -258,24 +352,32 @@ func file_mesh_v1alpha1_mesh_insight_proto_rawDescGZIP() []byte {
 	return file_mesh_v1alpha1_mesh_insight_proto_rawDescData
 }
 
-var file_mesh_v1alpha1_mesh_insight_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
+var file_mesh_v1alpha1_mesh_insight_proto_msgTypes = make([]protoimpl.MessageInfo, 7)
 var file_mesh_v1alpha1_mesh_insight_proto_goTypes = []interface{}{
 	(*MeshInsight)(nil),               // 0: kuma.mesh.v1alpha1.MeshInsight
 	(*MeshInsight_DataplaneStat)(nil), // 1: kuma.mesh.v1alpha1.MeshInsight.DataplaneStat
 	(*MeshInsight_PolicyStat)(nil),    // 2: kuma.mesh.v1alpha1.MeshInsight.PolicyStat
 	nil,                               // 3: kuma.mesh.v1alpha1.MeshInsight.PoliciesEntry
-	(*timestamp.Timestamp)(nil),       // 4: google.protobuf.Timestamp
+	(*MeshInsight_DpVersions)(nil),    // 4: kuma.mesh.v1alpha1.MeshInsight.DpVersions
+	nil,                               // 5: kuma.mesh.v1alpha1.MeshInsight.DpVersions.KumaDpEntry
+	nil,                               // 6: kuma.mesh.v1alpha1.MeshInsight.DpVersions.EnvoyEntry
+	(*timestamp.Timestamp)(nil),       // 7: google.protobuf.Timestamp
 }
 var file_mesh_v1alpha1_mesh_insight_proto_depIdxs = []int32{
-	4, // 0: kuma.mesh.v1alpha1.MeshInsight.last_sync:type_name -> google.protobuf.Timestamp
+	7, // 0: kuma.mesh.v1alpha1.MeshInsight.last_sync:type_name -> google.protobuf.Timestamp
 	1, // 1: kuma.mesh.v1alpha1.MeshInsight.dataplanes:type_name -> kuma.mesh.v1alpha1.MeshInsight.DataplaneStat
 	3, // 2: kuma.mesh.v1alpha1.MeshInsight.policies:type_name -> kuma.mesh.v1alpha1.MeshInsight.PoliciesEntry
-	2, // 3: kuma.mesh.v1alpha1.MeshInsight.PoliciesEntry.value:type_name -> kuma.mesh.v1alpha1.MeshInsight.PolicyStat
-	4, // [4:4] is the sub-list for method output_type
-	4, // [4:4] is the sub-list for method input_type
-	4, // [4:4] is the sub-list for extension type_name
-	4, // [4:4] is the sub-list for extension extendee
-	0, // [0:4] is the sub-list for field type_name
+	4, // 3: kuma.mesh.v1alpha1.MeshInsight.dpVersions:type_name -> kuma.mesh.v1alpha1.MeshInsight.DpVersions
+	2, // 4: kuma.mesh.v1alpha1.MeshInsight.PoliciesEntry.value:type_name -> kuma.mesh.v1alpha1.MeshInsight.PolicyStat
+	5, // 5: kuma.mesh.v1alpha1.MeshInsight.DpVersions.kumaDp:type_name -> kuma.mesh.v1alpha1.MeshInsight.DpVersions.KumaDpEntry
+	6, // 6: kuma.mesh.v1alpha1.MeshInsight.DpVersions.envoy:type_name -> kuma.mesh.v1alpha1.MeshInsight.DpVersions.EnvoyEntry
+	1, // 7: kuma.mesh.v1alpha1.MeshInsight.DpVersions.KumaDpEntry.value:type_name -> kuma.mesh.v1alpha1.MeshInsight.DataplaneStat
+	1, // 8: kuma.mesh.v1alpha1.MeshInsight.DpVersions.EnvoyEntry.value:type_name -> kuma.mesh.v1alpha1.MeshInsight.DataplaneStat
+	9, // [9:9] is the sub-list for method output_type
+	9, // [9:9] is the sub-list for method input_type
+	9, // [9:9] is the sub-list for extension type_name
+	9, // [9:9] is the sub-list for extension extendee
+	0, // [0:9] is the sub-list for field type_name
 }
 
 func init() { file_mesh_v1alpha1_mesh_insight_proto_init() }
@@ -320,6 +422,18 @@ func file_mesh_v1alpha1_mesh_insight_proto_init() {
 				return nil
 			}
 		}
+		file_mesh_v1alpha1_mesh_insight_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*MeshInsight_DpVersions); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
 	}
 	type x struct{}
 	out := protoimpl.TypeBuilder{
@@ -327,7 +441,7 @@ func file_mesh_v1alpha1_mesh_insight_proto_init() {
 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
 			RawDescriptor: file_mesh_v1alpha1_mesh_insight_proto_rawDesc,
 			NumEnums:      0,
-			NumMessages:   4,
+			NumMessages:   7,
 			NumExtensions: 0,
 			NumServices:   0,
 		},
diff --git a/api/mesh/v1alpha1/mesh_insight.proto b/api/mesh/v1alpha1/mesh_insight.proto
index d87dc80ba..5ab73c564 100644
--- a/api/mesh/v1alpha1/mesh_insight.proto
+++ b/api/mesh/v1alpha1/mesh_insight.proto
@@ -23,4 +23,15 @@ message MeshInsight {
   // PolicyStat defines statistic for all policies in general
   message PolicyStat { uint32 total = 1; }
   map<string, PolicyStat> policies = 3;
+
+  // DpVersions defines statistics grouped by dataplane versions
+  message DpVersions {
+
+    // Dataplane stats grouped by KumaDP version
+    map<string, DataplaneStat> kumaDp = 1;
+
+    // Dataplan stats grouped by Envoy version
+    map<string, DataplaneStat> envoy = 2;
+  }
+  DpVersions dpVersions = 4;
 }
diff --git a/pkg/insights/resyncer.go b/pkg/insights/resyncer.go
index 03dc33ac8..8683293b9 100644
--- a/pkg/insights/resyncer.go
+++ b/pkg/insights/resyncer.go
@@ -256,6 +256,10 @@ func (r *resyncer) createOrUpdateMeshInsight(mesh string) error {
 	insight := &mesh_proto.MeshInsight{
 		Dataplanes: &mesh_proto.MeshInsight_DataplaneStat{},
 		Policies:   map[string]*mesh_proto.MeshInsight_PolicyStat{},
+		DpVersions: &mesh_proto.MeshInsight_DpVersions{
+			KumaDp: map[string]*mesh_proto.MeshInsight_DataplaneStat{},
+			Envoy:  map[string]*mesh_proto.MeshInsight_DataplaneStat{},
+		},
 	}
 	for _, resType := range registry.Global().ListTypes() {
 		if !meshScoped(resType) {
@@ -269,13 +273,25 @@ func (r *resyncer) createOrUpdateMeshInsight(mesh string) error {
 			return err
 		}
 		switch resType {
-		case core_mesh.DataplaneType:
-			insight.Dataplanes.Total = uint32(len(list.GetItems()))
 		case core_mesh.DataplaneInsightType:
 			for _, dpInsight := range list.(*core_mesh.DataplaneInsightResourceList).Items {
+				dpSubscription, _ := dpInsight.Spec.GetLatestSubscription()
+				kumaDpVersion := getOrDefault(dpSubscription.GetVersion().GetKumaDp().GetVersion())
+				envoyVersion := getOrDefault(dpSubscription.GetVersion().GetEnvoy().GetVersion())
+				ensureVersionExists(kumaDpVersion, insight.DpVersions.KumaDp)
+				ensureVersionExists(envoyVersion, insight.DpVersions.Envoy)
 				if dpInsight.Spec.IsOnline() {
 					insight.Dataplanes.Online++
+					insight.DpVersions.KumaDp[kumaDpVersion].Online++
+					insight.DpVersions.Envoy[envoyVersion].Online++
+				} else {
+					insight.Dataplanes.Offline++
+					insight.DpVersions.KumaDp[kumaDpVersion].Offline++
+					insight.DpVersions.Envoy[envoyVersion].Offline++
 				}
+				insight.Dataplanes.Total = insight.Dataplanes.Online + insight.Dataplanes.Offline
+				updateTotal(kumaDpVersion, insight.DpVersions.KumaDp)
+				updateTotal(envoyVersion, insight.DpVersions.Envoy)
 			}
 		default:
 			if len(list.GetItems()) != 0 {
@@ -285,7 +301,6 @@ func (r *resyncer) createOrUpdateMeshInsight(mesh string) error {
 			}
 		}
 	}
-	insight.Dataplanes.Offline = insight.Dataplanes.Total - insight.Dataplanes.Online
 
 	err := manager.Upsert(r.rm, model.ResourceKey{Mesh: model.NoMesh, Name: mesh}, core_mesh.NewMeshInsightResource(), func(resource model.Resource) {
 		insight.LastSync = proto.MustTimestampProto(core.Now())
@@ -307,6 +322,23 @@ func (r *resyncer) createOrUpdateMeshInsight(mesh string) error {
 	return nil
 }
 
+func updateTotal(version string, dpStats map[string]*mesh_proto.MeshInsight_DataplaneStat) {
+	dpStats[version].Total = dpStats[version].Online + dpStats[version].Offline
+}
+
+func ensureVersionExists(version string, m map[string]*mesh_proto.MeshInsight_DataplaneStat) {
+	if _, versionExists := m[version]; !versionExists {
+		m[version] = &mesh_proto.MeshInsight_DataplaneStat{}
+	}
+}
+
+func getOrDefault(version string) string {
+	if version == "" {
+		return "unknown"
+	}
+	return version
+}
+
 func (r *resyncer) needResyncServiceInsight(mesh string) (bool, error) {
 	serviceInsight := core_mesh.NewServiceInsightResource()
 	if err := r.rm.Get(context.Background(), serviceInsight, store.GetByKey(ServiceInsightName(mesh), mesh)); err != nil {


Test patch:
diff --git a/pkg/insights/resyncer_test.go b/pkg/insights/resyncer_test.go
index 3521cffd2..beacedf10 100644
--- a/pkg/insights/resyncer_test.go
+++ b/pkg/insights/resyncer_test.go
@@ -2,9 +2,12 @@ package insights_test
 
 import (
 	"context"
+	"strconv"
 	"sync"
 	"time"
 
+	mesh_proto "github.com/kumahq/kuma/api/mesh/v1alpha1"
+
 	. "github.com/onsi/ginkgo"
 	. "github.com/onsi/gomega"
 
@@ -101,4 +104,76 @@ var _ = Describe("Insight Persistence", func() {
 		Expect(insight.Spec.Policies[string(core_mesh.TrafficPermissionType)].Total).To(Equal(uint32(1)))
 		Expect(insight.Spec.LastSync).To(MatchProto(proto.MustTimestampProto(now)))
 	})
+
+	It("should count dataplanes by version", func() {
+		// setup
+		err := rm.Create(context.Background(), core_mesh.NewMeshResource(), store.CreateByKey("mesh-1", model.NoMesh))
+		Expect(err).ToNot(HaveOccurred())
+
+		dp1 := core_mesh.NewDataplaneInsightResource()
+		dp1.Spec.Subscriptions = append(dp1.Spec.Subscriptions, &mesh_proto.DiscoverySubscription{
+			Id: strconv.Itoa(1),
+			Version: &mesh_proto.Version{
+				KumaDp: &mesh_proto.KumaDpVersion{
+					Version: "1.0.3",
+				},
+				Envoy: &mesh_proto.EnvoyVersion{
+					Version: "1.15.0",
+				},
+			},
+		})
+		err = rm.Create(context.Background(), dp1, store.CreateByKey("dp1", "mesh-1"))
+		Expect(err).ToNot(HaveOccurred())
+
+		dp2 := core_mesh.NewDataplaneInsightResource()
+		dp2.Spec.Subscriptions = append(dp2.Spec.Subscriptions, &mesh_proto.DiscoverySubscription{
+			Id: strconv.Itoa(2),
+			Version: &mesh_proto.Version{
+				KumaDp: &mesh_proto.KumaDpVersion{
+					Version: "1.0.4",
+				},
+				Envoy: &mesh_proto.EnvoyVersion{
+					Version: "1.15.0",
+				},
+			},
+		})
+		err = rm.Create(context.Background(), dp2, store.CreateByKey("dp2", "mesh-1"))
+		Expect(err).ToNot(HaveOccurred())
+
+		dp3 := core_mesh.NewDataplaneInsightResource()
+		dp3.Spec.Subscriptions = append(dp3.Spec.Subscriptions, &mesh_proto.DiscoverySubscription{
+			Id: strconv.Itoa(3),
+		})
+		err = rm.Create(context.Background(), dp3, store.CreateByKey("dp3", "mesh-1"))
+		Expect(err).ToNot(HaveOccurred())
+
+		nowMtx.Lock()
+		now = now.Add(60 * time.Second)
+		nowMtx.Unlock()
+		tickCh <- now
+
+		// when
+		meshInsight := core_mesh.NewMeshInsightResource()
+		Eventually(func() error {
+			return rm.Get(context.Background(), meshInsight, store.GetByKey("mesh-1", model.NoMesh))
+		}, "10s", "100ms").Should(BeNil())
+
+		// then
+		Expect(meshInsight.Spec.Dataplanes.Total).To(Equal(uint32(3)))
+		Expect(meshInsight.Spec.Dataplanes.Offline).To(Equal(uint32(3)))
+
+		kumaDp := meshInsight.Spec.DpVersions.KumaDp
+		Expect(kumaDp["unknown"].Total).To(Equal(uint32(1)))
+		Expect(kumaDp["unknown"].Offline).To(Equal(uint32(1)))
+		Expect(kumaDp["1.0.3"].Total).To(Equal(uint32(1)))
+		Expect(kumaDp["1.0.3"].Offline).To(Equal(uint32(1)))
+		Expect(kumaDp["1.0.4"].Total).To(Equal(uint32(1)))
+		Expect(kumaDp["1.0.4"].Offline).To(Equal(uint32(1)))
+
+		envoy := meshInsight.Spec.DpVersions.Envoy
+		Expect(envoy["unknown"].Total).To(Equal(uint32(1)))
+		Expect(envoy["unknown"].Offline).To(Equal(uint32(1)))
+		Expect(envoy["1.15.0"].Total).To(Equal(uint32(2)))
+		Expect(envoy["1.15.0"].Offline).To(Equal(uint32(2)))
+	})
 })