The open and composable observability and data visualization platform. Visualize metrics, logs, and traces from multiple sources like Prometheus, Loki, Elasticsearch, InfluxDB, Postgres and many more.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
grafana/pkg/tsdb/parca/resources.go

155 lines
5.4 KiB

package parca
import (
"context"
"encoding/json"
"fmt"
"net/url"
v1alpha1 "buf.build/gen/go/parca-dev/parca/protocolbuffers/go/parca/query/v1alpha1"
"github.com/bufbuild/connect-go"
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana-plugin-sdk-go/backend/tracing"
"go.opentelemetry.io/otel/codes"
)
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 {
ctxLogger := logger.FromContext(ctx)
ctxLogger.Debug("Getting profile types", "function", logEntrypoint())
ctx, span := tracing.DefaultTracer().Start(ctx, "datasource.parca.callProfileTypes")
defer span.End()
res, err := d.client.ProfileTypes(ctx, connect.NewRequest(&v1alpha1.ProfileTypesRequest{}))
if err != nil {
ctxLogger.Error("Failed to get profile types", "error", err, "function", logEntrypoint())
span.RecordError(err)
span.SetStatus(codes.Error, err.Error())
return err
}
types := make([]*ProfileType, 0, len(res.Msg.Types))
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 {
ctxLogger.Error("Failed to marshal profile types", "error", err, "function", logEntrypoint())
span.RecordError(err)
span.SetStatus(codes.Error, err.Error())
return err
}
err = sender.Send(&backend.CallResourceResponse{Body: data, Headers: req.Headers, Status: 200})
if err != nil {
ctxLogger.Error("Failed to send data to Parca", "error", err, "function", logEntrypoint())
span.RecordError(err)
span.SetStatus(codes.Error, err.Error())
return err
}
ctxLogger.Debug("Successfully got profile types", "function", logEntrypoint())
return nil
}
func (d *ParcaDatasource) callLabelNames(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
ctxLogger := logger.FromContext(ctx)
ctxLogger.Debug("Getting label names", "function", logEntrypoint())
ctx, span := tracing.DefaultTracer().Start(ctx, "datasource.parca.callLabelNames")
defer span.End()
res, err := d.client.Labels(ctx, connect.NewRequest(&v1alpha1.LabelsRequest{}))
if err != nil {
ctxLogger.Error("Failed to get label names", "error", err, "function", logEntrypoint())
span.RecordError(err)
span.SetStatus(codes.Error, err.Error())
return err
}
data, err := json.Marshal(res.Msg.LabelNames)
if err != nil {
ctxLogger.Error("Failed to marshal label names", "error", err, "function", logEntrypoint())
span.RecordError(err)
span.SetStatus(codes.Error, err.Error())
return err
}
err = sender.Send(&backend.CallResourceResponse{Body: data, Headers: req.Headers, Status: 200})
if err != nil {
ctxLogger.Error("Failed to send data to Parca", "error", err, "function", logEntrypoint())
span.RecordError(err)
span.SetStatus(codes.Error, err.Error())
return err
}
ctxLogger.Debug("Successfully got label names", "function", logEntrypoint())
return nil
}
func (d *ParcaDatasource) callLabelValues(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
ctxLogger := logger.FromContext(ctx)
ctxLogger.Debug("Getting label values", "function", logEntrypoint())
ctx, span := tracing.DefaultTracer().Start(ctx, "datasource.parca.callLabelValues")
defer span.End()
parsedUrl, err := url.Parse(req.URL)
if err != nil {
ctxLogger.Error("Failed to parse URL", "error", err, "function", logEntrypoint())
span.RecordError(err)
span.SetStatus(codes.Error, err.Error())
return err
}
label, ok := parsedUrl.Query()["label"]
if !ok {
ctxLogger.Error("Failed to get label from query", "error", err, "function", logEntrypoint())
label = []string{""}
}
res, err := d.client.Values(ctx, connect.NewRequest(&v1alpha1.ValuesRequest{LabelName: label[0]}))
if err != nil {
ctxLogger.Error("Failed to get values for given label", "error", err, "function", logEntrypoint())
span.RecordError(err)
span.SetStatus(codes.Error, err.Error())
return err
}
data, err := json.Marshal(res.Msg.LabelValues)
if err != nil {
ctxLogger.Error("Failed to marshal label values", "error", err, "function", logEntrypoint())
span.RecordError(err)
span.SetStatus(codes.Error, err.Error())
return err
}
err = sender.Send(&backend.CallResourceResponse{Body: data, Headers: req.Headers, Status: 200})
if err != nil {
ctxLogger.Error("Failed to send data to Parca", "error", err, "function", logEntrypoint())
span.RecordError(err)
span.SetStatus(codes.Error, err.Error())
return err
}
ctxLogger.Debug("Successfully got label values", "function", logEntrypoint())
return nil
}