Profiling: Add Phlare and Parca datasources (#57809)

* Add phlare datasource

* Rename

* Add parca

* Add self field to parca

* Make sure phlare works with add to dashboard flow

* Add profiling category and hide behind feature flag

* Update description and logos

* Update phlare icon

* Cleanup logging

* Clean up logging

* Fix for shift+enter

* onRunQuery to set label

* Update type naming

* Fix lint

* Fix test and quality issues

Co-authored-by: Joey Tawadrous <joey.tawadrous@grafana.com>
This commit is contained in:
Andrej Ocenas
2022-10-28 13:33:37 +02:00
committed by GitHub
co-authored by Joey Tawadrous
parent 1d53a6f57e
commit 0845ac2f53
81 changed files with 41611 additions and 271 deletions
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,829 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.28.1
// protoc (unknown)
// source: parca/debuginfo/v1alpha1/debuginfo.proto
package debuginfov1alpha1
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
// Source enum describes the source a debuginfo is from.
type DownloadInfo_Source int32
const (
// To understand when no source is set we have the unknown source.
DownloadInfo_SOURCE_UNKNOWN_UNSPECIFIED DownloadInfo_Source = 0
// The debuginfo was uploaded by a user/agent.
DownloadInfo_SOURCE_UPLOAD DownloadInfo_Source = 1
// The debuginfo was downloaded from a public debuginfod server.
DownloadInfo_SOURCE_DEBUGINFOD DownloadInfo_Source = 2
)
// Enum value maps for DownloadInfo_Source.
var (
DownloadInfo_Source_name = map[int32]string{
0: "SOURCE_UNKNOWN_UNSPECIFIED",
1: "SOURCE_UPLOAD",
2: "SOURCE_DEBUGINFOD",
}
DownloadInfo_Source_value = map[string]int32{
"SOURCE_UNKNOWN_UNSPECIFIED": 0,
"SOURCE_UPLOAD": 1,
"SOURCE_DEBUGINFOD": 2,
}
)
func (x DownloadInfo_Source) Enum() *DownloadInfo_Source {
p := new(DownloadInfo_Source)
*p = x
return p
}
func (x DownloadInfo_Source) String() string {
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
}
func (DownloadInfo_Source) Descriptor() protoreflect.EnumDescriptor {
return file_parca_debuginfo_v1alpha1_debuginfo_proto_enumTypes[0].Descriptor()
}
func (DownloadInfo_Source) Type() protoreflect.EnumType {
return &file_parca_debuginfo_v1alpha1_debuginfo_proto_enumTypes[0]
}
func (x DownloadInfo_Source) Number() protoreflect.EnumNumber {
return protoreflect.EnumNumber(x)
}
// Deprecated: Use DownloadInfo_Source.Descriptor instead.
func (DownloadInfo_Source) EnumDescriptor() ([]byte, []int) {
return file_parca_debuginfo_v1alpha1_debuginfo_proto_rawDescGZIP(), []int{7, 0}
}
// ExistsRequest request to determine if debug info exists for a given build_id
type ExistsRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// build_id is a unique identifier for the debug data
BuildId string `protobuf:"bytes,1,opt,name=build_id,json=buildId,proto3" json:"build_id,omitempty"`
// hash is the hash of the debug information file
Hash string `protobuf:"bytes,2,opt,name=hash,proto3" json:"hash,omitempty"`
}
func (x *ExistsRequest) Reset() {
*x = ExistsRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_parca_debuginfo_v1alpha1_debuginfo_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *ExistsRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ExistsRequest) ProtoMessage() {}
func (x *ExistsRequest) ProtoReflect() protoreflect.Message {
mi := &file_parca_debuginfo_v1alpha1_debuginfo_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ExistsRequest.ProtoReflect.Descriptor instead.
func (*ExistsRequest) Descriptor() ([]byte, []int) {
return file_parca_debuginfo_v1alpha1_debuginfo_proto_rawDescGZIP(), []int{0}
}
func (x *ExistsRequest) GetBuildId() string {
if x != nil {
return x.BuildId
}
return ""
}
func (x *ExistsRequest) GetHash() string {
if x != nil {
return x.Hash
}
return ""
}
// ExistsResponse returns whether the given build_id has debug info
type ExistsResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// exists indicates if there is debug data present for the given build_id
Exists bool `protobuf:"varint,1,opt,name=exists,proto3" json:"exists,omitempty"`
}
func (x *ExistsResponse) Reset() {
*x = ExistsResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_parca_debuginfo_v1alpha1_debuginfo_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *ExistsResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ExistsResponse) ProtoMessage() {}
func (x *ExistsResponse) ProtoReflect() protoreflect.Message {
mi := &file_parca_debuginfo_v1alpha1_debuginfo_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ExistsResponse.ProtoReflect.Descriptor instead.
func (*ExistsResponse) Descriptor() ([]byte, []int) {
return file_parca_debuginfo_v1alpha1_debuginfo_proto_rawDescGZIP(), []int{1}
}
func (x *ExistsResponse) GetExists() bool {
if x != nil {
return x.Exists
}
return false
}
// UploadRequest upload debug info
type UploadRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// data contains either the upload info metadata or the debug info
//
// Types that are assignable to Data:
// *UploadRequest_Info
// *UploadRequest_ChunkData
Data isUploadRequest_Data `protobuf_oneof:"data"`
}
func (x *UploadRequest) Reset() {
*x = UploadRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_parca_debuginfo_v1alpha1_debuginfo_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *UploadRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*UploadRequest) ProtoMessage() {}
func (x *UploadRequest) ProtoReflect() protoreflect.Message {
mi := &file_parca_debuginfo_v1alpha1_debuginfo_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use UploadRequest.ProtoReflect.Descriptor instead.
func (*UploadRequest) Descriptor() ([]byte, []int) {
return file_parca_debuginfo_v1alpha1_debuginfo_proto_rawDescGZIP(), []int{2}
}
func (m *UploadRequest) GetData() isUploadRequest_Data {
if m != nil {
return m.Data
}
return nil
}
func (x *UploadRequest) GetInfo() *UploadInfo {
if x, ok := x.GetData().(*UploadRequest_Info); ok {
return x.Info
}
return nil
}
func (x *UploadRequest) GetChunkData() []byte {
if x, ok := x.GetData().(*UploadRequest_ChunkData); ok {
return x.ChunkData
}
return nil
}
type isUploadRequest_Data interface {
isUploadRequest_Data()
}
type UploadRequest_Info struct {
// info is the metadata for the debug info
Info *UploadInfo `protobuf:"bytes,1,opt,name=info,proto3,oneof"`
}
type UploadRequest_ChunkData struct {
// chunk_data is the raw bytes of the debug info
ChunkData []byte `protobuf:"bytes,2,opt,name=chunk_data,json=chunkData,proto3,oneof"`
}
func (*UploadRequest_Info) isUploadRequest_Data() {}
func (*UploadRequest_ChunkData) isUploadRequest_Data() {}
// UploadInfo contains the build_id and other metadata for the debug data
type UploadInfo struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// build_id is a unique identifier for the debug data
BuildId string `protobuf:"bytes,1,opt,name=build_id,json=buildId,proto3" json:"build_id,omitempty"`
// hash is the hash of the source file that debug information extracted from
Hash string `protobuf:"bytes,2,opt,name=hash,proto3" json:"hash,omitempty"`
}
func (x *UploadInfo) Reset() {
*x = UploadInfo{}
if protoimpl.UnsafeEnabled {
mi := &file_parca_debuginfo_v1alpha1_debuginfo_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *UploadInfo) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*UploadInfo) ProtoMessage() {}
func (x *UploadInfo) ProtoReflect() protoreflect.Message {
mi := &file_parca_debuginfo_v1alpha1_debuginfo_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use UploadInfo.ProtoReflect.Descriptor instead.
func (*UploadInfo) Descriptor() ([]byte, []int) {
return file_parca_debuginfo_v1alpha1_debuginfo_proto_rawDescGZIP(), []int{3}
}
func (x *UploadInfo) GetBuildId() string {
if x != nil {
return x.BuildId
}
return ""
}
func (x *UploadInfo) GetHash() string {
if x != nil {
return x.Hash
}
return ""
}
// UploadResponse returns the build_id and the size of the uploaded debug info
type UploadResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// build_id is a unique identifier for the debug data
BuildId string `protobuf:"bytes,1,opt,name=build_id,json=buildId,proto3" json:"build_id,omitempty"`
// size is the number of bytes of the debug info
Size uint64 `protobuf:"varint,2,opt,name=size,proto3" json:"size,omitempty"`
}
func (x *UploadResponse) Reset() {
*x = UploadResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_parca_debuginfo_v1alpha1_debuginfo_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *UploadResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*UploadResponse) ProtoMessage() {}
func (x *UploadResponse) ProtoReflect() protoreflect.Message {
mi := &file_parca_debuginfo_v1alpha1_debuginfo_proto_msgTypes[4]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use UploadResponse.ProtoReflect.Descriptor instead.
func (*UploadResponse) Descriptor() ([]byte, []int) {
return file_parca_debuginfo_v1alpha1_debuginfo_proto_rawDescGZIP(), []int{4}
}
func (x *UploadResponse) GetBuildId() string {
if x != nil {
return x.BuildId
}
return ""
}
func (x *UploadResponse) GetSize() uint64 {
if x != nil {
return x.Size
}
return 0
}
// DownloadRequest upload debug info
type DownloadRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// build_id is a unique identifier for the debug data
BuildId string `protobuf:"bytes,1,opt,name=build_id,json=buildId,proto3" json:"build_id,omitempty"`
}
func (x *DownloadRequest) Reset() {
*x = DownloadRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_parca_debuginfo_v1alpha1_debuginfo_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *DownloadRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*DownloadRequest) ProtoMessage() {}
func (x *DownloadRequest) ProtoReflect() protoreflect.Message {
mi := &file_parca_debuginfo_v1alpha1_debuginfo_proto_msgTypes[5]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use DownloadRequest.ProtoReflect.Descriptor instead.
func (*DownloadRequest) Descriptor() ([]byte, []int) {
return file_parca_debuginfo_v1alpha1_debuginfo_proto_rawDescGZIP(), []int{5}
}
func (x *DownloadRequest) GetBuildId() string {
if x != nil {
return x.BuildId
}
return ""
}
// DownloadRequest returns chunked data of the debuginfo.
type DownloadResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// data contains either the upload info metadata or the debug info
//
// Types that are assignable to Data:
// *DownloadResponse_Info
// *DownloadResponse_ChunkData
Data isDownloadResponse_Data `protobuf_oneof:"data"`
}
func (x *DownloadResponse) Reset() {
*x = DownloadResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_parca_debuginfo_v1alpha1_debuginfo_proto_msgTypes[6]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *DownloadResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*DownloadResponse) ProtoMessage() {}
func (x *DownloadResponse) ProtoReflect() protoreflect.Message {
mi := &file_parca_debuginfo_v1alpha1_debuginfo_proto_msgTypes[6]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use DownloadResponse.ProtoReflect.Descriptor instead.
func (*DownloadResponse) Descriptor() ([]byte, []int) {
return file_parca_debuginfo_v1alpha1_debuginfo_proto_rawDescGZIP(), []int{6}
}
func (m *DownloadResponse) GetData() isDownloadResponse_Data {
if m != nil {
return m.Data
}
return nil
}
func (x *DownloadResponse) GetInfo() *DownloadInfo {
if x, ok := x.GetData().(*DownloadResponse_Info); ok {
return x.Info
}
return nil
}
func (x *DownloadResponse) GetChunkData() []byte {
if x, ok := x.GetData().(*DownloadResponse_ChunkData); ok {
return x.ChunkData
}
return nil
}
type isDownloadResponse_Data interface {
isDownloadResponse_Data()
}
type DownloadResponse_Info struct {
// info is the metadata for the debug info
Info *DownloadInfo `protobuf:"bytes,1,opt,name=info,proto3,oneof"`
}
type DownloadResponse_ChunkData struct {
// chunk_data is the raw bytes of the debug info
ChunkData []byte `protobuf:"bytes,2,opt,name=chunk_data,json=chunkData,proto3,oneof"`
}
func (*DownloadResponse_Info) isDownloadResponse_Data() {}
func (*DownloadResponse_ChunkData) isDownloadResponse_Data() {}
// DownloadInfo metadata for the debug data that is being downloaded.
type DownloadInfo struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// Source indicates the origin of the debuginfo being downloaded.
Source DownloadInfo_Source `protobuf:"varint,1,opt,name=source,proto3,enum=parca.debuginfo.v1alpha1.DownloadInfo_Source" json:"source,omitempty"`
}
func (x *DownloadInfo) Reset() {
*x = DownloadInfo{}
if protoimpl.UnsafeEnabled {
mi := &file_parca_debuginfo_v1alpha1_debuginfo_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *DownloadInfo) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*DownloadInfo) ProtoMessage() {}
func (x *DownloadInfo) ProtoReflect() protoreflect.Message {
mi := &file_parca_debuginfo_v1alpha1_debuginfo_proto_msgTypes[7]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use DownloadInfo.ProtoReflect.Descriptor instead.
func (*DownloadInfo) Descriptor() ([]byte, []int) {
return file_parca_debuginfo_v1alpha1_debuginfo_proto_rawDescGZIP(), []int{7}
}
func (x *DownloadInfo) GetSource() DownloadInfo_Source {
if x != nil {
return x.Source
}
return DownloadInfo_SOURCE_UNKNOWN_UNSPECIFIED
}
var File_parca_debuginfo_v1alpha1_debuginfo_proto protoreflect.FileDescriptor
var file_parca_debuginfo_v1alpha1_debuginfo_proto_rawDesc = []byte{
0x0a, 0x28, 0x70, 0x61, 0x72, 0x63, 0x61, 0x2f, 0x64, 0x65, 0x62, 0x75, 0x67, 0x69, 0x6e, 0x66,
0x6f, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x64, 0x65, 0x62, 0x75, 0x67,
0x69, 0x6e, 0x66, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x18, 0x70, 0x61, 0x72, 0x63,
0x61, 0x2e, 0x64, 0x65, 0x62, 0x75, 0x67, 0x69, 0x6e, 0x66, 0x6f, 0x2e, 0x76, 0x31, 0x61, 0x6c,
0x70, 0x68, 0x61, 0x31, 0x22, 0x3e, 0x0a, 0x0d, 0x45, 0x78, 0x69, 0x73, 0x74, 0x73, 0x52, 0x65,
0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x69,
0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x49, 0x64,
0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04,
0x68, 0x61, 0x73, 0x68, 0x22, 0x28, 0x0a, 0x0e, 0x45, 0x78, 0x69, 0x73, 0x74, 0x73, 0x52, 0x65,
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x65, 0x78, 0x69, 0x73, 0x74, 0x73,
0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x65, 0x78, 0x69, 0x73, 0x74, 0x73, 0x22, 0x74,
0x0a, 0x0d, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12,
0x3a, 0x0a, 0x04, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e,
0x70, 0x61, 0x72, 0x63, 0x61, 0x2e, 0x64, 0x65, 0x62, 0x75, 0x67, 0x69, 0x6e, 0x66, 0x6f, 0x2e,
0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x49,
0x6e, 0x66, 0x6f, 0x48, 0x00, 0x52, 0x04, 0x69, 0x6e, 0x66, 0x6f, 0x12, 0x1f, 0x0a, 0x0a, 0x63,
0x68, 0x75, 0x6e, 0x6b, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x48,
0x00, 0x52, 0x09, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x44, 0x61, 0x74, 0x61, 0x42, 0x06, 0x0a, 0x04,
0x64, 0x61, 0x74, 0x61, 0x22, 0x3b, 0x0a, 0x0a, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x49, 0x6e,
0x66, 0x6f, 0x12, 0x19, 0x0a, 0x08, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x01,
0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x49, 0x64, 0x12, 0x12, 0x0a,
0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x61, 0x73,
0x68, 0x22, 0x3f, 0x0a, 0x0e, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f,
0x6e, 0x73, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x69, 0x64, 0x18,
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x49, 0x64, 0x12, 0x12,
0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x73, 0x69,
0x7a, 0x65, 0x22, 0x2c, 0x0a, 0x0f, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65,
0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x69,
0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x49, 0x64,
0x22, 0x79, 0x0a, 0x10, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70,
0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3c, 0x0a, 0x04, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x01, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x26, 0x2e, 0x70, 0x61, 0x72, 0x63, 0x61, 0x2e, 0x64, 0x65, 0x62, 0x75, 0x67,
0x69, 0x6e, 0x66, 0x6f, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x44, 0x6f,
0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x49, 0x6e, 0x66, 0x6f, 0x48, 0x00, 0x52, 0x04, 0x69, 0x6e,
0x66, 0x6f, 0x12, 0x1f, 0x0a, 0x0a, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x5f, 0x64, 0x61, 0x74, 0x61,
0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x09, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x44,
0x61, 0x74, 0x61, 0x42, 0x06, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0xa9, 0x01, 0x0a, 0x0c,
0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x45, 0x0a, 0x06,
0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2d, 0x2e, 0x70,
0x61, 0x72, 0x63, 0x61, 0x2e, 0x64, 0x65, 0x62, 0x75, 0x67, 0x69, 0x6e, 0x66, 0x6f, 0x2e, 0x76,
0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64,
0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x06, 0x73, 0x6f, 0x75,
0x72, 0x63, 0x65, 0x22, 0x52, 0x0a, 0x06, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x1e, 0x0a,
0x1a, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x5f,
0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x11, 0x0a,
0x0d, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x55, 0x50, 0x4c, 0x4f, 0x41, 0x44, 0x10, 0x01,
0x12, 0x15, 0x0a, 0x11, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x44, 0x45, 0x42, 0x55, 0x47,
0x49, 0x4e, 0x46, 0x4f, 0x44, 0x10, 0x02, 0x32, 0xb9, 0x02, 0x0a, 0x10, 0x44, 0x65, 0x62, 0x75,
0x67, 0x49, 0x6e, 0x66, 0x6f, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x5d, 0x0a, 0x06,
0x45, 0x78, 0x69, 0x73, 0x74, 0x73, 0x12, 0x27, 0x2e, 0x70, 0x61, 0x72, 0x63, 0x61, 0x2e, 0x64,
0x65, 0x62, 0x75, 0x67, 0x69, 0x6e, 0x66, 0x6f, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61,
0x31, 0x2e, 0x45, 0x78, 0x69, 0x73, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
0x28, 0x2e, 0x70, 0x61, 0x72, 0x63, 0x61, 0x2e, 0x64, 0x65, 0x62, 0x75, 0x67, 0x69, 0x6e, 0x66,
0x6f, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x45, 0x78, 0x69, 0x73, 0x74,
0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x5f, 0x0a, 0x06, 0x55,
0x70, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x27, 0x2e, 0x70, 0x61, 0x72, 0x63, 0x61, 0x2e, 0x64, 0x65,
0x62, 0x75, 0x67, 0x69, 0x6e, 0x66, 0x6f, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31,
0x2e, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28,
0x2e, 0x70, 0x61, 0x72, 0x63, 0x61, 0x2e, 0x64, 0x65, 0x62, 0x75, 0x67, 0x69, 0x6e, 0x66, 0x6f,
0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64,
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x28, 0x01, 0x12, 0x65, 0x0a, 0x08,
0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x29, 0x2e, 0x70, 0x61, 0x72, 0x63, 0x61,
0x2e, 0x64, 0x65, 0x62, 0x75, 0x67, 0x69, 0x6e, 0x66, 0x6f, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70,
0x68, 0x61, 0x31, 0x2e, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75,
0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x70, 0x61, 0x72, 0x63, 0x61, 0x2e, 0x64, 0x65, 0x62, 0x75,
0x67, 0x69, 0x6e, 0x66, 0x6f, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x44,
0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22,
0x00, 0x30, 0x01, 0x42, 0x84, 0x02, 0x0a, 0x1c, 0x63, 0x6f, 0x6d, 0x2e, 0x70, 0x61, 0x72, 0x63,
0x61, 0x2e, 0x64, 0x65, 0x62, 0x75, 0x67, 0x69, 0x6e, 0x66, 0x6f, 0x2e, 0x76, 0x31, 0x61, 0x6c,
0x70, 0x68, 0x61, 0x31, 0x42, 0x0e, 0x44, 0x65, 0x62, 0x75, 0x67, 0x69, 0x6e, 0x66, 0x6f, 0x50,
0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x52, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63,
0x6f, 0x6d, 0x2f, 0x70, 0x61, 0x72, 0x63, 0x61, 0x2d, 0x64, 0x65, 0x76, 0x2f, 0x70, 0x61, 0x72,
0x63, 0x61, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x2f,
0x70, 0x61, 0x72, 0x63, 0x61, 0x2f, 0x64, 0x65, 0x62, 0x75, 0x67, 0x69, 0x6e, 0x66, 0x6f, 0x2f,
0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3b, 0x64, 0x65, 0x62, 0x75, 0x67, 0x69, 0x6e,
0x66, 0x6f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xa2, 0x02, 0x03, 0x50, 0x44, 0x58,
0xaa, 0x02, 0x18, 0x50, 0x61, 0x72, 0x63, 0x61, 0x2e, 0x44, 0x65, 0x62, 0x75, 0x67, 0x69, 0x6e,
0x66, 0x6f, 0x2e, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xca, 0x02, 0x18, 0x50, 0x61,
0x72, 0x63, 0x61, 0x5c, 0x44, 0x65, 0x62, 0x75, 0x67, 0x69, 0x6e, 0x66, 0x6f, 0x5c, 0x56, 0x31,
0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xe2, 0x02, 0x24, 0x50, 0x61, 0x72, 0x63, 0x61, 0x5c, 0x44,
0x65, 0x62, 0x75, 0x67, 0x69, 0x6e, 0x66, 0x6f, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61,
0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x1a,
0x50, 0x61, 0x72, 0x63, 0x61, 0x3a, 0x3a, 0x44, 0x65, 0x62, 0x75, 0x67, 0x69, 0x6e, 0x66, 0x6f,
0x3a, 0x3a, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x33,
}
var (
file_parca_debuginfo_v1alpha1_debuginfo_proto_rawDescOnce sync.Once
file_parca_debuginfo_v1alpha1_debuginfo_proto_rawDescData = file_parca_debuginfo_v1alpha1_debuginfo_proto_rawDesc
)
func file_parca_debuginfo_v1alpha1_debuginfo_proto_rawDescGZIP() []byte {
file_parca_debuginfo_v1alpha1_debuginfo_proto_rawDescOnce.Do(func() {
file_parca_debuginfo_v1alpha1_debuginfo_proto_rawDescData = protoimpl.X.CompressGZIP(file_parca_debuginfo_v1alpha1_debuginfo_proto_rawDescData)
})
return file_parca_debuginfo_v1alpha1_debuginfo_proto_rawDescData
}
var file_parca_debuginfo_v1alpha1_debuginfo_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
var file_parca_debuginfo_v1alpha1_debuginfo_proto_msgTypes = make([]protoimpl.MessageInfo, 8)
var file_parca_debuginfo_v1alpha1_debuginfo_proto_goTypes = []interface{}{
(DownloadInfo_Source)(0), // 0: parca.debuginfo.v1alpha1.DownloadInfo.Source
(*ExistsRequest)(nil), // 1: parca.debuginfo.v1alpha1.ExistsRequest
(*ExistsResponse)(nil), // 2: parca.debuginfo.v1alpha1.ExistsResponse
(*UploadRequest)(nil), // 3: parca.debuginfo.v1alpha1.UploadRequest
(*UploadInfo)(nil), // 4: parca.debuginfo.v1alpha1.UploadInfo
(*UploadResponse)(nil), // 5: parca.debuginfo.v1alpha1.UploadResponse
(*DownloadRequest)(nil), // 6: parca.debuginfo.v1alpha1.DownloadRequest
(*DownloadResponse)(nil), // 7: parca.debuginfo.v1alpha1.DownloadResponse
(*DownloadInfo)(nil), // 8: parca.debuginfo.v1alpha1.DownloadInfo
}
var file_parca_debuginfo_v1alpha1_debuginfo_proto_depIdxs = []int32{
4, // 0: parca.debuginfo.v1alpha1.UploadRequest.info:type_name -> parca.debuginfo.v1alpha1.UploadInfo
8, // 1: parca.debuginfo.v1alpha1.DownloadResponse.info:type_name -> parca.debuginfo.v1alpha1.DownloadInfo
0, // 2: parca.debuginfo.v1alpha1.DownloadInfo.source:type_name -> parca.debuginfo.v1alpha1.DownloadInfo.Source
1, // 3: parca.debuginfo.v1alpha1.DebugInfoService.Exists:input_type -> parca.debuginfo.v1alpha1.ExistsRequest
3, // 4: parca.debuginfo.v1alpha1.DebugInfoService.Upload:input_type -> parca.debuginfo.v1alpha1.UploadRequest
6, // 5: parca.debuginfo.v1alpha1.DebugInfoService.Download:input_type -> parca.debuginfo.v1alpha1.DownloadRequest
2, // 6: parca.debuginfo.v1alpha1.DebugInfoService.Exists:output_type -> parca.debuginfo.v1alpha1.ExistsResponse
5, // 7: parca.debuginfo.v1alpha1.DebugInfoService.Upload:output_type -> parca.debuginfo.v1alpha1.UploadResponse
7, // 8: parca.debuginfo.v1alpha1.DebugInfoService.Download:output_type -> parca.debuginfo.v1alpha1.DownloadResponse
6, // [6:9] is the sub-list for method output_type
3, // [3:6] is the sub-list for method input_type
3, // [3:3] is the sub-list for extension type_name
3, // [3:3] is the sub-list for extension extendee
0, // [0:3] is the sub-list for field type_name
}
func init() { file_parca_debuginfo_v1alpha1_debuginfo_proto_init() }
func file_parca_debuginfo_v1alpha1_debuginfo_proto_init() {
if File_parca_debuginfo_v1alpha1_debuginfo_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_parca_debuginfo_v1alpha1_debuginfo_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ExistsRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_parca_debuginfo_v1alpha1_debuginfo_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ExistsResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_parca_debuginfo_v1alpha1_debuginfo_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*UploadRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_parca_debuginfo_v1alpha1_debuginfo_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*UploadInfo); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_parca_debuginfo_v1alpha1_debuginfo_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*UploadResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_parca_debuginfo_v1alpha1_debuginfo_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*DownloadRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_parca_debuginfo_v1alpha1_debuginfo_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*DownloadResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_parca_debuginfo_v1alpha1_debuginfo_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*DownloadInfo); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
file_parca_debuginfo_v1alpha1_debuginfo_proto_msgTypes[2].OneofWrappers = []interface{}{
(*UploadRequest_Info)(nil),
(*UploadRequest_ChunkData)(nil),
}
file_parca_debuginfo_v1alpha1_debuginfo_proto_msgTypes[6].OneofWrappers = []interface{}{
(*DownloadResponse_Info)(nil),
(*DownloadResponse_ChunkData)(nil),
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_parca_debuginfo_v1alpha1_debuginfo_proto_rawDesc,
NumEnums: 1,
NumMessages: 8,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_parca_debuginfo_v1alpha1_debuginfo_proto_goTypes,
DependencyIndexes: file_parca_debuginfo_v1alpha1_debuginfo_proto_depIdxs,
EnumInfos: file_parca_debuginfo_v1alpha1_debuginfo_proto_enumTypes,
MessageInfos: file_parca_debuginfo_v1alpha1_debuginfo_proto_msgTypes,
}.Build()
File_parca_debuginfo_v1alpha1_debuginfo_proto = out.File
file_parca_debuginfo_v1alpha1_debuginfo_proto_rawDesc = nil
file_parca_debuginfo_v1alpha1_debuginfo_proto_goTypes = nil
file_parca_debuginfo_v1alpha1_debuginfo_proto_depIdxs = nil
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,137 @@
// Code generated by protoc-gen-connect-go. DO NOT EDIT.
//
// Source: parca/debuginfo/v1alpha1/debuginfo.proto
package debuginfov1alpha1connect
import (
context "context"
errors "errors"
connect_go "github.com/bufbuild/connect-go"
v1alpha1 "github.com/parca-dev/parca/gen/proto/go/parca/debuginfo/v1alpha1"
http "net/http"
strings "strings"
)
// This is a compile-time assertion to ensure that this generated file and the connect package are
// compatible. If you get a compiler error that this constant is not defined, this code was
// generated with a version of connect newer than the one compiled into your binary. You can fix the
// problem by either regenerating this code with an older version of connect or updating the connect
// version compiled into your binary.
const _ = connect_go.IsAtLeastVersion0_1_0
const (
// DebugInfoServiceName is the fully-qualified name of the DebugInfoService service.
DebugInfoServiceName = "parca.debuginfo.v1alpha1.DebugInfoService"
)
// DebugInfoServiceClient is a client for the parca.debuginfo.v1alpha1.DebugInfoService service.
type DebugInfoServiceClient interface {
// Exists returns true if the given build_id has debug info uploaded for it.
Exists(context.Context, *connect_go.Request[v1alpha1.ExistsRequest]) (*connect_go.Response[v1alpha1.ExistsResponse], error)
// Upload ingests debug info for a given build_id
Upload(context.Context) *connect_go.ClientStreamForClient[v1alpha1.UploadRequest, v1alpha1.UploadResponse]
// Download returns the debug info for a given build_id.
Download(context.Context, *connect_go.Request[v1alpha1.DownloadRequest]) (*connect_go.ServerStreamForClient[v1alpha1.DownloadResponse], error)
}
// NewDebugInfoServiceClient constructs a client for the parca.debuginfo.v1alpha1.DebugInfoService
// service. By default, it uses the Connect protocol with the binary Protobuf Codec, asks for
// gzipped responses, and sends uncompressed requests. To use the gRPC or gRPC-Web protocols, supply
// the connect.WithGRPC() or connect.WithGRPCWeb() options.
//
// The URL supplied here should be the base URL for the Connect or gRPC server (for example,
// http://api.acme.com or https://acme.com/grpc).
func NewDebugInfoServiceClient(httpClient connect_go.HTTPClient, baseURL string, opts ...connect_go.ClientOption) DebugInfoServiceClient {
baseURL = strings.TrimRight(baseURL, "/")
return &debugInfoServiceClient{
exists: connect_go.NewClient[v1alpha1.ExistsRequest, v1alpha1.ExistsResponse](
httpClient,
baseURL+"/parca.debuginfo.v1alpha1.DebugInfoService/Exists",
opts...,
),
upload: connect_go.NewClient[v1alpha1.UploadRequest, v1alpha1.UploadResponse](
httpClient,
baseURL+"/parca.debuginfo.v1alpha1.DebugInfoService/Upload",
opts...,
),
download: connect_go.NewClient[v1alpha1.DownloadRequest, v1alpha1.DownloadResponse](
httpClient,
baseURL+"/parca.debuginfo.v1alpha1.DebugInfoService/Download",
opts...,
),
}
}
// debugInfoServiceClient implements DebugInfoServiceClient.
type debugInfoServiceClient struct {
exists *connect_go.Client[v1alpha1.ExistsRequest, v1alpha1.ExistsResponse]
upload *connect_go.Client[v1alpha1.UploadRequest, v1alpha1.UploadResponse]
download *connect_go.Client[v1alpha1.DownloadRequest, v1alpha1.DownloadResponse]
}
// Exists calls parca.debuginfo.v1alpha1.DebugInfoService.Exists.
func (c *debugInfoServiceClient) Exists(ctx context.Context, req *connect_go.Request[v1alpha1.ExistsRequest]) (*connect_go.Response[v1alpha1.ExistsResponse], error) {
return c.exists.CallUnary(ctx, req)
}
// Upload calls parca.debuginfo.v1alpha1.DebugInfoService.Upload.
func (c *debugInfoServiceClient) Upload(ctx context.Context) *connect_go.ClientStreamForClient[v1alpha1.UploadRequest, v1alpha1.UploadResponse] {
return c.upload.CallClientStream(ctx)
}
// Download calls parca.debuginfo.v1alpha1.DebugInfoService.Download.
func (c *debugInfoServiceClient) Download(ctx context.Context, req *connect_go.Request[v1alpha1.DownloadRequest]) (*connect_go.ServerStreamForClient[v1alpha1.DownloadResponse], error) {
return c.download.CallServerStream(ctx, req)
}
// DebugInfoServiceHandler is an implementation of the parca.debuginfo.v1alpha1.DebugInfoService
// service.
type DebugInfoServiceHandler interface {
// Exists returns true if the given build_id has debug info uploaded for it.
Exists(context.Context, *connect_go.Request[v1alpha1.ExistsRequest]) (*connect_go.Response[v1alpha1.ExistsResponse], error)
// Upload ingests debug info for a given build_id
Upload(context.Context, *connect_go.ClientStream[v1alpha1.UploadRequest]) (*connect_go.Response[v1alpha1.UploadResponse], error)
// Download returns the debug info for a given build_id.
Download(context.Context, *connect_go.Request[v1alpha1.DownloadRequest], *connect_go.ServerStream[v1alpha1.DownloadResponse]) error
}
// NewDebugInfoServiceHandler builds an HTTP handler from the service implementation. It returns the
// path on which to mount the handler and the handler itself.
//
// By default, handlers support the Connect, gRPC, and gRPC-Web protocols with the binary Protobuf
// and JSON codecs. They also support gzip compression.
func NewDebugInfoServiceHandler(svc DebugInfoServiceHandler, opts ...connect_go.HandlerOption) (string, http.Handler) {
mux := http.NewServeMux()
mux.Handle("/parca.debuginfo.v1alpha1.DebugInfoService/Exists", connect_go.NewUnaryHandler(
"/parca.debuginfo.v1alpha1.DebugInfoService/Exists",
svc.Exists,
opts...,
))
mux.Handle("/parca.debuginfo.v1alpha1.DebugInfoService/Upload", connect_go.NewClientStreamHandler(
"/parca.debuginfo.v1alpha1.DebugInfoService/Upload",
svc.Upload,
opts...,
))
mux.Handle("/parca.debuginfo.v1alpha1.DebugInfoService/Download", connect_go.NewServerStreamHandler(
"/parca.debuginfo.v1alpha1.DebugInfoService/Download",
svc.Download,
opts...,
))
return "/parca.debuginfo.v1alpha1.DebugInfoService/", mux
}
// UnimplementedDebugInfoServiceHandler returns CodeUnimplemented from all methods.
type UnimplementedDebugInfoServiceHandler struct{}
func (UnimplementedDebugInfoServiceHandler) Exists(context.Context, *connect_go.Request[v1alpha1.ExistsRequest]) (*connect_go.Response[v1alpha1.ExistsResponse], error) {
return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("parca.debuginfo.v1alpha1.DebugInfoService.Exists is not implemented"))
}
func (UnimplementedDebugInfoServiceHandler) Upload(context.Context, *connect_go.ClientStream[v1alpha1.UploadRequest]) (*connect_go.Response[v1alpha1.UploadResponse], error) {
return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("parca.debuginfo.v1alpha1.DebugInfoService.Upload is not implemented"))
}
func (UnimplementedDebugInfoServiceHandler) Download(context.Context, *connect_go.Request[v1alpha1.DownloadRequest], *connect_go.ServerStream[v1alpha1.DownloadResponse]) error {
return connect_go.NewError(connect_go.CodeUnimplemented, errors.New("parca.debuginfo.v1alpha1.DebugInfoService.Download is not implemented"))
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,327 @@
// Code generated by protoc-gen-connect-go. DO NOT EDIT.
//
// Source: parca/metastore/v1alpha1/metastore.proto
package metastorev1alpha1connect
import (
context "context"
errors "errors"
connect_go "github.com/bufbuild/connect-go"
v1alpha1 "github.com/parca-dev/parca/gen/proto/go/parca/metastore/v1alpha1"
http "net/http"
strings "strings"
)
// This is a compile-time assertion to ensure that this generated file and the connect package are
// compatible. If you get a compiler error that this constant is not defined, this code was
// generated with a version of connect newer than the one compiled into your binary. You can fix the
// problem by either regenerating this code with an older version of connect or updating the connect
// version compiled into your binary.
const _ = connect_go.IsAtLeastVersion0_1_0
const (
// MetastoreServiceName is the fully-qualified name of the MetastoreService service.
MetastoreServiceName = "parca.metastore.v1alpha1.MetastoreService"
)
// MetastoreServiceClient is a client for the parca.metastore.v1alpha1.MetastoreService service.
type MetastoreServiceClient interface {
// GetOrCreateMappings checks if the mappings in the request are already
// known and returns the known mapping (including its ID) if so. If a mapping
// does not already exist, it is written to the backing metastore.
GetOrCreateMappings(context.Context, *connect_go.Request[v1alpha1.GetOrCreateMappingsRequest]) (*connect_go.Response[v1alpha1.GetOrCreateMappingsResponse], error)
// GetOrCreateFunctions checks if the functions in the request are already
// known and returns the known function (including its ID) if so. If a
// function does not already exist, it is written to the backing metastore.
GetOrCreateFunctions(context.Context, *connect_go.Request[v1alpha1.GetOrCreateFunctionsRequest]) (*connect_go.Response[v1alpha1.GetOrCreateFunctionsResponse], error)
// GetOrCreateLocations checks if the locations in the request are already
// known and returns the known location (including its ID) if so. If a
// location does not already exist, it is written to the backing metastore.
GetOrCreateLocations(context.Context, *connect_go.Request[v1alpha1.GetOrCreateLocationsRequest]) (*connect_go.Response[v1alpha1.GetOrCreateLocationsResponse], error)
// GetOrCreateStacktraces checks if the stacktraces in the request are
// already known and returns the known stacktrace (including its ID) if so.
// If a stacktrace does not already exist, it is written to the backing
// metastore.
GetOrCreateStacktraces(context.Context, *connect_go.Request[v1alpha1.GetOrCreateStacktracesRequest]) (*connect_go.Response[v1alpha1.GetOrCreateStacktracesResponse], error)
// UnsymbolizedLocations returns locations that can be symbolized but haven't
// been asynchronously symbolized yet.
UnsymbolizedLocations(context.Context, *connect_go.Request[v1alpha1.UnsymbolizedLocationsRequest]) (*connect_go.Response[v1alpha1.UnsymbolizedLocationsResponse], error)
// CreateLocationLines creates the location lines contained in the provided
// locations.
CreateLocationLines(context.Context, *connect_go.Request[v1alpha1.CreateLocationLinesRequest]) (*connect_go.Response[v1alpha1.CreateLocationLinesResponse], error)
// Locations retrieves locations.
Locations(context.Context, *connect_go.Request[v1alpha1.LocationsRequest]) (*connect_go.Response[v1alpha1.LocationsResponse], error)
// Functions retrieves functions.
Functions(context.Context, *connect_go.Request[v1alpha1.FunctionsRequest]) (*connect_go.Response[v1alpha1.FunctionsResponse], error)
// Mappings retrieves mappings.
Mappings(context.Context, *connect_go.Request[v1alpha1.MappingsRequest]) (*connect_go.Response[v1alpha1.MappingsResponse], error)
// Stacktraces retrieves mappings.
Stacktraces(context.Context, *connect_go.Request[v1alpha1.StacktracesRequest]) (*connect_go.Response[v1alpha1.StacktracesResponse], error)
}
// NewMetastoreServiceClient constructs a client for the parca.metastore.v1alpha1.MetastoreService
// service. By default, it uses the Connect protocol with the binary Protobuf Codec, asks for
// gzipped responses, and sends uncompressed requests. To use the gRPC or gRPC-Web protocols, supply
// the connect.WithGRPC() or connect.WithGRPCWeb() options.
//
// The URL supplied here should be the base URL for the Connect or gRPC server (for example,
// http://api.acme.com or https://acme.com/grpc).
func NewMetastoreServiceClient(httpClient connect_go.HTTPClient, baseURL string, opts ...connect_go.ClientOption) MetastoreServiceClient {
baseURL = strings.TrimRight(baseURL, "/")
return &metastoreServiceClient{
getOrCreateMappings: connect_go.NewClient[v1alpha1.GetOrCreateMappingsRequest, v1alpha1.GetOrCreateMappingsResponse](
httpClient,
baseURL+"/parca.metastore.v1alpha1.MetastoreService/GetOrCreateMappings",
opts...,
),
getOrCreateFunctions: connect_go.NewClient[v1alpha1.GetOrCreateFunctionsRequest, v1alpha1.GetOrCreateFunctionsResponse](
httpClient,
baseURL+"/parca.metastore.v1alpha1.MetastoreService/GetOrCreateFunctions",
opts...,
),
getOrCreateLocations: connect_go.NewClient[v1alpha1.GetOrCreateLocationsRequest, v1alpha1.GetOrCreateLocationsResponse](
httpClient,
baseURL+"/parca.metastore.v1alpha1.MetastoreService/GetOrCreateLocations",
opts...,
),
getOrCreateStacktraces: connect_go.NewClient[v1alpha1.GetOrCreateStacktracesRequest, v1alpha1.GetOrCreateStacktracesResponse](
httpClient,
baseURL+"/parca.metastore.v1alpha1.MetastoreService/GetOrCreateStacktraces",
opts...,
),
unsymbolizedLocations: connect_go.NewClient[v1alpha1.UnsymbolizedLocationsRequest, v1alpha1.UnsymbolizedLocationsResponse](
httpClient,
baseURL+"/parca.metastore.v1alpha1.MetastoreService/UnsymbolizedLocations",
opts...,
),
createLocationLines: connect_go.NewClient[v1alpha1.CreateLocationLinesRequest, v1alpha1.CreateLocationLinesResponse](
httpClient,
baseURL+"/parca.metastore.v1alpha1.MetastoreService/CreateLocationLines",
opts...,
),
locations: connect_go.NewClient[v1alpha1.LocationsRequest, v1alpha1.LocationsResponse](
httpClient,
baseURL+"/parca.metastore.v1alpha1.MetastoreService/Locations",
opts...,
),
functions: connect_go.NewClient[v1alpha1.FunctionsRequest, v1alpha1.FunctionsResponse](
httpClient,
baseURL+"/parca.metastore.v1alpha1.MetastoreService/Functions",
opts...,
),
mappings: connect_go.NewClient[v1alpha1.MappingsRequest, v1alpha1.MappingsResponse](
httpClient,
baseURL+"/parca.metastore.v1alpha1.MetastoreService/Mappings",
opts...,
),
stacktraces: connect_go.NewClient[v1alpha1.StacktracesRequest, v1alpha1.StacktracesResponse](
httpClient,
baseURL+"/parca.metastore.v1alpha1.MetastoreService/Stacktraces",
opts...,
),
}
}
// metastoreServiceClient implements MetastoreServiceClient.
type metastoreServiceClient struct {
getOrCreateMappings *connect_go.Client[v1alpha1.GetOrCreateMappingsRequest, v1alpha1.GetOrCreateMappingsResponse]
getOrCreateFunctions *connect_go.Client[v1alpha1.GetOrCreateFunctionsRequest, v1alpha1.GetOrCreateFunctionsResponse]
getOrCreateLocations *connect_go.Client[v1alpha1.GetOrCreateLocationsRequest, v1alpha1.GetOrCreateLocationsResponse]
getOrCreateStacktraces *connect_go.Client[v1alpha1.GetOrCreateStacktracesRequest, v1alpha1.GetOrCreateStacktracesResponse]
unsymbolizedLocations *connect_go.Client[v1alpha1.UnsymbolizedLocationsRequest, v1alpha1.UnsymbolizedLocationsResponse]
createLocationLines *connect_go.Client[v1alpha1.CreateLocationLinesRequest, v1alpha1.CreateLocationLinesResponse]
locations *connect_go.Client[v1alpha1.LocationsRequest, v1alpha1.LocationsResponse]
functions *connect_go.Client[v1alpha1.FunctionsRequest, v1alpha1.FunctionsResponse]
mappings *connect_go.Client[v1alpha1.MappingsRequest, v1alpha1.MappingsResponse]
stacktraces *connect_go.Client[v1alpha1.StacktracesRequest, v1alpha1.StacktracesResponse]
}
// GetOrCreateMappings calls parca.metastore.v1alpha1.MetastoreService.GetOrCreateMappings.
func (c *metastoreServiceClient) GetOrCreateMappings(ctx context.Context, req *connect_go.Request[v1alpha1.GetOrCreateMappingsRequest]) (*connect_go.Response[v1alpha1.GetOrCreateMappingsResponse], error) {
return c.getOrCreateMappings.CallUnary(ctx, req)
}
// GetOrCreateFunctions calls parca.metastore.v1alpha1.MetastoreService.GetOrCreateFunctions.
func (c *metastoreServiceClient) GetOrCreateFunctions(ctx context.Context, req *connect_go.Request[v1alpha1.GetOrCreateFunctionsRequest]) (*connect_go.Response[v1alpha1.GetOrCreateFunctionsResponse], error) {
return c.getOrCreateFunctions.CallUnary(ctx, req)
}
// GetOrCreateLocations calls parca.metastore.v1alpha1.MetastoreService.GetOrCreateLocations.
func (c *metastoreServiceClient) GetOrCreateLocations(ctx context.Context, req *connect_go.Request[v1alpha1.GetOrCreateLocationsRequest]) (*connect_go.Response[v1alpha1.GetOrCreateLocationsResponse], error) {
return c.getOrCreateLocations.CallUnary(ctx, req)
}
// GetOrCreateStacktraces calls parca.metastore.v1alpha1.MetastoreService.GetOrCreateStacktraces.
func (c *metastoreServiceClient) GetOrCreateStacktraces(ctx context.Context, req *connect_go.Request[v1alpha1.GetOrCreateStacktracesRequest]) (*connect_go.Response[v1alpha1.GetOrCreateStacktracesResponse], error) {
return c.getOrCreateStacktraces.CallUnary(ctx, req)
}
// UnsymbolizedLocations calls parca.metastore.v1alpha1.MetastoreService.UnsymbolizedLocations.
func (c *metastoreServiceClient) UnsymbolizedLocations(ctx context.Context, req *connect_go.Request[v1alpha1.UnsymbolizedLocationsRequest]) (*connect_go.Response[v1alpha1.UnsymbolizedLocationsResponse], error) {
return c.unsymbolizedLocations.CallUnary(ctx, req)
}
// CreateLocationLines calls parca.metastore.v1alpha1.MetastoreService.CreateLocationLines.
func (c *metastoreServiceClient) CreateLocationLines(ctx context.Context, req *connect_go.Request[v1alpha1.CreateLocationLinesRequest]) (*connect_go.Response[v1alpha1.CreateLocationLinesResponse], error) {
return c.createLocationLines.CallUnary(ctx, req)
}
// Locations calls parca.metastore.v1alpha1.MetastoreService.Locations.
func (c *metastoreServiceClient) Locations(ctx context.Context, req *connect_go.Request[v1alpha1.LocationsRequest]) (*connect_go.Response[v1alpha1.LocationsResponse], error) {
return c.locations.CallUnary(ctx, req)
}
// Functions calls parca.metastore.v1alpha1.MetastoreService.Functions.
func (c *metastoreServiceClient) Functions(ctx context.Context, req *connect_go.Request[v1alpha1.FunctionsRequest]) (*connect_go.Response[v1alpha1.FunctionsResponse], error) {
return c.functions.CallUnary(ctx, req)
}
// Mappings calls parca.metastore.v1alpha1.MetastoreService.Mappings.
func (c *metastoreServiceClient) Mappings(ctx context.Context, req *connect_go.Request[v1alpha1.MappingsRequest]) (*connect_go.Response[v1alpha1.MappingsResponse], error) {
return c.mappings.CallUnary(ctx, req)
}
// Stacktraces calls parca.metastore.v1alpha1.MetastoreService.Stacktraces.
func (c *metastoreServiceClient) Stacktraces(ctx context.Context, req *connect_go.Request[v1alpha1.StacktracesRequest]) (*connect_go.Response[v1alpha1.StacktracesResponse], error) {
return c.stacktraces.CallUnary(ctx, req)
}
// MetastoreServiceHandler is an implementation of the parca.metastore.v1alpha1.MetastoreService
// service.
type MetastoreServiceHandler interface {
// GetOrCreateMappings checks if the mappings in the request are already
// known and returns the known mapping (including its ID) if so. If a mapping
// does not already exist, it is written to the backing metastore.
GetOrCreateMappings(context.Context, *connect_go.Request[v1alpha1.GetOrCreateMappingsRequest]) (*connect_go.Response[v1alpha1.GetOrCreateMappingsResponse], error)
// GetOrCreateFunctions checks if the functions in the request are already
// known and returns the known function (including its ID) if so. If a
// function does not already exist, it is written to the backing metastore.
GetOrCreateFunctions(context.Context, *connect_go.Request[v1alpha1.GetOrCreateFunctionsRequest]) (*connect_go.Response[v1alpha1.GetOrCreateFunctionsResponse], error)
// GetOrCreateLocations checks if the locations in the request are already
// known and returns the known location (including its ID) if so. If a
// location does not already exist, it is written to the backing metastore.
GetOrCreateLocations(context.Context, *connect_go.Request[v1alpha1.GetOrCreateLocationsRequest]) (*connect_go.Response[v1alpha1.GetOrCreateLocationsResponse], error)
// GetOrCreateStacktraces checks if the stacktraces in the request are
// already known and returns the known stacktrace (including its ID) if so.
// If a stacktrace does not already exist, it is written to the backing
// metastore.
GetOrCreateStacktraces(context.Context, *connect_go.Request[v1alpha1.GetOrCreateStacktracesRequest]) (*connect_go.Response[v1alpha1.GetOrCreateStacktracesResponse], error)
// UnsymbolizedLocations returns locations that can be symbolized but haven't
// been asynchronously symbolized yet.
UnsymbolizedLocations(context.Context, *connect_go.Request[v1alpha1.UnsymbolizedLocationsRequest]) (*connect_go.Response[v1alpha1.UnsymbolizedLocationsResponse], error)
// CreateLocationLines creates the location lines contained in the provided
// locations.
CreateLocationLines(context.Context, *connect_go.Request[v1alpha1.CreateLocationLinesRequest]) (*connect_go.Response[v1alpha1.CreateLocationLinesResponse], error)
// Locations retrieves locations.
Locations(context.Context, *connect_go.Request[v1alpha1.LocationsRequest]) (*connect_go.Response[v1alpha1.LocationsResponse], error)
// Functions retrieves functions.
Functions(context.Context, *connect_go.Request[v1alpha1.FunctionsRequest]) (*connect_go.Response[v1alpha1.FunctionsResponse], error)
// Mappings retrieves mappings.
Mappings(context.Context, *connect_go.Request[v1alpha1.MappingsRequest]) (*connect_go.Response[v1alpha1.MappingsResponse], error)
// Stacktraces retrieves mappings.
Stacktraces(context.Context, *connect_go.Request[v1alpha1.StacktracesRequest]) (*connect_go.Response[v1alpha1.StacktracesResponse], error)
}
// NewMetastoreServiceHandler builds an HTTP handler from the service implementation. It returns the
// path on which to mount the handler and the handler itself.
//
// By default, handlers support the Connect, gRPC, and gRPC-Web protocols with the binary Protobuf
// and JSON codecs. They also support gzip compression.
func NewMetastoreServiceHandler(svc MetastoreServiceHandler, opts ...connect_go.HandlerOption) (string, http.Handler) {
mux := http.NewServeMux()
mux.Handle("/parca.metastore.v1alpha1.MetastoreService/GetOrCreateMappings", connect_go.NewUnaryHandler(
"/parca.metastore.v1alpha1.MetastoreService/GetOrCreateMappings",
svc.GetOrCreateMappings,
opts...,
))
mux.Handle("/parca.metastore.v1alpha1.MetastoreService/GetOrCreateFunctions", connect_go.NewUnaryHandler(
"/parca.metastore.v1alpha1.MetastoreService/GetOrCreateFunctions",
svc.GetOrCreateFunctions,
opts...,
))
mux.Handle("/parca.metastore.v1alpha1.MetastoreService/GetOrCreateLocations", connect_go.NewUnaryHandler(
"/parca.metastore.v1alpha1.MetastoreService/GetOrCreateLocations",
svc.GetOrCreateLocations,
opts...,
))
mux.Handle("/parca.metastore.v1alpha1.MetastoreService/GetOrCreateStacktraces", connect_go.NewUnaryHandler(
"/parca.metastore.v1alpha1.MetastoreService/GetOrCreateStacktraces",
svc.GetOrCreateStacktraces,
opts...,
))
mux.Handle("/parca.metastore.v1alpha1.MetastoreService/UnsymbolizedLocations", connect_go.NewUnaryHandler(
"/parca.metastore.v1alpha1.MetastoreService/UnsymbolizedLocations",
svc.UnsymbolizedLocations,
opts...,
))
mux.Handle("/parca.metastore.v1alpha1.MetastoreService/CreateLocationLines", connect_go.NewUnaryHandler(
"/parca.metastore.v1alpha1.MetastoreService/CreateLocationLines",
svc.CreateLocationLines,
opts...,
))
mux.Handle("/parca.metastore.v1alpha1.MetastoreService/Locations", connect_go.NewUnaryHandler(
"/parca.metastore.v1alpha1.MetastoreService/Locations",
svc.Locations,
opts...,
))
mux.Handle("/parca.metastore.v1alpha1.MetastoreService/Functions", connect_go.NewUnaryHandler(
"/parca.metastore.v1alpha1.MetastoreService/Functions",
svc.Functions,
opts...,
))
mux.Handle("/parca.metastore.v1alpha1.MetastoreService/Mappings", connect_go.NewUnaryHandler(
"/parca.metastore.v1alpha1.MetastoreService/Mappings",
svc.Mappings,
opts...,
))
mux.Handle("/parca.metastore.v1alpha1.MetastoreService/Stacktraces", connect_go.NewUnaryHandler(
"/parca.metastore.v1alpha1.MetastoreService/Stacktraces",
svc.Stacktraces,
opts...,
))
return "/parca.metastore.v1alpha1.MetastoreService/", mux
}
// UnimplementedMetastoreServiceHandler returns CodeUnimplemented from all methods.
type UnimplementedMetastoreServiceHandler struct{}
func (UnimplementedMetastoreServiceHandler) GetOrCreateMappings(context.Context, *connect_go.Request[v1alpha1.GetOrCreateMappingsRequest]) (*connect_go.Response[v1alpha1.GetOrCreateMappingsResponse], error) {
return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("parca.metastore.v1alpha1.MetastoreService.GetOrCreateMappings is not implemented"))
}
func (UnimplementedMetastoreServiceHandler) GetOrCreateFunctions(context.Context, *connect_go.Request[v1alpha1.GetOrCreateFunctionsRequest]) (*connect_go.Response[v1alpha1.GetOrCreateFunctionsResponse], error) {
return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("parca.metastore.v1alpha1.MetastoreService.GetOrCreateFunctions is not implemented"))
}
func (UnimplementedMetastoreServiceHandler) GetOrCreateLocations(context.Context, *connect_go.Request[v1alpha1.GetOrCreateLocationsRequest]) (*connect_go.Response[v1alpha1.GetOrCreateLocationsResponse], error) {
return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("parca.metastore.v1alpha1.MetastoreService.GetOrCreateLocations is not implemented"))
}
func (UnimplementedMetastoreServiceHandler) GetOrCreateStacktraces(context.Context, *connect_go.Request[v1alpha1.GetOrCreateStacktracesRequest]) (*connect_go.Response[v1alpha1.GetOrCreateStacktracesResponse], error) {
return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("parca.metastore.v1alpha1.MetastoreService.GetOrCreateStacktraces is not implemented"))
}
func (UnimplementedMetastoreServiceHandler) UnsymbolizedLocations(context.Context, *connect_go.Request[v1alpha1.UnsymbolizedLocationsRequest]) (*connect_go.Response[v1alpha1.UnsymbolizedLocationsResponse], error) {
return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("parca.metastore.v1alpha1.MetastoreService.UnsymbolizedLocations is not implemented"))
}
func (UnimplementedMetastoreServiceHandler) CreateLocationLines(context.Context, *connect_go.Request[v1alpha1.CreateLocationLinesRequest]) (*connect_go.Response[v1alpha1.CreateLocationLinesResponse], error) {
return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("parca.metastore.v1alpha1.MetastoreService.CreateLocationLines is not implemented"))
}
func (UnimplementedMetastoreServiceHandler) Locations(context.Context, *connect_go.Request[v1alpha1.LocationsRequest]) (*connect_go.Response[v1alpha1.LocationsResponse], error) {
return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("parca.metastore.v1alpha1.MetastoreService.Locations is not implemented"))
}
func (UnimplementedMetastoreServiceHandler) Functions(context.Context, *connect_go.Request[v1alpha1.FunctionsRequest]) (*connect_go.Response[v1alpha1.FunctionsResponse], error) {
return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("parca.metastore.v1alpha1.MetastoreService.Functions is not implemented"))
}
func (UnimplementedMetastoreServiceHandler) Mappings(context.Context, *connect_go.Request[v1alpha1.MappingsRequest]) (*connect_go.Response[v1alpha1.MappingsResponse], error) {
return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("parca.metastore.v1alpha1.MetastoreService.Mappings is not implemented"))
}
func (UnimplementedMetastoreServiceHandler) Stacktraces(context.Context, *connect_go.Request[v1alpha1.StacktracesRequest]) (*connect_go.Response[v1alpha1.StacktracesResponse], error) {
return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("parca.metastore.v1alpha1.MetastoreService.Stacktraces is not implemented"))
}
@@ -0,0 +1,550 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.28.1
// protoc (unknown)
// source: parca/profilestore/v1alpha1/profilestore.proto
package profilestorev1alpha1
import (
_ "google.golang.org/genproto/googleapis/api/annotations"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
// WriteRawRequest writes a pprof profile for a given tenant
type WriteRawRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// tenant is the given tenant to store the pprof profile under
//
// Deprecated: Do not use.
Tenant string `protobuf:"bytes,1,opt,name=tenant,proto3" json:"tenant,omitempty"`
// series is a set raw pprof profiles and accompanying labels
Series []*RawProfileSeries `protobuf:"bytes,2,rep,name=series,proto3" json:"series,omitempty"`
// normalized is a flag indicating if the addresses in the profile is normalized for position independent code
Normalized bool `protobuf:"varint,3,opt,name=normalized,proto3" json:"normalized,omitempty"`
}
func (x *WriteRawRequest) Reset() {
*x = WriteRawRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_parca_profilestore_v1alpha1_profilestore_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *WriteRawRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*WriteRawRequest) ProtoMessage() {}
func (x *WriteRawRequest) ProtoReflect() protoreflect.Message {
mi := &file_parca_profilestore_v1alpha1_profilestore_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use WriteRawRequest.ProtoReflect.Descriptor instead.
func (*WriteRawRequest) Descriptor() ([]byte, []int) {
return file_parca_profilestore_v1alpha1_profilestore_proto_rawDescGZIP(), []int{0}
}
// Deprecated: Do not use.
func (x *WriteRawRequest) GetTenant() string {
if x != nil {
return x.Tenant
}
return ""
}
func (x *WriteRawRequest) GetSeries() []*RawProfileSeries {
if x != nil {
return x.Series
}
return nil
}
func (x *WriteRawRequest) GetNormalized() bool {
if x != nil {
return x.Normalized
}
return false
}
// WriteRawResponse is the empty response
type WriteRawResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
}
func (x *WriteRawResponse) Reset() {
*x = WriteRawResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_parca_profilestore_v1alpha1_profilestore_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *WriteRawResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*WriteRawResponse) ProtoMessage() {}
func (x *WriteRawResponse) ProtoReflect() protoreflect.Message {
mi := &file_parca_profilestore_v1alpha1_profilestore_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use WriteRawResponse.ProtoReflect.Descriptor instead.
func (*WriteRawResponse) Descriptor() ([]byte, []int) {
return file_parca_profilestore_v1alpha1_profilestore_proto_rawDescGZIP(), []int{1}
}
// RawProfileSeries represents the pprof profile and its associated labels
type RawProfileSeries struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// LabelSet is the key value pairs to identify the corresponding profile
Labels *LabelSet `protobuf:"bytes,1,opt,name=labels,proto3" json:"labels,omitempty"`
// samples are the set of profile bytes
Samples []*RawSample `protobuf:"bytes,2,rep,name=samples,proto3" json:"samples,omitempty"`
}
func (x *RawProfileSeries) Reset() {
*x = RawProfileSeries{}
if protoimpl.UnsafeEnabled {
mi := &file_parca_profilestore_v1alpha1_profilestore_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *RawProfileSeries) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*RawProfileSeries) ProtoMessage() {}
func (x *RawProfileSeries) ProtoReflect() protoreflect.Message {
mi := &file_parca_profilestore_v1alpha1_profilestore_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use RawProfileSeries.ProtoReflect.Descriptor instead.
func (*RawProfileSeries) Descriptor() ([]byte, []int) {
return file_parca_profilestore_v1alpha1_profilestore_proto_rawDescGZIP(), []int{2}
}
func (x *RawProfileSeries) GetLabels() *LabelSet {
if x != nil {
return x.Labels
}
return nil
}
func (x *RawProfileSeries) GetSamples() []*RawSample {
if x != nil {
return x.Samples
}
return nil
}
// Label is a key value pair of identifiers
type Label struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// name is the label name
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
// value is the value for the label name
Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"`
}
func (x *Label) Reset() {
*x = Label{}
if protoimpl.UnsafeEnabled {
mi := &file_parca_profilestore_v1alpha1_profilestore_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Label) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Label) ProtoMessage() {}
func (x *Label) ProtoReflect() protoreflect.Message {
mi := &file_parca_profilestore_v1alpha1_profilestore_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Label.ProtoReflect.Descriptor instead.
func (*Label) Descriptor() ([]byte, []int) {
return file_parca_profilestore_v1alpha1_profilestore_proto_rawDescGZIP(), []int{3}
}
func (x *Label) GetName() string {
if x != nil {
return x.Name
}
return ""
}
func (x *Label) GetValue() string {
if x != nil {
return x.Value
}
return ""
}
// LabelSet is a group of labels
type LabelSet struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// labels are the grouping of labels
Labels []*Label `protobuf:"bytes,1,rep,name=labels,proto3" json:"labels,omitempty"`
}
func (x *LabelSet) Reset() {
*x = LabelSet{}
if protoimpl.UnsafeEnabled {
mi := &file_parca_profilestore_v1alpha1_profilestore_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *LabelSet) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*LabelSet) ProtoMessage() {}
func (x *LabelSet) ProtoReflect() protoreflect.Message {
mi := &file_parca_profilestore_v1alpha1_profilestore_proto_msgTypes[4]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use LabelSet.ProtoReflect.Descriptor instead.
func (*LabelSet) Descriptor() ([]byte, []int) {
return file_parca_profilestore_v1alpha1_profilestore_proto_rawDescGZIP(), []int{4}
}
func (x *LabelSet) GetLabels() []*Label {
if x != nil {
return x.Labels
}
return nil
}
// RawSample is the set of bytes that correspond to a pprof profile
type RawSample struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// raw_profile is the set of bytes of the pprof profile
RawProfile []byte `protobuf:"bytes,1,opt,name=raw_profile,json=rawProfile,proto3" json:"raw_profile,omitempty"`
}
func (x *RawSample) Reset() {
*x = RawSample{}
if protoimpl.UnsafeEnabled {
mi := &file_parca_profilestore_v1alpha1_profilestore_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *RawSample) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*RawSample) ProtoMessage() {}
func (x *RawSample) ProtoReflect() protoreflect.Message {
mi := &file_parca_profilestore_v1alpha1_profilestore_proto_msgTypes[5]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use RawSample.ProtoReflect.Descriptor instead.
func (*RawSample) Descriptor() ([]byte, []int) {
return file_parca_profilestore_v1alpha1_profilestore_proto_rawDescGZIP(), []int{5}
}
func (x *RawSample) GetRawProfile() []byte {
if x != nil {
return x.RawProfile
}
return nil
}
var File_parca_profilestore_v1alpha1_profilestore_proto protoreflect.FileDescriptor
var file_parca_profilestore_v1alpha1_profilestore_proto_rawDesc = []byte{
0x0a, 0x2e, 0x70, 0x61, 0x72, 0x63, 0x61, 0x2f, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73,
0x74, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x70, 0x72,
0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x12, 0x1b, 0x70, 0x61, 0x72, 0x63, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73,
0x74, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x1a, 0x1c, 0x67,
0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61,
0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x94, 0x01, 0x0a, 0x0f,
0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x61, 0x77, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12,
0x1a, 0x0a, 0x06, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42,
0x02, 0x18, 0x01, 0x52, 0x06, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x12, 0x45, 0x0a, 0x06, 0x73,
0x65, 0x72, 0x69, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x70, 0x61,
0x72, 0x63, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65,
0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x52, 0x61, 0x77, 0x50, 0x72, 0x6f,
0x66, 0x69, 0x6c, 0x65, 0x53, 0x65, 0x72, 0x69, 0x65, 0x73, 0x52, 0x06, 0x73, 0x65, 0x72, 0x69,
0x65, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64,
0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a,
0x65, 0x64, 0x22, 0x12, 0x0a, 0x10, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x61, 0x77, 0x52, 0x65,
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x93, 0x01, 0x0a, 0x10, 0x52, 0x61, 0x77, 0x50, 0x72,
0x6f, 0x66, 0x69, 0x6c, 0x65, 0x53, 0x65, 0x72, 0x69, 0x65, 0x73, 0x12, 0x3d, 0x0a, 0x06, 0x6c,
0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x70, 0x61,
0x72, 0x63, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65,
0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x53,
0x65, 0x74, 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x12, 0x40, 0x0a, 0x07, 0x73, 0x61,
0x6d, 0x70, 0x6c, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x70, 0x61,
0x72, 0x63, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65,
0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x52, 0x61, 0x77, 0x53, 0x61, 0x6d,
0x70, 0x6c, 0x65, 0x52, 0x07, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x22, 0x31, 0x0a, 0x05,
0x4c, 0x61, 0x62, 0x65, 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20,
0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c,
0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22,
0x46, 0x0a, 0x08, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x53, 0x65, 0x74, 0x12, 0x3a, 0x0a, 0x06, 0x6c,
0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x70, 0x61,
0x72, 0x63, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65,
0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x52,
0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x22, 0x2c, 0x0a, 0x09, 0x52, 0x61, 0x77, 0x53, 0x61,
0x6d, 0x70, 0x6c, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x61, 0x77, 0x5f, 0x70, 0x72, 0x6f, 0x66,
0x69, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x72, 0x61, 0x77, 0x50, 0x72,
0x6f, 0x66, 0x69, 0x6c, 0x65, 0x32, 0x9e, 0x01, 0x0a, 0x13, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c,
0x65, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x86, 0x01,
0x0a, 0x08, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x61, 0x77, 0x12, 0x2c, 0x2e, 0x70, 0x61, 0x72,
0x63, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e,
0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x61,
0x77, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x70, 0x61, 0x72, 0x63, 0x61,
0x2e, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31,
0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x61, 0x77, 0x52,
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x3a,
0x01, 0x2a, 0x22, 0x12, 0x2f, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2f, 0x77, 0x72,
0x69, 0x74, 0x65, 0x72, 0x61, 0x77, 0x42, 0x9c, 0x02, 0x0a, 0x1f, 0x63, 0x6f, 0x6d, 0x2e, 0x70,
0x61, 0x72, 0x63, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x74, 0x6f, 0x72,
0x65, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x42, 0x11, 0x50, 0x72, 0x6f, 0x66,
0x69, 0x6c, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a,
0x58, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x61, 0x72, 0x63,
0x61, 0x2d, 0x64, 0x65, 0x76, 0x2f, 0x70, 0x61, 0x72, 0x63, 0x61, 0x2f, 0x67, 0x65, 0x6e, 0x2f,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x61, 0x72, 0x63, 0x61, 0x2f, 0x70,
0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x31, 0x61, 0x6c,
0x70, 0x68, 0x61, 0x31, 0x3b, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x74, 0x6f, 0x72,
0x65, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xa2, 0x02, 0x03, 0x50, 0x50, 0x58, 0xaa,
0x02, 0x1b, 0x50, 0x61, 0x72, 0x63, 0x61, 0x2e, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73,
0x74, 0x6f, 0x72, 0x65, 0x2e, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xca, 0x02, 0x1b,
0x50, 0x61, 0x72, 0x63, 0x61, 0x5c, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x74, 0x6f,
0x72, 0x65, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xe2, 0x02, 0x27, 0x50, 0x61,
0x72, 0x63, 0x61, 0x5c, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65,
0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74,
0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x1d, 0x50, 0x61, 0x72, 0x63, 0x61, 0x3a, 0x3a, 0x50,
0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x3a, 0x3a, 0x56, 0x31, 0x61,
0x6c, 0x70, 0x68, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
file_parca_profilestore_v1alpha1_profilestore_proto_rawDescOnce sync.Once
file_parca_profilestore_v1alpha1_profilestore_proto_rawDescData = file_parca_profilestore_v1alpha1_profilestore_proto_rawDesc
)
func file_parca_profilestore_v1alpha1_profilestore_proto_rawDescGZIP() []byte {
file_parca_profilestore_v1alpha1_profilestore_proto_rawDescOnce.Do(func() {
file_parca_profilestore_v1alpha1_profilestore_proto_rawDescData = protoimpl.X.CompressGZIP(file_parca_profilestore_v1alpha1_profilestore_proto_rawDescData)
})
return file_parca_profilestore_v1alpha1_profilestore_proto_rawDescData
}
var file_parca_profilestore_v1alpha1_profilestore_proto_msgTypes = make([]protoimpl.MessageInfo, 6)
var file_parca_profilestore_v1alpha1_profilestore_proto_goTypes = []interface{}{
(*WriteRawRequest)(nil), // 0: parca.profilestore.v1alpha1.WriteRawRequest
(*WriteRawResponse)(nil), // 1: parca.profilestore.v1alpha1.WriteRawResponse
(*RawProfileSeries)(nil), // 2: parca.profilestore.v1alpha1.RawProfileSeries
(*Label)(nil), // 3: parca.profilestore.v1alpha1.Label
(*LabelSet)(nil), // 4: parca.profilestore.v1alpha1.LabelSet
(*RawSample)(nil), // 5: parca.profilestore.v1alpha1.RawSample
}
var file_parca_profilestore_v1alpha1_profilestore_proto_depIdxs = []int32{
2, // 0: parca.profilestore.v1alpha1.WriteRawRequest.series:type_name -> parca.profilestore.v1alpha1.RawProfileSeries
4, // 1: parca.profilestore.v1alpha1.RawProfileSeries.labels:type_name -> parca.profilestore.v1alpha1.LabelSet
5, // 2: parca.profilestore.v1alpha1.RawProfileSeries.samples:type_name -> parca.profilestore.v1alpha1.RawSample
3, // 3: parca.profilestore.v1alpha1.LabelSet.labels:type_name -> parca.profilestore.v1alpha1.Label
0, // 4: parca.profilestore.v1alpha1.ProfileStoreService.WriteRaw:input_type -> parca.profilestore.v1alpha1.WriteRawRequest
1, // 5: parca.profilestore.v1alpha1.ProfileStoreService.WriteRaw:output_type -> parca.profilestore.v1alpha1.WriteRawResponse
5, // [5:6] is the sub-list for method output_type
4, // [4:5] is the sub-list for method input_type
4, // [4:4] is the sub-list for extension type_name
4, // [4:4] is the sub-list for extension extendee
0, // [0:4] is the sub-list for field type_name
}
func init() { file_parca_profilestore_v1alpha1_profilestore_proto_init() }
func file_parca_profilestore_v1alpha1_profilestore_proto_init() {
if File_parca_profilestore_v1alpha1_profilestore_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_parca_profilestore_v1alpha1_profilestore_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*WriteRawRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_parca_profilestore_v1alpha1_profilestore_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*WriteRawResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_parca_profilestore_v1alpha1_profilestore_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*RawProfileSeries); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_parca_profilestore_v1alpha1_profilestore_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Label); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_parca_profilestore_v1alpha1_profilestore_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*LabelSet); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_parca_profilestore_v1alpha1_profilestore_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*RawSample); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_parca_profilestore_v1alpha1_profilestore_proto_rawDesc,
NumEnums: 0,
NumMessages: 6,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_parca_profilestore_v1alpha1_profilestore_proto_goTypes,
DependencyIndexes: file_parca_profilestore_v1alpha1_profilestore_proto_depIdxs,
MessageInfos: file_parca_profilestore_v1alpha1_profilestore_proto_msgTypes,
}.Build()
File_parca_profilestore_v1alpha1_profilestore_proto = out.File
file_parca_profilestore_v1alpha1_profilestore_proto_rawDesc = nil
file_parca_profilestore_v1alpha1_profilestore_proto_goTypes = nil
file_parca_profilestore_v1alpha1_profilestore_proto_depIdxs = nil
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,91 @@
// Code generated by protoc-gen-connect-go. DO NOT EDIT.
//
// Source: parca/profilestore/v1alpha1/profilestore.proto
package profilestorev1alpha1connect
import (
context "context"
errors "errors"
connect_go "github.com/bufbuild/connect-go"
v1alpha1 "github.com/parca-dev/parca/gen/proto/go/parca/profilestore/v1alpha1"
http "net/http"
strings "strings"
)
// This is a compile-time assertion to ensure that this generated file and the connect package are
// compatible. If you get a compiler error that this constant is not defined, this code was
// generated with a version of connect newer than the one compiled into your binary. You can fix the
// problem by either regenerating this code with an older version of connect or updating the connect
// version compiled into your binary.
const _ = connect_go.IsAtLeastVersion0_1_0
const (
// ProfileStoreServiceName is the fully-qualified name of the ProfileStoreService service.
ProfileStoreServiceName = "parca.profilestore.v1alpha1.ProfileStoreService"
)
// ProfileStoreServiceClient is a client for the parca.profilestore.v1alpha1.ProfileStoreService
// service.
type ProfileStoreServiceClient interface {
// WriteRaw accepts a raw set of bytes of a pprof file
WriteRaw(context.Context, *connect_go.Request[v1alpha1.WriteRawRequest]) (*connect_go.Response[v1alpha1.WriteRawResponse], error)
}
// NewProfileStoreServiceClient constructs a client for the
// parca.profilestore.v1alpha1.ProfileStoreService service. By default, it uses the Connect protocol
// with the binary Protobuf Codec, asks for gzipped responses, and sends uncompressed requests. To
// use the gRPC or gRPC-Web protocols, supply the connect.WithGRPC() or connect.WithGRPCWeb()
// options.
//
// The URL supplied here should be the base URL for the Connect or gRPC server (for example,
// http://api.acme.com or https://acme.com/grpc).
func NewProfileStoreServiceClient(httpClient connect_go.HTTPClient, baseURL string, opts ...connect_go.ClientOption) ProfileStoreServiceClient {
baseURL = strings.TrimRight(baseURL, "/")
return &profileStoreServiceClient{
writeRaw: connect_go.NewClient[v1alpha1.WriteRawRequest, v1alpha1.WriteRawResponse](
httpClient,
baseURL+"/parca.profilestore.v1alpha1.ProfileStoreService/WriteRaw",
opts...,
),
}
}
// profileStoreServiceClient implements ProfileStoreServiceClient.
type profileStoreServiceClient struct {
writeRaw *connect_go.Client[v1alpha1.WriteRawRequest, v1alpha1.WriteRawResponse]
}
// WriteRaw calls parca.profilestore.v1alpha1.ProfileStoreService.WriteRaw.
func (c *profileStoreServiceClient) WriteRaw(ctx context.Context, req *connect_go.Request[v1alpha1.WriteRawRequest]) (*connect_go.Response[v1alpha1.WriteRawResponse], error) {
return c.writeRaw.CallUnary(ctx, req)
}
// ProfileStoreServiceHandler is an implementation of the
// parca.profilestore.v1alpha1.ProfileStoreService service.
type ProfileStoreServiceHandler interface {
// WriteRaw accepts a raw set of bytes of a pprof file
WriteRaw(context.Context, *connect_go.Request[v1alpha1.WriteRawRequest]) (*connect_go.Response[v1alpha1.WriteRawResponse], error)
}
// NewProfileStoreServiceHandler builds an HTTP handler from the service implementation. It returns
// the path on which to mount the handler and the handler itself.
//
// By default, handlers support the Connect, gRPC, and gRPC-Web protocols with the binary Protobuf
// and JSON codecs. They also support gzip compression.
func NewProfileStoreServiceHandler(svc ProfileStoreServiceHandler, opts ...connect_go.HandlerOption) (string, http.Handler) {
mux := http.NewServeMux()
mux.Handle("/parca.profilestore.v1alpha1.ProfileStoreService/WriteRaw", connect_go.NewUnaryHandler(
"/parca.profilestore.v1alpha1.ProfileStoreService/WriteRaw",
svc.WriteRaw,
opts...,
))
return "/parca.profilestore.v1alpha1.ProfileStoreService/", mux
}
// UnimplementedProfileStoreServiceHandler returns CodeUnimplemented from all methods.
type UnimplementedProfileStoreServiceHandler struct{}
func (UnimplementedProfileStoreServiceHandler) WriteRaw(context.Context, *connect_go.Request[v1alpha1.WriteRawRequest]) (*connect_go.Response[v1alpha1.WriteRawResponse], error) {
return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("parca.profilestore.v1alpha1.ProfileStoreService.WriteRaw is not implemented"))
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,232 @@
// Code generated by protoc-gen-connect-go. DO NOT EDIT.
//
// Source: parca/query/v1alpha1/query.proto
package queryv1alpha1connect
import (
context "context"
errors "errors"
connect_go "github.com/bufbuild/connect-go"
v1alpha1 "github.com/parca-dev/parca/gen/proto/go/parca/query/v1alpha1"
http "net/http"
strings "strings"
)
// This is a compile-time assertion to ensure that this generated file and the connect package are
// compatible. If you get a compiler error that this constant is not defined, this code was
// generated with a version of connect newer than the one compiled into your binary. You can fix the
// problem by either regenerating this code with an older version of connect or updating the connect
// version compiled into your binary.
const _ = connect_go.IsAtLeastVersion0_1_0
const (
// QueryServiceName is the fully-qualified name of the QueryService service.
QueryServiceName = "parca.query.v1alpha1.QueryService"
)
// QueryServiceClient is a client for the parca.query.v1alpha1.QueryService service.
type QueryServiceClient interface {
// QueryRange performs a profile query over a time range
QueryRange(context.Context, *connect_go.Request[v1alpha1.QueryRangeRequest]) (*connect_go.Response[v1alpha1.QueryRangeResponse], error)
// Query performs a profile query
Query(context.Context, *connect_go.Request[v1alpha1.QueryRequest]) (*connect_go.Response[v1alpha1.QueryResponse], error)
// Series is unimplemented
Series(context.Context, *connect_go.Request[v1alpha1.SeriesRequest]) (*connect_go.Response[v1alpha1.SeriesResponse], error)
// ProfileTypes returns the list of available profile types.
ProfileTypes(context.Context, *connect_go.Request[v1alpha1.ProfileTypesRequest]) (*connect_go.Response[v1alpha1.ProfileTypesResponse], error)
// Labels returns the set of label names against a given matching string and time frame
Labels(context.Context, *connect_go.Request[v1alpha1.LabelsRequest]) (*connect_go.Response[v1alpha1.LabelsResponse], error)
// Values returns the set of values that match a given label and time frame
Values(context.Context, *connect_go.Request[v1alpha1.ValuesRequest]) (*connect_go.Response[v1alpha1.ValuesResponse], error)
// ShareProfile uploads the given profile to pprof.me and returns a link to the profile.
ShareProfile(context.Context, *connect_go.Request[v1alpha1.ShareProfileRequest]) (*connect_go.Response[v1alpha1.ShareProfileResponse], error)
}
// NewQueryServiceClient constructs a client for the parca.query.v1alpha1.QueryService service. By
// default, it uses the Connect protocol with the binary Protobuf Codec, asks for gzipped responses,
// and sends uncompressed requests. To use the gRPC or gRPC-Web protocols, supply the
// connect.WithGRPC() or connect.WithGRPCWeb() options.
//
// The URL supplied here should be the base URL for the Connect or gRPC server (for example,
// http://api.acme.com or https://acme.com/grpc).
func NewQueryServiceClient(httpClient connect_go.HTTPClient, baseURL string, opts ...connect_go.ClientOption) QueryServiceClient {
baseURL = strings.TrimRight(baseURL, "/")
return &queryServiceClient{
queryRange: connect_go.NewClient[v1alpha1.QueryRangeRequest, v1alpha1.QueryRangeResponse](
httpClient,
baseURL+"/parca.query.v1alpha1.QueryService/QueryRange",
opts...,
),
query: connect_go.NewClient[v1alpha1.QueryRequest, v1alpha1.QueryResponse](
httpClient,
baseURL+"/parca.query.v1alpha1.QueryService/Query",
opts...,
),
series: connect_go.NewClient[v1alpha1.SeriesRequest, v1alpha1.SeriesResponse](
httpClient,
baseURL+"/parca.query.v1alpha1.QueryService/Series",
opts...,
),
profileTypes: connect_go.NewClient[v1alpha1.ProfileTypesRequest, v1alpha1.ProfileTypesResponse](
httpClient,
baseURL+"/parca.query.v1alpha1.QueryService/ProfileTypes",
opts...,
),
labels: connect_go.NewClient[v1alpha1.LabelsRequest, v1alpha1.LabelsResponse](
httpClient,
baseURL+"/parca.query.v1alpha1.QueryService/Labels",
opts...,
),
values: connect_go.NewClient[v1alpha1.ValuesRequest, v1alpha1.ValuesResponse](
httpClient,
baseURL+"/parca.query.v1alpha1.QueryService/Values",
opts...,
),
shareProfile: connect_go.NewClient[v1alpha1.ShareProfileRequest, v1alpha1.ShareProfileResponse](
httpClient,
baseURL+"/parca.query.v1alpha1.QueryService/ShareProfile",
opts...,
),
}
}
// queryServiceClient implements QueryServiceClient.
type queryServiceClient struct {
queryRange *connect_go.Client[v1alpha1.QueryRangeRequest, v1alpha1.QueryRangeResponse]
query *connect_go.Client[v1alpha1.QueryRequest, v1alpha1.QueryResponse]
series *connect_go.Client[v1alpha1.SeriesRequest, v1alpha1.SeriesResponse]
profileTypes *connect_go.Client[v1alpha1.ProfileTypesRequest, v1alpha1.ProfileTypesResponse]
labels *connect_go.Client[v1alpha1.LabelsRequest, v1alpha1.LabelsResponse]
values *connect_go.Client[v1alpha1.ValuesRequest, v1alpha1.ValuesResponse]
shareProfile *connect_go.Client[v1alpha1.ShareProfileRequest, v1alpha1.ShareProfileResponse]
}
// QueryRange calls parca.query.v1alpha1.QueryService.QueryRange.
func (c *queryServiceClient) QueryRange(ctx context.Context, req *connect_go.Request[v1alpha1.QueryRangeRequest]) (*connect_go.Response[v1alpha1.QueryRangeResponse], error) {
return c.queryRange.CallUnary(ctx, req)
}
// Query calls parca.query.v1alpha1.QueryService.Query.
func (c *queryServiceClient) Query(ctx context.Context, req *connect_go.Request[v1alpha1.QueryRequest]) (*connect_go.Response[v1alpha1.QueryResponse], error) {
return c.query.CallUnary(ctx, req)
}
// Series calls parca.query.v1alpha1.QueryService.Series.
func (c *queryServiceClient) Series(ctx context.Context, req *connect_go.Request[v1alpha1.SeriesRequest]) (*connect_go.Response[v1alpha1.SeriesResponse], error) {
return c.series.CallUnary(ctx, req)
}
// ProfileTypes calls parca.query.v1alpha1.QueryService.ProfileTypes.
func (c *queryServiceClient) ProfileTypes(ctx context.Context, req *connect_go.Request[v1alpha1.ProfileTypesRequest]) (*connect_go.Response[v1alpha1.ProfileTypesResponse], error) {
return c.profileTypes.CallUnary(ctx, req)
}
// Labels calls parca.query.v1alpha1.QueryService.Labels.
func (c *queryServiceClient) Labels(ctx context.Context, req *connect_go.Request[v1alpha1.LabelsRequest]) (*connect_go.Response[v1alpha1.LabelsResponse], error) {
return c.labels.CallUnary(ctx, req)
}
// Values calls parca.query.v1alpha1.QueryService.Values.
func (c *queryServiceClient) Values(ctx context.Context, req *connect_go.Request[v1alpha1.ValuesRequest]) (*connect_go.Response[v1alpha1.ValuesResponse], error) {
return c.values.CallUnary(ctx, req)
}
// ShareProfile calls parca.query.v1alpha1.QueryService.ShareProfile.
func (c *queryServiceClient) ShareProfile(ctx context.Context, req *connect_go.Request[v1alpha1.ShareProfileRequest]) (*connect_go.Response[v1alpha1.ShareProfileResponse], error) {
return c.shareProfile.CallUnary(ctx, req)
}
// QueryServiceHandler is an implementation of the parca.query.v1alpha1.QueryService service.
type QueryServiceHandler interface {
// QueryRange performs a profile query over a time range
QueryRange(context.Context, *connect_go.Request[v1alpha1.QueryRangeRequest]) (*connect_go.Response[v1alpha1.QueryRangeResponse], error)
// Query performs a profile query
Query(context.Context, *connect_go.Request[v1alpha1.QueryRequest]) (*connect_go.Response[v1alpha1.QueryResponse], error)
// Series is unimplemented
Series(context.Context, *connect_go.Request[v1alpha1.SeriesRequest]) (*connect_go.Response[v1alpha1.SeriesResponse], error)
// ProfileTypes returns the list of available profile types.
ProfileTypes(context.Context, *connect_go.Request[v1alpha1.ProfileTypesRequest]) (*connect_go.Response[v1alpha1.ProfileTypesResponse], error)
// Labels returns the set of label names against a given matching string and time frame
Labels(context.Context, *connect_go.Request[v1alpha1.LabelsRequest]) (*connect_go.Response[v1alpha1.LabelsResponse], error)
// Values returns the set of values that match a given label and time frame
Values(context.Context, *connect_go.Request[v1alpha1.ValuesRequest]) (*connect_go.Response[v1alpha1.ValuesResponse], error)
// ShareProfile uploads the given profile to pprof.me and returns a link to the profile.
ShareProfile(context.Context, *connect_go.Request[v1alpha1.ShareProfileRequest]) (*connect_go.Response[v1alpha1.ShareProfileResponse], error)
}
// NewQueryServiceHandler builds an HTTP handler from the service implementation. It returns the
// path on which to mount the handler and the handler itself.
//
// By default, handlers support the Connect, gRPC, and gRPC-Web protocols with the binary Protobuf
// and JSON codecs. They also support gzip compression.
func NewQueryServiceHandler(svc QueryServiceHandler, opts ...connect_go.HandlerOption) (string, http.Handler) {
mux := http.NewServeMux()
mux.Handle("/parca.query.v1alpha1.QueryService/QueryRange", connect_go.NewUnaryHandler(
"/parca.query.v1alpha1.QueryService/QueryRange",
svc.QueryRange,
opts...,
))
mux.Handle("/parca.query.v1alpha1.QueryService/Query", connect_go.NewUnaryHandler(
"/parca.query.v1alpha1.QueryService/Query",
svc.Query,
opts...,
))
mux.Handle("/parca.query.v1alpha1.QueryService/Series", connect_go.NewUnaryHandler(
"/parca.query.v1alpha1.QueryService/Series",
svc.Series,
opts...,
))
mux.Handle("/parca.query.v1alpha1.QueryService/ProfileTypes", connect_go.NewUnaryHandler(
"/parca.query.v1alpha1.QueryService/ProfileTypes",
svc.ProfileTypes,
opts...,
))
mux.Handle("/parca.query.v1alpha1.QueryService/Labels", connect_go.NewUnaryHandler(
"/parca.query.v1alpha1.QueryService/Labels",
svc.Labels,
opts...,
))
mux.Handle("/parca.query.v1alpha1.QueryService/Values", connect_go.NewUnaryHandler(
"/parca.query.v1alpha1.QueryService/Values",
svc.Values,
opts...,
))
mux.Handle("/parca.query.v1alpha1.QueryService/ShareProfile", connect_go.NewUnaryHandler(
"/parca.query.v1alpha1.QueryService/ShareProfile",
svc.ShareProfile,
opts...,
))
return "/parca.query.v1alpha1.QueryService/", mux
}
// UnimplementedQueryServiceHandler returns CodeUnimplemented from all methods.
type UnimplementedQueryServiceHandler struct{}
func (UnimplementedQueryServiceHandler) QueryRange(context.Context, *connect_go.Request[v1alpha1.QueryRangeRequest]) (*connect_go.Response[v1alpha1.QueryRangeResponse], error) {
return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("parca.query.v1alpha1.QueryService.QueryRange is not implemented"))
}
func (UnimplementedQueryServiceHandler) Query(context.Context, *connect_go.Request[v1alpha1.QueryRequest]) (*connect_go.Response[v1alpha1.QueryResponse], error) {
return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("parca.query.v1alpha1.QueryService.Query is not implemented"))
}
func (UnimplementedQueryServiceHandler) Series(context.Context, *connect_go.Request[v1alpha1.SeriesRequest]) (*connect_go.Response[v1alpha1.SeriesResponse], error) {
return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("parca.query.v1alpha1.QueryService.Series is not implemented"))
}
func (UnimplementedQueryServiceHandler) ProfileTypes(context.Context, *connect_go.Request[v1alpha1.ProfileTypesRequest]) (*connect_go.Response[v1alpha1.ProfileTypesResponse], error) {
return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("parca.query.v1alpha1.QueryService.ProfileTypes is not implemented"))
}
func (UnimplementedQueryServiceHandler) Labels(context.Context, *connect_go.Request[v1alpha1.LabelsRequest]) (*connect_go.Response[v1alpha1.LabelsResponse], error) {
return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("parca.query.v1alpha1.QueryService.Labels is not implemented"))
}
func (UnimplementedQueryServiceHandler) Values(context.Context, *connect_go.Request[v1alpha1.ValuesRequest]) (*connect_go.Response[v1alpha1.ValuesResponse], error) {
return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("parca.query.v1alpha1.QueryService.Values is not implemented"))
}
func (UnimplementedQueryServiceHandler) ShareProfile(context.Context, *connect_go.Request[v1alpha1.ShareProfileRequest]) (*connect_go.Response[v1alpha1.ShareProfileResponse], error) {
return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("parca.query.v1alpha1.QueryService.ShareProfile is not implemented"))
}
@@ -0,0 +1,600 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.28.1
// protoc (unknown)
// source: parca/scrape/v1alpha1/scrape.proto
package scrapev1alpha1
import (
v1alpha1 "github.com/parca-dev/parca/gen/proto/go/parca/profilestore/v1alpha1"
_ "google.golang.org/genproto/googleapis/api/annotations"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
durationpb "google.golang.org/protobuf/types/known/durationpb"
timestamppb "google.golang.org/protobuf/types/known/timestamppb"
reflect "reflect"
sync "sync"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
// State represents the current state of a target
type TargetsRequest_State int32
const (
// STATE_ANY_UNSPECIFIED unspecified
TargetsRequest_STATE_ANY_UNSPECIFIED TargetsRequest_State = 0
// STATE_ACTIVE target active state
TargetsRequest_STATE_ACTIVE TargetsRequest_State = 1
// STATE_DROPPED target dropped state
TargetsRequest_STATE_DROPPED TargetsRequest_State = 2
)
// Enum value maps for TargetsRequest_State.
var (
TargetsRequest_State_name = map[int32]string{
0: "STATE_ANY_UNSPECIFIED",
1: "STATE_ACTIVE",
2: "STATE_DROPPED",
}
TargetsRequest_State_value = map[string]int32{
"STATE_ANY_UNSPECIFIED": 0,
"STATE_ACTIVE": 1,
"STATE_DROPPED": 2,
}
)
func (x TargetsRequest_State) Enum() *TargetsRequest_State {
p := new(TargetsRequest_State)
*p = x
return p
}
func (x TargetsRequest_State) String() string {
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
}
func (TargetsRequest_State) Descriptor() protoreflect.EnumDescriptor {
return file_parca_scrape_v1alpha1_scrape_proto_enumTypes[0].Descriptor()
}
func (TargetsRequest_State) Type() protoreflect.EnumType {
return &file_parca_scrape_v1alpha1_scrape_proto_enumTypes[0]
}
func (x TargetsRequest_State) Number() protoreflect.EnumNumber {
return protoreflect.EnumNumber(x)
}
// Deprecated: Use TargetsRequest_State.Descriptor instead.
func (TargetsRequest_State) EnumDescriptor() ([]byte, []int) {
return file_parca_scrape_v1alpha1_scrape_proto_rawDescGZIP(), []int{0, 0}
}
// Health are the possible health values of a target
type Target_Health int32
const (
// HEALTH_UNKNOWN_UNSPECIFIED unspecified
Target_HEALTH_UNKNOWN_UNSPECIFIED Target_Health = 0
// HEALTH_GOOD healthy target
Target_HEALTH_GOOD Target_Health = 1
// HEALTH_BAD unhealthy target
Target_HEALTH_BAD Target_Health = 2
)
// Enum value maps for Target_Health.
var (
Target_Health_name = map[int32]string{
0: "HEALTH_UNKNOWN_UNSPECIFIED",
1: "HEALTH_GOOD",
2: "HEALTH_BAD",
}
Target_Health_value = map[string]int32{
"HEALTH_UNKNOWN_UNSPECIFIED": 0,
"HEALTH_GOOD": 1,
"HEALTH_BAD": 2,
}
)
func (x Target_Health) Enum() *Target_Health {
p := new(Target_Health)
*p = x
return p
}
func (x Target_Health) String() string {
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
}
func (Target_Health) Descriptor() protoreflect.EnumDescriptor {
return file_parca_scrape_v1alpha1_scrape_proto_enumTypes[1].Descriptor()
}
func (Target_Health) Type() protoreflect.EnumType {
return &file_parca_scrape_v1alpha1_scrape_proto_enumTypes[1]
}
func (x Target_Health) Number() protoreflect.EnumNumber {
return protoreflect.EnumNumber(x)
}
// Deprecated: Use Target_Health.Descriptor instead.
func (Target_Health) EnumDescriptor() ([]byte, []int) {
return file_parca_scrape_v1alpha1_scrape_proto_rawDescGZIP(), []int{3, 0}
}
// TargetsRequest contains the parameters for the set of targets to return
type TargetsRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// state is the state of targets to returns
State TargetsRequest_State `protobuf:"varint,1,opt,name=state,proto3,enum=parca.scrape.v1alpha1.TargetsRequest_State" json:"state,omitempty"`
}
func (x *TargetsRequest) Reset() {
*x = TargetsRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_parca_scrape_v1alpha1_scrape_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *TargetsRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*TargetsRequest) ProtoMessage() {}
func (x *TargetsRequest) ProtoReflect() protoreflect.Message {
mi := &file_parca_scrape_v1alpha1_scrape_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use TargetsRequest.ProtoReflect.Descriptor instead.
func (*TargetsRequest) Descriptor() ([]byte, []int) {
return file_parca_scrape_v1alpha1_scrape_proto_rawDescGZIP(), []int{0}
}
func (x *TargetsRequest) GetState() TargetsRequest_State {
if x != nil {
return x.State
}
return TargetsRequest_STATE_ANY_UNSPECIFIED
}
// TargetsResponse is the set of targets for the given requested state
type TargetsResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// targets is the mapping of targets
Targets map[string]*Targets `protobuf:"bytes,1,rep,name=targets,proto3" json:"targets,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
}
func (x *TargetsResponse) Reset() {
*x = TargetsResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_parca_scrape_v1alpha1_scrape_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *TargetsResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*TargetsResponse) ProtoMessage() {}
func (x *TargetsResponse) ProtoReflect() protoreflect.Message {
mi := &file_parca_scrape_v1alpha1_scrape_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use TargetsResponse.ProtoReflect.Descriptor instead.
func (*TargetsResponse) Descriptor() ([]byte, []int) {
return file_parca_scrape_v1alpha1_scrape_proto_rawDescGZIP(), []int{1}
}
func (x *TargetsResponse) GetTargets() map[string]*Targets {
if x != nil {
return x.Targets
}
return nil
}
// Targets is a list of targets
type Targets struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// targets is a list of targets
Targets []*Target `protobuf:"bytes,1,rep,name=targets,proto3" json:"targets,omitempty"`
}
func (x *Targets) Reset() {
*x = Targets{}
if protoimpl.UnsafeEnabled {
mi := &file_parca_scrape_v1alpha1_scrape_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Targets) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Targets) ProtoMessage() {}
func (x *Targets) ProtoReflect() protoreflect.Message {
mi := &file_parca_scrape_v1alpha1_scrape_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Targets.ProtoReflect.Descriptor instead.
func (*Targets) Descriptor() ([]byte, []int) {
return file_parca_scrape_v1alpha1_scrape_proto_rawDescGZIP(), []int{2}
}
func (x *Targets) GetTargets() []*Target {
if x != nil {
return x.Targets
}
return nil
}
// Target is the scrape target representation
type Target struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// discovered_labels are the set of labels for the target that have been discovered
DiscoveredLabels *v1alpha1.LabelSet `protobuf:"bytes,1,opt,name=discovered_labels,json=discoveredLabels,proto3" json:"discovered_labels,omitempty"`
// labels are the set of labels given for the target
Labels *v1alpha1.LabelSet `protobuf:"bytes,2,opt,name=labels,proto3" json:"labels,omitempty"`
// lase_error is the error message most recently received from a scrape attempt
LastError string `protobuf:"bytes,3,opt,name=last_error,json=lastError,proto3" json:"last_error,omitempty"`
// last_scrape is the time stamp the last scrape request was performed
LastScrape *timestamppb.Timestamp `protobuf:"bytes,4,opt,name=last_scrape,json=lastScrape,proto3" json:"last_scrape,omitempty"`
// last_scrape_duration is the duration of the last scrape request
LastScrapeDuration *durationpb.Duration `protobuf:"bytes,5,opt,name=last_scrape_duration,json=lastScrapeDuration,proto3" json:"last_scrape_duration,omitempty"`
// url is the url of the target
Url string `protobuf:"bytes,6,opt,name=url,proto3" json:"url,omitempty"`
// health indicates the current health of the target
Health Target_Health `protobuf:"varint,7,opt,name=health,proto3,enum=parca.scrape.v1alpha1.Target_Health" json:"health,omitempty"`
}
func (x *Target) Reset() {
*x = Target{}
if protoimpl.UnsafeEnabled {
mi := &file_parca_scrape_v1alpha1_scrape_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Target) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Target) ProtoMessage() {}
func (x *Target) ProtoReflect() protoreflect.Message {
mi := &file_parca_scrape_v1alpha1_scrape_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Target.ProtoReflect.Descriptor instead.
func (*Target) Descriptor() ([]byte, []int) {
return file_parca_scrape_v1alpha1_scrape_proto_rawDescGZIP(), []int{3}
}
func (x *Target) GetDiscoveredLabels() *v1alpha1.LabelSet {
if x != nil {
return x.DiscoveredLabels
}
return nil
}
func (x *Target) GetLabels() *v1alpha1.LabelSet {
if x != nil {
return x.Labels
}
return nil
}
func (x *Target) GetLastError() string {
if x != nil {
return x.LastError
}
return ""
}
func (x *Target) GetLastScrape() *timestamppb.Timestamp {
if x != nil {
return x.LastScrape
}
return nil
}
func (x *Target) GetLastScrapeDuration() *durationpb.Duration {
if x != nil {
return x.LastScrapeDuration
}
return nil
}
func (x *Target) GetUrl() string {
if x != nil {
return x.Url
}
return ""
}
func (x *Target) GetHealth() Target_Health {
if x != nil {
return x.Health
}
return Target_HEALTH_UNKNOWN_UNSPECIFIED
}
var File_parca_scrape_v1alpha1_scrape_proto protoreflect.FileDescriptor
var file_parca_scrape_v1alpha1_scrape_proto_rawDesc = []byte{
0x0a, 0x22, 0x70, 0x61, 0x72, 0x63, 0x61, 0x2f, 0x73, 0x63, 0x72, 0x61, 0x70, 0x65, 0x2f, 0x76,
0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x73, 0x63, 0x72, 0x61, 0x70, 0x65, 0x2e, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x12, 0x15, 0x70, 0x61, 0x72, 0x63, 0x61, 0x2e, 0x73, 0x63, 0x72, 0x61,
0x70, 0x65, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x1a, 0x1c, 0x67, 0x6f, 0x6f,
0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69,
0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x75, 0x72, 0x61, 0x74,
0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73,
0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x2e, 0x70, 0x61, 0x72, 0x63,
0x61, 0x2f, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2f, 0x76,
0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73,
0x74, 0x6f, 0x72, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x9c, 0x01, 0x0a, 0x0e, 0x54,
0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x41, 0x0a,
0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2b, 0x2e, 0x70,
0x61, 0x72, 0x63, 0x61, 0x2e, 0x73, 0x63, 0x72, 0x61, 0x70, 0x65, 0x2e, 0x76, 0x31, 0x61, 0x6c,
0x70, 0x68, 0x61, 0x31, 0x2e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75,
0x65, 0x73, 0x74, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65,
0x22, 0x47, 0x0a, 0x05, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x19, 0x0a, 0x15, 0x53, 0x54, 0x41,
0x54, 0x45, 0x5f, 0x41, 0x4e, 0x59, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49,
0x45, 0x44, 0x10, 0x00, 0x12, 0x10, 0x0a, 0x0c, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x41, 0x43,
0x54, 0x49, 0x56, 0x45, 0x10, 0x01, 0x12, 0x11, 0x0a, 0x0d, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f,
0x44, 0x52, 0x4f, 0x50, 0x50, 0x45, 0x44, 0x10, 0x02, 0x22, 0xbc, 0x01, 0x0a, 0x0f, 0x54, 0x61,
0x72, 0x67, 0x65, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4d, 0x0a,
0x07, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x33,
0x2e, 0x70, 0x61, 0x72, 0x63, 0x61, 0x2e, 0x73, 0x63, 0x72, 0x61, 0x70, 0x65, 0x2e, 0x76, 0x31,
0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x52, 0x65,
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x45, 0x6e,
0x74, 0x72, 0x79, 0x52, 0x07, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x1a, 0x5a, 0x0a, 0x0c,
0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03,
0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x34,
0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e,
0x70, 0x61, 0x72, 0x63, 0x61, 0x2e, 0x73, 0x63, 0x72, 0x61, 0x70, 0x65, 0x2e, 0x76, 0x31, 0x61,
0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x52, 0x05, 0x76,
0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x42, 0x0a, 0x07, 0x54, 0x61, 0x72, 0x67,
0x65, 0x74, 0x73, 0x12, 0x37, 0x0a, 0x07, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x18, 0x01,
0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x70, 0x61, 0x72, 0x63, 0x61, 0x2e, 0x73, 0x63, 0x72,
0x61, 0x70, 0x65, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x54, 0x61, 0x72,
0x67, 0x65, 0x74, 0x52, 0x07, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x22, 0xdf, 0x03, 0x0a,
0x06, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x52, 0x0a, 0x11, 0x64, 0x69, 0x73, 0x63, 0x6f,
0x76, 0x65, 0x72, 0x65, 0x64, 0x5f, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x25, 0x2e, 0x70, 0x61, 0x72, 0x63, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x66, 0x69,
0x6c, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31,
0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x53, 0x65, 0x74, 0x52, 0x10, 0x64, 0x69, 0x73, 0x63, 0x6f,
0x76, 0x65, 0x72, 0x65, 0x64, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x12, 0x3d, 0x0a, 0x06, 0x6c,
0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x70, 0x61,
0x72, 0x63, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65,
0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x53,
0x65, 0x74, 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x6c, 0x61,
0x73, 0x74, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09,
0x6c, 0x61, 0x73, 0x74, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x3b, 0x0a, 0x0b, 0x6c, 0x61, 0x73,
0x74, 0x5f, 0x73, 0x63, 0x72, 0x61, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a,
0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x6c, 0x61, 0x73, 0x74,
0x53, 0x63, 0x72, 0x61, 0x70, 0x65, 0x12, 0x4b, 0x0a, 0x14, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x73,
0x63, 0x72, 0x61, 0x70, 0x65, 0x5f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05,
0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52,
0x12, 0x6c, 0x61, 0x73, 0x74, 0x53, 0x63, 0x72, 0x61, 0x70, 0x65, 0x44, 0x75, 0x72, 0x61, 0x74,
0x69, 0x6f, 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09,
0x52, 0x03, 0x75, 0x72, 0x6c, 0x12, 0x3c, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x18,
0x07, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x24, 0x2e, 0x70, 0x61, 0x72, 0x63, 0x61, 0x2e, 0x73, 0x63,
0x72, 0x61, 0x70, 0x65, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x54, 0x61,
0x72, 0x67, 0x65, 0x74, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x52, 0x06, 0x68, 0x65, 0x61,
0x6c, 0x74, 0x68, 0x22, 0x49, 0x0a, 0x06, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x12, 0x1e, 0x0a,
0x1a, 0x48, 0x45, 0x41, 0x4c, 0x54, 0x48, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x5f,
0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0f, 0x0a,
0x0b, 0x48, 0x45, 0x41, 0x4c, 0x54, 0x48, 0x5f, 0x47, 0x4f, 0x4f, 0x44, 0x10, 0x01, 0x12, 0x0e,
0x0a, 0x0a, 0x48, 0x45, 0x41, 0x4c, 0x54, 0x48, 0x5f, 0x42, 0x41, 0x44, 0x10, 0x02, 0x32, 0x7b,
0x0a, 0x0d, 0x53, 0x63, 0x72, 0x61, 0x70, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12,
0x6a, 0x0a, 0x07, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x12, 0x25, 0x2e, 0x70, 0x61, 0x72,
0x63, 0x61, 0x2e, 0x73, 0x63, 0x72, 0x61, 0x70, 0x65, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68,
0x61, 0x31, 0x2e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x1a, 0x26, 0x2e, 0x70, 0x61, 0x72, 0x63, 0x61, 0x2e, 0x73, 0x63, 0x72, 0x61, 0x70, 0x65,
0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74,
0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x10, 0x82, 0xd3, 0xe4, 0x93, 0x02,
0x0a, 0x12, 0x08, 0x2f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x42, 0xec, 0x01, 0x0a, 0x19,
0x63, 0x6f, 0x6d, 0x2e, 0x70, 0x61, 0x72, 0x63, 0x61, 0x2e, 0x73, 0x63, 0x72, 0x61, 0x70, 0x65,
0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x42, 0x0b, 0x53, 0x63, 0x72, 0x61, 0x70,
0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x4c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62,
0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x61, 0x72, 0x63, 0x61, 0x2d, 0x64, 0x65, 0x76, 0x2f, 0x70,
0x61, 0x72, 0x63, 0x61, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67,
0x6f, 0x2f, 0x70, 0x61, 0x72, 0x63, 0x61, 0x2f, 0x73, 0x63, 0x72, 0x61, 0x70, 0x65, 0x2f, 0x76,
0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3b, 0x73, 0x63, 0x72, 0x61, 0x70, 0x65, 0x76, 0x31,
0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xa2, 0x02, 0x03, 0x50, 0x53, 0x58, 0xaa, 0x02, 0x15, 0x50,
0x61, 0x72, 0x63, 0x61, 0x2e, 0x53, 0x63, 0x72, 0x61, 0x70, 0x65, 0x2e, 0x56, 0x31, 0x61, 0x6c,
0x70, 0x68, 0x61, 0x31, 0xca, 0x02, 0x15, 0x50, 0x61, 0x72, 0x63, 0x61, 0x5c, 0x53, 0x63, 0x72,
0x61, 0x70, 0x65, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xe2, 0x02, 0x21, 0x50,
0x61, 0x72, 0x63, 0x61, 0x5c, 0x53, 0x63, 0x72, 0x61, 0x70, 0x65, 0x5c, 0x56, 0x31, 0x61, 0x6c,
0x70, 0x68, 0x61, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61,
0xea, 0x02, 0x17, 0x50, 0x61, 0x72, 0x63, 0x61, 0x3a, 0x3a, 0x53, 0x63, 0x72, 0x61, 0x70, 0x65,
0x3a, 0x3a, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x33,
}
var (
file_parca_scrape_v1alpha1_scrape_proto_rawDescOnce sync.Once
file_parca_scrape_v1alpha1_scrape_proto_rawDescData = file_parca_scrape_v1alpha1_scrape_proto_rawDesc
)
func file_parca_scrape_v1alpha1_scrape_proto_rawDescGZIP() []byte {
file_parca_scrape_v1alpha1_scrape_proto_rawDescOnce.Do(func() {
file_parca_scrape_v1alpha1_scrape_proto_rawDescData = protoimpl.X.CompressGZIP(file_parca_scrape_v1alpha1_scrape_proto_rawDescData)
})
return file_parca_scrape_v1alpha1_scrape_proto_rawDescData
}
var file_parca_scrape_v1alpha1_scrape_proto_enumTypes = make([]protoimpl.EnumInfo, 2)
var file_parca_scrape_v1alpha1_scrape_proto_msgTypes = make([]protoimpl.MessageInfo, 5)
var file_parca_scrape_v1alpha1_scrape_proto_goTypes = []interface{}{
(TargetsRequest_State)(0), // 0: parca.scrape.v1alpha1.TargetsRequest.State
(Target_Health)(0), // 1: parca.scrape.v1alpha1.Target.Health
(*TargetsRequest)(nil), // 2: parca.scrape.v1alpha1.TargetsRequest
(*TargetsResponse)(nil), // 3: parca.scrape.v1alpha1.TargetsResponse
(*Targets)(nil), // 4: parca.scrape.v1alpha1.Targets
(*Target)(nil), // 5: parca.scrape.v1alpha1.Target
nil, // 6: parca.scrape.v1alpha1.TargetsResponse.TargetsEntry
(*v1alpha1.LabelSet)(nil), // 7: parca.profilestore.v1alpha1.LabelSet
(*timestamppb.Timestamp)(nil), // 8: google.protobuf.Timestamp
(*durationpb.Duration)(nil), // 9: google.protobuf.Duration
}
var file_parca_scrape_v1alpha1_scrape_proto_depIdxs = []int32{
0, // 0: parca.scrape.v1alpha1.TargetsRequest.state:type_name -> parca.scrape.v1alpha1.TargetsRequest.State
6, // 1: parca.scrape.v1alpha1.TargetsResponse.targets:type_name -> parca.scrape.v1alpha1.TargetsResponse.TargetsEntry
5, // 2: parca.scrape.v1alpha1.Targets.targets:type_name -> parca.scrape.v1alpha1.Target
7, // 3: parca.scrape.v1alpha1.Target.discovered_labels:type_name -> parca.profilestore.v1alpha1.LabelSet
7, // 4: parca.scrape.v1alpha1.Target.labels:type_name -> parca.profilestore.v1alpha1.LabelSet
8, // 5: parca.scrape.v1alpha1.Target.last_scrape:type_name -> google.protobuf.Timestamp
9, // 6: parca.scrape.v1alpha1.Target.last_scrape_duration:type_name -> google.protobuf.Duration
1, // 7: parca.scrape.v1alpha1.Target.health:type_name -> parca.scrape.v1alpha1.Target.Health
4, // 8: parca.scrape.v1alpha1.TargetsResponse.TargetsEntry.value:type_name -> parca.scrape.v1alpha1.Targets
2, // 9: parca.scrape.v1alpha1.ScrapeService.Targets:input_type -> parca.scrape.v1alpha1.TargetsRequest
3, // 10: parca.scrape.v1alpha1.ScrapeService.Targets:output_type -> parca.scrape.v1alpha1.TargetsResponse
10, // [10:11] is the sub-list for method output_type
9, // [9:10] is the sub-list for method input_type
9, // [9:9] is the sub-list for extension type_name
9, // [9:9] is the sub-list for extension extendee
0, // [0:9] is the sub-list for field type_name
}
func init() { file_parca_scrape_v1alpha1_scrape_proto_init() }
func file_parca_scrape_v1alpha1_scrape_proto_init() {
if File_parca_scrape_v1alpha1_scrape_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_parca_scrape_v1alpha1_scrape_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*TargetsRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_parca_scrape_v1alpha1_scrape_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*TargetsResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_parca_scrape_v1alpha1_scrape_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Targets); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_parca_scrape_v1alpha1_scrape_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Target); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_parca_scrape_v1alpha1_scrape_proto_rawDesc,
NumEnums: 2,
NumMessages: 5,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_parca_scrape_v1alpha1_scrape_proto_goTypes,
DependencyIndexes: file_parca_scrape_v1alpha1_scrape_proto_depIdxs,
EnumInfos: file_parca_scrape_v1alpha1_scrape_proto_enumTypes,
MessageInfos: file_parca_scrape_v1alpha1_scrape_proto_msgTypes,
}.Build()
File_parca_scrape_v1alpha1_scrape_proto = out.File
file_parca_scrape_v1alpha1_scrape_proto_rawDesc = nil
file_parca_scrape_v1alpha1_scrape_proto_goTypes = nil
file_parca_scrape_v1alpha1_scrape_proto_depIdxs = nil
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,88 @@
// Code generated by protoc-gen-connect-go. DO NOT EDIT.
//
// Source: parca/scrape/v1alpha1/scrape.proto
package scrapev1alpha1connect
import (
context "context"
errors "errors"
connect_go "github.com/bufbuild/connect-go"
v1alpha1 "github.com/parca-dev/parca/gen/proto/go/parca/scrape/v1alpha1"
http "net/http"
strings "strings"
)
// This is a compile-time assertion to ensure that this generated file and the connect package are
// compatible. If you get a compiler error that this constant is not defined, this code was
// generated with a version of connect newer than the one compiled into your binary. You can fix the
// problem by either regenerating this code with an older version of connect or updating the connect
// version compiled into your binary.
const _ = connect_go.IsAtLeastVersion0_1_0
const (
// ScrapeServiceName is the fully-qualified name of the ScrapeService service.
ScrapeServiceName = "parca.scrape.v1alpha1.ScrapeService"
)
// ScrapeServiceClient is a client for the parca.scrape.v1alpha1.ScrapeService service.
type ScrapeServiceClient interface {
// Targets returns the set of scrape targets that are configured
Targets(context.Context, *connect_go.Request[v1alpha1.TargetsRequest]) (*connect_go.Response[v1alpha1.TargetsResponse], error)
}
// NewScrapeServiceClient constructs a client for the parca.scrape.v1alpha1.ScrapeService service.
// By default, it uses the Connect protocol with the binary Protobuf Codec, asks for gzipped
// responses, and sends uncompressed requests. To use the gRPC or gRPC-Web protocols, supply the
// connect.WithGRPC() or connect.WithGRPCWeb() options.
//
// The URL supplied here should be the base URL for the Connect or gRPC server (for example,
// http://api.acme.com or https://acme.com/grpc).
func NewScrapeServiceClient(httpClient connect_go.HTTPClient, baseURL string, opts ...connect_go.ClientOption) ScrapeServiceClient {
baseURL = strings.TrimRight(baseURL, "/")
return &scrapeServiceClient{
targets: connect_go.NewClient[v1alpha1.TargetsRequest, v1alpha1.TargetsResponse](
httpClient,
baseURL+"/parca.scrape.v1alpha1.ScrapeService/Targets",
opts...,
),
}
}
// scrapeServiceClient implements ScrapeServiceClient.
type scrapeServiceClient struct {
targets *connect_go.Client[v1alpha1.TargetsRequest, v1alpha1.TargetsResponse]
}
// Targets calls parca.scrape.v1alpha1.ScrapeService.Targets.
func (c *scrapeServiceClient) Targets(ctx context.Context, req *connect_go.Request[v1alpha1.TargetsRequest]) (*connect_go.Response[v1alpha1.TargetsResponse], error) {
return c.targets.CallUnary(ctx, req)
}
// ScrapeServiceHandler is an implementation of the parca.scrape.v1alpha1.ScrapeService service.
type ScrapeServiceHandler interface {
// Targets returns the set of scrape targets that are configured
Targets(context.Context, *connect_go.Request[v1alpha1.TargetsRequest]) (*connect_go.Response[v1alpha1.TargetsResponse], error)
}
// NewScrapeServiceHandler builds an HTTP handler from the service implementation. It returns the
// path on which to mount the handler and the handler itself.
//
// By default, handlers support the Connect, gRPC, and gRPC-Web protocols with the binary Protobuf
// and JSON codecs. They also support gzip compression.
func NewScrapeServiceHandler(svc ScrapeServiceHandler, opts ...connect_go.HandlerOption) (string, http.Handler) {
mux := http.NewServeMux()
mux.Handle("/parca.scrape.v1alpha1.ScrapeService/Targets", connect_go.NewUnaryHandler(
"/parca.scrape.v1alpha1.ScrapeService/Targets",
svc.Targets,
opts...,
))
return "/parca.scrape.v1alpha1.ScrapeService/", mux
}
// UnimplementedScrapeServiceHandler returns CodeUnimplemented from all methods.
type UnimplementedScrapeServiceHandler struct{}
func (UnimplementedScrapeServiceHandler) Targets(context.Context, *connect_go.Request[v1alpha1.TargetsRequest]) (*connect_go.Response[v1alpha1.TargetsResponse], error) {
return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("parca.scrape.v1alpha1.ScrapeService.Targets is not implemented"))
}
+114
View File
@@ -0,0 +1,114 @@
package parca
import (
"context"
"github.com/bufbuild/connect-go"
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana-plugin-sdk-go/backend/instancemgmt"
"github.com/grafana/grafana/pkg/infra/httpclient"
"github.com/grafana/grafana/pkg/tsdb/parca/gen/parca/parca/query/v1alpha1/queryv1alpha1connect"
v1alpha1 "github.com/parca-dev/parca/gen/proto/go/parca/query/v1alpha1"
)
// Make sure ParcaDatasource implements required interfaces. This is important to do
// since otherwise we will only get a not implemented error response from plugin in
// runtime. In this example datasource instance implements backend.QueryDataHandler,
// backend.CheckHealthHandler, backend.StreamHandler interfaces. Plugin should not
// implement all these interfaces - only those which are required for a particular task.
// For example if plugin does not need streaming functionality then you are free to remove
// methods that implement backend.StreamHandler. Implementing instancemgmt.InstanceDisposer
// is useful to clean up resources used by previous datasource instance when a new datasource
// instance created upon datasource settings changed.
var (
_ backend.QueryDataHandler = (*ParcaDatasource)(nil)
_ backend.CallResourceHandler = (*ParcaDatasource)(nil)
_ backend.CheckHealthHandler = (*ParcaDatasource)(nil)
)
// ParcaDatasource is a datasource for querying application performance profiles.
type ParcaDatasource struct {
client queryv1alpha1connect.QueryServiceClient
}
// NewParcaDatasource creates a new datasource instance.
func NewParcaDatasource(httpClientProvider httpclient.Provider, settings backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) {
opt, err := settings.HTTPClientOptions()
if err != nil {
return nil, err
}
httpClient, err := httpClientProvider.New(opt)
if err != nil {
return nil, err
}
return &ParcaDatasource{
client: queryv1alpha1connect.NewQueryServiceClient(httpClient, settings.URL, connect.WithGRPCWeb()),
}, nil
}
// Dispose here tells plugin SDK that plugin wants to clean up resources when a new instance
// created. As soon as datasource settings change detected by SDK old datasource instance will
// be disposed and a new one will be created using NewSampleDatasource factory function.
func (d *ParcaDatasource) Dispose() {
// Clean up datasource instance resources.
}
func (d *ParcaDatasource) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
logger.Debug("CallResource", "Path", req.Path, "Method", req.Method, "Body", req.Body)
if req.Path == "profileTypes" {
return d.callProfileTypes(ctx, req, sender)
}
if req.Path == "labelNames" {
return d.callLabelNames(ctx, req, sender)
}
if req.Path == "labelValues" {
return d.callLabelValues(ctx, req, sender)
}
return sender.Send(&backend.CallResourceResponse{
Status: 404,
})
}
// QueryData handles multiple queries and returns multiple responses.
// req contains the queries []DataQuery (where each query contains RefID as a unique identifier).
// The QueryDataResponse contains a map of RefID to the response for each query, and each response
// contains Frames ([]*Frame).
func (d *ParcaDatasource) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
logger.Debug("QueryData called", "queries", req.Queries)
// create response struct
response := backend.NewQueryDataResponse()
// loop over queries and execute them individually.
for _, q := range req.Queries {
res := d.query(ctx, req.PluginContext, q)
// save the response in a hashmap
// based on with RefID as identifier
response.Responses[q.RefID] = res
}
return response, nil
}
// CheckHealth handles health checks sent from Grafana to the plugin.
// The main use case for these health checks is the test button on the
// datasource configuration page which allows users to verify that
// a datasource is working as expected.
func (d *ParcaDatasource) CheckHealth(ctx context.Context, _ *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) {
logger.Debug("CheckHealth called")
status := backend.HealthStatusOk
message := "Data source is working"
if _, err := d.client.ProfileTypes(ctx, connect.NewRequest(&v1alpha1.ProfileTypesRequest{})); err != nil {
status = backend.HealthStatusError
message = err.Error()
}
return &backend.CheckHealthResult{
Status: status,
Message: message,
}, nil
}
+67
View File
@@ -0,0 +1,67 @@
package parca
import (
"context"
"testing"
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/stretchr/testify/require"
)
// This is where the tests for the datasource backend live.
func Test_QueryData(t *testing.T) {
ds := ParcaDatasource{}
resp, err := ds.QueryData(
context.Background(),
&backend.QueryDataRequest{
Queries: []backend.DataQuery{
{
RefID: "A",
QueryType: "profile",
},
},
},
)
if err != nil {
t.Error(err)
}
if len(resp.Responses) != 1 {
t.Fatal("QueryData must return a response")
}
}
func Test_CallResource(t *testing.T) {
ds := &ParcaDatasource{
client: &FakeClient{},
}
t.Run("labels resource", func(t *testing.T) {
sender := &FakeSender{}
err := ds.CallResource(
context.Background(),
&backend.CallResourceRequest{
PluginContext: backend.PluginContext{},
Path: "labelNames",
Method: "GET",
URL: "labelNames",
Headers: nil,
Body: nil,
},
sender,
)
require.NoError(t, err)
require.Equal(t, 200, sender.Resp.Status)
require.Equal(t, `["instance","job"]`, string(sender.Resp.Body))
})
}
type FakeSender struct {
Resp *backend.CallResourceResponse
}
func (fs *FakeSender) Send(resp *backend.CallResourceResponse) error {
fs.Resp = resp
return nil
}
+246
View File
@@ -0,0 +1,246 @@
package parca
import (
"context"
"encoding/json"
"fmt"
"strings"
"time"
"github.com/bufbuild/connect-go"
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana-plugin-sdk-go/data"
v1alpha1 "github.com/parca-dev/parca/gen/proto/go/parca/query/v1alpha1"
"google.golang.org/protobuf/types/known/timestamppb"
)
type queryModel struct {
ProfileTypeID string `json:"profileTypeId"`
LabelSelector string `json:"labelSelector"`
}
// These constants need to match the ones in the frontend.
const queryTypeProfile = "profile"
const queryTypeMetrics = "metrics"
const queryTypeBoth = "both"
// query processes single Fire query transforming the response to data.Frame packaged in DataResponse
func (d *ParcaDatasource) query(ctx context.Context, pCtx backend.PluginContext, query backend.DataQuery) backend.DataResponse {
var qm queryModel
response := backend.DataResponse{}
err := json.Unmarshal(query.JSON, &qm)
if err != nil {
response.Error = err
return response
}
if query.QueryType == queryTypeMetrics || query.QueryType == queryTypeBoth {
seriesResp, err := d.client.QueryRange(ctx, makeMetricRequest(qm, query))
if err != nil {
response.Error = err
return response
}
response.Frames = append(response.Frames, seriesToDataFrame(seriesResp, qm.ProfileTypeID)...)
}
if query.QueryType == queryTypeProfile || query.QueryType == queryTypeBoth {
logger.Debug("Querying SelectMergeStacktraces()", "queryModel", qm)
resp, err := d.client.Query(ctx, makeProfileRequest(qm, query))
if err != nil {
response.Error = err
return response
}
frame := responseToDataFrames(resp)
response.Frames = append(response.Frames, frame)
}
return response
}
func makeProfileRequest(qm queryModel, query backend.DataQuery) *connect.Request[v1alpha1.QueryRequest] {
return &connect.Request[v1alpha1.QueryRequest]{
Msg: &v1alpha1.QueryRequest{
Mode: v1alpha1.QueryRequest_MODE_MERGE,
Options: &v1alpha1.QueryRequest_Merge{
Merge: &v1alpha1.MergeProfile{
Query: fmt.Sprintf("%s%s", qm.ProfileTypeID, qm.LabelSelector),
Start: &timestamppb.Timestamp{
Seconds: query.TimeRange.From.Unix(),
},
End: &timestamppb.Timestamp{
Seconds: query.TimeRange.To.Unix(),
},
},
},
ReportType: v1alpha1.QueryRequest_REPORT_TYPE_FLAMEGRAPH_UNSPECIFIED,
},
}
}
func makeMetricRequest(qm queryModel, query backend.DataQuery) *connect.Request[v1alpha1.QueryRangeRequest] {
return &connect.Request[v1alpha1.QueryRangeRequest]{
Msg: &v1alpha1.QueryRangeRequest{
Query: fmt.Sprintf("%s%s", qm.ProfileTypeID, qm.LabelSelector),
Start: &timestamppb.Timestamp{
Seconds: query.TimeRange.From.Unix(),
},
End: &timestamppb.Timestamp{
Seconds: query.TimeRange.To.Unix(),
},
Limit: uint32(query.MaxDataPoints),
},
}
}
type CustomMeta struct {
ProfileTypeID string
}
// responseToDataFrames turns fire response to data.Frame. We encode the data into a nested set format where we have
// [level, value, label] columns and by ordering the items in a depth first traversal order we can recreate the whole
// tree back.
func responseToDataFrames(resp *connect.Response[v1alpha1.QueryResponse]) *data.Frame {
if flameResponse, ok := resp.Msg.Report.(*v1alpha1.QueryResponse_Flamegraph); ok {
frame := treeToNestedSetDataFrame(flameResponse.Flamegraph)
frame.Meta = &data.FrameMeta{PreferredVisualization: "flamegraph"}
return frame
} else {
panic("unknown report type returned from query")
}
}
// treeToNestedSetDataFrame walks the tree depth first and adds items into the dataframe. This is a nested set format
// where by ordering the items in depth first order and knowing the level/depth of each item we can recreate the
// parent - child relationship without explicitly needing parent/child column and we can later just iterate over the
// dataFrame to again basically walking depth first over the tree/profile.
func treeToNestedSetDataFrame(tree *v1alpha1.Flamegraph) *data.Frame {
frame := data.NewFrame("response")
levelField := data.NewField("level", nil, []int64{})
valueField := data.NewField("value", nil, []int64{})
valueField.Config = &data.FieldConfig{Unit: normalizeUnit(tree.Unit)}
selfField := data.NewField("self", nil, []int64{})
selfField.Config = &data.FieldConfig{Unit: normalizeUnit(tree.Unit)}
labelField := data.NewField("label", nil, []string{})
frame.Fields = data.Fields{levelField, valueField, selfField, labelField}
walkTree(tree.Root, func(level int64, value int64, name string, self int64) {
levelField.Append(level)
valueField.Append(value)
labelField.Append(name)
selfField.Append(self)
})
return frame
}
type Node struct {
Node *v1alpha1.FlamegraphNode
Level int64
}
func walkTree(tree *v1alpha1.FlamegraphRootNode, fn func(level int64, value int64, name string, self int64)) {
var stack []*Node
var childrenValue int64 = 0
for _, child := range tree.Children {
childrenValue += child.Cumulative
stack = append(stack, &Node{Node: child, Level: 1})
}
fn(0, tree.Cumulative, "total", tree.Cumulative-childrenValue)
for {
if len(stack) == 0 {
break
}
// shift stack
node := stack[0]
stack = stack[1:]
childrenValue = 0
if node.Node.Children != nil {
var children []*Node
for _, child := range node.Node.Children {
childrenValue += child.Cumulative
children = append(children, &Node{Node: child, Level: node.Level + 1})
}
// Put the children first so we do depth first traversal
stack = append(children, stack...)
}
fn(node.Level, node.Node.Cumulative, nodeName(node.Node), node.Node.Cumulative-childrenValue)
}
}
func nodeName(node *v1alpha1.FlamegraphNode) string {
if node.Meta == nil {
return "<unknown>"
}
mapping := ""
if node.Meta.Mapping != nil && node.Meta.Mapping.File != "" {
mapping = "[" + getLastItem(node.Meta.Mapping.File) + "] "
}
if node.Meta.Function != nil && node.Meta.Function.Name != "" {
return mapping + node.Meta.Function.Name
}
address := ""
if node.Meta.Location != nil {
address = fmt.Sprintf("0x%x", node.Meta.Location.Address)
}
if mapping == "" && address == "" {
return "<unknown>"
} else {
return mapping + address
}
}
func getLastItem(path string) string {
parts := strings.Split(path, "/")
return parts[len(parts)-1]
}
func normalizeUnit(unit string) string {
if unit == "nanoseconds" {
return "ns"
}
if unit == "count" {
return "short"
}
return unit
}
func seriesToDataFrame(seriesResp *connect.Response[v1alpha1.QueryRangeResponse], profileTypeID string) []*data.Frame {
var frames []*data.Frame
for _, series := range seriesResp.Msg.Series {
frame := data.NewFrame("series")
frame.Meta = &data.FrameMeta{PreferredVisualization: "graph"}
frames = append(frames, frame)
fields := data.Fields{}
timeField := data.NewField("time", nil, []time.Time{})
fields = append(fields, timeField)
labels := data.Labels{}
for _, label := range series.Labelset.Labels {
labels[label.Name] = label.Value
}
valueField := data.NewField(strings.Split(profileTypeID, ":")[1], labels, []int64{})
for _, sample := range series.Samples {
timeField.Append(sample.Timestamp.AsTime())
valueField.Append(sample.Value)
}
fields = append(fields, valueField)
frame.Fields = fields
}
return frames
}
+217
View File
@@ -0,0 +1,217 @@
package parca
import (
"context"
"testing"
"time"
"github.com/bufbuild/connect-go"
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana-plugin-sdk-go/data"
v1alpha11 "github.com/parca-dev/parca/gen/proto/go/parca/metastore/v1alpha1"
profilestore "github.com/parca-dev/parca/gen/proto/go/parca/profilestore/v1alpha1"
v1alpha1 "github.com/parca-dev/parca/gen/proto/go/parca/query/v1alpha1"
"github.com/stretchr/testify/require"
"google.golang.org/protobuf/types/known/timestamppb"
)
// This is where the tests for the datasource backend live.
func Test_query(t *testing.T) {
ds := &ParcaDatasource{
client: &FakeClient{},
}
dataQuery := backend.DataQuery{
RefID: "A",
QueryType: queryTypeBoth,
MaxDataPoints: 0,
Interval: 0,
TimeRange: backend.TimeRange{
From: time.UnixMilli(10000),
To: time.UnixMilli(20000),
},
JSON: []byte(`{"profileTypeId":"foo:bar","labelSelector":"{app=\\\"baz\\\"}"}`),
}
t.Run("query both", func(t *testing.T) {
resp := ds.query(context.Background(), backend.PluginContext{}, dataQuery)
require.Nil(t, resp.Error)
require.Equal(t, 2, len(resp.Frames))
require.Equal(t, "time", resp.Frames[0].Fields[0].Name)
require.Equal(t, data.NewField("level", nil, []int64{0, 1, 2, 3}), resp.Frames[1].Fields[0])
})
t.Run("query profile", func(t *testing.T) {
dataQuery.QueryType = queryTypeProfile
resp := ds.query(context.Background(), backend.PluginContext{}, dataQuery)
require.Nil(t, resp.Error)
require.Equal(t, 1, len(resp.Frames))
require.Equal(t, data.NewField("level", nil, []int64{0, 1, 2, 3}), resp.Frames[0].Fields[0])
})
t.Run("query metrics", func(t *testing.T) {
dataQuery.QueryType = queryTypeMetrics
resp := ds.query(context.Background(), backend.PluginContext{}, dataQuery)
require.Nil(t, resp.Error)
require.Equal(t, 1, len(resp.Frames))
require.Equal(t, "time", resp.Frames[0].Fields[0].Name)
})
}
// This is where the tests for the datasource backend live.
func Test_profileToDataFrame(t *testing.T) {
frame := responseToDataFrames(flamegraphResponse)
require.Equal(t, 4, len(frame.Fields))
require.Equal(t, data.NewField("level", nil, []int64{0, 1, 2, 3}), frame.Fields[0])
values := data.NewField("value", nil, []int64{100, 10, 9, 8})
values.Config = &data.FieldConfig{
Unit: "samples",
}
require.Equal(t, values, frame.Fields[1])
self := data.NewField("self", nil, []int64{90, 1, 1, 8})
self.Config = &data.FieldConfig{
Unit: "samples",
}
require.Equal(t, self, frame.Fields[2])
require.Equal(t, data.NewField("label", nil, []string{"total", "foo", "bar", "baz"}), frame.Fields[3])
}
func Test_seriesToDataFrame(t *testing.T) {
frames := seriesToDataFrame(rangeResponse, "process_cpu:samples:count:cpu:nanoseconds")
require.Equal(t, 1, len(frames))
require.Equal(t, 2, len(frames[0].Fields))
require.Equal(t, data.NewField("time", nil, []time.Time{time.UnixMilli(1000 * 10).UTC(), time.UnixMilli(1000 * 20).UTC()}), frames[0].Fields[0])
require.Equal(t, data.NewField("samples", map[string]string{"foo": "bar"}, []int64{30, 10}), frames[0].Fields[1])
}
var rangeResponse = &connect.Response[v1alpha1.QueryRangeResponse]{
Msg: &v1alpha1.QueryRangeResponse{
Series: []*v1alpha1.MetricsSeries{
{
Labelset: &profilestore.LabelSet{
Labels: []*profilestore.Label{
{
Name: "foo",
Value: "bar",
},
},
},
Samples: []*v1alpha1.MetricsSample{
{
Timestamp: &timestamppb.Timestamp{
Seconds: 10,
Nanos: 0,
},
Value: 30,
},
{
Timestamp: &timestamppb.Timestamp{
Seconds: 20,
Nanos: 0,
},
Value: 10,
},
},
PeriodType: nil,
SampleType: nil,
},
},
},
}
var flamegraphResponse = &connect.Response[v1alpha1.QueryResponse]{
Msg: &v1alpha1.QueryResponse{
Report: &v1alpha1.QueryResponse_Flamegraph{
Flamegraph: &v1alpha1.Flamegraph{
Root: &v1alpha1.FlamegraphRootNode{
Cumulative: 100,
Diff: 0,
Children: []*v1alpha1.FlamegraphNode{
{
Meta: &v1alpha1.FlamegraphNodeMeta{
Function: &v1alpha11.Function{
Name: "foo",
},
},
Cumulative: 10,
Diff: 0,
Children: []*v1alpha1.FlamegraphNode{
{
Meta: &v1alpha1.FlamegraphNodeMeta{
Function: &v1alpha11.Function{
Name: "bar",
},
},
Cumulative: 9,
Diff: 0,
Children: []*v1alpha1.FlamegraphNode{
{
Meta: &v1alpha1.FlamegraphNodeMeta{
Function: &v1alpha11.Function{
Name: "baz",
},
},
Cumulative: 8,
Diff: 0,
},
},
},
},
},
},
},
Total: 100,
Unit: "samples",
Height: 3,
},
},
},
}
type FakeClient struct {
Req *connect.Request[v1alpha1.QueryRequest]
}
func (f *FakeClient) QueryRange(ctx context.Context, c *connect.Request[v1alpha1.QueryRangeRequest]) (*connect.Response[v1alpha1.QueryRangeResponse], error) {
return rangeResponse, nil
}
func (f *FakeClient) Query(ctx context.Context, c *connect.Request[v1alpha1.QueryRequest]) (*connect.Response[v1alpha1.QueryResponse], error) {
f.Req = c
return flamegraphResponse, nil
}
func (f *FakeClient) Series(ctx context.Context, c *connect.Request[v1alpha1.SeriesRequest]) (*connect.Response[v1alpha1.SeriesResponse], error) {
//TODO implement me
panic("implement me")
}
func (f *FakeClient) ProfileTypes(ctx context.Context, c *connect.Request[v1alpha1.ProfileTypesRequest]) (*connect.Response[v1alpha1.ProfileTypesResponse], error) {
//TODO implement me
panic("implement me")
}
func (f *FakeClient) Labels(ctx context.Context, c *connect.Request[v1alpha1.LabelsRequest]) (*connect.Response[v1alpha1.LabelsResponse], error) {
return &connect.Response[v1alpha1.LabelsResponse]{
Msg: &v1alpha1.LabelsResponse{
LabelNames: []string{"instance", "job"},
Warnings: nil,
},
}, nil
}
func (f *FakeClient) Values(ctx context.Context, c *connect.Request[v1alpha1.ValuesRequest]) (*connect.Response[v1alpha1.ValuesResponse], error) {
return &connect.Response[v1alpha1.ValuesResponse]{
Msg: &v1alpha1.ValuesResponse{
LabelValues: []string{"foo", "bar"},
Warnings: nil,
},
}, nil
}
func (f *FakeClient) ShareProfile(ctx context.Context, c *connect.Request[v1alpha1.ShareProfileRequest]) (*connect.Response[v1alpha1.ShareProfileResponse], error) {
//TODO implement me
panic("implement me")
}
+101
View File
@@ -0,0 +1,101 @@
package parca
import (
"context"
"encoding/json"
"fmt"
"net/url"
"github.com/bufbuild/connect-go"
"github.com/grafana/grafana-plugin-sdk-go/backend"
v1alpha1 "github.com/parca-dev/parca/gen/proto/go/parca/query/v1alpha1"
)
type ProfileType struct {
// Same as *v1alpha1.ProfileType just added the ID
Name string `json:"name,omitempty"`
SampleType string `json:"sample_type,omitempty"`
SampleUnit string `json:"sample_unit,omitempty"`
PeriodType string `json:"period_type,omitempty"`
PeriodUnit string `json:"period_unit,omitempty"`
Delta bool `json:"delta,omitempty"`
ID string `json:"ID,omitempty"`
}
func (d *ParcaDatasource) callProfileTypes(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
res, err := d.client.ProfileTypes(ctx, connect.NewRequest(&v1alpha1.ProfileTypesRequest{}))
if err != nil {
return err
}
var types []*ProfileType
for _, t := range res.Msg.Types {
var id string
if t.Delta {
id = fmt.Sprintf("%s:%s:%s:%s:%s:delta", t.Name, t.SampleType, t.SampleUnit, t.PeriodType, t.PeriodUnit)
} else {
id = fmt.Sprintf("%s:%s:%s:%s:%s", t.Name, t.SampleType, t.SampleUnit, t.PeriodType, t.PeriodUnit)
}
types = append(types, &ProfileType{
Name: t.Name,
SampleType: t.SampleType,
SampleUnit: t.SampleUnit,
PeriodType: t.PeriodType,
PeriodUnit: t.PeriodUnit,
Delta: t.Delta,
ID: id,
})
}
data, err := json.Marshal(types)
if err != nil {
return err
}
err = sender.Send(&backend.CallResourceResponse{Body: data, Headers: req.Headers, Status: 200})
if err != nil {
return err
}
return nil
}
func (d *ParcaDatasource) callLabelNames(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
res, err := d.client.Labels(ctx, connect.NewRequest(&v1alpha1.LabelsRequest{}))
if err != nil {
return err
}
data, err := json.Marshal(res.Msg.LabelNames)
if err != nil {
return err
}
err = sender.Send(&backend.CallResourceResponse{Body: data, Headers: req.Headers, Status: 200})
if err != nil {
return err
}
return nil
}
func (d *ParcaDatasource) callLabelValues(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
parsedUrl, err := url.Parse(req.URL)
if err != nil {
return err
}
label, ok := parsedUrl.Query()["label"]
if !ok {
label = []string{""}
}
res, err := d.client.Values(ctx, connect.NewRequest(&v1alpha1.ValuesRequest{LabelName: label[0]}))
if err != nil {
return err
}
data, err := json.Marshal(res.Msg.LabelValues)
if err != nil {
return err
}
err = sender.Send(&backend.CallResourceResponse{Body: data, Headers: req.Headers, Status: 200})
if err != nil {
return err
}
return nil
}
+77
View File
@@ -0,0 +1,77 @@
package parca
import (
"context"
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana-plugin-sdk-go/backend/datasource"
"github.com/grafana/grafana-plugin-sdk-go/backend/instancemgmt"
"github.com/grafana/grafana/pkg/infra/httpclient"
"github.com/grafana/grafana/pkg/infra/log"
)
// Make sure FireDatasource implements required interfaces. This is important to do
// since otherwise we will only get a not implemented error response from plugin in
// runtime. In this example datasource instance implements backend.QueryDataHandler,
// backend.CheckHealthHandler, backend.StreamHandler interfaces. Plugin should not
// implement all these interfaces - only those which are required for a particular task.
// For example if plugin does not need streaming functionality then you are free to remove
// methods that implement backend.StreamHandler. Implementing instancemgmt.InstanceDisposer
// is useful to clean up resources used by previous datasource instance when a new datasource
// instance created upon datasource settings changed.
var (
_ backend.QueryDataHandler = (*Service)(nil)
_ backend.CallResourceHandler = (*Service)(nil)
_ backend.CheckHealthHandler = (*Service)(nil)
)
var logger = log.New("tsdb.parca")
type Service struct {
im instancemgmt.InstanceManager
}
func (s *Service) getInstance(pluginCtx backend.PluginContext) (*ParcaDatasource, error) {
i, err := s.im.Get(pluginCtx)
if err != nil {
return nil, err
}
in := i.(*ParcaDatasource)
return in, nil
}
func ProvideService(httpClientProvider httpclient.Provider) *Service {
return &Service{
im: datasource.NewInstanceManager(newInstanceSettings(httpClientProvider)),
}
}
func newInstanceSettings(httpClientProvider httpclient.Provider) datasource.InstanceFactoryFunc {
return func(settings backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) {
return NewParcaDatasource(httpClientProvider, settings)
}
}
func (s *Service) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
i, err := s.getInstance(req.PluginContext)
if err != nil {
return nil, err
}
return i.QueryData(ctx, req)
}
func (s *Service) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
i, err := s.getInstance(req.PluginContext)
if err != nil {
return err
}
return i.CallResource(ctx, req, sender)
}
func (s *Service) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) {
i, err := s.getInstance(req.PluginContext)
if err != nil {
return nil, err
}
return i.CheckHealth(ctx, req)
}
+486
View File
@@ -0,0 +1,486 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.28.0
// protoc (unknown)
// source: common/v1/common.proto
package commonv1
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
type LabelPair struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"`
}
func (x *LabelPair) Reset() {
*x = LabelPair{}
if protoimpl.UnsafeEnabled {
mi := &file_common_v1_common_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *LabelPair) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*LabelPair) ProtoMessage() {}
func (x *LabelPair) ProtoReflect() protoreflect.Message {
mi := &file_common_v1_common_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use LabelPair.ProtoReflect.Descriptor instead.
func (*LabelPair) Descriptor() ([]byte, []int) {
return file_common_v1_common_proto_rawDescGZIP(), []int{0}
}
func (x *LabelPair) GetName() string {
if x != nil {
return x.Name
}
return ""
}
func (x *LabelPair) GetValue() string {
if x != nil {
return x.Value
}
return ""
}
type ProfileType struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
ID string `protobuf:"bytes,1,opt,name=ID,proto3" json:"ID,omitempty"`
Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
SampleType string `protobuf:"bytes,4,opt,name=sample_type,json=sampleType,proto3" json:"sample_type,omitempty"`
SampleUnit string `protobuf:"bytes,5,opt,name=sample_unit,json=sampleUnit,proto3" json:"sample_unit,omitempty"`
PeriodType string `protobuf:"bytes,6,opt,name=period_type,json=periodType,proto3" json:"period_type,omitempty"`
PeriodUnit string `protobuf:"bytes,7,opt,name=period_unit,json=periodUnit,proto3" json:"period_unit,omitempty"`
}
func (x *ProfileType) Reset() {
*x = ProfileType{}
if protoimpl.UnsafeEnabled {
mi := &file_common_v1_common_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *ProfileType) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ProfileType) ProtoMessage() {}
func (x *ProfileType) ProtoReflect() protoreflect.Message {
mi := &file_common_v1_common_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ProfileType.ProtoReflect.Descriptor instead.
func (*ProfileType) Descriptor() ([]byte, []int) {
return file_common_v1_common_proto_rawDescGZIP(), []int{1}
}
func (x *ProfileType) GetID() string {
if x != nil {
return x.ID
}
return ""
}
func (x *ProfileType) GetName() string {
if x != nil {
return x.Name
}
return ""
}
func (x *ProfileType) GetSampleType() string {
if x != nil {
return x.SampleType
}
return ""
}
func (x *ProfileType) GetSampleUnit() string {
if x != nil {
return x.SampleUnit
}
return ""
}
func (x *ProfileType) GetPeriodType() string {
if x != nil {
return x.PeriodType
}
return ""
}
func (x *ProfileType) GetPeriodUnit() string {
if x != nil {
return x.PeriodUnit
}
return ""
}
type Labels struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// LabelPair is the key value pairs to identify the corresponding profile
Labels []*LabelPair `protobuf:"bytes,1,rep,name=labels,proto3" json:"labels,omitempty"`
}
func (x *Labels) Reset() {
*x = Labels{}
if protoimpl.UnsafeEnabled {
mi := &file_common_v1_common_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Labels) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Labels) ProtoMessage() {}
func (x *Labels) ProtoReflect() protoreflect.Message {
mi := &file_common_v1_common_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Labels.ProtoReflect.Descriptor instead.
func (*Labels) Descriptor() ([]byte, []int) {
return file_common_v1_common_proto_rawDescGZIP(), []int{2}
}
func (x *Labels) GetLabels() []*LabelPair {
if x != nil {
return x.Labels
}
return nil
}
type Series struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Labels []*LabelPair `protobuf:"bytes,1,rep,name=labels,proto3" json:"labels,omitempty"`
Points []*Point `protobuf:"bytes,2,rep,name=points,proto3" json:"points,omitempty"`
}
func (x *Series) Reset() {
*x = Series{}
if protoimpl.UnsafeEnabled {
mi := &file_common_v1_common_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Series) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Series) ProtoMessage() {}
func (x *Series) ProtoReflect() protoreflect.Message {
mi := &file_common_v1_common_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Series.ProtoReflect.Descriptor instead.
func (*Series) Descriptor() ([]byte, []int) {
return file_common_v1_common_proto_rawDescGZIP(), []int{3}
}
func (x *Series) GetLabels() []*LabelPair {
if x != nil {
return x.Labels
}
return nil
}
func (x *Series) GetPoints() []*Point {
if x != nil {
return x.Points
}
return nil
}
type Point struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Value float64 `protobuf:"fixed64,1,opt,name=value,proto3" json:"value,omitempty"`
// Milliseconds unix timestamp
Timestamp int64 `protobuf:"varint,2,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
}
func (x *Point) Reset() {
*x = Point{}
if protoimpl.UnsafeEnabled {
mi := &file_common_v1_common_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Point) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Point) ProtoMessage() {}
func (x *Point) ProtoReflect() protoreflect.Message {
mi := &file_common_v1_common_proto_msgTypes[4]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Point.ProtoReflect.Descriptor instead.
func (*Point) Descriptor() ([]byte, []int) {
return file_common_v1_common_proto_rawDescGZIP(), []int{4}
}
func (x *Point) GetValue() float64 {
if x != nil {
return x.Value
}
return 0
}
func (x *Point) GetTimestamp() int64 {
if x != nil {
return x.Timestamp
}
return 0
}
var File_common_v1_common_proto protoreflect.FileDescriptor
var file_common_v1_common_proto_rawDesc = []byte{
0x0a, 0x16, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x6f, 0x6d, 0x6d,
0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x09, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e,
0x2e, 0x76, 0x31, 0x22, 0x35, 0x0a, 0x09, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x50, 0x61, 0x69, 0x72,
0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04,
0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20,
0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xb5, 0x01, 0x0a, 0x0b, 0x50,
0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x49, 0x44,
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x49, 0x44, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61,
0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1f,
0x0a, 0x0b, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20,
0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12,
0x1f, 0x0a, 0x0b, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x5f, 0x75, 0x6e, 0x69, 0x74, 0x18, 0x05,
0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x55, 0x6e, 0x69, 0x74,
0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18,
0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x54, 0x79, 0x70,
0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x5f, 0x75, 0x6e, 0x69, 0x74,
0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x55, 0x6e,
0x69, 0x74, 0x22, 0x36, 0x0a, 0x06, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x12, 0x2c, 0x0a, 0x06,
0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x63,
0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x50, 0x61,
0x69, 0x72, 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x22, 0x60, 0x0a, 0x06, 0x53, 0x65,
0x72, 0x69, 0x65, 0x73, 0x12, 0x2c, 0x0a, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x01,
0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31,
0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x50, 0x61, 0x69, 0x72, 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65,
0x6c, 0x73, 0x12, 0x28, 0x0a, 0x06, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03,
0x28, 0x0b, 0x32, 0x10, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x50,
0x6f, 0x69, 0x6e, 0x74, 0x52, 0x06, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x22, 0x3b, 0x0a, 0x05,
0x50, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01,
0x20, 0x01, 0x28, 0x01, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 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, 0x42, 0x95, 0x01, 0x0a, 0x0d, 0x63, 0x6f,
0x6d, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x42, 0x0b, 0x43, 0x6f, 0x6d,
0x6d, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x32, 0x67, 0x69, 0x74, 0x68,
0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x72, 0x61, 0x66, 0x61, 0x6e, 0x61, 0x2f, 0x66,
0x69, 0x72, 0x65, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x63, 0x6f, 0x6d, 0x6d,
0x6f, 0x6e, 0x2f, 0x76, 0x31, 0x3b, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x76, 0x31, 0xa2, 0x02,
0x03, 0x43, 0x58, 0x58, 0xaa, 0x02, 0x09, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x56, 0x31,
0xca, 0x02, 0x09, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x15, 0x43,
0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61,
0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x0a, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x3a, 0x3a, 0x56,
0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
file_common_v1_common_proto_rawDescOnce sync.Once
file_common_v1_common_proto_rawDescData = file_common_v1_common_proto_rawDesc
)
func file_common_v1_common_proto_rawDescGZIP() []byte {
file_common_v1_common_proto_rawDescOnce.Do(func() {
file_common_v1_common_proto_rawDescData = protoimpl.X.CompressGZIP(file_common_v1_common_proto_rawDescData)
})
return file_common_v1_common_proto_rawDescData
}
var file_common_v1_common_proto_msgTypes = make([]protoimpl.MessageInfo, 5)
var file_common_v1_common_proto_goTypes = []interface{}{
(*LabelPair)(nil), // 0: common.v1.LabelPair
(*ProfileType)(nil), // 1: common.v1.ProfileType
(*Labels)(nil), // 2: common.v1.Labels
(*Series)(nil), // 3: common.v1.Series
(*Point)(nil), // 4: common.v1.Point
}
var file_common_v1_common_proto_depIdxs = []int32{
0, // 0: common.v1.Labels.labels:type_name -> common.v1.LabelPair
0, // 1: common.v1.Series.labels:type_name -> common.v1.LabelPair
4, // 2: common.v1.Series.points:type_name -> common.v1.Point
3, // [3:3] is the sub-list for method output_type
3, // [3:3] is the sub-list for method input_type
3, // [3:3] is the sub-list for extension type_name
3, // [3:3] is the sub-list for extension extendee
0, // [0:3] is the sub-list for field type_name
}
func init() { file_common_v1_common_proto_init() }
func file_common_v1_common_proto_init() {
if File_common_v1_common_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_common_v1_common_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*LabelPair); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_common_v1_common_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ProfileType); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_common_v1_common_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Labels); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_common_v1_common_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Series); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_common_v1_common_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Point); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_common_v1_common_proto_rawDesc,
NumEnums: 0,
NumMessages: 5,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_common_v1_common_proto_goTypes,
DependencyIndexes: file_common_v1_common_proto_depIdxs,
MessageInfos: file_common_v1_common_proto_msgTypes,
}.Build()
File_common_v1_common_proto = out.File
file_common_v1_common_proto_rawDesc = nil
file_common_v1_common_proto_goTypes = nil
file_common_v1_common_proto_depIdxs = nil
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,196 @@
// Code generated by protoc-gen-connect-go. DO NOT EDIT.
//
// Source: querier/v1/querier.proto
package querierv1connect
import (
context "context"
errors "errors"
connect_go "github.com/bufbuild/connect-go"
v1 "github.com/grafana/grafana/pkg/tsdb/phlare/gen/querier/v1"
http "net/http"
strings "strings"
)
// This is a compile-time assertion to ensure that this generated file and the connect package are
// compatible. If you get a compiler error that this constant is not defined, this code was
// generated with a version of connect newer than the one compiled into your binary. You can fix the
// problem by either regenerating this code with an older version of connect or updating the connect
// version compiled into your binary.
const _ = connect_go.IsAtLeastVersion0_1_0
const (
// QuerierServiceName is the fully-qualified name of the QuerierService service.
QuerierServiceName = "querier.v1.QuerierService"
)
// QuerierServiceClient is a client for the querier.v1.QuerierService service.
type QuerierServiceClient interface {
ProfileTypes(context.Context, *connect_go.Request[v1.ProfileTypesRequest]) (*connect_go.Response[v1.ProfileTypesResponse], error)
LabelValues(context.Context, *connect_go.Request[v1.LabelValuesRequest]) (*connect_go.Response[v1.LabelValuesResponse], error)
LabelNames(context.Context, *connect_go.Request[v1.LabelNamesRequest]) (*connect_go.Response[v1.LabelNamesResponse], error)
Series(context.Context, *connect_go.Request[v1.SeriesRequest]) (*connect_go.Response[v1.SeriesResponse], error)
SelectMergeStacktraces(context.Context, *connect_go.Request[v1.SelectMergeStacktracesRequest]) (*connect_go.Response[v1.SelectMergeStacktracesResponse], error)
SelectSeries(context.Context, *connect_go.Request[v1.SelectSeriesRequest]) (*connect_go.Response[v1.SelectSeriesResponse], error)
}
// NewQuerierServiceClient constructs a client for the querier.v1.QuerierService service. By
// default, it uses the Connect protocol with the binary Protobuf Codec, asks for gzipped responses,
// and sends uncompressed requests. To use the gRPC or gRPC-Web protocols, supply the
// connect.WithGRPC() or connect.WithGRPCWeb() options.
//
// The URL supplied here should be the base URL for the Connect or gRPC server (for example,
// http://api.acme.com or https://acme.com/grpc).
func NewQuerierServiceClient(httpClient connect_go.HTTPClient, baseURL string, opts ...connect_go.ClientOption) QuerierServiceClient {
baseURL = strings.TrimRight(baseURL, "/")
return &querierServiceClient{
profileTypes: connect_go.NewClient[v1.ProfileTypesRequest, v1.ProfileTypesResponse](
httpClient,
baseURL+"/querier.v1.QuerierService/ProfileTypes",
opts...,
),
labelValues: connect_go.NewClient[v1.LabelValuesRequest, v1.LabelValuesResponse](
httpClient,
baseURL+"/querier.v1.QuerierService/LabelValues",
opts...,
),
labelNames: connect_go.NewClient[v1.LabelNamesRequest, v1.LabelNamesResponse](
httpClient,
baseURL+"/querier.v1.QuerierService/LabelNames",
opts...,
),
series: connect_go.NewClient[v1.SeriesRequest, v1.SeriesResponse](
httpClient,
baseURL+"/querier.v1.QuerierService/Series",
opts...,
),
selectMergeStacktraces: connect_go.NewClient[v1.SelectMergeStacktracesRequest, v1.SelectMergeStacktracesResponse](
httpClient,
baseURL+"/querier.v1.QuerierService/SelectMergeStacktraces",
opts...,
),
selectSeries: connect_go.NewClient[v1.SelectSeriesRequest, v1.SelectSeriesResponse](
httpClient,
baseURL+"/querier.v1.QuerierService/SelectSeries",
opts...,
),
}
}
// querierServiceClient implements QuerierServiceClient.
type querierServiceClient struct {
profileTypes *connect_go.Client[v1.ProfileTypesRequest, v1.ProfileTypesResponse]
labelValues *connect_go.Client[v1.LabelValuesRequest, v1.LabelValuesResponse]
labelNames *connect_go.Client[v1.LabelNamesRequest, v1.LabelNamesResponse]
series *connect_go.Client[v1.SeriesRequest, v1.SeriesResponse]
selectMergeStacktraces *connect_go.Client[v1.SelectMergeStacktracesRequest, v1.SelectMergeStacktracesResponse]
selectSeries *connect_go.Client[v1.SelectSeriesRequest, v1.SelectSeriesResponse]
}
// ProfileTypes calls querier.v1.QuerierService.ProfileTypes.
func (c *querierServiceClient) ProfileTypes(ctx context.Context, req *connect_go.Request[v1.ProfileTypesRequest]) (*connect_go.Response[v1.ProfileTypesResponse], error) {
return c.profileTypes.CallUnary(ctx, req)
}
// LabelValues calls querier.v1.QuerierService.LabelValues.
func (c *querierServiceClient) LabelValues(ctx context.Context, req *connect_go.Request[v1.LabelValuesRequest]) (*connect_go.Response[v1.LabelValuesResponse], error) {
return c.labelValues.CallUnary(ctx, req)
}
// LabelNames calls querier.v1.QuerierService.LabelNames.
func (c *querierServiceClient) LabelNames(ctx context.Context, req *connect_go.Request[v1.LabelNamesRequest]) (*connect_go.Response[v1.LabelNamesResponse], error) {
return c.labelNames.CallUnary(ctx, req)
}
// Series calls querier.v1.QuerierService.Series.
func (c *querierServiceClient) Series(ctx context.Context, req *connect_go.Request[v1.SeriesRequest]) (*connect_go.Response[v1.SeriesResponse], error) {
return c.series.CallUnary(ctx, req)
}
// SelectMergeStacktraces calls querier.v1.QuerierService.SelectMergeStacktraces.
func (c *querierServiceClient) SelectMergeStacktraces(ctx context.Context, req *connect_go.Request[v1.SelectMergeStacktracesRequest]) (*connect_go.Response[v1.SelectMergeStacktracesResponse], error) {
return c.selectMergeStacktraces.CallUnary(ctx, req)
}
// SelectSeries calls querier.v1.QuerierService.SelectSeries.
func (c *querierServiceClient) SelectSeries(ctx context.Context, req *connect_go.Request[v1.SelectSeriesRequest]) (*connect_go.Response[v1.SelectSeriesResponse], error) {
return c.selectSeries.CallUnary(ctx, req)
}
// QuerierServiceHandler is an implementation of the querier.v1.QuerierService service.
type QuerierServiceHandler interface {
ProfileTypes(context.Context, *connect_go.Request[v1.ProfileTypesRequest]) (*connect_go.Response[v1.ProfileTypesResponse], error)
LabelValues(context.Context, *connect_go.Request[v1.LabelValuesRequest]) (*connect_go.Response[v1.LabelValuesResponse], error)
LabelNames(context.Context, *connect_go.Request[v1.LabelNamesRequest]) (*connect_go.Response[v1.LabelNamesResponse], error)
Series(context.Context, *connect_go.Request[v1.SeriesRequest]) (*connect_go.Response[v1.SeriesResponse], error)
SelectMergeStacktraces(context.Context, *connect_go.Request[v1.SelectMergeStacktracesRequest]) (*connect_go.Response[v1.SelectMergeStacktracesResponse], error)
SelectSeries(context.Context, *connect_go.Request[v1.SelectSeriesRequest]) (*connect_go.Response[v1.SelectSeriesResponse], error)
}
// NewQuerierServiceHandler builds an HTTP handler from the service implementation. It returns the
// path on which to mount the handler and the handler itself.
//
// By default, handlers support the Connect, gRPC, and gRPC-Web protocols with the binary Protobuf
// and JSON codecs. They also support gzip compression.
func NewQuerierServiceHandler(svc QuerierServiceHandler, opts ...connect_go.HandlerOption) (string, http.Handler) {
mux := http.NewServeMux()
mux.Handle("/querier.v1.QuerierService/ProfileTypes", connect_go.NewUnaryHandler(
"/querier.v1.QuerierService/ProfileTypes",
svc.ProfileTypes,
opts...,
))
mux.Handle("/querier.v1.QuerierService/LabelValues", connect_go.NewUnaryHandler(
"/querier.v1.QuerierService/LabelValues",
svc.LabelValues,
opts...,
))
mux.Handle("/querier.v1.QuerierService/LabelNames", connect_go.NewUnaryHandler(
"/querier.v1.QuerierService/LabelNames",
svc.LabelNames,
opts...,
))
mux.Handle("/querier.v1.QuerierService/Series", connect_go.NewUnaryHandler(
"/querier.v1.QuerierService/Series",
svc.Series,
opts...,
))
mux.Handle("/querier.v1.QuerierService/SelectMergeStacktraces", connect_go.NewUnaryHandler(
"/querier.v1.QuerierService/SelectMergeStacktraces",
svc.SelectMergeStacktraces,
opts...,
))
mux.Handle("/querier.v1.QuerierService/SelectSeries", connect_go.NewUnaryHandler(
"/querier.v1.QuerierService/SelectSeries",
svc.SelectSeries,
opts...,
))
return "/querier.v1.QuerierService/", mux
}
// UnimplementedQuerierServiceHandler returns CodeUnimplemented from all methods.
type UnimplementedQuerierServiceHandler struct{}
func (UnimplementedQuerierServiceHandler) ProfileTypes(context.Context, *connect_go.Request[v1.ProfileTypesRequest]) (*connect_go.Response[v1.ProfileTypesResponse], error) {
return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("querier.v1.QuerierService.ProfileTypes is not implemented"))
}
func (UnimplementedQuerierServiceHandler) LabelValues(context.Context, *connect_go.Request[v1.LabelValuesRequest]) (*connect_go.Response[v1.LabelValuesResponse], error) {
return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("querier.v1.QuerierService.LabelValues is not implemented"))
}
func (UnimplementedQuerierServiceHandler) LabelNames(context.Context, *connect_go.Request[v1.LabelNamesRequest]) (*connect_go.Response[v1.LabelNamesResponse], error) {
return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("querier.v1.QuerierService.LabelNames is not implemented"))
}
func (UnimplementedQuerierServiceHandler) Series(context.Context, *connect_go.Request[v1.SeriesRequest]) (*connect_go.Response[v1.SeriesResponse], error) {
return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("querier.v1.QuerierService.Series is not implemented"))
}
func (UnimplementedQuerierServiceHandler) SelectMergeStacktraces(context.Context, *connect_go.Request[v1.SelectMergeStacktracesRequest]) (*connect_go.Response[v1.SelectMergeStacktracesResponse], error) {
return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("querier.v1.QuerierService.SelectMergeStacktraces is not implemented"))
}
func (UnimplementedQuerierServiceHandler) SelectSeries(context.Context, *connect_go.Request[v1.SelectSeriesRequest]) (*connect_go.Response[v1.SelectSeriesResponse], error) {
return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("querier.v1.QuerierService.SelectSeries is not implemented"))
}
@@ -0,0 +1,52 @@
// Code generated by protoc-gen-connect-go-mux. DO NOT EDIT.
//
// Source: querier/v1/querier.proto
package querierv1connect
import (
connect_go "github.com/bufbuild/connect-go"
mux "github.com/gorilla/mux"
)
// This is a compile-time assertion to ensure that this generated file and the connect package are
// compatible. If you get a compiler error that this constant is not defined, this code was
// generated with a version of connect newer than the one compiled into your binary. You can fix the
// problem by either regenerating this code with an older version of connect or updating the connect
// version compiled into your binary.
const _ = connect_go.IsAtLeastVersion0_1_0
// RegisterQuerierServiceHandler register an HTTP handler to a mux.Router from the service
// implementation.
func RegisterQuerierServiceHandler(mux *mux.Router, svc QuerierServiceHandler, opts ...connect_go.HandlerOption) {
mux.Handle("/querier.v1.QuerierService/ProfileTypes", connect_go.NewUnaryHandler(
"/querier.v1.QuerierService/ProfileTypes",
svc.ProfileTypes,
opts...,
))
mux.Handle("/querier.v1.QuerierService/LabelValues", connect_go.NewUnaryHandler(
"/querier.v1.QuerierService/LabelValues",
svc.LabelValues,
opts...,
))
mux.Handle("/querier.v1.QuerierService/LabelNames", connect_go.NewUnaryHandler(
"/querier.v1.QuerierService/LabelNames",
svc.LabelNames,
opts...,
))
mux.Handle("/querier.v1.QuerierService/Series", connect_go.NewUnaryHandler(
"/querier.v1.QuerierService/Series",
svc.Series,
opts...,
))
mux.Handle("/querier.v1.QuerierService/SelectMergeStacktraces", connect_go.NewUnaryHandler(
"/querier.v1.QuerierService/SelectMergeStacktraces",
svc.SelectMergeStacktraces,
opts...,
))
mux.Handle("/querier.v1.QuerierService/SelectSeries", connect_go.NewUnaryHandler(
"/querier.v1.QuerierService/SelectSeries",
svc.SelectSeries,
opts...,
))
}
+245
View File
@@ -0,0 +1,245 @@
package phlare
import (
"context"
"encoding/json"
"net/url"
"strings"
"time"
"github.com/bufbuild/connect-go"
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana-plugin-sdk-go/backend/instancemgmt"
"github.com/grafana/grafana-plugin-sdk-go/data"
"github.com/grafana/grafana/pkg/infra/httpclient"
commonv1 "github.com/grafana/grafana/pkg/tsdb/phlare/gen/common/v1"
querierv1 "github.com/grafana/grafana/pkg/tsdb/phlare/gen/querier/v1"
"github.com/grafana/grafana/pkg/tsdb/phlare/gen/querier/v1/querierv1connect"
)
var (
_ backend.QueryDataHandler = (*PhlareDatasource)(nil)
_ backend.CallResourceHandler = (*PhlareDatasource)(nil)
_ backend.CheckHealthHandler = (*PhlareDatasource)(nil)
_ backend.StreamHandler = (*PhlareDatasource)(nil)
)
// PhlareDatasource is a datasource for querying application performance profiles.
type PhlareDatasource struct {
client querierv1connect.QuerierServiceClient
}
// NewPhlareDatasource creates a new datasource instance.
func NewPhlareDatasource(httpClientProvider httpclient.Provider, settings backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) {
opt, err := settings.HTTPClientOptions()
if err != nil {
return nil, err
}
httpClient, err := httpClientProvider.New(opt)
if err != nil {
return nil, err
}
return &PhlareDatasource{
client: querierv1connect.NewQuerierServiceClient(httpClient, settings.URL),
}, nil
}
func (d *PhlareDatasource) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
logger.Debug("CallResource", "Path", req.Path, "Method", req.Method, "Body", req.Body)
if req.Path == "profileTypes" {
return d.callProfileTypes(ctx, req, sender)
}
if req.Path == "labelNames" {
return d.callLabelNames(ctx, req, sender)
}
if req.Path == "series" {
return d.callSeries(ctx, req, sender)
}
return sender.Send(&backend.CallResourceResponse{
Status: 404,
})
}
func (d *PhlareDatasource) callProfileTypes(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
res, err := d.client.ProfileTypes(ctx, connect.NewRequest(&querierv1.ProfileTypesRequest{}))
if err != nil {
return err
}
data, err := json.Marshal(res.Msg.ProfileTypes)
if err != nil {
return err
}
err = sender.Send(&backend.CallResourceResponse{Body: data, Headers: req.Headers, Status: 200})
if err != nil {
return err
}
return nil
}
type SeriesRequestJson struct {
Matchers []string `json:"matchers"`
}
func (d *PhlareDatasource) callSeries(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
parsedUrl, err := url.Parse(req.URL)
if err != nil {
return err
}
matchers, ok := parsedUrl.Query()["matchers"]
if !ok {
matchers = []string{"{}"}
}
res, err := d.client.Series(ctx, connect.NewRequest(&querierv1.SeriesRequest{Matchers: matchers}))
if err != nil {
return err
}
for _, val := range res.Msg.LabelsSet {
withoutPrivate := withoutPrivateLabels(val.Labels)
val.Labels = withoutPrivate
}
data, err := json.Marshal(res.Msg.LabelsSet)
if err != nil {
return err
}
err = sender.Send(&backend.CallResourceResponse{Body: data, Headers: req.Headers, Status: 200})
if err != nil {
return err
}
return nil
}
func (d *PhlareDatasource) callLabelNames(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
res, err := d.client.LabelNames(ctx, connect.NewRequest(&querierv1.LabelNamesRequest{}))
if err != nil {
return err
}
data, err := json.Marshal(res.Msg.Names)
if err != nil {
return err
}
err = sender.Send(&backend.CallResourceResponse{Body: data, Headers: req.Headers, Status: 200})
if err != nil {
return err
}
return nil
}
// QueryData handles multiple queries and returns multiple responses.
// req contains the queries []DataQuery (where each query contains RefID as a unique identifier).
// The QueryDataResponse contains a map of RefID to the response for each query, and each response
// contains Frames ([]*Frame).
func (d *PhlareDatasource) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
logger.Debug("QueryData called", "Queries", req.Queries)
// create response struct
response := backend.NewQueryDataResponse()
// loop over queries and execute them individually.
for _, q := range req.Queries {
res := d.query(ctx, req.PluginContext, q)
// save the response in a hashmap
// based on with RefID as identifier
response.Responses[q.RefID] = res
}
return response, nil
}
// CheckHealth handles health checks sent from Grafana to the plugin.
// The main use case for these health checks is the test button on the
// datasource configuration page which allows users to verify that
// a datasource is working as expected.
func (d *PhlareDatasource) CheckHealth(ctx context.Context, _ *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) {
logger.Debug("CheckHealth called")
status := backend.HealthStatusOk
message := "Data source is working"
if _, err := d.client.ProfileTypes(ctx, connect.NewRequest(&querierv1.ProfileTypesRequest{})); err != nil {
status = backend.HealthStatusError
message = err.Error()
}
return &backend.CheckHealthResult{
Status: status,
Message: message,
}, nil
}
// SubscribeStream is called when a client wants to connect to a stream. This callback
// allows sending the first message.
func (d *PhlareDatasource) SubscribeStream(_ context.Context, req *backend.SubscribeStreamRequest) (*backend.SubscribeStreamResponse, error) {
logger.Debug("SubscribeStream called")
status := backend.SubscribeStreamStatusPermissionDenied
if req.Path == "stream" {
// Allow subscribing only on expected path.
status = backend.SubscribeStreamStatusOK
}
return &backend.SubscribeStreamResponse{
Status: status,
}, nil
}
// RunStream is called once for any open channel. Results are shared with everyone
// subscribed to the same channel.
func (d *PhlareDatasource) RunStream(ctx context.Context, req *backend.RunStreamRequest, sender *backend.StreamSender) error {
logger.Debug("RunStream called")
// Create the same data frame as for query data.
frame := data.NewFrame("response")
// Add fields (matching the same schema used in QueryData).
frame.Fields = append(frame.Fields,
data.NewField("time", nil, make([]time.Time, 1)),
data.NewField("values", nil, make([]int64, 1)),
)
counter := 0
// Stream data frames periodically till stream closed by Grafana.
for {
select {
case <-ctx.Done():
logger.Info("Context done, finish streaming", "path", req.Path)
return nil
case <-time.After(time.Second):
// Send new data periodically.
frame.Fields[0].Set(0, time.Now())
frame.Fields[1].Set(0, int64(10*(counter%2+1)))
counter++
err := sender.SendFrame(frame, data.IncludeAll)
if err != nil {
logger.Error("Error sending frame", "error", err)
continue
}
}
}
}
// PublishStream is called when a client sends a message to the stream.
func (d *PhlareDatasource) PublishStream(_ context.Context, _ *backend.PublishStreamRequest) (*backend.PublishStreamResponse, error) {
logger.Debug("PublishStream called")
// Do not allow publishing at all.
return &backend.PublishStreamResponse{
Status: backend.PublishStreamStatusPermissionDenied,
}, nil
}
func withoutPrivateLabels(labels []*commonv1.LabelPair) []*commonv1.LabelPair {
res := make([]*commonv1.LabelPair, 0, len(labels))
for _, l := range labels {
if !strings.HasPrefix(l.Name, "__") {
res = append(res, l)
}
}
return res
}
+64
View File
@@ -0,0 +1,64 @@
package phlare
import (
"context"
"testing"
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/stretchr/testify/require"
)
// This is where the tests for the datasource backend live.
func Test_QueryData(t *testing.T) {
ds := PhlareDatasource{}
resp, err := ds.QueryData(
context.Background(),
&backend.QueryDataRequest{
Queries: []backend.DataQuery{
{RefID: "A"},
},
},
)
if err != nil {
t.Error(err)
}
if len(resp.Responses) != 1 {
t.Fatal("QueryData must return a response")
}
}
func Test_CallResource(t *testing.T) {
ds := &PhlareDatasource{
client: &FakeClient{},
}
t.Run("series resource", func(t *testing.T) {
sender := &FakeSender{}
err := ds.CallResource(
context.Background(),
&backend.CallResourceRequest{
PluginContext: backend.PluginContext{},
Path: "series",
Method: "GET",
URL: "series?matchers=%7B%7D",
Headers: nil,
Body: nil,
},
sender,
)
require.NoError(t, err)
require.Equal(t, 200, sender.Resp.Status)
require.Equal(t, `[{"labels":[{"name":"instance","value":"127.0.0.1"},{"name":"job","value":"default"}]}]`, string(sender.Resp.Body))
})
}
type FakeSender struct {
Resp *backend.CallResourceResponse
}
func (fs *FakeSender) Send(resp *backend.CallResourceResponse) error {
fs.Resp = resp
return nil
}
+335
View File
@@ -0,0 +1,335 @@
package phlare
import (
"context"
"encoding/json"
"fmt"
"math"
"strings"
"time"
"github.com/bufbuild/connect-go"
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana-plugin-sdk-go/backend/gtime"
"github.com/grafana/grafana-plugin-sdk-go/data"
"github.com/grafana/grafana-plugin-sdk-go/live"
querierv1 "github.com/grafana/grafana/pkg/tsdb/phlare/gen/querier/v1"
)
type queryModel struct {
WithStreaming bool
ProfileTypeID string `json:"profileTypeId"`
LabelSelector string `json:"labelSelector"`
GroupBy []string `json:"groupBy"`
}
type dsJsonModel struct {
MinStep string `json:"minStep"`
}
// These constants need to match the ones in the frontend.
const queryTypeProfile = "profile"
const (
queryTypeMetrics = "metrics"
queryTypeBoth = "both"
)
// query processes single Fire query transforming the response to data.Frame packaged in DataResponse
func (d *PhlareDatasource) query(ctx context.Context, pCtx backend.PluginContext, query backend.DataQuery) backend.DataResponse {
var qm queryModel
response := backend.DataResponse{}
err := json.Unmarshal(query.JSON, &qm)
if err != nil {
response.Error = fmt.Errorf("error unmarshaling query model: %v", err)
return response
}
if query.QueryType == queryTypeMetrics || query.QueryType == queryTypeBoth {
var dsJson dsJsonModel
err = json.Unmarshal(pCtx.DataSourceInstanceSettings.JSONData, &dsJson)
if err != nil {
response.Error = fmt.Errorf("error unmarshaling datasource json model: %v", err)
return response
}
parsedInterval := time.Second * 15
if dsJson.MinStep != "" {
parsedInterval, err = gtime.ParseDuration(dsJson.MinStep)
if err != nil {
parsedInterval = time.Second * 15
logger.Debug("Failed to parse the MinStep using default", "MinStep", dsJson.MinStep)
}
}
req := connect.NewRequest(&querierv1.SelectSeriesRequest{
ProfileTypeID: qm.ProfileTypeID,
LabelSelector: qm.LabelSelector,
Start: query.TimeRange.From.UnixMilli(),
End: query.TimeRange.To.UnixMilli(),
Step: math.Max(query.Interval.Seconds(), parsedInterval.Seconds()),
GroupBy: qm.GroupBy,
})
logger.Debug("Sending SelectSeriesRequest", "request", req, "queryModel", qm)
seriesResp, err := d.client.SelectSeries(ctx, req)
if err != nil {
logger.Error("Querying SelectSeries()", "err", err)
response.Error = err
return response
}
// add the frames to the response.
response.Frames = append(response.Frames, seriesToDataFrames(seriesResp, qm.ProfileTypeID)...)
}
if query.QueryType == queryTypeProfile || query.QueryType == queryTypeBoth {
req := makeRequest(qm, query)
logger.Debug("Sending SelectMergeStacktracesRequest", "request", req, "queryModel", qm)
resp, err := d.client.SelectMergeStacktraces(ctx, makeRequest(qm, query))
if err != nil {
logger.Error("Querying SelectMergeStacktraces()", "err", err)
response.Error = err
return response
}
frame := responseToDataFrames(resp, qm.ProfileTypeID)
response.Frames = append(response.Frames, frame)
// If query called with streaming on then return a channel
// to subscribe on a client-side and consume updates from a plugin.
// Feel free to remove this if you don't need streaming for your datasource.
if qm.WithStreaming {
channel := live.Channel{
Scope: live.ScopeDatasource,
Namespace: pCtx.DataSourceInstanceSettings.UID,
Path: "stream",
}
frame.SetMeta(&data.FrameMeta{Channel: channel.String()})
}
}
return response
}
func makeRequest(qm queryModel, query backend.DataQuery) *connect.Request[querierv1.SelectMergeStacktracesRequest] {
return &connect.Request[querierv1.SelectMergeStacktracesRequest]{
Msg: &querierv1.SelectMergeStacktracesRequest{
ProfileTypeID: qm.ProfileTypeID,
LabelSelector: qm.LabelSelector,
Start: query.TimeRange.From.UnixMilli(),
End: query.TimeRange.To.UnixMilli(),
},
}
}
// responseToDataFrames turns fire response to data.Frame. We encode the data into a nested set format where we have
// [level, value, label] columns and by ordering the items in a depth first traversal order we can recreate the whole
// tree back.
func responseToDataFrames(resp *connect.Response[querierv1.SelectMergeStacktracesResponse], profileTypeID string) *data.Frame {
tree := levelsToTree(resp.Msg.Flamegraph.Levels, resp.Msg.Flamegraph.Names)
return treeToNestedSetDataFrame(tree, profileTypeID)
}
// START_OFFSET is offset of the bar relative to previous sibling
const START_OFFSET = 0
// VALUE_OFFSET is value or width of the bar
const VALUE_OFFSET = 1
// SELF_OFFSET is self value of the bar
const SELF_OFFSET = 2
// NAME_OFFSET is index into the names array
const NAME_OFFSET = 3
// ITEM_OFFSET Next bar. Each bar of the profile is represented by 4 number in a flat array.
const ITEM_OFFSET = 4
type ProfileTree struct {
Start int64
Value int64
Self int64
Level int
Name string
Nodes []*ProfileTree
}
// levelsToTree converts flamebearer format into a tree. This is needed to then convert it into nested set format
// dataframe. This should be temporary, and ideally we should get some sort of tree struct directly from Fire API.
func levelsToTree(levels []*querierv1.Level, names []string) *ProfileTree {
tree := &ProfileTree{
Start: 0,
Value: levels[0].Values[VALUE_OFFSET],
Self: levels[0].Values[SELF_OFFSET],
Level: 0,
Name: names[levels[0].Values[0]],
}
parentsStack := []*ProfileTree{tree}
currentLevel := 1
// Cycle through each level
for {
if currentLevel >= len(levels) {
break
}
// If we still have levels to go, this should not happen. Something is probably wrong with the flamebearer data.
if len(parentsStack) == 0 {
logger.Error("parentsStack is empty but we are not at the the last level", "currentLevel", currentLevel)
break
}
var nextParentsStack []*ProfileTree
currentParent := parentsStack[:1][0]
parentsStack = parentsStack[1:]
itemIndex := 0
// cumulative offset as items in flamebearer format have just relative to prev item
offset := int64(0)
// Cycle through bar in a level
for {
if itemIndex >= len(levels[currentLevel].Values) {
break
}
itemStart := levels[currentLevel].Values[itemIndex+START_OFFSET] + offset
itemValue := levels[currentLevel].Values[itemIndex+VALUE_OFFSET]
selfValue := levels[currentLevel].Values[itemIndex+SELF_OFFSET]
itemEnd := itemStart + itemValue
parentEnd := currentParent.Start + currentParent.Value
if itemStart >= currentParent.Start && itemEnd <= parentEnd {
// We have an item that is in the bounds of current parent item, so it should be its child
treeItem := &ProfileTree{
Start: itemStart,
Value: itemValue,
Self: selfValue,
Level: currentLevel,
Name: names[levels[currentLevel].Values[itemIndex+NAME_OFFSET]],
}
// Add to parent
currentParent.Nodes = append(currentParent.Nodes, treeItem)
// Add this item as parent for the next level
nextParentsStack = append(nextParentsStack, treeItem)
itemIndex += ITEM_OFFSET
// Update offset for next item. This is changing relative offset to absolute one.
offset = itemEnd
} else {
// We went out of parents bounds so lets move to next parent. We will evaluate the same item again, but
// we will check if it is a child of the next parent item in line.
if len(parentsStack) == 0 {
logger.Error("parentsStack is empty but there are still items in current level", "currentLevel", currentLevel, "itemIndex", itemIndex)
break
}
currentParent = parentsStack[:1][0]
parentsStack = parentsStack[1:]
continue
}
}
parentsStack = nextParentsStack
currentLevel++
}
return tree
}
type CustomMeta struct {
ProfileTypeID string
}
// treeToNestedSetDataFrame walks the tree depth first and adds items into the dataframe. This is a nested set format
// where by ordering the items in depth first order and knowing the level/depth of each item we can recreate the
// parent - child relationship without explicitly needing parent/child column and we can later just iterate over the
// dataFrame to again basically walking depth first over the tree/profile.
func treeToNestedSetDataFrame(tree *ProfileTree, profileTypeID string) *data.Frame {
frame := data.NewFrame("response")
frame.Meta = &data.FrameMeta{PreferredVisualization: "flamegraph"}
levelField := data.NewField("level", nil, []int64{})
valueField := data.NewField("value", nil, []int64{})
selfField := data.NewField("self", nil, []int64{})
// profileTypeID should encode the type of the profile with unit being the 3rd part
parts := strings.Split(profileTypeID, ":")
valueField.Config = &data.FieldConfig{Unit: normalizeUnit(parts[2])}
selfField.Config = &data.FieldConfig{Unit: normalizeUnit(parts[2])}
labelField := data.NewField("label", nil, []string{})
frame.Fields = data.Fields{levelField, valueField, selfField, labelField}
walkTree(tree, func(tree *ProfileTree) {
levelField.Append(int64(tree.Level))
valueField.Append(tree.Value)
selfField.Append(tree.Self)
labelField.Append(tree.Name)
})
return frame
}
func walkTree(tree *ProfileTree, fn func(tree *ProfileTree)) {
fn(tree)
stack := tree.Nodes
for {
if len(stack) == 0 {
break
}
fn(stack[0])
if stack[0].Nodes != nil {
stack = append(stack[0].Nodes, stack[1:]...)
} else {
stack = stack[1:]
}
}
}
func seriesToDataFrames(seriesResp *connect.Response[querierv1.SelectSeriesResponse], profileTypeID string) []*data.Frame {
var frames []*data.Frame
for _, series := range seriesResp.Msg.Series {
// We create separate data frames as the series may not have the same length
frame := data.NewFrame("series")
frame.Meta = &data.FrameMeta{PreferredVisualization: "graph"}
fields := data.Fields{}
timeField := data.NewField("time", nil, []time.Time{})
fields = append(fields, timeField)
label := ""
unit := ""
parts := strings.Split(profileTypeID, ":")
if len(parts) == 5 {
label = parts[1] // sample type e.g. cpu, goroutine, alloc_objects
unit = normalizeUnit(parts[2])
}
labels := make(map[string]string)
for _, label := range series.Labels {
labels[label.Name] = label.Value
}
valueField := data.NewField(label, labels, []float64{})
valueField.Config = &data.FieldConfig{Unit: unit}
for _, point := range series.Points {
timeField.Append(time.UnixMilli(point.Timestamp))
valueField.Append(point.Value)
}
fields = append(fields, valueField)
frame.Fields = fields
frames = append(frames, frame)
}
return frames
}
func normalizeUnit(unit string) string {
if unit == "nanoseconds" {
return "ns"
}
if unit == "count" {
return "short"
}
return unit
}
+314
View File
@@ -0,0 +1,314 @@
package phlare
import (
"context"
"testing"
"time"
"github.com/bufbuild/connect-go"
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana-plugin-sdk-go/data"
"github.com/stretchr/testify/require"
commonv1 "github.com/grafana/grafana/pkg/tsdb/phlare/gen/common/v1"
querierv1 "github.com/grafana/grafana/pkg/tsdb/phlare/gen/querier/v1"
)
// This is where the tests for the datasource backend live.
func Test_query(t *testing.T) {
client := &FakeClient{}
ds := &PhlareDatasource{
client: client,
}
pCtx := backend.PluginContext{
DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{
JSONData: []byte(`{"minStep":"30s"}`),
},
}
t.Run("query both", func(t *testing.T) {
dataQuery := makeDataQuery()
resp := ds.query(context.Background(), pCtx, *dataQuery)
require.Nil(t, resp.Error)
require.Equal(t, 2, len(resp.Frames))
require.Equal(t, "time", resp.Frames[0].Fields[0].Name)
require.Equal(t, data.NewField("level", nil, []int64{0, 1, 2}), resp.Frames[1].Fields[0])
})
t.Run("query profile", func(t *testing.T) {
dataQuery := makeDataQuery()
dataQuery.QueryType = queryTypeProfile
resp := ds.query(context.Background(), pCtx, *dataQuery)
require.Nil(t, resp.Error)
require.Equal(t, 1, len(resp.Frames))
require.Equal(t, data.NewField("level", nil, []int64{0, 1, 2}), resp.Frames[0].Fields[0])
})
t.Run("query metrics", func(t *testing.T) {
dataQuery := makeDataQuery()
dataQuery.QueryType = queryTypeMetrics
resp := ds.query(context.Background(), pCtx, *dataQuery)
require.Nil(t, resp.Error)
require.Equal(t, 1, len(resp.Frames))
require.Equal(t, "time", resp.Frames[0].Fields[0].Name)
})
t.Run("query metrics uses min step", func(t *testing.T) {
dataQuery := makeDataQuery()
dataQuery.QueryType = queryTypeMetrics
resp := ds.query(context.Background(), pCtx, *dataQuery)
require.Nil(t, resp.Error)
r, ok := client.Req.(*connect.Request[querierv1.SelectSeriesRequest])
require.True(t, ok)
require.Equal(t, float64(30), r.Msg.Step)
})
t.Run("query metrics uses default min step", func(t *testing.T) {
dataQuery := makeDataQuery()
dataQuery.QueryType = queryTypeMetrics
pCtxNoMinStep := backend.PluginContext{
DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{
JSONData: []byte(`{}`),
},
}
resp := ds.query(context.Background(), pCtxNoMinStep, *dataQuery)
require.Nil(t, resp.Error)
r, ok := client.Req.(*connect.Request[querierv1.SelectSeriesRequest])
require.True(t, ok)
require.Equal(t, float64(15), r.Msg.Step)
})
t.Run("query metrics uses group by", func(t *testing.T) {
dataQuery := makeDataQuery()
dataQuery.QueryType = queryTypeMetrics
dataQuery.JSON = []byte(`{"profileTypeId":"memory:alloc_objects:count:space:bytes","labelSelector":"{app=\\\"baz\\\"}","groupBy":["app","instance"]}`)
resp := ds.query(context.Background(), pCtx, *dataQuery)
require.Nil(t, resp.Error)
r, ok := client.Req.(*connect.Request[querierv1.SelectSeriesRequest])
require.True(t, ok)
require.Equal(t, []string{"app", "instance"}, r.Msg.GroupBy)
})
}
func makeDataQuery() *backend.DataQuery {
return &backend.DataQuery{
RefID: "A",
QueryType: queryTypeBoth,
MaxDataPoints: 0,
Interval: 0,
TimeRange: backend.TimeRange{
From: time.UnixMilli(10000),
To: time.UnixMilli(20000),
},
JSON: []byte(`{"profileTypeId":"memory:alloc_objects:count:space:bytes","labelSelector":"{app=\\\"baz\\\"}"}`),
}
}
// This is where the tests for the datasource backend live.
func Test_profileToDataFrame(t *testing.T) {
resp := &connect.Response[querierv1.SelectMergeStacktracesResponse]{
Msg: &querierv1.SelectMergeStacktracesResponse{
Flamegraph: &querierv1.FlameGraph{
Names: []string{"func1", "func2", "func3"},
Levels: []*querierv1.Level{
{Values: []int64{0, 20, 1, 2}},
{Values: []int64{0, 10, 3, 1, 4, 5, 5, 2}},
},
Total: 987,
MaxSelf: 123,
},
},
}
frame := responseToDataFrames(resp, "memory:alloc_objects:count:space:bytes")
require.Equal(t, 4, len(frame.Fields))
require.Equal(t, data.NewField("level", nil, []int64{0, 1, 1}), frame.Fields[0])
require.Equal(t, data.NewField("value", nil, []int64{20, 10, 5}).SetConfig(&data.FieldConfig{Unit: "short"}), frame.Fields[1])
require.Equal(t, data.NewField("self", nil, []int64{1, 3, 5}).SetConfig(&data.FieldConfig{Unit: "short"}), frame.Fields[2])
require.Equal(t, data.NewField("label", nil, []string{"func1", "func2", "func3"}), frame.Fields[3])
}
// This is where the tests for the datasource backend live.
func Test_levelsToTree(t *testing.T) {
t.Run("simple", func(t *testing.T) {
levels := []*querierv1.Level{
{Values: []int64{0, 100, 0, 0}},
{Values: []int64{0, 40, 0, 1, 0, 30, 0, 2}},
{Values: []int64{0, 15, 0, 3}},
}
tree := levelsToTree(levels, []string{"root", "func1", "func2", "func1:func3"})
require.Equal(t, &ProfileTree{
Start: 0, Value: 100, Level: 0, Name: "root", Nodes: []*ProfileTree{
{
Start: 0, Value: 40, Level: 1, Name: "func1", Nodes: []*ProfileTree{
{Start: 0, Value: 15, Level: 2, Name: "func1:func3"},
},
},
{Start: 40, Value: 30, Level: 1, Name: "func2"},
},
}, tree)
})
t.Run("medium", func(t *testing.T) {
levels := []*querierv1.Level{
{Values: []int64{0, 100, 0, 0}},
{Values: []int64{0, 40, 0, 1, 0, 30, 0, 2, 0, 30, 0, 3}},
{Values: []int64{0, 20, 0, 4, 50, 10, 0, 5}},
}
tree := levelsToTree(levels, []string{"root", "func1", "func2", "func3", "func1:func4", "func3:func5"})
require.Equal(t, &ProfileTree{
Start: 0, Value: 100, Level: 0, Name: "root", Nodes: []*ProfileTree{
{
Start: 0, Value: 40, Level: 1, Name: "func1", Nodes: []*ProfileTree{
{Start: 0, Value: 20, Level: 2, Name: "func1:func4"},
},
},
{Start: 40, Value: 30, Level: 1, Name: "func2"},
{
Start: 70, Value: 30, Level: 1, Name: "func3", Nodes: []*ProfileTree{
{Start: 70, Value: 10, Level: 2, Name: "func3:func5"},
},
},
},
}, tree)
})
}
func Test_treeToNestedDataFrame(t *testing.T) {
tree := &ProfileTree{
Start: 0, Value: 100, Level: 0, Self: 1, Name: "root", Nodes: []*ProfileTree{
{
Start: 10, Value: 40, Level: 1, Self: 2, Name: "func1",
},
{Start: 60, Value: 30, Level: 1, Self: 3, Name: "func2", Nodes: []*ProfileTree{
{Start: 61, Value: 15, Level: 2, Self: 4, Name: "func1:func3"},
}},
},
}
frame := treeToNestedSetDataFrame(tree, "memory:alloc_objects:count:space:bytes")
require.Equal(t,
[]*data.Field{
data.NewField("level", nil, []int64{0, 1, 1, 2}),
data.NewField("value", nil, []int64{100, 40, 30, 15}).SetConfig(&data.FieldConfig{Unit: "short"}),
data.NewField("self", nil, []int64{1, 2, 3, 4}).SetConfig(&data.FieldConfig{Unit: "short"}),
data.NewField("label", nil, []string{"root", "func1", "func2", "func1:func3"}),
}, frame.Fields)
}
func Test_seriesToDataFrame(t *testing.T) {
t.Run("single series", func(t *testing.T) {
resp := &connect.Response[querierv1.SelectSeriesResponse]{
Msg: &querierv1.SelectSeriesResponse{
Series: []*commonv1.Series{
{Labels: []*commonv1.LabelPair{}, Points: []*commonv1.Point{{Timestamp: int64(1000), Value: 30}, {Timestamp: int64(2000), Value: 10}}},
},
},
}
frames := seriesToDataFrames(resp, "process_cpu:samples:count:cpu:nanoseconds")
require.Equal(t, 2, len(frames[0].Fields))
require.Equal(t, data.NewField("time", nil, []time.Time{time.UnixMilli(1000), time.UnixMilli(2000)}), frames[0].Fields[0])
require.Equal(t, data.NewField("samples", map[string]string{}, []float64{30, 10}).SetConfig(&data.FieldConfig{Unit: "short"}), frames[0].Fields[1])
// with a label pair, the value field should name itself with a label pair name and not the profile type
resp = &connect.Response[querierv1.SelectSeriesResponse]{
Msg: &querierv1.SelectSeriesResponse{
Series: []*commonv1.Series{
{Labels: []*commonv1.LabelPair{{Name: "app", Value: "bar"}}, Points: []*commonv1.Point{{Timestamp: int64(1000), Value: 30}, {Timestamp: int64(2000), Value: 10}}},
},
},
}
frames = seriesToDataFrames(resp, "process_cpu:samples:count:cpu:nanoseconds")
require.Equal(t, data.NewField("samples", map[string]string{"app": "bar"}, []float64{30, 10}).SetConfig(&data.FieldConfig{Unit: "short"}), frames[0].Fields[1])
})
t.Run("single series", func(t *testing.T) {
resp := &connect.Response[querierv1.SelectSeriesResponse]{
Msg: &querierv1.SelectSeriesResponse{
Series: []*commonv1.Series{
{Labels: []*commonv1.LabelPair{{Name: "foo", Value: "bar"}}, Points: []*commonv1.Point{{Timestamp: int64(1000), Value: 30}, {Timestamp: int64(2000), Value: 10}}},
{Labels: []*commonv1.LabelPair{{Name: "foo", Value: "baz"}}, Points: []*commonv1.Point{{Timestamp: int64(1000), Value: 30}, {Timestamp: int64(2000), Value: 10}}},
},
},
}
frames := seriesToDataFrames(resp, "process_cpu:samples:count:cpu:nanoseconds")
require.Equal(t, 2, len(frames))
require.Equal(t, 2, len(frames[0].Fields))
require.Equal(t, 2, len(frames[1].Fields))
require.Equal(t, data.NewField("samples", map[string]string{"foo": "bar"}, []float64{30, 10}).SetConfig(&data.FieldConfig{Unit: "short"}), frames[0].Fields[1])
require.Equal(t, data.NewField("samples", map[string]string{"foo": "baz"}, []float64{30, 10}).SetConfig(&data.FieldConfig{Unit: "short"}), frames[1].Fields[1])
})
}
type FakeClient struct {
Req interface{}
}
func (f *FakeClient) ProfileTypes(ctx context.Context, c *connect.Request[querierv1.ProfileTypesRequest]) (*connect.Response[querierv1.ProfileTypesResponse], error) {
panic("implement me")
}
func (f *FakeClient) LabelValues(ctx context.Context, c *connect.Request[querierv1.LabelValuesRequest]) (*connect.Response[querierv1.LabelValuesResponse], error) {
panic("implement me")
}
func (f *FakeClient) LabelNames(context.Context, *connect.Request[querierv1.LabelNamesRequest]) (*connect.Response[querierv1.LabelNamesResponse], error) {
panic("implement me")
}
func (f *FakeClient) Series(ctx context.Context, c *connect.Request[querierv1.SeriesRequest]) (*connect.Response[querierv1.SeriesResponse], error) {
return &connect.Response[querierv1.SeriesResponse]{
Msg: &querierv1.SeriesResponse{
LabelsSet: []*commonv1.Labels{{
Labels: []*commonv1.LabelPair{
{
Name: "__unit__",
Value: "cpu",
},
{
Name: "instance",
Value: "127.0.0.1",
},
{
Name: "job",
Value: "default",
},
},
}},
},
}, nil
}
func (f *FakeClient) SelectMergeStacktraces(ctx context.Context, c *connect.Request[querierv1.SelectMergeStacktracesRequest]) (*connect.Response[querierv1.SelectMergeStacktracesResponse], error) {
f.Req = c
return &connect.Response[querierv1.SelectMergeStacktracesResponse]{
Msg: &querierv1.SelectMergeStacktracesResponse{
Flamegraph: &querierv1.FlameGraph{
Names: []string{"foo", "bar", "baz"},
Levels: []*querierv1.Level{
{Values: []int64{0, 10, 0, 0}},
{Values: []int64{0, 9, 0, 1}},
{Values: []int64{0, 8, 8, 2}},
},
Total: 100,
MaxSelf: 56,
},
},
}, nil
}
func (f *FakeClient) SelectSeries(ctx context.Context, req *connect.Request[querierv1.SelectSeriesRequest]) (*connect.Response[querierv1.SelectSeriesResponse], error) {
f.Req = req
return &connect.Response[querierv1.SelectSeriesResponse]{
Msg: &querierv1.SelectSeriesResponse{
Series: []*commonv1.Series{
{
Labels: []*commonv1.LabelPair{{Name: "foo", Value: "bar"}},
Points: []*commonv1.Point{{Timestamp: int64(1000), Value: 30}, {Timestamp: int64(2000), Value: 10}},
},
},
},
}, nil
}
+103
View File
@@ -0,0 +1,103 @@
package phlare
import (
"context"
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana-plugin-sdk-go/backend/datasource"
"github.com/grafana/grafana-plugin-sdk-go/backend/instancemgmt"
"github.com/grafana/grafana/pkg/infra/httpclient"
"github.com/grafana/grafana/pkg/infra/log"
)
// Make sure FireDatasource implements required interfaces. This is important to do
// since otherwise we will only get a not implemented error response from plugin in
// runtime. In this example datasource instance implements backend.QueryDataHandler,
// backend.CheckHealthHandler, backend.StreamHandler interfaces. Plugin should not
// implement all these interfaces - only those which are required for a particular task.
// For example if plugin does not need streaming functionality then you are free to remove
// methods that implement backend.StreamHandler. Implementing instancemgmt.InstanceDisposer
// is useful to clean up resources used by previous datasource instance when a new datasource
// instance created upon datasource settings changed.
var (
_ backend.QueryDataHandler = (*Service)(nil)
_ backend.CallResourceHandler = (*Service)(nil)
_ backend.CheckHealthHandler = (*Service)(nil)
_ backend.StreamHandler = (*Service)(nil)
)
var logger = log.New("tsdb.phlare")
type Service struct {
im instancemgmt.InstanceManager
}
func (s *Service) getInstance(pluginCtx backend.PluginContext) (*PhlareDatasource, error) {
i, err := s.im.Get(pluginCtx)
if err != nil {
return nil, err
}
in := i.(*PhlareDatasource)
return in, nil
}
func ProvideService(httpClientProvider httpclient.Provider) *Service {
return &Service{
im: datasource.NewInstanceManager(newInstanceSettings(httpClientProvider)),
}
}
func newInstanceSettings(httpClientProvider httpclient.Provider) datasource.InstanceFactoryFunc {
return func(settings backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) {
return NewPhlareDatasource(httpClientProvider, settings)
}
}
func (s *Service) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
i, err := s.getInstance(req.PluginContext)
if err != nil {
return nil, err
}
return i.QueryData(ctx, req)
}
func (s *Service) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
i, err := s.getInstance(req.PluginContext)
if err != nil {
return err
}
return i.CallResource(ctx, req, sender)
}
func (s *Service) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) {
i, err := s.getInstance(req.PluginContext)
if err != nil {
return nil, err
}
return i.CheckHealth(ctx, req)
}
func (s *Service) SubscribeStream(ctx context.Context, req *backend.SubscribeStreamRequest) (*backend.SubscribeStreamResponse, error) {
i, err := s.getInstance(req.PluginContext)
if err != nil {
return nil, err
}
return i.SubscribeStream(ctx, req)
}
func (s *Service) RunStream(ctx context.Context, req *backend.RunStreamRequest, sender *backend.StreamSender) error {
i, err := s.getInstance(req.PluginContext)
if err != nil {
return err
}
return i.RunStream(ctx, req, sender)
}
// PublishStream is called when a client sends a message to the stream.
func (s *Service) PublishStream(ctx context.Context, req *backend.PublishStreamRequest) (*backend.PublishStreamResponse, error) {
i, err := s.getInstance(req.PluginContext)
if err != nil {
return nil, err
}
return i.PublishStream(ctx, req)
}