grafana/pkg/promlib/querydata/exemplar/framer.go
ismail simsek 3fb6319d1b
Prometheus: Introduce prometheus backend library (#83952)
* Move files to prometheus-library

* refactor core prometheus to use prometheus-library

* modify client transport options

* mock

* have a type

* import aliases

* rename

* call the right method

* remove unrelated test from the library

* update codeowners

* go work sync

* update go.work.sum

* make swagger-clean && make openapi3-gen

* add promlib to makefile

* remove clilogger

* Export the function

* update unit test

* add prometheus_test.go

* fix mock type

* use mapUtil from grafana-plugin-sdk-go
2024-03-11 17:22:33 +01:00

88 lines
2.3 KiB
Go

package exemplar
import (
"time"
"github.com/grafana/grafana-plugin-sdk-go/data"
)
var _ data.Framer = (*Framer)(nil)
type Framer struct {
frames data.Frames
sampler Sampler
labelTracker LabelTracker
meta *data.FrameMeta
refID string
}
func NewFramer(sampler Sampler, labelTracker LabelTracker) *Framer {
return &Framer{
frames: data.Frames{},
sampler: sampler,
labelTracker: labelTracker,
}
}
func (f *Framer) SetMeta(meta *data.FrameMeta) {
f.meta = meta
}
func (f *Framer) SetRefID(refID string) {
f.refID = refID
}
func (f *Framer) AddFrame(frame *data.Frame) {
f.frames = append(f.frames, frame)
}
func (f *Framer) Frames() (data.Frames, error) {
exemplars := f.sampler.Sample()
f.sampler.Reset()
if len(exemplars) == 0 {
return f.frames, nil
}
// the new exemplar frame will be a single frame in long format
// with a timestamp, metric value, and one or more label fields
exemplarFrame := data.NewFrame("exemplar")
exemplarFrame.RefID = f.refID
exemplarFrame.Meta = f.meta
// init the fields for the new exemplar frame
timeField := data.NewField(data.TimeSeriesTimeFieldName, nil, make([]time.Time, 0, len(exemplars)))
valueField := data.NewField(data.TimeSeriesValueFieldName, nil, make([]float64, 0, len(exemplars)))
exemplarFrame.Fields = append(exemplarFrame.Fields, timeField, valueField)
labelNames := f.labelTracker.GetNames()
exemplarLabels := make(map[string]string, len(labelNames))
for _, labelName := range labelNames {
exemplarFrame.Fields = append(exemplarFrame.Fields, data.NewField(labelName, nil, make([]string, 0, len(exemplars))))
}
// add the sampled exemplars to the new exemplar frame
for _, b := range exemplars {
// Fill labels map with default values
for _, n := range labelNames {
exemplarLabels[n] = b.SeriesLabels[n]
}
// Enter corresponding label values from exemplar fields
for _, bf := range b.Fields {
if _, exists := exemplarLabels[bf.Name]; exists {
exemplarLabels[bf.Name] = bf.CopyAt(b.RowIdx).(string)
}
}
timeField.Append(b.Timestamp)
valueField.Append(b.Value)
for i, labelName := range labelNames {
colIdx := i + 2 // +2 to skip time and value fields
exemplarFrame.Fields[colIdx].Append(exemplarLabels[labelName])
}
}
f.frames = append(f.frames, exemplarFrame)
return f.frames, nil
}