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 }