data

package
v0.37.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 7, 2020 License: Apache-2.0 Imports: 19 Imported by: 277

README

data

Testing

This package uses golden files to verify Arrow serialization.

Add the update flag to go test to update the golden files:

go test -update

Make sure you check in any updated golden files.

Documentation

Overview

Package data provides data structures that Grafana recognizes.

The Frame object represents a Grafana Dataframe which can represent data such as tables and time series.

Frames can be encoded using Apache Arrow (https://arrow.apache.org/) for transmission.

The corresponding Grafana frontend package the @grafana/data package (https://github.com/grafana/grafana/tree/master/packages/grafana-data).

Index

Examples

Constants

This section is empty.

Variables

View Source
var AsStringFieldConverter = FieldConverter{
	OutputFieldType: FieldTypeString,
	Converter:       asStringConverter,
}

AsStringFieldConverter will always return a string a regardless of the input. This is done with fmt.Sprintf which uses reflection.

Functions

func FrameTestCompareOptions

func FrameTestCompareOptions() []cmp.Option

FrameTestCompareOptions returns go-cmp testing options to allow testing of Frame equivelnce. Since the data within a Frame's Fields is not exported, this function allows the unexported values to be tested. The intent is to only use this for testing.

func FramesToBytesSlice added in v0.35.0

func FramesToBytesSlice(frames []*Frame) ([][]byte, error)

FramesToBytesSlice encodes a slice of Frames into a slice of []byte.

func MarshalArrow

func MarshalArrow(f *Frame) ([]byte, error)

MarshalArrow converts the Frame to an arrow table and returns a byte representation of that table.

func Replace

func Replace(frame *Frame, fieldIdx int, replacer *StringFieldReplacer) error

Replace will replace a *string Vector of the specified Field's index using the StringFieldReplacer.

Example
package main

import (
	"fmt"
	"strconv"

	"github.com/grafana/grafana-plugin-sdk-go/data"
)

func main() {
	i := 0
	getString := func() *string {
		i++
		s := strconv.Itoa(i)
		return &s
	}

	frame := data.NewFrame("Before",
		data.NewField("string", nil, []*string{getString(), getString()}))

	fmt.Println(frame.String()) // Before

	intReplacer := &data.StringFieldReplacer{
		VectorType: []*int64{},
		ReplaceFunc: func(in *string) (interface{}, error) {
			if in == nil {
				return nil, nil
			}
			v, err := strconv.ParseInt(*in, 10, 64)
			if err != nil {
				return nil, err
			}
			return &v, nil
		},
	}

	err := data.Replace(frame, 0, intReplacer)
	if err != nil {
		// return err
	}

	frame.Name = "After"
	fmt.Println(frame.String()) // After
}
Output:

Name: Before
Dimensions: 1 Fields by 2 Rows
+-----------------+
| Name: string    |
| Labels:         |
| Type: []*string |
+-----------------+
| 1               |
| 2               |
+-----------------+

Name: After
Dimensions: 1 Fields by 2 Rows
+----------------+
| Name: string   |
| Labels:        |
| Type: []*int64 |
+----------------+
| 1              |
| 2              |
+----------------+

func ValidFieldType

func ValidFieldType(t interface{}) bool

ValidFieldType returns if a primitive slice is a valid supported Field type.

Types

type ConfFloat64

type ConfFloat64 float64

ConfFloat64 is a float64. It Marshals float64 values of NaN of Inf to null.

func (*ConfFloat64) MarshalJSON

func (sf *ConfFloat64) MarshalJSON() ([]byte, error)

MarshalJSON fullfills the json.Marshaler interface.

func (*ConfFloat64) UnmarshalJSON

func (sf *ConfFloat64) UnmarshalJSON(data []byte) error

UnmarshalJSON fullfills the json.Unmarshaler interface.

type Converter added in v0.36.0

type Converter func(v interface{}) (interface{}, error)

Converter is a function type for converting values in a Frame. It is the consumers responsibility to the check the underlying interface types of the input and return types to avoid panics.

type DataLink struct {
	Title       string `json:"title,omitempty"`
	TargetBlank bool   `json:"targetBlank,omitempty"`
	URL         string `json:"url,omitempty"`
}

DataLink define what

type Field

type Field struct {
	Name   string
	Config *FieldConfig

	Labels Labels
	// contains filtered or unexported fields
}

Field represents a typed column of data within a Frame. The data in the Field is a not exported, so methods on the Field are used to to manipulate its data.

func NewField

func NewField(name string, labels Labels, values interface{}) *Field

NewField returns a instance of *Field.

Supported types for values are: []int8, []*int8, []int16, []*int16, []int32, []*int32, []int64, []*int64, []uint8, []*uint8, []uint16, []*uint16, []uint32, []*uint32, []uint64, []*uint64, []float32, []*float32, []float64, []*float64, []string, []*string, []bool, []*bool, []time.Time, and []*time.Time.

If an unsupported values type is passed, NewField will panic.

func NewFieldFromFieldType

func NewFieldFromFieldType(p FieldType, n int) *Field

NewFieldFromFieldType creates a new Field of the given pType of length n.

func (*Field) Append

func (f *Field) Append(i interface{})

Append appends element i to the Field.

func (*Field) At

func (f *Field) At(idx int) interface{}

At returns the the element at index idx of the Field. It will panic if idx is out of range.

func (*Field) ConcreteAt

func (f *Field) ConcreteAt(idx int) (val interface{}, ok bool)

ConcreteAt returns the concrete value at the specified index idx. A non-pointer type is returned regardless if the underlying vector is a pointer type or not. If the value is a pointer type, and is nil, then the zero value is returned and ok will be false.

func (*Field) CopyAt

func (f *Field) CopyAt(idx int) interface{}

CopyAt returns a copy of the value of the specified index idx. It will panic if idx is out of range.

func (*Field) Extend

func (f *Field) Extend(i int)

Extend extends the Field length by i.

func (*Field) FloatAt added in v0.31.0

func (f *Field) FloatAt(idx int) (float64, error)

FloatAt returns a float64 at the specified index idx. It will panic if idx is out of range. If the Field type is numeric and the value at idx is nil, NaN is returned. Precision may be lost on large numbers. If the Field type is a bool then 0 is return if false or nil, and 1 if true. If the Field type is time.Time, then the millisecond epoch representation of the time is returned, or NaN is the value is nil. If the Field type is a string, then strconv.ParseFloat is called on it and will return an error if ParseFloat errors. If the value is nil, NaN is returned.

func (*Field) Len

func (f *Field) Len() int

Len returns the number of elements in the Field.

func (*Field) Nullable

func (f *Field) Nullable() bool

Nullable returns if the the Field's elements are nullable.

func (*Field) PointerAt

func (f *Field) PointerAt(idx int) interface{}

PointerAt returns a pointer to the value at idx of the Field. It will panic if idx is out of range.

func (*Field) Set

func (f *Field) Set(idx int, val interface{})

Set sets the Field's value at index idx to val. It will panic if idx is out of range.

func (*Field) SetConfig

func (f *Field) SetConfig(conf *FieldConfig) *Field

SetConfig modifies the Field's Config property to be set to conf and returns the Field.

func (*Field) Type

func (f *Field) Type() FieldType

Type returns the underlying primitive type of the Field.

type FieldConfig

type FieldConfig struct {
	Title      string `json:"title,omitempty"`
	Filterable *bool  `json:"filterable,omitempty"` // indicates if the Field's data can be filtered by additional calls.

	// Numeric Options
	Unit     string       `json:"unit,omitempty"`     // is the string to display to represent the Field's unit, such as "Requests/sec"
	Decimals *uint16      `json:"decimals,omitempty"` // is the number of decimal places to display
	Min      *ConfFloat64 `json:"min,omitempty"`      // is the maximum value of fields in the column. When present the frontend can skip the calculation.
	Max      *ConfFloat64 `json:"max,omitempty"`      // see Min

	// Convert input values into a display string
	Mappings []ValueMapping `json:"mappings,omitempty"`

	// Map numeric values to states
	Thresholds *ThresholdsConfig `json:"thresholds,omitempty"`

	// Map values to a display color
	// NOTE: this interface is under development in the frontend... so simple map for now
	Color map[string]interface{} `json:"color,omitempty"`

	// Used when reducing field values
	NullValueMode NullValueMode `json:"nullValueMode,omitempty"`

	// The behavior when clicking on a result
	Links []DataLink `json:"links,omitempty"`

	// Alternative to empty string
	NoValue string `json:"noValue,omitempty"`

	// Panel Specific Values
	Custom map[string]interface{} `json:"custom,omitempty"`
}

FieldConfig represents the display properties for a Field.

func (*FieldConfig) SetDecimals

func (fc *FieldConfig) SetDecimals(v uint16) *FieldConfig

SetDecimals modifies the FieldConfig's Decimals property to be set to v and returns the FieldConfig. It is a convenance function since the Decimals property is a pointer.

func (*FieldConfig) SetFilterable

func (fc *FieldConfig) SetFilterable(b bool) *FieldConfig

SetFilterable modifies the FieldConfig's Filterable property to be set to b and returns the FieldConfig. It is a convenance function since the Filterable property is a pointer.

func (*FieldConfig) SetMax

func (fc *FieldConfig) SetMax(v float64) *FieldConfig

SetMax modifies the FieldConfig's Max property to be set to v and returns the FieldConfig. It is a convenance function since the Min property is a pointer.

func (*FieldConfig) SetMin

func (fc *FieldConfig) SetMin(v float64) *FieldConfig

SetMin modifies the FieldConfig's Min property to be set to v and returns the FieldConfig. It is a convenance function since the Min property is a pointer.

type FieldConverter added in v0.36.0

type FieldConverter struct {
	// OutputFieldType is the type of Field that will be created.
	OutputFieldType FieldType

	// Converter is a conversion function that is called when setting Field values with a FrameInputConverter.
	// Care must be taken that the type returned by the conversion function matches the member type of the FieldType,
	// and that the input type matches the expected input type for the Converter function, or panics can occur.
	// If the Converter is nil, no conversion is performed when calling methods to set values.
	Converter Converter
}

A FieldConverter is a type to support building Frame fields of a different type than one's input data.

type FieldType

type FieldType int

FieldType indicates the Go type underlying the Field.

const (
	// FieldTypeInt8 indicates the underlying primitive is a []int8.
	FieldTypeInt8 FieldType = iota
	// FieldTypeNullableInt8 indicates the underlying primitive is a []*int8.
	FieldTypeNullableInt8

	// FieldTypeInt16 indicates the underlying primitive is a []Int16.
	FieldTypeInt16
	// FieldTypeNullableInt16 indicates the underlying primitive is a []*Int16.
	FieldTypeNullableInt16

	// FieldTypeInt32 indicates the underlying primitive is a []int32.
	FieldTypeInt32
	// FieldTypeNullableInt32 indicates the underlying primitive is a []*int32.
	FieldTypeNullableInt32

	// FieldTypeInt64 indicates the underlying primitive is a []int64.
	FieldTypeInt64
	// FieldTypeNullableInt64 indicates the underlying primitive is a []*int64.
	FieldTypeNullableInt64

	// FieldTypeUint8 indicates the underlying primitive is a []int8.
	FieldTypeUint8
	// FieldTypeNullableUint8 indicates the underlying primitive is a []*int8.
	FieldTypeNullableUint8

	// FieldTypeUint16 indicates the underlying primitive is a []uint16.
	FieldTypeUint16
	// FieldTypeNullableUint16 indicates the underlying primitive is a []*uint16.
	FieldTypeNullableUint16

	// FieldTypeUint32 indicates the underlying primitive is a []uint32.
	FieldTypeUint32
	// FieldTypeNullableUint32 indicates the underlying primitive is a []*uint32.
	FieldTypeNullableUint32

	// FieldTypeUint64 indicates the underlying primitive is a []uint64.
	FieldTypeUint64
	// FieldTypeNullableUint64 indicates the underlying primitive is a []*uint64.
	FieldTypeNullableUint64

	// FieldTypeFloat32 indicates the underlying primitive is a []float32.
	FieldTypeFloat32
	// FieldTypeNullableFloat32 indicates the underlying primitive is a []*float32.
	FieldTypeNullableFloat32

	// FieldTypeFloat64 indicates the underlying primitive is a []float64.
	FieldTypeFloat64
	// FieldTypeNullableFloat64 indicates the underlying primitive is a []*float64.
	FieldTypeNullableFloat64

	// FieldTypeString indicates the underlying primitive is a []string.
	FieldTypeString
	// FieldTypeNullableString indicates the underlying primitive is a []*string.
	FieldTypeNullableString

	// FieldTypeBool indicates the underlying primitive is a []bool.
	FieldTypeBool
	// FieldTypeNullableBool indicates the underlying primitive is a []*bool.
	FieldTypeNullableBool

	// FieldTypeTime indicates the underlying primitive is a []time.Time.
	FieldTypeTime
	// FieldTypeNullableTime indicates the underlying primitive is a []*time.Time.
	FieldTypeNullableTime
)

func NumericFieldTypes

func NumericFieldTypes() []FieldType

NumericFieldTypes returns a slice of FieldTypes that are numeric.

func (FieldType) ItemTypeString

func (p FieldType) ItemTypeString() string

ItemTypeString returns the string representation of the type of element within in the vector

func (FieldType) Nullable

func (p FieldType) Nullable() bool

Nullable returns if Field type is a nullable type

func (FieldType) Numeric added in v0.31.0

func (p FieldType) Numeric() bool

Numeric returns if Field type is a nullable type

func (FieldType) String

func (p FieldType) String() string

type Fields

type Fields []*Field

Fields is a slice of Field pointers.

type Frame

type Frame struct {
	Name   string
	Fields []*Field

	RefID    string
	Meta     *FrameMeta
	Warnings []Warning
}

Frame represents a columnar storage with optional labels. Each Field in Fields represents a column, all Fields must be of the same the length.

func BytesSliceToFrames added in v0.35.0

func BytesSliceToFrames(bFrames [][]byte) ([]*Frame, error)

BytesSliceToFrames decodes a slice of encoded Arrow frames to a slice of *Frame.

func LongToWide

func LongToWide(longFrame *Frame) (*Frame, error)

LongToWide converts a Long formated time series Frame to a Wide format (see TimeSeriesType for descriptions). The first Field of type time.Time or *time.Time will be the time index for the series, and will be the first field of the outputted longFrame.

During conversion: String Fields in the longFrame become Labels on the Fields of wideFrame. The name of each string Field becomes a label key, and the values of that Field become label values. Each unique combination of value Fields and set of Label key/values become a Field of longFrame.

Additionally, if the time index is a *time.Time field, it will become time.Time Field. If a *string Field has nil values, they are equivalent to "" when converted into labels.

An error is returned if any of the following are true: The input frame is not a long formated time series frame. The input frame's Fields are of length 0. The time index is not sorted ascending by time. The time index has null values.

With a conversion of Long to Wide, and then back to Long via WideToLong(), the outputted Long Frame may not match the original inputted Long frame.

func NewFrame

func NewFrame(name string, fields ...*Field) *Frame

NewFrame returns a new instance of a Frame.

Example
package main

import (
	"fmt"
	"math"
	"time"

	"github.com/grafana/grafana-plugin-sdk-go/data"
)

func main() {
	aTime := time.Date(2020, 1, 2, 3, 4, 5, 0, time.UTC)
	var anInt64 int64 = 12
	frame := data.NewFrame("Frame Name",
		data.NewField("Time", nil, []time.Time{aTime, aTime.Add(time.Minute)}),
		data.NewField("Temp", data.Labels{"place": "Ecuador"}, []float64{1, math.NaN()}),
		data.NewField("Count", data.Labels{"place": "Ecuador"}, []*int64{&anInt64, nil}),
	)
	fmt.Println(frame.String())
}
Output:

Name: Frame Name
Dimensions: 3 Fields by 2 Rows
+-------------------------------+-----------------------+-----------------------+
| Name: Time                    | Name: Temp            | Name: Count           |
| Labels:                       | Labels: place=Ecuador | Labels: place=Ecuador |
| Type: []time.Time             | Type: []float64       | Type: []*int64        |
+-------------------------------+-----------------------+-----------------------+
| 2020-01-02 03:04:05 +0000 UTC | 1                     | 12                    |
| 2020-01-02 03:05:05 +0000 UTC | NaN                   | null                  |
+-------------------------------+-----------------------+-----------------------+

func NewFrameOfFieldTypes added in v0.36.0

func NewFrameOfFieldTypes(name string, fieldLen int, fTypes ...FieldType) *Frame

NewFrameOfFieldTypes returns a Frame where the Fields are initalized to the corresponding field type in fTypes. Each Field will be of length FieldLen.

func NewFromSQLRows

func NewFromSQLRows(rows *sql.Rows, converters ...SQLStringConverter) (*Frame, map[int]SQLStringConverter, error)

NewFromSQLRows returns a new Frame populated with the data from rows. The Field Vector types will be Vectors of pointer types, []*T, if the SQL column is nullable or if the nullable property is unknown. Otherwise, they will be []T types.

Fields will be named to match name of the SQL columns and the SQL column names must be unique (https://github.com/grafana/grafana-plugin-sdk-go/issues/59).

All the types must be supported by the Frame or a SQLStringConverter will be created and the resulting Field Vector type will be of type []*string.

The SQLStringConverter's ConversionFunc will be applied to matching rows if it is not nil. Additionally, if the SQLStringConverter's Replacer is not nil, the replacement will be performed. A map of Field/Column index to the corresponding SQLStringConverter is returned so what conversions were done can be inspected.

Example
package main

import (
	"database/sql"

	"github.com/grafana/grafana-plugin-sdk-go/data"
)

func main() {
	aQuery := "SELECT * FROM GoodData"
	db, err := sql.Open("fancySql", "fancysql://user:pass@localhost:1433")
	if err != nil {
		// return err
	}

	defer db.Close()

	rows, err := db.Query(aQuery)
	if err != nil {
		// return err
	}
	defer rows.Close()

	frame, mappings, err := data.NewFromSQLRows(rows)
	if err != nil {
		// return err
	}
	_, _ = frame, mappings
}
Output:

func UnmarshalArrow

func UnmarshalArrow(b []byte) (*Frame, error)

UnmarshalArrow converts a byte representation of an arrow table to a Frame

func WideToLong

func WideToLong(wideFrame *Frame) (*Frame, error)

WideToLong converts a Wide formated time series Frame to a Long formated time series Frame (see TimeSeriesType for descriptions). The first Field of type time.Time or *time.Time in wideFrame will be the time index for the series, and will be the first field of the outputted wideFrame.

During conversion: All the unique keys in all of the Labels across the Fields of wideFrame become string Fields with the corresponding name in longFrame. The corresponding Labels values become values in those Fields of longFrame. For each unique non-timeIndex Field across the Fields of wideFrame (value fields), a Field of the same type is created in longFrame. For each unique set of Labels across the Fields of wideFrame, a row is added to longFrame, and then for each unique value Field, the corresponding value Field of longFrame is set.

An error is returned if any of the following are true: The input frame is not a wide formated time series frame. The input row has no rows. The time index not sorted ascending by time. The time index has null values. Two numeric Fields have the same name but different types.

With a conversion of Wide to Long, and then back to Wide via LongToWide(), the outputted Wide Frame may not match the original inputted Wide frame.

func (*Frame) AppendRow

func (f *Frame) AppendRow(vals ...interface{})

AppendRow adds a new row to the Frame by appending to each element of vals to the corresponding Field in the data. The Frame's Fields must be initalized or AppendRow will panic. The number of arguments must match the number of Fields in the Frame and each type must coorespond to the Field type or AppendRow will panic.

func (*Frame) AppendRowSafe

func (f *Frame) AppendRowSafe(vals ...interface{}) error

AppendRowSafe adds a new row to the Frame by appending to each each element of vals to the corresponding Field in the data. It has the some constraints as AppendRow but will return an error under those conditions instead of panicing.

func (*Frame) AppendWarning

func (f *Frame) AppendWarning(message string, details string)

AppendWarning adds warnings to the data frame.

func (*Frame) At

func (f *Frame) At(fieldIdx int, rowIdx int) interface{}

At returns the value of the specified fieldIdx and rowIdx. It will panic if either the fieldIdx or rowIdx are out of range.

func (*Frame) ConcreteAt

func (f *Frame) ConcreteAt(fieldIdx int, rowIdx int) (val interface{}, ok bool)

ConcreteAt returns the concrete value at the specified fieldIdx and rowIdx. A non-pointer type is returned regardless if the underlying type is a pointer type or not. If the value is a pointer type, and is nil, then the zero value is returned and ok will be false.

func (*Frame) CopyAt

func (f *Frame) CopyAt(fieldIdx int, rowIdx int) interface{}

CopyAt returns a copy of the value of the specified fieldIdx and rowIdx. It will panic if either the fieldIdx or rowIdx are out of range.

func (*Frame) EmptyCopy added in v0.28.0

func (f *Frame) EmptyCopy() *Frame

EmptyCopy returns a copy of Frame f but with Fields of zero length, and no copy of the FieldConfigs, Metadata, or Warnings.

func (*Frame) Extend

func (f *Frame) Extend(i int)

Extend extends all the Fields by length by i.

func (*Frame) FilterRowsByField added in v0.28.0

func (f *Frame) FilterRowsByField(fieldIdx int, filter func(i interface{}) (bool, error)) (*Frame, error)

FilterRowsByField returns a copy of frame f (as per EmptyCopy()) that includes rows where the filter returns true and no error. If filter returns an error, then an error is returned.

func (*Frame) FloatAt added in v0.31.0

func (f *Frame) FloatAt(fieldIdx int, rowIdx int) (float64, error)

FloatAt returns a float64 representation of value of the specified fieldIdx and rowIdx as per Field.FloatAt(). It will panic if either the fieldIdx or rowIdx are out of range.

func (*Frame) RowCopy added in v0.28.0

func (f *Frame) RowCopy(rowIdx int) []interface{}

RowCopy returns an interface slice that contains the values of each Field for the given rowIdx.

func (*Frame) RowLen

func (f *Frame) RowLen() (int, error)

RowLen returns the the length of the Frame Fields. If the Length of all the Fields is not the same then error is returned. If the Frame's Fields are nil an error is returned.

func (*Frame) Rows

func (f *Frame) Rows() int

Rows returns the number of rows in the frame.

func (*Frame) Set

func (f *Frame) Set(fieldIdx int, rowIdx int, val interface{})

Set set the val to the specified fieldIdx and rowIdx. It will panic if either the fieldIdx or rowIdx are out of range.

func (*Frame) SetFieldNames added in v0.36.0

func (f *Frame) SetFieldNames(names ...string) error

SetFieldNames sets each Field Name in the frame to the corresponding frame. If the number of provided names does not match the number of Fields in the frame an error is returned.

func (*Frame) String added in v0.32.0

func (f *Frame) String() string

func (*Frame) StringTable added in v0.32.0

func (f *Frame) StringTable(maxFields, maxRows int) (string, error)

StringTable prints a human readable table of the Frame. The table's width is limited to maxFields and the length is limited to maxRows. If the width or length is excceded then last column or row displays "..." as the contents.

func (*Frame) TimeSeriesSchema

func (f *Frame) TimeSeriesSchema() (tsSchema TimeSeriesSchema)

TimeSeriesSchema returns the TimeSeriesSchema of the frame. The TimeSeriesSchema's Type value will be TimeSeriesNot if it is not a time series.

func (*Frame) TypeIndices

func (f *Frame) TypeIndices(fTypes ...FieldType) []int

TypeIndices returns a slice of Field index positions for the given fTypes.

type FrameInputConverter added in v0.36.0

type FrameInputConverter struct {
	Frame *Frame
	// contains filtered or unexported fields
}

FrameInputConverter is a type to support building a Frame while also doing conversion as data is added to the Frame.

func NewFrameInputConverter added in v0.36.0

func NewFrameInputConverter(fieldConvs []FieldConverter, rowLen int) (*FrameInputConverter, error)

NewFrameInputConverter returns a FrameInputConverter which is used to create a Frame from data that needs value conversions. The FrameInputConverter will create a new Frame with fields based on the FieldConverters' OutputFieldTypes of length rowLen.

Example
package main

import (
	"fmt"
	"log"
	"strconv"
	"time"

	"github.com/grafana/grafana-plugin-sdk-go/data"
)

func main() {
	inputData := struct { // inputData is a pretend table-like structure response from an API.
		ColumnTypes []string
		ColumnNames []string
		Rows        [][]string
	}{
		[]string{
			"Stringz",
			"Floatz",
			"Timez",
		},
		[]string{
			"Animal",
			"Weight (lbs)",
			"Time",
		},
		[][]string{
			[]string{"sloth", "3.5", "1586014367"},
			[]string{"sloth", "5.5", "1586100767"},
			[]string{"sloth", "7", "1586187167"},
		},
	}

	// Build field converters appropriate for converting out pretend data structure.
	stringzFieldConverter := data.FieldConverter{
		OutputFieldType: data.FieldTypeString,
		// No Converter, string = string
	}
	floatzFieldConverter := data.FieldConverter{ // a converter appropriate for our pretend API's Floatz type.
		OutputFieldType: data.FieldTypeFloat64,
		Converter: func(v interface{}) (interface{}, error) {
			val, ok := v.(string)
			if !ok { // or return some default value instead of erroring
				return nil, fmt.Errorf("expected string input but got type %T", val)
			}
			return strconv.ParseFloat(val, 64)
		},
	}
	timezFieldConverter := data.FieldConverter{ // a converter appropriate for our pretend API's Timez type.
		OutputFieldType: data.FieldTypeTime,
		Converter: func(v interface{}) (interface{}, error) {
			val, ok := v.(string)
			if !ok { // or return some default value instead of erroring
				return nil, fmt.Errorf("expected string input but got type %T", val)
			}
			iV, err := strconv.ParseInt(val, 10, 64)
			if err != nil {
				return nil, fmt.Errorf("could not parse epoch time into an int64")
			}
			return time.Unix(iV, 0).UTC(), nil
		},
	}

	// a map of pretend API's types to converters
	converterMap := map[string]data.FieldConverter{
		"Stringz": stringzFieldConverter,
		"Floatz":  floatzFieldConverter,
		"Timez":   timezFieldConverter,
	}

	// build a slice of converters for Pretend API known types in the appropriate Field/Column order
	// for this specific response.
	converters := make([]data.FieldConverter, len(inputData.ColumnTypes))
	for i, cType := range inputData.ColumnTypes {
		fc, ok := converterMap[cType]
		if !ok {
			fc = data.AsStringFieldConverter
		}
		converters[i] = fc
	}

	// Get a new FrameInputConverter, which includes a Frame with appropriate Field types and length
	// for out input data.
	convBuilder, err := data.NewFrameInputConverter(converters, len(inputData.Rows))
	if err != nil {
		log.Fatal(err)
	}

	// Set field names
	err = convBuilder.Frame.SetFieldNames(inputData.ColumnNames...)
	if err != nil {
		log.Fatal(err)
	}

	// Insert data into the frame, passing data through the Converters before
	// writing to the frame.
	for rowIdx, row := range inputData.Rows {
		for fieldIdx, cell := range row {
			err = convBuilder.Set(fieldIdx, rowIdx, cell)
			if err != nil {
				log.Fatal(err)
			}
		}
	}
	convBuilder.Frame.Name = "Converted"

	fmt.Println(convBuilder.Frame.String())
}
Output:

Name: Converted
Dimensions: 3 Fields by 3 Rows
+----------------+--------------------+-------------------------------+
| Name: Animal   | Name: Weight (lbs) | Name: Time                    |
| Labels:        | Labels:            | Labels:                       |
| Type: []string | Type: []float64    | Type: []time.Time             |
+----------------+--------------------+-------------------------------+
| sloth          | 3.5                | 2020-04-04 15:32:47 +0000 UTC |
| sloth          | 5.5                | 2020-04-05 15:32:47 +0000 UTC |
| sloth          | 7                  | 2020-04-06 15:32:47 +0000 UTC |
+----------------+--------------------+-------------------------------+

func (*FrameInputConverter) Set added in v0.36.0

func (fcb *FrameInputConverter) Set(fieldIdx, rowIdx int, val interface{}) error

Set sets val a FieldIdx and rowIdx of the frame. If the corresponding FieldConverter's Converter is not nil, then the Converter function is called before setting the value (otherwise Frame.Set is called directly). If an error is returned from the Converter function this function returns that error. Like Frame.Set and Field.Set, it will panic if fieldIdx or rowIdx are out of range.

type FrameMeta added in v0.35.0

type FrameMeta struct {
	// Datasource specific values
	Custom map[string]interface{} `json:"custom,omitempty"`

	// Stats is TODO
	Stats interface{} `json:"stats,omitempty"`

	// Notices is TODO
	Notices interface{} `json:"notices,omitempty"`
}

FrameMeta matches: https://github.com/grafana/grafana/blob/master/packages/grafana-data/src/types/data.ts#L11 NOTE -- in javascript this can accept any `[key: string]: any;` however this interface only exposes the values we want to be exposed

func FrameMetaFromJSON added in v0.35.0

func FrameMetaFromJSON(jsonStr string) (*FrameMeta, error)

FrameMetaFromJSON creates a QueryResultMeta from a json string

type Labels

type Labels map[string]string

Labels are used to add metadata to an object.

func LabelsFromString

func LabelsFromString(s string) (Labels, error)

LabelsFromString parses the output of Labels.String() into a Labels object. It probably has some flaws.

func (Labels) Contains

func (l Labels) Contains(arg Labels) bool

Contains returns true if all k=v pairs of the argument are in the receiver.

func (Labels) Copy added in v0.28.0

func (l Labels) Copy() Labels

Copy returns a copy of the labels.

func (Labels) Equals

func (l Labels) Equals(arg Labels) bool

Equals returns true if the argument has the same k=v pairs as the receiver.

func (Labels) String

func (l Labels) String() string

type MappingType

type MappingType int8

MappingType value or range

const (
	// ValueToText map a value to text
	ValueToText MappingType = iota + 1

	// RangeToText map a range to text
	RangeToText
)

type NullValueMode

type NullValueMode string

NullValueMode say how the UI should show null values

const (
	// NullValueModeNull displays null values
	NullValueModeNull NullValueMode = "null"
	// NullValueModeIgnore sets the display to ignore null values
	NullValueModeIgnore NullValueMode = "connected"
	// NullValueModeAsZero set the display show null values as zero
	NullValueModeAsZero NullValueMode = "null as zero"
)

type SQLStringConverter

type SQLStringConverter struct {
	// Name is an optional property that can be used to identify a converter
	Name          string
	InputScanKind reflect.Kind // reflect.Type might better or worse option?
	InputTypeName string

	// Conversion func may be nil to do no additional operations on the string conversion.
	ConversionFunc func(in *string) (*string, error)

	// If the Replacer is not nil, the replacement will be performed.
	Replacer *StringFieldReplacer
}

SQLStringConverter can be used to store types not supported by a Frame into a *string. When scanning, if a SQL's row's InputScanType's Kind and InputScanKind match that returned by the sql response, then the conversion func will be run on the row.

Example
package main

import (
	"reflect"
	"strconv"

	"github.com/grafana/grafana-plugin-sdk-go/data"
)

func main() {
	_ = data.SQLStringConverter{
		Name:          "BIGINT to *int64",
		InputScanKind: reflect.Struct,
		InputTypeName: "BIGINT",
		Replacer: &data.StringFieldReplacer{
			VectorType: []*int64{},
			ReplaceFunc: func(in *string) (interface{}, error) {
				if in == nil {
					return nil, nil
				}
				v, err := strconv.ParseInt(*in, 10, 64)
				if err != nil {
					return nil, err
				}
				return &v, nil
			},
		},
	}
}
Output:

type StringFieldReplacer

type StringFieldReplacer struct {
	VectorType  interface{}
	ReplaceFunc func(in *string) (interface{}, error)
}

StringFieldReplacer is used to replace a *string Field in a Frame. The type returned by the ReplaceFunc must match the type of elements of VectorType. Both properties must be non-nil.

type Threshold

type Threshold struct {
	Value ConfFloat64 `json:"value,omitempty"` // First value is always -Infinity serialize to null
	Color string      `json:"color,omitempty"`
	State string      `json:"state,omitempty"`
}

Threshold a single step on the threshold list

func NewThreshold

func NewThreshold(value float64, color, state string) Threshold

NewThreshold Creates a new Threshold object

type ThresholdsConfig

type ThresholdsConfig struct {
	Mode ThresholdsMode `json:"mode"`

	// Must be sorted by 'value', first value is always -Infinity
	Steps []Threshold `json:"steps"`
}

ThresholdsConfig setup thresholds

type ThresholdsMode

type ThresholdsMode string

ThresholdsMode absolute or percentage

const (
	// ThresholdsModeAbsolute pick thresholds based on absolute value
	ThresholdsModeAbsolute ThresholdsMode = "absolute"

	// ThresholdsModePercentage the threshold is relative to min/max
	ThresholdsModePercentage ThresholdsMode = "percentage"
)

type TimeSeriesSchema

type TimeSeriesSchema struct {
	Type           TimeSeriesType // the type of series, as determinted by frame.TimeSeriesSchema()
	TimeIndex      int            // Field index of the time series index
	TimeIsNullable bool           // true if the time index is nullable (of *time.Time)
	ValueIndices   []int          // Field indices of value columns (All fields excluding string fields and the time index)
	FactorIndices  []int          // Field indices of string or *string Fields
}

TimeSeriesSchema is information about a Frame's schema. It is populated from the Frame's TimeSeriesSchema() method.

type TimeSeriesType

type TimeSeriesType int

TimeSeriesType represents the type of time series the schema can be treated as (if any).

const (
	// TimeSeriesTypeNot means this Frame is not a valid time series. This means it lacks at least
	// one of a time Field and another (value) Field.
	TimeSeriesTypeNot TimeSeriesType = iota

	// TimeSeriesTypeLong means this Frame can be treated as a "Long" time series.
	//
	// A Long series has one or more string Fields, disregards Labels on Fields, and generally
	// repeated time values in the time index.
	TimeSeriesTypeLong

	// TimeSeriesTypeWide means this Frame can be treated as a "Wide" time series.
	//
	// A Wide series has no string fields, should not have repeated time values, and generally
	// uses labels.
	TimeSeriesTypeWide
)

TODO: Create and link to Grafana documentation on Long vs Wide

func (TimeSeriesType) String

func (t TimeSeriesType) String() string

type ValueMapping

type ValueMapping struct {
	ID       int16       `json:"id"`
	Operator string      `json:"operator"`
	Text     string      `json:"title"`
	Type     MappingType `json:"type"`

	// Only valid for MappingType == ValueMap
	Value string `json:"value,omitempty"`

	// Only valid for MappingType == RangeMap
	From string `json:"from,omitempty"`
	To   string `json:"to,omitempty"`
}

ValueMapping convert input value to something else

type Warning

type Warning struct {
	// Short message (typically shown in the header)
	Message string `json:"message,omitempty"`

	// longer error message, shown in the body
	Details string `json:"details,omitempty"`
}

Warning contains information about problems in a data.

func WarningsFromJSON

func WarningsFromJSON(jsonStr string) ([]Warning, error)

WarningsFromJSON creates a *Warning from a json string.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL