github.com/go-graphite/carbonapi@v0.17.0/expr/types/list.go (about)

     1  package types
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"math"
     7  	"strings"
     8  )
     9  
    10  // FunctionType is a special type to handle parameter type in function description
    11  type FunctionType int
    12  
    13  const (
    14  	// AggFunc is a constant for AggregationFunction type
    15  	AggFunc FunctionType = iota
    16  	// Boolean is a constant for Boolean type
    17  	Boolean
    18  	// Date is a constant for Date type
    19  	Date
    20  	// Float is a constant for Float type
    21  	Float
    22  	// IntOrInterval is a constant for Interval-Or-Integer type
    23  	IntOrInterval
    24  	// Integer is a constant for Integer type
    25  	Integer
    26  	// Interval is a constant for Interval type
    27  	Interval
    28  	// Node is a constant for Node type
    29  	Node
    30  	// NodeOrTag is a constant for Node-Or-Tag type
    31  	NodeOrTag
    32  	// SeriesList is a constant for SeriesList type
    33  	SeriesList
    34  	// SeriesLists is a constant for SeriesLists type
    35  	SeriesLists
    36  	// String is a constant for String type
    37  	String
    38  	// Tag is a constant for Tag type
    39  	Tag
    40  	// Any is a constant for `Any` type
    41  	Any
    42  	// AggOrSeriesFunc is a constant for AggregationFunction or SeriesList
    43  	AggOrSeriesFunc
    44  	// IntOrInf is a constant for Integer that can be infinity
    45  	IntOrInf
    46  )
    47  
    48  var strToFunctionType = map[string]FunctionType{
    49  	"aggFunc":         AggFunc,
    50  	"boolean":         Boolean,
    51  	"date":            Date,
    52  	"float":           Float,
    53  	"intOrInterval":   IntOrInterval,
    54  	"integer":         Integer,
    55  	"interval":        Interval,
    56  	"node":            Node,
    57  	"nodeOrTag":       NodeOrTag,
    58  	"seriesList":      SeriesList,
    59  	"seriesLists":     SeriesLists,
    60  	"string":          String,
    61  	"tag":             Tag,
    62  	"any":             Any,
    63  	"aggOrSeriesFunc": AggOrSeriesFunc,
    64  	"intOrInf":        IntOrInf,
    65  }
    66  
    67  // FunctionTypeToStr provides a mapping between internal type constants and graphite-friendly string that have a name of a type
    68  var FunctionTypeToStr = map[FunctionType]string{
    69  	AggFunc:         "aggFunc",
    70  	Boolean:         "boolean",
    71  	Date:            "date",
    72  	Float:           "float",
    73  	IntOrInterval:   "intOrInterval",
    74  	Integer:         "integer",
    75  	Interval:        "interval",
    76  	Node:            "node",
    77  	NodeOrTag:       "nodeOrTag",
    78  	SeriesList:      "seriesList",
    79  	SeriesLists:     "seriesLists",
    80  	String:          "string",
    81  	Tag:             "tag",
    82  	Any:             "any",
    83  	AggOrSeriesFunc: "aggOrSeriesFunc",
    84  	IntOrInf:        "intOrInf",
    85  }
    86  
    87  // MarshalJSON marshals metric data to JSON
    88  func (t FunctionType) MarshalJSON() ([]byte, error) {
    89  	v, ok := FunctionTypeToStr[t]
    90  	if ok {
    91  		return json.Marshal(v)
    92  	}
    93  
    94  	return nil, fmt.Errorf("unknown type specified: %v", t)
    95  }
    96  
    97  func (t *FunctionType) UnmarshalJSON(d []byte) error {
    98  	var err error
    99  	s := strings.Trim(string(d), "\n\t \"")
   100  	v, ok := strToFunctionType[s]
   101  	if ok {
   102  		*t = v
   103  	} else {
   104  		err = fmt.Errorf("failed to parse value '%v'", string(d))
   105  	}
   106  
   107  	return err
   108  }
   109  
   110  type SuggestionTypes int
   111  
   112  const (
   113  	SInt SuggestionTypes = iota
   114  	SInt32
   115  	SInt64
   116  	SUint
   117  	SUint32
   118  	SUint64
   119  	SFloat64
   120  	SString
   121  	SBool
   122  	SNone
   123  )
   124  
   125  type Suggestion struct {
   126  	Type  SuggestionTypes
   127  	Value interface{}
   128  }
   129  
   130  func NewSuggestion(arg interface{}) *Suggestion {
   131  	switch v := arg.(type) {
   132  	case int:
   133  		return &Suggestion{Type: SInt, Value: v}
   134  	case int32:
   135  		return &Suggestion{Type: SInt32, Value: v}
   136  	case int64:
   137  		return &Suggestion{Type: SInt64, Value: v}
   138  	case uint:
   139  		return &Suggestion{Type: SUint, Value: v}
   140  	case uint32:
   141  		return &Suggestion{Type: SUint32, Value: v}
   142  	case uint64:
   143  		return &Suggestion{Type: SUint64, Value: v}
   144  	case float64:
   145  		return &Suggestion{Type: SFloat64, Value: v}
   146  	case string:
   147  		return &Suggestion{Type: SString, Value: v}
   148  	case bool:
   149  		return &Suggestion{Type: SBool, Value: v}
   150  	}
   151  
   152  	return &Suggestion{Type: SNone}
   153  }
   154  
   155  func NewSuggestions(vaArgs ...interface{}) []*Suggestion {
   156  	res := make([]*Suggestion, 0, len(vaArgs))
   157  
   158  	for _, a := range vaArgs {
   159  		res = append(res, NewSuggestion(a))
   160  	}
   161  
   162  	return res
   163  }
   164  
   165  // MarshalJSON marshals metric data to JSON
   166  func (t Suggestion) MarshalJSON() ([]byte, error) {
   167  	switch t.Type {
   168  	case SInt:
   169  		return json.Marshal(t.Value.(int))
   170  	case SInt32:
   171  		return json.Marshal(t.Value.(int32))
   172  	case SInt64:
   173  		return json.Marshal(t.Value.(int64))
   174  	case SUint:
   175  		return json.Marshal(t.Value.(uint))
   176  	case SUint32:
   177  		return json.Marshal(t.Value.(int64))
   178  	case SUint64:
   179  		return json.Marshal(t.Value.(uint64))
   180  	case SFloat64:
   181  		fVal := t.Value.(float64)
   182  		if math.IsInf(fVal, 1) {
   183  			return []byte("1e9999"), nil
   184  		}
   185  		if math.IsInf(fVal, -1) {
   186  			return []byte("-1e9999"), nil
   187  		}
   188  		return json.Marshal(fVal)
   189  	case SString:
   190  		return json.Marshal(t.Value.(string))
   191  	case SBool:
   192  		return json.Marshal(t.Value.(bool))
   193  	case SNone:
   194  		return []byte{}, nil
   195  	}
   196  
   197  	return nil, fmt.Errorf("unknown type %v", t.Type)
   198  }
   199  
   200  func (t *Suggestion) UnmarshalJSON(d []byte) error {
   201  	if len(d) == 0 {
   202  		t.Type = SNone
   203  		return nil
   204  	}
   205  
   206  	var res interface{}
   207  	err := json.Unmarshal(d, &res)
   208  	if err != nil {
   209  		switch string(d) {
   210  		case "1e9999":
   211  			res = math.Inf(1)
   212  		case "-1e9999":
   213  			res = math.Inf(-1)
   214  		default:
   215  			return err
   216  		}
   217  	}
   218  	switch v := res.(type) {
   219  	case int:
   220  		t.Type = SInt
   221  		t.Value = v
   222  	case int32:
   223  		t.Type = SInt32
   224  		t.Value = v
   225  	case int64:
   226  		t.Type = SInt64
   227  		t.Value = v
   228  	case float64:
   229  		t.Type = SFloat64
   230  		t.Value = v
   231  	case string:
   232  		t.Type = SString
   233  		t.Value = v
   234  	case bool:
   235  		t.Type = SBool
   236  		t.Value = v
   237  	case nil:
   238  		t.Type = SNone
   239  		t.Value = nil
   240  	default:
   241  		return fmt.Errorf("unknown type for suggestion: %v, %T", string(d), v)
   242  	}
   243  
   244  	return nil
   245  }
   246  
   247  type Option struct {
   248  	Type  SuggestionTypes
   249  	Value interface{}
   250  }
   251  
   252  func StringsToSuggestionList(in []string) []Suggestion {
   253  	res := make([]Suggestion, 0, len(in))
   254  
   255  	for _, v := range in {
   256  		res = append(res, Suggestion{Type: SString, Value: v})
   257  	}
   258  	return res
   259  }
   260  
   261  // FunctionParam contains list of all available parameters of function
   262  type FunctionParam struct {
   263  	Name        string        `json:"name"`
   264  	Multiple    bool          `json:"multiple,omitempty"`
   265  	Required    bool          `json:"required,omitempty"`
   266  	Type        FunctionType  `json:"type,omitempty"`
   267  	Options     []Suggestion  `json:"options,omitempty"`
   268  	Suggestions []*Suggestion `json:"suggestions,omitempty"`
   269  	Default     *Suggestion   `json:"default,omitempty"`
   270  }
   271  
   272  // FunctionDescription contains full function description.
   273  type FunctionDescription struct {
   274  	Description string          `json:"description"`
   275  	Function    string          `json:"function"`
   276  	Group       string          `json:"group"`
   277  	Module      string          `json:"module"`
   278  	Name        string          `json:"name"`
   279  	Params      []FunctionParam `json:"params,omitempty"`
   280  
   281  	Proxied bool `json:"proxied"`
   282  
   283  	SeriesChange bool `json:"aggregate,omitempty"`       //  function aggregate metrics, for tests and verify results in future
   284  	NameChange   bool `json:"name-change,omitempty"`     // function change name, for tests and verify results in future
   285  	TagsChange   bool `json:"name-tag-change,omitempty"` //  function change name tag, for tests and verify results in future
   286  	ValuesChange bool `json:"values-change,omitempty"`   //  function change values, for tests and verify results in future
   287  }