diff --git a/Makefile b/Makefile index 90a677a7b5..4d12d055ba 100644 --- a/Makefile +++ b/Makefile @@ -320,7 +320,7 @@ $(BIN)/updater: Makefile $(BIN)/goreleaser: Makefile go.mod @mkdir -p $(@D) - GOBIN=$(abspath $(@D)) $(GO) install github.com/goreleaser/goreleaser@v1.20.0 + GOBIN=$(abspath $(@D)) $(GO) install github.com/goreleaser/goreleaser/v2@v2.0.0 $(BIN)/gotestsum: Makefile go.mod @mkdir -p $(@D) diff --git a/api/gen/proto/go/ingester/v1/ingester.pb.go b/api/gen/proto/go/ingester/v1/ingester.pb.go index 09928c4b9f..3b679ca791 100644 --- a/api/gen/proto/go/ingester/v1/ingester.pb.go +++ b/api/gen/proto/go/ingester/v1/ingester.pb.go @@ -929,8 +929,10 @@ type ProfileSets struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - LabelsSets []*v1.Labels `protobuf:"bytes,1,rep,name=labelsSets,proto3" json:"labelsSets,omitempty"` - Profiles []*SeriesProfile `protobuf:"bytes,2,rep,name=profiles,proto3" json:"profiles,omitempty"` + // DEPRECATED: Use fingerprints instead. + LabelsSets []*v1.Labels `protobuf:"bytes,1,rep,name=labelsSets,proto3" json:"labelsSets,omitempty"` + Profiles []*SeriesProfile `protobuf:"bytes,2,rep,name=profiles,proto3" json:"profiles,omitempty"` + Fingerprints []uint64 `protobuf:"varint,3,rep,packed,name=fingerprints,proto3" json:"fingerprints,omitempty"` } func (x *ProfileSets) Reset() { @@ -979,6 +981,13 @@ func (x *ProfileSets) GetProfiles() []*SeriesProfile { return nil } +func (x *ProfileSets) GetFingerprints() []uint64 { + if x != nil { + return x.Fingerprints + } + return nil +} + type SeriesProfile struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1961,218 +1970,220 @@ var file_ingester_v1_ingester_proto_rawDesc = []byte{ 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, 0xf4, 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, 0x53, 0x0a, 0x14, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x5f, 0x74, 0x72, 0x61, - 0x63, 0x65, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1c, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, - 0x63, 0x6b, 0x54, 0x72, 0x61, 0x63, 0x65, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x48, - 0x00, 0x52, 0x12, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x54, 0x72, 0x61, 0x63, 0x65, 0x53, 0x65, 0x6c, - 0x65, 0x63, 0x74, 0x6f, 0x72, 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, 0x17, 0x0a, 0x15, 0x5f, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x5f, 0x74, - 0x72, 0x61, 0x63, 0x65, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 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, 0x93, 0x02, - 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, 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, 0x53, 0x0a, 0x14, 0x73, - 0x74, 0x61, 0x63, 0x6b, 0x5f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, - 0x74, 0x6f, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x74, 0x79, 0x70, 0x65, - 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x63, 0x6b, 0x54, 0x72, 0x61, 0x63, 0x65, 0x53, - 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x48, 0x01, 0x52, 0x12, 0x73, 0x74, 0x61, 0x63, 0x6b, - 0x54, 0x72, 0x61, 0x63, 0x65, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 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, 0x42, 0x17, 0x0a, 0x15, 0x5f, 0x73, - 0x74, 0x61, 0x63, 0x6b, 0x5f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, - 0x74, 0x6f, 0x72, 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, 0x22, 0x2c, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x42, 0x6c, - 0x6f, 0x63, 0x6b, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x14, 0x0a, 0x05, 0x75, 0x6c, 0x69, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, - 0x75, 0x6c, 0x69, 0x64, 0x73, 0x22, 0x51, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, - 0x6b, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x38, - 0x0a, 0x0b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x69, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, - 0x31, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x0a, 0x62, 0x6c, - 0x6f, 0x63, 0x6b, 0x53, 0x74, 0x61, 0x74, 0x73, 0x22, 0xe0, 0x01, 0x0a, 0x0a, 0x42, 0x6c, 0x6f, - 0x63, 0x6b, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x65, 0x72, 0x69, 0x65, - 0x73, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x73, - 0x65, 0x72, 0x69, 0x65, 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x72, - 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x04, 0x52, 0x0c, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, - 0x21, 0x0a, 0x0c, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x43, 0x6f, 0x75, - 0x6e, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x5f, 0x62, 0x79, 0x74, 0x65, - 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x42, 0x79, - 0x74, 0x65, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x62, - 0x79, 0x74, 0x65, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0c, 0x70, 0x72, 0x6f, 0x66, - 0x69, 0x6c, 0x65, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x79, 0x6d, 0x62, - 0x6f, 0x6c, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, - 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x42, 0x79, 0x74, 0x65, 0x73, 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, 0x90, 0x09, 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, + 0x01, 0x28, 0x0c, 0x52, 0x09, 0x74, 0x72, 0x65, 0x65, 0x42, 0x79, 0x74, 0x65, 0x73, 0x22, 0x9b, + 0x01, 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, 0x12, 0x22, 0x0a, 0x0c, 0x66, 0x69, 0x6e, 0x67, + 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x04, 0x52, 0x0c, + 0x66, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 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, 0xf4, 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, 0x53, 0x0a, 0x14, 0x73, 0x74, 0x61, 0x63, + 0x6b, 0x5f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x76, + 0x31, 0x2e, 0x53, 0x74, 0x61, 0x63, 0x6b, 0x54, 0x72, 0x61, 0x63, 0x65, 0x53, 0x65, 0x6c, 0x65, + 0x63, 0x74, 0x6f, 0x72, 0x48, 0x00, 0x52, 0x12, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x54, 0x72, 0x61, + 0x63, 0x65, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 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, 0x17, 0x0a, 0x15, 0x5f, 0x73, 0x74, + 0x61, 0x63, 0x6b, 0x5f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, + 0x6f, 0x72, 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, 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, + 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, 0x93, 0x02, 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, 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, 0x53, 0x0a, 0x14, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x5f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x5f, + 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, + 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x63, 0x6b, 0x54, + 0x72, 0x61, 0x63, 0x65, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x48, 0x01, 0x52, 0x12, + 0x73, 0x74, 0x61, 0x63, 0x6b, 0x54, 0x72, 0x61, 0x63, 0x65, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, + 0x6f, 0x72, 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, 0x42, + 0x17, 0x0a, 0x15, 0x5f, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x5f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x5f, + 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 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, 0x22, 0x2c, 0x0a, 0x14, + 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x75, 0x6c, 0x69, 0x64, 0x73, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x09, 0x52, 0x05, 0x75, 0x6c, 0x69, 0x64, 0x73, 0x22, 0x51, 0x0a, 0x15, 0x47, 0x65, + 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x38, 0x0a, 0x0b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73, 0x74, 0x61, + 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x69, 0x6e, 0x67, 0x65, 0x73, + 0x74, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x74, 0x61, 0x74, + 0x73, 0x52, 0x0a, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x74, 0x61, 0x74, 0x73, 0x22, 0xe0, 0x01, + 0x0a, 0x0a, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x21, 0x0a, 0x0c, + 0x73, 0x65, 0x72, 0x69, 0x65, 0x73, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x04, 0x52, 0x0b, 0x73, 0x65, 0x72, 0x69, 0x65, 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, + 0x23, 0x0a, 0x0d, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0c, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x43, + 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x5f, 0x63, + 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x73, 0x61, 0x6d, 0x70, + 0x6c, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x6e, 0x64, 0x65, 0x78, + 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x69, 0x6e, + 0x64, 0x65, 0x78, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x72, 0x6f, 0x66, + 0x69, 0x6c, 0x65, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, + 0x0c, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x21, 0x0a, + 0x0c, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x07, 0x20, + 0x01, 0x28, 0x04, 0x52, 0x0b, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x42, 0x79, 0x74, 0x65, 0x73, + 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, 0x90, 0x09, + 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, 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, 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, 0x12, 0x58, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x50, 0x72, - 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x20, 0x2e, 0x74, 0x79, 0x70, - 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, - 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x74, - 0x79, 0x70, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x66, 0x69, - 0x6c, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x00, 0x12, 0x58, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x74, 0x61, - 0x74, 0x73, 0x12, 0x21, 0x2e, 0x69, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x31, - 0x2e, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x69, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x65, 0x72, - 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x74, 0x61, 0x74, - 0x73, 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, + 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, + 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, 0x12, 0x58, 0x0a, 0x0f, + 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, + 0x20, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x72, + 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x21, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, + 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x58, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, + 0x63, 0x6b, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x21, 0x2e, 0x69, 0x6e, 0x67, 0x65, 0x73, 0x74, + 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x74, + 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x69, 0x6e, 0x67, + 0x65, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, + 0x6b, 0x53, 0x74, 0x61, 0x74, 0x73, 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 ( 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 30f26068b1..1a00cf8185 100644 --- a/api/gen/proto/go/ingester/v1/ingester_vtproto.pb.go +++ b/api/gen/proto/go/ingester/v1/ingester_vtproto.pb.go @@ -386,6 +386,11 @@ func (m *ProfileSets) CloneVT() *ProfileSets { } r.Profiles = tmpContainer } + if rhs := m.Fingerprints; rhs != nil { + tmpContainer := make([]uint64, len(rhs)) + copy(tmpContainer, rhs) + r.Fingerprints = tmpContainer + } if len(m.unknownFields) > 0 { r.unknownFields = make([]byte, len(m.unknownFields)) copy(r.unknownFields, m.unknownFields) @@ -1214,6 +1219,15 @@ func (this *ProfileSets) EqualVT(that *ProfileSets) bool { } } } + if len(this.Fingerprints) != len(that.Fingerprints) { + return false + } + for i, vx := range this.Fingerprints { + vy := that.Fingerprints[i] + if vx != vy { + return false + } + } return string(this.unknownFields) == string(that.unknownFields) } @@ -3172,6 +3186,26 @@ func (m *ProfileSets) MarshalToSizedBufferVT(dAtA []byte) (int, error) { i -= len(m.unknownFields) copy(dAtA[i:], m.unknownFields) } + if len(m.Fingerprints) > 0 { + var pksize2 int + for _, num := range m.Fingerprints { + pksize2 += protohelpers.SizeOfVarint(uint64(num)) + } + i -= pksize2 + j1 := i + for _, num := range m.Fingerprints { + for num >= 1<<7 { + dAtA[j1] = uint8(uint64(num)&0x7f | 0x80) + num >>= 7 + j1++ + } + dAtA[j1] = uint8(num) + j1++ + } + i = protohelpers.EncodeVarint(dAtA, i, uint64(pksize2)) + i-- + dAtA[i] = 0x1a + } if len(m.Profiles) > 0 { for iNdEx := len(m.Profiles) - 1; iNdEx >= 0; iNdEx-- { size, err := m.Profiles[iNdEx].MarshalToSizedBufferVT(dAtA[:i]) @@ -4376,6 +4410,13 @@ func (m *ProfileSets) SizeVT() (n int) { n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) } } + if len(m.Fingerprints) > 0 { + l = 0 + for _, e := range m.Fingerprints { + l += protohelpers.SizeOfVarint(uint64(e)) + } + n += 1 + protohelpers.SizeOfVarint(uint64(l)) + l + } n += len(m.unknownFields) return n } @@ -6643,6 +6684,82 @@ func (m *ProfileSets) UnmarshalVT(dAtA []byte) error { return err } iNdEx = postIndex + case 3: + if wireType == 0 { + var v uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.Fingerprints = append(m.Fingerprints, v) + } else if wireType == 2 { + var packedLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + packedLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if packedLen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + packedLen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + var elementCount int + var count int + for _, integer := range dAtA[iNdEx:postIndex] { + if integer < 128 { + count++ + } + } + elementCount = count + if elementCount != 0 && len(m.Fingerprints) == 0 { + m.Fingerprints = make([]uint64, 0, elementCount) + } + for iNdEx < postIndex { + var v uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.Fingerprints = append(m.Fingerprints, v) + } + } else { + return fmt.Errorf("proto: wrong wireType = %d for field Fingerprints", wireType) + } default: iNdEx = preIndex skippy, err := protohelpers.Skip(dAtA[iNdEx:]) diff --git a/api/gen/proto/go/querier/v1/querier.pb.go b/api/gen/proto/go/querier/v1/querier.pb.go index 4951cf9b66..3cfa0a2ec6 100644 --- a/api/gen/proto/go/querier/v1/querier.pb.go +++ b/api/gen/proto/go/querier/v1/querier.pb.go @@ -22,6 +22,55 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) +type ProfileFormat int32 + +const ( + ProfileFormat_PROFILE_FORMAT_UNSPECIFIED ProfileFormat = 0 + ProfileFormat_PROFILE_FORMAT_FLAMEGRAPH ProfileFormat = 1 + ProfileFormat_PROFILE_FORMAT_TREE ProfileFormat = 2 +) + +// Enum value maps for ProfileFormat. +var ( + ProfileFormat_name = map[int32]string{ + 0: "PROFILE_FORMAT_UNSPECIFIED", + 1: "PROFILE_FORMAT_FLAMEGRAPH", + 2: "PROFILE_FORMAT_TREE", + } + ProfileFormat_value = map[string]int32{ + "PROFILE_FORMAT_UNSPECIFIED": 0, + "PROFILE_FORMAT_FLAMEGRAPH": 1, + "PROFILE_FORMAT_TREE": 2, + } +) + +func (x ProfileFormat) Enum() *ProfileFormat { + p := new(ProfileFormat) + *p = x + return p +} + +func (x ProfileFormat) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (ProfileFormat) Descriptor() protoreflect.EnumDescriptor { + return file_querier_v1_querier_proto_enumTypes[0].Descriptor() +} + +func (ProfileFormat) Type() protoreflect.EnumType { + return &file_querier_v1_querier_proto_enumTypes[0] +} + +func (x ProfileFormat) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use ProfileFormat.Descriptor instead. +func (ProfileFormat) EnumDescriptor() ([]byte, []int) { + return file_querier_v1_querier_proto_rawDescGZIP(), []int{0} +} + type ProfileTypesRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -263,6 +312,9 @@ type SelectMergeStacktracesRequest struct { End int64 `protobuf:"varint,4,opt,name=end,proto3" json:"end,omitempty"` // Limit the nodes returned to only show the node with the max_node's biggest total MaxNodes *int64 `protobuf:"varint,5,opt,name=max_nodes,json=maxNodes,proto3,oneof" json:"max_nodes,omitempty"` + // Profile format specifies the format of profile to be returned. + // If not specified, the profile will be returned in flame graph format. + Format ProfileFormat `protobuf:"varint,6,opt,name=format,proto3,enum=querier.v1.ProfileFormat" json:"format,omitempty"` } func (x *SelectMergeStacktracesRequest) Reset() { @@ -332,12 +384,21 @@ func (x *SelectMergeStacktracesRequest) GetMaxNodes() int64 { return 0 } +func (x *SelectMergeStacktracesRequest) GetFormat() ProfileFormat { + if x != nil { + return x.Format + } + return ProfileFormat_PROFILE_FORMAT_UNSPECIFIED +} + type SelectMergeStacktracesResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Flamegraph *FlameGraph `protobuf:"bytes,1,opt,name=flamegraph,proto3" json:"flamegraph,omitempty"` + // Pyroscope tree bytes. + Tree []byte `protobuf:"bytes,2,opt,name=tree,proto3" json:"tree,omitempty"` } func (x *SelectMergeStacktracesResponse) Reset() { @@ -379,6 +440,13 @@ func (x *SelectMergeStacktracesResponse) GetFlamegraph() *FlameGraph { return nil } +func (x *SelectMergeStacktracesResponse) GetTree() []byte { + if x != nil { + return x.Tree + } + return nil +} + type SelectMergeSpanProfileRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -393,6 +461,9 @@ type SelectMergeSpanProfileRequest struct { End int64 `protobuf:"varint,5,opt,name=end,proto3" json:"end,omitempty"` // Limit the nodes returned to only show the node with the max_node's biggest total MaxNodes *int64 `protobuf:"varint,6,opt,name=max_nodes,json=maxNodes,proto3,oneof" json:"max_nodes,omitempty"` + // Profile format specifies the format of profile to be returned. + // If not specified, the profile will be returned in flame graph format. + Format ProfileFormat `protobuf:"varint,7,opt,name=format,proto3,enum=querier.v1.ProfileFormat" json:"format,omitempty"` } func (x *SelectMergeSpanProfileRequest) Reset() { @@ -469,12 +540,21 @@ func (x *SelectMergeSpanProfileRequest) GetMaxNodes() int64 { return 0 } +func (x *SelectMergeSpanProfileRequest) GetFormat() ProfileFormat { + if x != nil { + return x.Format + } + return ProfileFormat_PROFILE_FORMAT_UNSPECIFIED +} + type SelectMergeSpanProfileResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Flamegraph *FlameGraph `protobuf:"bytes,1,opt,name=flamegraph,proto3" json:"flamegraph,omitempty"` + // Pyroscope tree bytes. + Tree []byte `protobuf:"bytes,2,opt,name=tree,proto3" json:"tree,omitempty"` } func (x *SelectMergeSpanProfileResponse) Reset() { @@ -516,6 +596,13 @@ func (x *SelectMergeSpanProfileResponse) GetFlamegraph() *FlameGraph { return nil } +func (x *SelectMergeSpanProfileResponse) GetTree() []byte { + if x != nil { + return x.Tree + } + return nil +} + type DiffRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1389,7 +1476,7 @@ var file_querier_v1_querier_proto_rawDesc = []byte{ 0x12, 0x2f, 0x0a, 0x0a, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x5f, 0x73, 0x65, 0x74, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x74, 0x79, 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, 0xc5, 0x01, 0x0a, 0x1d, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x4d, 0x65, 0x72, 0x67, + 0x74, 0x22, 0xf8, 0x01, 0x0a, 0x1d, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x53, 0x74, 0x61, 0x63, 0x6b, 0x74, 0x72, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x25, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x70, 0x72, 0x6f, @@ -1400,236 +1487,251 @@ var file_querier_v1_querier_proto_rawDesc = []byte{ 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, 0x20, 0x0a, 0x09, 0x6d, 0x61, 0x78, 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x48, 0x00, 0x52, 0x08, - 0x6d, 0x61, 0x78, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x88, 0x01, 0x01, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, - 0x6d, 0x61, 0x78, 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x22, 0x58, 0x0a, 0x1e, 0x53, 0x65, 0x6c, - 0x65, 0x63, 0x74, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x53, 0x74, 0x61, 0x63, 0x6b, 0x74, 0x72, 0x61, - 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, 0x0a, 0x66, - 0x6c, 0x61, 0x6d, 0x65, 0x67, 0x72, 0x61, 0x70, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x16, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x6c, 0x61, - 0x6d, 0x65, 0x47, 0x72, 0x61, 0x70, 0x68, 0x52, 0x0a, 0x66, 0x6c, 0x61, 0x6d, 0x65, 0x67, 0x72, - 0x61, 0x70, 0x68, 0x22, 0xea, 0x01, 0x0a, 0x1d, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x4d, 0x65, - 0x72, 0x67, 0x65, 0x53, 0x70, 0x61, 0x6e, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x25, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, - 0x5f, 0x74, 0x79, 0x70, 0x65, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x70, - 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x49, 0x44, 0x12, 0x25, 0x0a, 0x0e, - 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x53, 0x65, 0x6c, 0x65, 0x63, - 0x74, 0x6f, 0x72, 0x12, 0x23, 0x0a, 0x0d, 0x73, 0x70, 0x61, 0x6e, 0x5f, 0x73, 0x65, 0x6c, 0x65, - 0x63, 0x74, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x73, 0x70, 0x61, 0x6e, - 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, - 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x10, - 0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x65, 0x6e, 0x64, - 0x12, 0x20, 0x0a, 0x09, 0x6d, 0x61, 0x78, 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x06, 0x20, - 0x01, 0x28, 0x03, 0x48, 0x00, 0x52, 0x08, 0x6d, 0x61, 0x78, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x88, - 0x01, 0x01, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x73, - 0x22, 0x58, 0x0a, 0x1e, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 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, 0x36, 0x0a, 0x0a, 0x66, 0x6c, 0x61, 0x6d, 0x65, 0x67, 0x72, 0x61, 0x70, 0x68, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x72, - 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x6c, 0x61, 0x6d, 0x65, 0x47, 0x72, 0x61, 0x70, 0x68, 0x52, 0x0a, - 0x66, 0x6c, 0x61, 0x6d, 0x65, 0x67, 0x72, 0x61, 0x70, 0x68, 0x22, 0x8d, 0x01, 0x0a, 0x0b, 0x44, - 0x69, 0x66, 0x66, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3d, 0x0a, 0x04, 0x6c, 0x65, - 0x66, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x69, - 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x4d, 0x65, 0x72, 0x67, - 0x65, 0x53, 0x74, 0x61, 0x63, 0x6b, 0x74, 0x72, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x52, 0x04, 0x6c, 0x65, 0x66, 0x74, 0x12, 0x3f, 0x0a, 0x05, 0x72, 0x69, 0x67, - 0x68, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x69, - 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x4d, 0x65, 0x72, 0x67, - 0x65, 0x53, 0x74, 0x61, 0x63, 0x6b, 0x74, 0x72, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x52, 0x05, 0x72, 0x69, 0x67, 0x68, 0x74, 0x22, 0x4a, 0x0a, 0x0c, 0x44, 0x69, - 0x66, 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3a, 0x0a, 0x0a, 0x66, 0x6c, - 0x61, 0x6d, 0x65, 0x67, 0x72, 0x61, 0x70, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, - 0x2e, 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x6c, 0x61, 0x6d, - 0x65, 0x47, 0x72, 0x61, 0x70, 0x68, 0x44, 0x69, 0x66, 0x66, 0x52, 0x0a, 0x66, 0x6c, 0x61, 0x6d, - 0x65, 0x67, 0x72, 0x61, 0x70, 0x68, 0x22, 0x7e, 0x0a, 0x0a, 0x46, 0x6c, 0x61, 0x6d, 0x65, 0x47, - 0x72, 0x61, 0x70, 0x68, 0x12, 0x14, 0x0a, 0x05, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x09, 0x52, 0x05, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x29, 0x0a, 0x06, 0x6c, 0x65, - 0x76, 0x65, 0x6c, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x71, 0x75, 0x65, - 0x72, 0x69, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x06, 0x6c, - 0x65, 0x76, 0x65, 0x6c, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x12, 0x19, 0x0a, 0x08, 0x6d, - 0x61, 0x78, 0x5f, 0x73, 0x65, 0x6c, 0x66, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x6d, - 0x61, 0x78, 0x53, 0x65, 0x6c, 0x66, 0x22, 0xc0, 0x01, 0x0a, 0x0e, 0x46, 0x6c, 0x61, 0x6d, 0x65, - 0x47, 0x72, 0x61, 0x70, 0x68, 0x44, 0x69, 0x66, 0x66, 0x12, 0x14, 0x0a, 0x05, 0x6e, 0x61, 0x6d, - 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x12, - 0x29, 0x0a, 0x06, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x11, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x65, 0x76, - 0x65, 0x6c, 0x52, 0x06, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, - 0x74, 0x61, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, - 0x12, 0x19, 0x0a, 0x08, 0x6d, 0x61, 0x78, 0x5f, 0x73, 0x65, 0x6c, 0x66, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x07, 0x6d, 0x61, 0x78, 0x53, 0x65, 0x6c, 0x66, 0x12, 0x1c, 0x0a, 0x09, 0x6c, - 0x65, 0x66, 0x74, 0x54, 0x69, 0x63, 0x6b, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, - 0x6c, 0x65, 0x66, 0x74, 0x54, 0x69, 0x63, 0x6b, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x72, 0x69, 0x67, - 0x68, 0x74, 0x54, 0x69, 0x63, 0x6b, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x72, - 0x69, 0x67, 0x68, 0x74, 0x54, 0x69, 0x63, 0x6b, 0x73, 0x22, 0x1f, 0x0a, 0x05, 0x4c, 0x65, 0x76, - 0x65, 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x03, 0x52, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x22, 0xaf, 0x02, 0x0a, 0x19, 0x53, - 0x65, 0x6c, 0x65, 0x63, 0x74, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, - 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x25, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x66, - 0x69, 0x6c, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x49, 0x44, 0x12, - 0x25, 0x0a, 0x0e, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, - 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x53, 0x65, - 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 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, 0x20, - 0x0a, 0x09, 0x6d, 0x61, 0x78, 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x03, 0x48, 0x00, 0x52, 0x08, 0x6d, 0x61, 0x78, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x88, 0x01, 0x01, - 0x12, 0x53, 0x0a, 0x14, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x5f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x5f, - 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, - 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x63, 0x6b, 0x54, - 0x72, 0x61, 0x63, 0x65, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x48, 0x01, 0x52, 0x12, - 0x73, 0x74, 0x61, 0x63, 0x6b, 0x54, 0x72, 0x61, 0x63, 0x65, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, - 0x6f, 0x72, 0x88, 0x01, 0x01, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x6e, 0x6f, - 0x64, 0x65, 0x73, 0x42, 0x17, 0x0a, 0x15, 0x5f, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x5f, 0x74, 0x72, - 0x61, 0x63, 0x65, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x22, 0x84, 0x03, 0x0a, - 0x13, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x53, 0x65, 0x72, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x25, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x5f, - 0x74, 0x79, 0x70, 0x65, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x70, 0x72, - 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x49, 0x44, 0x12, 0x25, 0x0a, 0x0e, 0x6c, - 0x61, 0x62, 0x65, 0x6c, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, - 0x6f, 0x72, 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, 0x19, 0x0a, 0x08, 0x67, 0x72, - 0x6f, 0x75, 0x70, 0x5f, 0x62, 0x79, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x67, 0x72, - 0x6f, 0x75, 0x70, 0x42, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x74, 0x65, 0x70, 0x18, 0x06, 0x20, - 0x01, 0x28, 0x01, 0x52, 0x04, 0x73, 0x74, 0x65, 0x70, 0x12, 0x4a, 0x0a, 0x0b, 0x61, 0x67, 0x67, - 0x72, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x23, - 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x53, 0x65, - 0x72, 0x69, 0x65, 0x73, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, - 0x79, 0x70, 0x65, 0x48, 0x00, 0x52, 0x0b, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x12, 0x53, 0x0a, 0x14, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x5f, 0x74, - 0x72, 0x61, 0x63, 0x65, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x18, 0x08, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, - 0x74, 0x61, 0x63, 0x6b, 0x54, 0x72, 0x61, 0x63, 0x65, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, - 0x72, 0x48, 0x01, 0x52, 0x12, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x54, 0x72, 0x61, 0x63, 0x65, 0x53, - 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x88, 0x01, 0x01, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x61, - 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x17, 0x0a, 0x15, 0x5f, 0x73, - 0x74, 0x61, 0x63, 0x6b, 0x5f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, - 0x74, 0x6f, 0x72, 0x22, 0x40, 0x0a, 0x14, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x53, 0x65, 0x72, - 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x28, 0x0a, 0x06, 0x73, - 0x65, 0x72, 0x69, 0x65, 0x73, 0x18, 0x01, 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, 0x53, 0x0a, 0x13, 0x41, 0x6e, 0x61, 0x6c, 0x79, 0x7a, 0x65, - 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, - 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x73, 0x74, 0x61, - 0x72, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x03, 0x65, 0x6e, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x22, 0x8d, 0x01, 0x0a, 0x14, 0x41, - 0x6e, 0x61, 0x6c, 0x79, 0x7a, 0x65, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x0c, 0x71, 0x75, 0x65, 0x72, 0x79, 0x5f, 0x73, 0x63, 0x6f, - 0x70, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x71, 0x75, 0x65, 0x72, - 0x69, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x53, 0x63, 0x6f, 0x70, - 0x65, 0x52, 0x0b, 0x71, 0x75, 0x65, 0x72, 0x79, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x12, 0x3a, - 0x0a, 0x0c, 0x71, 0x75, 0x65, 0x72, 0x79, 0x5f, 0x69, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x72, 0x2e, 0x76, - 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x49, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x52, 0x0b, 0x71, - 0x75, 0x65, 0x72, 0x79, 0x49, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x22, 0xd1, 0x02, 0x0a, 0x0a, 0x51, - 0x75, 0x65, 0x72, 0x79, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x63, 0x6f, 0x6d, - 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0d, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, - 0x12, 0x27, 0x0a, 0x0f, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x6f, - 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0e, 0x63, 0x6f, 0x6d, 0x70, 0x6f, - 0x6e, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x62, 0x6c, 0x6f, - 0x63, 0x6b, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, - 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x65, - 0x72, 0x69, 0x65, 0x73, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, - 0x52, 0x0b, 0x73, 0x65, 0x72, 0x69, 0x65, 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x23, 0x0a, - 0x0d, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x04, 0x52, 0x0c, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x43, 0x6f, 0x75, - 0x6e, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x5f, 0x63, 0x6f, 0x75, - 0x6e, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, - 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x5f, 0x62, - 0x79, 0x74, 0x65, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x69, 0x6e, 0x64, 0x65, - 0x78, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, - 0x65, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0c, 0x70, - 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x73, - 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, - 0x04, 0x52, 0x0b, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x42, 0x79, 0x74, 0x65, 0x73, 0x22, 0xac, - 0x01, 0x0a, 0x0b, 0x51, 0x75, 0x65, 0x72, 0x79, 0x49, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x12, 0x38, - 0x0a, 0x19, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x69, 0x6e, - 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x04, 0x52, 0x15, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x42, 0x79, 0x74, 0x65, 0x73, 0x49, 0x6e, 0x54, - 0x69, 0x6d, 0x65, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x30, 0x0a, 0x14, 0x74, 0x6f, 0x74, 0x61, - 0x6c, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x64, 0x5f, 0x73, 0x65, 0x72, 0x69, 0x65, 0x73, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x12, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x51, 0x75, 0x65, - 0x72, 0x69, 0x65, 0x64, 0x53, 0x65, 0x72, 0x69, 0x65, 0x73, 0x12, 0x31, 0x0a, 0x14, 0x64, 0x65, - 0x64, 0x75, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6e, 0x65, 0x65, 0x64, - 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x64, 0x65, 0x64, 0x75, 0x70, 0x6c, - 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x65, 0x65, 0x64, 0x65, 0x64, 0x32, 0xbb, 0x07, - 0x0a, 0x0e, 0x51, 0x75, 0x65, 0x72, 0x69, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x12, 0x53, 0x0a, 0x0c, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x73, - 0x12, 0x1f, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x69, 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, 0x20, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x69, 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, 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, 0x41, - 0x0a, 0x06, 0x53, 0x65, 0x72, 0x69, 0x65, 0x73, 0x12, 0x19, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x69, - 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x72, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x72, 0x2e, 0x76, 0x31, - 0x2e, 0x53, 0x65, 0x72, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x00, 0x12, 0x71, 0x0a, 0x16, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x4d, 0x65, 0x72, 0x67, 0x65, - 0x53, 0x74, 0x61, 0x63, 0x6b, 0x74, 0x72, 0x61, 0x63, 0x65, 0x73, 0x12, 0x29, 0x2e, 0x71, 0x75, - 0x65, 0x72, 0x69, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x4d, - 0x65, 0x72, 0x67, 0x65, 0x53, 0x74, 0x61, 0x63, 0x6b, 0x74, 0x72, 0x61, 0x63, 0x65, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x72, + 0x6d, 0x61, 0x78, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x88, 0x01, 0x01, 0x12, 0x31, 0x0a, 0x06, 0x66, + 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x19, 0x2e, 0x71, 0x75, + 0x65, 0x72, 0x69, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, + 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x52, 0x06, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x42, 0x0c, + 0x0a, 0x0a, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x22, 0x6c, 0x0a, 0x1e, + 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x53, 0x74, 0x61, 0x63, 0x6b, + 0x74, 0x72, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x36, + 0x0a, 0x0a, 0x66, 0x6c, 0x61, 0x6d, 0x65, 0x67, 0x72, 0x61, 0x70, 0x68, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, + 0x46, 0x6c, 0x61, 0x6d, 0x65, 0x47, 0x72, 0x61, 0x70, 0x68, 0x52, 0x0a, 0x66, 0x6c, 0x61, 0x6d, + 0x65, 0x67, 0x72, 0x61, 0x70, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x72, 0x65, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x74, 0x72, 0x65, 0x65, 0x22, 0x9d, 0x02, 0x0a, 0x1d, 0x53, + 0x65, 0x6c, 0x65, 0x63, 0x74, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x53, 0x70, 0x61, 0x6e, 0x50, 0x72, + 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x25, 0x0a, 0x0e, + 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x49, 0x44, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x54, 0x79, 0x70, + 0x65, 0x49, 0x44, 0x12, 0x25, 0x0a, 0x0e, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x5f, 0x73, 0x65, 0x6c, + 0x65, 0x63, 0x74, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6c, 0x61, 0x62, + 0x65, 0x6c, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x23, 0x0a, 0x0d, 0x73, 0x70, + 0x61, 0x6e, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x03, 0x28, + 0x09, 0x52, 0x0c, 0x73, 0x70, 0x61, 0x6e, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, + 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, + 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x03, 0x65, 0x6e, 0x64, 0x12, 0x20, 0x0a, 0x09, 0x6d, 0x61, 0x78, 0x5f, 0x6e, + 0x6f, 0x64, 0x65, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x48, 0x00, 0x52, 0x08, 0x6d, 0x61, + 0x78, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x88, 0x01, 0x01, 0x12, 0x31, 0x0a, 0x06, 0x66, 0x6f, 0x72, + 0x6d, 0x61, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x19, 0x2e, 0x71, 0x75, 0x65, 0x72, + 0x69, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x46, 0x6f, + 0x72, 0x6d, 0x61, 0x74, 0x52, 0x06, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x42, 0x0c, 0x0a, 0x0a, + 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x22, 0x6c, 0x0a, 0x1e, 0x53, 0x65, + 0x6c, 0x65, 0x63, 0x74, 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, 0x36, 0x0a, 0x0a, + 0x66, 0x6c, 0x61, 0x6d, 0x65, 0x67, 0x72, 0x61, 0x70, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x16, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x6c, + 0x61, 0x6d, 0x65, 0x47, 0x72, 0x61, 0x70, 0x68, 0x52, 0x0a, 0x66, 0x6c, 0x61, 0x6d, 0x65, 0x67, + 0x72, 0x61, 0x70, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x72, 0x65, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0c, 0x52, 0x04, 0x74, 0x72, 0x65, 0x65, 0x22, 0x8d, 0x01, 0x0a, 0x0b, 0x44, 0x69, 0x66, + 0x66, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3d, 0x0a, 0x04, 0x6c, 0x65, 0x66, 0x74, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x72, + 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x53, + 0x74, 0x61, 0x63, 0x6b, 0x74, 0x72, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x52, 0x04, 0x6c, 0x65, 0x66, 0x74, 0x12, 0x3f, 0x0a, 0x05, 0x72, 0x69, 0x67, 0x68, 0x74, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x53, - 0x74, 0x61, 0x63, 0x6b, 0x74, 0x72, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x00, 0x12, 0x71, 0x0a, 0x16, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x4d, 0x65, - 0x72, 0x67, 0x65, 0x53, 0x70, 0x61, 0x6e, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x29, - 0x2e, 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x6c, 0x65, - 0x63, 0x74, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x53, 0x70, 0x61, 0x6e, 0x50, 0x72, 0x6f, 0x66, 0x69, - 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x71, 0x75, 0x65, 0x72, - 0x69, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 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, 0x12, 0x51, 0x0a, 0x12, 0x53, 0x65, 0x6c, 0x65, 0x63, - 0x74, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x25, 0x2e, + 0x74, 0x61, 0x63, 0x6b, 0x74, 0x72, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x52, 0x05, 0x72, 0x69, 0x67, 0x68, 0x74, 0x22, 0x4a, 0x0a, 0x0c, 0x44, 0x69, 0x66, 0x66, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3a, 0x0a, 0x0a, 0x66, 0x6c, 0x61, 0x6d, + 0x65, 0x67, 0x72, 0x61, 0x70, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x71, + 0x75, 0x65, 0x72, 0x69, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x6c, 0x61, 0x6d, 0x65, 0x47, + 0x72, 0x61, 0x70, 0x68, 0x44, 0x69, 0x66, 0x66, 0x52, 0x0a, 0x66, 0x6c, 0x61, 0x6d, 0x65, 0x67, + 0x72, 0x61, 0x70, 0x68, 0x22, 0x7e, 0x0a, 0x0a, 0x46, 0x6c, 0x61, 0x6d, 0x65, 0x47, 0x72, 0x61, + 0x70, 0x68, 0x12, 0x14, 0x0a, 0x05, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, + 0x09, 0x52, 0x05, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x29, 0x0a, 0x06, 0x6c, 0x65, 0x76, 0x65, + 0x6c, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x69, + 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x06, 0x6c, 0x65, 0x76, + 0x65, 0x6c, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x12, 0x19, 0x0a, 0x08, 0x6d, 0x61, 0x78, + 0x5f, 0x73, 0x65, 0x6c, 0x66, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x6d, 0x61, 0x78, + 0x53, 0x65, 0x6c, 0x66, 0x22, 0xc0, 0x01, 0x0a, 0x0e, 0x46, 0x6c, 0x61, 0x6d, 0x65, 0x47, 0x72, + 0x61, 0x70, 0x68, 0x44, 0x69, 0x66, 0x66, 0x12, 0x14, 0x0a, 0x05, 0x6e, 0x61, 0x6d, 0x65, 0x73, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x29, 0x0a, + 0x06, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, + 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x65, 0x76, 0x65, 0x6c, + 0x52, 0x06, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x74, 0x61, + 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x12, 0x19, + 0x0a, 0x08, 0x6d, 0x61, 0x78, 0x5f, 0x73, 0x65, 0x6c, 0x66, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x07, 0x6d, 0x61, 0x78, 0x53, 0x65, 0x6c, 0x66, 0x12, 0x1c, 0x0a, 0x09, 0x6c, 0x65, 0x66, + 0x74, 0x54, 0x69, 0x63, 0x6b, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x6c, 0x65, + 0x66, 0x74, 0x54, 0x69, 0x63, 0x6b, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x72, 0x69, 0x67, 0x68, 0x74, + 0x54, 0x69, 0x63, 0x6b, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x72, 0x69, 0x67, + 0x68, 0x74, 0x54, 0x69, 0x63, 0x6b, 0x73, 0x22, 0x1f, 0x0a, 0x05, 0x4c, 0x65, 0x76, 0x65, 0x6c, + 0x12, 0x16, 0x0a, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x03, + 0x52, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x22, 0xaf, 0x02, 0x0a, 0x19, 0x53, 0x65, 0x6c, + 0x65, 0x63, 0x74, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x25, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, + 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, + 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x49, 0x44, 0x12, 0x25, 0x0a, + 0x0e, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x53, 0x65, 0x6c, 0x65, + 0x63, 0x74, 0x6f, 0x72, 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, 0x20, 0x0a, 0x09, + 0x6d, 0x61, 0x78, 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x48, + 0x00, 0x52, 0x08, 0x6d, 0x61, 0x78, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x88, 0x01, 0x01, 0x12, 0x53, + 0x0a, 0x14, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x5f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x5f, 0x73, 0x65, + 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x74, + 0x79, 0x70, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x63, 0x6b, 0x54, 0x72, 0x61, + 0x63, 0x65, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x48, 0x01, 0x52, 0x12, 0x73, 0x74, + 0x61, 0x63, 0x6b, 0x54, 0x72, 0x61, 0x63, 0x65, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, + 0x88, 0x01, 0x01, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x6e, 0x6f, 0x64, 0x65, + 0x73, 0x42, 0x17, 0x0a, 0x15, 0x5f, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x5f, 0x74, 0x72, 0x61, 0x63, + 0x65, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x22, 0x84, 0x03, 0x0a, 0x13, 0x53, + 0x65, 0x6c, 0x65, 0x63, 0x74, 0x53, 0x65, 0x72, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x25, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x74, 0x79, + 0x70, 0x65, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x66, + 0x69, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x49, 0x44, 0x12, 0x25, 0x0a, 0x0e, 0x6c, 0x61, 0x62, + 0x65, 0x6c, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0d, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, + 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, 0x19, 0x0a, 0x08, 0x67, 0x72, 0x6f, 0x75, + 0x70, 0x5f, 0x62, 0x79, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x67, 0x72, 0x6f, 0x75, + 0x70, 0x42, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x74, 0x65, 0x70, 0x18, 0x06, 0x20, 0x01, 0x28, + 0x01, 0x52, 0x04, 0x73, 0x74, 0x65, 0x70, 0x12, 0x4a, 0x0a, 0x0b, 0x61, 0x67, 0x67, 0x72, 0x65, + 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x23, 0x2e, 0x74, + 0x79, 0x70, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x69, + 0x65, 0x73, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, + 0x65, 0x48, 0x00, 0x52, 0x0b, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x88, 0x01, 0x01, 0x12, 0x53, 0x0a, 0x14, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x5f, 0x74, 0x72, 0x61, + 0x63, 0x65, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x18, 0x08, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1c, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, + 0x63, 0x6b, 0x54, 0x72, 0x61, 0x63, 0x65, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x48, + 0x01, 0x52, 0x12, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x54, 0x72, 0x61, 0x63, 0x65, 0x53, 0x65, 0x6c, + 0x65, 0x63, 0x74, 0x6f, 0x72, 0x88, 0x01, 0x01, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x61, 0x67, 0x67, + 0x72, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x17, 0x0a, 0x15, 0x5f, 0x73, 0x74, 0x61, + 0x63, 0x6b, 0x5f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, + 0x72, 0x22, 0x40, 0x0a, 0x14, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x53, 0x65, 0x72, 0x69, 0x65, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x28, 0x0a, 0x06, 0x73, 0x65, 0x72, + 0x69, 0x65, 0x73, 0x18, 0x01, 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, 0x53, 0x0a, 0x13, 0x41, 0x6e, 0x61, 0x6c, 0x79, 0x7a, 0x65, 0x51, 0x75, + 0x65, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, + 0x61, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, + 0x12, 0x10, 0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x65, + 0x6e, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x22, 0x8d, 0x01, 0x0a, 0x14, 0x41, 0x6e, 0x61, + 0x6c, 0x79, 0x7a, 0x65, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x39, 0x0a, 0x0c, 0x71, 0x75, 0x65, 0x72, 0x79, 0x5f, 0x73, 0x63, 0x6f, 0x70, 0x65, + 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, + 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x52, + 0x0b, 0x71, 0x75, 0x65, 0x72, 0x79, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x12, 0x3a, 0x0a, 0x0c, + 0x71, 0x75, 0x65, 0x72, 0x79, 0x5f, 0x69, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, + 0x51, 0x75, 0x65, 0x72, 0x79, 0x49, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x52, 0x0b, 0x71, 0x75, 0x65, + 0x72, 0x79, 0x49, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x22, 0xd1, 0x02, 0x0a, 0x0a, 0x51, 0x75, 0x65, + 0x72, 0x79, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x63, 0x6f, 0x6d, 0x70, 0x6f, + 0x6e, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0d, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x27, + 0x0a, 0x0f, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x6f, 0x75, 0x6e, + 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0e, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, + 0x6e, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, + 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x62, 0x6c, + 0x6f, 0x63, 0x6b, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x65, 0x72, 0x69, + 0x65, 0x73, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, + 0x73, 0x65, 0x72, 0x69, 0x65, 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x70, + 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x04, 0x52, 0x0c, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, + 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, + 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x43, 0x6f, + 0x75, 0x6e, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x5f, 0x62, 0x79, 0x74, + 0x65, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x42, + 0x79, 0x74, 0x65, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x5f, + 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0c, 0x70, 0x72, 0x6f, + 0x66, 0x69, 0x6c, 0x65, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x79, 0x6d, + 0x62, 0x6f, 0x6c, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, + 0x0b, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x42, 0x79, 0x74, 0x65, 0x73, 0x22, 0xac, 0x01, 0x0a, + 0x0b, 0x51, 0x75, 0x65, 0x72, 0x79, 0x49, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x12, 0x38, 0x0a, 0x19, + 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x69, 0x6e, 0x5f, 0x74, + 0x69, 0x6d, 0x65, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, + 0x15, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x42, 0x79, 0x74, 0x65, 0x73, 0x49, 0x6e, 0x54, 0x69, 0x6d, + 0x65, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x30, 0x0a, 0x14, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, + 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x64, 0x5f, 0x73, 0x65, 0x72, 0x69, 0x65, 0x73, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x04, 0x52, 0x12, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x51, 0x75, 0x65, 0x72, 0x69, + 0x65, 0x64, 0x53, 0x65, 0x72, 0x69, 0x65, 0x73, 0x12, 0x31, 0x0a, 0x14, 0x64, 0x65, 0x64, 0x75, + 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6e, 0x65, 0x65, 0x64, 0x65, 0x64, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x64, 0x65, 0x64, 0x75, 0x70, 0x6c, 0x69, 0x63, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x65, 0x65, 0x64, 0x65, 0x64, 0x2a, 0x67, 0x0a, 0x0d, 0x50, + 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x1e, 0x0a, 0x1a, + 0x50, 0x52, 0x4f, 0x46, 0x49, 0x4c, 0x45, 0x5f, 0x46, 0x4f, 0x52, 0x4d, 0x41, 0x54, 0x5f, 0x55, + 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1d, 0x0a, 0x19, + 0x50, 0x52, 0x4f, 0x46, 0x49, 0x4c, 0x45, 0x5f, 0x46, 0x4f, 0x52, 0x4d, 0x41, 0x54, 0x5f, 0x46, + 0x4c, 0x41, 0x4d, 0x45, 0x47, 0x52, 0x41, 0x50, 0x48, 0x10, 0x01, 0x12, 0x17, 0x0a, 0x13, 0x50, + 0x52, 0x4f, 0x46, 0x49, 0x4c, 0x45, 0x5f, 0x46, 0x4f, 0x52, 0x4d, 0x41, 0x54, 0x5f, 0x54, 0x52, + 0x45, 0x45, 0x10, 0x02, 0x32, 0xbb, 0x07, 0x0a, 0x0e, 0x51, 0x75, 0x65, 0x72, 0x69, 0x65, 0x72, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x53, 0x0a, 0x0c, 0x50, 0x72, 0x6f, 0x66, 0x69, + 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x73, 0x12, 0x1f, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x69, 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, 0x20, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x69, + 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, 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, 0x41, 0x0a, 0x06, 0x53, 0x65, 0x72, 0x69, 0x65, 0x73, 0x12, + 0x19, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x72, + 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x71, 0x75, 0x65, + 0x72, 0x69, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x72, 0x69, 0x65, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x71, 0x0a, 0x16, 0x53, 0x65, 0x6c, 0x65, + 0x63, 0x74, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x53, 0x74, 0x61, 0x63, 0x6b, 0x74, 0x72, 0x61, 0x63, + 0x65, 0x73, 0x12, 0x29, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, + 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x53, 0x74, 0x61, 0x63, 0x6b, + 0x74, 0x72, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x6c, 0x65, 0x63, - 0x74, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x76, 0x31, - 0x2e, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x22, 0x00, 0x12, 0x53, 0x0a, 0x0c, 0x53, 0x65, - 0x6c, 0x65, 0x63, 0x74, 0x53, 0x65, 0x72, 0x69, 0x65, 0x73, 0x12, 0x1f, 0x2e, 0x71, 0x75, 0x65, - 0x72, 0x69, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x53, 0x65, - 0x72, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x71, 0x75, - 0x65, 0x72, 0x69, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x53, - 0x65, 0x72, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, - 0x3b, 0x0a, 0x04, 0x44, 0x69, 0x66, 0x66, 0x12, 0x17, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, - 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x69, 0x66, 0x66, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x18, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x69, - 0x66, 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x58, 0x0a, 0x0f, - 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, - 0x20, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x72, - 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x21, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, - 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x53, 0x0a, 0x0c, 0x41, 0x6e, 0x61, 0x6c, 0x79, 0x7a, - 0x65, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x1f, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x72, - 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x6e, 0x61, 0x6c, 0x79, 0x7a, 0x65, 0x51, 0x75, 0x65, 0x72, 0x79, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, - 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x6e, 0x61, 0x6c, 0x79, 0x7a, 0x65, 0x51, 0x75, 0x65, 0x72, - 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0xab, 0x01, 0x0a, 0x0e, - 0x63, 0x6f, 0x6d, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x42, 0x0c, - 0x51, 0x75, 0x65, 0x72, 0x69, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x42, - 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, 0x71, 0x75, - 0x65, 0x72, 0x69, 0x65, 0x72, 0x2f, 0x76, 0x31, 0x3b, 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x72, - 0x76, 0x31, 0xa2, 0x02, 0x03, 0x51, 0x58, 0x58, 0xaa, 0x02, 0x0a, 0x51, 0x75, 0x65, 0x72, 0x69, - 0x65, 0x72, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x0a, 0x51, 0x75, 0x65, 0x72, 0x69, 0x65, 0x72, 0x5c, - 0x56, 0x31, 0xe2, 0x02, 0x16, 0x51, 0x75, 0x65, 0x72, 0x69, 0x65, 0x72, 0x5c, 0x56, 0x31, 0x5c, - 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x0b, 0x51, 0x75, - 0x65, 0x72, 0x69, 0x65, 0x72, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x33, + 0x74, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x53, 0x74, 0x61, 0x63, 0x6b, 0x74, 0x72, 0x61, 0x63, 0x65, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x71, 0x0a, 0x16, 0x53, + 0x65, 0x6c, 0x65, 0x63, 0x74, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x53, 0x70, 0x61, 0x6e, 0x50, 0x72, + 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x29, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x72, 0x2e, + 0x76, 0x31, 0x2e, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x53, 0x70, + 0x61, 0x6e, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x2a, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, + 0x6c, 0x65, 0x63, 0x74, 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, 0x12, 0x51, + 0x0a, 0x12, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x50, 0x72, 0x6f, + 0x66, 0x69, 0x6c, 0x65, 0x12, 0x25, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x72, 0x2e, 0x76, + 0x31, 0x2e, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x50, 0x72, 0x6f, + 0x66, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x22, + 0x00, 0x12, 0x53, 0x0a, 0x0c, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x53, 0x65, 0x72, 0x69, 0x65, + 0x73, 0x12, 0x1f, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, + 0x65, 0x6c, 0x65, 0x63, 0x74, 0x53, 0x65, 0x72, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, + 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x53, 0x65, 0x72, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x3b, 0x0a, 0x04, 0x44, 0x69, 0x66, 0x66, 0x12, 0x17, + 0x2e, 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x69, 0x66, 0x66, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, + 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x69, 0x66, 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x00, 0x12, 0x58, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, + 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x20, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x76, + 0x31, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x74, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, + 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x53, 0x74, + 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x53, 0x0a, + 0x0c, 0x41, 0x6e, 0x61, 0x6c, 0x79, 0x7a, 0x65, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x1f, 0x2e, + 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x6e, 0x61, 0x6c, 0x79, + 0x7a, 0x65, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, + 0x2e, 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x6e, 0x61, 0x6c, + 0x79, 0x7a, 0x65, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x00, 0x42, 0xab, 0x01, 0x0a, 0x0e, 0x63, 0x6f, 0x6d, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x69, + 0x65, 0x72, 0x2e, 0x76, 0x31, 0x42, 0x0c, 0x51, 0x75, 0x65, 0x72, 0x69, 0x65, 0x72, 0x50, 0x72, + 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x42, 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, 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x72, 0x2f, 0x76, 0x31, 0x3b, + 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x72, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x51, 0x58, 0x58, 0xaa, + 0x02, 0x0a, 0x51, 0x75, 0x65, 0x72, 0x69, 0x65, 0x72, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x0a, 0x51, + 0x75, 0x65, 0x72, 0x69, 0x65, 0x72, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x16, 0x51, 0x75, 0x65, 0x72, + 0x69, 0x65, 0x72, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, + 0x74, 0x61, 0xea, 0x02, 0x0b, 0x51, 0x75, 0x65, 0x72, 0x69, 0x65, 0x72, 0x3a, 0x3a, 0x56, 0x31, + 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1644,84 +1746,88 @@ func file_querier_v1_querier_proto_rawDescGZIP() []byte { return file_querier_v1_querier_proto_rawDescData } +var file_querier_v1_querier_proto_enumTypes = make([]protoimpl.EnumInfo, 1) var file_querier_v1_querier_proto_msgTypes = make([]protoimpl.MessageInfo, 20) var file_querier_v1_querier_proto_goTypes = []interface{}{ - (*ProfileTypesRequest)(nil), // 0: querier.v1.ProfileTypesRequest - (*ProfileTypesResponse)(nil), // 1: querier.v1.ProfileTypesResponse - (*SeriesRequest)(nil), // 2: querier.v1.SeriesRequest - (*SeriesResponse)(nil), // 3: querier.v1.SeriesResponse - (*SelectMergeStacktracesRequest)(nil), // 4: querier.v1.SelectMergeStacktracesRequest - (*SelectMergeStacktracesResponse)(nil), // 5: querier.v1.SelectMergeStacktracesResponse - (*SelectMergeSpanProfileRequest)(nil), // 6: querier.v1.SelectMergeSpanProfileRequest - (*SelectMergeSpanProfileResponse)(nil), // 7: querier.v1.SelectMergeSpanProfileResponse - (*DiffRequest)(nil), // 8: querier.v1.DiffRequest - (*DiffResponse)(nil), // 9: querier.v1.DiffResponse - (*FlameGraph)(nil), // 10: querier.v1.FlameGraph - (*FlameGraphDiff)(nil), // 11: querier.v1.FlameGraphDiff - (*Level)(nil), // 12: querier.v1.Level - (*SelectMergeProfileRequest)(nil), // 13: querier.v1.SelectMergeProfileRequest - (*SelectSeriesRequest)(nil), // 14: querier.v1.SelectSeriesRequest - (*SelectSeriesResponse)(nil), // 15: querier.v1.SelectSeriesResponse - (*AnalyzeQueryRequest)(nil), // 16: querier.v1.AnalyzeQueryRequest - (*AnalyzeQueryResponse)(nil), // 17: querier.v1.AnalyzeQueryResponse - (*QueryScope)(nil), // 18: querier.v1.QueryScope - (*QueryImpact)(nil), // 19: querier.v1.QueryImpact - (*v1.ProfileType)(nil), // 20: types.v1.ProfileType - (*v1.Labels)(nil), // 21: types.v1.Labels - (*v1.StackTraceSelector)(nil), // 22: types.v1.StackTraceSelector - (v1.TimeSeriesAggregationType)(0), // 23: types.v1.TimeSeriesAggregationType - (*v1.Series)(nil), // 24: types.v1.Series - (*v1.LabelValuesRequest)(nil), // 25: types.v1.LabelValuesRequest - (*v1.LabelNamesRequest)(nil), // 26: types.v1.LabelNamesRequest - (*v1.GetProfileStatsRequest)(nil), // 27: types.v1.GetProfileStatsRequest - (*v1.LabelValuesResponse)(nil), // 28: types.v1.LabelValuesResponse - (*v1.LabelNamesResponse)(nil), // 29: types.v1.LabelNamesResponse - (*v11.Profile)(nil), // 30: google.v1.Profile - (*v1.GetProfileStatsResponse)(nil), // 31: types.v1.GetProfileStatsResponse + (ProfileFormat)(0), // 0: querier.v1.ProfileFormat + (*ProfileTypesRequest)(nil), // 1: querier.v1.ProfileTypesRequest + (*ProfileTypesResponse)(nil), // 2: querier.v1.ProfileTypesResponse + (*SeriesRequest)(nil), // 3: querier.v1.SeriesRequest + (*SeriesResponse)(nil), // 4: querier.v1.SeriesResponse + (*SelectMergeStacktracesRequest)(nil), // 5: querier.v1.SelectMergeStacktracesRequest + (*SelectMergeStacktracesResponse)(nil), // 6: querier.v1.SelectMergeStacktracesResponse + (*SelectMergeSpanProfileRequest)(nil), // 7: querier.v1.SelectMergeSpanProfileRequest + (*SelectMergeSpanProfileResponse)(nil), // 8: querier.v1.SelectMergeSpanProfileResponse + (*DiffRequest)(nil), // 9: querier.v1.DiffRequest + (*DiffResponse)(nil), // 10: querier.v1.DiffResponse + (*FlameGraph)(nil), // 11: querier.v1.FlameGraph + (*FlameGraphDiff)(nil), // 12: querier.v1.FlameGraphDiff + (*Level)(nil), // 13: querier.v1.Level + (*SelectMergeProfileRequest)(nil), // 14: querier.v1.SelectMergeProfileRequest + (*SelectSeriesRequest)(nil), // 15: querier.v1.SelectSeriesRequest + (*SelectSeriesResponse)(nil), // 16: querier.v1.SelectSeriesResponse + (*AnalyzeQueryRequest)(nil), // 17: querier.v1.AnalyzeQueryRequest + (*AnalyzeQueryResponse)(nil), // 18: querier.v1.AnalyzeQueryResponse + (*QueryScope)(nil), // 19: querier.v1.QueryScope + (*QueryImpact)(nil), // 20: querier.v1.QueryImpact + (*v1.ProfileType)(nil), // 21: types.v1.ProfileType + (*v1.Labels)(nil), // 22: types.v1.Labels + (*v1.StackTraceSelector)(nil), // 23: types.v1.StackTraceSelector + (v1.TimeSeriesAggregationType)(0), // 24: types.v1.TimeSeriesAggregationType + (*v1.Series)(nil), // 25: types.v1.Series + (*v1.LabelValuesRequest)(nil), // 26: types.v1.LabelValuesRequest + (*v1.LabelNamesRequest)(nil), // 27: types.v1.LabelNamesRequest + (*v1.GetProfileStatsRequest)(nil), // 28: types.v1.GetProfileStatsRequest + (*v1.LabelValuesResponse)(nil), // 29: types.v1.LabelValuesResponse + (*v1.LabelNamesResponse)(nil), // 30: types.v1.LabelNamesResponse + (*v11.Profile)(nil), // 31: google.v1.Profile + (*v1.GetProfileStatsResponse)(nil), // 32: types.v1.GetProfileStatsResponse } var file_querier_v1_querier_proto_depIdxs = []int32{ - 20, // 0: querier.v1.ProfileTypesResponse.profile_types:type_name -> types.v1.ProfileType - 21, // 1: querier.v1.SeriesResponse.labels_set:type_name -> types.v1.Labels - 10, // 2: querier.v1.SelectMergeStacktracesResponse.flamegraph:type_name -> querier.v1.FlameGraph - 10, // 3: querier.v1.SelectMergeSpanProfileResponse.flamegraph:type_name -> querier.v1.FlameGraph - 4, // 4: querier.v1.DiffRequest.left:type_name -> querier.v1.SelectMergeStacktracesRequest - 4, // 5: querier.v1.DiffRequest.right:type_name -> querier.v1.SelectMergeStacktracesRequest - 11, // 6: querier.v1.DiffResponse.flamegraph:type_name -> querier.v1.FlameGraphDiff - 12, // 7: querier.v1.FlameGraph.levels:type_name -> querier.v1.Level - 12, // 8: querier.v1.FlameGraphDiff.levels:type_name -> querier.v1.Level - 22, // 9: querier.v1.SelectMergeProfileRequest.stack_trace_selector:type_name -> types.v1.StackTraceSelector - 23, // 10: querier.v1.SelectSeriesRequest.aggregation:type_name -> types.v1.TimeSeriesAggregationType - 22, // 11: querier.v1.SelectSeriesRequest.stack_trace_selector:type_name -> types.v1.StackTraceSelector - 24, // 12: querier.v1.SelectSeriesResponse.series:type_name -> types.v1.Series - 18, // 13: querier.v1.AnalyzeQueryResponse.query_scopes:type_name -> querier.v1.QueryScope - 19, // 14: querier.v1.AnalyzeQueryResponse.query_impact:type_name -> querier.v1.QueryImpact - 0, // 15: querier.v1.QuerierService.ProfileTypes:input_type -> querier.v1.ProfileTypesRequest - 25, // 16: querier.v1.QuerierService.LabelValues:input_type -> types.v1.LabelValuesRequest - 26, // 17: querier.v1.QuerierService.LabelNames:input_type -> types.v1.LabelNamesRequest - 2, // 18: querier.v1.QuerierService.Series:input_type -> querier.v1.SeriesRequest - 4, // 19: querier.v1.QuerierService.SelectMergeStacktraces:input_type -> querier.v1.SelectMergeStacktracesRequest - 6, // 20: querier.v1.QuerierService.SelectMergeSpanProfile:input_type -> querier.v1.SelectMergeSpanProfileRequest - 13, // 21: querier.v1.QuerierService.SelectMergeProfile:input_type -> querier.v1.SelectMergeProfileRequest - 14, // 22: querier.v1.QuerierService.SelectSeries:input_type -> querier.v1.SelectSeriesRequest - 8, // 23: querier.v1.QuerierService.Diff:input_type -> querier.v1.DiffRequest - 27, // 24: querier.v1.QuerierService.GetProfileStats:input_type -> types.v1.GetProfileStatsRequest - 16, // 25: querier.v1.QuerierService.AnalyzeQuery:input_type -> querier.v1.AnalyzeQueryRequest - 1, // 26: querier.v1.QuerierService.ProfileTypes:output_type -> querier.v1.ProfileTypesResponse - 28, // 27: querier.v1.QuerierService.LabelValues:output_type -> types.v1.LabelValuesResponse - 29, // 28: querier.v1.QuerierService.LabelNames:output_type -> types.v1.LabelNamesResponse - 3, // 29: querier.v1.QuerierService.Series:output_type -> querier.v1.SeriesResponse - 5, // 30: querier.v1.QuerierService.SelectMergeStacktraces:output_type -> querier.v1.SelectMergeStacktracesResponse - 7, // 31: querier.v1.QuerierService.SelectMergeSpanProfile:output_type -> querier.v1.SelectMergeSpanProfileResponse - 30, // 32: querier.v1.QuerierService.SelectMergeProfile:output_type -> google.v1.Profile - 15, // 33: querier.v1.QuerierService.SelectSeries:output_type -> querier.v1.SelectSeriesResponse - 9, // 34: querier.v1.QuerierService.Diff:output_type -> querier.v1.DiffResponse - 31, // 35: querier.v1.QuerierService.GetProfileStats:output_type -> types.v1.GetProfileStatsResponse - 17, // 36: querier.v1.QuerierService.AnalyzeQuery:output_type -> querier.v1.AnalyzeQueryResponse - 26, // [26:37] is the sub-list for method output_type - 15, // [15:26] is the sub-list for method input_type - 15, // [15:15] is the sub-list for extension type_name - 15, // [15:15] is the sub-list for extension extendee - 0, // [0:15] is the sub-list for field type_name + 21, // 0: querier.v1.ProfileTypesResponse.profile_types:type_name -> types.v1.ProfileType + 22, // 1: querier.v1.SeriesResponse.labels_set:type_name -> types.v1.Labels + 0, // 2: querier.v1.SelectMergeStacktracesRequest.format:type_name -> querier.v1.ProfileFormat + 11, // 3: querier.v1.SelectMergeStacktracesResponse.flamegraph:type_name -> querier.v1.FlameGraph + 0, // 4: querier.v1.SelectMergeSpanProfileRequest.format:type_name -> querier.v1.ProfileFormat + 11, // 5: querier.v1.SelectMergeSpanProfileResponse.flamegraph:type_name -> querier.v1.FlameGraph + 5, // 6: querier.v1.DiffRequest.left:type_name -> querier.v1.SelectMergeStacktracesRequest + 5, // 7: querier.v1.DiffRequest.right:type_name -> querier.v1.SelectMergeStacktracesRequest + 12, // 8: querier.v1.DiffResponse.flamegraph:type_name -> querier.v1.FlameGraphDiff + 13, // 9: querier.v1.FlameGraph.levels:type_name -> querier.v1.Level + 13, // 10: querier.v1.FlameGraphDiff.levels:type_name -> querier.v1.Level + 23, // 11: querier.v1.SelectMergeProfileRequest.stack_trace_selector:type_name -> types.v1.StackTraceSelector + 24, // 12: querier.v1.SelectSeriesRequest.aggregation:type_name -> types.v1.TimeSeriesAggregationType + 23, // 13: querier.v1.SelectSeriesRequest.stack_trace_selector:type_name -> types.v1.StackTraceSelector + 25, // 14: querier.v1.SelectSeriesResponse.series:type_name -> types.v1.Series + 19, // 15: querier.v1.AnalyzeQueryResponse.query_scopes:type_name -> querier.v1.QueryScope + 20, // 16: querier.v1.AnalyzeQueryResponse.query_impact:type_name -> querier.v1.QueryImpact + 1, // 17: querier.v1.QuerierService.ProfileTypes:input_type -> querier.v1.ProfileTypesRequest + 26, // 18: querier.v1.QuerierService.LabelValues:input_type -> types.v1.LabelValuesRequest + 27, // 19: querier.v1.QuerierService.LabelNames:input_type -> types.v1.LabelNamesRequest + 3, // 20: querier.v1.QuerierService.Series:input_type -> querier.v1.SeriesRequest + 5, // 21: querier.v1.QuerierService.SelectMergeStacktraces:input_type -> querier.v1.SelectMergeStacktracesRequest + 7, // 22: querier.v1.QuerierService.SelectMergeSpanProfile:input_type -> querier.v1.SelectMergeSpanProfileRequest + 14, // 23: querier.v1.QuerierService.SelectMergeProfile:input_type -> querier.v1.SelectMergeProfileRequest + 15, // 24: querier.v1.QuerierService.SelectSeries:input_type -> querier.v1.SelectSeriesRequest + 9, // 25: querier.v1.QuerierService.Diff:input_type -> querier.v1.DiffRequest + 28, // 26: querier.v1.QuerierService.GetProfileStats:input_type -> types.v1.GetProfileStatsRequest + 17, // 27: querier.v1.QuerierService.AnalyzeQuery:input_type -> querier.v1.AnalyzeQueryRequest + 2, // 28: querier.v1.QuerierService.ProfileTypes:output_type -> querier.v1.ProfileTypesResponse + 29, // 29: querier.v1.QuerierService.LabelValues:output_type -> types.v1.LabelValuesResponse + 30, // 30: querier.v1.QuerierService.LabelNames:output_type -> types.v1.LabelNamesResponse + 4, // 31: querier.v1.QuerierService.Series:output_type -> querier.v1.SeriesResponse + 6, // 32: querier.v1.QuerierService.SelectMergeStacktraces:output_type -> querier.v1.SelectMergeStacktracesResponse + 8, // 33: querier.v1.QuerierService.SelectMergeSpanProfile:output_type -> querier.v1.SelectMergeSpanProfileResponse + 31, // 34: querier.v1.QuerierService.SelectMergeProfile:output_type -> google.v1.Profile + 16, // 35: querier.v1.QuerierService.SelectSeries:output_type -> querier.v1.SelectSeriesResponse + 10, // 36: querier.v1.QuerierService.Diff:output_type -> querier.v1.DiffResponse + 32, // 37: querier.v1.QuerierService.GetProfileStats:output_type -> types.v1.GetProfileStatsResponse + 18, // 38: querier.v1.QuerierService.AnalyzeQuery:output_type -> querier.v1.AnalyzeQueryResponse + 28, // [28:39] is the sub-list for method output_type + 17, // [17:28] is the sub-list for method input_type + 17, // [17:17] is the sub-list for extension type_name + 17, // [17:17] is the sub-list for extension extendee + 0, // [0:17] is the sub-list for field type_name } func init() { file_querier_v1_querier_proto_init() } @@ -1980,13 +2086,14 @@ func file_querier_v1_querier_proto_init() { File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_querier_v1_querier_proto_rawDesc, - NumEnums: 0, + NumEnums: 1, NumMessages: 20, NumExtensions: 0, NumServices: 1, }, GoTypes: file_querier_v1_querier_proto_goTypes, DependencyIndexes: file_querier_v1_querier_proto_depIdxs, + EnumInfos: file_querier_v1_querier_proto_enumTypes, MessageInfos: file_querier_v1_querier_proto_msgTypes, }.Build() File_querier_v1_querier_proto = out.File diff --git a/api/gen/proto/go/querier/v1/querier_vtproto.pb.go b/api/gen/proto/go/querier/v1/querier_vtproto.pb.go index af659588c7..fd94196998 100644 --- a/api/gen/proto/go/querier/v1/querier_vtproto.pb.go +++ b/api/gen/proto/go/querier/v1/querier_vtproto.pb.go @@ -136,6 +136,7 @@ func (m *SelectMergeStacktracesRequest) CloneVT() *SelectMergeStacktracesRequest r.LabelSelector = m.LabelSelector r.Start = m.Start r.End = m.End + r.Format = m.Format if rhs := m.MaxNodes; rhs != nil { tmpVal := *rhs r.MaxNodes = &tmpVal @@ -157,6 +158,11 @@ func (m *SelectMergeStacktracesResponse) CloneVT() *SelectMergeStacktracesRespon } r := new(SelectMergeStacktracesResponse) r.Flamegraph = m.Flamegraph.CloneVT() + if rhs := m.Tree; rhs != nil { + tmpBytes := make([]byte, len(rhs)) + copy(tmpBytes, rhs) + r.Tree = tmpBytes + } if len(m.unknownFields) > 0 { r.unknownFields = make([]byte, len(m.unknownFields)) copy(r.unknownFields, m.unknownFields) @@ -177,6 +183,7 @@ func (m *SelectMergeSpanProfileRequest) CloneVT() *SelectMergeSpanProfileRequest r.LabelSelector = m.LabelSelector r.Start = m.Start r.End = m.End + r.Format = m.Format if rhs := m.SpanSelector; rhs != nil { tmpContainer := make([]string, len(rhs)) copy(tmpContainer, rhs) @@ -203,6 +210,11 @@ func (m *SelectMergeSpanProfileResponse) CloneVT() *SelectMergeSpanProfileRespon } r := new(SelectMergeSpanProfileResponse) r.Flamegraph = m.Flamegraph.CloneVT() + if rhs := m.Tree; rhs != nil { + tmpBytes := make([]byte, len(rhs)) + copy(tmpBytes, rhs) + r.Tree = tmpBytes + } if len(m.unknownFields) > 0 { r.unknownFields = make([]byte, len(m.unknownFields)) copy(r.unknownFields, m.unknownFields) @@ -671,6 +683,9 @@ func (this *SelectMergeStacktracesRequest) EqualVT(that *SelectMergeStacktracesR if p, q := this.MaxNodes, that.MaxNodes; (p == nil && q != nil) || (p != nil && (q == nil || *p != *q)) { return false } + if this.Format != that.Format { + return false + } return string(this.unknownFields) == string(that.unknownFields) } @@ -690,6 +705,9 @@ func (this *SelectMergeStacktracesResponse) EqualVT(that *SelectMergeStacktraces if !this.Flamegraph.EqualVT(that.Flamegraph) { return false } + if string(this.Tree) != string(that.Tree) { + return false + } return string(this.unknownFields) == string(that.unknownFields) } @@ -730,6 +748,9 @@ func (this *SelectMergeSpanProfileRequest) EqualVT(that *SelectMergeSpanProfileR if p, q := this.MaxNodes, that.MaxNodes; (p == nil && q != nil) || (p != nil && (q == nil || *p != *q)) { return false } + if this.Format != that.Format { + return false + } return string(this.unknownFields) == string(that.unknownFields) } @@ -749,6 +770,9 @@ func (this *SelectMergeSpanProfileResponse) EqualVT(that *SelectMergeSpanProfile if !this.Flamegraph.EqualVT(that.Flamegraph) { return false } + if string(this.Tree) != string(that.Tree) { + return false + } return string(this.unknownFields) == string(that.unknownFields) } @@ -1905,6 +1929,11 @@ func (m *SelectMergeStacktracesRequest) MarshalToSizedBufferVT(dAtA []byte) (int i -= len(m.unknownFields) copy(dAtA[i:], m.unknownFields) } + if m.Format != 0 { + i = protohelpers.EncodeVarint(dAtA, i, uint64(m.Format)) + i-- + dAtA[i] = 0x30 + } if m.MaxNodes != nil { i = protohelpers.EncodeVarint(dAtA, i, uint64(*m.MaxNodes)) i-- @@ -1967,6 +1996,13 @@ func (m *SelectMergeStacktracesResponse) MarshalToSizedBufferVT(dAtA []byte) (in i -= len(m.unknownFields) copy(dAtA[i:], m.unknownFields) } + if len(m.Tree) > 0 { + i -= len(m.Tree) + copy(dAtA[i:], m.Tree) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.Tree))) + i-- + dAtA[i] = 0x12 + } if m.Flamegraph != nil { size, err := m.Flamegraph.MarshalToSizedBufferVT(dAtA[:i]) if err != nil { @@ -2010,6 +2046,11 @@ func (m *SelectMergeSpanProfileRequest) MarshalToSizedBufferVT(dAtA []byte) (int i -= len(m.unknownFields) copy(dAtA[i:], m.unknownFields) } + if m.Format != 0 { + i = protohelpers.EncodeVarint(dAtA, i, uint64(m.Format)) + i-- + dAtA[i] = 0x38 + } if m.MaxNodes != nil { i = protohelpers.EncodeVarint(dAtA, i, uint64(*m.MaxNodes)) i-- @@ -2081,6 +2122,13 @@ func (m *SelectMergeSpanProfileResponse) MarshalToSizedBufferVT(dAtA []byte) (in i -= len(m.unknownFields) copy(dAtA[i:], m.unknownFields) } + if len(m.Tree) > 0 { + i -= len(m.Tree) + copy(dAtA[i:], m.Tree) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.Tree))) + i-- + dAtA[i] = 0x12 + } if m.Flamegraph != nil { size, err := m.Flamegraph.MarshalToSizedBufferVT(dAtA[:i]) if err != nil { @@ -2971,6 +3019,9 @@ func (m *SelectMergeStacktracesRequest) SizeVT() (n int) { if m.MaxNodes != nil { n += 1 + protohelpers.SizeOfVarint(uint64(*m.MaxNodes)) } + if m.Format != 0 { + n += 1 + protohelpers.SizeOfVarint(uint64(m.Format)) + } n += len(m.unknownFields) return n } @@ -2985,6 +3036,10 @@ func (m *SelectMergeStacktracesResponse) SizeVT() (n int) { l = m.Flamegraph.SizeVT() n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) } + l = len(m.Tree) + if l > 0 { + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } n += len(m.unknownFields) return n } @@ -3018,6 +3073,9 @@ func (m *SelectMergeSpanProfileRequest) SizeVT() (n int) { if m.MaxNodes != nil { n += 1 + protohelpers.SizeOfVarint(uint64(*m.MaxNodes)) } + if m.Format != 0 { + n += 1 + protohelpers.SizeOfVarint(uint64(m.Format)) + } n += len(m.unknownFields) return n } @@ -3032,6 +3090,10 @@ func (m *SelectMergeSpanProfileResponse) SizeVT() (n int) { l = m.Flamegraph.SizeVT() n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) } + l = len(m.Tree) + if l > 0 { + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } n += len(m.unknownFields) return n } @@ -3928,6 +3990,25 @@ func (m *SelectMergeStacktracesRequest) UnmarshalVT(dAtA []byte) error { } } m.MaxNodes = &v + case 6: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Format", wireType) + } + m.Format = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Format |= ProfileFormat(b&0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := protohelpers.Skip(dAtA[iNdEx:]) @@ -4015,6 +4096,40 @@ func (m *SelectMergeStacktracesResponse) UnmarshalVT(dAtA []byte) error { return err } iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Tree", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Tree = append(m.Tree[:0], dAtA[iNdEx:postIndex]...) + if m.Tree == nil { + m.Tree = []byte{} + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := protohelpers.Skip(dAtA[iNdEx:]) @@ -4220,6 +4335,25 @@ func (m *SelectMergeSpanProfileRequest) UnmarshalVT(dAtA []byte) error { } } m.MaxNodes = &v + case 7: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Format", wireType) + } + m.Format = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Format |= ProfileFormat(b&0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := protohelpers.Skip(dAtA[iNdEx:]) @@ -4307,6 +4441,40 @@ func (m *SelectMergeSpanProfileResponse) UnmarshalVT(dAtA []byte) error { return err } iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Tree", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Tree = append(m.Tree[:0], dAtA[iNdEx:postIndex]...) + if m.Tree == nil { + m.Tree = []byte{} + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := protohelpers.Skip(dAtA[iNdEx:]) diff --git a/api/ingester/v1/ingester.proto b/api/ingester/v1/ingester.proto index 52bf13600e..1c294519ad 100644 --- a/api/ingester/v1/ingester.proto +++ b/api/ingester/v1/ingester.proto @@ -136,8 +136,10 @@ message MergeSpanProfileResult { } message ProfileSets { + // DEPRECATED: Use fingerprints instead. repeated types.v1.Labels labelsSets = 1; repeated SeriesProfile profiles = 2; + repeated uint64 fingerprints = 3; } message SeriesProfile { diff --git a/api/openapiv2/gen/phlare.swagger.json b/api/openapiv2/gen/phlare.swagger.json index 145f6a2369..1162fbcc02 100644 --- a/api/openapiv2/gen/phlare.swagger.json +++ b/api/openapiv2/gen/phlare.swagger.json @@ -1063,6 +1063,15 @@ } } }, + "v1ProfileFormat": { + "type": "string", + "enum": [ + "PROFILE_FORMAT_UNSPECIFIED", + "PROFILE_FORMAT_FLAMEGRAPH", + "PROFILE_FORMAT_TREE" + ], + "default": "PROFILE_FORMAT_UNSPECIFIED" + }, "v1ProfileSets": { "type": "object", "properties": { @@ -1071,7 +1080,8 @@ "items": { "type": "object", "$ref": "#/definitions/v1Labels" - } + }, + "description": "DEPRECATED: Use fingerprints instead." }, "profiles": { "type": "array", @@ -1079,6 +1089,13 @@ "type": "object", "$ref": "#/definitions/v1SeriesProfile" } + }, + "fingerprints": { + "type": "array", + "items": { + "type": "string", + "format": "uint64" + } } } }, @@ -1238,6 +1255,11 @@ "properties": { "flamegraph": { "$ref": "#/definitions/v1FlameGraph" + }, + "tree": { + "type": "string", + "format": "byte", + "description": "Pyroscope tree bytes." } } }, @@ -1264,6 +1286,10 @@ "type": "string", "format": "int64", "title": "Limit the nodes returned to only show the node with the max_node's biggest total" + }, + "format": { + "$ref": "#/definitions/v1ProfileFormat", + "description": "Profile format specifies the format of profile to be returned.\nIf not specified, the profile will be returned in flame graph format." } } }, @@ -1272,6 +1298,11 @@ "properties": { "flamegraph": { "$ref": "#/definitions/v1FlameGraph" + }, + "tree": { + "type": "string", + "format": "byte", + "description": "Pyroscope tree bytes." } } }, diff --git a/api/querier/v1/querier.proto b/api/querier/v1/querier.proto index 3192ecc663..78ae0da066 100644 --- a/api/querier/v1/querier.proto +++ b/api/querier/v1/querier.proto @@ -68,10 +68,21 @@ message SelectMergeStacktracesRequest { int64 end = 4; // Limit the nodes returned to only show the node with the max_node's biggest total optional int64 max_nodes = 5; + // Profile format specifies the format of profile to be returned. + // If not specified, the profile will be returned in flame graph format. + ProfileFormat format = 6; +} + +enum ProfileFormat { + PROFILE_FORMAT_UNSPECIFIED = 0; + PROFILE_FORMAT_FLAMEGRAPH = 1; + PROFILE_FORMAT_TREE = 2; } message SelectMergeStacktracesResponse { FlameGraph flamegraph = 1; + // Pyroscope tree bytes. + bytes tree = 2; } message SelectMergeSpanProfileRequest { @@ -84,10 +95,15 @@ message SelectMergeSpanProfileRequest { int64 end = 5; // Limit the nodes returned to only show the node with the max_node's biggest total optional int64 max_nodes = 6; + // Profile format specifies the format of profile to be returned. + // If not specified, the profile will be returned in flame graph format. + ProfileFormat format = 7; } message SelectMergeSpanProfileResponse { FlameGraph flamegraph = 1; + // Pyroscope tree bytes. + bytes tree = 2; } message DiffRequest { diff --git a/cmd/profilecli/tsdb.go b/cmd/profilecli/tsdb.go index 4d12ec4649..6c0d7264f6 100644 --- a/cmd/profilecli/tsdb.go +++ b/cmd/profilecli/tsdb.go @@ -44,7 +44,7 @@ func tsdbSeries(ctx context.Context, path string) error { return fmt.Errorf("error retrieving seriesRef: %w", err) } - line.Labels, err = lbls.ToPrometheusLabels().MarshalJSON() + line.Labels, err = json.Marshal(lbls) if err != nil { return fmt.Errorf("error marshalling labels: %w", err) } diff --git a/cmd/pyroscope/frontend.Dockerfile b/cmd/pyroscope/frontend.Dockerfile new file mode 100644 index 0000000000..d516e956d1 --- /dev/null +++ b/cmd/pyroscope/frontend.Dockerfile @@ -0,0 +1,13 @@ +FROM node:18 as builder +RUN apt-get update && apt-get install -y libpango1.0-dev libcairo2-dev +WORKDIR /pyroscope +COPY yarn.lock package.json tsconfig.json ./ +RUN yarn --frozen-lockfile +COPY scripts/webpack ./scripts/webpack/ +COPY public/app ./public/app +COPY public/templates ./public/templates +RUN yarn build + +# Usage: docker build -f cmd/pyroscope/frontend.Dockerfile --output=public/build . +FROM scratch +COPY --from=builder /pyroscope/public/build / \ No newline at end of file diff --git a/cmd/pyroscope/help-all.txt.tmpl b/cmd/pyroscope/help-all.txt.tmpl index 0b0c0de789..bf47cbe097 100644 --- a/cmd/pyroscope/help-all.txt.tmpl +++ b/cmd/pyroscope/help-all.txt.tmpl @@ -1047,6 +1047,8 @@ Usage of ./pyroscope: [experimental] Set to true to enable profiling integration. -usage-stats.enabled Enable anonymous usage reporting. (default true) + -validation.enforce-labels-order + Enforce labels order optimization. -validation.max-label-names-per-series int Maximum number of label names per series. (default 30) -validation.max-length-label-name int diff --git a/cmd/pyroscope/help.txt.tmpl b/cmd/pyroscope/help.txt.tmpl index e949ba0ea2..ad077e714e 100644 --- a/cmd/pyroscope/help.txt.tmpl +++ b/cmd/pyroscope/help.txt.tmpl @@ -381,6 +381,8 @@ Usage of ./pyroscope: Set to false to disable tracing. (default true) -usage-stats.enabled Enable anonymous usage reporting. (default true) + -validation.enforce-labels-order + Enforce labels order optimization. -validation.max-label-names-per-series int Maximum number of label names per series. (default 30) -validation.max-length-label-name int diff --git a/docs/sources/configure-server/reference-configuration-parameters/index.md b/docs/sources/configure-server/reference-configuration-parameters/index.md index 59748393f6..070f09b853 100644 --- a/docs/sources/configure-server/reference-configuration-parameters/index.md +++ b/docs/sources/configure-server/reference-configuration-parameters/index.md @@ -1815,6 +1815,10 @@ The `limits` block configures default and per-tenant limits imposed by component # CLI flag: -validation.max-sessions-per-series [max_sessions_per_series: | default = 0] +# Enforce labels order optimization. +# CLI flag: -validation.enforce-labels-order +[enforce_labels_order: | default = false] + # Maximum size of a profile in bytes. This is based off the uncompressed size. 0 # to disable. # CLI flag: -validation.max-profile-size-bytes diff --git a/operations/pyroscope/helm/pyroscope/rendered/micro-services-hpa.yaml b/operations/pyroscope/helm/pyroscope/rendered/micro-services-hpa.yaml index ad084da3f9..82d9624a6a 100644 --- a/operations/pyroscope/helm/pyroscope/rendered/micro-services-hpa.yaml +++ b/operations/pyroscope/helm/pyroscope/rendered/micro-services-hpa.yaml @@ -2058,7 +2058,6 @@ metadata: app.kubernetes.io/managed-by: Helm app.kubernetes.io/component: "distributor" spec: - replicas: 2 selector: matchLabels: app.kubernetes.io/name: pyroscope @@ -2152,7 +2151,6 @@ metadata: app.kubernetes.io/managed-by: Helm app.kubernetes.io/component: "querier" spec: - replicas: 3 selector: matchLabels: app.kubernetes.io/name: pyroscope @@ -2246,7 +2244,6 @@ metadata: app.kubernetes.io/managed-by: Helm app.kubernetes.io/component: "query-frontend" spec: - replicas: 2 selector: matchLabels: app.kubernetes.io/name: pyroscope @@ -2340,7 +2337,6 @@ metadata: app.kubernetes.io/managed-by: Helm app.kubernetes.io/component: "query-scheduler" spec: - replicas: 2 selector: matchLabels: app.kubernetes.io/name: pyroscope diff --git a/operations/pyroscope/helm/pyroscope/templates/deployments-statefulsets.yaml b/operations/pyroscope/helm/pyroscope/templates/deployments-statefulsets.yaml index f86c3e8bc7..d2bd71a643 100644 --- a/operations/pyroscope/helm/pyroscope/templates/deployments-statefulsets.yaml +++ b/operations/pyroscope/helm/pyroscope/templates/deployments-statefulsets.yaml @@ -17,7 +17,7 @@ spec: serviceName: {{ $values.name }}-headless podManagementPolicy: Parallel {{- end }} -{{- if hasKey $values "replicaCount" }} +{{- if and (hasKey $values "replicaCount") (not ($values.autoscaling).enabled) }} replicas: {{ $values.replicaCount }} {{- end }} selector: diff --git a/pkg/distributor/distributor.go b/pkg/distributor/distributor.go index 8c1611f80e..64d5592803 100644 --- a/pkg/distributor/distributor.go +++ b/pkg/distributor/distributor.go @@ -122,6 +122,7 @@ type Limits interface { MaxProfileStacktraceDepth(tenantID string) int MaxProfileSymbolValueLength(tenantID string) int MaxSessionsPerSeries(tenantID string) int + EnforceLabelsOrder(tenantID string) bool validation.ProfileValidationLimits aggregator.Limits } @@ -393,8 +394,9 @@ func (d *Distributor) sendAggregatedProfile(ctx context.Context, req *distributo func (d *Distributor) sendRequests(ctx context.Context, req *distributormodel.PushRequest, tenantID string) (resp *connect.Response[pushv1.PushResponse], err error) { // Reduce cardinality of session_id label. + maxSessionsPerSeries := d.limits.MaxSessionsPerSeries(tenantID) for _, series := range req.Series { - series.Labels = d.limitMaxSessionsPerSeries(tenantID, series.Labels) + series.Labels = d.limitMaxSessionsPerSeries(maxSessionsPerSeries, series.Labels) } // Next we split profiles by labels. @@ -414,7 +416,11 @@ func (d *Distributor) sendRequests(ctx context.Context, req *distributormodel.Pu // Validate the labels again and generate tokens for shuffle sharding. keys := make([]uint32, len(profileSeries)) + enforceLabelsOrder := d.limits.EnforceLabelsOrder(tenantID) for i, series := range profileSeries { + if enforceLabelsOrder { + series.Labels = phlaremodel.Labels(series.Labels).InsertSorted(phlaremodel.LabelNameOrder, phlaremodel.LabelOrderEnforced) + } if err = validation.ValidateLabels(d.limits, tenantID, series.Labels); err != nil { validation.DiscardedProfiles.WithLabelValues(string(validation.ReasonOf(err)), tenantID).Add(float64(req.TotalProfiles)) validation.DiscardedBytes.WithLabelValues(string(validation.ReasonOf(err)), tenantID).Add(float64(req.TotalBytesUncompressed)) @@ -666,8 +672,7 @@ func extractSampleSeries(req *distributormodel.PushRequest) []*distributormodel. return profileSeries } -func (d *Distributor) limitMaxSessionsPerSeries(tenantID string, labels phlaremodel.Labels) phlaremodel.Labels { - maxSessionsPerSeries := d.limits.MaxSessionsPerSeries(tenantID) +func (d *Distributor) limitMaxSessionsPerSeries(maxSessionsPerSeries int, labels phlaremodel.Labels) phlaremodel.Labels { if maxSessionsPerSeries == 0 { return labels.Delete(phlaremodel.LabelNameSessionID) } diff --git a/pkg/distributor/distributor_test.go b/pkg/distributor/distributor_test.go index f78464adb7..acc0f9e5dd 100644 --- a/pkg/distributor/distributor_test.go +++ b/pkg/distributor/distributor_test.go @@ -415,7 +415,8 @@ func Test_Sessions_Limit(t *testing.T) { }), nil, log.NewLogfmtLogger(os.Stdout)) require.NoError(t, err) - assert.Equal(t, tc.expectedLabels, d.limitMaxSessionsPerSeries("user-1", tc.seriesLabels)) + limit := d.limits.MaxSessionsPerSeries("user-1") + assert.Equal(t, tc.expectedLabels, d.limitMaxSessionsPerSeries(limit, tc.seriesLabels)) }) } } diff --git a/pkg/frontend/frontend_diff.go b/pkg/frontend/frontend_diff.go index 46745599d2..1390770776 100644 --- a/pkg/frontend/frontend_diff.go +++ b/pkg/frontend/frontend_diff.go @@ -38,26 +38,16 @@ func (f *Frontend) Diff(ctx context.Context, var left, right *phlaremodel.Tree g.Go(func() error { - resp, err := f.SelectMergeStacktraces(ctx, connect.NewRequest(c.Msg.Left)) - if err != nil { - return err - } - m := phlaremodel.NewFlameGraphMerger() - m.MergeFlameGraph(resp.Msg.Flamegraph) - left = m.Tree() - return err + var leftErr error + left, leftErr = f.selectMergeStacktracesTree(ctx, connect.NewRequest(c.Msg.Left)) + return leftErr }) g.Go(func() error { - resp, err := f.SelectMergeStacktraces(ctx, connect.NewRequest(c.Msg.Right)) - if err != nil { - return err - } - m := phlaremodel.NewFlameGraphMerger() - m.MergeFlameGraph(resp.Msg.Flamegraph) - right = m.Tree() - return err + var rightErr error + right, rightErr = f.selectMergeStacktracesTree(ctx, connect.NewRequest(c.Msg.Right)) + return rightErr }) - if err := g.Wait(); err != nil { + if err = g.Wait(); err != nil { return nil, err } diff --git a/pkg/frontend/frontend_select_merge_span_profile.go b/pkg/frontend/frontend_select_merge_span_profile.go index 9648907df1..85ac11ffc6 100644 --- a/pkg/frontend/frontend_select_merge_span_profile.go +++ b/pkg/frontend/frontend_select_merge_span_profile.go @@ -66,6 +66,7 @@ func (f *Frontend) SelectMergeSpanProfile(ctx context.Context, End: r.End.UnixMilli(), MaxNodes: &maxNodes, SpanSelector: c.Msg.SpanSelector, + Format: querierv1.ProfileFormat_PROFILE_FORMAT_TREE, }) resp, err := connectgrpc.RoundTripUnary[ querierv1.SelectMergeSpanProfileRequest, @@ -73,8 +74,13 @@ func (f *Frontend) SelectMergeSpanProfile(ctx context.Context, if err != nil { return err } - m.MergeFlameGraph(resp.Msg.Flamegraph) - return nil + if len(resp.Msg.Tree) > 0 { + err = m.MergeTreeBytes(resp.Msg.Tree) + } else if resp.Msg.Flamegraph != nil { + // For backward compatibility. + m.MergeFlameGraph(resp.Msg.Flamegraph) + } + return err }) } @@ -83,7 +89,12 @@ func (f *Frontend) SelectMergeSpanProfile(ctx context.Context, } t := m.Tree() - return connect.NewResponse(&querierv1.SelectMergeSpanProfileResponse{ - Flamegraph: phlaremodel.NewFlameGraph(t, c.Msg.GetMaxNodes()), - }), nil + var resp querierv1.SelectMergeSpanProfileResponse + switch c.Msg.Format { + default: + resp.Flamegraph = phlaremodel.NewFlameGraph(t, c.Msg.GetMaxNodes()) + case querierv1.ProfileFormat_PROFILE_FORMAT_TREE: + resp.Tree = t.Bytes(c.Msg.GetMaxNodes()) + } + return connect.NewResponse(&resp), nil } diff --git a/pkg/frontend/frontend_select_merge_stacktraces.go b/pkg/frontend/frontend_select_merge_stacktraces.go index 046a688a6e..1811318e04 100644 --- a/pkg/frontend/frontend_select_merge_stacktraces.go +++ b/pkg/frontend/frontend_select_merge_stacktraces.go @@ -21,6 +21,24 @@ import ( func (f *Frontend) SelectMergeStacktraces(ctx context.Context, c *connect.Request[querierv1.SelectMergeStacktracesRequest]) ( *connect.Response[querierv1.SelectMergeStacktracesResponse], error, +) { + t, err := f.selectMergeStacktracesTree(ctx, c) + if err != nil { + return nil, err + } + var resp querierv1.SelectMergeStacktracesResponse + switch c.Msg.Format { + default: + resp.Flamegraph = phlaremodel.NewFlameGraph(t, c.Msg.GetMaxNodes()) + case querierv1.ProfileFormat_PROFILE_FORMAT_TREE: + resp.Tree = t.Bytes(c.Msg.GetMaxNodes()) + } + return connect.NewResponse(&resp), nil +} + +func (f *Frontend) selectMergeStacktracesTree(ctx context.Context, + c *connect.Request[querierv1.SelectMergeStacktracesRequest]) ( + *phlaremodel.Tree, error, ) { opentracing.SpanFromContext(ctx). SetTag("start", model.Time(c.Msg.Start).Time().String()). @@ -40,9 +58,7 @@ func (f *Frontend) SelectMergeStacktraces(ctx context.Context, return nil, connect.NewError(connect.CodeInvalidArgument, err) } if validated.IsEmpty { - return connect.NewResponse(&querierv1.SelectMergeStacktracesResponse{ - Flamegraph: &querierv1.FlameGraph{}, - }), nil + return new(phlaremodel.Tree), nil } maxNodes, err := validation.ValidateMaxNodes(f.limits, tenantIDs, c.Msg.GetMaxNodes()) if err != nil { @@ -67,6 +83,7 @@ func (f *Frontend) SelectMergeStacktraces(ctx context.Context, Start: r.Start.UnixMilli(), End: r.End.UnixMilli(), MaxNodes: &maxNodes, + Format: querierv1.ProfileFormat_PROFILE_FORMAT_TREE, }) resp, err := connectgrpc.RoundTripUnary[ querierv1.SelectMergeStacktracesRequest, @@ -74,8 +91,13 @@ func (f *Frontend) SelectMergeStacktraces(ctx context.Context, if err != nil { return err } - m.MergeFlameGraph(resp.Msg.Flamegraph) - return nil + if len(resp.Msg.Tree) > 0 { + err = m.MergeTreeBytes(resp.Msg.Tree) + } else if resp.Msg.Flamegraph != nil { + // For backward compatibility. + m.MergeFlameGraph(resp.Msg.Flamegraph) + } + return err }) } @@ -83,8 +105,5 @@ func (f *Frontend) SelectMergeStacktraces(ctx context.Context, return nil, err } - t := m.Tree() - return connect.NewResponse(&querierv1.SelectMergeStacktracesResponse{ - Flamegraph: phlaremodel.NewFlameGraph(t, c.Msg.GetMaxNodes()), - }), nil + return m.Tree(), nil } diff --git a/pkg/model/flamegraph.go b/pkg/model/flamegraph.go index 25628b1b2b..9838c3a5ca 100644 --- a/pkg/model/flamegraph.go +++ b/pkg/model/flamegraph.go @@ -207,6 +207,17 @@ func (m *FlameGraphMerger) MergeFlameGraph(src *querierv1.FlameGraph) { } } +func (m *FlameGraphMerger) MergeTreeBytes(src []byte) error { + t, err := UnmarshalTree(src) + if err != nil { + return err + } + m.mu.Lock() + defer m.mu.Unlock() + m.t.Merge(t) + return nil +} + func (m *FlameGraphMerger) Tree() *Tree { return m.t } func (m *FlameGraphMerger) FlameGraph(maxNodes int64) *querierv1.FlameGraph { diff --git a/pkg/model/labels.go b/pkg/model/labels.go index 191a77e7d8..b4dd84f5c1 100644 --- a/pkg/model/labels.go +++ b/pkg/model/labels.go @@ -5,6 +5,7 @@ import ( "encoding/binary" "encoding/hex" "fmt" + "slices" "sort" "strconv" "strings" @@ -12,31 +13,32 @@ import ( "github.com/cespare/xxhash/v2" pmodel "github.com/prometheus/common/model" "github.com/prometheus/prometheus/model/labels" - "github.com/prometheus/prometheus/promql/parser" typesv1 "github.com/grafana/pyroscope/api/gen/proto/go/types/v1" - "github.com/grafana/pyroscope/pkg/slices" "github.com/grafana/pyroscope/pkg/util" ) var seps = []byte{'\xff'} const ( - LabelNameProfileType = "__profile_type__" - LabelNameType = "__type__" - LabelNameUnit = "__unit__" - LabelNamePeriodType = "__period_type__" - LabelNamePeriodUnit = "__period_unit__" - LabelNameDelta = "__delta__" - LabelNameProfileName = pmodel.MetricNameLabel - LabelNameSessionID = "__session_id__" + LabelNameProfileType = "__profile_type__" + LabelNameServiceNamePrivate = "__service_name__" + LabelNameDelta = "__delta__" + LabelNameProfileName = pmodel.MetricNameLabel + LabelNamePeriodType = "__period_type__" + LabelNamePeriodUnit = "__period_unit__" + LabelNameSessionID = "__session_id__" + LabelNameType = "__type__" + LabelNameUnit = "__unit__" + LabelNameServiceGitRef = "service_git_ref" LabelNameServiceName = "service_name" LabelNameServiceRepository = "service_repository" - LabelNameServiceGitRef = "service_git_ref" - LabelNamePyroscopeSpy = "pyroscope_spy" - LabelNameServiceNameK8s = "__meta_kubernetes_pod_annotation_pyroscope_io_service_name" + LabelNameOrder = "__order__" + LabelOrderEnforced = "enforced" + + LabelNamePyroscopeSpy = "pyroscope_spy" labelSep = '\xfe' ) @@ -49,6 +51,30 @@ func (ls Labels) Len() int { return len(ls) } func (ls Labels) Swap(i, j int) { ls[i], ls[j] = ls[j], ls[i] } func (ls Labels) Less(i, j int) bool { return ls[i].Name < ls[j].Name } +// LabelsEnforcedOrder is a sort order of labels, where profile type and +// service name labels always go first. This is crucial for query performance +// as labels determine the physical order of the profiling data. +type LabelsEnforcedOrder []*typesv1.LabelPair + +func (ls LabelsEnforcedOrder) Len() int { return len(ls) } +func (ls LabelsEnforcedOrder) Swap(i, j int) { ls[i], ls[j] = ls[j], ls[i] } + +func (ls LabelsEnforcedOrder) Less(i, j int) bool { + if ls[i].Name[0] == '_' || ls[j].Name[0] == '_' { + leftType := ls[i].Name == LabelNameProfileType + rightType := ls[j].Name == LabelNameProfileType + if leftType || rightType { + return leftType || !rightType + } + leftService := ls[i].Name == LabelNameServiceNamePrivate + rightService := ls[j].Name == LabelNameServiceNamePrivate + if leftService || rightService { + return leftService || !rightService + } + } + return ls[i].Name < ls[j].Name +} + // Hash returns a hash value for the label set. func (ls Labels) Hash() uint64 { // Use xxhash.Sum64(b) for fast path as it's faster. @@ -75,52 +101,25 @@ func (ls Labels) Hash() uint64 { return xxhash.Sum64(b) } -// HashForLabels returns a hash value for the labels matching the provided names. -// 'names' have to be sorted in ascending order. -func (ls Labels) HashForLabels(b []byte, names ...string) (uint64, []byte) { - b = b[:0] - i, j := 0, 0 - for i < len(ls) && j < len(names) { - if names[j] < ls[i].Name { - j++ - } else if ls[i].Name < names[j] { - i++ - } else { - b = append(b, ls[i].Name...) - b = append(b, seps[0]) - b = append(b, ls[i].Value...) - b = append(b, seps[0]) - i++ - j++ - } - } - return xxhash.Sum64(b), b -} - // BytesWithLabels is just as Bytes(), but only for labels matching names. -// 'names' have to be sorted in ascending order. // It uses an byte invalid character as a separator and so should not be used for printing. func (ls Labels) BytesWithLabels(buf []byte, names ...string) []byte { - b := bytes.NewBuffer(buf[:0]) - b.WriteByte(labelSep) - i, j := 0, 0 - for i < len(ls) && j < len(names) { - if names[j] < ls[i].Name { - j++ - } else if ls[i].Name < names[j] { - i++ - } else { - if b.Len() > 1 { - b.WriteByte(seps[0]) + buf = buf[:0] + buf = append(buf, labelSep) + for _, name := range names { + for _, l := range ls { + if l.Name == name { + if len(buf) > 1 { + buf = append(buf, seps[0]) + } + buf = append(buf, l.Name...) + buf = append(buf, seps[0]) + buf = append(buf, l.Value...) + break } - b.WriteString(ls[i].Name) - b.WriteByte(seps[0]) - b.WriteString(ls[i].Value) - i++ - j++ } } - return b.Bytes() + return buf } func (ls Labels) ToPrometheusLabels() labels.Labels { @@ -153,22 +152,18 @@ func IsLabelAllowedForIngestion(name string) bool { return allowed } -// WithLabels returns a subset of Labels that matches match with the provided label names. +// WithLabels returns a subset of Labels that match with the provided label names. func (ls Labels) WithLabels(names ...string) Labels { - matchedLabels := Labels{} - - nameSet := make(map[string]struct{}, len(names)) - for _, n := range names { - nameSet[n] = struct{}{} - } - - for _, v := range ls { - if _, ok := nameSet[v.Name]; ok { - matchedLabels = append(matchedLabels, v) + matched := make(Labels, 0, len(names)) + for _, name := range names { + for _, l := range ls { + if l.Name == name { + matched = append(matched, l) + break + } } } - - return matchedLabels + return matched } // Get returns the value for the label with the given name. @@ -192,12 +187,44 @@ func (ls Labels) GetLabel(name string) (*typesv1.LabelPair, bool) { return nil, false } -// Delete removes the first label encountered with the name given. -// A copy of the label set without the label is returned. +// Delete removes the first label encountered with the name given in place. func (ls Labels) Delete(name string) Labels { - return slices.RemoveInPlace(ls, func(pair *typesv1.LabelPair, i int) bool { - return pair.Name == name - }) + for i, l := range ls { + if l.Name == name { + return slices.Delete(ls, i, i+1) + } + } + return ls +} + +// InsertSorted adds the given label to the set of labels. +// It assumes the labels are sorted lexicographically. +func (ls Labels) InsertSorted(name, value string) Labels { + // Find the index where the new label should be inserted. + // TODO: Use binary search on large label sets. + index := -1 + for i, label := range ls { + if label.Name > name { + index = i + break + } + if label.Name == name { + label.Value = value + return ls + } + } + // Insert the new label at the found index. + l := &typesv1.LabelPair{ + Name: name, + Value: value, + } + c := append(ls, l) + if index == -1 { + return c + } + copy((c)[index+1:], (c)[index:]) + (c)[index] = l + return c } func (ls Labels) Clone() Labels { @@ -247,22 +274,6 @@ func LabelPairsString(lbs []*typesv1.LabelPair) string { return b.String() } -// StringToLabelsPairs converts a string representation of label pairs to a slice of label pairs. -func StringToLabelsPairs(s string) ([]*typesv1.LabelPair, error) { - matchers, err := parser.ParseMetricSelector(s) - if err != nil { - return nil, err - } - result := make([]*typesv1.LabelPair, len(matchers)) - for i := range matchers { - result[i] = &typesv1.LabelPair{ - Name: matchers[i].Name, - Value: matchers[i].Value, - } - } - return result, nil -} - // LabelsFromStrings creates new labels from pairs of strings. func LabelsFromStrings(ss ...string) Labels { if len(ss)%2 != 0 { @@ -277,19 +288,7 @@ func LabelsFromStrings(ss ...string) Labels { return res } -// CloneLabelPairs clones the label pairs. -func CloneLabelPairs(lbs []*typesv1.LabelPair) []*typesv1.LabelPair { - result := make([]*typesv1.LabelPair, len(lbs)) - for i, l := range lbs { - result[i] = &typesv1.LabelPair{ - Name: l.Name, - Value: l.Value, - } - } - return result -} - -// Compare compares the two label sets. +// CompareLabelPairs compares the two label sets. // The result will be 0 if a==b, <0 if a < b, and >0 if a > b. func CompareLabelPairs(a []*typesv1.LabelPair, b []*typesv1.LabelPair) int { l := len(a) @@ -377,6 +376,16 @@ func (b *LabelsBuilder) Set(n, v string) *LabelsBuilder { // Labels returns the labels from the builder. If no modifications // were made, the original labels are returned. func (b *LabelsBuilder) Labels() Labels { + res := b.LabelsUnsorted() + sort.Sort(res) + return res +} + +// LabelsUnsorted returns the labels from the builder. If no modifications +// were made, the original labels are returned. +// +// The order is not deterministic. +func (b *LabelsBuilder) LabelsUnsorted() Labels { if len(b.del) == 0 && len(b.add) == 0 { return b.base } @@ -398,37 +407,8 @@ Outer: } res = append(res, l) } - res = append(res, b.add...) - sort.Sort(res) - - return res -} - -// StableHash is a labels hashing implementation which is guaranteed to not change over time. -// This function should be used whenever labels hashing backward compatibility must be guaranteed. -func StableHash(ls labels.Labels) uint64 { - // Use xxhash.Sum64(b) for fast path as it's faster. - b := make([]byte, 0, 1024) - for i, v := range ls { - if len(b)+len(v.Name)+len(v.Value)+2 >= cap(b) { - // If labels entry is 1KB+ do not allocate whole entry. - h := xxhash.New() - _, _ = h.Write(b) - for _, v := range ls[i:] { - _, _ = h.WriteString(v.Name) - _, _ = h.Write(seps) - _, _ = h.WriteString(v.Value) - _, _ = h.Write(seps) - } - return h.Sum64() - } - b = append(b, v.Name...) - b = append(b, seps[0]) - b = append(b, v.Value...) - b = append(b, seps[0]) - } - return xxhash.Sum64(b) + return append(res, b.add...) } type SessionID uint64 diff --git a/pkg/model/labels_test.go b/pkg/model/labels_test.go index 3395f238df..5e7fdcd26c 100644 --- a/pkg/model/labels_test.go +++ b/pkg/model/labels_test.go @@ -6,6 +6,8 @@ import ( "testing" "github.com/stretchr/testify/assert" + + typesv1 "github.com/grafana/pyroscope/api/gen/proto/go/types/v1" ) func TestLabelsUnique(t *testing.T) { @@ -67,21 +69,20 @@ func TestLabelsUnique(t *testing.T) { } func TestLabels_SessionID_Order(t *testing.T) { - const serviceNameLabel = "__service_name__" input := []Labels{ { {Name: LabelNameSessionID, Value: "session-a"}, {Name: LabelNameProfileType, Value: "cpu"}, - {Name: serviceNameLabel, Value: "service-name"}, + {Name: LabelNameServiceNamePrivate, Value: "service-name"}, }, { {Name: LabelNameSessionID, Value: "session-b"}, {Name: LabelNameProfileType, Value: "cpu"}, - {Name: serviceNameLabel, Value: "service-name"}, + {Name: LabelNameServiceNamePrivate, Value: "service-name"}, }, } for _, x := range input { - sort.Sort(x) + sort.Sort(LabelsEnforcedOrder(x)) } sort.Slice(input, func(i, j int) bool { return CompareLabelPairs(input[i], input[j]) < 0 @@ -90,11 +91,11 @@ func TestLabels_SessionID_Order(t *testing.T) { expectedOrder := []Labels{ { {Name: LabelNameProfileType, Value: "cpu"}, - {Name: serviceNameLabel, Value: "service-name"}, + {Name: LabelNameServiceNamePrivate, Value: "service-name"}, {Name: LabelNameSessionID, Value: "session-a"}, }, { {Name: LabelNameProfileType, Value: "cpu"}, - {Name: serviceNameLabel, Value: "service-name"}, + {Name: LabelNameServiceNamePrivate, Value: "service-name"}, {Name: LabelNameSessionID, Value: "session-b"}, }, } @@ -133,3 +134,150 @@ func Test_SessionID_Parse(t *testing.T) { _, err = ParseSessionID("not-a-session-id-either") assert.NotNil(t, err) } + +func TestLabels_LabelsEnforcedOrder(t *testing.T) { + labels := []*typesv1.LabelPair{ + {Name: "foo", Value: "bar"}, + {Name: LabelNameProfileType, Value: "cpu"}, + {Name: "__request_id__", Value: "mess"}, + {Name: LabelNameServiceNamePrivate, Value: "service"}, + {Name: "Alarm", Value: "Order"}, + } + + expected := Labels{ + {Name: LabelNameProfileType, Value: "cpu"}, + {Name: LabelNameServiceNamePrivate, Value: "service"}, + {Name: "Alarm", Value: "Order"}, + {Name: "__request_id__", Value: "mess"}, + {Name: "foo", Value: "bar"}, + } + + permute(labels, func(x []*typesv1.LabelPair) { + sort.Sort(LabelsEnforcedOrder(x)) + assert.Equal(t, LabelPairsString(expected), LabelPairsString(labels)) + }) +} + +func TestLabels_LabelsEnforcedOrder_BytesWithLabels(t *testing.T) { + labels := Labels{ + {Name: LabelNameProfileType, Value: "cpu"}, + {Name: LabelNameServiceNamePrivate, Value: "service"}, + {Name: "__request_id__", Value: "mess"}, + {Name: "A_label", Value: "bad"}, + {Name: "foo", Value: "bar"}, + } + sort.Sort(LabelsEnforcedOrder(labels)) + + assert.NotEqual(t, + labels.BytesWithLabels(nil, "A_label"), + labels.BytesWithLabels(nil, "not_a_label"), + ) + + assert.Equal(t, + labels.BytesWithLabels(nil, "A_label"), + Labels{{Name: "A_label", Value: "bad"}}.BytesWithLabels(nil, "A_label"), + ) +} + +func permute[T any](s []T, f func([]T)) { + n := len(s) + stack := make([]int, n) + f(s) + i := 0 + for i < n { + if stack[i] < i { + if i%2 == 0 { + s[0], s[i] = s[i], s[0] + } else { + s[stack[i]], s[i] = s[i], s[stack[i]] + } + f(s) + stack[i]++ + i = 0 + } else { + stack[i] = 0 + i++ + } + } +} + +func TestInsert(t *testing.T) { + tests := []struct { + name string + labels Labels + insertName string + insertValue string + expected Labels + }{ + { + name: "Insert into empty slice", + labels: Labels{}, + insertName: "foo", + insertValue: "bar", + expected: Labels{ + {Name: "foo", Value: "bar"}, + }, + }, + { + name: "Insert at the beginning", + labels: Labels{ + {Name: "baz", Value: "qux"}, + {Name: "quux", Value: "corge"}, + }, + insertName: "alice", + insertValue: "bob", + expected: Labels{ + {Name: "alice", Value: "bob"}, + {Name: "baz", Value: "qux"}, + {Name: "quux", Value: "corge"}, + }, + }, + { + name: "Insert in the middle", + labels: Labels{ + {Name: "baz", Value: "qux"}, + {Name: "quux", Value: "corge"}, + }, + insertName: "foo", + insertValue: "bar", + expected: Labels{ + {Name: "baz", Value: "qux"}, + {Name: "foo", Value: "bar"}, + {Name: "quux", Value: "corge"}, + }, + }, + { + name: "Insert at the end", + labels: Labels{ + {Name: "baz", Value: "qux"}, + {Name: "quux", Value: "corge"}, + }, + insertName: "xyz", + insertValue: "123", + expected: Labels{ + {Name: "baz", Value: "qux"}, + {Name: "quux", Value: "corge"}, + {Name: "xyz", Value: "123"}, + }, + }, + { + name: "Update existing label", + labels: Labels{ + {Name: "baz", Value: "qux"}, + {Name: "quux", Value: "corge"}, + }, + insertName: "baz", + insertValue: "updated_value", + expected: Labels{ + {Name: "baz", Value: "updated_value"}, + {Name: "quux", Value: "corge"}, + }, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + assert.Equal(t, test.expected, test.labels.InsertSorted(test.insertName, test.insertValue)) + }) + } +} diff --git a/pkg/model/stacktraces.go b/pkg/model/stacktraces.go index 1aa61b59ef..ca0d1fc203 100644 --- a/pkg/model/stacktraces.go +++ b/pkg/model/stacktraces.go @@ -140,6 +140,18 @@ func NewStacktraceTree(size int) *StacktraceTree { return &t } +func (t *StacktraceTree) Reset() { + if cap(t.Nodes) < 1 { + *t = *(NewStacktraceTree(0)) + return + } + t.Nodes = t.Nodes[:1] + t.Nodes[0] = StacktraceNode{ + FirstChild: sentinel, + NextSibling: sentinel, + } +} + const sentinel = -1 func (t *StacktraceTree) Insert(locations []int32, value int64) int32 { @@ -201,6 +213,7 @@ func (t *StacktraceTree) LookupLocations(dst []uint64, idx int32) []uint64 { // MinValue returns the minimum "total" value a node in a tree has to have. func (t *StacktraceTree) MinValue(maxNodes int64) int64 { + // TODO(kolesnikovae): Consider quickselect. if maxNodes < 1 || maxNodes >= int64(len(t.Nodes)) { return 0 } @@ -225,7 +238,7 @@ func (t *StacktraceTree) MinValue(maxNodes int64) int64 { type StacktraceTreeTraverseFn = func(index int32, children []int32) error func (t *StacktraceTree) Traverse(maxNodes int64, fn StacktraceTreeTraverseFn) error { - min := t.MinValue(maxNodes) + minValue := t.MinValue(maxNodes) children := make([]int32, 0, 128) // Children per node. nodesSize := maxNodes // Depth search buffer. if nodesSize < 1 || nodesSize > 10<<10 { @@ -243,7 +256,7 @@ func (t *StacktraceTree) Traverse(maxNodes int64, fn StacktraceTreeTraverseFn) e for x := n.FirstChild; x > 0; { child := &t.Nodes[x] - if child.Total >= min && child.Location != sentinel { + if child.Total >= minValue && child.Location != sentinel { children = append(children, x) } else { truncated += child.Total @@ -274,8 +287,6 @@ func (t *StacktraceTree) Traverse(maxNodes int64, fn StacktraceTreeTraverseFn) e return nil } -var lostDuringSerializationNameBytes = []byte(truncatedNodeName) - func (t *StacktraceTree) Bytes(dst io.Writer, maxNodes int64, funcs []string) { if len(t.Nodes) == 0 || len(funcs) == 0 { return @@ -290,9 +301,8 @@ func (t *StacktraceTree) Bytes(dst io.Writer, maxNodes int64, funcs []string) { // and the byte slice backing capacity is managed by GC. name = unsafeStringBytes(funcs[n.Location]) case sentinel: - name = lostDuringSerializationNameBytes + name = truncatedNodeNameBytes } - _, _ = vw.Write(dst, uint64(len(name))) _, _ = dst.Write(name) _, _ = vw.Write(dst, uint64(n.Value)) @@ -304,3 +314,41 @@ func (t *StacktraceTree) Bytes(dst io.Writer, maxNodes int64, funcs []string) { func unsafeStringBytes(s string) []byte { return unsafe.Slice(unsafe.StringData(s), len(s)) } + +func (t *StacktraceTree) Tree(maxNodes int64, names []string) *Tree { + if len(t.Nodes) < 2 || len(names) == 0 { + // stack trace tree has root at 0: trees with less + // than 2 nodes are considered empty. + return new(Tree) + } + + nodesSize := maxNodes + if nodesSize < 1 || nodesSize > 10<<10 { + nodesSize = 1 << 10 // Sane default. + } + root := new(node) // Virtual root node. + nodes := make([]*node, 1, nodesSize) + nodes[0] = root + var current *node + + _ = t.Traverse(maxNodes, func(index int32, children []int32) error { + current, nodes = nodes[len(nodes)-1], nodes[:len(nodes)-1] + sn := &t.Nodes[index] + var name string + if sn.Location < 0 { + name = truncatedNodeName + } else { + name = names[sn.Location] + } + n := current.insert(name) + n.self = sn.Value + n.total = sn.Total + n.children = make([]*node, 0, len(children)) + for i := 0; i < len(children); i++ { + nodes = append(nodes, n) + } + return nil + }) + + return &Tree{root: root.children[0].children} +} diff --git a/pkg/model/tree.go b/pkg/model/tree.go index 9077c7e6e7..4ad11b04f8 100644 --- a/pkg/model/tree.go +++ b/pkg/model/tree.go @@ -1,6 +1,7 @@ package model import ( + "bytes" "container/heap" "fmt" "io" @@ -129,6 +130,14 @@ func (t *Tree) IterateStacks(cb func(name string, self int64, stack []string)) { const defaultDFSSize = 128 func (t *Tree) Merge(src *Tree) { + if t.Total() == 0 && src.Total() > 0 { + *t = *src + return + } + if src.Total() == 0 { + return + } + srcNodes := make([]*node, 0, defaultDFSSize) srcRoot := &node{children: src.root} srcNodes = append(srcNodes, srcRoot) @@ -326,6 +335,17 @@ func (h *minHeap) Pop() interface{} { const truncatedNodeName = "other" +var truncatedNodeNameBytes = []byte(truncatedNodeName) + +// Bytes returns marshaled tree byte representation; the number of nodes +// is limited to maxNodes. The function modifies the tree: truncated nodes +// are removed from the tree in place. +func (t *Tree) Bytes(maxNodes int64) []byte { + var buf bytes.Buffer + _ = t.MarshalTruncate(&buf, maxNodes) + return buf.Bytes() +} + // MarshalTruncate writes tree byte representation to the writer provider, // the number of nodes is limited to maxNodes. The function modifies // the tree: truncated nodes are removed from the tree. diff --git a/pkg/og/convert/pprof/profile.go b/pkg/og/convert/pprof/profile.go index 7337174985..047d42862c 100644 --- a/pkg/og/convert/pprof/profile.go +++ b/pkg/og/convert/pprof/profile.go @@ -245,26 +245,55 @@ func isScriptingSpy(md ingestion.Metadata) bool { return md.SpyName == "pyspy" || md.SpyName == "rbspy" || md.SpyName == "scripting" } +// FixFunctionNamesForScriptingLanguages modifies the function names in the provided profile +// to include line numbers. This is a workaround for frontend limitations in rendering line numbers. +// The function is specifically designed for profiles generated by scripting languages. +// Note: This function modifies the provided profile in place. func FixFunctionNamesForScriptingLanguages(p *pprof.Profile, md ingestion.Metadata) { if !needFunctionNameRewrite(md) { return } smap := map[string]int{} - for _, fn := range p.Function { - // obtaining correct line number will require rewriting functions and slices - // lets not do it and wait until we render line numbers on frontend - const lineNumber = -1 - name := fmt.Sprintf("%s:%d - %s", - p.StringTable[fn.Filename], - lineNumber, - p.StringTable[fn.Name]) + addString := func(name string) int { sid := smap[name] if sid == 0 { sid = len(p.StringTable) p.StringTable = append(p.StringTable, name) smap[name] = sid } - fn.Name = int64(sid) + return sid + } + funcId2Index := map[uint64]int64{} + newFunctions := map[string]*profilev1.Function{} + maxId := uint64(0) + for index, fn := range p.Function { + funcId2Index[fn.Id] = int64(index) + if fn.Id > maxId { + maxId = fn.Id + } + } + for _, location := range p.Location { + for _, line := range location.Line { + fn := p.Function[funcId2Index[line.FunctionId]] + name := fmt.Sprintf("%s:%d - %s", + p.StringTable[fn.Filename], + line.Line, + p.StringTable[fn.Name]) + newFunc, ok := newFunctions[name] + if !ok { + maxId++ + newFunc = &profilev1.Function{ + Id: maxId, + Name: int64(addString(name)), + Filename: fn.Filename, + SystemName: fn.SystemName, + StartLine: fn.StartLine, + } + newFunctions[name] = newFunc + p.Function = append(p.Function, newFunc) + } + line.FunctionId = newFunc.Id + } } } diff --git a/pkg/og/convert/pprof/profile_test.go b/pkg/og/convert/pprof/profile_test.go index 86390faa44..effed00957 100644 --- a/pkg/og/convert/pprof/profile_test.go +++ b/pkg/og/convert/pprof/profile_test.go @@ -1,6 +1,10 @@ package pprof import ( + profilev1 "github.com/grafana/pyroscope/api/gen/proto/go/google/v1" + "github.com/grafana/pyroscope/pkg/og/convert/pprof/bench" + "github.com/grafana/pyroscope/pkg/pprof" + "github.com/stretchr/testify/assert" "testing" "github.com/grafana/pyroscope/pkg/og/ingestion" @@ -22,3 +26,56 @@ func TestEmptyPPROF(t *testing.T) { require.NoError(t, err) require.Equal(t, 0, len(profile.Series)) } + +func TestFixFunctionNamesForScriptingLanguages(t *testing.T) { + profile := pprof.RawFromProto(&profilev1.Profile{ + StringTable: []string{"", "main", "func1", "func2", "qwe.py"}, + Function: []*profilev1.Function{ + {Id: 1, Name: 1, Filename: 4, SystemName: 1, StartLine: 239}, + {Id: 2, Name: 2, Filename: 4, SystemName: 2, StartLine: 42}, + {Id: 3, Name: 3, Filename: 4, SystemName: 3, StartLine: 7}, + }, + Location: []*profilev1.Location{ + {Id: 1, Line: []*profilev1.Line{{FunctionId: 1, Line: 242}}}, + {Id: 2, Line: []*profilev1.Line{{FunctionId: 2, Line: 50}}}, + {Id: 3, Line: []*profilev1.Line{{FunctionId: 3, Line: 8}}}, + }, + Sample: []*profilev1.Sample{ + {LocationId: []uint64{2, 1}, Value: []int64{10, 1000}}, + {LocationId: []uint64{3, 1}, Value: []int64{13, 1300}}, + }, + }) + functionNameFromLocation := func(locID uint64) string { + for _, loc := range profile.Location { + if loc.Id == locID { + for _, fun := range profile.Function { + if fun.Id == loc.Line[0].FunctionId { + return profile.StringTable[fun.Name] + } + } + } + } + return "" + } + + md := ingestion.Metadata{ + SpyName: "pyspy", + } + + FixFunctionNamesForScriptingLanguages(profile, md) + + assert.Len(t, profile.Function, 6) // we do not remove unreferenced functions for now, let the distributor do it + assert.Len(t, profile.Location, 3) + assert.Len(t, profile.Sample, 2) + + collapsed := bench.StackCollapseProto(profile.Profile, 0, 1) + expected := []string{ + "qwe.py:242 - main;qwe.py:50 - func1 10", + "qwe.py:242 - main;qwe.py:8 - func2 13", + } + assert.Equal(t, expected, collapsed) + + assert.Equal(t, "qwe.py:242 - main", functionNameFromLocation(profile.Location[0].Id)) + assert.Equal(t, "qwe.py:50 - func1", functionNameFromLocation(profile.Location[1].Id)) + assert.Equal(t, "qwe.py:8 - func2", functionNameFromLocation(profile.Location[2].Id)) +} diff --git a/pkg/phlaredb/block_querier.go b/pkg/phlaredb/block_querier.go index 33afa3cf36..e5d45b5e35 100644 --- a/pkg/phlaredb/block_querier.go +++ b/pkg/phlaredb/block_querier.go @@ -49,7 +49,7 @@ import ( ) const ( - defaultBatchSize = 4096 + defaultBatchSize = 64 << 10 // This controls the buffer size for reads to a parquet io.Reader. This value should be small for memory or // disk backed readers, but when the reader is backed by network storage a larger size will be advantageous. @@ -566,14 +566,14 @@ type Querier interface { Open(ctx context.Context) error Sort([]Profile) []Profile - MergeByStacktraces(ctx context.Context, rows iter.Iterator[Profile]) (*phlaremodel.Tree, error) + MergeByStacktraces(ctx context.Context, rows iter.Iterator[Profile], maxNodes int64) (*phlaremodel.Tree, error) MergeBySpans(ctx context.Context, rows iter.Iterator[Profile], spans phlaremodel.SpanSelector) (*phlaremodel.Tree, error) MergeByLabels(ctx context.Context, rows iter.Iterator[Profile], s *typesv1.StackTraceSelector, by ...string) ([]*typesv1.Series, error) MergePprof(ctx context.Context, rows iter.Iterator[Profile], maxNodes int64, s *typesv1.StackTraceSelector) (*profilev1.Profile, error) Series(ctx context.Context, params *ingestv1.SeriesRequest) ([]*typesv1.Labels, error) SelectMatchingProfiles(ctx context.Context, params *ingestv1.SelectProfilesRequest) (iter.Iterator[Profile], error) - SelectMergeByStacktraces(ctx context.Context, params *ingestv1.SelectProfilesRequest) (*phlaremodel.Tree, error) + SelectMergeByStacktraces(ctx context.Context, params *ingestv1.SelectProfilesRequest, maxNodes int64) (*phlaremodel.Tree, error) SelectMergeByLabels(ctx context.Context, params *ingestv1.SelectProfilesRequest, s *typesv1.StackTraceSelector, by ...string) ([]*typesv1.Series, error) SelectMergeBySpans(ctx context.Context, params *ingestv1.SelectSpanProfileRequest) (*phlaremodel.Tree, error) SelectMergePprof(ctx context.Context, params *ingestv1.SelectProfilesRequest, maxNodes int64, s *typesv1.StackTraceSelector) (*profilev1.Profile, error) @@ -835,7 +835,7 @@ func MergeProfilesStacktraces(ctx context.Context, stream *connect.BidiStream[in querier := querier g.Go(util.RecoverPanic(func() error { // TODO(simonswine): Split profiles per row group and run the MergeByStacktraces in parallel. - merge, err := querier.SelectMergeByStacktraces(ctx, request) + merge, err := querier.SelectMergeByStacktraces(ctx, request, r.GetMaxNodes()) if err != nil { return err } @@ -871,7 +871,7 @@ func MergeProfilesStacktraces(ctx context.Context, stream *connect.BidiStream[in // 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]))) + merge, err := querier.MergeByStacktraces(ctx, iter.NewSliceIterator(querier.Sort(selectedProfiles[i])), r.GetMaxNodes()) if err != nil { return err } @@ -894,13 +894,8 @@ func MergeProfilesStacktraces(ctx context.Context, stream *connect.BidiStream[in return err } - var buf bytes.Buffer - if err = t.MarshalTruncate(&buf, r.GetMaxNodes()); err != nil { - return err - } - // sends the final result to the client. - treeBytes := buf.Bytes() + treeBytes := t.Bytes(r.GetMaxNodes()) sp.LogFields( otlog.String("msg", "sending the final result to the client"), otlog.Int("tree_bytes", len(treeBytes)), @@ -1042,13 +1037,8 @@ func MergeSpanProfile(ctx context.Context, stream *connect.BidiStream[ingestv1.M return err } - var buf bytes.Buffer - if err = t.MarshalTruncate(&buf, r.GetMaxNodes()); err != nil { - return err - } - // sends the final result to the client. - treeBytes := buf.Bytes() + treeBytes := t.Bytes(r.GetMaxNodes()) sp.LogFields( otlog.String("msg", "sending the final result to the client"), otlog.Int("tree_bytes", len(treeBytes)), @@ -1709,7 +1699,7 @@ func (b *singleBlockQuerier) SelectMergeByLabels( return mergeByLabelsWithStackTraceSelector[Profile](ctx, profiles.file, rows, r, by...) } -func (b *singleBlockQuerier) SelectMergeByStacktraces(ctx context.Context, params *ingestv1.SelectProfilesRequest) (tree *phlaremodel.Tree, err error) { +func (b *singleBlockQuerier) SelectMergeByStacktraces(ctx context.Context, params *ingestv1.SelectProfilesRequest, maxNodes int64) (tree *phlaremodel.Tree, err error) { sp, ctx := opentracing.StartSpanFromContext(ctx, "SelectMergeByStacktraces - Block") defer sp.Finish() sp.SetTag("block ULID", b.meta.ULID.String()) @@ -1748,7 +1738,7 @@ func (b *singleBlockQuerier) SelectMergeByStacktraces(ctx context.Context, param } lblsPerRef[int64(chks[0].SeriesIndex)] = struct{}{} } - r := symdb.NewResolver(ctx, b.symbols) + r := symdb.NewResolver(ctx, b.symbols, symdb.WithResolverMaxNodes(maxNodes)) defer r.Release() g, ctx := errgroup.WithContext(ctx) diff --git a/pkg/phlaredb/block_querier_test.go b/pkg/phlaredb/block_querier_test.go index f79d5428e3..4ce7732152 100644 --- a/pkg/phlaredb/block_querier_test.go +++ b/pkg/phlaredb/block_querier_test.go @@ -1163,7 +1163,7 @@ func TestSelectMergeStacktraces(t *testing.T) { }, Start: 0, End: int64(model.TimeFromUnixNano(math.MaxInt64)), - }) + }, 16<<10) require.NoError(t, err) expected := phlaremodel.Tree{} expected.InsertStack(1000, "baz", "bar", "foo") @@ -1293,6 +1293,14 @@ func genPoints(count int) []*typesv1.Point { } func TestSelectMergeByStacktracesRace(t *testing.T) { + testSelectMergeByStacktracesRace(t, 30) +} + +func BenchmarkSelectMergeByStacktracesRace(b *testing.B) { + testSelectMergeByStacktracesRace(b, b.N) +} + +func testSelectMergeByStacktracesRace(t testing.TB, times int) { defer goleak.VerifyNone(t, goleak.IgnoreCurrent()) ctx := context.Background() @@ -1323,7 +1331,12 @@ func TestSelectMergeByStacktracesRace(t *testing.T) { tree := new(phlaremodel.Tree) var m sync.Mutex - for i := 0; i < 30; i++ { + if b, ok := t.(*testing.B); ok { + b.ResetTimer() + b.ReportAllocs() + } + + for i := 0; i < times; i++ { g.Go(func() error { it, err := querier.SelectMatchingProfiles(ctx, &ingesterv1.SelectProfilesRequest{ LabelSelector: `{}`, @@ -1359,7 +1372,7 @@ func TestSelectMergeByStacktracesRace(t *testing.T) { }, Start: 0, End: int64(model.TimeFromUnixNano(math.MaxInt64)), - }) + }, 16<<10) if err != nil { return err } diff --git a/pkg/phlaredb/compact_test.go b/pkg/phlaredb/compact_test.go index e7890ce3bb..e2b5f0ad4e 100644 --- a/pkg/phlaredb/compact_test.go +++ b/pkg/phlaredb/compact_test.go @@ -81,7 +81,7 @@ func TestCompact(t *testing.T) { it, err = querier.SelectMatchingProfiles(ctx, matchAll) require.NoError(t, err) - res, err := querier.MergeByStacktraces(ctx, it) + res, err := querier.MergeByStacktraces(ctx, it, 0) require.NoError(t, err) require.NotNil(t, res) @@ -148,7 +148,7 @@ func TestCompactWithDownsampling(t *testing.T) { it, err = querier.SelectMatchingProfiles(ctx, matchAll) require.NoError(t, err) - res, err := querier.MergeByStacktraces(ctx, it) + res, err := querier.MergeByStacktraces(ctx, it, 0) require.NoError(t, err) require.NotNil(t, res) @@ -156,7 +156,7 @@ func TestCompactWithDownsampling(t *testing.T) { expected.InsertStack(3, "baz", "bar", "foo") require.Equal(t, expected.String(), res.String()) - res, err = querier.SelectMergeByStacktraces(ctx, matchAll) + res, err = querier.SelectMergeByStacktraces(ctx, matchAll, 0) require.NoError(t, err) require.NotNil(t, res) require.Equal(t, expected.String(), res.String()) @@ -281,7 +281,7 @@ func TestCompactWithSplitting(t *testing.T) { // Finally test some stacktraces resolution. it, err = queriers[1].SelectMatchingProfiles(ctx, matchAll) require.NoError(t, err) - res, err := queriers[1].MergeByStacktraces(ctx, it) + res, err := queriers[1].MergeByStacktraces(ctx, it, 0) require.NoError(t, err) expected := new(phlaremodel.Tree) diff --git a/pkg/phlaredb/filter_profiles_bidi.go b/pkg/phlaredb/filter_profiles_bidi.go index 7e9e77d3f7..7cdf6dc131 100644 --- a/pkg/phlaredb/filter_profiles_bidi.go +++ b/pkg/phlaredb/filter_profiles_bidi.go @@ -11,9 +11,7 @@ import ( "github.com/prometheus/common/model" 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/iter" - phlaremodel "github.com/grafana/pyroscope/pkg/model" ) type BidiServerMerge[Res any, Req any] interface { @@ -21,11 +19,6 @@ type BidiServerMerge[Res any, Req any] interface { Receive() (Req, error) } -type labelWithIndex struct { - phlaremodel.Labels - index int -} - type ProfileWithIndex struct { Profile Index int @@ -72,8 +65,8 @@ func filterProfiles[B BidiServerMerge[Res, Req], Res filterResponse, Req filterR defer sp.Finish() selection := make([][]Profile, len(profiles)) selectProfileResult := &ingestv1.ProfileSets{ - Profiles: make([]*ingestv1.SeriesProfile, 0, batchProfileSize), - LabelsSets: make([]*typesv1.Labels, 0, batchProfileSize), + Profiles: make([]*ingestv1.SeriesProfile, 0, batchProfileSize), + Fingerprints: make([]uint64, 0, batchProfileSize), } its := make([]iter.Iterator[ProfileWithIndex], len(profiles)) for i, iter := range profiles { @@ -92,28 +85,26 @@ func filterProfiles[B BidiServerMerge[Res, Req], Res filterResponse, Req filterR otlog.Int("batch_requested_size", batchProfileSize), ) - seriesByFP := map[model.Fingerprint]labelWithIndex{} - selectProfileResult.LabelsSets = selectProfileResult.LabelsSets[:0] + seriesByFP := map[model.Fingerprint]int{} selectProfileResult.Profiles = selectProfileResult.Profiles[:0] + selectProfileResult.Fingerprints = selectProfileResult.Fingerprints[:0] for _, profile := range batch { var ok bool - var lblsIdx labelWithIndex - lblsIdx, ok = seriesByFP[profile.Fingerprint()] + var idx int + fp := profile.Fingerprint() + idx, ok = seriesByFP[fp] if !ok { - lblsIdx = labelWithIndex{ - Labels: profile.Labels(), - index: len(selectProfileResult.LabelsSets), - } - seriesByFP[profile.Fingerprint()] = lblsIdx - selectProfileResult.LabelsSets = append(selectProfileResult.LabelsSets, &typesv1.Labels{Labels: profile.Labels()}) + idx = len(selectProfileResult.Fingerprints) + seriesByFP[fp] = idx + selectProfileResult.Fingerprints = append(selectProfileResult.Fingerprints, uint64(fp)) } selectProfileResult.Profiles = append(selectProfileResult.Profiles, &ingestv1.SeriesProfile{ - LabelIndex: int32(lblsIdx.index), + LabelIndex: int32(idx), Timestamp: int64(profile.Timestamp()), }) - } + sp.LogFields(otlog.String("msg", "sending batch to client")) var err error switch s := BidiServerMerge[Res, Req](stream).(type) { diff --git a/pkg/phlaredb/filter_profiles_bidi_test.go b/pkg/phlaredb/filter_profiles_bidi_test.go index 0f93b587f7..1639ae2068 100644 --- a/pkg/phlaredb/filter_profiles_bidi_test.go +++ b/pkg/phlaredb/filter_profiles_bidi_test.go @@ -11,7 +11,6 @@ import ( "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/iter" phlaremodel "github.com/grafana/pyroscope/pkg/model" schemav1 "github.com/grafana/pyroscope/pkg/phlaredb/schemas/v1" @@ -39,34 +38,36 @@ func TestFilterProfiles(t *testing.T) { require.NoError(t, err) require.Equal(t, 2, len(filtered[0])) require.Equal(t, 3, len(bidi.profilesSent)) - testhelper.EqualProto(t, []*ingestv1.ProfileSets{ + + expectedSent := []*ingestv1.ProfileSets{ { - LabelsSets: lo.Times(5, func(i int) *typesv1.Labels { - return &typesv1.Labels{Labels: phlaremodel.LabelsFromStrings("foo", "bar", "i", fmt.Sprintf("%d", i))} + Fingerprints: lo.Times(5, func(i int) uint64 { + return phlaremodel.LabelsFromStrings("foo", "bar", "i", fmt.Sprintf("%d", i)).Hash() }), Profiles: lo.Times(5, func(i int) *ingestv1.SeriesProfile { return &ingestv1.SeriesProfile{Timestamp: int64(model.TimeFromUnixNano(int64(i * int(time.Minute)))), LabelIndex: int32(i)} }), }, { - LabelsSets: lo.Times(5, func(i int) *typesv1.Labels { - return &typesv1.Labels{Labels: phlaremodel.LabelsFromStrings("foo", "bar", "i", fmt.Sprintf("%d", i+5))} + Fingerprints: lo.Times(5, func(i int) uint64 { + return phlaremodel.LabelsFromStrings("foo", "bar", "i", fmt.Sprintf("%d", i+5)).Hash() }), Profiles: lo.Times(5, func(i int) *ingestv1.SeriesProfile { return &ingestv1.SeriesProfile{Timestamp: int64(model.TimeFromUnixNano(int64((i + 5) * int(time.Minute)))), LabelIndex: int32(i)} }), }, { - LabelsSets: lo.Times(1, func(i int) *typesv1.Labels { - return &typesv1.Labels{Labels: phlaremodel.LabelsFromStrings("foo", "bar", "i", fmt.Sprintf("%d", i+10))} + Fingerprints: lo.Times(1, func(i int) uint64 { + return phlaremodel.LabelsFromStrings("foo", "bar", "i", fmt.Sprintf("%d", i+10)).Hash() }), Profiles: lo.Times(1, func(i int) *ingestv1.SeriesProfile { return &ingestv1.SeriesProfile{Timestamp: int64(model.TimeFromUnixNano(int64((i + 10) * int(time.Minute)))), LabelIndex: int32(i)} }), }, - }, bidi.profilesSent) + } + testhelper.EqualProto(t, expectedSent, bidi.profilesSent) - require.Equal(t, []Profile{ + expectedFiltered := []Profile{ ProfileWithLabels{ profile: &schemav1.InMemoryProfile{TimeNanos: int64(5 * int(time.Minute))}, lbs: phlaremodel.LabelsFromStrings("foo", "bar", "i", fmt.Sprintf("%d", 5)), @@ -77,5 +78,6 @@ func TestFilterProfiles(t *testing.T) { lbs: phlaremodel.LabelsFromStrings("foo", "bar", "i", fmt.Sprintf("%d", 10)), fp: model.Fingerprint(phlaremodel.LabelsFromStrings("foo", "bar", "i", fmt.Sprintf("%d", 10)).Hash()), }, - }, filtered[0]) + } + require.Equal(t, expectedFiltered, filtered[0]) } diff --git a/pkg/phlaredb/head.go b/pkg/phlaredb/head.go index b82d5c4904..d5f18b3e2b 100644 --- a/pkg/phlaredb/head.go +++ b/pkg/phlaredb/head.go @@ -187,7 +187,10 @@ func (h *Head) Ingest(ctx context.Context, p *profilev1.Profile, id uuid.UUID, e delta := phlaremodel.Labels(externalLabels).Get(phlaremodel.LabelNameDelta) != "false" externalLabels = phlaremodel.Labels(externalLabels).Delete(phlaremodel.LabelNameDelta) - lbls, seriesFingerprints := phlarelabels.CreateProfileLabels(p, externalLabels...) + enforceLabelOrder := phlaremodel.Labels(externalLabels).Get(phlaremodel.LabelNameOrder) == phlaremodel.LabelOrderEnforced + externalLabels = phlaremodel.Labels(externalLabels).Delete(phlaremodel.LabelNameOrder) + + lbls, seriesFingerprints := phlarelabels.CreateProfileLabels(enforceLabelOrder, p, externalLabels...) for i, fp := range seriesFingerprints { if err := h.limiter.AllowProfile(fp, lbls[i], p.TimeNanos); err != nil { diff --git a/pkg/phlaredb/head_queriers.go b/pkg/phlaredb/head_queriers.go index 3bcf5f43c8..ac5233e45a 100644 --- a/pkg/phlaredb/head_queriers.go +++ b/pkg/phlaredb/head_queriers.go @@ -111,7 +111,7 @@ func (q *headOnDiskQuerier) SelectMatchingProfiles(ctx context.Context, params * return iter.NewSliceIterator(profiles), nil } -func (q *headOnDiskQuerier) SelectMergeByStacktraces(ctx context.Context, params *ingestv1.SelectProfilesRequest) (*phlaremodel.Tree, error) { +func (q *headOnDiskQuerier) SelectMergeByStacktraces(ctx context.Context, params *ingestv1.SelectProfilesRequest, maxNodes int64) (*phlaremodel.Tree, error) { sp, ctx := opentracing.StartSpanFromContext(ctx, "SelectMergeByStacktraces - HeadOnDisk") defer sp.Finish() @@ -137,7 +137,7 @@ func (q *headOnDiskQuerier) SelectMergeByStacktraces(ctx context.Context, params rows := profileRowBatchIterator(it) defer rows.Close() - r := symdb.NewResolver(ctx, q.head.symdb) + r := symdb.NewResolver(ctx, q.head.symdb, symdb.WithResolverMaxNodes(maxNodes)) defer r.Release() if err := mergeByStacktraces[rowProfile](ctx, q.rowGroup(), rows, r); err != nil { @@ -245,10 +245,10 @@ func (q *headOnDiskQuerier) LabelNames(ctx context.Context, req *connect.Request return connect.NewResponse(&typesv1.LabelNamesResponse{}), nil } -func (q *headOnDiskQuerier) MergeByStacktraces(ctx context.Context, rows iter.Iterator[Profile]) (*phlaremodel.Tree, error) { +func (q *headOnDiskQuerier) MergeByStacktraces(ctx context.Context, rows iter.Iterator[Profile], maxNodes int64) (*phlaremodel.Tree, error) { sp, ctx := opentracing.StartSpanFromContext(ctx, "MergeByStacktraces") defer sp.Finish() - r := symdb.NewResolver(ctx, q.head.symdb) + r := symdb.NewResolver(ctx, q.head.symdb, symdb.WithResolverMaxNodes(maxNodes)) defer r.Release() if err := mergeByStacktraces(ctx, q.rowGroup(), rows, r); err != nil { return nil, err @@ -403,10 +403,10 @@ func (q *headInMemoryQuerier) SelectMatchingProfiles(ctx context.Context, params return iter.NewMergeIterator(maxBlockProfile, false, iters...), nil } -func (q *headInMemoryQuerier) SelectMergeByStacktraces(ctx context.Context, params *ingestv1.SelectProfilesRequest) (*phlaremodel.Tree, error) { +func (q *headInMemoryQuerier) SelectMergeByStacktraces(ctx context.Context, params *ingestv1.SelectProfilesRequest, maxNodes int64) (*phlaremodel.Tree, error) { sp, ctx := opentracing.StartSpanFromContext(ctx, "SelectMergeByStacktraces - HeadInMemory") defer sp.Finish() - r := symdb.NewResolver(ctx, q.head.symdb) + r := symdb.NewResolver(ctx, q.head.symdb, symdb.WithResolverMaxNodes(maxNodes)) defer r.Release() index := q.head.profiles.index @@ -551,10 +551,10 @@ func (q *headInMemoryQuerier) LabelNames(ctx context.Context, req *connect.Reque return q.head.LabelNames(ctx, req) } -func (q *headInMemoryQuerier) MergeByStacktraces(ctx context.Context, rows iter.Iterator[Profile]) (*phlaremodel.Tree, error) { +func (q *headInMemoryQuerier) MergeByStacktraces(ctx context.Context, rows iter.Iterator[Profile], maxNodes int64) (*phlaremodel.Tree, error) { sp, _ := opentracing.StartSpanFromContext(ctx, "MergeByStacktraces - HeadInMemory") defer sp.Finish() - r := symdb.NewResolver(ctx, q.head.symdb) + r := symdb.NewResolver(ctx, q.head.symdb, symdb.WithResolverMaxNodes(maxNodes)) defer r.Release() for rows.Next() { p, ok := rows.At().(ProfileWithLabels) diff --git a/pkg/phlaredb/head_test.go b/pkg/phlaredb/head_test.go index 7f2c5cbd5b..8d7232de77 100644 --- a/pkg/phlaredb/head_test.go +++ b/pkg/phlaredb/head_test.go @@ -12,6 +12,7 @@ import ( "connectrpc.com/connect" "github.com/google/uuid" "github.com/oklog/ulid" + "github.com/parquet-go/parquet-go" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/common/model" "github.com/stretchr/testify/assert" @@ -525,6 +526,89 @@ func TestIsStale(t *testing.T) { require.False(t, head.isStale(now.Add(2*StaleGracePeriod).UnixNano(), now.Add(2*StaleGracePeriod))) } +func profileWithID(id int) (*profilev1.Profile, uuid.UUID) { + p := newProfileFoo() + p.TimeNanos = int64(id) + return p, uuid.MustParse(fmt.Sprintf("00000000-0000-0000-0000-%012d", id)) +} + +func TestHead_ProfileOrder(t *testing.T) { + head := newTestHead(t) + + p, u := profileWithID(1) + require.NoError(t, head.Ingest( + context.Background(), + p, + u, + &typesv1.LabelPair{Name: phlaremodel.LabelNameProfileName, Value: "memory"}, + &typesv1.LabelPair{Name: phlaremodel.LabelNameOrder, Value: phlaremodel.LabelOrderEnforced}, + &typesv1.LabelPair{Name: phlaremodel.LabelNameServiceName, Value: "service-a"}, + )) + + p, u = profileWithID(2) + require.NoError(t, head.Ingest( + context.Background(), + p, + u, + &typesv1.LabelPair{Name: phlaremodel.LabelNameProfileName, Value: "memory"}, + &typesv1.LabelPair{Name: phlaremodel.LabelNameOrder, Value: phlaremodel.LabelOrderEnforced}, + &typesv1.LabelPair{Name: phlaremodel.LabelNameServiceName, Value: "service-b"}, + &typesv1.LabelPair{Name: "____Label", Value: "important"}, + )) + + p, u = profileWithID(3) + require.NoError(t, head.Ingest( + context.Background(), + p, + u, + &typesv1.LabelPair{Name: phlaremodel.LabelNameProfileName, Value: "memory"}, + &typesv1.LabelPair{Name: phlaremodel.LabelNameOrder, Value: phlaremodel.LabelOrderEnforced}, + &typesv1.LabelPair{Name: phlaremodel.LabelNameServiceName, Value: "service-c"}, + &typesv1.LabelPair{Name: "AAALabel", Value: "important"}, + )) + + p, u = profileWithID(4) + require.NoError(t, head.Ingest( + context.Background(), + p, + u, + &typesv1.LabelPair{Name: phlaremodel.LabelNameProfileName, Value: "cpu"}, + &typesv1.LabelPair{Name: phlaremodel.LabelNameOrder, Value: phlaremodel.LabelOrderEnforced}, + &typesv1.LabelPair{Name: phlaremodel.LabelNameServiceName, Value: "service-a"}, + &typesv1.LabelPair{Name: "000Label", Value: "important"}, + )) + + p, u = profileWithID(5) + require.NoError(t, head.Ingest( + context.Background(), + p, + u, + &typesv1.LabelPair{Name: phlaremodel.LabelNameProfileName, Value: "cpu"}, + &typesv1.LabelPair{Name: phlaremodel.LabelNameOrder, Value: phlaremodel.LabelOrderEnforced}, + &typesv1.LabelPair{Name: phlaremodel.LabelNameServiceName, Value: "service-b"}, + )) + + p, u = profileWithID(6) + require.NoError(t, head.Ingest( + context.Background(), + p, + u, + &typesv1.LabelPair{Name: phlaremodel.LabelNameProfileName, Value: "cpu"}, + &typesv1.LabelPair{Name: phlaremodel.LabelNameOrder, Value: phlaremodel.LabelOrderEnforced}, + &typesv1.LabelPair{Name: phlaremodel.LabelNameServiceName, Value: "service-b"}, + )) + + head.Flush(context.Background()) + + // test that the profiles are ordered correctly + type row struct{ TimeNanos uint64 } + rows, err := parquet.ReadFile[row](filepath.Join(head.headPath, "profiles.parquet")) + require.NoError(t, err) + require.Equal(t, []row{ + {4}, {5}, {6}, {1}, {2}, {3}, + }, rows) +} + func BenchmarkHeadIngestProfiles(t *testing.B) { var ( profilePaths = []string{ diff --git a/pkg/phlaredb/labels/labels.go b/pkg/phlaredb/labels/labels.go index fb931ad160..405955abde 100644 --- a/pkg/phlaredb/labels/labels.go +++ b/pkg/phlaredb/labels/labels.go @@ -1,7 +1,7 @@ package labels import ( - "fmt" + "sort" "strings" "github.com/prometheus/common/model" @@ -11,9 +11,7 @@ import ( phlaremodel "github.com/grafana/pyroscope/pkg/model" ) -var labelNameServiceName = fmt.Sprintf("__%s__", phlaremodel.LabelNameServiceName) - -func CreateProfileLabels(p *profilev1.Profile, externalLabels ...*typesv1.LabelPair) ([]phlaremodel.Labels, []model.Fingerprint) { +func CreateProfileLabels(enforceOrder bool, p *profilev1.Profile, externalLabels ...*typesv1.LabelPair) ([]phlaremodel.Labels, []model.Fingerprint) { // build label set per sample type before references are rewritten var ( sb strings.Builder @@ -24,8 +22,8 @@ func CreateProfileLabels(p *profilev1.Profile, externalLabels ...*typesv1.LabelP // Inject into labels the __service_name__ label if it exists // This allows better locality of the data in parquet files (row group are sorted by). - if serviceName := lbls.Labels().Get(phlaremodel.LabelNameServiceName); serviceName != "" { - lbls.Set(labelNameServiceName, serviceName) + if serviceName := phlaremodel.Labels(externalLabels).Get(phlaremodel.LabelNameServiceName); serviceName != "" { + lbls.Set(phlaremodel.LabelNameServiceNamePrivate, serviceName) } // set common labels @@ -56,7 +54,12 @@ func CreateProfileLabels(p *profilev1.Profile, externalLabels ...*typesv1.LabelP _, _ = sb.WriteString(periodUnit) t := sb.String() lbls.Set(phlaremodel.LabelNameProfileType, t) - lbs := lbls.Labels().Clone() + lbs := lbls.LabelsUnsorted().Clone() + if enforceOrder { + sort.Sort(phlaremodel.LabelsEnforcedOrder(lbs)) + } else { + sort.Sort(lbs) + } profilesLabels[pos] = lbs seriesRefs[pos] = model.Fingerprint(lbs.Hash()) diff --git a/pkg/phlaredb/labels/labels_test.go b/pkg/phlaredb/labels/labels_test.go index 2d7b6dc09a..aaf7786362 100644 --- a/pkg/phlaredb/labels/labels_test.go +++ b/pkg/phlaredb/labels/labels_test.go @@ -1,7 +1,6 @@ package labels import ( - "sort" "testing" "github.com/prometheus/common/model" @@ -21,12 +20,12 @@ func TestLabelsForProfiles(t *testing.T) { "default", phlaremodel.Labels{{Name: model.MetricNameLabel, Value: "cpu"}}, phlaremodel.Labels{ - {Name: model.MetricNameLabel, Value: "cpu"}, - {Name: phlaremodel.LabelNameUnit, Value: "unit"}, {Name: phlaremodel.LabelNameProfileType, Value: "cpu:type:unit:type:unit"}, - {Name: phlaremodel.LabelNameType, Value: "type"}, + {Name: model.MetricNameLabel, Value: "cpu"}, {Name: phlaremodel.LabelNamePeriodType, Value: "type"}, {Name: phlaremodel.LabelNamePeriodUnit, Value: "unit"}, + {Name: phlaremodel.LabelNameType, Value: "type"}, + {Name: phlaremodel.LabelNameUnit, Value: "unit"}, }, }, { @@ -36,21 +35,20 @@ func TestLabelsForProfiles(t *testing.T) { {Name: phlaremodel.LabelNameServiceName, Value: "service_name"}, }, phlaremodel.Labels{ - {Name: model.MetricNameLabel, Value: "cpu"}, - {Name: phlaremodel.LabelNameUnit, Value: "unit"}, {Name: phlaremodel.LabelNameProfileType, Value: "cpu:type:unit:type:unit"}, - {Name: phlaremodel.LabelNameType, Value: "type"}, + {Name: phlaremodel.LabelNameServiceNamePrivate, Value: "service_name"}, + {Name: model.MetricNameLabel, Value: "cpu"}, {Name: phlaremodel.LabelNamePeriodType, Value: "type"}, {Name: phlaremodel.LabelNamePeriodUnit, Value: "unit"}, - {Name: labelNameServiceName, Value: "service_name"}, + {Name: phlaremodel.LabelNameType, Value: "type"}, + {Name: phlaremodel.LabelNameUnit, Value: "unit"}, {Name: phlaremodel.LabelNameServiceName, Value: "service_name"}, }, }, } { tt := tt t.Run(tt.name, func(t *testing.T) { - sort.Sort(tt.expected) - result, fps := CreateProfileLabels(newProfileFoo(), tt.in...) + result, fps := CreateProfileLabels(true, newProfileFoo(), tt.in...) require.Equal(t, tt.expected, result[0]) require.Equal(t, model.Fingerprint(tt.expected.Hash()), fps[0]) }) diff --git a/pkg/phlaredb/phlaredb_test.go b/pkg/phlaredb/phlaredb_test.go index 1af6e2d172..603cbe112a 100644 --- a/pkg/phlaredb/phlaredb_test.go +++ b/pkg/phlaredb/phlaredb_test.go @@ -195,7 +195,7 @@ func TestMergeProfilesStacktraces(t *testing.T) { resp, err := bidi.Receive() require.NoError(t, err) require.Nil(t, resp.Result) - require.Len(t, resp.SelectedProfiles.LabelsSets, 1) + require.Len(t, resp.SelectedProfiles.Fingerprints, 1) require.Len(t, resp.SelectedProfiles.Profiles, 5) require.NoError(t, bidi.Send(&ingestv1.MergeProfilesStacktracesRequest{ @@ -325,7 +325,7 @@ func TestMergeProfilesPprof(t *testing.T) { resp, err := bidi.Receive() require.NoError(t, err) require.Nil(t, resp.Result) - require.Len(t, resp.SelectedProfiles.LabelsSets, 1) + require.Len(t, resp.SelectedProfiles.Fingerprints, 1) require.Len(t, resp.SelectedProfiles.Profiles, 5) require.NoError(t, bidi.Send(&ingestv1.MergeProfilesPprofRequest{ diff --git a/pkg/phlaredb/sample_merge.go b/pkg/phlaredb/sample_merge.go index 801c385bdd..411a10bf24 100644 --- a/pkg/phlaredb/sample_merge.go +++ b/pkg/phlaredb/sample_merge.go @@ -20,7 +20,7 @@ import ( "github.com/grafana/pyroscope/pkg/phlaredb/symdb" ) -func (b *singleBlockQuerier) MergeByStacktraces(ctx context.Context, rows iter.Iterator[Profile]) (*phlaremodel.Tree, error) { +func (b *singleBlockQuerier) MergeByStacktraces(ctx context.Context, rows iter.Iterator[Profile], maxNodes int64) (*phlaremodel.Tree, error) { sp, ctx := opentracing.StartSpanFromContext(ctx, "MergeByStacktraces - Block") defer sp.Finish() sp.SetTag("block ULID", b.meta.ULID.String()) @@ -32,7 +32,7 @@ func (b *singleBlockQuerier) MergeByStacktraces(ctx context.Context, rows iter.I defer b.queries.Done() ctx = query.AddMetricsToContext(ctx, b.metrics.query) - r := symdb.NewResolver(ctx, b.symbols) + r := symdb.NewResolver(ctx, b.symbols, symdb.WithResolverMaxNodes(maxNodes)) defer r.Release() if err := mergeByStacktraces(ctx, b.profileSourceTable().file, rows, r); err != nil { return nil, err diff --git a/pkg/phlaredb/sample_merge_test.go b/pkg/phlaredb/sample_merge_test.go index c0ed15086e..3f3568c88c 100644 --- a/pkg/phlaredb/sample_merge_test.go +++ b/pkg/phlaredb/sample_merge_test.go @@ -125,7 +125,7 @@ func TestMergeSampleByStacktraces(t *testing.T) { }) require.NoError(t, err) - r, err := q.queriers[0].MergeByStacktraces(ctx, profiles) + r, err := q.queriers[0].MergeByStacktraces(ctx, profiles, 0) require.NoError(t, err) require.Equal(t, expected.String(), r.String()) }) @@ -220,7 +220,7 @@ func TestHeadMergeSampleByStacktraces(t *testing.T) { End: int64(model.TimeFromUnixNano(int64(1 * time.Minute))), }) require.NoError(t, err) - r, err := db.queriers()[0].MergeByStacktraces(ctx, profiles) + r, err := db.queriers()[0].MergeByStacktraces(ctx, profiles, 0) require.NoError(t, err) require.Equal(t, expected.String(), r.String()) }) diff --git a/pkg/phlaredb/schemas/v1/testhelper/profile.go b/pkg/phlaredb/schemas/v1/testhelper/profile.go index 0189cdf669..5829b44476 100644 --- a/pkg/phlaredb/schemas/v1/testhelper/profile.go +++ b/pkg/phlaredb/schemas/v1/testhelper/profile.go @@ -14,7 +14,7 @@ import ( func NewProfileSchema(p *profilev1.Profile, name string) ([]schemav1.InMemoryProfile, []phlaremodel.Labels) { var ( - lbls, seriesRefs = labels.CreateProfileLabels(p, &typesv1.LabelPair{Name: model.MetricNameLabel, Value: name}) + lbls, seriesRefs = labels.CreateProfileLabels(true, p, &typesv1.LabelPair{Name: model.MetricNameLabel, Value: name}) ps = make([]schemav1.InMemoryProfile, len(lbls)) ) for idxType := range lbls { diff --git a/pkg/phlaredb/symdb/resolver.go b/pkg/phlaredb/symdb/resolver.go index 8705ae31cd..6049ed0528 100644 --- a/pkg/phlaredb/symdb/resolver.go +++ b/pkg/phlaredb/symdb/resolver.go @@ -223,7 +223,7 @@ func (r *Resolver) Tree() (*model.Tree, error) { var lock sync.Mutex tree := new(model.Tree) err := r.withSymbols(ctx, func(symbols *Symbols, samples schemav1.Samples) error { - resolved, err := symbols.Tree(ctx, samples) + resolved, err := symbols.Tree(ctx, samples, r.maxNodes) if err != nil { return err } @@ -309,14 +309,18 @@ func (r *Symbols) Pprof( return b.buildPprof(), nil } -func (r *Symbols) Tree(ctx context.Context, samples schemav1.Samples) (*model.Tree, error) { +func (r *Symbols) Tree( + ctx context.Context, + samples schemav1.Samples, + maxNodes int64, +) (*model.Tree, error) { t := treeSymbolsFromPool() defer t.reset() t.init(r, samples) if err := r.Stacktraces.ResolveStacktraceLocations(ctx, t, samples.StacktraceIDs); err != nil { return nil, err } - return t.tree, nil + return t.tree.Tree(maxNodes, t.symbols.Strings), nil } // findCallSite returns the stack trace of the call site diff --git a/pkg/phlaredb/symdb/resolver_tree.go b/pkg/phlaredb/symdb/resolver_tree.go index df63fa2880..9deac35547 100644 --- a/pkg/phlaredb/symdb/resolver_tree.go +++ b/pkg/phlaredb/symdb/resolver_tree.go @@ -10,8 +10,8 @@ import ( type treeSymbols struct { symbols *Symbols samples *schemav1.Samples - tree *model.Tree - lines []string + tree *model.StacktraceTree + lines []int32 cur int } @@ -26,7 +26,7 @@ func treeSymbolsFromPool() *treeSymbols { func (r *treeSymbols) reset() { r.symbols = nil r.samples = nil - r.tree = nil + r.tree.Reset() r.lines = r.lines[:0] r.cur = 0 treeSymbolsPool.Put(r) @@ -35,18 +35,21 @@ func (r *treeSymbols) reset() { func (r *treeSymbols) init(symbols *Symbols, samples schemav1.Samples) { r.symbols = symbols r.samples = &samples - r.tree = new(model.Tree) + if r.tree == nil { + // Branching factor. + r.tree = model.NewStacktraceTree(samples.Len() * 2) + } } func (r *treeSymbols) InsertStacktrace(_ uint32, locations []int32) { r.lines = r.lines[:0] - for i := len(locations) - 1; i >= 0; i-- { + for i := 0; i < len(locations); i++ { lines := r.symbols.Locations[locations[i]].Line - for j := len(lines) - 1; j >= 0; j-- { + for j := 0; j < len(lines); j++ { f := r.symbols.Functions[lines[j].FunctionId] - r.lines = append(r.lines, r.symbols.Strings[f.Name]) + r.lines = append(r.lines, int32(f.Name)) } } - r.tree.InsertStack(int64(r.samples.Values[r.cur]), r.lines...) + r.tree.Insert(r.lines, int64(r.samples.Values[r.cur])) r.cur++ } diff --git a/pkg/phlaredb/symdb/resolver_tree_test.go b/pkg/phlaredb/symdb/resolver_tree_test.go index b083929b29..75baf98de8 100644 --- a/pkg/phlaredb/symdb/resolver_tree_test.go +++ b/pkg/phlaredb/symdb/resolver_tree_test.go @@ -5,6 +5,8 @@ import ( "testing" "github.com/stretchr/testify/require" + + v1 "github.com/grafana/pyroscope/pkg/phlaredb/schemas/v1" ) func Test_memory_Resolver_ResolveTree(t *testing.T) { @@ -30,26 +32,34 @@ func Test_block_Resolver_ResolveTree(t *testing.T) { require.Equal(t, expectedFingerprint, treeFingerprint(resolved)) } -func Benchmark_block_Resolver_ResolveTree_Small(t *testing.B) { - s := newMemSuite(t, [][]string{{"testdata/profile.pb.gz"}}) - t.ResetTimer() - t.ReportAllocs() - for i := 0; i < t.N; i++ { - r := NewResolver(context.Background(), s.db) - r.AddSamples(0, s.indexed[0][0].Samples) - _, _ = r.Tree() - } +func Benchmark_Resolver_ResolveTree_Small(b *testing.B) { + s := newMemSuite(b, [][]string{{"testdata/profile.pb.gz"}}) + samples := s.indexed[0][0].Samples + b.Run("0", benchmarkResolverResolveTree(s.db, samples, 0)) + b.Run("1K", benchmarkResolverResolveTree(s.db, samples, 1<<10)) + b.Run("8K", benchmarkResolverResolveTree(s.db, samples, 8<<10)) } -func Benchmark_block_Resolver_ResolveTree_Big(b *testing.B) { +func Benchmark_Resolver_ResolveTree_Big(b *testing.B) { s := memSuite{t: b, files: [][]string{{"testdata/big-profile.pb.gz"}}} s.config = DefaultConfig().WithDirectory(b.TempDir()) s.init() - b.ResetTimer() - b.ReportAllocs() - for i := 0; i < b.N; i++ { - r := NewResolver(context.Background(), s.db) - r.AddSamples(0, s.indexed[0][0].Samples) - _, _ = r.Tree() + samples := s.indexed[0][0].Samples + b.Run("0", benchmarkResolverResolveTree(s.db, samples, 0)) + b.Run("8K", benchmarkResolverResolveTree(s.db, samples, 8<<10)) + b.Run("16K", benchmarkResolverResolveTree(s.db, samples, 16<<10)) + b.Run("32K", benchmarkResolverResolveTree(s.db, samples, 32<<10)) + b.Run("64K", benchmarkResolverResolveTree(s.db, samples, 64<<10)) +} + +func benchmarkResolverResolveTree(sym SymbolsReader, samples v1.Samples, n int64) func(b *testing.B) { + return func(b *testing.B) { + b.ResetTimer() + b.ReportAllocs() + for i := 0; i < b.N; i++ { + r := NewResolver(context.Background(), sym, WithResolverMaxNodes(n)) + r.AddSamples(0, samples) + _, _ = r.Tree() + } } } diff --git a/pkg/phlaredb/tsdb/index.go b/pkg/phlaredb/tsdb/index.go index ad1ff52e8c..bb8769094d 100644 --- a/pkg/phlaredb/tsdb/index.go +++ b/pkg/phlaredb/tsdb/index.go @@ -298,7 +298,6 @@ func (shard *indexShard) add(metric []*typesv1.LabelPair, fp model.Fingerprint) values.fps[fingerprints.value] = fingerprints internedLabels[i] = &typesv1.LabelPair{Name: values.name, Value: fingerprints.value} } - sort.Sort(internedLabels) return internedLabels } diff --git a/pkg/pprof/fix_go_heap_truncated_test.go b/pkg/pprof/fix_go_heap_truncated_test.go deleted file mode 100644 index 5c648507e7..0000000000 --- a/pkg/pprof/fix_go_heap_truncated_test.go +++ /dev/null @@ -1,42 +0,0 @@ -package pprof - -import ( - "os" - "testing" - - "github.com/stretchr/testify/require" -) - -func Benchmark_RepairGoTruncatedStacktraces(b *testing.B) { - p, err := OpenFile("testdata/goheapfix/heap_go_truncated_3.pb.gz") - require.NoError(b, err) - b.ResetTimer() - b.ReportAllocs() - for i := 0; i < b.N; i++ { - RepairGoHeapTruncatedStacktraces(FixGoProfile(p.CloneVT())) - } -} - -func Test_UpdateFixtures_RepairGoTruncatedStacktraces(t *testing.T) { - t.Skip() - t.Helper() - paths := []string{ - "testdata/goheapfix/heap_go_truncated_1.pb.gz", // Cortex. - "testdata/goheapfix/heap_go_truncated_2.pb.gz", // Cortex. - "testdata/goheapfix/heap_go_truncated_3.pb.gz", // Loki. Pathological. - "testdata/goheapfix/heap_go_truncated_4.pb.gz", // Pyroscope. - } - for _, path := range paths { - func() { - p, err := OpenFile(path) - require.NoError(t, err, path) - f, err := os.Create(path + ".fixed") - require.NoError(t, err, path) - defer f.Close() - p.Profile = FixGoProfile(p.Profile) - RepairGoHeapTruncatedStacktraces(p.Profile) - _, err = p.WriteTo(f) - require.NoError(t, err, path) - }() - } -} diff --git a/pkg/pprof/fix_go_profile.go b/pkg/pprof/fix_go_profile.go index e073f9ae21..adf6715de0 100644 --- a/pkg/pprof/fix_go_profile.go +++ b/pkg/pprof/fix_go_profile.go @@ -19,8 +19,8 @@ func FixGoProfile(p *profilev1.Profile) *profilev1.Profile { // Now that the profile is normalized, we can try to repair // truncated stack traces, if any. Note that repaired stacks // are not deduplicated, so the caller need to normalize the - if MayHaveGoHeapTruncatedStacktraces(p) { - RepairGoHeapTruncatedStacktraces(p) + if PotentialTruncatedGoStacktraces(p) { + RepairGoTruncatedStacktraces(p) } return p } diff --git a/pkg/pprof/fix_go_profile_test.go b/pkg/pprof/fix_go_profile_test.go index 30be1864ad..6fa8d48e8f 100644 --- a/pkg/pprof/fix_go_profile_test.go +++ b/pkg/pprof/fix_go_profile_test.go @@ -10,7 +10,7 @@ import ( ) func Test_FixGoProfile(t *testing.T) { - p, err := OpenFile("testdata/goheapfix/heap_go_truncated_4.pb.gz") + p, err := OpenFile("testdata/gotruncatefix/heap_go_truncated_4.pb.gz") require.NoError(t, err) f := FixGoProfile(p.Profile) diff --git a/pkg/pprof/fix_go_heap_truncated.go b/pkg/pprof/fix_go_truncated.go similarity index 83% rename from pkg/pprof/fix_go_heap_truncated.go rename to pkg/pprof/fix_go_truncated.go index e5ef857f2f..1e169165a0 100644 --- a/pkg/pprof/fix_go_heap_truncated.go +++ b/pkg/pprof/fix_go_truncated.go @@ -10,30 +10,49 @@ import ( ) const ( - minGroupSize = 2 + minGroupSize = 2 + maxRecursiveDepth = 56 // Profiles with deeply recursive stack traces are ignored. tokens = 8 tokenLen = 16 - suffixLen = tokens + tokenLen + suffixLen = tokens + tokenLen // stacktraces shorter than suffixLen are not considered as truncated or missing stacks copied from tokenBytesLen = tokenLen * 8 suffixBytesLen = suffixLen * 8 ) -// MayHaveGoHeapTruncatedStacktraces reports whether there are +// PotentialTruncatedGoStacktraces reports whether there are // any chances that the profile may have truncated stack traces. -func MayHaveGoHeapTruncatedStacktraces(p *profilev1.Profile) bool { - if !hasGoHeapSampleTypes(p) { +func PotentialTruncatedGoStacktraces(p *profilev1.Profile) bool { + var minDepth int + var maxDepth int + + if hasGoHeapSampleTypes(p) { + minDepth = 32 + + // Go heap profiles in Go 1.23+ have a depth limit of 128 frames. Let's not try to fix truncation if we see any longer stacks. + maxDepth = 33 + } else if hasGoCPUSampleTypes(p) { + minDepth = 64 + } else { return false } - // Some truncated stacks have depth less than the depth limit (32). - const minDepth = 28 + + // Some truncated heap stacks have depth less than the depth limit. + // https://github.com/golang/go/blob/f7c330eac7777612574d8a1652fd415391f6095e/src/runtime/mprof.go#L446 + minDepth -= 4 + + deepEnough := false for _, s := range p.Sample { if len(s.LocationId) >= minDepth { - return true + deepEnough = true + } + // when it's too deep we no longer perform reassemlbing of truncated stacktraces + if maxDepth != 0 && len(s.LocationId) >= maxDepth { + return false } } - return false + return deepEnough } func hasGoHeapSampleTypes(p *profilev1.Profile) bool { @@ -50,7 +69,18 @@ func hasGoHeapSampleTypes(p *profilev1.Profile) bool { return false } -// RepairGoHeapTruncatedStacktraces repairs truncated stack traces +func hasGoCPUSampleTypes(p *profilev1.Profile) bool { + for _, st := range p.SampleType { + switch p.StringTable[st.Type] { + case + "cpu": + return true + } + } + return false +} + +// RepairGoTruncatedStacktraces repairs truncated stack traces // in Go heap profiles. // // Go heap profile has a depth limit of 32 frames, which often @@ -66,7 +96,7 @@ func hasGoHeapSampleTypes(p *profilev1.Profile) bool { // one by at least 16 frames in a row from the top, and has frames // above its root, stack S considered truncated, and the missing part // is copied from R. -func RepairGoHeapTruncatedStacktraces(p *profilev1.Profile) { +func RepairGoTruncatedStacktraces(p *profilev1.Profile) { // Group stack traces by bottom (closest to the root) locations. // Typically, there are very few groups (a hundred or two). samples, groups := split(p) @@ -82,7 +112,7 @@ func RepairGoHeapTruncatedStacktraces(p *profilev1.Profile) { if i+1 < len(groups) { n = groups[i+1] } - if s := n - g; s < minGroupSize { + if s := n - g; s < (minGroupSize - 1) { continue } // We take suffix of the first sample in the group. @@ -168,8 +198,7 @@ func RepairGoHeapTruncatedStacktraces(p *profilev1.Profile) { } c = n j++ - if j == tokenLen { - // Profiles with deeply recursive stack traces are ignored. + if j == maxRecursiveDepth { return } } diff --git a/pkg/pprof/fix_go_truncated_test.go b/pkg/pprof/fix_go_truncated_test.go new file mode 100644 index 0000000000..cd6c15af64 --- /dev/null +++ b/pkg/pprof/fix_go_truncated_test.go @@ -0,0 +1,89 @@ +package pprof + +import ( + "fmt" + "os" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/grafana/pyroscope/pkg/pprof/testhelper" +) + +func Benchmark_RepairGoTruncatedStacktraces(b *testing.B) { + p, err := OpenFile("testdata/gotruncatefix/heap_go_truncated_3.pb.gz") + require.NoError(b, err) + b.ResetTimer() + b.ReportAllocs() + for i := 0; i < b.N; i++ { + RepairGoTruncatedStacktraces(FixGoProfile(p.CloneVT())) + } +} + +func generateStackTrace(n int) []string { + res := make([]string, n) + runes := []rune("abcdefghijklmnopqrstuvwxyz") + + for idx := range res { + dest := n - (idx + 1) + if idx == 0 { + res[dest] = "start" + continue + } + res[dest] = fmt.Sprintf("%c%d", runes[(idx-1)/10], (idx-1)%10) + } + return res +} + +func Test_RepairGoTruncatedStacktraces(t *testing.T) { + n := 128 + fullStack := generateStackTrace(n) + b := testhelper.NewProfileBuilder(0).CPUProfile() + b.ForStacktraceString(fullStack[n-24:]...).AddSamples(1) + b.ForStacktraceString(fullStack[n-58 : n-9]...).AddSamples(2) + b.ForStacktraceString(fullStack[n-57 : n-8]...).AddSamples(4) + b.ForStacktraceString(fullStack[n-56 : n-7]...).AddSamples(8) + b.ForStacktraceString(append([]string{"yy1"}, fullStack[n-22:]...)...).AddSamples(16) + + RepairGoTruncatedStacktraces(b.Profile) + + // ensure all stacktraces start with the same 8 location ids + stacks := make([]uint64, 8) + for idx, sample := range b.Profile.Sample { + first8Stacks := sample.LocationId[len(sample.LocationId)-8:] + if idx == 0 { + copy(stacks, first8Stacks) + continue + } + t.Log(stacks) + assert.Equal(t, stacks, first8Stacks) + } +} + +func Test_UpdateFixtures_RepairGoTruncatedStacktraces(t *testing.T) { + if os.Getenv("UPDATE_FIXTURES") != "true" { + t.Skip() + } + t.Helper() + paths := []string{ + "testdata/gotruncatefix/heap_go_truncated_1.pb.gz", // Cortex. + "testdata/gotruncatefix/heap_go_truncated_2.pb.gz", // Cortex. + "testdata/gotruncatefix/heap_go_truncated_3.pb.gz", // Loki. Pathological. + "testdata/gotruncatefix/heap_go_truncated_4.pb.gz", // Pyroscope. + "testdata/gotruncatefix/cpu_go_truncated_1.pb.gz", // Cloudwatch Exporter + } + for _, path := range paths { + func() { + p, err := OpenFile(path) + require.NoError(t, err, path) + f, err := os.Create(path + ".fixed") + require.NoError(t, err, path) + defer f.Close() + p.Profile = FixGoProfile(p.Profile) + RepairGoTruncatedStacktraces(p.Profile) + _, err = p.WriteTo(f) + require.NoError(t, err, path) + }() + } +} diff --git a/pkg/pprof/testdata/gotruncatefix/cpu_go_truncated_1.pb.gz b/pkg/pprof/testdata/gotruncatefix/cpu_go_truncated_1.pb.gz new file mode 100644 index 0000000000..8234eba5dd Binary files /dev/null and b/pkg/pprof/testdata/gotruncatefix/cpu_go_truncated_1.pb.gz differ diff --git a/pkg/pprof/testdata/gotruncatefix/cpu_go_truncated_1.pb.gz.fixed b/pkg/pprof/testdata/gotruncatefix/cpu_go_truncated_1.pb.gz.fixed new file mode 100644 index 0000000000..d57624acec Binary files /dev/null and b/pkg/pprof/testdata/gotruncatefix/cpu_go_truncated_1.pb.gz.fixed differ diff --git a/pkg/pprof/testdata/goheapfix/heap_go_truncated_1.pb.gz b/pkg/pprof/testdata/gotruncatefix/heap_go_truncated_1.pb.gz similarity index 100% rename from pkg/pprof/testdata/goheapfix/heap_go_truncated_1.pb.gz rename to pkg/pprof/testdata/gotruncatefix/heap_go_truncated_1.pb.gz diff --git a/pkg/pprof/testdata/goheapfix/heap_go_truncated_1.pb.gz.fixed b/pkg/pprof/testdata/gotruncatefix/heap_go_truncated_1.pb.gz.fixed similarity index 100% rename from pkg/pprof/testdata/goheapfix/heap_go_truncated_1.pb.gz.fixed rename to pkg/pprof/testdata/gotruncatefix/heap_go_truncated_1.pb.gz.fixed diff --git a/pkg/pprof/testdata/goheapfix/heap_go_truncated_2.pb.gz b/pkg/pprof/testdata/gotruncatefix/heap_go_truncated_2.pb.gz similarity index 100% rename from pkg/pprof/testdata/goheapfix/heap_go_truncated_2.pb.gz rename to pkg/pprof/testdata/gotruncatefix/heap_go_truncated_2.pb.gz diff --git a/pkg/pprof/testdata/goheapfix/heap_go_truncated_2.pb.gz.fixed b/pkg/pprof/testdata/gotruncatefix/heap_go_truncated_2.pb.gz.fixed similarity index 100% rename from pkg/pprof/testdata/goheapfix/heap_go_truncated_2.pb.gz.fixed rename to pkg/pprof/testdata/gotruncatefix/heap_go_truncated_2.pb.gz.fixed diff --git a/pkg/pprof/testdata/goheapfix/heap_go_truncated_3.pb.gz b/pkg/pprof/testdata/gotruncatefix/heap_go_truncated_3.pb.gz similarity index 100% rename from pkg/pprof/testdata/goheapfix/heap_go_truncated_3.pb.gz rename to pkg/pprof/testdata/gotruncatefix/heap_go_truncated_3.pb.gz diff --git a/pkg/pprof/testdata/goheapfix/heap_go_truncated_3.pb.gz.fixed b/pkg/pprof/testdata/gotruncatefix/heap_go_truncated_3.pb.gz.fixed similarity index 100% rename from pkg/pprof/testdata/goheapfix/heap_go_truncated_3.pb.gz.fixed rename to pkg/pprof/testdata/gotruncatefix/heap_go_truncated_3.pb.gz.fixed diff --git a/pkg/pprof/testdata/goheapfix/heap_go_truncated_4.pb.gz b/pkg/pprof/testdata/gotruncatefix/heap_go_truncated_4.pb.gz similarity index 100% rename from pkg/pprof/testdata/goheapfix/heap_go_truncated_4.pb.gz rename to pkg/pprof/testdata/gotruncatefix/heap_go_truncated_4.pb.gz diff --git a/pkg/pprof/testdata/goheapfix/heap_go_truncated_4.pb.gz.fixed b/pkg/pprof/testdata/gotruncatefix/heap_go_truncated_4.pb.gz.fixed similarity index 100% rename from pkg/pprof/testdata/goheapfix/heap_go_truncated_4.pb.gz.fixed rename to pkg/pprof/testdata/gotruncatefix/heap_go_truncated_4.pb.gz.fixed diff --git a/pkg/querier/querier.go b/pkg/querier/querier.go index 0dee90a9fd..78977b9b2f 100644 --- a/pkg/querier/querier.go +++ b/pkg/querier/querier.go @@ -604,9 +604,14 @@ func (q *Querier) SelectMergeStacktraces(ctx context.Context, req *connect.Reque return nil, err } - return connect.NewResponse(&querierv1.SelectMergeStacktracesResponse{ - Flamegraph: phlaremodel.NewFlameGraph(t, req.Msg.GetMaxNodes()), - }), nil + var resp querierv1.SelectMergeStacktracesResponse + switch req.Msg.Format { + default: + resp.Flamegraph = phlaremodel.NewFlameGraph(t, req.Msg.GetMaxNodes()) + case querierv1.ProfileFormat_PROFILE_FORMAT_TREE: + resp.Tree = t.Bytes(req.Msg.GetMaxNodes()) + } + return connect.NewResponse(&resp), nil } func (q *Querier) SelectMergeSpanProfile(ctx context.Context, req *connect.Request[querierv1.SelectMergeSpanProfileRequest]) (*connect.Response[querierv1.SelectMergeSpanProfileResponse], error) { @@ -631,9 +636,14 @@ func (q *Querier) SelectMergeSpanProfile(ctx context.Context, req *connect.Reque return nil, err } - return connect.NewResponse(&querierv1.SelectMergeSpanProfileResponse{ - Flamegraph: phlaremodel.NewFlameGraph(t, req.Msg.GetMaxNodes()), - }), nil + var resp querierv1.SelectMergeSpanProfileResponse + switch req.Msg.Format { + default: + resp.Flamegraph = phlaremodel.NewFlameGraph(t, req.Msg.GetMaxNodes()) + case querierv1.ProfileFormat_PROFILE_FORMAT_TREE: + resp.Tree = t.Bytes(req.Msg.GetMaxNodes()) + } + return connect.NewResponse(&resp), nil } func isEndpointNotExistingErr(err error) bool { @@ -718,6 +728,7 @@ func (sq storeQuery) MergeStacktracesRequest(req *querierv1.SelectMergeStacktrac LabelSelector: req.LabelSelector, ProfileTypeID: req.ProfileTypeID, MaxNodes: req.MaxNodes, + Format: req.Format, } } @@ -743,6 +754,7 @@ func (sq storeQuery) MergeSpanProfileRequest(req *querierv1.SelectMergeSpanProfi LabelSelector: req.LabelSelector, SpanSelector: req.SpanSelector, MaxNodes: req.MaxNodes, + Format: req.Format, } } diff --git a/pkg/querier/select_merge.go b/pkg/querier/select_merge.go index 961f4b2ce5..e4bb2a48c6 100644 --- a/pkg/querier/select_merge.go +++ b/pkg/querier/select_merge.go @@ -26,9 +26,10 @@ import ( ) type ProfileWithLabels struct { - Timestamp int64 - phlaremodel.Labels + Timestamp int64 + Fingerprint uint64 IngesterAddr string + phlaremodel.Labels } type BidiClientMerge[Req any, Res any] interface { @@ -139,16 +140,25 @@ func (s *mergeIterator[R, Req, Res]) Next() bool { return false } s.currIdx = 0 - s.currentProfile.Timestamp = s.curr.Profiles[s.currIdx].Timestamp - s.currentProfile.Labels = s.curr.LabelsSets[s.curr.Profiles[s.currIdx].LabelIndex].Labels + s.setCurrentProfile() return true } s.currIdx++ - s.currentProfile.Timestamp = s.curr.Profiles[s.currIdx].Timestamp - s.currentProfile.Labels = s.curr.LabelsSets[s.curr.Profiles[s.currIdx].LabelIndex].Labels + s.setCurrentProfile() return true } +func (s *mergeIterator[R, Req, Res]) setCurrentProfile() { + p := s.curr.Profiles[s.currIdx] + s.currentProfile.Timestamp = p.Timestamp + if len(s.curr.LabelsSets) > 0 { + s.currentProfile.Labels = s.curr.LabelsSets[p.LabelIndex].Labels + } + if len(s.curr.Fingerprints) > 0 { + s.currentProfile.Fingerprint = s.curr.Fingerprints[p.LabelIndex] + } +} + func (s *mergeIterator[R, Req, Res]) fetchBatch() { var selectedProfiles *ingestv1.ProfileSets switch bidi := (s.bidi).(type) { @@ -250,10 +260,7 @@ func skipDuplicates(ctx context.Context, its []MergeIterator) error { return s.At() }, func(p1, p2 *ProfileWithLabels) bool { - if p1.Timestamp == p2.Timestamp { - return phlaremodel.CompareLabelPairs(p1.Labels, p2.Labels) < 0 - } - return p1.Timestamp < p2.Timestamp + return p1.Timestamp <= p2.Timestamp }, func(s MergeIterator) { if err := s.Close(); err != nil { @@ -262,17 +269,21 @@ func skipDuplicates(ctx context.Context, its []MergeIterator) error { }) defer tree.Close() + // We rely on the fact that profiles are ordered by timestamp. + // In order to deduplicate profiles, we only keep the first profile + // with a given fingerprint for a given timestamp. + fingerprints := newTimestampedFingerprints() duplicates := 0 total := 0 - previousTs := int64(-1) - previousLabels := phlaremodel.Labels{} for tree.Next() { next := tree.Winner() profile := next.At() total++ - if previousTs != profile.Timestamp || phlaremodel.CompareLabelPairs(previousLabels, profile.Labels) != 0 { - previousTs = profile.Timestamp - previousLabels = profile.Labels + fingerprint := profile.Fingerprint + if fingerprint == 0 && len(profile.Labels) > 0 { + fingerprint = profile.Labels.Hash() + } + if fingerprints.keep(profile.Timestamp, fingerprint) { next.Keep() continue } @@ -287,6 +298,42 @@ func skipDuplicates(ctx context.Context, its []MergeIterator) error { return errors.Err() } +func newTimestampedFingerprints() *timestampedFingerprints { + return ×tampedFingerprints{ + timestamp: math.MaxInt64, + fingerprints: make(map[uint64]struct{}), + } +} + +type timestampedFingerprints struct { + timestamp int64 + fingerprints map[uint64]struct{} +} + +// keep reports whether the profile has unique fingerprint for the timestamp. +func (p *timestampedFingerprints) keep(ts int64, fingerprint uint64) bool { + if p.timestamp != ts { + p.reset(ts, fingerprint) + return true + } + return !p.fingerprintSeen(fingerprint) +} + +func (p *timestampedFingerprints) reset(ts int64, fingerprint uint64) { + p.timestamp = ts + clear(p.fingerprints) + p.fingerprints[fingerprint] = struct{}{} +} + +func (p *timestampedFingerprints) fingerprintSeen(fingerprint uint64) (seen bool) { + _, seen = p.fingerprints[fingerprint] + if seen { + return true + } + p.fingerprints[fingerprint] = struct{}{} + return false +} + // selectMergeTree selects the profile from each ingester by deduping them and // returns merge of stacktrace samples represented as a tree. func selectMergeTree(ctx context.Context, responses []ResponseFromReplica[clientpool.BidiClientMergeProfilesStacktraces]) (*phlaremodel.Tree, error) { diff --git a/pkg/storegateway/bucket_stores_test.go b/pkg/storegateway/bucket_stores_test.go index dfbe2cfb05..e490c5cf80 100644 --- a/pkg/storegateway/bucket_stores_test.go +++ b/pkg/storegateway/bucket_stores_test.go @@ -66,7 +66,7 @@ func TestBucketStores_BlockMetricsRegistration(t *testing.T) { }, Start: 0, End: time.Now().UnixMilli(), - }) + }, 0) require.NoError(t, err) require.NotNil(t, r) diff --git a/pkg/test/integration/ingest_pprof_test.go b/pkg/test/integration/ingest_pprof_test.go index f410ca3f0a..0cc8133444 100644 --- a/pkg/test/integration/ingest_pprof_test.go +++ b/pkg/test/integration/ingest_pprof_test.go @@ -267,6 +267,57 @@ func TestIngest(t *testing.T) { } } +func TestIngestPPROFFixPythonLinenumbers(t *testing.T) { + p := PyroscopeTest{} + p.Start(t) + defer p.Stop(t) + profile := pprof.RawFromProto(&profilev1.Profile{ + SampleType: []*profilev1.ValueType{{ + Type: 5, + Unit: 6, + }}, + PeriodType: &profilev1.ValueType{ + Type: 5, Unit: 6, + }, + StringTable: []string{"", "main", "func1", "func2", "qwe.py", "cpu", "nanoseconds"}, + Period: 1000000000, + Function: []*profilev1.Function{ + {Id: 1, Name: 1, Filename: 4, SystemName: 1, StartLine: 239}, + {Id: 2, Name: 2, Filename: 4, SystemName: 2, StartLine: 42}, + {Id: 3, Name: 3, Filename: 4, SystemName: 3, StartLine: 7}, + }, + Location: []*profilev1.Location{ + {Id: 1, Line: []*profilev1.Line{{FunctionId: 1, Line: 242}}}, + {Id: 2, Line: []*profilev1.Line{{FunctionId: 2, Line: 50}}}, + {Id: 3, Line: []*profilev1.Line{{FunctionId: 3, Line: 8}}}, + }, + Sample: []*profilev1.Sample{ + {LocationId: []uint64{2, 1}, Value: []int64{10}}, + {LocationId: []uint64{3, 1}, Value: []int64{13}}, + }, + }) + + tempProfileFile, err := os.CreateTemp("", "profile") + require.NoError(t, err) + _, err = profile.WriteTo(tempProfileFile) + assert.NoError(t, err) + tempProfileFile.Close() + defer os.Remove(tempProfileFile.Name()) + + rb := p.NewRequestBuilder(t). + Spy("pyspy") + req := rb.IngestPPROFRequest(tempProfileFile.Name(), "", "") + p.Ingest(t, req, 200) + + renderedProfile := rb.SelectMergeProfile("process_cpu:cpu:nanoseconds:cpu:nanoseconds", nil) + actual := bench.StackCollapseProto(renderedProfile.Msg, 0, 1) + expected := []string{ + "qwe.py:242 - main;qwe.py:50 - func1 10", + "qwe.py:242 - main;qwe.py:8 - func2 13", + } + assert.Equal(t, expected, actual) +} + func TestPush(t *testing.T) { p := new(PyroscopeTest) p.Start(t) diff --git a/pkg/validation/limits.go b/pkg/validation/limits.go index 64a9fd91b6..4d0131628b 100644 --- a/pkg/validation/limits.go +++ b/pkg/validation/limits.go @@ -33,6 +33,7 @@ type Limits struct { MaxLabelValueLength int `yaml:"max_label_value_length" json:"max_label_value_length"` MaxLabelNamesPerSeries int `yaml:"max_label_names_per_series" json:"max_label_names_per_series"` MaxSessionsPerSeries int `yaml:"max_sessions_per_series" json:"max_sessions_per_series"` + EnforceLabelsOrder bool `yaml:"enforce_labels_order" json:"enforce_labels_order"` MaxProfileSizeBytes int `yaml:"max_profile_size_bytes" json:"max_profile_size_bytes"` MaxProfileStacktraceSamples int `yaml:"max_profile_stacktrace_samples" json:"max_profile_stacktrace_samples"` @@ -109,6 +110,7 @@ func (l *Limits) RegisterFlags(f *flag.FlagSet) { f.IntVar(&l.MaxLabelValueLength, "validation.max-length-label-value", 2048, "Maximum length accepted for label value. This setting also applies to the metric name.") f.IntVar(&l.MaxLabelNamesPerSeries, "validation.max-label-names-per-series", 30, "Maximum number of label names per series.") f.IntVar(&l.MaxSessionsPerSeries, "validation.max-sessions-per-series", 0, "Maximum number of sessions per series. 0 to disable.") + f.BoolVar(&l.EnforceLabelsOrder, "validation.enforce-labels-order", false, "Enforce labels order optimization.") f.IntVar(&l.MaxLocalSeriesPerTenant, "ingester.max-local-series-per-tenant", 0, "Maximum number of active series of profiles per tenant, per ingester. 0 to disable.") f.IntVar(&l.MaxGlobalSeriesPerTenant, "ingester.max-global-series-per-tenant", 5000, "Maximum number of active series of profiles per tenant, across the cluster. 0 to disable. When the global limit is enabled, each ingester is configured with a dynamic local limit based on the replication factor and the current number of healthy ingesters, and is kept updated whenever the number of ingesters change.") @@ -286,6 +288,10 @@ func (o *Overrides) MaxSessionsPerSeries(tenantID string) int { return o.getOverridesForTenant(tenantID).MaxSessionsPerSeries } +func (o *Overrides) EnforceLabelsOrder(tenantID string) bool { + return o.getOverridesForTenant(tenantID).EnforceLabelsOrder +} + func (o *Overrides) DistributorAggregationWindow(tenantID string) model.Duration { return o.getOverridesForTenant(tenantID).DistributorAggregationWindow }