grafana/vendor/github.com/grafana/grafana-plugin-sdk-go/dataframe/dataframe.go

275 lines
5.4 KiB
Go

package dataframe
import (
"fmt"
"sort"
"strings"
"time"
)
// Frame represents a columnar storage with optional labels.
type Frame struct {
Name string
Fields []*Field
RefID string
Meta *QueryResultMeta
}
// Field represents a column of data with a specific type.
type Field struct {
Name string
Config *FieldConfig
Vector Vector // TODO? in the frontend, the variable is called "Values"
Labels Labels
}
// Fields is a slice of Field pointers.
type Fields []*Field
// NewField returns a new instance of Field.
func NewField(name string, labels Labels, values interface{}) *Field {
var vec Vector
switch v := values.(type) {
case []int8:
vec = newVector(v, len(v))
for i := 0; i < len(v); i++ {
vec.Set(i, v[i])
}
case []*int8:
vec = newVector(v, len(v))
for i := 0; i < len(v); i++ {
vec.Set(i, v[i])
}
case []int16:
vec = newVector(v, len(v))
for i := 0; i < len(v); i++ {
vec.Set(i, v[i])
}
case []*int16:
vec = newVector(v, len(v))
for i := 0; i < len(v); i++ {
vec.Set(i, v[i])
}
case []int32:
vec = newVector(v, len(v))
for i := 0; i < len(v); i++ {
vec.Set(i, v[i])
}
case []*int32:
vec = newVector(v, len(v))
for i := 0; i < len(v); i++ {
vec.Set(i, v[i])
}
case []int64:
vec = newVector(v, len(v))
for i := 0; i < len(v); i++ {
vec.Set(i, v[i])
}
case []*int64:
vec = newVector(v, len(v))
for i := 0; i < len(v); i++ {
vec.Set(i, v[i])
}
case []uint8:
vec = newVector(v, len(v))
for i := 0; i < len(v); i++ {
vec.Set(i, v[i])
}
case []*uint8:
vec = newVector(v, len(v))
for i := 0; i < len(v); i++ {
vec.Set(i, v[i])
}
case []uint16:
vec = newVector(v, len(v))
for i := 0; i < len(v); i++ {
vec.Set(i, v[i])
}
case []*uint16:
vec = newVector(v, len(v))
for i := 0; i < len(v); i++ {
vec.Set(i, v[i])
}
case []uint32:
vec = newVector(v, len(v))
for i := 0; i < len(v); i++ {
vec.Set(i, v[i])
}
case []*uint32:
vec = newVector(v, len(v))
for i := 0; i < len(v); i++ {
vec.Set(i, v[i])
}
case []uint64:
vec = newVector(v, len(v))
for i := 0; i < len(v); i++ {
vec.Set(i, v[i])
}
case []*uint64:
vec = newVector(v, len(v))
for i := 0; i < len(v); i++ {
vec.Set(i, v[i])
}
case []float32:
vec = newVector(v, len(v))
for i := 0; i < len(v); i++ {
vec.Set(i, v[i])
}
case []*float32:
vec = newVector(v, len(v))
for i := 0; i < len(v); i++ {
vec.Set(i, v[i])
}
case []float64:
vec = newVector(v, len(v))
for i := 0; i < len(v); i++ {
vec.Set(i, v[i])
}
case []*float64:
vec = newVector(v, len(v))
for i := 0; i < len(v); i++ {
vec.Set(i, v[i])
}
case []string:
vec = newVector(v, len(v))
for i := 0; i < len(v); i++ {
vec.Set(i, v[i])
}
case []*string:
vec = newVector(v, len(v))
for i := 0; i < len(v); i++ {
vec.Set(i, v[i])
}
case []bool:
vec = newVector(v, len(v))
for i := 0; i < len(v); i++ {
vec.Set(i, v[i])
}
case []*bool:
vec = newVector(v, len(v))
for i := 0; i < len(v); i++ {
vec.Set(i, v[i])
}
case []time.Time:
vec = newVector(v, len(v))
for i := 0; i < len(v); i++ {
vec.Set(i, v[i])
}
case []*time.Time:
vec = newVector(v, len(v))
for i := 0; i < len(v); i++ {
vec.Set(i, v[i])
}
default:
panic(fmt.Errorf("unsupported field type %T", v))
}
return &Field{
Name: name,
Vector: vec,
Labels: labels,
}
}
// Len returns the number of elements in the field.
func (f *Field) Len() int {
return f.Vector.Len()
}
// SetConfig modifies the Field's Config property to
// be set to conf and returns the Field.
func (f *Field) SetConfig(conf *FieldConfig) *Field {
f.Config = conf
return f
}
// Labels are used to add metadata to an object.
type Labels map[string]string
// Equals returns true if the argument has the same k=v pairs as the receiver.
func (l Labels) Equals(arg Labels) bool {
if len(l) != len(arg) {
return false
}
for k, v := range l {
if argVal, ok := arg[k]; !ok || argVal != v {
return false
}
}
return true
}
// Contains returns true if all k=v pairs of the argument are in the receiver.
func (l Labels) Contains(arg Labels) bool {
if len(arg) > len(l) {
return false
}
for k, v := range arg {
if argVal, ok := l[k]; !ok || argVal != v {
return false
}
}
return true
}
func (l Labels) String() string {
// Better structure, should be sorted, copy prom probably
keys := make([]string, len(l))
i := 0
for k := range l {
keys[i] = k
i++
}
sort.Strings(keys)
var sb strings.Builder
i = 0
for _, k := range keys {
sb.WriteString(k)
sb.WriteString("=")
sb.WriteString(l[k])
if i != len(keys)-1 {
sb.WriteString(", ")
}
i++
}
return sb.String()
}
// LabelsFromString parses the output of Labels.String() into
// a Labels object. It probably has some flaws.
func LabelsFromString(s string) (Labels, error) {
if s == "" {
return nil, nil
}
labels := make(map[string]string)
for _, rawKV := range strings.Split(s, ", ") {
kV := strings.SplitN(rawKV, "=", 2)
if len(kV) != 2 {
return nil, fmt.Errorf(`invalid label key=value pair "%v"`, rawKV)
}
labels[kV[0]] = kV[1]
}
return labels, nil
}
// New returns a new instance of a Frame.
func New(name string, fields ...*Field) *Frame {
return &Frame{
Name: name,
Fields: fields,
}
}
// Rows returns the number of rows in the frame.
func (f *Frame) Rows() int {
if len(f.Fields) > 0 {
return f.Fields[0].Len()
}
return 0
}