From a8c7ee48d314e630d20d26103e50cfcbffc3e1a2 Mon Sep 17 00:00:00 2001 From: bryanhuhta Date: Fri, 13 Sep 2024 11:43:24 -0700 Subject: [PATCH 1/4] Add option to request cardinality --- api/gen/proto/go/types/v1/types.pb.go | 174 ++++++++++-------- api/gen/proto/go/types/v1/types_vtproto.pb.go | 159 ++++++++++++++++ api/openapiv2/gen/phlare.swagger.json | 7 + api/types/v1/types.proto | 2 + 4 files changed, 267 insertions(+), 75 deletions(-) diff --git a/api/gen/proto/go/types/v1/types.pb.go b/api/gen/proto/go/types/v1/types.pb.go index cd2f67933f..33c6586c91 100644 --- a/api/gen/proto/go/types/v1/types.pb.go +++ b/api/gen/proto/go/types/v1/types.pb.go @@ -490,9 +490,10 @@ type LabelNamesRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Matchers []string `protobuf:"bytes,1,rep,name=matchers,proto3" json:"matchers,omitempty"` - Start int64 `protobuf:"varint,2,opt,name=start,proto3" json:"start,omitempty"` - End int64 `protobuf:"varint,3,opt,name=end,proto3" json:"end,omitempty"` + Matchers []string `protobuf:"bytes,1,rep,name=matchers,proto3" json:"matchers,omitempty"` + Start int64 `protobuf:"varint,2,opt,name=start,proto3" json:"start,omitempty"` + End int64 `protobuf:"varint,3,opt,name=end,proto3" json:"end,omitempty"` + IncludeCardinality *bool `protobuf:"varint,4,opt,name=include_cardinality,json=includeCardinality,proto3,oneof" json:"include_cardinality,omitempty"` } func (x *LabelNamesRequest) Reset() { @@ -548,12 +549,20 @@ func (x *LabelNamesRequest) GetEnd() int64 { return 0 } +func (x *LabelNamesRequest) GetIncludeCardinality() bool { + if x != nil && x.IncludeCardinality != nil { + return *x.IncludeCardinality + } + return false +} + type LabelNamesResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Names []string `protobuf:"bytes,1,rep,name=names,proto3" json:"names,omitempty"` + Names []string `protobuf:"bytes,1,rep,name=names,proto3" json:"names,omitempty"` + Cardinality []int64 `protobuf:"varint,2,rep,packed,name=cardinality,proto3" json:"cardinality,omitempty"` } func (x *LabelNamesResponse) Reset() { @@ -595,6 +604,13 @@ func (x *LabelNamesResponse) GetNames() []string { return nil } +func (x *LabelNamesResponse) GetCardinality() []int64 { + if x != nil { + return x.Cardinality + } + return nil +} + type BlockInfo struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1049,77 +1065,84 @@ var file_types_v1_types_proto_rawDesc = []byte{ 0x10, 0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x65, 0x6e, 0x64, 0x22, 0x2b, 0x0a, 0x13, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x6e, 0x61, 0x6d, 0x65, - 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x22, 0x57, - 0x0a, 0x11, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x73, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x73, 0x12, - 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, - 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x03, 0x65, 0x6e, 0x64, 0x22, 0x2a, 0x0a, 0x12, 0x4c, 0x61, 0x62, 0x65, 0x6c, - 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, - 0x05, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x6e, 0x61, - 0x6d, 0x65, 0x73, 0x22, 0xbd, 0x01, 0x0a, 0x09, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x49, 0x6e, 0x66, - 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x6c, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x04, 0x75, 0x6c, 0x69, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x6d, 0x69, 0x6e, 0x5f, 0x74, 0x69, 0x6d, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x6d, 0x69, 0x6e, 0x54, 0x69, 0x6d, 0x65, - 0x12, 0x19, 0x0a, 0x08, 0x6d, 0x61, 0x78, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x07, 0x6d, 0x61, 0x78, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x39, 0x0a, 0x0a, 0x63, - 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x19, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, - 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x63, 0x6f, 0x6d, 0x70, - 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2b, 0x0a, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, - 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x76, - 0x31, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x50, 0x61, 0x69, 0x72, 0x52, 0x06, 0x6c, 0x61, 0x62, - 0x65, 0x6c, 0x73, 0x22, 0x5b, 0x0a, 0x0f, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x6f, 0x6d, 0x70, - 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x18, 0x0a, 0x07, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, - 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x73, - 0x22, 0x6d, 0x0a, 0x12, 0x53, 0x74, 0x61, 0x63, 0x6b, 0x54, 0x72, 0x61, 0x63, 0x65, 0x53, 0x65, - 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x2f, 0x0a, 0x09, 0x63, 0x61, 0x6c, 0x6c, 0x5f, 0x73, - 0x69, 0x74, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x74, 0x79, 0x70, 0x65, - 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x63, - 0x61, 0x6c, 0x6c, 0x53, 0x69, 0x74, 0x65, 0x12, 0x26, 0x0a, 0x06, 0x67, 0x6f, 0x5f, 0x70, 0x67, - 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, - 0x76, 0x31, 0x2e, 0x47, 0x6f, 0x50, 0x47, 0x4f, 0x52, 0x05, 0x67, 0x6f, 0x50, 0x67, 0x6f, 0x22, - 0x1e, 0x0a, 0x08, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e, - 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, - 0x5b, 0x0a, 0x05, 0x47, 0x6f, 0x50, 0x47, 0x4f, 0x12, 0x25, 0x0a, 0x0e, 0x6b, 0x65, 0x65, 0x70, - 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, - 0x52, 0x0d, 0x6b, 0x65, 0x65, 0x70, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, - 0x2b, 0x0a, 0x11, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x5f, 0x63, 0x61, 0x6c, - 0x6c, 0x65, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x61, 0x67, 0x67, 0x72, - 0x65, 0x67, 0x61, 0x74, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x65, 0x65, 0x73, 0x22, 0x18, 0x0a, 0x16, - 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x9e, 0x01, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x50, 0x72, - 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x69, 0x6e, 0x67, 0x65, 0x73, - 0x74, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x64, 0x61, 0x74, 0x61, 0x49, - 0x6e, 0x67, 0x65, 0x73, 0x74, 0x65, 0x64, 0x12, 0x2e, 0x0a, 0x13, 0x6f, 0x6c, 0x64, 0x65, 0x73, - 0x74, 0x5f, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x11, 0x6f, 0x6c, 0x64, 0x65, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x66, - 0x69, 0x6c, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x2e, 0x0a, 0x13, 0x6e, 0x65, 0x77, 0x65, 0x73, - 0x74, 0x5f, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x11, 0x6e, 0x65, 0x77, 0x65, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x66, - 0x69, 0x6c, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x2a, 0x6b, 0x0a, 0x19, 0x54, 0x69, 0x6d, 0x65, 0x53, - 0x65, 0x72, 0x69, 0x65, 0x73, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x54, 0x79, 0x70, 0x65, 0x12, 0x24, 0x0a, 0x20, 0x54, 0x49, 0x4d, 0x45, 0x5f, 0x53, 0x45, 0x52, - 0x49, 0x45, 0x53, 0x5f, 0x41, 0x47, 0x47, 0x52, 0x45, 0x47, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, - 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x55, 0x4d, 0x10, 0x00, 0x12, 0x28, 0x0a, 0x24, 0x54, 0x49, - 0x4d, 0x45, 0x5f, 0x53, 0x45, 0x52, 0x49, 0x45, 0x53, 0x5f, 0x41, 0x47, 0x47, 0x52, 0x45, 0x47, - 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x41, 0x56, 0x45, 0x52, 0x41, - 0x47, 0x45, 0x10, 0x01, 0x42, 0x9b, 0x01, 0x0a, 0x0c, 0x63, 0x6f, 0x6d, 0x2e, 0x74, 0x79, 0x70, - 0x65, 0x73, 0x2e, 0x76, 0x31, 0x42, 0x0a, 0x54, 0x79, 0x70, 0x65, 0x73, 0x50, 0x72, 0x6f, 0x74, - 0x6f, 0x50, 0x01, 0x5a, 0x3e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, - 0x67, 0x72, 0x61, 0x66, 0x61, 0x6e, 0x61, 0x2f, 0x70, 0x79, 0x72, 0x6f, 0x73, 0x63, 0x6f, 0x70, - 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, - 0x67, 0x6f, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x76, 0x31, 0x3b, 0x74, 0x79, 0x70, 0x65, - 0x73, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x54, 0x58, 0x58, 0xaa, 0x02, 0x08, 0x54, 0x79, 0x70, 0x65, - 0x73, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x08, 0x54, 0x79, 0x70, 0x65, 0x73, 0x5c, 0x56, 0x31, 0xe2, - 0x02, 0x14, 0x54, 0x79, 0x70, 0x65, 0x73, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, - 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x09, 0x54, 0x79, 0x70, 0x65, 0x73, 0x3a, 0x3a, - 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x22, 0xa5, + 0x01, 0x0a, 0x11, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x73, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x73, + 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x03, 0x65, 0x6e, 0x64, 0x12, 0x34, 0x0a, 0x13, 0x69, 0x6e, 0x63, 0x6c, + 0x75, 0x64, 0x65, 0x5f, 0x63, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x12, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, + 0x43, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x88, 0x01, 0x01, 0x42, 0x16, + 0x0a, 0x14, 0x5f, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x63, 0x61, 0x72, 0x64, 0x69, + 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x22, 0x4c, 0x0a, 0x12, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x4e, + 0x61, 0x6d, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, + 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x6e, 0x61, 0x6d, + 0x65, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x63, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, + 0x79, 0x18, 0x02, 0x20, 0x03, 0x28, 0x03, 0x52, 0x0b, 0x63, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x61, + 0x6c, 0x69, 0x74, 0x79, 0x22, 0xbd, 0x01, 0x0a, 0x09, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x49, 0x6e, + 0x66, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x6c, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x75, 0x6c, 0x69, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x6d, 0x69, 0x6e, 0x5f, 0x74, 0x69, + 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x6d, 0x69, 0x6e, 0x54, 0x69, 0x6d, + 0x65, 0x12, 0x19, 0x0a, 0x08, 0x6d, 0x61, 0x78, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x07, 0x6d, 0x61, 0x78, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x39, 0x0a, 0x0a, + 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x19, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6c, 0x6f, 0x63, + 0x6b, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x63, 0x6f, 0x6d, + 0x70, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2b, 0x0a, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, + 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, + 0x76, 0x31, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x50, 0x61, 0x69, 0x72, 0x52, 0x06, 0x6c, 0x61, + 0x62, 0x65, 0x6c, 0x73, 0x22, 0x5b, 0x0a, 0x0f, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x6f, 0x6d, + 0x70, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x18, 0x0a, + 0x07, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x72, 0x65, 0x6e, + 0x74, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, + 0x73, 0x22, 0x6d, 0x0a, 0x12, 0x53, 0x74, 0x61, 0x63, 0x6b, 0x54, 0x72, 0x61, 0x63, 0x65, 0x53, + 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x2f, 0x0a, 0x09, 0x63, 0x61, 0x6c, 0x6c, 0x5f, + 0x73, 0x69, 0x74, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x74, 0x79, 0x70, + 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, + 0x63, 0x61, 0x6c, 0x6c, 0x53, 0x69, 0x74, 0x65, 0x12, 0x26, 0x0a, 0x06, 0x67, 0x6f, 0x5f, 0x70, + 0x67, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, + 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x6f, 0x50, 0x47, 0x4f, 0x52, 0x05, 0x67, 0x6f, 0x50, 0x67, 0x6f, + 0x22, 0x1e, 0x0a, 0x08, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x22, 0x5b, 0x0a, 0x05, 0x47, 0x6f, 0x50, 0x47, 0x4f, 0x12, 0x25, 0x0a, 0x0e, 0x6b, 0x65, 0x65, + 0x70, 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0d, 0x52, 0x0d, 0x6b, 0x65, 0x65, 0x70, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x12, 0x2b, 0x0a, 0x11, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x5f, 0x63, 0x61, + 0x6c, 0x6c, 0x65, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x61, 0x67, 0x67, + 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x65, 0x65, 0x73, 0x22, 0x18, 0x0a, + 0x16, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x9e, 0x01, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x50, + 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x69, 0x6e, 0x67, 0x65, + 0x73, 0x74, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x64, 0x61, 0x74, 0x61, + 0x49, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x65, 0x64, 0x12, 0x2e, 0x0a, 0x13, 0x6f, 0x6c, 0x64, 0x65, + 0x73, 0x74, 0x5f, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x11, 0x6f, 0x6c, 0x64, 0x65, 0x73, 0x74, 0x50, 0x72, 0x6f, + 0x66, 0x69, 0x6c, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x2e, 0x0a, 0x13, 0x6e, 0x65, 0x77, 0x65, + 0x73, 0x74, 0x5f, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x11, 0x6e, 0x65, 0x77, 0x65, 0x73, 0x74, 0x50, 0x72, 0x6f, + 0x66, 0x69, 0x6c, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x2a, 0x6b, 0x0a, 0x19, 0x54, 0x69, 0x6d, 0x65, + 0x53, 0x65, 0x72, 0x69, 0x65, 0x73, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x54, 0x79, 0x70, 0x65, 0x12, 0x24, 0x0a, 0x20, 0x54, 0x49, 0x4d, 0x45, 0x5f, 0x53, 0x45, + 0x52, 0x49, 0x45, 0x53, 0x5f, 0x41, 0x47, 0x47, 0x52, 0x45, 0x47, 0x41, 0x54, 0x49, 0x4f, 0x4e, + 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x55, 0x4d, 0x10, 0x00, 0x12, 0x28, 0x0a, 0x24, 0x54, + 0x49, 0x4d, 0x45, 0x5f, 0x53, 0x45, 0x52, 0x49, 0x45, 0x53, 0x5f, 0x41, 0x47, 0x47, 0x52, 0x45, + 0x47, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x41, 0x56, 0x45, 0x52, + 0x41, 0x47, 0x45, 0x10, 0x01, 0x42, 0x9b, 0x01, 0x0a, 0x0c, 0x63, 0x6f, 0x6d, 0x2e, 0x74, 0x79, + 0x70, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x42, 0x0a, 0x54, 0x79, 0x70, 0x65, 0x73, 0x50, 0x72, 0x6f, + 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, + 0x2f, 0x67, 0x72, 0x61, 0x66, 0x61, 0x6e, 0x61, 0x2f, 0x70, 0x79, 0x72, 0x6f, 0x73, 0x63, 0x6f, + 0x70, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x2f, 0x67, 0x6f, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x76, 0x31, 0x3b, 0x74, 0x79, 0x70, + 0x65, 0x73, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x54, 0x58, 0x58, 0xaa, 0x02, 0x08, 0x54, 0x79, 0x70, + 0x65, 0x73, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x08, 0x54, 0x79, 0x70, 0x65, 0x73, 0x5c, 0x56, 0x31, + 0xe2, 0x02, 0x14, 0x54, 0x79, 0x70, 0x65, 0x73, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, + 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x09, 0x54, 0x79, 0x70, 0x65, 0x73, 0x3a, + 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1369,6 +1392,7 @@ func file_types_v1_types_proto_init() { } } } + file_types_v1_types_proto_msgTypes[7].OneofWrappers = []any{} type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ diff --git a/api/gen/proto/go/types/v1/types_vtproto.pb.go b/api/gen/proto/go/types/v1/types_vtproto.pb.go index 14a8bcc7c7..dbcdd1d43e 100644 --- a/api/gen/proto/go/types/v1/types_vtproto.pb.go +++ b/api/gen/proto/go/types/v1/types_vtproto.pb.go @@ -189,6 +189,10 @@ func (m *LabelNamesRequest) CloneVT() *LabelNamesRequest { copy(tmpContainer, rhs) r.Matchers = tmpContainer } + if rhs := m.IncludeCardinality; rhs != nil { + tmpVal := *rhs + r.IncludeCardinality = &tmpVal + } if len(m.unknownFields) > 0 { r.unknownFields = make([]byte, len(m.unknownFields)) copy(r.unknownFields, m.unknownFields) @@ -210,6 +214,11 @@ func (m *LabelNamesResponse) CloneVT() *LabelNamesResponse { copy(tmpContainer, rhs) r.Names = tmpContainer } + if rhs := m.Cardinality; rhs != nil { + tmpContainer := make([]int64, len(rhs)) + copy(tmpContainer, rhs) + r.Cardinality = tmpContainer + } if len(m.unknownFields) > 0 { r.unknownFields = make([]byte, len(m.unknownFields)) copy(r.unknownFields, m.unknownFields) @@ -610,6 +619,9 @@ func (this *LabelNamesRequest) EqualVT(that *LabelNamesRequest) bool { if this.End != that.End { return false } + if p, q := this.IncludeCardinality, that.IncludeCardinality; (p == nil && q != nil) || (p != nil && (q == nil || *p != *q)) { + return false + } return string(this.unknownFields) == string(that.unknownFields) } @@ -635,6 +647,15 @@ func (this *LabelNamesResponse) EqualVT(that *LabelNamesResponse) bool { return false } } + if len(this.Cardinality) != len(that.Cardinality) { + return false + } + for i, vx := range this.Cardinality { + vy := that.Cardinality[i] + if vx != vy { + return false + } + } return string(this.unknownFields) == string(that.unknownFields) } @@ -1244,6 +1265,16 @@ func (m *LabelNamesRequest) MarshalToSizedBufferVT(dAtA []byte) (int, error) { i -= len(m.unknownFields) copy(dAtA[i:], m.unknownFields) } + if m.IncludeCardinality != nil { + i-- + if *m.IncludeCardinality { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x20 + } if m.End != 0 { i = protohelpers.EncodeVarint(dAtA, i, uint64(m.End)) i-- @@ -1296,6 +1327,27 @@ func (m *LabelNamesResponse) MarshalToSizedBufferVT(dAtA []byte) (int, error) { i -= len(m.unknownFields) copy(dAtA[i:], m.unknownFields) } + if len(m.Cardinality) > 0 { + var pksize2 int + for _, num := range m.Cardinality { + pksize2 += protohelpers.SizeOfVarint(uint64(num)) + } + i -= pksize2 + j1 := i + for _, num1 := range m.Cardinality { + num := uint64(num1) + for num >= 1<<7 { + dAtA[j1] = uint8(uint64(num)&0x7f | 0x80) + num >>= 7 + j1++ + } + dAtA[j1] = uint8(num) + j1++ + } + i = protohelpers.EncodeVarint(dAtA, i, uint64(pksize2)) + i-- + dAtA[i] = 0x12 + } if len(m.Names) > 0 { for iNdEx := len(m.Names) - 1; iNdEx >= 0; iNdEx-- { i -= len(m.Names[iNdEx]) @@ -1831,6 +1883,9 @@ func (m *LabelNamesRequest) SizeVT() (n int) { if m.End != 0 { n += 1 + protohelpers.SizeOfVarint(uint64(m.End)) } + if m.IncludeCardinality != nil { + n += 2 + } n += len(m.unknownFields) return n } @@ -1847,6 +1902,13 @@ func (m *LabelNamesResponse) SizeVT() (n int) { n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) } } + if len(m.Cardinality) > 0 { + l = 0 + for _, e := range m.Cardinality { + l += protohelpers.SizeOfVarint(uint64(e)) + } + n += 1 + protohelpers.SizeOfVarint(uint64(l)) + l + } n += len(m.unknownFields) return n } @@ -2963,6 +3025,27 @@ func (m *LabelNamesRequest) UnmarshalVT(dAtA []byte) error { break } } + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field IncludeCardinality", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + b := bool(v != 0) + m.IncludeCardinality = &b default: iNdEx = preIndex skippy, err := protohelpers.Skip(dAtA[iNdEx:]) @@ -3046,6 +3129,82 @@ func (m *LabelNamesResponse) UnmarshalVT(dAtA []byte) error { } m.Names = append(m.Names, string(dAtA[iNdEx:postIndex])) iNdEx = postIndex + case 2: + if wireType == 0 { + var v int64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.Cardinality = append(m.Cardinality, v) + } else if wireType == 2 { + var packedLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + packedLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if packedLen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + packedLen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + var elementCount int + var count int + for _, integer := range dAtA[iNdEx:postIndex] { + if integer < 128 { + count++ + } + } + elementCount = count + if elementCount != 0 && len(m.Cardinality) == 0 { + m.Cardinality = make([]int64, 0, elementCount) + } + for iNdEx < postIndex { + var v int64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.Cardinality = append(m.Cardinality, v) + } + } else { + return fmt.Errorf("proto: wrong wireType = %d for field Cardinality", wireType) + } default: iNdEx = preIndex skippy, err := protohelpers.Skip(dAtA[iNdEx:]) diff --git a/api/openapiv2/gen/phlare.swagger.json b/api/openapiv2/gen/phlare.swagger.json index 7a14fd90c3..248ffaccf8 100644 --- a/api/openapiv2/gen/phlare.swagger.json +++ b/api/openapiv2/gen/phlare.swagger.json @@ -1214,6 +1214,13 @@ "items": { "type": "string" } + }, + "cardinality": { + "type": "array", + "items": { + "type": "string", + "format": "int64" + } } } }, diff --git a/api/types/v1/types.proto b/api/types/v1/types.proto index 45edf69f84..1dadfca300 100644 --- a/api/types/v1/types.proto +++ b/api/types/v1/types.proto @@ -47,10 +47,12 @@ message LabelNamesRequest { repeated string matchers = 1; int64 start = 2; int64 end = 3; + optional bool include_cardinality = 4; } message LabelNamesResponse { repeated string names = 1; + repeated int64 cardinality = 2; } message BlockInfo { From 23c428a7eb6581c5873c513fc6314d173ac215d6 Mon Sep 17 00:00:00 2001 From: bryanhuhta Date: Fri, 13 Sep 2024 15:45:01 -0700 Subject: [PATCH 2/4] Implement fetching label name cardinality --- pkg/phlaredb/block_querier.go | 57 ++++++++++++----- pkg/phlaredb/head.go | 26 ++++++-- pkg/querier/ingester_querier.go | 6 +- pkg/querier/querier.go | 91 +++++++++++++++++++--------- pkg/querier/store_gateway_querier.go | 6 +- pkg/util/sort.go | 32 ++++++++++ 6 files changed, 163 insertions(+), 55 deletions(-) create mode 100644 pkg/util/sort.go diff --git a/pkg/phlaredb/block_querier.go b/pkg/phlaredb/block_querier.go index dcdfe9cdcf..258d47ac37 100644 --- a/pkg/phlaredb/block_querier.go +++ b/pkg/phlaredb/block_querier.go @@ -479,7 +479,7 @@ func (b *singleBlockQuerier) LabelNames(ctx context.Context, req *connect.Reques iters = append(iters, iter) } - nameSet := make(map[string]struct{}) + nameSet := make(map[string]int64) iter := index.Intersect(iters...) for iter.Next() { names, err := b.index.LabelNamesFor(iter.At()) @@ -491,18 +491,32 @@ func (b *singleBlockQuerier) LabelNames(ctx context.Context, req *connect.Reques } for _, name := range names { - nameSet[name] = struct{}{} + if _, ok := nameSet[name]; !ok { + nameSet[name] = 1 + } else { + nameSet[name]++ + } } } - names := make([]string, 0, len(nameSet)) - for name := range nameSet { - names = append(names, name) + res := &typesv1.LabelNamesResponse{ + Names: make([]string, 0, len(nameSet)), } - slices.Sort(names) - return connect.NewResponse(&typesv1.LabelNamesResponse{ - Names: names, - }), nil + if req.Msg.IncludeCardinality != nil && *req.Msg.IncludeCardinality { + res.Cardinality = make([]int64, 0, len(nameSet)) + for name, cardinality := range nameSet { + res.Names = append(res.Names, name) + res.Cardinality = append(res.Cardinality, cardinality) + } + // TODO(bryan): sort by name + } else { + for name := range nameSet { + res.Names = append(res.Names, name) + } + slices.Sort(res.Names) + } + + return connect.NewResponse(res), nil } func (b *singleBlockQuerier) BlockID() string { @@ -1393,7 +1407,7 @@ func LabelNames(ctx context.Context, req *connect.Request[typesv1.LabelNamesRequ return nil, err } - var labelNames []string + labelNames := make(map[string]int) var lock sync.Mutex group, ctx := errgroup.WithContext(ctx) @@ -1408,7 +1422,15 @@ func LabelNames(ctx context.Context, req *connect.Request[typesv1.LabelNamesRequ } lock.Lock() - labelNames = append(labelNames, res.Msg.Names...) + for i, name := range res.Msg.Names { + cardinality := int(res.Msg.Cardinality[i]) + + if _, ok := labelNames[name]; !ok { + labelNames[name] = cardinality + } else { + labelNames[name] += cardinality + } + } lock.Unlock() return nil })) @@ -1418,10 +1440,15 @@ func LabelNames(ctx context.Context, req *connect.Request[typesv1.LabelNamesRequ return nil, err } - slices.Sort(labelNames) - return &typesv1.LabelNamesResponse{ - Names: lo.Uniq(labelNames), - }, nil + res := &typesv1.LabelNamesResponse{ + Names: make([]string, 0, len(labelNames)), + Cardinality: make([]int64, 0, len(labelNames)), + } + for name, cardinality := range labelNames { + res.Names = append(res.Names, name) + res.Cardinality = append(res.Cardinality, int64(cardinality)) + } + return res, nil } func Series(ctx context.Context, req *ingestv1.SeriesRequest, blockGetter BlockGetter) (*ingestv1.SeriesResponse, error) { diff --git a/pkg/phlaredb/head.go b/pkg/phlaredb/head.go index 24239e7489..b4fab32c61 100644 --- a/pkg/phlaredb/head.go +++ b/pkg/phlaredb/head.go @@ -312,19 +312,35 @@ func (h *Head) LabelNames(ctx context.Context, req *connect.Request[typesv1.Labe } // aggregate all label values from series matching, when matchers are given. - values := make(map[string]struct{}) + values := make(map[string]int64) if err := h.forMatchingSelectors(selectors, func(lbs phlaremodel.Labels, fp model.Fingerprint) error { for _, lbl := range lbs { - values[lbl.Name] = struct{}{} + if _, ok := values[lbl.Name]; !ok { + values[lbl.Name] = 1 + } else { + values[lbl.Name]++ + } } return nil }); err != nil { return nil, err } - return connect.NewResponse(&typesv1.LabelNamesResponse{ - Names: lo.Keys(values), - }), nil + res := &typesv1.LabelNamesResponse{ + Names: make([]string, 0, len(values)), + } + + if req.Msg.IncludeCardinality != nil && *req.Msg.IncludeCardinality { + res.Cardinality = make([]int64, 0, len(values)) + for name, cardinality := range values { + res.Names = append(res.Names, name) + res.Cardinality = append(res.Cardinality, cardinality) + } + } else { + res.Names = lo.Keys(values) + } + + return connect.NewResponse(res), nil } func (h *Head) MustProfileTypeNames() []string { diff --git a/pkg/querier/ingester_querier.go b/pkg/querier/ingester_querier.go index 739ad2765b..476bec2a15 100644 --- a/pkg/querier/ingester_querier.go +++ b/pkg/querier/ingester_querier.go @@ -254,16 +254,16 @@ func (q *Querier) labelValuesFromIngesters(ctx context.Context, req *typesv1.Lab return responses, nil } -func (q *Querier) labelNamesFromIngesters(ctx context.Context, req *typesv1.LabelNamesRequest) ([]ResponseFromReplica[[]string], error) { +func (q *Querier) labelNamesFromIngesters(ctx context.Context, req *typesv1.LabelNamesRequest) ([]ResponseFromReplica[*typesv1.LabelNamesResponse], error) { sp, ctx := opentracing.StartSpanFromContext(ctx, "LabelNames Ingesters") defer sp.Finish() - responses, err := forAllIngesters(ctx, q.ingesterQuerier, func(childCtx context.Context, ic IngesterQueryClient) ([]string, error) { + responses, err := forAllIngesters(ctx, q.ingesterQuerier, func(childCtx context.Context, ic IngesterQueryClient) (*typesv1.LabelNamesResponse, error) { res, err := ic.LabelNames(childCtx, connect.NewRequest(req)) if err != nil { return nil, err } - return res.Msg.Names, nil + return res.Msg, nil }) if err != nil { return nil, connect.NewError(connect.CodeInternal, err) diff --git a/pkg/querier/querier.go b/pkg/querier/querier.go index 510a9aa2cb..58c5bea745 100644 --- a/pkg/querier/querier.go +++ b/pkg/querier/querier.go @@ -40,6 +40,7 @@ import ( "github.com/grafana/pyroscope/pkg/pprof" "github.com/grafana/pyroscope/pkg/querier/vcs" "github.com/grafana/pyroscope/pkg/storegateway" + "github.com/grafana/pyroscope/pkg/util" pmath "github.com/grafana/pyroscope/pkg/util/math" "github.com/grafana/pyroscope/pkg/util/spanlogger" "github.com/grafana/pyroscope/pkg/validation" @@ -294,9 +295,9 @@ func (q *Querier) LabelNames(ctx context.Context, req *connect.Request[typesv1.L if err != nil { return nil, err } - return connect.NewResponse(&typesv1.LabelNamesResponse{ - Names: uniqueSortedStrings(responses), - }), nil + + res := uniqueSortedLabelNames(responses) + return connect.NewResponse(res), nil } storeQueries := splitQueryToStores(model.Time(req.Msg.Start), model.Time(req.Msg.End), model.Now(), q.cfg.QueryStoreAfter, nil) @@ -305,7 +306,7 @@ func (q *Querier) LabelNames(ctx context.Context, req *connect.Request[typesv1.L } storeQueries.Log(level.Debug(spanlogger.FromContext(ctx, q.logger))) - var responses []ResponseFromReplica[[]string] + var responses []ResponseFromReplica[*typesv1.LabelNamesResponse] var lock sync.Mutex group, gCtx := errgroup.WithContext(ctx) @@ -342,9 +343,8 @@ func (q *Querier) LabelNames(ctx context.Context, req *connect.Request[typesv1.L return nil, err } - return connect.NewResponse(&typesv1.LabelNamesResponse{ - Names: uniqueSortedStrings(responses), - }), nil + res := uniqueSortedLabelNames(responses) + return connect.NewResponse(res), nil } func (q *Querier) blockSelect(ctx context.Context, start, end model.Time) (blockPlan, error) { @@ -779,9 +779,10 @@ func (sq storeQuery) SeriesRequest(req *querierv1.SeriesRequest) *ingestv1.Serie func (sq storeQuery) LabelNamesRequest(req *typesv1.LabelNamesRequest) *typesv1.LabelNamesRequest { return &typesv1.LabelNamesRequest{ - Matchers: req.Matchers, - Start: int64(sq.start), - End: int64(sq.end), + Matchers: req.Matchers, + Start: int64(sq.start), + End: int64(sq.end), + IncludeCardinality: req.IncludeCardinality, } } @@ -1039,25 +1040,6 @@ func (q *Querier) selectSeries(ctx context.Context, req *connect.Request[querier return responses, nil } -func uniqueSortedStrings(responses []ResponseFromReplica[[]string]) []string { - total := 0 - for _, r := range responses { - total += len(r.response) - } - unique := make(map[string]struct{}, total) - result := make([]string, 0, total) - for _, r := range responses { - for _, elem := range r.response { - if _, ok := unique[elem]; !ok { - unique[elem] = struct{}{} - result = append(result, elem) - } - } - } - sort.Strings(result) - return result -} - func (q *Querier) selectSpanProfile(ctx context.Context, req *querierv1.SelectMergeSpanProfileRequest) (*phlaremodel.Tree, error) { // determine the block hints plan, err := q.blockSelect(ctx, model.Time(req.Start), model.Time(req.End)) @@ -1114,3 +1096,54 @@ func (q *Querier) selectSpanProfile(ctx context.Context, req *querierv1.SelectMe storegatewayTree.Merge(ingesterTree) return storegatewayTree, nil } + +func uniqueSortedStrings(responses []ResponseFromReplica[[]string]) []string { + total := 0 + for _, r := range responses { + total += len(r.response) + } + unique := make(map[string]struct{}, total) + result := make([]string, 0, total) + for _, r := range responses { + for _, elem := range r.response { + if _, ok := unique[elem]; !ok { + unique[elem] = struct{}{} + result = append(result, elem) + } + } + } + sort.Strings(result) + return result +} + +func uniqueSortedLabelNames(responses []ResponseFromReplica[*typesv1.LabelNamesResponse]) *typesv1.LabelNamesResponse { + total := 0 + for _, r := range responses { + total += len(r.response.Names) + } + + unique := make(map[string]int64, total) + for _, r := range responses { + for i, name := range r.response.Names { + cardinality := r.response.Cardinality[i] + + if _, ok := unique[name]; !ok { + unique[name] = cardinality + } else { + unique[name] += cardinality + } + } + } + + res := &typesv1.LabelNamesResponse{ + Names: make([]string, 0, len(unique)), + Cardinality: make([]int64, 0, len(unique)), + } + for name, cardinality := range unique { + res.Names = append(res.Names, name) + res.Cardinality = append(res.Cardinality, cardinality) + } + + util.SortLabelNamesResponse(res) + return res +} diff --git a/pkg/querier/store_gateway_querier.go b/pkg/querier/store_gateway_querier.go index 7de34312c8..3cf0dab085 100644 --- a/pkg/querier/store_gateway_querier.go +++ b/pkg/querier/store_gateway_querier.go @@ -358,7 +358,7 @@ func (q *Querier) labelValuesFromStoreGateway(ctx context.Context, req *typesv1. return responses, nil } -func (q *Querier) labelNamesFromStoreGateway(ctx context.Context, req *typesv1.LabelNamesRequest) ([]ResponseFromReplica[[]string], error) { +func (q *Querier) labelNamesFromStoreGateway(ctx context.Context, req *typesv1.LabelNamesRequest) ([]ResponseFromReplica[*typesv1.LabelNamesResponse], error) { sp, ctx := opentracing.StartSpanFromContext(ctx, "LabelNames StoreGateway") defer sp.Finish() @@ -367,12 +367,12 @@ func (q *Querier) labelNamesFromStoreGateway(ctx context.Context, req *typesv1.L return nil, connect.NewError(connect.CodeInvalidArgument, err) } - responses, err := forAllStoreGateways(ctx, tenantID, q.storeGatewayQuerier, func(ctx context.Context, ic StoreGatewayQueryClient) ([]string, error) { + responses, err := forAllStoreGateways(ctx, tenantID, q.storeGatewayQuerier, func(ctx context.Context, ic StoreGatewayQueryClient) (*typesv1.LabelNamesResponse, error) { res, err := ic.LabelNames(ctx, connect.NewRequest(req)) if err != nil { return nil, err } - return res.Msg.Names, nil + return res.Msg, nil }) if err != nil { return nil, connect.NewError(connect.CodeInternal, err) diff --git a/pkg/util/sort.go b/pkg/util/sort.go new file mode 100644 index 0000000000..f4c357e2f4 --- /dev/null +++ b/pkg/util/sort.go @@ -0,0 +1,32 @@ +package util + +import ( + "slices" + "sort" + + typesv1 "github.com/grafana/pyroscope/api/gen/proto/go/types/v1" +) + +type labelNameCardinalitySort typesv1.LabelNamesResponse + +func (s *labelNameCardinalitySort) Len() int { + return len(s.Names) +} + +func (s *labelNameCardinalitySort) Less(i, j int) bool { + return s.Names[i] < s.Names[j] +} + +func (s *labelNameCardinalitySort) Swap(i, j int) { + s.Names[i], s.Names[j] = s.Names[j], s.Names[i] + s.Cardinality[i], s.Cardinality[j] = s.Cardinality[j], s.Cardinality[i] +} + +func SortLabelNamesResponse(r *typesv1.LabelNamesResponse) { + if len(r.Cardinality) == 0 { + slices.Sort(r.Names) + return + } + + sort.Sort((*labelNameCardinalitySort)(r)) +} From cea1b2df2ebdb7a9062e7fe1e1586b77543f32db Mon Sep 17 00:00:00 2001 From: bryanhuhta Date: Tue, 17 Sep 2024 10:42:16 -0700 Subject: [PATCH 3/4] Respect cardinality request down the entire callstack --- pkg/phlaredb/block_querier.go | 38 ++++++++++++++++++++++++----------- pkg/querier/querier.go | 26 ++++++++++++++++++------ 2 files changed, 46 insertions(+), 18 deletions(-) diff --git a/pkg/phlaredb/block_querier.go b/pkg/phlaredb/block_querier.go index 258d47ac37..3185058e76 100644 --- a/pkg/phlaredb/block_querier.go +++ b/pkg/phlaredb/block_querier.go @@ -1408,6 +1408,7 @@ func LabelNames(ctx context.Context, req *connect.Request[typesv1.LabelNamesRequ } labelNames := make(map[string]int) + includeCardinality := req.Msg.IncludeCardinality != nil && *req.Msg.IncludeCardinality var lock sync.Mutex group, ctx := errgroup.WithContext(ctx) @@ -1422,13 +1423,19 @@ func LabelNames(ctx context.Context, req *connect.Request[typesv1.LabelNamesRequ } lock.Lock() - for i, name := range res.Msg.Names { - cardinality := int(res.Msg.Cardinality[i]) - - if _, ok := labelNames[name]; !ok { - labelNames[name] = cardinality - } else { - labelNames[name] += cardinality + if includeCardinality { + for i, name := range res.Msg.Names { + cardinality := int(res.Msg.Cardinality[i]) + + if _, ok := labelNames[name]; !ok { + labelNames[name] = cardinality + } else { + labelNames[name] += cardinality + } + } + } else { + for _, name := range res.Msg.Names { + labelNames[name] = 0 } } lock.Unlock() @@ -1441,12 +1448,19 @@ func LabelNames(ctx context.Context, req *connect.Request[typesv1.LabelNamesRequ } res := &typesv1.LabelNamesResponse{ - Names: make([]string, 0, len(labelNames)), - Cardinality: make([]int64, 0, len(labelNames)), + Names: make([]string, 0, len(labelNames)), } - for name, cardinality := range labelNames { - res.Names = append(res.Names, name) - res.Cardinality = append(res.Cardinality, int64(cardinality)) + + if includeCardinality { + res.Cardinality = make([]int64, 0, len(labelNames)) + for name, cardinality := range labelNames { + res.Names = append(res.Names, name) + res.Cardinality = append(res.Cardinality, int64(cardinality)) + } + } else { + for name := range labelNames { + res.Names = append(res.Names, name) + } } return res, nil } diff --git a/pkg/querier/querier.go b/pkg/querier/querier.go index 58c5bea745..f6f1f6149f 100644 --- a/pkg/querier/querier.go +++ b/pkg/querier/querier.go @@ -1118,14 +1118,21 @@ func uniqueSortedStrings(responses []ResponseFromReplica[[]string]) []string { func uniqueSortedLabelNames(responses []ResponseFromReplica[*typesv1.LabelNamesResponse]) *typesv1.LabelNamesResponse { total := 0 + includeCardinality := true for _, r := range responses { total += len(r.response.Names) + if len(r.response.Cardinality) != len(r.response.Names) { + includeCardinality = false + } } unique := make(map[string]int64, total) for _, r := range responses { for i, name := range r.response.Names { - cardinality := r.response.Cardinality[i] + cardinality := int64(0) + if includeCardinality { + cardinality = r.response.Cardinality[i] + } if _, ok := unique[name]; !ok { unique[name] = cardinality @@ -1136,12 +1143,19 @@ func uniqueSortedLabelNames(responses []ResponseFromReplica[*typesv1.LabelNamesR } res := &typesv1.LabelNamesResponse{ - Names: make([]string, 0, len(unique)), - Cardinality: make([]int64, 0, len(unique)), + Names: make([]string, 0, len(unique)), } - for name, cardinality := range unique { - res.Names = append(res.Names, name) - res.Cardinality = append(res.Cardinality, cardinality) + + if includeCardinality { + res.Cardinality = make([]int64, 0, len(unique)) + for name, cardinality := range unique { + res.Names = append(res.Names, name) + res.Cardinality = append(res.Cardinality, cardinality) + } + } else { + for name := range unique { + res.Names = append(res.Names, name) + } } util.SortLabelNamesResponse(res) From 2ef6a246dc3a48377231f4d28ca010074a5856eb Mon Sep 17 00:00:00 2001 From: bryanhuhta Date: Tue, 17 Sep 2024 17:17:40 -0700 Subject: [PATCH 4/4] Optimize when to query for label values --- api/gen/proto/go/types/v1/types.pb.go | 139 +++++++++--------- api/gen/proto/go/types/v1/types_vtproto.pb.go | 30 ++-- api/openapiv2/gen/phlare.swagger.json | 2 +- api/types/v1/types.proto | 2 +- load.js | 57 +++++++ pkg/phlaredb/block_querier.go | 70 ++++----- pkg/phlaredb/head.go | 34 +++-- pkg/querier/querier.go | 45 +----- pkg/util/labels.go | 53 +++++++ pkg/util/labels_test.go | 128 ++++++++++++++++ pkg/util/sort.go | 4 +- 11 files changed, 383 insertions(+), 181 deletions(-) create mode 100644 load.js create mode 100644 pkg/util/labels_test.go diff --git a/api/gen/proto/go/types/v1/types.pb.go b/api/gen/proto/go/types/v1/types.pb.go index 33c6586c91..1fecdd8aba 100644 --- a/api/gen/proto/go/types/v1/types.pb.go +++ b/api/gen/proto/go/types/v1/types.pb.go @@ -561,8 +561,8 @@ type LabelNamesResponse struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Names []string `protobuf:"bytes,1,rep,name=names,proto3" json:"names,omitempty"` - Cardinality []int64 `protobuf:"varint,2,rep,packed,name=cardinality,proto3" json:"cardinality,omitempty"` + Names []string `protobuf:"bytes,1,rep,name=names,proto3" json:"names,omitempty"` + EstimatedCardinality []int64 `protobuf:"varint,2,rep,packed,name=estimated_cardinality,json=estimatedCardinality,proto3" json:"estimated_cardinality,omitempty"` } func (x *LabelNamesResponse) Reset() { @@ -604,9 +604,9 @@ func (x *LabelNamesResponse) GetNames() []string { return nil } -func (x *LabelNamesResponse) GetCardinality() []int64 { +func (x *LabelNamesResponse) GetEstimatedCardinality() []int64 { if x != nil { - return x.Cardinality + return x.EstimatedCardinality } return nil } @@ -1076,73 +1076,74 @@ var file_types_v1_types_proto_rawDesc = []byte{ 0x04, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x12, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x43, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x88, 0x01, 0x01, 0x42, 0x16, 0x0a, 0x14, 0x5f, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x63, 0x61, 0x72, 0x64, 0x69, - 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x22, 0x4c, 0x0a, 0x12, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x4e, + 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x22, 0x5f, 0x0a, 0x12, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x6e, 0x61, 0x6d, - 0x65, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x63, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, - 0x79, 0x18, 0x02, 0x20, 0x03, 0x28, 0x03, 0x52, 0x0b, 0x63, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x61, - 0x6c, 0x69, 0x74, 0x79, 0x22, 0xbd, 0x01, 0x0a, 0x09, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x49, 0x6e, - 0x66, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x6c, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x04, 0x75, 0x6c, 0x69, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x6d, 0x69, 0x6e, 0x5f, 0x74, 0x69, - 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x6d, 0x69, 0x6e, 0x54, 0x69, 0x6d, - 0x65, 0x12, 0x19, 0x0a, 0x08, 0x6d, 0x61, 0x78, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x07, 0x6d, 0x61, 0x78, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x39, 0x0a, 0x0a, - 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x19, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6c, 0x6f, 0x63, - 0x6b, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x63, 0x6f, 0x6d, - 0x70, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2b, 0x0a, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, - 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, - 0x76, 0x31, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x50, 0x61, 0x69, 0x72, 0x52, 0x06, 0x6c, 0x61, - 0x62, 0x65, 0x6c, 0x73, 0x22, 0x5b, 0x0a, 0x0f, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x6f, 0x6d, - 0x70, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x18, 0x0a, - 0x07, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x72, 0x65, 0x6e, - 0x74, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, - 0x73, 0x22, 0x6d, 0x0a, 0x12, 0x53, 0x74, 0x61, 0x63, 0x6b, 0x54, 0x72, 0x61, 0x63, 0x65, 0x53, - 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x2f, 0x0a, 0x09, 0x63, 0x61, 0x6c, 0x6c, 0x5f, - 0x73, 0x69, 0x74, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x74, 0x79, 0x70, - 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, - 0x63, 0x61, 0x6c, 0x6c, 0x53, 0x69, 0x74, 0x65, 0x12, 0x26, 0x0a, 0x06, 0x67, 0x6f, 0x5f, 0x70, - 0x67, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, - 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x6f, 0x50, 0x47, 0x4f, 0x52, 0x05, 0x67, 0x6f, 0x50, 0x67, 0x6f, - 0x22, 0x1e, 0x0a, 0x08, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, - 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, - 0x22, 0x5b, 0x0a, 0x05, 0x47, 0x6f, 0x50, 0x47, 0x4f, 0x12, 0x25, 0x0a, 0x0e, 0x6b, 0x65, 0x65, - 0x70, 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0d, 0x52, 0x0d, 0x6b, 0x65, 0x65, 0x70, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x12, 0x2b, 0x0a, 0x11, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x5f, 0x63, 0x61, - 0x6c, 0x6c, 0x65, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x61, 0x67, 0x67, - 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x65, 0x65, 0x73, 0x22, 0x18, 0x0a, - 0x16, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x9e, 0x01, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x50, - 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x69, 0x6e, 0x67, 0x65, - 0x73, 0x74, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x64, 0x61, 0x74, 0x61, - 0x49, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x65, 0x64, 0x12, 0x2e, 0x0a, 0x13, 0x6f, 0x6c, 0x64, 0x65, - 0x73, 0x74, 0x5f, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x11, 0x6f, 0x6c, 0x64, 0x65, 0x73, 0x74, 0x50, 0x72, 0x6f, - 0x66, 0x69, 0x6c, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x2e, 0x0a, 0x13, 0x6e, 0x65, 0x77, 0x65, - 0x73, 0x74, 0x5f, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x11, 0x6e, 0x65, 0x77, 0x65, 0x73, 0x74, 0x50, 0x72, 0x6f, - 0x66, 0x69, 0x6c, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x2a, 0x6b, 0x0a, 0x19, 0x54, 0x69, 0x6d, 0x65, - 0x53, 0x65, 0x72, 0x69, 0x65, 0x73, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x54, 0x79, 0x70, 0x65, 0x12, 0x24, 0x0a, 0x20, 0x54, 0x49, 0x4d, 0x45, 0x5f, 0x53, 0x45, - 0x52, 0x49, 0x45, 0x53, 0x5f, 0x41, 0x47, 0x47, 0x52, 0x45, 0x47, 0x41, 0x54, 0x49, 0x4f, 0x4e, - 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x55, 0x4d, 0x10, 0x00, 0x12, 0x28, 0x0a, 0x24, 0x54, - 0x49, 0x4d, 0x45, 0x5f, 0x53, 0x45, 0x52, 0x49, 0x45, 0x53, 0x5f, 0x41, 0x47, 0x47, 0x52, 0x45, - 0x47, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x41, 0x56, 0x45, 0x52, - 0x41, 0x47, 0x45, 0x10, 0x01, 0x42, 0x9b, 0x01, 0x0a, 0x0c, 0x63, 0x6f, 0x6d, 0x2e, 0x74, 0x79, - 0x70, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x42, 0x0a, 0x54, 0x79, 0x70, 0x65, 0x73, 0x50, 0x72, 0x6f, - 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, - 0x2f, 0x67, 0x72, 0x61, 0x66, 0x61, 0x6e, 0x61, 0x2f, 0x70, 0x79, 0x72, 0x6f, 0x73, 0x63, 0x6f, - 0x70, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x2f, 0x67, 0x6f, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x76, 0x31, 0x3b, 0x74, 0x79, 0x70, - 0x65, 0x73, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x54, 0x58, 0x58, 0xaa, 0x02, 0x08, 0x54, 0x79, 0x70, - 0x65, 0x73, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x08, 0x54, 0x79, 0x70, 0x65, 0x73, 0x5c, 0x56, 0x31, - 0xe2, 0x02, 0x14, 0x54, 0x79, 0x70, 0x65, 0x73, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, - 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x09, 0x54, 0x79, 0x70, 0x65, 0x73, 0x3a, - 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x65, 0x73, 0x12, 0x33, 0x0a, 0x15, 0x65, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x64, 0x5f, + 0x63, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x18, 0x02, 0x20, 0x03, 0x28, + 0x03, 0x52, 0x14, 0x65, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x64, 0x43, 0x61, 0x72, 0x64, + 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x22, 0xbd, 0x01, 0x0a, 0x09, 0x42, 0x6c, 0x6f, 0x63, + 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x6c, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x6c, 0x69, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x6d, 0x69, 0x6e, + 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x6d, 0x69, 0x6e, + 0x54, 0x69, 0x6d, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x6d, 0x61, 0x78, 0x5f, 0x74, 0x69, 0x6d, 0x65, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x6d, 0x61, 0x78, 0x54, 0x69, 0x6d, 0x65, 0x12, + 0x39, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x42, + 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, + 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2b, 0x0a, 0x06, 0x6c, 0x61, + 0x62, 0x65, 0x6c, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x74, 0x79, 0x70, + 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x50, 0x61, 0x69, 0x72, 0x52, + 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x22, 0x5b, 0x0a, 0x0f, 0x42, 0x6c, 0x6f, 0x63, 0x6b, + 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x65, + 0x76, 0x65, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, + 0x12, 0x18, 0x0a, 0x07, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, + 0x09, 0x52, 0x07, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, + 0x72, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x70, 0x61, 0x72, + 0x65, 0x6e, 0x74, 0x73, 0x22, 0x6d, 0x0a, 0x12, 0x53, 0x74, 0x61, 0x63, 0x6b, 0x54, 0x72, 0x61, + 0x63, 0x65, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x2f, 0x0a, 0x09, 0x63, 0x61, + 0x6c, 0x6c, 0x5f, 0x73, 0x69, 0x74, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, + 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x52, 0x08, 0x63, 0x61, 0x6c, 0x6c, 0x53, 0x69, 0x74, 0x65, 0x12, 0x26, 0x0a, 0x06, 0x67, + 0x6f, 0x5f, 0x70, 0x67, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, 0x79, + 0x70, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x6f, 0x50, 0x47, 0x4f, 0x52, 0x05, 0x67, 0x6f, + 0x50, 0x67, 0x6f, 0x22, 0x1e, 0x0a, 0x08, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, + 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, + 0x61, 0x6d, 0x65, 0x22, 0x5b, 0x0a, 0x05, 0x47, 0x6f, 0x50, 0x47, 0x4f, 0x12, 0x25, 0x0a, 0x0e, + 0x6b, 0x65, 0x65, 0x70, 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x6b, 0x65, 0x65, 0x70, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, + 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, + 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x65, 0x65, 0x73, + 0x22, 0x18, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x53, 0x74, + 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x9e, 0x01, 0x0a, 0x17, 0x47, + 0x65, 0x74, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x69, + 0x6e, 0x67, 0x65, 0x73, 0x74, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x64, + 0x61, 0x74, 0x61, 0x49, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x65, 0x64, 0x12, 0x2e, 0x0a, 0x13, 0x6f, + 0x6c, 0x64, 0x65, 0x73, 0x74, 0x5f, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x74, 0x69, + 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x11, 0x6f, 0x6c, 0x64, 0x65, 0x73, 0x74, + 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x2e, 0x0a, 0x13, 0x6e, + 0x65, 0x77, 0x65, 0x73, 0x74, 0x5f, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x74, 0x69, + 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x11, 0x6e, 0x65, 0x77, 0x65, 0x73, 0x74, + 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x2a, 0x6b, 0x0a, 0x19, 0x54, + 0x69, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x69, 0x65, 0x73, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x12, 0x24, 0x0a, 0x20, 0x54, 0x49, 0x4d, 0x45, + 0x5f, 0x53, 0x45, 0x52, 0x49, 0x45, 0x53, 0x5f, 0x41, 0x47, 0x47, 0x52, 0x45, 0x47, 0x41, 0x54, + 0x49, 0x4f, 0x4e, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x55, 0x4d, 0x10, 0x00, 0x12, 0x28, + 0x0a, 0x24, 0x54, 0x49, 0x4d, 0x45, 0x5f, 0x53, 0x45, 0x52, 0x49, 0x45, 0x53, 0x5f, 0x41, 0x47, + 0x47, 0x52, 0x45, 0x47, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x41, + 0x56, 0x45, 0x52, 0x41, 0x47, 0x45, 0x10, 0x01, 0x42, 0x9b, 0x01, 0x0a, 0x0c, 0x63, 0x6f, 0x6d, + 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x42, 0x0a, 0x54, 0x79, 0x70, 0x65, 0x73, + 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, + 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x72, 0x61, 0x66, 0x61, 0x6e, 0x61, 0x2f, 0x70, 0x79, 0x72, 0x6f, + 0x73, 0x63, 0x6f, 0x70, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x76, 0x31, 0x3b, + 0x74, 0x79, 0x70, 0x65, 0x73, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x54, 0x58, 0x58, 0xaa, 0x02, 0x08, + 0x54, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x08, 0x54, 0x79, 0x70, 0x65, 0x73, + 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x14, 0x54, 0x79, 0x70, 0x65, 0x73, 0x5c, 0x56, 0x31, 0x5c, 0x47, + 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x09, 0x54, 0x79, 0x70, + 0x65, 0x73, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/api/gen/proto/go/types/v1/types_vtproto.pb.go b/api/gen/proto/go/types/v1/types_vtproto.pb.go index dbcdd1d43e..0944f3a533 100644 --- a/api/gen/proto/go/types/v1/types_vtproto.pb.go +++ b/api/gen/proto/go/types/v1/types_vtproto.pb.go @@ -214,10 +214,10 @@ func (m *LabelNamesResponse) CloneVT() *LabelNamesResponse { copy(tmpContainer, rhs) r.Names = tmpContainer } - if rhs := m.Cardinality; rhs != nil { + if rhs := m.EstimatedCardinality; rhs != nil { tmpContainer := make([]int64, len(rhs)) copy(tmpContainer, rhs) - r.Cardinality = tmpContainer + r.EstimatedCardinality = tmpContainer } if len(m.unknownFields) > 0 { r.unknownFields = make([]byte, len(m.unknownFields)) @@ -647,11 +647,11 @@ func (this *LabelNamesResponse) EqualVT(that *LabelNamesResponse) bool { return false } } - if len(this.Cardinality) != len(that.Cardinality) { + if len(this.EstimatedCardinality) != len(that.EstimatedCardinality) { return false } - for i, vx := range this.Cardinality { - vy := that.Cardinality[i] + for i, vx := range this.EstimatedCardinality { + vy := that.EstimatedCardinality[i] if vx != vy { return false } @@ -1327,14 +1327,14 @@ func (m *LabelNamesResponse) MarshalToSizedBufferVT(dAtA []byte) (int, error) { i -= len(m.unknownFields) copy(dAtA[i:], m.unknownFields) } - if len(m.Cardinality) > 0 { + if len(m.EstimatedCardinality) > 0 { var pksize2 int - for _, num := range m.Cardinality { + for _, num := range m.EstimatedCardinality { pksize2 += protohelpers.SizeOfVarint(uint64(num)) } i -= pksize2 j1 := i - for _, num1 := range m.Cardinality { + for _, num1 := range m.EstimatedCardinality { num := uint64(num1) for num >= 1<<7 { dAtA[j1] = uint8(uint64(num)&0x7f | 0x80) @@ -1902,9 +1902,9 @@ func (m *LabelNamesResponse) SizeVT() (n int) { n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) } } - if len(m.Cardinality) > 0 { + if len(m.EstimatedCardinality) > 0 { l = 0 - for _, e := range m.Cardinality { + for _, e := range m.EstimatedCardinality { l += protohelpers.SizeOfVarint(uint64(e)) } n += 1 + protohelpers.SizeOfVarint(uint64(l)) + l @@ -3146,7 +3146,7 @@ func (m *LabelNamesResponse) UnmarshalVT(dAtA []byte) error { break } } - m.Cardinality = append(m.Cardinality, v) + m.EstimatedCardinality = append(m.EstimatedCardinality, v) } else if wireType == 2 { var packedLen int for shift := uint(0); ; shift += 7 { @@ -3181,8 +3181,8 @@ func (m *LabelNamesResponse) UnmarshalVT(dAtA []byte) error { } } elementCount = count - if elementCount != 0 && len(m.Cardinality) == 0 { - m.Cardinality = make([]int64, 0, elementCount) + if elementCount != 0 && len(m.EstimatedCardinality) == 0 { + m.EstimatedCardinality = make([]int64, 0, elementCount) } for iNdEx < postIndex { var v int64 @@ -3200,10 +3200,10 @@ func (m *LabelNamesResponse) UnmarshalVT(dAtA []byte) error { break } } - m.Cardinality = append(m.Cardinality, v) + m.EstimatedCardinality = append(m.EstimatedCardinality, v) } } else { - return fmt.Errorf("proto: wrong wireType = %d for field Cardinality", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field EstimatedCardinality", wireType) } default: iNdEx = preIndex diff --git a/api/openapiv2/gen/phlare.swagger.json b/api/openapiv2/gen/phlare.swagger.json index 248ffaccf8..9c9f4099e6 100644 --- a/api/openapiv2/gen/phlare.swagger.json +++ b/api/openapiv2/gen/phlare.swagger.json @@ -1215,7 +1215,7 @@ "type": "string" } }, - "cardinality": { + "estimatedCardinality": { "type": "array", "items": { "type": "string", diff --git a/api/types/v1/types.proto b/api/types/v1/types.proto index 1dadfca300..1ea30ecb2d 100644 --- a/api/types/v1/types.proto +++ b/api/types/v1/types.proto @@ -52,7 +52,7 @@ message LabelNamesRequest { message LabelNamesResponse { repeated string names = 1; - repeated int64 cardinality = 2; + repeated int64 estimated_cardinality = 2; } message BlockInfo { diff --git a/load.js b/load.js new file mode 100644 index 0000000000..f06542ccf5 --- /dev/null +++ b/load.js @@ -0,0 +1,57 @@ +import http from 'k6/http'; +import { check } from 'k6'; + +export let options = { + vus: 5, + duration: '10m', +}; + +export default function () { + // 24h query + const start = 1726473370933; + const end = 1726617370933; + + const response = labelNamesRequest({ + matchers: ["{service_name=\"fire-dev-001/querier\"}"], + start: start, + end: end + }); + + const names = response.json('names'); + check(response, { + 'Label names response is 200': (r) => r.status === 200, + 'Label names response has data': (r) => names.length > 0, + }); + + for (let name of names) { + const response = labelValuesRequest({ + matchers: [`{service_name=\"fire-dev-001/querier\", metric_name=\"${name}\"}`], + start: start, + end: end + }); + + const values = response.json('names'); + check(response, { + 'Label values response is 200': (r) => r.status === 200, + 'Label values response has data': () => values !== undefined && values.length > 0, + }); + } +} + +function labelNamesRequest(body) { + return http.post('http://localhost:4100/querier.v1.QuerierService/LabelNames', JSON.stringify(body), { + headers: { + 'Content-Type': 'application/json', + 'X-Scope-OrgID': '1218' + }, + }); +} + +function labelValuesRequest(body) { + return http.post('http://localhost:4100/querier.v1.QuerierService/LabelValues', JSON.stringify(body), { + headers: { + 'Content-Type': 'application/json', + 'X-Scope-OrgID': '1218' + }, + }); +} diff --git a/pkg/phlaredb/block_querier.go b/pkg/phlaredb/block_querier.go index 3185058e76..7641420eaa 100644 --- a/pkg/phlaredb/block_querier.go +++ b/pkg/phlaredb/block_querier.go @@ -479,7 +479,10 @@ func (b *singleBlockQuerier) LabelNames(ctx context.Context, req *connect.Reques iters = append(iters, iter) } - nameSet := make(map[string]int64) + // Maps label name to a set of label values. + nameSet := make(map[string]map[string]struct{}) + includeCardinality := req.Msg.IncludeCardinality != nil && *req.Msg.IncludeCardinality + iter := index.Intersect(iters...) for iter.Next() { names, err := b.index.LabelNamesFor(iter.At()) @@ -491,10 +494,25 @@ func (b *singleBlockQuerier) LabelNames(ctx context.Context, req *connect.Reques } for _, name := range names { - if _, ok := nameSet[name]; !ok { - nameSet[name] = 1 + var value string + if includeCardinality { + value, err = b.index.LabelValueFor(iter.At(), name) + if err != nil { + if err == storage.ErrNotFound { + continue + } + return nil, err + } + + if _, ok := nameSet[name]; !ok { + nameSet[name] = map[string]struct{}{value: {}} + } else { + nameSet[name][value] = struct{}{} + } } else { - nameSet[name]++ + if _, ok := nameSet[name]; !ok { + nameSet[name] = map[string]struct{}{} + } } } } @@ -502,20 +520,19 @@ func (b *singleBlockQuerier) LabelNames(ctx context.Context, req *connect.Reques res := &typesv1.LabelNamesResponse{ Names: make([]string, 0, len(nameSet)), } - if req.Msg.IncludeCardinality != nil && *req.Msg.IncludeCardinality { - res.Cardinality = make([]int64, 0, len(nameSet)) + if includeCardinality { + res.EstimatedCardinality = make([]int64, 0, len(nameSet)) for name, cardinality := range nameSet { res.Names = append(res.Names, name) - res.Cardinality = append(res.Cardinality, cardinality) + res.EstimatedCardinality = append(res.EstimatedCardinality, int64(len(cardinality))) } - // TODO(bryan): sort by name } else { for name := range nameSet { res.Names = append(res.Names, name) } - slices.Sort(res.Names) } + util.SortLabelNamesResponse(res) return connect.NewResponse(res), nil } @@ -1407,8 +1424,7 @@ func LabelNames(ctx context.Context, req *connect.Request[typesv1.LabelNamesRequ return nil, err } - labelNames := make(map[string]int) - includeCardinality := req.Msg.IncludeCardinality != nil && *req.Msg.IncludeCardinality + responses := make([]*typesv1.LabelNamesResponse, 0, len(queriers)) var lock sync.Mutex group, ctx := errgroup.WithContext(ctx) @@ -1423,21 +1439,7 @@ func LabelNames(ctx context.Context, req *connect.Request[typesv1.LabelNamesRequ } lock.Lock() - if includeCardinality { - for i, name := range res.Msg.Names { - cardinality := int(res.Msg.Cardinality[i]) - - if _, ok := labelNames[name]; !ok { - labelNames[name] = cardinality - } else { - labelNames[name] += cardinality - } - } - } else { - for _, name := range res.Msg.Names { - labelNames[name] = 0 - } - } + responses = append(responses, res.Msg) lock.Unlock() return nil })) @@ -1447,21 +1449,7 @@ func LabelNames(ctx context.Context, req *connect.Request[typesv1.LabelNamesRequ return nil, err } - res := &typesv1.LabelNamesResponse{ - Names: make([]string, 0, len(labelNames)), - } - - if includeCardinality { - res.Cardinality = make([]int64, 0, len(labelNames)) - for name, cardinality := range labelNames { - res.Names = append(res.Names, name) - res.Cardinality = append(res.Cardinality, int64(cardinality)) - } - } else { - for name := range labelNames { - res.Names = append(res.Names, name) - } - } + res := util.MergeLabelNames(responses) return res, nil } diff --git a/pkg/phlaredb/head.go b/pkg/phlaredb/head.go index b4fab32c61..07eadf5a39 100644 --- a/pkg/phlaredb/head.go +++ b/pkg/phlaredb/head.go @@ -311,14 +311,18 @@ func (h *Head) LabelNames(ctx context.Context, req *connect.Request[typesv1.Labe }), nil } - // aggregate all label values from series matching, when matchers are given. - values := make(map[string]int64) + // aggregate all label nameSet from series matching, when matchers are given. + nameSet := make(map[string]map[string]struct{}) + includeCardinality := req.Msg.IncludeCardinality != nil && *req.Msg.IncludeCardinality + if err := h.forMatchingSelectors(selectors, func(lbs phlaremodel.Labels, fp model.Fingerprint) error { for _, lbl := range lbs { - if _, ok := values[lbl.Name]; !ok { - values[lbl.Name] = 1 + if includeCardinality { + addToLabelNameMap(nameSet, lbl) } else { - values[lbl.Name]++ + if _, ok := nameSet[lbl.Name]; !ok { + nameSet[lbl.Name] = nil + } } } return nil @@ -327,17 +331,17 @@ func (h *Head) LabelNames(ctx context.Context, req *connect.Request[typesv1.Labe } res := &typesv1.LabelNamesResponse{ - Names: make([]string, 0, len(values)), + Names: make([]string, 0, len(nameSet)), } - if req.Msg.IncludeCardinality != nil && *req.Msg.IncludeCardinality { - res.Cardinality = make([]int64, 0, len(values)) - for name, cardinality := range values { + if includeCardinality { + res.EstimatedCardinality = make([]int64, 0, len(nameSet)) + for name, cardinality := range nameSet { res.Names = append(res.Names, name) - res.Cardinality = append(res.Cardinality, cardinality) + res.EstimatedCardinality = append(res.EstimatedCardinality, int64(len(cardinality))) } } else { - res.Names = lo.Keys(values) + res.Names = lo.Keys(nameSet) } return connect.NewResponse(res), nil @@ -690,3 +694,11 @@ func (h *Head) Meta() *block.Meta { func (h *Head) LocalPathFor(relPath string) string { return filepath.Join(h.localPath, relPath) } + +func addToLabelNameMap(labelNameMap map[string]map[string]struct{}, label *typesv1.LabelPair) map[string]map[string]struct{} { + if _, ok := labelNameMap[label.Name]; !ok { + labelNameMap[label.Name] = make(map[string]struct{}, 1) + } + labelNameMap[label.Name][label.Value] = struct{}{} + return labelNameMap +} diff --git a/pkg/querier/querier.go b/pkg/querier/querier.go index f6f1f6149f..12c73d7aa5 100644 --- a/pkg/querier/querier.go +++ b/pkg/querier/querier.go @@ -1117,47 +1117,10 @@ func uniqueSortedStrings(responses []ResponseFromReplica[[]string]) []string { } func uniqueSortedLabelNames(responses []ResponseFromReplica[*typesv1.LabelNamesResponse]) *typesv1.LabelNamesResponse { - total := 0 - includeCardinality := true - for _, r := range responses { - total += len(r.response.Names) - if len(r.response.Cardinality) != len(r.response.Names) { - includeCardinality = false - } - } - - unique := make(map[string]int64, total) - for _, r := range responses { - for i, name := range r.response.Names { - cardinality := int64(0) - if includeCardinality { - cardinality = r.response.Cardinality[i] - } - - if _, ok := unique[name]; !ok { - unique[name] = cardinality - } else { - unique[name] += cardinality - } - } - } - - res := &typesv1.LabelNamesResponse{ - Names: make([]string, 0, len(unique)), - } - - if includeCardinality { - res.Cardinality = make([]int64, 0, len(unique)) - for name, cardinality := range unique { - res.Names = append(res.Names, name) - res.Cardinality = append(res.Cardinality, cardinality) - } - } else { - for name := range unique { - res.Names = append(res.Names, name) - } + innerResponses := make([]*typesv1.LabelNamesResponse, len(responses)) + for i, r := range responses { + innerResponses[i] = r.response } - util.SortLabelNamesResponse(res) - return res + return util.MergeLabelNames(innerResponses) } diff --git a/pkg/util/labels.go b/pkg/util/labels.go index 82c0fa88ce..092a38af38 100644 --- a/pkg/util/labels.go +++ b/pkg/util/labels.go @@ -3,6 +3,8 @@ package util import ( "github.com/cespare/xxhash/v2" "github.com/prometheus/prometheus/model/labels" + + typesv1 "github.com/grafana/pyroscope/api/gen/proto/go/types/v1" ) var seps = []byte{'\xff'} @@ -33,3 +35,54 @@ func StableHash(ls labels.Labels) uint64 { } return xxhash.Sum64(b) } + +// MergeLabelNames merges multiple LabelNamesResponses into a single response. +// The result is sorted by label name. +func MergeLabelNames(responses []*typesv1.LabelNamesResponse) *typesv1.LabelNamesResponse { + nameCount := 0 + includeCardinality := true + for _, r := range responses { + nameCount += len(r.Names) + + // Cardinality and names should have a 1:1 mapping. If they don't, we + // can assume cardinality was not requested. + if len(r.Names) != len(r.EstimatedCardinality) { + includeCardinality = false + } + } + + uniqueNames := make(map[string]int64, nameCount) + for _, r := range responses { + for i, name := range r.Names { + cardinality := int64(0) + if includeCardinality { + cardinality = r.EstimatedCardinality[i] + } + + if _, ok := uniqueNames[name]; !ok { + uniqueNames[name] = cardinality + } else { + uniqueNames[name] += cardinality + } + } + } + + uniqueRes := &typesv1.LabelNamesResponse{ + Names: make([]string, 0, len(uniqueNames)), + } + + if includeCardinality { + uniqueRes.EstimatedCardinality = make([]int64, 0, len(uniqueNames)) + for name, cardinality := range uniqueNames { + uniqueRes.Names = append(uniqueRes.Names, name) + uniqueRes.EstimatedCardinality = append(uniqueRes.EstimatedCardinality, cardinality) + } + } else { + for name := range uniqueNames { + uniqueRes.Names = append(uniqueRes.Names, name) + } + } + + SortLabelNamesResponse(uniqueRes) + return uniqueRes +} diff --git a/pkg/util/labels_test.go b/pkg/util/labels_test.go new file mode 100644 index 0000000000..ce437e81b5 --- /dev/null +++ b/pkg/util/labels_test.go @@ -0,0 +1,128 @@ +package util + +import ( + "testing" + + "github.com/stretchr/testify/require" + + typesv1 "github.com/grafana/pyroscope/api/gen/proto/go/types/v1" +) + +func TestMergeLabelNames(t *testing.T) { + tests := []struct { + Name string + Responses []*typesv1.LabelNamesResponse + Want *typesv1.LabelNamesResponse + }{ + { + Name: "no_responses", + Responses: []*typesv1.LabelNamesResponse{}, + Want: &typesv1.LabelNamesResponse{ + Names: []string{}, + EstimatedCardinality: []int64{}, + }, + }, + { + Name: "single_response", + Responses: []*typesv1.LabelNamesResponse{ + { + Names: []string{"label_a", "label_b"}, + EstimatedCardinality: []int64{}, + }, + }, + Want: &typesv1.LabelNamesResponse{ + Names: []string{"label_a", "label_b"}, + EstimatedCardinality: nil, + }, + }, + { + Name: "single_response_with_cardinality", + Responses: []*typesv1.LabelNamesResponse{ + { + Names: []string{"label_a", "label_b"}, + EstimatedCardinality: []int64{10, 20}, + }, + }, + Want: &typesv1.LabelNamesResponse{ + Names: []string{"label_a", "label_b"}, + EstimatedCardinality: []int64{10, 20}, + }, + }, + { + Name: "multiple_responses", + Responses: []*typesv1.LabelNamesResponse{ + { + Names: []string{"label_a", "label_b"}, + EstimatedCardinality: []int64{}, + }, + { + Names: []string{"label_b", "label_c"}, + EstimatedCardinality: []int64{}, + }, + }, + Want: &typesv1.LabelNamesResponse{ + Names: []string{"label_a", "label_b", "label_c"}, + EstimatedCardinality: nil, + }, + }, + { + Name: "multiple_responses_with_cardinality", + Responses: []*typesv1.LabelNamesResponse{ + { + Names: []string{"label_a", "label_b"}, + EstimatedCardinality: []int64{10, 20}, + }, + { + Names: []string{"label_b", "label_c"}, + EstimatedCardinality: []int64{5, 6}, + }, + }, + Want: &typesv1.LabelNamesResponse{ + Names: []string{"label_a", "label_b", "label_c"}, + EstimatedCardinality: []int64{10, 25, 6}, + }, + }, + { + Name: "response_missing_cardinality", + Responses: []*typesv1.LabelNamesResponse{ + { + Names: []string{"label_a", "label_b"}, + EstimatedCardinality: []int64{10, 20}, + }, + { + Names: []string{"label_b", "label_c"}, + EstimatedCardinality: []int64{}, + }, + }, + Want: &typesv1.LabelNamesResponse{ + Names: []string{"label_a", "label_b", "label_c"}, + EstimatedCardinality: nil, + }, + }, + { + Name: "multiple_responses_with_empty_response", + Responses: []*typesv1.LabelNamesResponse{ + { + Names: []string{"label_a", "label_b"}, + EstimatedCardinality: []int64{10, 20}, + }, + { + Names: []string{}, + EstimatedCardinality: []int64{}, + }, + }, + Want: &typesv1.LabelNamesResponse{ + Names: []string{"label_a", "label_b"}, + EstimatedCardinality: []int64{10, 20}, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.Name, func(t *testing.T) { + got := MergeLabelNames(tt.Responses) + require.Equal(t, tt.Want.Names, got.Names) + require.Equal(t, tt.Want.EstimatedCardinality, got.EstimatedCardinality) + }) + } +} diff --git a/pkg/util/sort.go b/pkg/util/sort.go index f4c357e2f4..8c7cb30b47 100644 --- a/pkg/util/sort.go +++ b/pkg/util/sort.go @@ -19,11 +19,11 @@ func (s *labelNameCardinalitySort) Less(i, j int) bool { func (s *labelNameCardinalitySort) Swap(i, j int) { s.Names[i], s.Names[j] = s.Names[j], s.Names[i] - s.Cardinality[i], s.Cardinality[j] = s.Cardinality[j], s.Cardinality[i] + s.EstimatedCardinality[i], s.EstimatedCardinality[j] = s.EstimatedCardinality[j], s.EstimatedCardinality[i] } func SortLabelNamesResponse(r *typesv1.LabelNamesResponse) { - if len(r.Cardinality) == 0 { + if len(r.EstimatedCardinality) == 0 { slices.Sort(r.Names) return }