diff --git a/api/gen/proto/go/ingester/v1/ingester.pb.go b/api/gen/proto/go/ingester/v1/ingester.pb.go index 2a872ad8f4..26be1fbef0 100644 --- a/api/gen/proto/go/ingester/v1/ingester.pb.go +++ b/api/gen/proto/go/ingester/v1/ingester.pb.go @@ -381,8 +381,12 @@ type SelectProfilesRequest struct { LabelSelector string `protobuf:"bytes,1,opt,name=label_selector,json=labelSelector,proto3" json:"label_selector,omitempty"` Type *v1.ProfileType `protobuf:"bytes,2,opt,name=type,proto3" json:"type,omitempty"` - Start int64 `protobuf:"varint,3,opt,name=start,proto3" json:"start,omitempty"` - End int64 `protobuf:"varint,4,opt,name=end,proto3" json:"end,omitempty"` + // Milliseconds since epoch. + Start int64 `protobuf:"varint,3,opt,name=start,proto3" json:"start,omitempty"` + // Milliseconds since epoch. + End int64 `protobuf:"varint,4,opt,name=end,proto3" json:"end,omitempty"` + // Optional: Hints for querying + Hints *Hints `protobuf:"bytes,5,opt,name=hints,proto3,oneof" json:"hints,omitempty"` } func (x *SelectProfilesRequest) Reset() { @@ -445,6 +449,13 @@ func (x *SelectProfilesRequest) GetEnd() int64 { return 0 } +func (x *SelectProfilesRequest) GetHints() *Hints { + if x != nil { + return x.Hints + } + return nil +} + type MergeProfilesStacktracesRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1383,6 +1394,218 @@ func (x *MergeProfilesPprofResponse) GetResult() []byte { return nil } +type BlockMetadataRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Milliseconds since epoch. If missing or zero, only the ingesters will be + // queried. + Start int64 `protobuf:"varint,1,opt,name=start,proto3" json:"start,omitempty"` + // Milliseconds since epoch. If missing or zero, only the ingesters will be + // queried. + End int64 `protobuf:"varint,2,opt,name=end,proto3" json:"end,omitempty"` +} + +func (x *BlockMetadataRequest) Reset() { + *x = BlockMetadataRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_ingester_v1_ingester_proto_msgTypes[22] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *BlockMetadataRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BlockMetadataRequest) ProtoMessage() {} + +func (x *BlockMetadataRequest) ProtoReflect() protoreflect.Message { + mi := &file_ingester_v1_ingester_proto_msgTypes[22] + 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 BlockMetadataRequest.ProtoReflect.Descriptor instead. +func (*BlockMetadataRequest) Descriptor() ([]byte, []int) { + return file_ingester_v1_ingester_proto_rawDescGZIP(), []int{22} +} + +func (x *BlockMetadataRequest) GetStart() int64 { + if x != nil { + return x.Start + } + return 0 +} + +func (x *BlockMetadataRequest) GetEnd() int64 { + if x != nil { + return x.End + } + return 0 +} + +type BlockMetadataResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Blocks that are present on the instance for the start to end period + Blocks []*v1.BlockInfo `protobuf:"bytes,1,rep,name=blocks,proto3" json:"blocks,omitempty"` +} + +func (x *BlockMetadataResponse) Reset() { + *x = BlockMetadataResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_ingester_v1_ingester_proto_msgTypes[23] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *BlockMetadataResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BlockMetadataResponse) ProtoMessage() {} + +func (x *BlockMetadataResponse) ProtoReflect() protoreflect.Message { + mi := &file_ingester_v1_ingester_proto_msgTypes[23] + 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 BlockMetadataResponse.ProtoReflect.Descriptor instead. +func (*BlockMetadataResponse) Descriptor() ([]byte, []int) { + return file_ingester_v1_ingester_proto_rawDescGZIP(), []int{23} +} + +func (x *BlockMetadataResponse) GetBlocks() []*v1.BlockInfo { + if x != nil { + return x.Blocks + } + return nil +} + +// Hints are used to propagate information about querying +type Hints struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Block *BlockHints `protobuf:"bytes,1,opt,name=block,proto3" json:"block,omitempty"` +} + +func (x *Hints) Reset() { + *x = Hints{} + if protoimpl.UnsafeEnabled { + mi := &file_ingester_v1_ingester_proto_msgTypes[24] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Hints) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Hints) ProtoMessage() {} + +func (x *Hints) ProtoReflect() protoreflect.Message { + mi := &file_ingester_v1_ingester_proto_msgTypes[24] + 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 Hints.ProtoReflect.Descriptor instead. +func (*Hints) Descriptor() ([]byte, []int) { + return file_ingester_v1_ingester_proto_rawDescGZIP(), []int{24} +} + +func (x *Hints) GetBlock() *BlockHints { + if x != nil { + return x.Block + } + return nil +} + +type BlockHints struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // The ULID of blocks to query + Ulids []string `protobuf:"bytes,1,rep,name=ulids,proto3" json:"ulids,omitempty"` + // When all blocks are compacted, there is no effect of the replication factor, hence we do not need to run deduplication. + Deduplication bool `protobuf:"varint,2,opt,name=deduplication,proto3" json:"deduplication,omitempty"` +} + +func (x *BlockHints) Reset() { + *x = BlockHints{} + if protoimpl.UnsafeEnabled { + mi := &file_ingester_v1_ingester_proto_msgTypes[25] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *BlockHints) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BlockHints) ProtoMessage() {} + +func (x *BlockHints) ProtoReflect() protoreflect.Message { + mi := &file_ingester_v1_ingester_proto_msgTypes[25] + 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 BlockHints.ProtoReflect.Descriptor instead. +func (*BlockHints) Descriptor() ([]byte, []int) { + return file_ingester_v1_ingester_proto_rawDescGZIP(), []int{25} +} + +func (x *BlockHints) GetUlids() []string { + if x != nil { + return x.Ulids + } + return nil +} + +func (x *BlockHints) GetDeduplication() bool { + if x != nil { + return x.Deduplication + } + return false +} + var File_ingester_v1_ingester_proto protoreflect.FileDescriptor var file_ingester_v1_ingester_proto_rawDesc = []byte{ @@ -1415,7 +1638,7 @@ var file_ingester_v1_ingester_proto_rawDesc = []byte{ 0x70, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x52, 0x09, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x53, 0x65, 0x74, 0x22, 0x0e, 0x0a, 0x0c, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x0f, 0x0a, 0x0d, 0x46, 0x6c, 0x75, 0x73, - 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x91, 0x01, 0x0a, 0x15, 0x53, 0x65, + 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xca, 0x01, 0x0a, 0x15, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x25, 0x0a, 0x0e, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6c, 0x61, 0x62, @@ -1424,218 +1647,243 @@ var file_ingester_v1_ingester_proto_rawDesc = []byte{ 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x65, - 0x6e, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x65, 0x6e, 0x64, 0x22, 0xab, 0x01, - 0x0a, 0x1f, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x53, - 0x74, 0x61, 0x63, 0x6b, 0x74, 0x72, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x3c, 0x0a, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x69, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x31, - 0x2e, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x20, 0x0a, 0x09, 0x6d, 0x61, 0x78, 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x03, 0x48, 0x00, 0x52, 0x08, 0x6d, 0x61, 0x78, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x88, 0x01, - 0x01, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x02, 0x20, - 0x03, 0x28, 0x08, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x42, 0x0c, 0x0a, - 0x0a, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x22, 0xe4, 0x01, 0x0a, 0x1e, - 0x4d, 0x65, 0x72, 0x67, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x53, 0x74, 0x61, - 0x63, 0x6b, 0x74, 0x72, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x3b, - 0x0a, 0x06, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x23, - 0x2e, 0x69, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, - 0x63, 0x6b, 0x74, 0x72, 0x61, 0x63, 0x65, 0x73, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x46, 0x6f, 0x72, - 0x6d, 0x61, 0x74, 0x52, 0x06, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x3f, 0x0a, 0x0b, 0x73, - 0x74, 0x61, 0x63, 0x6b, 0x74, 0x72, 0x61, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x1d, 0x2e, 0x69, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, - 0x74, 0x61, 0x63, 0x6b, 0x74, 0x72, 0x61, 0x63, 0x65, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x52, - 0x0b, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x74, 0x72, 0x61, 0x63, 0x65, 0x73, 0x12, 0x25, 0x0a, 0x0e, - 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x02, - 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, - 0x6d, 0x65, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x62, 0x79, 0x74, 0x65, - 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x74, 0x72, 0x65, 0x65, 0x42, 0x79, 0x74, - 0x65, 0x73, 0x22, 0xad, 0x01, 0x0a, 0x20, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x50, 0x72, 0x6f, 0x66, - 0x69, 0x6c, 0x65, 0x73, 0x53, 0x74, 0x61, 0x63, 0x6b, 0x74, 0x72, 0x61, 0x63, 0x65, 0x73, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x44, 0x0a, 0x10, 0x73, 0x65, 0x6c, 0x65, 0x63, - 0x74, 0x65, 0x64, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x18, 0x2e, 0x69, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, - 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x53, 0x65, 0x74, 0x73, 0x52, 0x10, 0x73, 0x65, 0x6c, - 0x65, 0x63, 0x74, 0x65, 0x64, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x43, 0x0a, - 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, - 0x69, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x65, 0x72, 0x67, - 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x53, 0x74, 0x61, 0x63, 0x6b, 0x74, 0x72, - 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, - 0x6c, 0x74, 0x22, 0xb9, 0x01, 0x0a, 0x18, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x53, 0x70, 0x61, - 0x6e, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x25, 0x0a, 0x0e, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, - 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x53, 0x65, - 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x29, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, - 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, - 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x65, 0x6e, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x73, 0x70, 0x61, - 0x6e, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, - 0x52, 0x0c, 0x73, 0x70, 0x61, 0x6e, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x22, 0xa6, - 0x01, 0x0a, 0x17, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x53, 0x70, 0x61, 0x6e, 0x50, 0x72, 0x6f, 0x66, - 0x69, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3f, 0x0a, 0x07, 0x72, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x69, 0x6e, + 0x6e, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x65, 0x6e, 0x64, 0x12, 0x2d, 0x0a, + 0x05, 0x68, 0x69, 0x6e, 0x74, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x69, + 0x6e, 0x67, 0x65, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x48, 0x69, 0x6e, 0x74, 0x73, + 0x48, 0x00, 0x52, 0x05, 0x68, 0x69, 0x6e, 0x74, 0x73, 0x88, 0x01, 0x01, 0x42, 0x08, 0x0a, 0x06, + 0x5f, 0x68, 0x69, 0x6e, 0x74, 0x73, 0x22, 0xab, 0x01, 0x0a, 0x1f, 0x4d, 0x65, 0x72, 0x67, 0x65, + 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x53, 0x74, 0x61, 0x63, 0x6b, 0x74, 0x72, 0x61, + 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3c, 0x0a, 0x07, 0x72, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x69, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, - 0x53, 0x70, 0x61, 0x6e, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x52, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x20, 0x0a, 0x09, 0x6d, - 0x61, 0x78, 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x48, 0x00, - 0x52, 0x08, 0x6d, 0x61, 0x78, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x88, 0x01, 0x01, 0x12, 0x1a, 0x0a, - 0x08, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x08, 0x52, - 0x08, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x6d, 0x61, - 0x78, 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x22, 0x9d, 0x01, 0x0a, 0x18, 0x4d, 0x65, 0x72, 0x67, - 0x65, 0x53, 0x70, 0x61, 0x6e, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x44, 0x0a, 0x10, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, - 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, - 0x2e, 0x69, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, - 0x66, 0x69, 0x6c, 0x65, 0x53, 0x65, 0x74, 0x73, 0x52, 0x10, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, - 0x65, 0x64, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x3b, 0x0a, 0x06, 0x72, 0x65, - 0x73, 0x75, 0x6c, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x69, 0x6e, 0x67, - 0x65, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x53, 0x70, - 0x61, 0x6e, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, - 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x37, 0x0a, 0x16, 0x4d, 0x65, 0x72, 0x67, 0x65, - 0x53, 0x70, 0x61, 0x6e, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x75, 0x6c, - 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x74, 0x72, 0x65, 0x65, 0x42, 0x79, 0x74, 0x65, 0x73, - 0x22, 0x77, 0x0a, 0x0b, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x53, 0x65, 0x74, 0x73, 0x12, - 0x30, 0x0a, 0x0a, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x53, 0x65, 0x74, 0x73, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, - 0x61, 0x62, 0x65, 0x6c, 0x73, 0x52, 0x0a, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x53, 0x65, 0x74, - 0x73, 0x12, 0x36, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x02, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x69, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, - 0x31, 0x2e, 0x53, 0x65, 0x72, 0x69, 0x65, 0x73, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, - 0x08, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x22, 0x4d, 0x0a, 0x0d, 0x53, 0x65, 0x72, - 0x69, 0x65, 0x73, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x6c, 0x61, - 0x62, 0x65, 0x6c, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, - 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, - 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, - 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0xd0, 0x01, 0x0a, 0x07, 0x50, 0x72, 0x6f, - 0x66, 0x69, 0x6c, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x02, 0x49, 0x44, 0x12, 0x29, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, - 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, - 0x2b, 0x0a, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x03, 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, 0x12, 0x1c, 0x0a, 0x09, - 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x3f, 0x0a, 0x0b, 0x73, 0x74, - 0x61, 0x63, 0x6b, 0x74, 0x72, 0x61, 0x63, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x1d, 0x2e, 0x69, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, - 0x61, 0x63, 0x6b, 0x74, 0x72, 0x61, 0x63, 0x65, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x52, 0x0b, - 0x73, 0x74, 0x61, 0x63, 0x6b, 0x74, 0x72, 0x61, 0x63, 0x65, 0x73, 0x22, 0x4b, 0x0a, 0x10, 0x53, - 0x74, 0x61, 0x63, 0x6b, 0x74, 0x72, 0x61, 0x63, 0x65, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x12, - 0x21, 0x0a, 0x0c, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x73, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x05, 0x52, 0x0b, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, - 0x64, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x86, 0x01, 0x0a, 0x1a, 0x4d, 0x65, 0x72, - 0x67, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, + 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, + 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x20, 0x0a, 0x09, 0x6d, 0x61, 0x78, 0x5f, + 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x48, 0x00, 0x52, 0x08, 0x6d, + 0x61, 0x78, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x88, 0x01, 0x01, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, + 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x08, 0x52, 0x08, 0x70, 0x72, + 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x6e, + 0x6f, 0x64, 0x65, 0x73, 0x22, 0xe4, 0x01, 0x0a, 0x1e, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x50, 0x72, + 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x53, 0x74, 0x61, 0x63, 0x6b, 0x74, 0x72, 0x61, 0x63, 0x65, + 0x73, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x3b, 0x0a, 0x06, 0x66, 0x6f, 0x72, 0x6d, 0x61, + 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x23, 0x2e, 0x69, 0x6e, 0x67, 0x65, 0x73, 0x74, + 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x63, 0x6b, 0x74, 0x72, 0x61, 0x63, 0x65, + 0x73, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x52, 0x06, 0x66, 0x6f, + 0x72, 0x6d, 0x61, 0x74, 0x12, 0x3f, 0x0a, 0x0b, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x74, 0x72, 0x61, + 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x69, 0x6e, 0x67, 0x65, + 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x63, 0x6b, 0x74, 0x72, 0x61, + 0x63, 0x65, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x52, 0x0b, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x74, + 0x72, 0x61, 0x63, 0x65, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x66, + 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x1d, 0x0a, 0x0a, + 0x74, 0x72, 0x65, 0x65, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, + 0x52, 0x09, 0x74, 0x72, 0x65, 0x65, 0x42, 0x79, 0x74, 0x65, 0x73, 0x22, 0xad, 0x01, 0x0a, 0x20, + 0x4d, 0x65, 0x72, 0x67, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x53, 0x74, 0x61, + 0x63, 0x6b, 0x74, 0x72, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x44, 0x0a, 0x10, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x50, 0x72, 0x6f, 0x66, + 0x69, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x69, 0x6e, 0x67, + 0x65, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, + 0x53, 0x65, 0x74, 0x73, 0x52, 0x10, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x50, 0x72, + 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x43, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x69, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x65, + 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, + 0x65, 0x73, 0x53, 0x74, 0x61, 0x63, 0x6b, 0x74, 0x72, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, + 0x75, 0x6c, 0x74, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0xb9, 0x01, 0x0a, 0x18, + 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x53, 0x70, 0x61, 0x6e, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, + 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x25, 0x0a, 0x0e, 0x6c, 0x61, 0x62, 0x65, + 0x6c, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0d, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, + 0x29, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, + 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, + 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, + 0x61, 0x72, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, + 0x12, 0x10, 0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x65, + 0x6e, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x73, 0x70, 0x61, 0x6e, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, + 0x74, 0x6f, 0x72, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x73, 0x70, 0x61, 0x6e, 0x53, + 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x22, 0xa6, 0x01, 0x0a, 0x17, 0x4d, 0x65, 0x72, 0x67, + 0x65, 0x53, 0x70, 0x61, 0x6e, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x3f, 0x0a, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x69, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x65, 0x72, 0x2e, + 0x76, 0x31, 0x2e, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x53, 0x70, 0x61, 0x6e, 0x50, 0x72, 0x6f, + 0x66, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x07, 0x72, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x20, 0x0a, 0x09, 0x6d, 0x61, 0x78, 0x5f, 0x6e, 0x6f, 0x64, 0x65, + 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x48, 0x00, 0x52, 0x08, 0x6d, 0x61, 0x78, 0x4e, 0x6f, + 0x64, 0x65, 0x73, 0x88, 0x01, 0x01, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, + 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x08, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, + 0x65, 0x73, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x73, + 0x22, 0x9d, 0x01, 0x0a, 0x18, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x53, 0x70, 0x61, 0x6e, 0x50, 0x72, + 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x44, 0x0a, + 0x10, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, + 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x69, 0x6e, 0x67, 0x65, 0x73, 0x74, + 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x53, 0x65, 0x74, + 0x73, 0x52, 0x10, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x50, 0x72, 0x6f, 0x66, 0x69, + 0x6c, 0x65, 0x73, 0x12, 0x3b, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x69, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, + 0x31, 0x2e, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x53, 0x70, 0x61, 0x6e, 0x50, 0x72, 0x6f, 0x66, 0x69, + 0x6c, 0x65, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, + 0x22, 0x37, 0x0a, 0x16, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x53, 0x70, 0x61, 0x6e, 0x50, 0x72, 0x6f, + 0x66, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x74, 0x72, + 0x65, 0x65, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, + 0x74, 0x72, 0x65, 0x65, 0x42, 0x79, 0x74, 0x65, 0x73, 0x22, 0x77, 0x0a, 0x0b, 0x50, 0x72, 0x6f, + 0x66, 0x69, 0x6c, 0x65, 0x53, 0x65, 0x74, 0x73, 0x12, 0x30, 0x0a, 0x0a, 0x6c, 0x61, 0x62, 0x65, + 0x6c, 0x73, 0x53, 0x65, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x74, + 0x79, 0x70, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x52, 0x0a, + 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x53, 0x65, 0x74, 0x73, 0x12, 0x36, 0x0a, 0x08, 0x70, 0x72, + 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x69, + 0x6e, 0x67, 0x65, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x72, 0x69, 0x65, + 0x73, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, + 0x65, 0x73, 0x22, 0x4d, 0x0a, 0x0d, 0x53, 0x65, 0x72, 0x69, 0x65, 0x73, 0x50, 0x72, 0x6f, 0x66, + 0x69, 0x6c, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x49, 0x6e, 0x64, 0x65, + 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x49, 0x6e, + 0x64, 0x65, 0x78, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, + 0x70, 0x22, 0xd0, 0x01, 0x0a, 0x07, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x0e, 0x0a, + 0x02, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x49, 0x44, 0x12, 0x29, 0x0a, + 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x74, 0x79, + 0x70, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x54, 0x79, + 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x2b, 0x0a, 0x06, 0x6c, 0x61, 0x62, 0x65, + 0x6c, 0x73, 0x18, 0x03, 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, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, + 0x6d, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, + 0x61, 0x6d, 0x70, 0x12, 0x3f, 0x0a, 0x0b, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x74, 0x72, 0x61, 0x63, + 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x69, 0x6e, 0x67, 0x65, 0x73, + 0x74, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x63, 0x6b, 0x74, 0x72, 0x61, 0x63, + 0x65, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x52, 0x0b, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x74, 0x72, + 0x61, 0x63, 0x65, 0x73, 0x22, 0x4b, 0x0a, 0x10, 0x53, 0x74, 0x61, 0x63, 0x6b, 0x74, 0x72, 0x61, + 0x63, 0x65, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x66, 0x75, 0x6e, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x05, 0x52, 0x0b, + 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x22, 0x86, 0x01, 0x0a, 0x1a, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, + 0x6c, 0x65, 0x73, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x3c, 0x0a, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x22, 0x2e, 0x69, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, + 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, + 0x0a, 0x02, 0x62, 0x79, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x02, 0x62, 0x79, 0x12, 0x1a, + 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x08, + 0x52, 0x08, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x22, 0x8d, 0x01, 0x0a, 0x1b, 0x4d, + 0x65, 0x72, 0x67, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x4c, 0x61, 0x62, 0x65, + 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x44, 0x0a, 0x10, 0x73, 0x65, + 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x69, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x65, 0x72, 0x2e, + 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x53, 0x65, 0x74, 0x73, 0x52, 0x10, + 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, + 0x12, 0x28, 0x0a, 0x06, 0x73, 0x65, 0x72, 0x69, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x10, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x72, 0x69, + 0x65, 0x73, 0x52, 0x06, 0x73, 0x65, 0x72, 0x69, 0x65, 0x73, 0x22, 0x75, 0x0a, 0x19, 0x4d, 0x65, + 0x72, 0x67, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x50, 0x70, 0x72, 0x6f, 0x66, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3c, 0x0a, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x69, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x07, 0x72, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x62, 0x79, 0x18, 0x02, 0x20, 0x03, 0x28, - 0x09, 0x52, 0x02, 0x62, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, - 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x08, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, - 0x73, 0x22, 0x8d, 0x01, 0x0a, 0x1b, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, - 0x6c, 0x65, 0x73, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x44, 0x0a, 0x10, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x50, 0x72, 0x6f, - 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x69, 0x6e, - 0x67, 0x65, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, - 0x65, 0x53, 0x65, 0x74, 0x73, 0x52, 0x10, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x50, - 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x28, 0x0a, 0x06, 0x73, 0x65, 0x72, 0x69, 0x65, - 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, - 0x76, 0x31, 0x2e, 0x53, 0x65, 0x72, 0x69, 0x65, 0x73, 0x52, 0x06, 0x73, 0x65, 0x72, 0x69, 0x65, - 0x73, 0x22, 0x75, 0x0a, 0x19, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, - 0x65, 0x73, 0x50, 0x70, 0x72, 0x6f, 0x66, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3c, - 0x0a, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x22, 0x2e, 0x69, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, - 0x6c, 0x65, 0x63, 0x74, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x52, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, - 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x08, 0x52, 0x08, - 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x22, 0x7a, 0x0a, 0x1a, 0x4d, 0x65, 0x72, 0x67, - 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x50, 0x70, 0x72, 0x6f, 0x66, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x44, 0x0a, 0x10, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, - 0x65, 0x64, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x18, 0x2e, 0x69, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x50, - 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x53, 0x65, 0x74, 0x73, 0x52, 0x10, 0x73, 0x65, 0x6c, 0x65, - 0x63, 0x74, 0x65, 0x64, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x16, 0x0a, 0x06, - 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x72, 0x65, - 0x73, 0x75, 0x6c, 0x74, 0x2a, 0x6b, 0x0a, 0x16, 0x53, 0x74, 0x61, 0x63, 0x6b, 0x74, 0x72, 0x61, - 0x63, 0x65, 0x73, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x1c, - 0x0a, 0x18, 0x4d, 0x45, 0x52, 0x47, 0x45, 0x5f, 0x46, 0x4f, 0x52, 0x4d, 0x41, 0x54, 0x5f, 0x55, - 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1c, 0x0a, 0x18, - 0x4d, 0x45, 0x52, 0x47, 0x45, 0x5f, 0x46, 0x4f, 0x52, 0x4d, 0x41, 0x54, 0x5f, 0x53, 0x54, 0x41, - 0x43, 0x4b, 0x54, 0x52, 0x41, 0x43, 0x45, 0x53, 0x10, 0x01, 0x12, 0x15, 0x0a, 0x11, 0x4d, 0x45, - 0x52, 0x47, 0x45, 0x5f, 0x46, 0x4f, 0x52, 0x4d, 0x41, 0x54, 0x5f, 0x54, 0x52, 0x45, 0x45, 0x10, - 0x02, 0x32, 0x82, 0x07, 0x0a, 0x0f, 0x49, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x65, 0x72, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x35, 0x0a, 0x04, 0x50, 0x75, 0x73, 0x68, 0x12, 0x14, 0x2e, - 0x70, 0x75, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x75, 0x73, 0x68, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x70, 0x75, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x75, - 0x73, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4c, 0x0a, 0x0b, - 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x1c, 0x2e, 0x74, 0x79, - 0x70, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x56, 0x61, 0x6c, 0x75, - 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x74, 0x79, 0x70, 0x65, - 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x49, 0x0a, 0x0a, 0x4c, 0x61, - 0x62, 0x65, 0x6c, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x1b, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, - 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x76, 0x31, - 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x55, 0x0a, 0x0c, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, - 0x54, 0x79, 0x70, 0x65, 0x73, 0x12, 0x20, 0x2e, 0x69, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x65, 0x72, - 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x69, 0x6e, 0x67, 0x65, 0x73, 0x74, - 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x54, 0x79, 0x70, - 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x43, 0x0a, 0x06, - 0x53, 0x65, 0x72, 0x69, 0x65, 0x73, 0x12, 0x1a, 0x2e, 0x69, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x65, - 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x72, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x69, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x31, - 0x2e, 0x53, 0x65, 0x72, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x00, 0x12, 0x40, 0x0a, 0x05, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x12, 0x19, 0x2e, 0x69, 0x6e, 0x67, - 0x65, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x69, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x65, 0x72, - 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x00, 0x12, 0x7d, 0x0a, 0x18, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x50, 0x72, 0x6f, 0x66, - 0x69, 0x6c, 0x65, 0x73, 0x53, 0x74, 0x61, 0x63, 0x6b, 0x74, 0x72, 0x61, 0x63, 0x65, 0x73, 0x12, - 0x2c, 0x2e, 0x69, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x65, - 0x72, 0x67, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x53, 0x74, 0x61, 0x63, 0x6b, - 0x74, 0x72, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, - 0x69, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x65, 0x72, 0x67, - 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x53, 0x74, 0x61, 0x63, 0x6b, 0x74, 0x72, - 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x28, 0x01, - 0x30, 0x01, 0x12, 0x6e, 0x0a, 0x13, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, - 0x6c, 0x65, 0x73, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x12, 0x27, 0x2e, 0x69, 0x6e, 0x67, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, + 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x08, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, + 0x73, 0x22, 0x7a, 0x0a, 0x1a, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, + 0x65, 0x73, 0x50, 0x70, 0x72, 0x6f, 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x44, 0x0a, 0x10, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x50, 0x72, 0x6f, 0x66, 0x69, + 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x69, 0x6e, 0x67, 0x65, + 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x53, + 0x65, 0x74, 0x73, 0x52, 0x10, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x50, 0x72, 0x6f, + 0x66, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x3e, 0x0a, + 0x14, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x65, + 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x65, 0x6e, 0x64, 0x22, 0x44, 0x0a, + 0x15, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2b, 0x0a, 0x06, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x76, + 0x31, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x06, 0x62, 0x6c, 0x6f, + 0x63, 0x6b, 0x73, 0x22, 0x36, 0x0a, 0x05, 0x48, 0x69, 0x6e, 0x74, 0x73, 0x12, 0x2d, 0x0a, 0x05, + 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x69, 0x6e, + 0x67, 0x65, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, + 0x69, 0x6e, 0x74, 0x73, 0x52, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x22, 0x48, 0x0a, 0x0a, 0x42, + 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x69, 0x6e, 0x74, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x75, 0x6c, 0x69, + 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x75, 0x6c, 0x69, 0x64, 0x73, 0x12, + 0x24, 0x0a, 0x0d, 0x64, 0x65, 0x64, 0x75, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x64, 0x65, 0x64, 0x75, 0x70, 0x6c, 0x69, 0x63, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2a, 0x6b, 0x0a, 0x16, 0x53, 0x74, 0x61, 0x63, 0x6b, 0x74, 0x72, + 0x61, 0x63, 0x65, 0x73, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, + 0x1c, 0x0a, 0x18, 0x4d, 0x45, 0x52, 0x47, 0x45, 0x5f, 0x46, 0x4f, 0x52, 0x4d, 0x41, 0x54, 0x5f, + 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1c, 0x0a, + 0x18, 0x4d, 0x45, 0x52, 0x47, 0x45, 0x5f, 0x46, 0x4f, 0x52, 0x4d, 0x41, 0x54, 0x5f, 0x53, 0x54, + 0x41, 0x43, 0x4b, 0x54, 0x52, 0x41, 0x43, 0x45, 0x53, 0x10, 0x01, 0x12, 0x15, 0x0a, 0x11, 0x4d, + 0x45, 0x52, 0x47, 0x45, 0x5f, 0x46, 0x4f, 0x52, 0x4d, 0x41, 0x54, 0x5f, 0x54, 0x52, 0x45, 0x45, + 0x10, 0x02, 0x32, 0xdc, 0x07, 0x0a, 0x0f, 0x49, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x65, 0x72, 0x53, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x35, 0x0a, 0x04, 0x50, 0x75, 0x73, 0x68, 0x12, 0x14, + 0x2e, 0x70, 0x75, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x75, 0x73, 0x68, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x70, 0x75, 0x73, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x50, + 0x75, 0x73, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4c, 0x0a, + 0x0b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x1c, 0x2e, 0x74, + 0x79, 0x70, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x74, 0x79, 0x70, + 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x49, 0x0a, 0x0a, 0x4c, + 0x61, 0x62, 0x65, 0x6c, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x1b, 0x2e, 0x74, 0x79, 0x70, 0x65, + 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x76, + 0x31, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x55, 0x0a, 0x0c, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, + 0x65, 0x54, 0x79, 0x70, 0x65, 0x73, 0x12, 0x20, 0x2e, 0x69, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x65, + 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x69, 0x6e, 0x67, 0x65, 0x73, + 0x74, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x54, 0x79, + 0x70, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x43, 0x0a, + 0x06, 0x53, 0x65, 0x72, 0x69, 0x65, 0x73, 0x12, 0x1a, 0x2e, 0x69, 0x6e, 0x67, 0x65, 0x73, 0x74, + 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x72, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x69, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, + 0x31, 0x2e, 0x53, 0x65, 0x72, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x00, 0x12, 0x40, 0x0a, 0x05, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x12, 0x19, 0x2e, 0x69, 0x6e, + 0x67, 0x65, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x69, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x65, + 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x00, 0x12, 0x7d, 0x0a, 0x18, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x50, 0x72, 0x6f, + 0x66, 0x69, 0x6c, 0x65, 0x73, 0x53, 0x74, 0x61, 0x63, 0x6b, 0x74, 0x72, 0x61, 0x63, 0x65, 0x73, + 0x12, 0x2c, 0x2e, 0x69, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4d, + 0x65, 0x72, 0x67, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x53, 0x74, 0x61, 0x63, + 0x6b, 0x74, 0x72, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, + 0x2e, 0x69, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x65, 0x72, + 0x67, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x53, 0x74, 0x61, 0x63, 0x6b, 0x74, + 0x72, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x28, + 0x01, 0x30, 0x01, 0x12, 0x6e, 0x0a, 0x13, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x50, 0x72, 0x6f, 0x66, + 0x69, 0x6c, 0x65, 0x73, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x12, 0x27, 0x2e, 0x69, 0x6e, 0x67, + 0x65, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x50, 0x72, + 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x69, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, + 0x31, 0x2e, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x4c, + 0x61, 0x62, 0x65, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x28, + 0x01, 0x30, 0x01, 0x12, 0x6b, 0x0a, 0x12, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x50, 0x72, 0x6f, 0x66, + 0x69, 0x6c, 0x65, 0x73, 0x50, 0x70, 0x72, 0x6f, 0x66, 0x12, 0x26, 0x2e, 0x69, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x50, 0x72, 0x6f, - 0x66, 0x69, 0x6c, 0x65, 0x73, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x69, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x31, - 0x2e, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x4c, 0x61, - 0x62, 0x65, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x28, 0x01, - 0x30, 0x01, 0x12, 0x6b, 0x0a, 0x12, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, - 0x6c, 0x65, 0x73, 0x50, 0x70, 0x72, 0x6f, 0x66, 0x12, 0x26, 0x2e, 0x69, 0x6e, 0x67, 0x65, 0x73, - 0x74, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x50, 0x72, 0x6f, 0x66, - 0x69, 0x6c, 0x65, 0x73, 0x50, 0x70, 0x72, 0x6f, 0x66, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x27, 0x2e, 0x69, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4d, - 0x65, 0x72, 0x67, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x50, 0x70, 0x72, 0x6f, - 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x28, 0x01, 0x30, 0x01, 0x12, - 0x65, 0x0a, 0x10, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x53, 0x70, 0x61, 0x6e, 0x50, 0x72, 0x6f, 0x66, - 0x69, 0x6c, 0x65, 0x12, 0x24, 0x2e, 0x69, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, - 0x31, 0x2e, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x53, 0x70, 0x61, 0x6e, 0x50, 0x72, 0x6f, 0x66, 0x69, - 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x69, 0x6e, 0x67, 0x65, - 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x53, 0x70, 0x61, - 0x6e, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x00, 0x28, 0x01, 0x30, 0x01, 0x42, 0xb3, 0x01, 0x0a, 0x0f, 0x63, 0x6f, 0x6d, 0x2e, 0x69, - 0x6e, 0x67, 0x65, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x42, 0x0d, 0x49, 0x6e, 0x67, 0x65, - 0x73, 0x74, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x44, 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, 0x69, 0x6e, 0x67, 0x65, 0x73, - 0x74, 0x65, 0x72, 0x2f, 0x76, 0x31, 0x3b, 0x69, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x65, 0x72, 0x76, - 0x31, 0xa2, 0x02, 0x03, 0x49, 0x58, 0x58, 0xaa, 0x02, 0x0b, 0x49, 0x6e, 0x67, 0x65, 0x73, 0x74, - 0x65, 0x72, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x0b, 0x49, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x65, 0x72, - 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x17, 0x49, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x65, 0x72, 0x5c, 0x56, - 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x0c, - 0x49, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x65, 0x72, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x33, + 0x66, 0x69, 0x6c, 0x65, 0x73, 0x50, 0x70, 0x72, 0x6f, 0x66, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x27, 0x2e, 0x69, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, + 0x4d, 0x65, 0x72, 0x67, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x50, 0x70, 0x72, + 0x6f, 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x28, 0x01, 0x30, 0x01, + 0x12, 0x65, 0x0a, 0x10, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x53, 0x70, 0x61, 0x6e, 0x50, 0x72, 0x6f, + 0x66, 0x69, 0x6c, 0x65, 0x12, 0x24, 0x2e, 0x69, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x65, 0x72, 0x2e, + 0x76, 0x31, 0x2e, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x53, 0x70, 0x61, 0x6e, 0x50, 0x72, 0x6f, 0x66, + 0x69, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x69, 0x6e, 0x67, + 0x65, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x53, 0x70, + 0x61, 0x6e, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x00, 0x28, 0x01, 0x30, 0x01, 0x12, 0x58, 0x0a, 0x0d, 0x42, 0x6c, 0x6f, 0x63, 0x6b, + 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x21, 0x2e, 0x69, 0x6e, 0x67, 0x65, 0x73, + 0x74, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x4d, 0x65, 0x74, 0x61, + 0x64, 0x61, 0x74, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x69, 0x6e, + 0x67, 0x65, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x4d, + 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x00, 0x42, 0xb3, 0x01, 0x0a, 0x0f, 0x63, 0x6f, 0x6d, 0x2e, 0x69, 0x6e, 0x67, 0x65, 0x73, 0x74, + 0x65, 0x72, 0x2e, 0x76, 0x31, 0x42, 0x0d, 0x49, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x65, 0x72, 0x50, + 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x44, 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, 0x69, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x65, 0x72, 0x2f, 0x76, + 0x31, 0x3b, 0x69, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x65, 0x72, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x49, + 0x58, 0x58, 0xaa, 0x02, 0x0b, 0x49, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x56, 0x31, + 0xca, 0x02, 0x0b, 0x49, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x65, 0x72, 0x5c, 0x56, 0x31, 0xe2, 0x02, + 0x17, 0x49, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x65, 0x72, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, + 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x0c, 0x49, 0x6e, 0x67, 0x65, 0x73, + 0x74, 0x65, 0x72, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1651,7 +1899,7 @@ func file_ingester_v1_ingester_proto_rawDescGZIP() []byte { } var file_ingester_v1_ingester_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_ingester_v1_ingester_proto_msgTypes = make([]protoimpl.MessageInfo, 22) +var file_ingester_v1_ingester_proto_msgTypes = make([]protoimpl.MessageInfo, 26) var file_ingester_v1_ingester_proto_goTypes = []interface{}{ (StacktracesMergeFormat)(0), // 0: ingester.v1.StacktracesMergeFormat (*ProfileTypesRequest)(nil), // 1: ingester.v1.ProfileTypesRequest @@ -1676,65 +1924,75 @@ var file_ingester_v1_ingester_proto_goTypes = []interface{}{ (*MergeProfilesLabelsResponse)(nil), // 20: ingester.v1.MergeProfilesLabelsResponse (*MergeProfilesPprofRequest)(nil), // 21: ingester.v1.MergeProfilesPprofRequest (*MergeProfilesPprofResponse)(nil), // 22: ingester.v1.MergeProfilesPprofResponse - (*v1.ProfileType)(nil), // 23: types.v1.ProfileType - (*v1.Labels)(nil), // 24: types.v1.Labels - (*v1.LabelPair)(nil), // 25: types.v1.LabelPair - (*v1.Series)(nil), // 26: types.v1.Series - (*v11.PushRequest)(nil), // 27: push.v1.PushRequest - (*v1.LabelValuesRequest)(nil), // 28: types.v1.LabelValuesRequest - (*v1.LabelNamesRequest)(nil), // 29: types.v1.LabelNamesRequest - (*v11.PushResponse)(nil), // 30: push.v1.PushResponse - (*v1.LabelValuesResponse)(nil), // 31: types.v1.LabelValuesResponse - (*v1.LabelNamesResponse)(nil), // 32: types.v1.LabelNamesResponse + (*BlockMetadataRequest)(nil), // 23: ingester.v1.BlockMetadataRequest + (*BlockMetadataResponse)(nil), // 24: ingester.v1.BlockMetadataResponse + (*Hints)(nil), // 25: ingester.v1.Hints + (*BlockHints)(nil), // 26: ingester.v1.BlockHints + (*v1.ProfileType)(nil), // 27: types.v1.ProfileType + (*v1.Labels)(nil), // 28: types.v1.Labels + (*v1.LabelPair)(nil), // 29: types.v1.LabelPair + (*v1.Series)(nil), // 30: types.v1.Series + (*v1.BlockInfo)(nil), // 31: types.v1.BlockInfo + (*v11.PushRequest)(nil), // 32: push.v1.PushRequest + (*v1.LabelValuesRequest)(nil), // 33: types.v1.LabelValuesRequest + (*v1.LabelNamesRequest)(nil), // 34: types.v1.LabelNamesRequest + (*v11.PushResponse)(nil), // 35: push.v1.PushResponse + (*v1.LabelValuesResponse)(nil), // 36: types.v1.LabelValuesResponse + (*v1.LabelNamesResponse)(nil), // 37: types.v1.LabelNamesResponse } var file_ingester_v1_ingester_proto_depIdxs = []int32{ - 23, // 0: ingester.v1.ProfileTypesResponse.profile_types:type_name -> types.v1.ProfileType - 24, // 1: ingester.v1.SeriesResponse.labels_set:type_name -> types.v1.Labels - 23, // 2: ingester.v1.SelectProfilesRequest.type:type_name -> types.v1.ProfileType - 7, // 3: ingester.v1.MergeProfilesStacktracesRequest.request:type_name -> ingester.v1.SelectProfilesRequest - 0, // 4: ingester.v1.MergeProfilesStacktracesResult.format:type_name -> ingester.v1.StacktracesMergeFormat - 18, // 5: ingester.v1.MergeProfilesStacktracesResult.stacktraces:type_name -> ingester.v1.StacktraceSample - 15, // 6: ingester.v1.MergeProfilesStacktracesResponse.selectedProfiles:type_name -> ingester.v1.ProfileSets - 9, // 7: ingester.v1.MergeProfilesStacktracesResponse.result:type_name -> ingester.v1.MergeProfilesStacktracesResult - 23, // 8: ingester.v1.SelectSpanProfileRequest.type:type_name -> types.v1.ProfileType - 11, // 9: ingester.v1.MergeSpanProfileRequest.request:type_name -> ingester.v1.SelectSpanProfileRequest - 15, // 10: ingester.v1.MergeSpanProfileResponse.selectedProfiles:type_name -> ingester.v1.ProfileSets - 14, // 11: ingester.v1.MergeSpanProfileResponse.result:type_name -> ingester.v1.MergeSpanProfileResult - 24, // 12: ingester.v1.ProfileSets.labelsSets:type_name -> types.v1.Labels - 16, // 13: ingester.v1.ProfileSets.profiles:type_name -> ingester.v1.SeriesProfile - 23, // 14: ingester.v1.Profile.type:type_name -> types.v1.ProfileType - 25, // 15: ingester.v1.Profile.labels:type_name -> types.v1.LabelPair - 18, // 16: ingester.v1.Profile.stacktraces:type_name -> ingester.v1.StacktraceSample - 7, // 17: ingester.v1.MergeProfilesLabelsRequest.request:type_name -> ingester.v1.SelectProfilesRequest - 15, // 18: ingester.v1.MergeProfilesLabelsResponse.selectedProfiles:type_name -> ingester.v1.ProfileSets - 26, // 19: ingester.v1.MergeProfilesLabelsResponse.series:type_name -> types.v1.Series - 7, // 20: ingester.v1.MergeProfilesPprofRequest.request:type_name -> ingester.v1.SelectProfilesRequest - 15, // 21: ingester.v1.MergeProfilesPprofResponse.selectedProfiles:type_name -> ingester.v1.ProfileSets - 27, // 22: ingester.v1.IngesterService.Push:input_type -> push.v1.PushRequest - 28, // 23: ingester.v1.IngesterService.LabelValues:input_type -> types.v1.LabelValuesRequest - 29, // 24: ingester.v1.IngesterService.LabelNames:input_type -> types.v1.LabelNamesRequest - 1, // 25: ingester.v1.IngesterService.ProfileTypes:input_type -> ingester.v1.ProfileTypesRequest - 3, // 26: ingester.v1.IngesterService.Series:input_type -> ingester.v1.SeriesRequest - 5, // 27: ingester.v1.IngesterService.Flush:input_type -> ingester.v1.FlushRequest - 8, // 28: ingester.v1.IngesterService.MergeProfilesStacktraces:input_type -> ingester.v1.MergeProfilesStacktracesRequest - 19, // 29: ingester.v1.IngesterService.MergeProfilesLabels:input_type -> ingester.v1.MergeProfilesLabelsRequest - 21, // 30: ingester.v1.IngesterService.MergeProfilesPprof:input_type -> ingester.v1.MergeProfilesPprofRequest - 12, // 31: ingester.v1.IngesterService.MergeSpanProfile:input_type -> ingester.v1.MergeSpanProfileRequest - 30, // 32: ingester.v1.IngesterService.Push:output_type -> push.v1.PushResponse - 31, // 33: ingester.v1.IngesterService.LabelValues:output_type -> types.v1.LabelValuesResponse - 32, // 34: ingester.v1.IngesterService.LabelNames:output_type -> types.v1.LabelNamesResponse - 2, // 35: ingester.v1.IngesterService.ProfileTypes:output_type -> ingester.v1.ProfileTypesResponse - 4, // 36: ingester.v1.IngesterService.Series:output_type -> ingester.v1.SeriesResponse - 6, // 37: ingester.v1.IngesterService.Flush:output_type -> ingester.v1.FlushResponse - 10, // 38: ingester.v1.IngesterService.MergeProfilesStacktraces:output_type -> ingester.v1.MergeProfilesStacktracesResponse - 20, // 39: ingester.v1.IngesterService.MergeProfilesLabels:output_type -> ingester.v1.MergeProfilesLabelsResponse - 22, // 40: ingester.v1.IngesterService.MergeProfilesPprof:output_type -> ingester.v1.MergeProfilesPprofResponse - 13, // 41: ingester.v1.IngesterService.MergeSpanProfile:output_type -> ingester.v1.MergeSpanProfileResponse - 32, // [32:42] is the sub-list for method output_type - 22, // [22:32] is the sub-list for method input_type - 22, // [22:22] is the sub-list for extension type_name - 22, // [22:22] is the sub-list for extension extendee - 0, // [0:22] is the sub-list for field type_name + 27, // 0: ingester.v1.ProfileTypesResponse.profile_types:type_name -> types.v1.ProfileType + 28, // 1: ingester.v1.SeriesResponse.labels_set:type_name -> types.v1.Labels + 27, // 2: ingester.v1.SelectProfilesRequest.type:type_name -> types.v1.ProfileType + 25, // 3: ingester.v1.SelectProfilesRequest.hints:type_name -> ingester.v1.Hints + 7, // 4: ingester.v1.MergeProfilesStacktracesRequest.request:type_name -> ingester.v1.SelectProfilesRequest + 0, // 5: ingester.v1.MergeProfilesStacktracesResult.format:type_name -> ingester.v1.StacktracesMergeFormat + 18, // 6: ingester.v1.MergeProfilesStacktracesResult.stacktraces:type_name -> ingester.v1.StacktraceSample + 15, // 7: ingester.v1.MergeProfilesStacktracesResponse.selectedProfiles:type_name -> ingester.v1.ProfileSets + 9, // 8: ingester.v1.MergeProfilesStacktracesResponse.result:type_name -> ingester.v1.MergeProfilesStacktracesResult + 27, // 9: ingester.v1.SelectSpanProfileRequest.type:type_name -> types.v1.ProfileType + 11, // 10: ingester.v1.MergeSpanProfileRequest.request:type_name -> ingester.v1.SelectSpanProfileRequest + 15, // 11: ingester.v1.MergeSpanProfileResponse.selectedProfiles:type_name -> ingester.v1.ProfileSets + 14, // 12: ingester.v1.MergeSpanProfileResponse.result:type_name -> ingester.v1.MergeSpanProfileResult + 28, // 13: ingester.v1.ProfileSets.labelsSets:type_name -> types.v1.Labels + 16, // 14: ingester.v1.ProfileSets.profiles:type_name -> ingester.v1.SeriesProfile + 27, // 15: ingester.v1.Profile.type:type_name -> types.v1.ProfileType + 29, // 16: ingester.v1.Profile.labels:type_name -> types.v1.LabelPair + 18, // 17: ingester.v1.Profile.stacktraces:type_name -> ingester.v1.StacktraceSample + 7, // 18: ingester.v1.MergeProfilesLabelsRequest.request:type_name -> ingester.v1.SelectProfilesRequest + 15, // 19: ingester.v1.MergeProfilesLabelsResponse.selectedProfiles:type_name -> ingester.v1.ProfileSets + 30, // 20: ingester.v1.MergeProfilesLabelsResponse.series:type_name -> types.v1.Series + 7, // 21: ingester.v1.MergeProfilesPprofRequest.request:type_name -> ingester.v1.SelectProfilesRequest + 15, // 22: ingester.v1.MergeProfilesPprofResponse.selectedProfiles:type_name -> ingester.v1.ProfileSets + 31, // 23: ingester.v1.BlockMetadataResponse.blocks:type_name -> types.v1.BlockInfo + 26, // 24: ingester.v1.Hints.block:type_name -> ingester.v1.BlockHints + 32, // 25: ingester.v1.IngesterService.Push:input_type -> push.v1.PushRequest + 33, // 26: ingester.v1.IngesterService.LabelValues:input_type -> types.v1.LabelValuesRequest + 34, // 27: ingester.v1.IngesterService.LabelNames:input_type -> types.v1.LabelNamesRequest + 1, // 28: ingester.v1.IngesterService.ProfileTypes:input_type -> ingester.v1.ProfileTypesRequest + 3, // 29: ingester.v1.IngesterService.Series:input_type -> ingester.v1.SeriesRequest + 5, // 30: ingester.v1.IngesterService.Flush:input_type -> ingester.v1.FlushRequest + 8, // 31: ingester.v1.IngesterService.MergeProfilesStacktraces:input_type -> ingester.v1.MergeProfilesStacktracesRequest + 19, // 32: ingester.v1.IngesterService.MergeProfilesLabels:input_type -> ingester.v1.MergeProfilesLabelsRequest + 21, // 33: ingester.v1.IngesterService.MergeProfilesPprof:input_type -> ingester.v1.MergeProfilesPprofRequest + 12, // 34: ingester.v1.IngesterService.MergeSpanProfile:input_type -> ingester.v1.MergeSpanProfileRequest + 23, // 35: ingester.v1.IngesterService.BlockMetadata:input_type -> ingester.v1.BlockMetadataRequest + 35, // 36: ingester.v1.IngesterService.Push:output_type -> push.v1.PushResponse + 36, // 37: ingester.v1.IngesterService.LabelValues:output_type -> types.v1.LabelValuesResponse + 37, // 38: ingester.v1.IngesterService.LabelNames:output_type -> types.v1.LabelNamesResponse + 2, // 39: ingester.v1.IngesterService.ProfileTypes:output_type -> ingester.v1.ProfileTypesResponse + 4, // 40: ingester.v1.IngesterService.Series:output_type -> ingester.v1.SeriesResponse + 6, // 41: ingester.v1.IngesterService.Flush:output_type -> ingester.v1.FlushResponse + 10, // 42: ingester.v1.IngesterService.MergeProfilesStacktraces:output_type -> ingester.v1.MergeProfilesStacktracesResponse + 20, // 43: ingester.v1.IngesterService.MergeProfilesLabels:output_type -> ingester.v1.MergeProfilesLabelsResponse + 22, // 44: ingester.v1.IngesterService.MergeProfilesPprof:output_type -> ingester.v1.MergeProfilesPprofResponse + 13, // 45: ingester.v1.IngesterService.MergeSpanProfile:output_type -> ingester.v1.MergeSpanProfileResponse + 24, // 46: ingester.v1.IngesterService.BlockMetadata:output_type -> ingester.v1.BlockMetadataResponse + 36, // [36:47] is the sub-list for method output_type + 25, // [25:36] is the sub-list for method input_type + 25, // [25:25] is the sub-list for extension type_name + 25, // [25:25] is the sub-list for extension extendee + 0, // [0:25] is the sub-list for field type_name } func init() { file_ingester_v1_ingester_proto_init() } @@ -2007,7 +2265,56 @@ func file_ingester_v1_ingester_proto_init() { return nil } } + file_ingester_v1_ingester_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*BlockMetadataRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_ingester_v1_ingester_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*BlockMetadataResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_ingester_v1_ingester_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Hints); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_ingester_v1_ingester_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*BlockHints); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } + file_ingester_v1_ingester_proto_msgTypes[6].OneofWrappers = []interface{}{} file_ingester_v1_ingester_proto_msgTypes[7].OneofWrappers = []interface{}{} file_ingester_v1_ingester_proto_msgTypes[11].OneofWrappers = []interface{}{} type x struct{} @@ -2016,7 +2323,7 @@ func file_ingester_v1_ingester_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_ingester_v1_ingester_proto_rawDesc, NumEnums: 1, - NumMessages: 22, + NumMessages: 26, NumExtensions: 0, NumServices: 1, }, diff --git a/api/gen/proto/go/ingester/v1/ingester_vtproto.pb.go b/api/gen/proto/go/ingester/v1/ingester_vtproto.pb.go index 47d40a14f7..3ab46510ca 100644 --- a/api/gen/proto/go/ingester/v1/ingester_vtproto.pb.go +++ b/api/gen/proto/go/ingester/v1/ingester_vtproto.pb.go @@ -167,6 +167,7 @@ func (m *SelectProfilesRequest) CloneVT() *SelectProfilesRequest { LabelSelector: m.LabelSelector, Start: m.Start, End: m.End, + Hints: m.Hints.CloneVT(), } if rhs := m.Type; rhs != nil { if vtpb, ok := interface{}(rhs).(interface{ CloneVT() *v1.ProfileType }); ok { @@ -589,6 +590,93 @@ func (m *MergeProfilesPprofResponse) CloneMessageVT() proto.Message { return m.CloneVT() } +func (m *BlockMetadataRequest) CloneVT() *BlockMetadataRequest { + if m == nil { + return (*BlockMetadataRequest)(nil) + } + r := &BlockMetadataRequest{ + Start: m.Start, + End: m.End, + } + if len(m.unknownFields) > 0 { + r.unknownFields = make([]byte, len(m.unknownFields)) + copy(r.unknownFields, m.unknownFields) + } + return r +} + +func (m *BlockMetadataRequest) CloneMessageVT() proto.Message { + return m.CloneVT() +} + +func (m *BlockMetadataResponse) CloneVT() *BlockMetadataResponse { + if m == nil { + return (*BlockMetadataResponse)(nil) + } + r := &BlockMetadataResponse{} + if rhs := m.Blocks; rhs != nil { + tmpContainer := make([]*v1.BlockInfo, len(rhs)) + for k, v := range rhs { + if vtpb, ok := interface{}(v).(interface{ CloneVT() *v1.BlockInfo }); ok { + tmpContainer[k] = vtpb.CloneVT() + } else { + tmpContainer[k] = proto.Clone(v).(*v1.BlockInfo) + } + } + r.Blocks = tmpContainer + } + if len(m.unknownFields) > 0 { + r.unknownFields = make([]byte, len(m.unknownFields)) + copy(r.unknownFields, m.unknownFields) + } + return r +} + +func (m *BlockMetadataResponse) CloneMessageVT() proto.Message { + return m.CloneVT() +} + +func (m *Hints) CloneVT() *Hints { + if m == nil { + return (*Hints)(nil) + } + r := &Hints{ + Block: m.Block.CloneVT(), + } + if len(m.unknownFields) > 0 { + r.unknownFields = make([]byte, len(m.unknownFields)) + copy(r.unknownFields, m.unknownFields) + } + return r +} + +func (m *Hints) CloneMessageVT() proto.Message { + return m.CloneVT() +} + +func (m *BlockHints) CloneVT() *BlockHints { + if m == nil { + return (*BlockHints)(nil) + } + r := &BlockHints{ + Deduplication: m.Deduplication, + } + if rhs := m.Ulids; rhs != nil { + tmpContainer := make([]string, len(rhs)) + copy(tmpContainer, rhs) + r.Ulids = tmpContainer + } + if len(m.unknownFields) > 0 { + r.unknownFields = make([]byte, len(m.unknownFields)) + copy(r.unknownFields, m.unknownFields) + } + return r +} + +func (m *BlockHints) CloneMessageVT() proto.Message { + return m.CloneVT() +} + // This is a compile-time assertion to ensure that this generated file // is compatible with the grpc package it is being compiled against. // Requires gRPC-Go v1.32.0 or later. @@ -608,6 +696,7 @@ type IngesterServiceClient interface { MergeProfilesLabels(ctx context.Context, opts ...grpc.CallOption) (IngesterService_MergeProfilesLabelsClient, error) MergeProfilesPprof(ctx context.Context, opts ...grpc.CallOption) (IngesterService_MergeProfilesPprofClient, error) MergeSpanProfile(ctx context.Context, opts ...grpc.CallOption) (IngesterService_MergeSpanProfileClient, error) + BlockMetadata(ctx context.Context, in *BlockMetadataRequest, opts ...grpc.CallOption) (*BlockMetadataResponse, error) } type ingesterServiceClient struct { @@ -796,6 +885,15 @@ func (x *ingesterServiceMergeSpanProfileClient) Recv() (*MergeSpanProfileRespons return m, nil } +func (c *ingesterServiceClient) BlockMetadata(ctx context.Context, in *BlockMetadataRequest, opts ...grpc.CallOption) (*BlockMetadataResponse, error) { + out := new(BlockMetadataResponse) + err := c.cc.Invoke(ctx, "/ingester.v1.IngesterService/BlockMetadata", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // IngesterServiceServer is the server API for IngesterService service. // All implementations must embed UnimplementedIngesterServiceServer // for forward compatibility @@ -810,6 +908,7 @@ type IngesterServiceServer interface { MergeProfilesLabels(IngesterService_MergeProfilesLabelsServer) error MergeProfilesPprof(IngesterService_MergeProfilesPprofServer) error MergeSpanProfile(IngesterService_MergeSpanProfileServer) error + BlockMetadata(context.Context, *BlockMetadataRequest) (*BlockMetadataResponse, error) mustEmbedUnimplementedIngesterServiceServer() } @@ -847,6 +946,9 @@ func (UnimplementedIngesterServiceServer) MergeProfilesPprof(IngesterService_Mer func (UnimplementedIngesterServiceServer) MergeSpanProfile(IngesterService_MergeSpanProfileServer) error { return status.Errorf(codes.Unimplemented, "method MergeSpanProfile not implemented") } +func (UnimplementedIngesterServiceServer) BlockMetadata(context.Context, *BlockMetadataRequest) (*BlockMetadataResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method BlockMetadata not implemented") +} func (UnimplementedIngesterServiceServer) mustEmbedUnimplementedIngesterServiceServer() {} // UnsafeIngesterServiceServer may be embedded to opt out of forward compatibility for this service. @@ -1072,6 +1174,24 @@ func (x *ingesterServiceMergeSpanProfileServer) Recv() (*MergeSpanProfileRequest return m, nil } +func _IngesterService_BlockMetadata_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(BlockMetadataRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(IngesterServiceServer).BlockMetadata(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/ingester.v1.IngesterService/BlockMetadata", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(IngesterServiceServer).BlockMetadata(ctx, req.(*BlockMetadataRequest)) + } + return interceptor(ctx, in, info, handler) +} + // IngesterService_ServiceDesc is the grpc.ServiceDesc for IngesterService service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) @@ -1103,6 +1223,10 @@ var IngesterService_ServiceDesc = grpc.ServiceDesc{ MethodName: "Flush", Handler: _IngesterService_Flush_Handler, }, + { + MethodName: "BlockMetadata", + Handler: _IngesterService_BlockMetadata_Handler, + }, }, Streams: []grpc.StreamDesc{ { @@ -1447,6 +1571,16 @@ func (m *SelectProfilesRequest) MarshalToSizedBufferVT(dAtA []byte) (int, error) i -= len(m.unknownFields) copy(dAtA[i:], m.unknownFields) } + if m.Hints != nil { + size, err := m.Hints.MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x2a + } if m.End != 0 { i = encodeVarint(dAtA, i, uint64(m.End)) i-- @@ -2416,136 +2550,331 @@ func (m *MergeProfilesPprofResponse) MarshalToSizedBufferVT(dAtA []byte) (int, e return len(dAtA) - i, nil } -func encodeVarint(dAtA []byte, offset int, v uint64) int { - offset -= sov(v) - base := offset - for v >= 1<<7 { - dAtA[offset] = uint8(v&0x7f | 0x80) - v >>= 7 - offset++ - } - dAtA[offset] = uint8(v) - return base -} -func (m *ProfileTypesRequest) SizeVT() (n int) { +func (m *BlockMetadataRequest) MarshalVT() (dAtA []byte, err error) { if m == nil { - return 0 - } - var l int - _ = l - if m.Start != 0 { - n += 1 + sov(uint64(m.Start)) + return nil, nil } - if m.End != 0 { - n += 1 + sov(uint64(m.End)) + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err } - n += len(m.unknownFields) - return n + return dAtA[:n], nil } -func (m *ProfileTypesResponse) SizeVT() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if len(m.ProfileTypes) > 0 { - for _, e := range m.ProfileTypes { - if size, ok := interface{}(e).(interface { - SizeVT() int - }); ok { - l = size.SizeVT() - } else { - l = proto.Size(e) - } - n += 1 + l + sov(uint64(l)) - } - } - n += len(m.unknownFields) - return n +func (m *BlockMetadataRequest) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) } -func (m *SeriesRequest) SizeVT() (n int) { +func (m *BlockMetadataRequest) MarshalToSizedBufferVT(dAtA []byte) (int, error) { if m == nil { - return 0 + return 0, nil } + i := len(dAtA) + _ = i var l int _ = l - if len(m.Matchers) > 0 { - for _, s := range m.Matchers { - l = len(s) - n += 1 + l + sov(uint64(l)) - } + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) } - if len(m.LabelNames) > 0 { - for _, s := range m.LabelNames { - l = len(s) - n += 1 + l + sov(uint64(l)) - } + if m.End != 0 { + i = encodeVarint(dAtA, i, uint64(m.End)) + i-- + dAtA[i] = 0x10 } if m.Start != 0 { - n += 1 + sov(uint64(m.Start)) + i = encodeVarint(dAtA, i, uint64(m.Start)) + i-- + dAtA[i] = 0x8 } - if m.End != 0 { - n += 1 + sov(uint64(m.End)) + return len(dAtA) - i, nil +} + +func (m *BlockMetadataResponse) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil } - n += len(m.unknownFields) - return n + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil } -func (m *SeriesResponse) SizeVT() (n int) { +func (m *BlockMetadataResponse) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *BlockMetadataResponse) MarshalToSizedBufferVT(dAtA []byte) (int, error) { if m == nil { - return 0 + return 0, nil } + i := len(dAtA) + _ = i var l int _ = l - if len(m.LabelsSet) > 0 { - for _, e := range m.LabelsSet { - if size, ok := interface{}(e).(interface { - SizeVT() int + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if len(m.Blocks) > 0 { + for iNdEx := len(m.Blocks) - 1; iNdEx >= 0; iNdEx-- { + if vtmsg, ok := interface{}(m.Blocks[iNdEx]).(interface { + MarshalToSizedBufferVT([]byte) (int, error) }); ok { - l = size.SizeVT() + size, err := vtmsg.MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarint(dAtA, i, uint64(size)) } else { - l = proto.Size(e) + encoded, err := proto.Marshal(m.Blocks[iNdEx]) + if err != nil { + return 0, err + } + i -= len(encoded) + copy(dAtA[i:], encoded) + i = encodeVarint(dAtA, i, uint64(len(encoded))) } - n += 1 + l + sov(uint64(l)) + i-- + dAtA[i] = 0xa } } - n += len(m.unknownFields) - return n + return len(dAtA) - i, nil } -func (m *FlushRequest) SizeVT() (n int) { +func (m *Hints) MarshalVT() (dAtA []byte, err error) { if m == nil { - return 0 + return nil, nil } - var l int - _ = l - n += len(m.unknownFields) - return n + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil } -func (m *FlushResponse) SizeVT() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - n += len(m.unknownFields) - return n +func (m *Hints) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) } -func (m *SelectProfilesRequest) SizeVT() (n int) { +func (m *Hints) MarshalToSizedBufferVT(dAtA []byte) (int, error) { if m == nil { - return 0 + return 0, nil } + i := len(dAtA) + _ = i var l int _ = l - l = len(m.LabelSelector) - if l > 0 { - n += 1 + l + sov(uint64(l)) - } - if m.Type != nil { + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if m.Block != nil { + size, err := m.Block.MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *BlockHints) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *BlockHints) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *BlockHints) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if m.Deduplication { + i-- + if m.Deduplication { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x10 + } + if len(m.Ulids) > 0 { + for iNdEx := len(m.Ulids) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.Ulids[iNdEx]) + copy(dAtA[i:], m.Ulids[iNdEx]) + i = encodeVarint(dAtA, i, uint64(len(m.Ulids[iNdEx]))) + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func encodeVarint(dAtA []byte, offset int, v uint64) int { + offset -= sov(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *ProfileTypesRequest) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Start != 0 { + n += 1 + sov(uint64(m.Start)) + } + if m.End != 0 { + n += 1 + sov(uint64(m.End)) + } + n += len(m.unknownFields) + return n +} + +func (m *ProfileTypesResponse) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.ProfileTypes) > 0 { + for _, e := range m.ProfileTypes { + if size, ok := interface{}(e).(interface { + SizeVT() int + }); ok { + l = size.SizeVT() + } else { + l = proto.Size(e) + } + n += 1 + l + sov(uint64(l)) + } + } + n += len(m.unknownFields) + return n +} + +func (m *SeriesRequest) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Matchers) > 0 { + for _, s := range m.Matchers { + l = len(s) + n += 1 + l + sov(uint64(l)) + } + } + if len(m.LabelNames) > 0 { + for _, s := range m.LabelNames { + l = len(s) + n += 1 + l + sov(uint64(l)) + } + } + if m.Start != 0 { + n += 1 + sov(uint64(m.Start)) + } + if m.End != 0 { + n += 1 + sov(uint64(m.End)) + } + n += len(m.unknownFields) + return n +} + +func (m *SeriesResponse) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.LabelsSet) > 0 { + for _, e := range m.LabelsSet { + if size, ok := interface{}(e).(interface { + SizeVT() int + }); ok { + l = size.SizeVT() + } else { + l = proto.Size(e) + } + n += 1 + l + sov(uint64(l)) + } + } + n += len(m.unknownFields) + return n +} + +func (m *FlushRequest) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + n += len(m.unknownFields) + return n +} + +func (m *FlushResponse) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + n += len(m.unknownFields) + return n +} + +func (m *SelectProfilesRequest) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.LabelSelector) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } + if m.Type != nil { if size, ok := interface{}(m.Type).(interface { SizeVT() int }); ok { @@ -2561,6 +2890,10 @@ func (m *SelectProfilesRequest) SizeVT() (n int) { if m.End != 0 { n += 1 + sov(uint64(m.End)) } + if m.Hints != nil { + l = m.Hints.SizeVT() + n += 1 + l + sov(uint64(l)) + } n += len(m.unknownFields) return n } @@ -2913,6 +3246,77 @@ func (m *MergeProfilesPprofResponse) SizeVT() (n int) { return n } +func (m *BlockMetadataRequest) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Start != 0 { + n += 1 + sov(uint64(m.Start)) + } + if m.End != 0 { + n += 1 + sov(uint64(m.End)) + } + n += len(m.unknownFields) + return n +} + +func (m *BlockMetadataResponse) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Blocks) > 0 { + for _, e := range m.Blocks { + if size, ok := interface{}(e).(interface { + SizeVT() int + }); ok { + l = size.SizeVT() + } else { + l = proto.Size(e) + } + n += 1 + l + sov(uint64(l)) + } + } + n += len(m.unknownFields) + return n +} + +func (m *Hints) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Block != nil { + l = m.Block.SizeVT() + n += 1 + l + sov(uint64(l)) + } + n += len(m.unknownFields) + return n +} + +func (m *BlockHints) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Ulids) > 0 { + for _, s := range m.Ulids { + l = len(s) + n += 1 + l + sov(uint64(l)) + } + } + if m.Deduplication { + n += 2 + } + n += len(m.unknownFields) + return n +} + func sov(x uint64) (n int) { return (bits.Len64(x|1) + 6) / 7 } @@ -3592,14 +3996,50 @@ func (m *SelectProfilesRequest) UnmarshalVT(dAtA []byte) error { break } } - default: - iNdEx = preIndex - skippy, err := skip(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLength + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Hints", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Hints == nil { + m.Hints = &Hints{} + } + if err := m.Hints.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLength } if (iNdEx + skippy) > l { return io.ErrUnexpectedEOF @@ -5846,6 +6286,378 @@ func (m *MergeProfilesPprofResponse) UnmarshalVT(dAtA []byte) error { } return nil } +func (m *BlockMetadataRequest) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: BlockMetadataRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: BlockMetadataRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Start", wireType) + } + m.Start = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Start |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field End", wireType) + } + m.End = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.End |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *BlockMetadataResponse) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: BlockMetadataResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: BlockMetadataResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Blocks", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Blocks = append(m.Blocks, &v1.BlockInfo{}) + if unmarshal, ok := interface{}(m.Blocks[len(m.Blocks)-1]).(interface { + UnmarshalVT([]byte) error + }); ok { + if err := unmarshal.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + } else { + if err := proto.Unmarshal(dAtA[iNdEx:postIndex], m.Blocks[len(m.Blocks)-1]); err != nil { + return err + } + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Hints) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Hints: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Hints: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Block", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Block == nil { + m.Block = &BlockHints{} + } + if err := m.Block.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *BlockHints) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: BlockHints: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: BlockHints: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Ulids", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Ulids = append(m.Ulids, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Deduplication", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.Deduplication = bool(v != 0) + default: + iNdEx = preIndex + skippy, err := skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skip(dAtA []byte) (n int, err error) { l := len(dAtA) diff --git a/api/gen/proto/go/ingester/v1/ingesterv1connect/ingester.connect.go b/api/gen/proto/go/ingester/v1/ingesterv1connect/ingester.connect.go index 360442c3d2..2b5be27c19 100644 --- a/api/gen/proto/go/ingester/v1/ingesterv1connect/ingester.connect.go +++ b/api/gen/proto/go/ingester/v1/ingesterv1connect/ingester.connect.go @@ -62,6 +62,9 @@ const ( // IngesterServiceMergeSpanProfileProcedure is the fully-qualified name of the IngesterService's // MergeSpanProfile RPC. IngesterServiceMergeSpanProfileProcedure = "/ingester.v1.IngesterService/MergeSpanProfile" + // IngesterServiceBlockMetadataProcedure is the fully-qualified name of the IngesterService's + // BlockMetadata RPC. + IngesterServiceBlockMetadataProcedure = "/ingester.v1.IngesterService/BlockMetadata" ) // IngesterServiceClient is a client for the ingester.v1.IngesterService service. @@ -76,6 +79,7 @@ type IngesterServiceClient interface { MergeProfilesLabels(context.Context) *connect_go.BidiStreamForClient[v12.MergeProfilesLabelsRequest, v12.MergeProfilesLabelsResponse] MergeProfilesPprof(context.Context) *connect_go.BidiStreamForClient[v12.MergeProfilesPprofRequest, v12.MergeProfilesPprofResponse] MergeSpanProfile(context.Context) *connect_go.BidiStreamForClient[v12.MergeSpanProfileRequest, v12.MergeSpanProfileResponse] + BlockMetadata(context.Context, *connect_go.Request[v12.BlockMetadataRequest]) (*connect_go.Response[v12.BlockMetadataResponse], error) } // NewIngesterServiceClient constructs a client for the ingester.v1.IngesterService service. By @@ -138,6 +142,11 @@ func NewIngesterServiceClient(httpClient connect_go.HTTPClient, baseURL string, baseURL+IngesterServiceMergeSpanProfileProcedure, opts..., ), + blockMetadata: connect_go.NewClient[v12.BlockMetadataRequest, v12.BlockMetadataResponse]( + httpClient, + baseURL+IngesterServiceBlockMetadataProcedure, + opts..., + ), } } @@ -153,6 +162,7 @@ type ingesterServiceClient struct { mergeProfilesLabels *connect_go.Client[v12.MergeProfilesLabelsRequest, v12.MergeProfilesLabelsResponse] mergeProfilesPprof *connect_go.Client[v12.MergeProfilesPprofRequest, v12.MergeProfilesPprofResponse] mergeSpanProfile *connect_go.Client[v12.MergeSpanProfileRequest, v12.MergeSpanProfileResponse] + blockMetadata *connect_go.Client[v12.BlockMetadataRequest, v12.BlockMetadataResponse] } // Push calls ingester.v1.IngesterService.Push. @@ -205,6 +215,11 @@ func (c *ingesterServiceClient) MergeSpanProfile(ctx context.Context) *connect_g return c.mergeSpanProfile.CallBidiStream(ctx) } +// BlockMetadata calls ingester.v1.IngesterService.BlockMetadata. +func (c *ingesterServiceClient) BlockMetadata(ctx context.Context, req *connect_go.Request[v12.BlockMetadataRequest]) (*connect_go.Response[v12.BlockMetadataResponse], error) { + return c.blockMetadata.CallUnary(ctx, req) +} + // IngesterServiceHandler is an implementation of the ingester.v1.IngesterService service. type IngesterServiceHandler interface { Push(context.Context, *connect_go.Request[v1.PushRequest]) (*connect_go.Response[v1.PushResponse], error) @@ -217,6 +232,7 @@ type IngesterServiceHandler interface { MergeProfilesLabels(context.Context, *connect_go.BidiStream[v12.MergeProfilesLabelsRequest, v12.MergeProfilesLabelsResponse]) error MergeProfilesPprof(context.Context, *connect_go.BidiStream[v12.MergeProfilesPprofRequest, v12.MergeProfilesPprofResponse]) error MergeSpanProfile(context.Context, *connect_go.BidiStream[v12.MergeSpanProfileRequest, v12.MergeSpanProfileResponse]) error + BlockMetadata(context.Context, *connect_go.Request[v12.BlockMetadataRequest]) (*connect_go.Response[v12.BlockMetadataResponse], error) } // NewIngesterServiceHandler builds an HTTP handler from the service implementation. It returns the @@ -275,6 +291,11 @@ func NewIngesterServiceHandler(svc IngesterServiceHandler, opts ...connect_go.Ha svc.MergeSpanProfile, opts..., ) + ingesterServiceBlockMetadataHandler := connect_go.NewUnaryHandler( + IngesterServiceBlockMetadataProcedure, + svc.BlockMetadata, + opts..., + ) return "/ingester.v1.IngesterService/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { switch r.URL.Path { case IngesterServicePushProcedure: @@ -297,6 +318,8 @@ func NewIngesterServiceHandler(svc IngesterServiceHandler, opts ...connect_go.Ha ingesterServiceMergeProfilesPprofHandler.ServeHTTP(w, r) case IngesterServiceMergeSpanProfileProcedure: ingesterServiceMergeSpanProfileHandler.ServeHTTP(w, r) + case IngesterServiceBlockMetadataProcedure: + ingesterServiceBlockMetadataHandler.ServeHTTP(w, r) default: http.NotFound(w, r) } @@ -345,3 +368,7 @@ func (UnimplementedIngesterServiceHandler) MergeProfilesPprof(context.Context, * func (UnimplementedIngesterServiceHandler) MergeSpanProfile(context.Context, *connect_go.BidiStream[v12.MergeSpanProfileRequest, v12.MergeSpanProfileResponse]) error { return connect_go.NewError(connect_go.CodeUnimplemented, errors.New("ingester.v1.IngesterService.MergeSpanProfile is not implemented")) } + +func (UnimplementedIngesterServiceHandler) BlockMetadata(context.Context, *connect_go.Request[v12.BlockMetadataRequest]) (*connect_go.Response[v12.BlockMetadataResponse], error) { + return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("ingester.v1.IngesterService.BlockMetadata is not implemented")) +} diff --git a/api/gen/proto/go/ingester/v1/ingesterv1connect/ingester.connect.mux.go b/api/gen/proto/go/ingester/v1/ingesterv1connect/ingester.connect.mux.go index 9541da2b85..2898f77a72 100644 --- a/api/gen/proto/go/ingester/v1/ingesterv1connect/ingester.connect.mux.go +++ b/api/gen/proto/go/ingester/v1/ingesterv1connect/ingester.connect.mux.go @@ -69,4 +69,9 @@ func RegisterIngesterServiceHandler(mux *mux.Router, svc IngesterServiceHandler, svc.MergeSpanProfile, opts..., )) + mux.Handle("/ingester.v1.IngesterService/BlockMetadata", connect_go.NewUnaryHandler( + "/ingester.v1.IngesterService/BlockMetadata", + svc.BlockMetadata, + opts..., + )) } diff --git a/api/gen/proto/go/storegateway/v1/storegateway.pb.go b/api/gen/proto/go/storegateway/v1/storegateway.pb.go index 32a375fb71..757fdc86a5 100644 --- a/api/gen/proto/go/storegateway/v1/storegateway.pb.go +++ b/api/gen/proto/go/storegateway/v1/storegateway.pb.go @@ -35,7 +35,7 @@ var file_storegateway_v1_storegateway_proto_rawDesc = []byte{ 0x73, 0x74, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x12, 0x70, 0x75, 0x73, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x75, 0x73, 0x68, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x14, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x32, 0x8d, 0x06, 0x0a, 0x13, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x47, 0x61, + 0x72, 0x6f, 0x74, 0x6f, 0x32, 0xe7, 0x06, 0x0a, 0x13, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x7d, 0x0a, 0x18, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x53, 0x74, 0x61, 0x63, 0x6b, 0x74, 0x72, 0x61, 0x63, 0x65, 0x73, 0x12, 0x2c, 0x2e, 0x69, 0x6e, 0x67, 0x65, 0x73, @@ -84,21 +84,26 @@ var file_storegateway_v1_storegateway_proto_rawDesc = []byte{ 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x72, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x69, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x72, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x00, 0x42, 0xd3, 0x01, 0x0a, 0x13, 0x63, 0x6f, 0x6d, 0x2e, 0x73, 0x74, 0x6f, - 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x76, 0x31, 0x42, 0x11, 0x53, 0x74, - 0x6f, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, - 0x01, 0x5a, 0x4c, 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, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2f, 0x76, 0x31, - 0x3b, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x76, 0x31, 0xa2, - 0x02, 0x03, 0x53, 0x58, 0x58, 0xaa, 0x02, 0x0f, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x67, 0x61, 0x74, - 0x65, 0x77, 0x61, 0x79, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x0f, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x67, - 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x1b, 0x53, 0x74, 0x6f, 0x72, - 0x65, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, - 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x10, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x67, - 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x33, + 0x73, 0x65, 0x22, 0x00, 0x12, 0x58, 0x0a, 0x0d, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x4d, 0x65, 0x74, + 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x21, 0x2e, 0x69, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x65, 0x72, + 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, + 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x69, 0x6e, 0x67, 0x65, 0x73, + 0x74, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x4d, 0x65, 0x74, 0x61, + 0x64, 0x61, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0xd3, + 0x01, 0x0a, 0x13, 0x63, 0x6f, 0x6d, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, + 0x77, 0x61, 0x79, 0x2e, 0x76, 0x31, 0x42, 0x11, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x67, 0x61, 0x74, + 0x65, 0x77, 0x61, 0x79, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x4c, 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, 0x73, 0x74, 0x6f, 0x72, 0x65, + 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2f, 0x76, 0x31, 0x3b, 0x73, 0x74, 0x6f, 0x72, 0x65, + 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x53, 0x58, 0x58, 0xaa, + 0x02, 0x0f, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x56, + 0x31, 0xca, 0x02, 0x0f, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, + 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x1b, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x77, + 0x61, 0x79, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, + 0x61, 0xea, 0x02, 0x10, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, + 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var file_storegateway_v1_storegateway_proto_goTypes = []interface{}{ @@ -110,14 +115,16 @@ var file_storegateway_v1_storegateway_proto_goTypes = []interface{}{ (*v11.LabelValuesRequest)(nil), // 5: types.v1.LabelValuesRequest (*v11.LabelNamesRequest)(nil), // 6: types.v1.LabelNamesRequest (*v1.SeriesRequest)(nil), // 7: ingester.v1.SeriesRequest - (*v1.MergeProfilesStacktracesResponse)(nil), // 8: ingester.v1.MergeProfilesStacktracesResponse - (*v1.MergeProfilesLabelsResponse)(nil), // 9: ingester.v1.MergeProfilesLabelsResponse - (*v1.MergeProfilesPprofResponse)(nil), // 10: ingester.v1.MergeProfilesPprofResponse - (*v1.MergeSpanProfileResponse)(nil), // 11: ingester.v1.MergeSpanProfileResponse - (*v1.ProfileTypesResponse)(nil), // 12: ingester.v1.ProfileTypesResponse - (*v11.LabelValuesResponse)(nil), // 13: types.v1.LabelValuesResponse - (*v11.LabelNamesResponse)(nil), // 14: types.v1.LabelNamesResponse - (*v1.SeriesResponse)(nil), // 15: ingester.v1.SeriesResponse + (*v1.BlockMetadataRequest)(nil), // 8: ingester.v1.BlockMetadataRequest + (*v1.MergeProfilesStacktracesResponse)(nil), // 9: ingester.v1.MergeProfilesStacktracesResponse + (*v1.MergeProfilesLabelsResponse)(nil), // 10: ingester.v1.MergeProfilesLabelsResponse + (*v1.MergeProfilesPprofResponse)(nil), // 11: ingester.v1.MergeProfilesPprofResponse + (*v1.MergeSpanProfileResponse)(nil), // 12: ingester.v1.MergeSpanProfileResponse + (*v1.ProfileTypesResponse)(nil), // 13: ingester.v1.ProfileTypesResponse + (*v11.LabelValuesResponse)(nil), // 14: types.v1.LabelValuesResponse + (*v11.LabelNamesResponse)(nil), // 15: types.v1.LabelNamesResponse + (*v1.SeriesResponse)(nil), // 16: ingester.v1.SeriesResponse + (*v1.BlockMetadataResponse)(nil), // 17: ingester.v1.BlockMetadataResponse } var file_storegateway_v1_storegateway_proto_depIdxs = []int32{ 0, // 0: storegateway.v1.StoreGatewayService.MergeProfilesStacktraces:input_type -> ingester.v1.MergeProfilesStacktracesRequest @@ -128,16 +135,18 @@ var file_storegateway_v1_storegateway_proto_depIdxs = []int32{ 5, // 5: storegateway.v1.StoreGatewayService.LabelValues:input_type -> types.v1.LabelValuesRequest 6, // 6: storegateway.v1.StoreGatewayService.LabelNames:input_type -> types.v1.LabelNamesRequest 7, // 7: storegateway.v1.StoreGatewayService.Series:input_type -> ingester.v1.SeriesRequest - 8, // 8: storegateway.v1.StoreGatewayService.MergeProfilesStacktraces:output_type -> ingester.v1.MergeProfilesStacktracesResponse - 9, // 9: storegateway.v1.StoreGatewayService.MergeProfilesLabels:output_type -> ingester.v1.MergeProfilesLabelsResponse - 10, // 10: storegateway.v1.StoreGatewayService.MergeProfilesPprof:output_type -> ingester.v1.MergeProfilesPprofResponse - 11, // 11: storegateway.v1.StoreGatewayService.MergeSpanProfile:output_type -> ingester.v1.MergeSpanProfileResponse - 12, // 12: storegateway.v1.StoreGatewayService.ProfileTypes:output_type -> ingester.v1.ProfileTypesResponse - 13, // 13: storegateway.v1.StoreGatewayService.LabelValues:output_type -> types.v1.LabelValuesResponse - 14, // 14: storegateway.v1.StoreGatewayService.LabelNames:output_type -> types.v1.LabelNamesResponse - 15, // 15: storegateway.v1.StoreGatewayService.Series:output_type -> ingester.v1.SeriesResponse - 8, // [8:16] is the sub-list for method output_type - 0, // [0:8] is the sub-list for method input_type + 8, // 8: storegateway.v1.StoreGatewayService.BlockMetadata:input_type -> ingester.v1.BlockMetadataRequest + 9, // 9: storegateway.v1.StoreGatewayService.MergeProfilesStacktraces:output_type -> ingester.v1.MergeProfilesStacktracesResponse + 10, // 10: storegateway.v1.StoreGatewayService.MergeProfilesLabels:output_type -> ingester.v1.MergeProfilesLabelsResponse + 11, // 11: storegateway.v1.StoreGatewayService.MergeProfilesPprof:output_type -> ingester.v1.MergeProfilesPprofResponse + 12, // 12: storegateway.v1.StoreGatewayService.MergeSpanProfile:output_type -> ingester.v1.MergeSpanProfileResponse + 13, // 13: storegateway.v1.StoreGatewayService.ProfileTypes:output_type -> ingester.v1.ProfileTypesResponse + 14, // 14: storegateway.v1.StoreGatewayService.LabelValues:output_type -> types.v1.LabelValuesResponse + 15, // 15: storegateway.v1.StoreGatewayService.LabelNames:output_type -> types.v1.LabelNamesResponse + 16, // 16: storegateway.v1.StoreGatewayService.Series:output_type -> ingester.v1.SeriesResponse + 17, // 17: storegateway.v1.StoreGatewayService.BlockMetadata:output_type -> ingester.v1.BlockMetadataResponse + 9, // [9:18] is the sub-list for method output_type + 0, // [0:9] is the sub-list for method input_type 0, // [0:0] is the sub-list for extension type_name 0, // [0:0] is the sub-list for extension extendee 0, // [0:0] is the sub-list for field type_name diff --git a/api/gen/proto/go/storegateway/v1/storegateway_vtproto.pb.go b/api/gen/proto/go/storegateway/v1/storegateway_vtproto.pb.go index d22f5dc64c..7400aac65b 100644 --- a/api/gen/proto/go/storegateway/v1/storegateway_vtproto.pb.go +++ b/api/gen/proto/go/storegateway/v1/storegateway_vtproto.pb.go @@ -38,6 +38,7 @@ type StoreGatewayServiceClient interface { LabelValues(ctx context.Context, in *v11.LabelValuesRequest, opts ...grpc.CallOption) (*v11.LabelValuesResponse, error) LabelNames(ctx context.Context, in *v11.LabelNamesRequest, opts ...grpc.CallOption) (*v11.LabelNamesResponse, error) Series(ctx context.Context, in *v1.SeriesRequest, opts ...grpc.CallOption) (*v1.SeriesResponse, error) + BlockMetadata(ctx context.Context, in *v1.BlockMetadataRequest, opts ...grpc.CallOption) (*v1.BlockMetadataResponse, error) } type storeGatewayServiceClient struct { @@ -208,6 +209,15 @@ func (c *storeGatewayServiceClient) Series(ctx context.Context, in *v1.SeriesReq return out, nil } +func (c *storeGatewayServiceClient) BlockMetadata(ctx context.Context, in *v1.BlockMetadataRequest, opts ...grpc.CallOption) (*v1.BlockMetadataResponse, error) { + out := new(v1.BlockMetadataResponse) + err := c.cc.Invoke(ctx, "/storegateway.v1.StoreGatewayService/BlockMetadata", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // StoreGatewayServiceServer is the server API for StoreGatewayService service. // All implementations must embed UnimplementedStoreGatewayServiceServer // for forward compatibility @@ -220,6 +230,7 @@ type StoreGatewayServiceServer interface { LabelValues(context.Context, *v11.LabelValuesRequest) (*v11.LabelValuesResponse, error) LabelNames(context.Context, *v11.LabelNamesRequest) (*v11.LabelNamesResponse, error) Series(context.Context, *v1.SeriesRequest) (*v1.SeriesResponse, error) + BlockMetadata(context.Context, *v1.BlockMetadataRequest) (*v1.BlockMetadataResponse, error) mustEmbedUnimplementedStoreGatewayServiceServer() } @@ -251,6 +262,9 @@ func (UnimplementedStoreGatewayServiceServer) LabelNames(context.Context, *v11.L func (UnimplementedStoreGatewayServiceServer) Series(context.Context, *v1.SeriesRequest) (*v1.SeriesResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method Series not implemented") } +func (UnimplementedStoreGatewayServiceServer) BlockMetadata(context.Context, *v1.BlockMetadataRequest) (*v1.BlockMetadataResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method BlockMetadata not implemented") +} func (UnimplementedStoreGatewayServiceServer) mustEmbedUnimplementedStoreGatewayServiceServer() {} // UnsafeStoreGatewayServiceServer may be embedded to opt out of forward compatibility for this service. @@ -440,6 +454,24 @@ func _StoreGatewayService_Series_Handler(srv interface{}, ctx context.Context, d return interceptor(ctx, in, info, handler) } +func _StoreGatewayService_BlockMetadata_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(v1.BlockMetadataRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(StoreGatewayServiceServer).BlockMetadata(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/storegateway.v1.StoreGatewayService/BlockMetadata", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(StoreGatewayServiceServer).BlockMetadata(ctx, req.(*v1.BlockMetadataRequest)) + } + return interceptor(ctx, in, info, handler) +} + // StoreGatewayService_ServiceDesc is the grpc.ServiceDesc for StoreGatewayService service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) @@ -463,6 +495,10 @@ var StoreGatewayService_ServiceDesc = grpc.ServiceDesc{ MethodName: "Series", Handler: _StoreGatewayService_Series_Handler, }, + { + MethodName: "BlockMetadata", + Handler: _StoreGatewayService_BlockMetadata_Handler, + }, }, Streams: []grpc.StreamDesc{ { diff --git a/api/gen/proto/go/storegateway/v1/storegatewayv1connect/storegateway.connect.go b/api/gen/proto/go/storegateway/v1/storegatewayv1connect/storegateway.connect.go index 883d5f34f1..79768f3023 100644 --- a/api/gen/proto/go/storegateway/v1/storegatewayv1connect/storegateway.connect.go +++ b/api/gen/proto/go/storegateway/v1/storegatewayv1connect/storegateway.connect.go @@ -59,6 +59,9 @@ const ( // StoreGatewayServiceSeriesProcedure is the fully-qualified name of the StoreGatewayService's // Series RPC. StoreGatewayServiceSeriesProcedure = "/storegateway.v1.StoreGatewayService/Series" + // StoreGatewayServiceBlockMetadataProcedure is the fully-qualified name of the + // StoreGatewayService's BlockMetadata RPC. + StoreGatewayServiceBlockMetadataProcedure = "/storegateway.v1.StoreGatewayService/BlockMetadata" ) // StoreGatewayServiceClient is a client for the storegateway.v1.StoreGatewayService service. @@ -71,6 +74,7 @@ type StoreGatewayServiceClient interface { LabelValues(context.Context, *connect_go.Request[v11.LabelValuesRequest]) (*connect_go.Response[v11.LabelValuesResponse], error) LabelNames(context.Context, *connect_go.Request[v11.LabelNamesRequest]) (*connect_go.Response[v11.LabelNamesResponse], error) Series(context.Context, *connect_go.Request[v1.SeriesRequest]) (*connect_go.Response[v1.SeriesResponse], error) + BlockMetadata(context.Context, *connect_go.Request[v1.BlockMetadataRequest]) (*connect_go.Response[v1.BlockMetadataResponse], error) } // NewStoreGatewayServiceClient constructs a client for the storegateway.v1.StoreGatewayService @@ -123,6 +127,11 @@ func NewStoreGatewayServiceClient(httpClient connect_go.HTTPClient, baseURL stri baseURL+StoreGatewayServiceSeriesProcedure, opts..., ), + blockMetadata: connect_go.NewClient[v1.BlockMetadataRequest, v1.BlockMetadataResponse]( + httpClient, + baseURL+StoreGatewayServiceBlockMetadataProcedure, + opts..., + ), } } @@ -136,6 +145,7 @@ type storeGatewayServiceClient struct { labelValues *connect_go.Client[v11.LabelValuesRequest, v11.LabelValuesResponse] labelNames *connect_go.Client[v11.LabelNamesRequest, v11.LabelNamesResponse] series *connect_go.Client[v1.SeriesRequest, v1.SeriesResponse] + blockMetadata *connect_go.Client[v1.BlockMetadataRequest, v1.BlockMetadataResponse] } // MergeProfilesStacktraces calls storegateway.v1.StoreGatewayService.MergeProfilesStacktraces. @@ -178,6 +188,11 @@ func (c *storeGatewayServiceClient) Series(ctx context.Context, req *connect_go. return c.series.CallUnary(ctx, req) } +// BlockMetadata calls storegateway.v1.StoreGatewayService.BlockMetadata. +func (c *storeGatewayServiceClient) BlockMetadata(ctx context.Context, req *connect_go.Request[v1.BlockMetadataRequest]) (*connect_go.Response[v1.BlockMetadataResponse], error) { + return c.blockMetadata.CallUnary(ctx, req) +} + // StoreGatewayServiceHandler is an implementation of the storegateway.v1.StoreGatewayService // service. type StoreGatewayServiceHandler interface { @@ -189,6 +204,7 @@ type StoreGatewayServiceHandler interface { LabelValues(context.Context, *connect_go.Request[v11.LabelValuesRequest]) (*connect_go.Response[v11.LabelValuesResponse], error) LabelNames(context.Context, *connect_go.Request[v11.LabelNamesRequest]) (*connect_go.Response[v11.LabelNamesResponse], error) Series(context.Context, *connect_go.Request[v1.SeriesRequest]) (*connect_go.Response[v1.SeriesResponse], error) + BlockMetadata(context.Context, *connect_go.Request[v1.BlockMetadataRequest]) (*connect_go.Response[v1.BlockMetadataResponse], error) } // NewStoreGatewayServiceHandler builds an HTTP handler from the service implementation. It returns @@ -237,6 +253,11 @@ func NewStoreGatewayServiceHandler(svc StoreGatewayServiceHandler, opts ...conne svc.Series, opts..., ) + storeGatewayServiceBlockMetadataHandler := connect_go.NewUnaryHandler( + StoreGatewayServiceBlockMetadataProcedure, + svc.BlockMetadata, + opts..., + ) return "/storegateway.v1.StoreGatewayService/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { switch r.URL.Path { case StoreGatewayServiceMergeProfilesStacktracesProcedure: @@ -255,6 +276,8 @@ func NewStoreGatewayServiceHandler(svc StoreGatewayServiceHandler, opts ...conne storeGatewayServiceLabelNamesHandler.ServeHTTP(w, r) case StoreGatewayServiceSeriesProcedure: storeGatewayServiceSeriesHandler.ServeHTTP(w, r) + case StoreGatewayServiceBlockMetadataProcedure: + storeGatewayServiceBlockMetadataHandler.ServeHTTP(w, r) default: http.NotFound(w, r) } @@ -295,3 +318,7 @@ func (UnimplementedStoreGatewayServiceHandler) LabelNames(context.Context, *conn func (UnimplementedStoreGatewayServiceHandler) Series(context.Context, *connect_go.Request[v1.SeriesRequest]) (*connect_go.Response[v1.SeriesResponse], error) { return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("storegateway.v1.StoreGatewayService.Series is not implemented")) } + +func (UnimplementedStoreGatewayServiceHandler) BlockMetadata(context.Context, *connect_go.Request[v1.BlockMetadataRequest]) (*connect_go.Response[v1.BlockMetadataResponse], error) { + return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("storegateway.v1.StoreGatewayService.BlockMetadata is not implemented")) +} diff --git a/api/gen/proto/go/storegateway/v1/storegatewayv1connect/storegateway.connect.mux.go b/api/gen/proto/go/storegateway/v1/storegatewayv1connect/storegateway.connect.mux.go index d13002f446..b772f6a7e3 100644 --- a/api/gen/proto/go/storegateway/v1/storegatewayv1connect/storegateway.connect.mux.go +++ b/api/gen/proto/go/storegateway/v1/storegatewayv1connect/storegateway.connect.mux.go @@ -59,4 +59,9 @@ func RegisterStoreGatewayServiceHandler(mux *mux.Router, svc StoreGatewayService svc.Series, opts..., )) + mux.Handle("/storegateway.v1.StoreGatewayService/BlockMetadata", connect_go.NewUnaryHandler( + "/storegateway.v1.StoreGatewayService/BlockMetadata", + svc.BlockMetadata, + opts..., + )) } diff --git a/api/gen/proto/go/types/v1/types.pb.go b/api/gen/proto/go/types/v1/types.pb.go index e1d6fbe392..ae0984d8f7 100644 --- a/api/gen/proto/go/types/v1/types.pb.go +++ b/api/gen/proto/go/types/v1/types.pb.go @@ -549,6 +549,148 @@ func (x *LabelNamesResponse) GetNames() []string { return nil } +type BlockInfo struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Ulid string `protobuf:"bytes,1,opt,name=ulid,proto3" json:"ulid,omitempty"` + MinTime int64 `protobuf:"varint,2,opt,name=min_time,json=minTime,proto3" json:"min_time,omitempty"` + MaxTime int64 `protobuf:"varint,3,opt,name=max_time,json=maxTime,proto3" json:"max_time,omitempty"` + Compaction *BlockCompaction `protobuf:"bytes,4,opt,name=compaction,proto3" json:"compaction,omitempty"` + Labels []*LabelPair `protobuf:"bytes,5,rep,name=labels,proto3" json:"labels,omitempty"` +} + +func (x *BlockInfo) Reset() { + *x = BlockInfo{} + if protoimpl.UnsafeEnabled { + mi := &file_types_v1_types_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *BlockInfo) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BlockInfo) ProtoMessage() {} + +func (x *BlockInfo) ProtoReflect() protoreflect.Message { + mi := &file_types_v1_types_proto_msgTypes[9] + 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 BlockInfo.ProtoReflect.Descriptor instead. +func (*BlockInfo) Descriptor() ([]byte, []int) { + return file_types_v1_types_proto_rawDescGZIP(), []int{9} +} + +func (x *BlockInfo) GetUlid() string { + if x != nil { + return x.Ulid + } + return "" +} + +func (x *BlockInfo) GetMinTime() int64 { + if x != nil { + return x.MinTime + } + return 0 +} + +func (x *BlockInfo) GetMaxTime() int64 { + if x != nil { + return x.MaxTime + } + return 0 +} + +func (x *BlockInfo) GetCompaction() *BlockCompaction { + if x != nil { + return x.Compaction + } + return nil +} + +func (x *BlockInfo) GetLabels() []*LabelPair { + if x != nil { + return x.Labels + } + return nil +} + +type BlockCompaction struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Level int32 `protobuf:"varint,1,opt,name=level,proto3" json:"level,omitempty"` + Sources []string `protobuf:"bytes,2,rep,name=sources,proto3" json:"sources,omitempty"` + Parents []string `protobuf:"bytes,3,rep,name=parents,proto3" json:"parents,omitempty"` +} + +func (x *BlockCompaction) Reset() { + *x = BlockCompaction{} + if protoimpl.UnsafeEnabled { + mi := &file_types_v1_types_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *BlockCompaction) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BlockCompaction) ProtoMessage() {} + +func (x *BlockCompaction) ProtoReflect() protoreflect.Message { + mi := &file_types_v1_types_proto_msgTypes[10] + 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 BlockCompaction.ProtoReflect.Descriptor instead. +func (*BlockCompaction) Descriptor() ([]byte, []int) { + return file_types_v1_types_proto_rawDescGZIP(), []int{10} +} + +func (x *BlockCompaction) GetLevel() int32 { + if x != nil { + return x.Level + } + return 0 +} + +func (x *BlockCompaction) GetSources() []string { + if x != nil { + return x.Sources + } + return nil +} + +func (x *BlockCompaction) GetParents() []string { + if x != nil { + return x.Parents + } + return nil +} + var File_types_v1_types_proto protoreflect.FileDescriptor var file_types_v1_types_proto_rawDesc = []byte{ @@ -600,17 +742,35 @@ var file_types_v1_types_proto_rawDesc = []byte{ 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, 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, + 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, + 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 ( @@ -625,7 +785,7 @@ func file_types_v1_types_proto_rawDescGZIP() []byte { return file_types_v1_types_proto_rawDescData } -var file_types_v1_types_proto_msgTypes = make([]protoimpl.MessageInfo, 9) +var file_types_v1_types_proto_msgTypes = make([]protoimpl.MessageInfo, 11) var file_types_v1_types_proto_goTypes = []interface{}{ (*LabelPair)(nil), // 0: types.v1.LabelPair (*ProfileType)(nil), // 1: types.v1.ProfileType @@ -636,16 +796,20 @@ var file_types_v1_types_proto_goTypes = []interface{}{ (*LabelValuesResponse)(nil), // 6: types.v1.LabelValuesResponse (*LabelNamesRequest)(nil), // 7: types.v1.LabelNamesRequest (*LabelNamesResponse)(nil), // 8: types.v1.LabelNamesResponse + (*BlockInfo)(nil), // 9: types.v1.BlockInfo + (*BlockCompaction)(nil), // 10: types.v1.BlockCompaction } var file_types_v1_types_proto_depIdxs = []int32{ - 0, // 0: types.v1.Labels.labels:type_name -> types.v1.LabelPair - 0, // 1: types.v1.Series.labels:type_name -> types.v1.LabelPair - 4, // 2: types.v1.Series.points:type_name -> types.v1.Point - 3, // [3:3] is the sub-list for method output_type - 3, // [3:3] is the sub-list for method input_type - 3, // [3:3] is the sub-list for extension type_name - 3, // [3:3] is the sub-list for extension extendee - 0, // [0:3] is the sub-list for field type_name + 0, // 0: types.v1.Labels.labels:type_name -> types.v1.LabelPair + 0, // 1: types.v1.Series.labels:type_name -> types.v1.LabelPair + 4, // 2: types.v1.Series.points:type_name -> types.v1.Point + 10, // 3: types.v1.BlockInfo.compaction:type_name -> types.v1.BlockCompaction + 0, // 4: types.v1.BlockInfo.labels:type_name -> types.v1.LabelPair + 5, // [5:5] is the sub-list for method output_type + 5, // [5:5] is the sub-list for method input_type + 5, // [5:5] is the sub-list for extension type_name + 5, // [5:5] is the sub-list for extension extendee + 0, // [0:5] is the sub-list for field type_name } func init() { file_types_v1_types_proto_init() } @@ -762,6 +926,30 @@ func file_types_v1_types_proto_init() { return nil } } + file_types_v1_types_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*BlockInfo); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_types_v1_types_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*BlockCompaction); 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{ @@ -769,7 +957,7 @@ func file_types_v1_types_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_types_v1_types_proto_rawDesc, NumEnums: 0, - NumMessages: 9, + NumMessages: 11, NumExtensions: 0, NumServices: 0, }, 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 21288fca44..b945468c04 100644 --- a/api/gen/proto/go/types/v1/types_vtproto.pb.go +++ b/api/gen/proto/go/types/v1/types_vtproto.pb.go @@ -226,6 +226,62 @@ func (m *LabelNamesResponse) CloneMessageVT() proto.Message { return m.CloneVT() } +func (m *BlockInfo) CloneVT() *BlockInfo { + if m == nil { + return (*BlockInfo)(nil) + } + r := &BlockInfo{ + Ulid: m.Ulid, + MinTime: m.MinTime, + MaxTime: m.MaxTime, + Compaction: m.Compaction.CloneVT(), + } + if rhs := m.Labels; rhs != nil { + tmpContainer := make([]*LabelPair, len(rhs)) + for k, v := range rhs { + tmpContainer[k] = v.CloneVT() + } + r.Labels = tmpContainer + } + if len(m.unknownFields) > 0 { + r.unknownFields = make([]byte, len(m.unknownFields)) + copy(r.unknownFields, m.unknownFields) + } + return r +} + +func (m *BlockInfo) CloneMessageVT() proto.Message { + return m.CloneVT() +} + +func (m *BlockCompaction) CloneVT() *BlockCompaction { + if m == nil { + return (*BlockCompaction)(nil) + } + r := &BlockCompaction{ + Level: m.Level, + } + if rhs := m.Sources; rhs != nil { + tmpContainer := make([]string, len(rhs)) + copy(tmpContainer, rhs) + r.Sources = tmpContainer + } + if rhs := m.Parents; rhs != nil { + tmpContainer := make([]string, len(rhs)) + copy(tmpContainer, rhs) + r.Parents = tmpContainer + } + if len(m.unknownFields) > 0 { + r.unknownFields = make([]byte, len(m.unknownFields)) + copy(r.unknownFields, m.unknownFields) + } + return r +} + +func (m *BlockCompaction) CloneMessageVT() proto.Message { + return m.CloneVT() +} + func (m *LabelPair) MarshalVT() (dAtA []byte, err error) { if m == nil { return nil, nil @@ -689,6 +745,134 @@ func (m *LabelNamesResponse) MarshalToSizedBufferVT(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *BlockInfo) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *BlockInfo) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *BlockInfo) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if len(m.Labels) > 0 { + for iNdEx := len(m.Labels) - 1; iNdEx >= 0; iNdEx-- { + size, err := m.Labels[iNdEx].MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x2a + } + } + if m.Compaction != nil { + size, err := m.Compaction.MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x22 + } + if m.MaxTime != 0 { + i = encodeVarint(dAtA, i, uint64(m.MaxTime)) + i-- + dAtA[i] = 0x18 + } + if m.MinTime != 0 { + i = encodeVarint(dAtA, i, uint64(m.MinTime)) + i-- + dAtA[i] = 0x10 + } + if len(m.Ulid) > 0 { + i -= len(m.Ulid) + copy(dAtA[i:], m.Ulid) + i = encodeVarint(dAtA, i, uint64(len(m.Ulid))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *BlockCompaction) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *BlockCompaction) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *BlockCompaction) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if len(m.Parents) > 0 { + for iNdEx := len(m.Parents) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.Parents[iNdEx]) + copy(dAtA[i:], m.Parents[iNdEx]) + i = encodeVarint(dAtA, i, uint64(len(m.Parents[iNdEx]))) + i-- + dAtA[i] = 0x1a + } + } + if len(m.Sources) > 0 { + for iNdEx := len(m.Sources) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.Sources[iNdEx]) + copy(dAtA[i:], m.Sources[iNdEx]) + i = encodeVarint(dAtA, i, uint64(len(m.Sources[iNdEx]))) + i-- + dAtA[i] = 0x12 + } + } + if m.Level != 0 { + i = encodeVarint(dAtA, i, uint64(m.Level)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + func encodeVarint(dAtA []byte, offset int, v uint64) int { offset -= sov(v) base := offset @@ -886,6 +1070,61 @@ func (m *LabelNamesResponse) SizeVT() (n int) { return n } +func (m *BlockInfo) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Ulid) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } + if m.MinTime != 0 { + n += 1 + sov(uint64(m.MinTime)) + } + if m.MaxTime != 0 { + n += 1 + sov(uint64(m.MaxTime)) + } + if m.Compaction != nil { + l = m.Compaction.SizeVT() + n += 1 + l + sov(uint64(l)) + } + if len(m.Labels) > 0 { + for _, e := range m.Labels { + l = e.SizeVT() + n += 1 + l + sov(uint64(l)) + } + } + n += len(m.unknownFields) + return n +} + +func (m *BlockCompaction) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Level != 0 { + n += 1 + sov(uint64(m.Level)) + } + if len(m.Sources) > 0 { + for _, s := range m.Sources { + l = len(s) + n += 1 + l + sov(uint64(l)) + } + } + if len(m.Parents) > 0 { + for _, s := range m.Parents { + l = len(s) + n += 1 + l + sov(uint64(l)) + } + } + n += len(m.unknownFields) + return n +} + func sov(x uint64) (n int) { return (bits.Len64(x|1) + 6) / 7 } @@ -1975,6 +2214,331 @@ func (m *LabelNamesResponse) UnmarshalVT(dAtA []byte) error { } return nil } +func (m *BlockInfo) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: BlockInfo: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: BlockInfo: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Ulid", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Ulid = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field MinTime", wireType) + } + m.MinTime = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.MinTime |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field MaxTime", wireType) + } + m.MaxTime = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.MaxTime |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Compaction", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Compaction == nil { + m.Compaction = &BlockCompaction{} + } + if err := m.Compaction.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Labels", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Labels = append(m.Labels, &LabelPair{}) + if err := m.Labels[len(m.Labels)-1].UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *BlockCompaction) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: BlockCompaction: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: BlockCompaction: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Level", wireType) + } + m.Level = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Level |= int32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Sources", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Sources = append(m.Sources, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Parents", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Parents = append(m.Parents, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skip(dAtA []byte) (n int, err error) { l := len(dAtA) diff --git a/api/ingester/v1/ingester.proto b/api/ingester/v1/ingester.proto index 3ccba9405b..08fc9b4592 100644 --- a/api/ingester/v1/ingester.proto +++ b/api/ingester/v1/ingester.proto @@ -17,6 +17,7 @@ service IngesterService { rpc MergeProfilesLabels(stream MergeProfilesLabelsRequest) returns (stream MergeProfilesLabelsResponse) {} rpc MergeProfilesPprof(stream MergeProfilesPprofRequest) returns (stream MergeProfilesPprofResponse) {} rpc MergeSpanProfile(stream MergeSpanProfileRequest) returns (stream MergeSpanProfileResponse) {} + rpc BlockMetadata(BlockMetadataRequest) returns (BlockMetadataResponse) {} } message ProfileTypesRequest { @@ -52,8 +53,12 @@ message FlushResponse {} message SelectProfilesRequest { string label_selector = 1; types.v1.ProfileType type = 2; + // Milliseconds since epoch. int64 start = 3; + // Milliseconds since epoch. int64 end = 4; + // Optional: Hints for querying + optional Hints hints = 5; } message MergeProfilesStacktracesRequest { @@ -84,6 +89,7 @@ message MergeProfilesStacktracesResponse { // The server replies batch of profiles. // A last message without profiles signals the next message will be the result of the merge. ProfileSets selectedProfiles = 1; + // The list of stracktraces for the profile with their respective value MergeProfilesStacktracesResult result = 3; } @@ -182,3 +188,29 @@ message MergeProfilesPprofResponse { // The merge result in the pprof format. bytes result = 2; } + +message BlockMetadataRequest { + // Milliseconds since epoch. If missing or zero, only the ingesters will be + // queried. + int64 start = 1; + // Milliseconds since epoch. If missing or zero, only the ingesters will be + // queried. + int64 end = 2; +} + +message BlockMetadataResponse { + // Blocks that are present on the instance for the start to end period + repeated types.v1.BlockInfo blocks = 1; +} + +// Hints are used to propagate information about querying +message Hints { + BlockHints block = 1; +} + +message BlockHints { + // The ULID of blocks to query + repeated string ulids = 1; + // When all blocks are compacted, there is no effect of the replication factor, hence we do not need to run deduplication. + bool deduplication = 2; +} diff --git a/api/openapiv2/gen/phlare.swagger.json b/api/openapiv2/gen/phlare.swagger.json index b6c95fb566..bb835f5a49 100644 --- a/api/openapiv2/gen/phlare.swagger.json +++ b/api/openapiv2/gen/phlare.swagger.json @@ -374,6 +374,82 @@ } } }, + "v1BlockCompaction": { + "type": "object", + "properties": { + "level": { + "type": "integer", + "format": "int32" + }, + "sources": { + "type": "array", + "items": { + "type": "string" + } + }, + "parents": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "v1BlockHints": { + "type": "object", + "properties": { + "ulids": { + "type": "array", + "items": { + "type": "string" + }, + "title": "The ULID of blocks to query" + }, + "deduplication": { + "type": "boolean", + "description": "When all blocks are compacted, there is no effect of the replication factor, hence we do not need to run deduplication." + } + } + }, + "v1BlockInfo": { + "type": "object", + "properties": { + "ulid": { + "type": "string" + }, + "minTime": { + "type": "string", + "format": "int64" + }, + "maxTime": { + "type": "string", + "format": "int64" + }, + "compaction": { + "$ref": "#/definitions/v1BlockCompaction" + }, + "labels": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1LabelPair" + } + } + } + }, + "v1BlockMetadataResponse": { + "type": "object", + "properties": { + "blocks": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1BlockInfo" + }, + "title": "Blocks that are present on the instance for the start to end period" + } + } + }, "v1DiffResponse": { "type": "object", "properties": { @@ -509,6 +585,15 @@ } } }, + "v1Hints": { + "type": "object", + "properties": { + "block": { + "$ref": "#/definitions/v1BlockHints" + } + }, + "title": "Hints are used to propagate information about querying" + }, "v1LabelNamesResponse": { "type": "object", "properties": { @@ -902,11 +987,17 @@ }, "start": { "type": "string", - "format": "int64" + "format": "int64", + "description": "Milliseconds since epoch." }, "end": { "type": "string", - "format": "int64" + "format": "int64", + "description": "Milliseconds since epoch." + }, + "hints": { + "$ref": "#/definitions/v1Hints", + "title": "Optional: Hints for querying" } } }, diff --git a/api/storegateway/v1/storegateway.proto b/api/storegateway/v1/storegateway.proto index 26db759e4d..cd62ee9494 100644 --- a/api/storegateway/v1/storegateway.proto +++ b/api/storegateway/v1/storegateway.proto @@ -16,4 +16,5 @@ service StoreGatewayService { rpc LabelValues(types.v1.LabelValuesRequest) returns (types.v1.LabelValuesResponse) {} rpc LabelNames(types.v1.LabelNamesRequest) returns (types.v1.LabelNamesResponse) {} rpc Series(ingester.v1.SeriesRequest) returns (ingester.v1.SeriesResponse) {} + rpc BlockMetadata(ingester.v1.BlockMetadataRequest) returns (ingester.v1.BlockMetadataResponse) {} } diff --git a/api/types/v1/types.proto b/api/types/v1/types.proto index 5b67e6ee66..948eca73a8 100644 --- a/api/types/v1/types.proto +++ b/api/types/v1/types.proto @@ -52,3 +52,17 @@ message LabelNamesRequest { message LabelNamesResponse { repeated string names = 1; } + +message BlockInfo { + string ulid = 1; + int64 min_time = 2; + int64 max_time = 3; + BlockCompaction compaction = 4; + repeated LabelPair labels = 5; +} + +message BlockCompaction { + int32 level = 1; + repeated string sources = 2; + repeated string parents = 3; +} diff --git a/docs/sources/configure-server/reference-configuration-parameters/index.md b/docs/sources/configure-server/reference-configuration-parameters/index.md index c9081725de..75ac063648 100644 --- a/docs/sources/configure-server/reference-configuration-parameters/index.md +++ b/docs/sources/configure-server/reference-configuration-parameters/index.md @@ -138,6 +138,16 @@ limits: # CLI flag: -validation.max-profile-symbol-value-length [max_profile_symbol_value_length: | default = 65535] + # Duration of the distributor aggregation window. Requires aggregation period + # to be specified. 0 to disable. + # CLI flag: -distributor.aggregation-window + [distributor_aggregation_window: | default = 0s] + + # Duration of the distributor aggregation period. Requires aggregation window + # to be specified. 0 to disable. + # CLI flag: -distributor.aggregation-period + [distributor_aggregation_period: | default = 0s] + # The tenant's shard size used by shuffle-sharding. Must be set both on # ingesters and distributors. 0 disables shuffle sharding. # CLI flag: -distributor.ingestion-tenant-shard-size diff --git a/pkg/ingester/query.go b/pkg/ingester/query.go index 533531b587..469b8dc4c1 100644 --- a/pkg/ingester/query.go +++ b/pkg/ingester/query.go @@ -37,6 +37,13 @@ func (i *Ingester) Series(ctx context.Context, req *connect.Request[ingestv1.Ser }) } +// BlockMetadata returns the metadata of the instance's blocks +func (i *Ingester) BlockMetadata(ctx context.Context, req *connect.Request[ingestv1.BlockMetadataRequest]) (*connect.Response[ingestv1.BlockMetadataResponse], error) { + return forInstanceUnary(ctx, i, func(instance *instance) (*connect.Response[ingestv1.BlockMetadataResponse], error) { + return instance.BlockMetadata(ctx, req) + }) +} + func (i *Ingester) MergeProfilesStacktraces(ctx context.Context, stream *connect.BidiStream[ingestv1.MergeProfilesStacktracesRequest, ingestv1.MergeProfilesStacktracesResponse]) error { return i.forInstance(ctx, func(instance *instance) error { return instance.MergeProfilesStacktraces(ctx, stream) diff --git a/pkg/phlaredb/block/metadata.go b/pkg/phlaredb/block/metadata.go index 619af65b71..32c404edb3 100644 --- a/pkg/phlaredb/block/metadata.go +++ b/pkg/phlaredb/block/metadata.go @@ -19,6 +19,8 @@ import ( "github.com/prometheus/common/model" "github.com/prometheus/prometheus/tsdb" "github.com/prometheus/prometheus/tsdb/fileutil" + + typesv1 "github.com/grafana/pyroscope/api/gen/proto/go/types/v1" ) const ( @@ -192,6 +194,36 @@ func (m *Meta) Clone() *Meta { } return &clone } +func (m *Meta) BlockInfo() *typesv1.BlockInfo { + info := &typesv1.BlockInfo{} + m.WriteBlockInfo(info) + return info +} + +func (m *Meta) WriteBlockInfo(info *typesv1.BlockInfo) { + info.Ulid = m.ULID.String() + info.MinTime = int64(m.MinTime) + info.MaxTime = int64(m.MaxTime) + if info.Compaction == nil { + info.Compaction = &typesv1.BlockCompaction{} + } + info.Compaction.Level = int32(m.Compaction.Level) + info.Compaction.Parents = make([]string, len(m.Compaction.Parents)) + for i, p := range m.Compaction.Parents { + info.Compaction.Parents[i] = p.ULID.String() + } + info.Compaction.Sources = make([]string, len(m.Compaction.Sources)) + for i, s := range m.Compaction.Sources { + info.Compaction.Sources[i] = s.String() + } + info.Labels = make([]*typesv1.LabelPair, 0, len(m.Labels)) + for k, v := range m.Labels { + info.Labels = append(info.Labels, &typesv1.LabelPair{ + Name: k, + Value: v, + }) + } +} func generateULID() ulid.ULID { return ulid.MustNew(ulid.Timestamp(time.Now()), rand.Reader) diff --git a/pkg/phlaredb/block_querier.go b/pkg/phlaredb/block_querier.go index adfaeaf6a6..26cefdac14 100644 --- a/pkg/phlaredb/block_querier.go +++ b/pkg/phlaredb/block_querier.go @@ -494,6 +494,10 @@ func (b *singleBlockQuerier) LabelNames(ctx context.Context, req *connect.Reques }), nil } +func (b *singleBlockQuerier) BlockID() string { + return b.meta.ULID.String() +} + func (b *singleBlockQuerier) Close() error { b.openLock.Lock() defer func() { @@ -541,6 +545,7 @@ type Profile interface { type Querier interface { Bounds() (model.Time, model.Time) + SelectMatchingProfiles(ctx context.Context, params *ingestv1.SelectProfilesRequest) (iter.Iterator[Profile], error) MergeByStacktraces(ctx context.Context, rows iter.Iterator[Profile]) (*phlaremodel.Tree, error) MergeBySpans(ctx context.Context, rows iter.Iterator[Profile], spans phlaremodel.SpanSelector) (*phlaremodel.Tree, error) @@ -553,9 +558,16 @@ type Querier interface { Open(ctx context.Context) error // Sorts profiles for retrieval. Sort([]Profile) []Profile + + // BlockID returns the block ID of the querier, when it is representing a single block. + BlockID() string +} + +type TimeBounded interface { + Bounds() (model.Time, model.Time) } -func InRange(q Querier, start, end model.Time) bool { +func InRange(q TimeBounded, start, end model.Time) bool { min, max := q.Bounds() if start > max { return false @@ -608,7 +620,7 @@ func (queriers Queriers) LabelValues(ctx context.Context, req *connect.Request[t blockGetter := queriers.forTimeRange _, hasTimeRange := phlaremodel.GetTimeRange(req.Msg) if !hasTimeRange { - blockGetter = func(_ context.Context, _, _ model.Time) (Queriers, error) { + blockGetter = func(_ context.Context, _, _ model.Time, _ *ingestv1.Hints) (Queriers, error) { return queriers, nil } } @@ -664,7 +676,7 @@ func (queriers Queriers) ProfileTypes(ctx context.Context, req *connect.Request[ blockGetter := queriers.forTimeRange _, hasTimeRange := phlaremodel.GetTimeRange(req.Msg) if !hasTimeRange { - blockGetter = func(_ context.Context, _, _ model.Time) (Queriers, error) { + blockGetter = func(_ context.Context, _, _ model.Time, _ *ingestv1.Hints) (Queriers, error) { return queriers, nil } } @@ -680,7 +692,7 @@ func (queriers Queriers) Series(ctx context.Context, req *connect.Request[ingest blockGetter := queriers.forTimeRange // Legacy Series queries without a range should return all series from all head blocks. if req.Msg.Start == 0 || req.Msg.End == 0 { - blockGetter = func(_ context.Context, _, _ model.Time) (Queriers, error) { + blockGetter = func(_ context.Context, _, _ model.Time, _ *ingestv1.Hints) (Queriers, error) { return queriers, nil } } @@ -707,24 +719,54 @@ func (queriers Queriers) MergeSpanProfile(ctx context.Context, stream *connect.B return MergeSpanProfile(ctx, stream, queriers.forTimeRange) } -type BlockGetter func(ctx context.Context, start, end model.Time) (Queriers, error) +type BlockGetter func(ctx context.Context, start, end model.Time, hints *ingestv1.Hints) (Queriers, error) + +func (queriers Queriers) forTimeRange(_ context.Context, start, end model.Time, hints *ingestv1.Hints) (Queriers, error) { + + skipBlock := HintsToBlockSkipper(hints) -func (queriers Queriers) forTimeRange(_ context.Context, start, end model.Time) (Queriers, error) { result := make(Queriers, 0, len(queriers)) for _, q := range queriers { - if InRange(q, start, end) { - result = append(result, q) + if !InRange(q, start, end) { + continue } + + if skipBlock(q.BlockID()) { + continue + } + + result = append(result, q) } return result, nil } +func HintsToBlockSkipper(hints *ingestv1.Hints) func(ulid string) bool { + if hints != nil && hints.Block != nil { + m := make(map[string]struct{}) + for _, blockID := range hints.Block.Ulids { + m[blockID] = struct{}{} + } + return func(ulid string) bool { + _, exists := m[ulid] + return !exists + } + } + + // without hints do not skip any block + return func(ulid string) bool { return false } +} + // SelectMatchingProfiles returns a list iterator of profiles matching the given request. func SelectMatchingProfiles(ctx context.Context, request *ingestv1.SelectProfilesRequest, queriers Queriers) ([]iter.Iterator[Profile], error) { g, ctx := errgroup.WithContext(ctx) iters := make([]iter.Iterator[Profile], len(queriers)) + skipBlock := HintsToBlockSkipper(request.Hints) + for i, querier := range queriers { + if skipBlock(querier.BlockID()) { + continue + } i := i querier := querier g.Go(util.RecoverPanic(func() error { @@ -769,56 +811,107 @@ func MergeProfilesStacktraces(ctx context.Context, stream *connect.BidiStream[in otlog.String("end", model.Time(request.End).Time().String()), otlog.String("selector", request.LabelSelector), otlog.String("profile_id", request.Type.ID), + otlog.Object("hints", request.Hints), ) - queriers, err := blockGetter(ctx, model.Time(request.Start), model.Time(request.End)) + queriers, err := blockGetter(ctx, model.Time(request.Start), model.Time(request.End), request.Hints) if err != nil { return err } - iters, err := SelectMatchingProfiles(ctx, request, queriers) - if err != nil { - return err - } - - // send batches of profiles to client and filter via bidi stream. - selectedProfiles, err := filterProfiles[ - BidiServerMerge[*ingestv1.MergeProfilesStacktracesResponse, *ingestv1.MergeProfilesStacktracesRequest], - *ingestv1.MergeProfilesStacktracesResponse, - *ingestv1.MergeProfilesStacktracesRequest](ctx, iters, defaultBatchSize, stream) - if err != nil { - return err + deduplicationNeeded := true + if request.Hints != nil && request.Hints.Block != nil { + deduplicationNeeded = request.Hints.Block.Deduplication } var m sync.Mutex t := new(phlaremodel.Tree) g, ctx := errgroup.WithContext(ctx) - for i, querier := range queriers { - querier := querier - i := i - if len(selectedProfiles[i]) == 0 { - continue + // depending on if new need deduplication or not there are two different code paths. + if !deduplicationNeeded { + // signal the end of the profile streaming by sending an empty response. + sp.LogFields(otlog.String("msg", "no profile streaming as no deduplication needed")) + if err = stream.Send(&ingestv1.MergeProfilesStacktracesResponse{}); err != nil { + return err } - // Sort profiles for better read locality. - // Merge async the result so we can continue streaming profiles. - g.Go(util.RecoverPanic(func() error { - merge, err := querier.MergeByStacktraces(ctx, iter.NewSliceIterator(querier.Sort(selectedProfiles[i]))) - if err != nil { - return err + + // in this path we can just merge the profiles from each block and send the result to the client. + for _, querier := range queriers { + querier := querier + g.Go(util.RecoverPanic(func() error { + + iters, err := querier.SelectMatchingProfiles(ctx, request) + if err != nil { + return err + } + defer func() { + iters.Close() + }() + + profiles, err := iter.Slice(iters) + if err != nil { + return err + } + + if len(profiles) == 0 { + return nil + } + + // TODO(simonswine): Split profiles per row group and run the MergeByStacktraces in parallel. + merge, err := querier.MergeByStacktraces(ctx, iter.NewSliceIterator(querier.Sort(profiles))) + if err != nil { + return err + } + + m.Lock() + t.Merge(merge) + m.Unlock() + return nil + })) + } + } else { + // in this path we have to go thorugh every profile and deduplicate them. + iters, err := SelectMatchingProfiles(ctx, request, queriers) + if err != nil { + return err + } + + // send batches of profiles to client and filter via bidi stream. + selectedProfiles, err := filterProfiles[ + BidiServerMerge[*ingestv1.MergeProfilesStacktracesResponse, *ingestv1.MergeProfilesStacktracesRequest], + *ingestv1.MergeProfilesStacktracesResponse, + *ingestv1.MergeProfilesStacktracesRequest](ctx, iters, defaultBatchSize, stream) + if err != nil { + return err + } + + for i, querier := range queriers { + querier := querier + i := i + if len(selectedProfiles[i]) == 0 { + continue } - m.Lock() - t.Merge(merge) - m.Unlock() - return nil - })) - } + // Sort profiles for better read locality. + // Merge async the result so we can continue streaming profiles. + g.Go(util.RecoverPanic(func() error { + merge, err := querier.MergeByStacktraces(ctx, iter.NewSliceIterator(querier.Sort(selectedProfiles[i]))) + if err != nil { + return err + } + m.Lock() + t.Merge(merge) + m.Unlock() + return nil + })) + } - // Signals the end of the profile streaming by sending an empty response. - // This allows the client to not block other streaming ingesters. - sp.LogFields(otlog.String("msg", "signaling the end of the profile streaming")) - if err = stream.Send(&ingestv1.MergeProfilesStacktracesResponse{}); err != nil { - return err + // Signals the end of the profile streaming by sending an empty response. + // This allows the client to not block other streaming ingesters. + sp.LogFields(otlog.String("msg", "signaling the end of the profile streaming")) + if err = stream.Send(&ingestv1.MergeProfilesStacktracesResponse{}); err != nil { + return err + } } if err = g.Wait(); err != nil { @@ -876,7 +969,7 @@ func MergeSpanProfile(ctx context.Context, stream *connect.BidiStream[ingestv1.M return err } - queriers, err := blockGetter(ctx, model.Time(request.Start), model.Time(request.End)) + queriers, err := blockGetter(ctx, model.Time(request.Start), model.Time(request.End), nil) if err != nil { return err } @@ -982,7 +1075,7 @@ func MergeProfilesLabels(ctx context.Context, stream *connect.BidiStream[ingestv otlog.String("by", strings.Join(by, ",")), ) - queriers, err := blockGetter(ctx, model.Time(request.Start), model.Time(request.End)) + queriers, err := blockGetter(ctx, model.Time(request.Start), model.Time(request.End), nil) if err != nil { return err } @@ -1073,7 +1166,7 @@ func MergeProfilesPprof(ctx context.Context, stream *connect.BidiStream[ingestv1 otlog.String("profile_id", request.Type.ID), ) - queriers, err := blockGetter(ctx, model.Time(request.Start), model.Time(request.End)) + queriers, err := blockGetter(ctx, model.Time(request.Start), model.Time(request.End), nil) if err != nil { return err } @@ -1156,7 +1249,7 @@ func MergeProfilesPprof(ctx context.Context, stream *connect.BidiStream[ingestv1 } func ProfileTypes(ctx context.Context, req *connect.Request[ingestv1.ProfileTypesRequest], blockGetter BlockGetter) (*connect.Response[ingestv1.ProfileTypesResponse], error) { - queriers, err := blockGetter(ctx, model.Time(req.Msg.Start), model.Time(req.Msg.End)) + queriers, err := blockGetter(ctx, model.Time(req.Msg.Start), model.Time(req.Msg.End), nil) if err != nil { return nil, err } @@ -1194,7 +1287,7 @@ func ProfileTypes(ctx context.Context, req *connect.Request[ingestv1.ProfileType } func LabelValues(ctx context.Context, req *connect.Request[typesv1.LabelValuesRequest], blockGetter BlockGetter) (*typesv1.LabelValuesResponse, error) { - queriers, err := blockGetter(ctx, model.Time(req.Msg.Start), model.Time(req.Msg.End)) + queriers, err := blockGetter(ctx, model.Time(req.Msg.Start), model.Time(req.Msg.End), nil) if err != nil { return nil, err } @@ -1229,7 +1322,7 @@ func LabelValues(ctx context.Context, req *connect.Request[typesv1.LabelValuesRe } func LabelNames(ctx context.Context, req *connect.Request[typesv1.LabelNamesRequest], blockGetter BlockGetter) (*typesv1.LabelNamesResponse, error) { - queriers, err := blockGetter(ctx, model.Time(req.Msg.Start), model.Time(req.Msg.End)) + queriers, err := blockGetter(ctx, model.Time(req.Msg.Start), model.Time(req.Msg.End), nil) if err != nil { return nil, err } @@ -1266,7 +1359,7 @@ func LabelNames(ctx context.Context, req *connect.Request[typesv1.LabelNamesRequ } func Series(ctx context.Context, req *ingestv1.SeriesRequest, blockGetter BlockGetter) (*ingestv1.SeriesResponse, error) { - queriers, err := blockGetter(ctx, model.Time(req.Start), model.Time(req.End)) + queriers, err := blockGetter(ctx, model.Time(req.Start), model.Time(req.End), nil) if err != nil { return nil, err } diff --git a/pkg/phlaredb/block_querier_test.go b/pkg/phlaredb/block_querier_test.go index cc3a89aa8f..2891f45f49 100644 --- a/pkg/phlaredb/block_querier_test.go +++ b/pkg/phlaredb/block_querier_test.go @@ -207,6 +207,10 @@ type fakeQuerier struct { doErr bool } +func (f *fakeQuerier) BlockID() string { + return "block-id" +} + func (f *fakeQuerier) SelectMatchingProfiles(ctx context.Context, params *ingestv1.SelectProfilesRequest) (iter.Iterator[Profile], error) { // add some jitter time.Sleep(time.Duration(rand.Intn(100)) * time.Millisecond) diff --git a/pkg/phlaredb/head.go b/pkg/phlaredb/head.go index 3cd47ca725..40d87cd59a 100644 --- a/pkg/phlaredb/head.go +++ b/pkg/phlaredb/head.go @@ -329,6 +329,10 @@ func (h *Head) ProfileTypes(ctx context.Context, req *connect.Request[ingestv1.P }), nil } +func (h *Head) BlockID() string { + return h.meta.ULID.String() +} + func (h *Head) Bounds() (mint, maxt model.Time) { h.metaLock.RLock() defer h.metaLock.RUnlock() diff --git a/pkg/phlaredb/head_queriers.go b/pkg/phlaredb/head_queriers.go index e1f85e9dcd..bfe7e98af8 100644 --- a/pkg/phlaredb/head_queriers.go +++ b/pkg/phlaredb/head_queriers.go @@ -36,6 +36,10 @@ func (q *headOnDiskQuerier) Open(_ context.Context) error { return nil } +func (q *headOnDiskQuerier) BlockID() string { + return q.head.meta.ULID.String() +} + func (q *headOnDiskQuerier) SelectMatchingProfiles(ctx context.Context, params *ingestv1.SelectProfilesRequest) (iter.Iterator[Profile], error) { sp, ctx := opentracing.StartSpanFromContext(ctx, "SelectMatchingProfiles - HeadOnDisk") defer sp.Finish() @@ -193,6 +197,10 @@ func (q *headInMemoryQuerier) Open(_ context.Context) error { return nil } +func (q *headInMemoryQuerier) BlockID() string { + return q.head.meta.ULID.String() +} + func (q *headInMemoryQuerier) SelectMatchingProfiles(ctx context.Context, params *ingestv1.SelectProfilesRequest) (iter.Iterator[Profile], error) { sp, ctx := opentracing.StartSpanFromContext(ctx, "SelectMatchingProfiles - HeadInMemory") defer sp.Finish() diff --git a/pkg/phlaredb/phlaredb.go b/pkg/phlaredb/phlaredb.go index cb03453eb5..49ca1587c8 100644 --- a/pkg/phlaredb/phlaredb.go +++ b/pkg/phlaredb/phlaredb.go @@ -472,3 +472,39 @@ func (f *PhlareDB) Evict(blockID ulid.ULID, fn func() error) (bool, error) { <-e.done return e.evicted, e.err } + +func (f *PhlareDB) BlockMetadata(ctx context.Context, req *connect.Request[ingestv1.BlockMetadataRequest]) (*connect.Response[ingestv1.BlockMetadataResponse], error) { + + var result ingestv1.BlockMetadataResponse + + appendInRange := func(q TimeBounded, meta *block.Meta) { + if !InRange(q, model.Time(req.Msg.Start), model.Time(req.Msg.End)) { + return + } + var info typesv1.BlockInfo + meta.WriteBlockInfo(&info) + result.Blocks = append(result.Blocks, &info) + } + + f.headLock.RLock() + for _, h := range f.heads { + appendInRange(h, h.meta) + } + for _, h := range f.flushing { + appendInRange(h, h.meta) + } + f.headLock.RUnlock() + + f.blockQuerier.queriersLock.RLock() + for _, q := range f.blockQuerier.queriers { + appendInRange(q, q.meta) + } + f.blockQuerier.queriersLock.RUnlock() + + // blocks move from heads to flushing to blockQuerier, so we need to check if that might have happened and caused a duplicate + result.Blocks = lo.UniqBy(result.Blocks, func(b *typesv1.BlockInfo) string { + return b.Ulid + }) + + return connect.NewResponse(&result), nil +} diff --git a/pkg/phlaredb/phlaredb_test.go b/pkg/phlaredb/phlaredb_test.go index 8b5cbc4b5d..e67fd39259 100644 --- a/pkg/phlaredb/phlaredb_test.go +++ b/pkg/phlaredb/phlaredb_test.go @@ -136,6 +136,10 @@ func (i *ingesterHandlerPhlareDB) Flush(context.Context, *connect.Request[ingest return nil, errors.New("not implemented") } +func (i *ingesterHandlerPhlareDB) BlockMetadata(context.Context, *connect.Request[ingestv1.BlockMetadataRequest]) (*connect.Response[ingestv1.BlockMetadataResponse], error) { + return nil, errors.New("not implemented") +} + func TestMergeProfilesStacktraces(t *testing.T) { defer goleak.VerifyNone(t, goleak.IgnoreCurrent()) diff --git a/pkg/querier/ingester_querier.go b/pkg/querier/ingester_querier.go index 2ad6dc7644..98ade3a616 100644 --- a/pkg/querier/ingester_querier.go +++ b/pkg/querier/ingester_querier.go @@ -2,6 +2,7 @@ package querier import ( "context" + "fmt" "github.com/bufbuild/connect-go" "github.com/grafana/dskit/ring" @@ -28,6 +29,7 @@ type IngesterQueryClient interface { MergeProfilesLabels(ctx context.Context) clientpool.BidiClientMergeProfilesLabels MergeProfilesPprof(ctx context.Context) clientpool.BidiClientMergeProfilesPprof MergeSpanProfile(ctx context.Context) clientpool.BidiClientMergeSpanProfile + BlockMetadata(ctx context.Context, req *connect.Request[ingestv1.BlockMetadataRequest]) (*connect.Response[ingestv1.BlockMetadataResponse], error) } // IngesterQuerier helps with querying the ingesters. @@ -62,7 +64,23 @@ func forAllIngesters[T any](ctx context.Context, ingesterQuerier *IngesterQuerie }, replicationSet, f) } -func (q *Querier) selectTreeFromIngesters(ctx context.Context, req *querierv1.SelectMergeStacktracesRequest) (*phlaremodel.Tree, error) { +// forAllPlannedIngesters runs f, in parallel, for all ingesters part of the plan +func forAllPlannedIngesters[T any](ctx context.Context, ingesterQuerier *IngesterQuerier, plan map[string]*ingestv1.BlockHints, f QueryReplicaWithHintsFn[T, IngesterQueryClient]) ([]ResponseFromReplica[T], error) { + replicationSet, err := ingesterQuerier.ring.GetReplicationSetForOperation(readNoExtend) + if err != nil { + return nil, err + } + + return forGivenPlan(ctx, plan, func(addr string) (IngesterQueryClient, error) { + client, err := ingesterQuerier.pool.GetClientFor(addr) + if err != nil { + return nil, err + } + return client.(IngesterQueryClient), nil + }, replicationSet, f) +} + +func (q *Querier) selectTreeFromIngesters(ctx context.Context, req *querierv1.SelectMergeStacktracesRequest, plan map[string]*ingestv1.BlockHints) (*phlaremodel.Tree, error) { sp, ctx := opentracing.StartSpanFromContext(ctx, "SelectTree Ingesters") defer sp.Finish() profileType, err := phlaremodel.ParseProfileTypeSelector(req.ProfileTypeID) @@ -76,16 +94,28 @@ func (q *Querier) selectTreeFromIngesters(ctx context.Context, req *querierv1.Se ctx, cancel := context.WithCancel(ctx) defer cancel() - responses, err := forAllIngesters(ctx, q.ingesterQuerier, func(ctx context.Context, ic IngesterQueryClient) (clientpool.BidiClientMergeProfilesStacktraces, error) { - return ic.MergeProfilesStacktraces(ctx), nil - }) + var responses []ResponseFromReplica[clientpool.BidiClientMergeProfilesStacktraces] + if plan != nil { + responses, err = forAllPlannedIngesters(ctx, q.ingesterQuerier, plan, func(ctx context.Context, ic IngesterQueryClient, hints *ingestv1.Hints) (clientpool.BidiClientMergeProfilesStacktraces, error) { + return ic.MergeProfilesStacktraces(ctx), nil + }) + } else { + responses, err = forAllIngesters(ctx, q.ingesterQuerier, func(ctx context.Context, ic IngesterQueryClient) (clientpool.BidiClientMergeProfilesStacktraces, error) { + return ic.MergeProfilesStacktraces(ctx), nil + }) + } if err != nil { return nil, connect.NewError(connect.CodeInternal, err) } // send the first initial request to all ingesters. g, gCtx := errgroup.WithContext(ctx) - for _, r := range responses { - r := r + for idx := range responses { + r := responses[idx] + hints, ok := plan[r.addr] + if !ok && plan != nil { + return nil, connect.NewError(connect.CodeInternal, fmt.Errorf("no hints found for replica %s", r.addr)) + } + g.Go(util.RecoverPanic(func() error { return r.response.Send(&ingestv1.MergeProfilesStacktracesRequest{ Request: &ingestv1.SelectProfilesRequest{ @@ -93,6 +123,7 @@ func (q *Querier) selectTreeFromIngesters(ctx context.Context, req *querierv1.Se Start: req.Start, End: req.End, Type: profileType, + Hints: &ingestv1.Hints{Block: hints}, }, MaxNodes: req.MaxNodes, // TODO(kolesnikovae): Max stacks. @@ -248,3 +279,23 @@ func (q *Querier) selectSpanProfileFromIngesters(ctx context.Context, req *queri // merge all profiles return selectMergeSpanProfile(gCtx, responses) } + +func (q *Querier) blockSelectFromIngesters(ctx context.Context, req *ingestv1.BlockMetadataRequest) ([]ResponseFromReplica[[]*typesv1.BlockInfo], error) { + sp, ctx := opentracing.StartSpanFromContext(ctx, "blockSelectFromIngesters") + defer sp.Finish() + + responses, err := forAllIngesters(ctx, q.ingesterQuerier, func(childCtx context.Context, ic IngesterQueryClient) ([]*typesv1.BlockInfo, error) { + res, err := ic.BlockMetadata(childCtx, connect.NewRequest(&ingestv1.BlockMetadataRequest{ + Start: req.Start, + End: req.End, + })) + if err != nil { + return nil, err + } + return res.Msg.Blocks, nil + }) + if err != nil { + return nil, connect.NewError(connect.CodeInternal, err) + } + return responses, nil +} diff --git a/pkg/querier/querier.go b/pkg/querier/querier.go index 83d77a859c..9612bff24f 100644 --- a/pkg/querier/querier.go +++ b/pkg/querier/querier.go @@ -3,6 +3,7 @@ package querier import ( "context" "flag" + "fmt" "sort" "strings" "sync" @@ -333,6 +334,44 @@ func (q *Querier) LabelNames(ctx context.Context, req *connect.Request[typesv1.L }), nil } +func (q *Querier) blockSelect(ctx context.Context, start, end model.Time) (map[string]*ingestv1.BlockHints, error) { + sp, ctx := opentracing.StartSpanFromContext(ctx, "blockSelect") + defer sp.Finish() + + sp.LogFields( + otlog.String("start", start.Time().String()), + otlog.String("end", end.Time().String()), + ) + + ingesterReq := &ingestv1.BlockMetadataRequest{ + Start: int64(start), + End: int64(end), + } + + results := newReplicasPerBlockID(q.logger) + + // get first all blocks from store gateways, as they should be querier with a priority and also aret the only ones containing duplicated blocks because of replication + if q.storeGatewayQuerier != nil { + res, err := q.blockSelectFromStoreGateway(ctx, ingesterReq) + if err != nil { + return nil, err + } + + results.add(res, storeGatewayInstance) + } + + if q.ingesterQuerier != nil { + res, err := q.blockSelectFromIngesters(ctx, ingesterReq) + if err != nil { + return nil, err + } + results.add(res, ingesterInstance) + } + + return results.blockPlan(ctx), nil + +} + func (q *Querier) Series(ctx context.Context, req *connect.Request[querierv1.SeriesRequest]) (*connect.Response[querierv1.SeriesResponse], error) { sp, ctx := opentracing.StartSpanFromContext(ctx, "Series") defer sp.Finish() @@ -536,10 +575,35 @@ func (q *Querier) SelectMergeSpanProfile(ctx context.Context, req *connect.Reque }), nil } +func isEndpointNotExistingErr(err error) bool { + if err == nil { + return false + } + + var cerr *connect.Error + // unwrap all intermediate connect errors + for errors.As(err, &cerr) { + err = cerr.Unwrap() + } + return err.Error() == "405 Method Not Allowed" +} + func (q *Querier) selectTree(ctx context.Context, req *querierv1.SelectMergeStacktracesRequest) (*phlaremodel.Tree, error) { + // determine the block hints + plan, err := q.blockSelect(ctx, model.Time(req.Start), model.Time(req.End)) + if isEndpointNotExistingErr(err) { + level.Warn(spanlogger.FromContext(ctx, q.logger)).Log( + "msg", "block select not supported on at least one component, fallback to use full dataset", + "err", err, + ) + plan = nil + } else if err != nil { + return nil, fmt.Errorf("error during block select: %w", err) + } + // no store gateways configured so just query the ingesters if q.storeGatewayQuerier == nil { - return q.selectTreeFromIngesters(ctx, req) + return q.selectTreeFromIngesters(ctx, req, plan) } storeQueries := splitQueryToStores(model.Time(req.Start), model.Time(req.End), model.Now(), q.cfg.QueryStoreAfter) @@ -550,17 +614,17 @@ func (q *Querier) selectTree(ctx context.Context, req *querierv1.SelectMergeStac storeQueries.Log(level.Debug(spanlogger.FromContext(ctx, q.logger))) if !storeQueries.ingester.shouldQuery { - return q.selectTreeFromStoreGateway(ctx, storeQueries.storeGateway.MergeStacktracesRequest(req)) + return q.selectTreeFromStoreGateway(ctx, storeQueries.storeGateway.MergeStacktracesRequest(req), plan) } if !storeQueries.storeGateway.shouldQuery { - return q.selectTreeFromIngesters(ctx, storeQueries.ingester.MergeStacktracesRequest(req)) + return q.selectTreeFromIngesters(ctx, storeQueries.ingester.MergeStacktracesRequest(req), plan) } g, ctx := errgroup.WithContext(ctx) var ingesterTree, storegatewayTree *phlaremodel.Tree g.Go(func() error { var err error - ingesterTree, err = q.selectTreeFromIngesters(ctx, storeQueries.ingester.MergeStacktracesRequest(req)) + ingesterTree, err = q.selectTreeFromIngesters(ctx, storeQueries.ingester.MergeStacktracesRequest(req), plan) if err != nil { return err } @@ -568,7 +632,7 @@ func (q *Querier) selectTree(ctx context.Context, req *querierv1.SelectMergeStac }) g.Go(func() error { var err error - storegatewayTree, err = q.selectTreeFromStoreGateway(ctx, storeQueries.storeGateway.MergeStacktracesRequest(req)) + storegatewayTree, err = q.selectTreeFromStoreGateway(ctx, storeQueries.storeGateway.MergeStacktracesRequest(req), plan) if err != nil { return err } diff --git a/pkg/querier/querier_test.go b/pkg/querier/querier_test.go index fed9ba0101..4ef3bae0db 100644 --- a/pkg/querier/querier_test.go +++ b/pkg/querier/querier_test.go @@ -3,6 +3,7 @@ package querier import ( "bytes" "context" + "errors" "os" "sort" "testing" @@ -15,6 +16,7 @@ import ( "github.com/grafana/dskit/ring" "github.com/grafana/dskit/ring/client" "github.com/prometheus/common/model" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" @@ -174,112 +176,152 @@ func Test_Series(t *testing.T) { }, out.Msg.LabelsSet) } +func newBlockMeta(ulids ...string) *connect.Response[ingestv1.BlockMetadataResponse] { + resp := &ingestv1.BlockMetadataResponse{} + + resp.Blocks = make([]*typesv1.BlockInfo, len(ulids)) + for i, ulid := range ulids { + resp.Blocks[i] = &typesv1.BlockInfo{ + Ulid: ulid, + } + } + + return connect.NewResponse(resp) +} + +var endpointNotExistingErr = connect.NewError( + connect.CodeInternal, + connect.NewError( + connect.CodeUnknown, + errors.New("405 Method Not Allowed"), + ), +) + +func Test_isEndpointNotExisting(t *testing.T) { + assert.False(t, isEndpointNotExistingErr(nil)) + assert.False(t, isEndpointNotExistingErr(errors.New("my-error"))) + assert.True(t, isEndpointNotExistingErr(endpointNotExistingErr)) +} + func Test_SelectMergeStacktraces(t *testing.T) { - req := connect.NewRequest(&querierv1.SelectMergeStacktracesRequest{ - LabelSelector: `{app="foo"}`, - ProfileTypeID: "memory:inuse_space:bytes:space:byte", - Start: 0, - End: 2, - }) - bidi1 := newFakeBidiClientStacktraces([]*ingestv1.ProfileSets{ - { - LabelsSets: []*typesv1.Labels{ - { - Labels: []*typesv1.LabelPair{{Name: "app", Value: "foo"}}, - }, - { - Labels: []*typesv1.LabelPair{{Name: "app", Value: "bar"}}, - }, - }, - Profiles: []*ingestv1.SeriesProfile{ - {Timestamp: 1, LabelIndex: 0}, - {Timestamp: 2, LabelIndex: 1}, - {Timestamp: 2, LabelIndex: 0}, - }, - }, - }) - bidi2 := newFakeBidiClientStacktraces([]*ingestv1.ProfileSets{ - { - LabelsSets: []*typesv1.Labels{ - { - Labels: []*typesv1.LabelPair{{Name: "app", Value: "foo"}}, - }, + now := time.Now().UnixMilli() + for _, tc := range []struct { + blockSelect bool + name string + }{ + // This tests the interoberabitlity between older ingesters and new queriers + {false, "WithoutBlockHints"}, + {true, "WithBlockHints"}, + } { + t.Run(tc.name, func(t *testing.T) { + + req := connect.NewRequest(&querierv1.SelectMergeStacktracesRequest{ + LabelSelector: `{app="foo"}`, + ProfileTypeID: "memory:inuse_space:bytes:space:byte", + Start: now + 0, + End: now + 2, + }) + bidi1 := newFakeBidiClientStacktraces([]*ingestv1.ProfileSets{ { - Labels: []*typesv1.LabelPair{{Name: "app", Value: "bar"}}, + LabelsSets: []*typesv1.Labels{ + { + Labels: []*typesv1.LabelPair{{Name: "app", Value: "foo"}}, + }, + { + Labels: []*typesv1.LabelPair{{Name: "app", Value: "bar"}}, + }, + }, + Profiles: []*ingestv1.SeriesProfile{ + {Timestamp: now + 1, LabelIndex: 0}, + {Timestamp: now + 2, LabelIndex: 1}, + {Timestamp: now + 2, LabelIndex: 0}, + }, }, - }, - Profiles: []*ingestv1.SeriesProfile{ - {Timestamp: 1, LabelIndex: 1}, - {Timestamp: 1, LabelIndex: 0}, - {Timestamp: 2, LabelIndex: 1}, - }, - }, - }) - bidi3 := newFakeBidiClientStacktraces([]*ingestv1.ProfileSets{ - { - LabelsSets: []*typesv1.Labels{ + }) + bidi2 := newFakeBidiClientStacktraces([]*ingestv1.ProfileSets{ { - Labels: []*typesv1.LabelPair{{Name: "app", Value: "foo"}}, + LabelsSets: []*typesv1.Labels{ + { + Labels: []*typesv1.LabelPair{{Name: "app", Value: "foo"}}, + }, + { + Labels: []*typesv1.LabelPair{{Name: "app", Value: "bar"}}, + }, + }, + Profiles: []*ingestv1.SeriesProfile{ + {Timestamp: now + 1, LabelIndex: 1}, + {Timestamp: now + 1, LabelIndex: 0}, + {Timestamp: now + 2, LabelIndex: 1}, + }, }, + }) + bidi3 := newFakeBidiClientStacktraces([]*ingestv1.ProfileSets{ { - Labels: []*typesv1.LabelPair{{Name: "app", Value: "bar"}}, + LabelsSets: []*typesv1.Labels{ + { + Labels: []*typesv1.LabelPair{{Name: "app", Value: "foo"}}, + }, + { + Labels: []*typesv1.LabelPair{{Name: "app", Value: "bar"}}, + }, + }, + Profiles: []*ingestv1.SeriesProfile{ + {Timestamp: now + 1, LabelIndex: 1}, + {Timestamp: now + 1, LabelIndex: 0}, + {Timestamp: now + 2, LabelIndex: 0}, + }, }, - }, - Profiles: []*ingestv1.SeriesProfile{ - {Timestamp: 1, LabelIndex: 1}, - {Timestamp: 1, LabelIndex: 0}, - {Timestamp: 2, LabelIndex: 0}, - }, - }, - }) - querier, err := New(Config{ - PoolConfig: clientpool.PoolConfig{ClientCleanupPeriod: 1 * time.Millisecond}, - }, testhelper.NewMockRing([]ring.InstanceDesc{ - {Addr: "1"}, - {Addr: "2"}, - {Addr: "3"}, - }, 3), &poolFactory{func(addr string) (client.PoolClient, error) { - q := newFakeQuerier() - switch addr { - case "1": - q.On("MergeProfilesStacktraces", mock.Anything).Once().Return(bidi1) - case "2": - q.On("MergeProfilesStacktraces", mock.Anything).Once().Return(bidi2) - case "3": - q.On("MergeProfilesStacktraces", mock.Anything).Once().Return(bidi3) - } - return q, nil - }}, nil, nil, log.NewLogfmtLogger(os.Stdout)) - require.NoError(t, err) - flame, err := querier.SelectMergeStacktraces(context.Background(), req) - require.NoError(t, err) + }) + querier, err := New(Config{ + PoolConfig: clientpool.PoolConfig{ClientCleanupPeriod: 1 * time.Millisecond}, + }, testhelper.NewMockRing([]ring.InstanceDesc{ + {Addr: "1"}, + {Addr: "2"}, + {Addr: "3"}, + }, 3), &poolFactory{func(addr string) (client.PoolClient, error) { + q := newFakeQuerier() + switch addr { + case "1": + q.mockMergeStacktraces(bidi1, []string{"a", "d"}, tc.blockSelect) + case "2": + q.mockMergeStacktraces(bidi2, []string{"b", "d"}, tc.blockSelect) + case "3": + q.mockMergeStacktraces(bidi3, []string{"c", "d"}, tc.blockSelect) + } + return q, nil + }}, nil, nil, log.NewLogfmtLogger(os.Stdout)) + require.NoError(t, err) + flame, err := querier.SelectMergeStacktraces(context.Background(), req) + require.NoError(t, err) - sort.Strings(flame.Msg.Flamegraph.Names) - require.Equal(t, []string{"bar", "buzz", "foo", "total"}, flame.Msg.Flamegraph.Names) - require.Equal(t, []int64{0, 2, 0, 0}, flame.Msg.Flamegraph.Levels[0].Values) - require.Equal(t, int64(2), flame.Msg.Flamegraph.Total) - require.Equal(t, int64(2), flame.Msg.Flamegraph.MaxSelf) - var selected []testProfile - selected = append(selected, bidi1.kept...) - selected = append(selected, bidi2.kept...) - selected = append(selected, bidi3.kept...) - sort.Slice(selected, func(i, j int) bool { - if selected[i].Ts == selected[j].Ts { - return phlaremodel.CompareLabelPairs(selected[i].Labels.Labels, selected[j].Labels.Labels) < 0 - } - return selected[i].Ts < selected[j].Ts - }) - require.Len(t, selected, 4) - require.Equal(t, - []testProfile{ - {Ts: 1, Labels: &typesv1.Labels{Labels: []*typesv1.LabelPair{{Name: "app", Value: "bar"}}}}, - {Ts: 1, Labels: &typesv1.Labels{Labels: []*typesv1.LabelPair{{Name: "app", Value: "foo"}}}}, - {Ts: 2, Labels: &typesv1.Labels{Labels: []*typesv1.LabelPair{{Name: "app", Value: "bar"}}}}, - {Ts: 2, Labels: &typesv1.Labels{Labels: []*typesv1.LabelPair{{Name: "app", Value: "foo"}}}}, - }, selected) + sort.Strings(flame.Msg.Flamegraph.Names) + require.Equal(t, []string{"bar", "buzz", "foo", "total"}, flame.Msg.Flamegraph.Names) + require.Equal(t, []int64{0, 2, 0, 0}, flame.Msg.Flamegraph.Levels[0].Values) + require.Equal(t, int64(2), flame.Msg.Flamegraph.Total) + require.Equal(t, int64(2), flame.Msg.Flamegraph.MaxSelf) + var selected []testProfile + selected = append(selected, bidi1.kept...) + selected = append(selected, bidi2.kept...) + selected = append(selected, bidi3.kept...) + sort.Slice(selected, func(i, j int) bool { + if selected[i].Ts == selected[j].Ts { + return phlaremodel.CompareLabelPairs(selected[i].Labels.Labels, selected[j].Labels.Labels) < 0 + } + return selected[i].Ts < selected[j].Ts + }) + require.Len(t, selected, 4) + require.Equal(t, + []testProfile{ + {Ts: now + 1, Labels: &typesv1.Labels{Labels: []*typesv1.LabelPair{{Name: "app", Value: "bar"}}}}, + {Ts: now + 1, Labels: &typesv1.Labels{Labels: []*typesv1.LabelPair{{Name: "app", Value: "foo"}}}}, + {Ts: now + 2, Labels: &typesv1.Labels{Labels: []*typesv1.LabelPair{{Name: "app", Value: "bar"}}}}, + {Ts: now + 2, Labels: &typesv1.Labels{Labels: []*typesv1.LabelPair{{Name: "app", Value: "foo"}}}}, + }, selected) + }) + } } -func Test_SelectMergeProfile(t *testing.T) { +func Test_SelectMergeProfiles(t *testing.T) { req := connect.NewRequest(&querierv1.SelectMergeProfileRequest{ LabelSelector: `{app="foo"}`, ProfileTypeID: "memory:inuse_space:bytes:space:byte", @@ -505,6 +547,15 @@ func newFakeQuerier() *fakeQuerierIngester { return &fakeQuerierIngester{} } +func (f *fakeQuerierIngester) mockMergeStacktraces(bidi *fakeBidiClientStacktraces, blocks []string, blockSelect bool) { + if blockSelect { + f.On("BlockMetadata", mock.Anything, mock.Anything).Once().Return(newBlockMeta(blocks...), nil) + } else { + f.On("BlockMetadata", mock.Anything, mock.Anything).Once().Return(nil, endpointNotExistingErr) + } + f.On("MergeProfilesStacktraces", mock.Anything).Once().Return(bidi) +} + func (f *fakeQuerierIngester) LabelValues(ctx context.Context, req *connect.Request[typesv1.LabelValuesRequest]) (*connect.Response[typesv1.LabelValuesResponse], error) { var ( args = f.Called(ctx, req) @@ -567,6 +618,22 @@ func (f *fakeQuerierIngester) Series(ctx context.Context, req *connect.Request[i return res, err } +func (f *fakeQuerierIngester) BlockMetadata(ctx context.Context, req *connect.Request[ingestv1.BlockMetadataRequest]) (*connect.Response[ingestv1.BlockMetadataResponse], error) { + var ( + args = f.Called(ctx, req) + res *connect.Response[ingestv1.BlockMetadataResponse] + err error + ) + if args[0] != nil { + res = args[0].(*connect.Response[ingestv1.BlockMetadataResponse]) + } + if args[1] != nil { + err = args.Get(1).(error) + } + + return res, err +} + type testProfile struct { Ts int64 Labels *typesv1.Labels diff --git a/pkg/querier/replication.go b/pkg/querier/replication.go index 6eb2619c29..1978ad5eb1 100644 --- a/pkg/querier/replication.go +++ b/pkg/querier/replication.go @@ -2,11 +2,23 @@ package querier import ( "context" + "encoding/json" + "sort" + "github.com/cespare/xxhash/v2" + "github.com/go-kit/log" "github.com/go-kit/log/level" "github.com/grafana/dskit/ring" + "github.com/opentracing/opentracing-go" + otlog "github.com/opentracing/opentracing-go/log" + "github.com/samber/lo" + "golang.org/x/sync/errgroup" + ingestv1 "github.com/grafana/pyroscope/api/gen/proto/go/ingester/v1" + typesv1 "github.com/grafana/pyroscope/api/gen/proto/go/types/v1" + "github.com/grafana/pyroscope/pkg/phlaredb/sharding" "github.com/grafana/pyroscope/pkg/util" + "github.com/grafana/pyroscope/pkg/util/spanlogger" ) type ResponseFromReplica[T any] struct { @@ -14,7 +26,9 @@ type ResponseFromReplica[T any] struct { response T } -type QueryReplicaFn[T any, Querier any] func(context.Context, Querier) (T, error) +type QueryReplicaFn[T any, Querier any] func(ctx context.Context, q Querier) (T, error) + +type QueryReplicaWithHintsFn[T any, Querier any] func(ctx context.Context, q Querier, hint *ingestv1.Hints) (T, error) type Closer interface { CloseRequest() error @@ -23,6 +37,24 @@ type Closer interface { type ClientFactory[T any] func(addr string) (T, error) +// cleanupResult, will make sure if the result was streamed, that we close the request and response +func cleanupStreams[Result any](result ResponseFromReplica[Result]) { + if stream, ok := any(result.response).(interface { + CloseRequest() error + }); ok { + if err := stream.CloseRequest(); err != nil { + level.Warn(util.Logger).Log("msg", "failed to close request", "err", err) + } + } + if stream, ok := any(result.response).(interface { + CloseResponse() error + }); ok { + if err := stream.CloseResponse(); err != nil { + level.Warn(util.Logger).Log("msg", "failed to close response", "err", err) + } + } +} + // forGivenReplicationSet runs f, in parallel, for given replica set. // Under the hood it returns only enough responses to satisfy the quorum. func forGivenReplicationSet[Result any, Querier any](ctx context.Context, clientFactory func(string) (Querier, error), replicationSet ring.ReplicationSet, f QueryReplicaFn[Result, Querier]) ([]ResponseFromReplica[Result], error) { @@ -46,26 +78,351 @@ func forGivenReplicationSet[Result any, Querier any](ctx context.Context, client return ResponseFromReplica[Result]{ingester.Addr, resp}, nil }, - func(result ResponseFromReplica[Result]) { - // If the result was streamed, we need to close the request and response - if stream, ok := any(result.response).(interface { - CloseRequest() error - }); ok { - if err := stream.CloseRequest(); err != nil { - level.Warn(util.Logger).Log("msg", "failed to close request", "err", err) - } + cleanupStreams[Result], + ) + if err != nil { + return nil, err + } + + return results, err +} + +// forGivenPlan runs f, in parallel, for given plan. +func forGivenPlan[Result any, Querier any](ctx context.Context, plan map[string]*ingestv1.BlockHints, clientFactory func(string) (Querier, error), replicationSet ring.ReplicationSet, f QueryReplicaWithHintsFn[Result, Querier]) ([]ResponseFromReplica[Result], error) { + g, _ := errgroup.WithContext(ctx) + + var ( + idx = 0 + result = make([]ResponseFromReplica[Result], len(plan)) + ) + + for replica, hints := range plan { + if !replicationSet.Includes(replica) { + continue + } + var ( + i = idx + r = replica + h = hints + ) + idx++ + g.Go(func() error { + + client, err := clientFactory(r) + if err != nil { + return err } - if stream, ok := any(result.response).(interface { - CloseResponse() error - }); ok { - if err := stream.CloseResponse(); err != nil { - level.Warn(util.Logger).Log("msg", "failed to close response", "err", err) - } + + resp, err := f(ctx, client, &ingestv1.Hints{Block: h}) + if err != nil { + return err } + + result[i] = ResponseFromReplica[Result]{r, resp} + + return nil + }) - if err != nil { + } + + if err := g.Wait(); err != nil { return nil, err } - return results, err + result = result[:idx] + + return result, nil +} + +type instanceType uint8 + +const ( + unknownInstanceType instanceType = iota + ingesterInstance + storeGatewayInstance +) + +// map of block ID to replicas containing the block, when empty replicas, the +// block is already contained by a higher compaction level block in full. +type replicasPerBlockID struct { + m map[string][]string + meta map[string]*typesv1.BlockInfo + instanceType map[string]instanceType + logger log.Logger +} + +func newReplicasPerBlockID(logger log.Logger) *replicasPerBlockID { + return &replicasPerBlockID{ + m: make(map[string][]string), + meta: make(map[string]*typesv1.BlockInfo), + instanceType: make(map[string]instanceType), + logger: logger, + } +} + +func (r *replicasPerBlockID) add(result []ResponseFromReplica[[]*typesv1.BlockInfo], t instanceType) { + for _, replica := range result { + // mark the replica's instance type + // TODO: Figure out if that breaks in single binary mode + r.instanceType[replica.addr] = t + + for _, block := range replica.response { + // add block to map + v, exists := r.m[block.Ulid] + if exists && len(v) > 0 || !exists { + r.m[block.Ulid] = append(r.m[block.Ulid], replica.addr) + } + + // add block meta to map + // note: we do override existing meta, as meta is immutable for all replicas + r.meta[block.Ulid] = block + } + } +} + +func shardFromBlock(m *typesv1.BlockInfo) (shard uint64, shardCount uint64, ok bool) { + for _, lp := range m.Labels { + if lp.Name != sharding.CompactorShardIDLabel { + continue + } + + shardID, shardCount, err := sharding.ParseShardIDLabelValue(lp.Value) + if err == nil { + return shardID, shardCount, true + } + } + + return 0, 0, false +} + +func (r *replicasPerBlockID) removeBlock(ulid string) { + delete(r.m, ulid) + delete(r.meta, ulid) +} + +// this step removes sharded blocks that don't have all the shards present for a time window +func (r *replicasPerBlockID) pruneIncompleteShardedBlocks() { + type compactionKey struct { + level int32 + minT int64 + } + compactions := make(map[compactionKey][]string) + + // group blocks by compaction level + for blockID := range r.m { + meta, ok := r.meta[blockID] + if !ok { + panic("meta missing") + } + if !ok { + continue + } + + key := compactionKey{ + level: 0, + minT: meta.MinTime, + } + + if meta.Compaction != nil { + key.level = meta.Compaction.Level + } + compactions[key] = append(compactions[key], blockID) + } + + // now we go through every group and check if we see at least a block for each shard + var ( + shardsSeen []bool + shardedBlocks []string + ) + for _, blocks := range compactions { + shardsSeen = shardsSeen[:0] + shardedBlocks = shardedBlocks[:0] + for _, block := range blocks { + meta, ok := r.meta[block] + if !ok { + panic("meta is missing") + } + + shardIdx, shards, ok := shardFromBlock(meta) + if !ok { + // not a sharded block continue + continue + } + shardedBlocks = append(shardedBlocks, block) + + if len(shardsSeen) == 0 { + if cap(shardsSeen) < int(shards) { + shardsSeen = make([]bool, shards) + } else { + shardsSeen = shardsSeen[:shards] + for idx := range shardsSeen { + shardsSeen[idx] = false + } + } + } + + if len(shardsSeen) != int(shards) { + panic("shard length mismatch") + } + + shardsSeen[shardIdx] = true + } + // check if all shards are present + allShardsPresent := true + for _, shardSeen := range shardsSeen { + if !shardSeen { + allShardsPresent = false + break + } + } + + if allShardsPresent { + continue + } + + // now remove all blocks that are shareded but not complete + for _, block := range shardedBlocks { + r.removeBlock(block) + } + } +} + +// prunes blocks that are contained by a higher compaction level block +func (r *replicasPerBlockID) pruneSupersededBlocks() { + for blockID := range r.m { + meta, ok := r.meta[blockID] + if !ok { + panic("meta missing") + } + if meta.Compaction == nil { + continue + } + if meta.Compaction.Level < 2 { + continue + } + for _, blockID := range meta.Compaction.Parents { + r.removeBlock(blockID) + } + for _, blockID := range meta.Compaction.Sources { + r.removeBlock(blockID) + } + } +} + +type jsonPlan map[string]*ingestv1.BlockHints + +func (p jsonPlan) String() string { + data, _ := json.Marshal(p) + return string(data) +} + +func (r *replicasPerBlockID) blockPlan(ctx context.Context) map[string]*ingestv1.BlockHints { + sp, _ := opentracing.StartSpanFromContext(ctx, "blockPlan") + defer sp.Finish() + + var ( + deduplicate = false + hash = xxhash.New() + plan = make(map[string]*ingestv1.BlockHints) + smallestCompactionLevel = int32(0) + ) + + r.pruneIncompleteShardedBlocks() + r.pruneSupersededBlocks() + + // now we go through all blocks and choose the replicas that we want to query + for blockID, replicas := range r.m { + // skip if we have no replicas, then block is already contained i an higher compaction level one + if len(replicas) == 0 { + continue + } + + meta, ok := r.meta[blockID] + if !ok { + continue + } + // when we see a single ingester block, we want to deduplicate + if meta.Compaction != nil && meta.Compaction.Level == 1 { + deduplicate = true + } + + // record the lowest compaction level + if meta.Compaction != nil && (smallestCompactionLevel == 0 || meta.Compaction.Level < smallestCompactionLevel) { + smallestCompactionLevel = meta.Compaction.Level + } + + // only get store gateways replicas + sgReplicas := lo.Filter(replicas, func(replica string, _ int) bool { + t, ok := r.instanceType[replica] + if !ok { + return false + } + return t == storeGatewayInstance + }) + + if len(sgReplicas) > 0 { + // if we have store gateway replicas, we want to query them + replicas = sgReplicas + } + + // now select one replica, based on block id + sort.Strings(replicas) + hash.Reset() + _, _ = hash.WriteString(blockID) + hashIdx := int(hash.Sum64()) + if hashIdx < 0 { + hashIdx = -hashIdx + } + selectedReplica := replicas[hashIdx%len(replicas)] + + // add block to plan + p, exists := plan[selectedReplica] + if !exists { + p = &ingestv1.BlockHints{} + plan[selectedReplica] = p + } + p.Ulids = append(p.Ulids, blockID) + + // set the selected replica + r.m[blockID] = []string{selectedReplica} + } + + // adapt the plan to make sure all replicas will deduplicate + if deduplicate { + for _, hints := range plan { + hints.Deduplication = deduplicate + } + } + + var plannedIngesterBlocks, plannedStoreGatwayBlocks int + for replica, blocks := range plan { + t, ok := r.instanceType[replica] + if !ok { + continue + } + if t == storeGatewayInstance { + plannedStoreGatwayBlocks += len(blocks.Ulids) + } + if t == ingesterInstance { + plannedIngesterBlocks += len(blocks.Ulids) + } + } + + sp.LogFields( + otlog.Bool("deduplicate", deduplicate), + otlog.Int32("smallest_compaction_level", smallestCompactionLevel), + otlog.Int("planned_blocks_ingesters", plannedIngesterBlocks), + otlog.Int("planned_blocks_store_gateways", plannedStoreGatwayBlocks), + ) + + level.Debug(spanlogger.FromContext(ctx, r.logger)).Log( + "msg", "block plan created", + "deduplicate", deduplicate, + "smallest_compaction_level", smallestCompactionLevel, + "planned_blocks_ingesters", plannedIngesterBlocks, + "planned_blocks_store_gateways", plannedStoreGatwayBlocks, + "plan", jsonPlan(plan), + ) + + return plan } diff --git a/pkg/querier/replication_test.go b/pkg/querier/replication_test.go new file mode 100644 index 0000000000..2833c51ceb --- /dev/null +++ b/pkg/querier/replication_test.go @@ -0,0 +1,250 @@ +package querier + +import ( + "context" + "fmt" + "sort" + "testing" + "time" + + "github.com/go-kit/log" + "github.com/prometheus/common/model" + "github.com/stretchr/testify/require" + + ingestv1 "github.com/grafana/pyroscope/api/gen/proto/go/ingester/v1" + typesv1 "github.com/grafana/pyroscope/api/gen/proto/go/types/v1" + "github.com/grafana/pyroscope/pkg/phlaredb/sharding" +) + +type blockInfo struct { + i typesv1.BlockInfo +} + +func newBlockInfo(ulid string) *blockInfo { + return &blockInfo{ + i: typesv1.BlockInfo{ + Ulid: ulid, + Compaction: &typesv1.BlockCompaction{ + Level: 1, + }, + }, + } +} + +func (b *blockInfo) withMinTime(minT time.Time, d time.Duration) *blockInfo { + b.i.MinTime = int64(model.TimeFromUnixNano(minT.UnixNano())) + b.i.MaxTime = int64(model.TimeFromUnixNano(minT.Add(d).UnixNano())) + return b +} + +func (b *blockInfo) withCompactionLevel(i int32) *blockInfo { + b.i.Compaction.Level = i + return b +} + +func (b *blockInfo) withCompactionSources(sources ...string) *blockInfo { + b.i.Compaction.Sources = sources + return b +} + +func (b *blockInfo) withCompactionParents(parents ...string) *blockInfo { + b.i.Compaction.Parents = parents + return b +} + +func (b *blockInfo) withLabelValue(k, v string) *blockInfo { + b.i.Labels = append(b.i.Labels, &typesv1.LabelPair{ + Name: k, + Value: v, + }) + return b +} + +func (b *blockInfo) withCompactorShard(shard, shardsCount uint64) *blockInfo { + + return b.withLabelValue( + sharding.CompactorShardIDLabel, + sharding.FormatShardIDLabelValue(shard, shardsCount), + ) +} + +func (b *blockInfo) info() *typesv1.BlockInfo { + return &b.i +} + +type validatorFunc func(t *testing.T, plan map[string]*ingestv1.BlockHints) + +func validatePlanBlockIDs(expBlockIDs ...string) validatorFunc { + return func(t *testing.T, plan map[string]*ingestv1.BlockHints) { + var blockIDs []string + for _, hints := range plan { + blockIDs = append(blockIDs, hints.Ulids...) + } + sort.Strings(blockIDs) + require.Equal(t, expBlockIDs, blockIDs) + } +} + +func validatePlanBlocksOnReplica(replica string, blocks ...string) validatorFunc { + return func(t *testing.T, plan map[string]*ingestv1.BlockHints) { + blockHints, ok := plan[replica] + require.True(t, ok, fmt.Sprintf("replica %s not found in plan", replica)) + for _, block := range blocks { + require.Contains(t, blockHints.Ulids, block, "block %s not found in replica's %s plan", block, replica) + } + } +} + +func Test_replicasPerBlockID_blockPlan(t *testing.T) { + + for _, tc := range []struct { + name string + inputs func(r *replicasPerBlockID) + validators []validatorFunc + }{ + { + name: "single ingester", + inputs: func(r *replicasPerBlockID) { + r.add([]ResponseFromReplica[[]*typesv1.BlockInfo]{ + { + addr: "ingester-0", + response: []*typesv1.BlockInfo{ + newBlockInfo("a").info(), + newBlockInfo("b").info(), + newBlockInfo("c").info(), + }, + }, + }, ingesterInstance) + }, + validators: []validatorFunc{ + validatePlanBlockIDs("a", "b", "c"), + validatePlanBlocksOnReplica("ingester-0", "a", "b", "c"), + }, + }, + { + name: "two ingester with duplicated blocks", + inputs: func(r *replicasPerBlockID) { + r.add([]ResponseFromReplica[[]*typesv1.BlockInfo]{ + { + addr: "ingester-0", + response: []*typesv1.BlockInfo{ + newBlockInfo("a").info(), + newBlockInfo("d").info(), + }, + }, + { + addr: "ingester-1", + response: []*typesv1.BlockInfo{ + newBlockInfo("b").info(), + newBlockInfo("d").info(), + }, + }, + }, ingesterInstance) + }, + validators: []validatorFunc{ + validatePlanBlockIDs("a", "b", "d"), + validatePlanBlocksOnReplica("ingester-0", "a", "d"), + validatePlanBlocksOnReplica("ingester-1", "b"), + }, + }, + { + name: "prefer block on store-gateway over ingester", + inputs: func(r *replicasPerBlockID) { + r.add([]ResponseFromReplica[[]*typesv1.BlockInfo]{ + { + addr: "ingester-0", + response: []*typesv1.BlockInfo{ + newBlockInfo("a").info(), + newBlockInfo("b").info(), + }, + }, + }, ingesterInstance) + r.add([]ResponseFromReplica[[]*typesv1.BlockInfo]{ + { + addr: "store-gateway-0", + response: []*typesv1.BlockInfo{ + newBlockInfo("a").info(), + }, + }, + }, storeGatewayInstance) + }, + validators: []validatorFunc{ + validatePlanBlockIDs("a", "b"), + validatePlanBlocksOnReplica("store-gateway-0", "a"), + validatePlanBlocksOnReplica("ingester-0", "b"), + }, + }, + { + name: "ignore incomplete shards", + inputs: func(r *replicasPerBlockID) { + t1, _ := time.Parse(time.RFC3339, "2021-01-01T00:00:00Z") + t2, _ := time.Parse(time.RFC3339, "2021-01-01T01:00:00Z") + r.add([]ResponseFromReplica[[]*typesv1.BlockInfo]{ + { + addr: "ingester-0", + response: []*typesv1.BlockInfo{ + newBlockInfo("a").withMinTime(t1, time.Hour-time.Second).info(), + newBlockInfo("b").withMinTime(t2, time.Hour-time.Second).info(), + }, + }, + }, ingesterInstance) + r.add([]ResponseFromReplica[[]*typesv1.BlockInfo]{ + { + addr: "store-gateway-0", + response: []*typesv1.BlockInfo{ + newBlockInfo("a-1").withCompactionLevel(2).withCompactionSources("a").withCompactionParents("a").withCompactorShard(1, 2).withMinTime(t1, time.Hour-time.Second).info(), + newBlockInfo("b-1").withCompactionLevel(2).withCompactionSources("b").withCompactionParents("b").withCompactorShard(2, 2).withMinTime(t2, time.Hour-(500*time.Millisecond)).info(), + newBlockInfo("b-2").withCompactionLevel(2).withCompactionSources("b").withCompactionParents("b").withCompactorShard(2, 2).withMinTime(t2, time.Hour-time.Second).info(), + }, + }, + }, storeGatewayInstance) + }, + validators: []validatorFunc{ + validatePlanBlockIDs("a", "b-1", "b-2"), + validatePlanBlocksOnReplica("store-gateway-0", "b-1"), + validatePlanBlocksOnReplica("store-gateway-0", "b-2"), + validatePlanBlocksOnReplica("ingester-0", "a"), + }, + }, + { + // Using a split-and-merge compactor, the level 2 will be referencing sources but will not guarantee that all the source is in the + // TEST if all splits are there before erasing the level 1 before. + name: "ignore blocks which are sharded and in level 2", + inputs: func(r *replicasPerBlockID) { + r.add([]ResponseFromReplica[[]*typesv1.BlockInfo]{ + { + addr: "ingester-0", + response: []*typesv1.BlockInfo{ + newBlockInfo("a").info(), + newBlockInfo("b").info(), + }, + }, + }, ingesterInstance) + r.add([]ResponseFromReplica[[]*typesv1.BlockInfo]{ + { + addr: "store-gateway-0", + response: []*typesv1.BlockInfo{ + newBlockInfo("a").info(), + }, + }, + }, storeGatewayInstance) + }, + validators: []validatorFunc{ + validatePlanBlockIDs("a", "b"), + validatePlanBlocksOnReplica("store-gateway-0", "a"), + validatePlanBlocksOnReplica("ingester-0", "b"), + }, + }, + } { + t.Run(tc.name, func(t *testing.T) { + r := newReplicasPerBlockID(log.NewNopLogger()) + tc.inputs(r) + + plan := r.blockPlan(context.TODO()) + for _, v := range tc.validators { + v(t, plan) + } + }) + } + +} diff --git a/pkg/querier/select_merge_test.go b/pkg/querier/select_merge_test.go index 71bd6ed58d..13fcd40bb1 100644 --- a/pkg/querier/select_merge_test.go +++ b/pkg/querier/select_merge_test.go @@ -117,6 +117,9 @@ func TestSelectMergeStacktraces(t *testing.T) { requireFakeMergeProfilesStacktracesResultTree(t, res) } +func TestSelectMergeStacktracesWithBlockDeduplication(t *testing.T) { +} + func TestSelectMergeByLabels(t *testing.T) { resp1 := newFakeBidiClientSeries([]*ingestv1.ProfileSets{ { diff --git a/pkg/querier/store_gateway_querier.go b/pkg/querier/store_gateway_querier.go index 767bd1b342..e7587983cc 100644 --- a/pkg/querier/store_gateway_querier.go +++ b/pkg/querier/store_gateway_querier.go @@ -2,6 +2,7 @@ package querier import ( "context" + "fmt" "github.com/bufbuild/connect-go" "github.com/go-kit/log" @@ -36,6 +37,7 @@ type StoreGatewayQueryClient interface { LabelValues(context.Context, *connect.Request[typesv1.LabelValuesRequest]) (*connect.Response[typesv1.LabelValuesResponse], error) LabelNames(context.Context, *connect.Request[typesv1.LabelNamesRequest]) (*connect.Response[typesv1.LabelNamesResponse], error) Series(context.Context, *connect.Request[ingestv1.SeriesRequest]) (*connect.Response[ingestv1.SeriesResponse], error) + BlockMetadata(ctx context.Context, req *connect.Request[ingestv1.BlockMetadataRequest]) (*connect.Response[ingestv1.BlockMetadataResponse], error) } type StoreGatewayLimits interface { @@ -142,6 +144,22 @@ func forAllStoreGateways[T any](ctx context.Context, tenantID string, storegatew }, replicationSet, f) } +// forAllPlannedStoreGatway runs f, in parallel, for all store-gateways part of the plan +func forAllPlannedStoreGateways[T any](ctx context.Context, _ string, storegatewayQuerier *StoreGatewayQuerier, plan map[string]*ingestv1.BlockHints, f QueryReplicaWithHintsFn[T, StoreGatewayQueryClient]) ([]ResponseFromReplica[T], error) { + replicationSet, err := storegatewayQuerier.ring.GetReplicationSetForOperation(readNoExtend) + if err != nil { + return nil, err + } + + return forGivenPlan(ctx, plan, func(addr string) (StoreGatewayQueryClient, error) { + client, err := storegatewayQuerier.pool.GetClientFor(addr) + if err != nil { + return nil, err + } + return client.(StoreGatewayQueryClient), nil + }, replicationSet, f) +} + // GetShuffleShardingSubring returns the subring to be used for a given user. This function // should be used both by store-gateway and querier in order to guarantee the same logic is used. func GetShuffleShardingSubring(ring ring.ReadRing, userID string, limits StoreGatewayLimits) ring.ReadRing { @@ -156,7 +174,7 @@ func GetShuffleShardingSubring(ring ring.ReadRing, userID string, limits StoreGa return ring.ShuffleShard(userID, shardSize) } -func (q *Querier) selectTreeFromStoreGateway(ctx context.Context, req *querierv1.SelectMergeStacktracesRequest) (*phlaremodel.Tree, error) { +func (q *Querier) selectTreeFromStoreGateway(ctx context.Context, req *querierv1.SelectMergeStacktracesRequest, plan map[string]*ingestv1.BlockHints) (*phlaremodel.Tree, error) { sp, ctx := opentracing.StartSpanFromContext(ctx, "SelectTree StoreGateway") defer sp.Finish() profileType, err := phlaremodel.ParseProfileTypeSelector(req.ProfileTypeID) @@ -174,9 +192,16 @@ func (q *Querier) selectTreeFromStoreGateway(ctx context.Context, req *querierv1 ctx, cancel := context.WithCancel(ctx) defer cancel() - responses, err := forAllStoreGateways(ctx, tenantID, q.storeGatewayQuerier, func(ctx context.Context, ic StoreGatewayQueryClient) (clientpool.BidiClientMergeProfilesStacktraces, error) { - return ic.MergeProfilesStacktraces(ctx), nil - }) + var responses []ResponseFromReplica[clientpool.BidiClientMergeProfilesStacktraces] + if plan != nil { + responses, err = forAllPlannedStoreGateways(ctx, tenantID, q.storeGatewayQuerier, plan, func(ctx context.Context, ic StoreGatewayQueryClient, hints *ingestv1.Hints) (clientpool.BidiClientMergeProfilesStacktraces, error) { + return ic.MergeProfilesStacktraces(ctx), nil + }) + } else { + responses, err = forAllStoreGateways(ctx, tenantID, q.storeGatewayQuerier, func(ctx context.Context, ic StoreGatewayQueryClient) (clientpool.BidiClientMergeProfilesStacktraces, error) { + return ic.MergeProfilesStacktraces(ctx), nil + }) + } if err != nil { return nil, connect.NewError(connect.CodeInternal, err) } @@ -184,6 +209,10 @@ func (q *Querier) selectTreeFromStoreGateway(ctx context.Context, req *querierv1 g, gCtx := errgroup.WithContext(ctx) for _, r := range responses { r := r + hints, ok := plan[r.addr] + if !ok && plan != nil { + return nil, connect.NewError(connect.CodeInternal, fmt.Errorf("no hints found for replica %s", r.addr)) + } g.Go(util.RecoverPanic(func() error { return r.response.Send(&ingestv1.MergeProfilesStacktracesRequest{ Request: &ingestv1.SelectProfilesRequest{ @@ -191,6 +220,7 @@ func (q *Querier) selectTreeFromStoreGateway(ctx context.Context, req *querierv1 Start: req.Start, End: req.End, Type: profileType, + Hints: &ingestv1.Hints{Block: hints}, }, MaxNodes: req.MaxNodes, // TODO(kolesnikovae): Max stacks. @@ -369,3 +399,25 @@ func (q *Querier) selectSpanProfileFromStoreGateway(ctx context.Context, req *qu // merge all profiles return selectMergeSpanProfile(gCtx, responses) } + +func (q *Querier) blockSelectFromStoreGateway(ctx context.Context, req *ingestv1.BlockMetadataRequest) ([]ResponseFromReplica[[]*typesv1.BlockInfo], error) { + sp, ctx := opentracing.StartSpanFromContext(ctx, "Series StoreGateway") + defer sp.Finish() + + tenantID, err := tenant.ExtractTenantIDFromContext(ctx) + if err != nil { + return nil, connect.NewError(connect.CodeInvalidArgument, err) + } + + responses, err := forAllStoreGateways(ctx, tenantID, q.storeGatewayQuerier, func(ctx context.Context, ic StoreGatewayQueryClient) ([]*typesv1.BlockInfo, error) { + res, err := ic.BlockMetadata(ctx, connect.NewRequest(req)) + if err != nil { + return nil, err + } + return res.Msg.Blocks, nil + }) + if err != nil { + return nil, connect.NewError(connect.CodeInternal, err) + } + return responses, nil +} diff --git a/pkg/storegateway/query.go b/pkg/storegateway/query.go index 6b163e244d..72e77d103d 100644 --- a/pkg/storegateway/query.go +++ b/pkg/storegateway/query.go @@ -122,6 +122,23 @@ func (s *StoreGateway) MergeSpanProfile(ctx context.Context, stream *connect.Bid return terminateStream(stream) } +func (s *StoreGateway) BlockMetadata(ctx context.Context, req *connect.Request[ingestv1.BlockMetadataRequest]) (*connect.Response[ingestv1.BlockMetadataResponse], error) { + var res *ingestv1.BlockMetadataResponse + found, err := s.forBucketStore(ctx, func(bs *BucketStore) error { + var err error + res, err = bs.BlockMetadata(ctx, req.Msg) + return err + }) + if err != nil { + return nil, connect.NewError(connect.CodeInternal, err) + } + if !found { + res = &ingestv1.BlockMetadataResponse{} + } + + return connect.NewResponse(res), nil +} + func terminateStream[Req, Resp any](stream *connect.BidiStream[Req, Resp]) (err error) { if _, err = stream.Receive(); err != nil { if errors.Is(err, io.EOF) { @@ -148,10 +165,14 @@ func (s *StoreGateway) forBucketStore(ctx context.Context, f func(*BucketStore) return false, nil } -func (s *BucketStore) openBlocksForReading(ctx context.Context, minT, maxT model.Time) (phlaredb.Queriers, error) { +func (s *BucketStore) openBlocksForReading(ctx context.Context, minT, maxT model.Time, hints *ingestv1.Hints) (phlaredb.Queriers, error) { + skipBlock := phlaredb.HintsToBlockSkipper(hints) blks := s.blockSet.getFor(minT, maxT) querier := make(phlaredb.Queriers, 0, len(blks)) for _, b := range blks { + if skipBlock(b.BlockID()) { + continue + } querier = append(querier, b) } if err := querier.Open(ctx); err != nil { @@ -175,3 +196,16 @@ func (store *BucketStore) MergeProfilesPprof(ctx context.Context, stream *connec func (store *BucketStore) MergeSpanProfile(ctx context.Context, stream *connect.BidiStream[ingestv1.MergeSpanProfileRequest, ingestv1.MergeSpanProfileResponse]) error { return phlaredb.MergeSpanProfile(ctx, stream, store.openBlocksForReading) } + +func (s *BucketStore) BlockMetadata(ctx context.Context, req *ingestv1.BlockMetadataRequest) (*ingestv1.BlockMetadataResponse, error) { + set := s.blockSet.getFor(model.Time(req.Start), model.Time(req.End)) + result := &ingestv1.BlockMetadataResponse{ + Blocks: make([]*typesv1.BlockInfo, len(set)), + } + for idx, b := range set { + var info typesv1.BlockInfo + b.meta.WriteBlockInfo(&info) + result.Blocks[idx] = &info + } + return result, nil +}