mirror of https://github.com/grafana/grafana.git
275 lines
5.4 KiB
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
|
|
}
|