github.com/influxdata/influxdb/v2@v2.7.6/influxql/query/call_iterator.go (about) 1 package query 2 3 import ( 4 "fmt" 5 "math" 6 "sort" 7 "time" 8 9 "github.com/influxdata/influxdb/v2/influxql/query/internal/gota" 10 "github.com/influxdata/influxql" 11 ) 12 13 /* 14 This file contains iterator implementations for each function call available 15 in InfluxQL. Call iterators are separated into two groups: 16 17 1. Map/reduce-style iterators - these are passed to IteratorCreator so that 18 processing can be at the low-level storage and aggregates are returned. 19 20 2. Raw aggregate iterators - these require the full set of data for a window. 21 These are handled by the select() function and raw points are streamed in 22 from the low-level storage. 23 24 There are helpers to aid in building aggregate iterators. For simple map/reduce 25 iterators, you can use the reduceIterator types and pass a reduce function. This 26 reduce function is passed a previous and current value and the new timestamp, 27 value, and auxiliary fields are returned from it. 28 29 For raw aggregate iterators, you can use the reduceSliceIterators which pass 30 in a slice of all points to the function and return a point. For more complex 31 iterator types, you may need to create your own iterators by hand. 32 33 Once your iterator is complete, you'll need to add it to the NewCallIterator() 34 function if it is to be available to IteratorCreators and add it to the select() 35 function to allow it to be included during planning. 36 */ 37 38 // NewCallIterator returns a new iterator for a Call. 39 func NewCallIterator(input Iterator, opt IteratorOptions) (Iterator, error) { 40 name := opt.Expr.(*influxql.Call).Name 41 switch name { 42 case "count": 43 return newCountIterator(input, opt) 44 case "min": 45 return newMinIterator(input, opt) 46 case "max": 47 return newMaxIterator(input, opt) 48 case "sum": 49 return newSumIterator(input, opt) 50 case "first": 51 return newFirstIterator(input, opt) 52 case "last": 53 return newLastIterator(input, opt) 54 case "mean": 55 return newMeanIterator(input, opt) 56 case "sum_hll": 57 return NewSumHllIterator(input, opt) 58 case "merge_hll": 59 return NewMergeHllIterator(input, opt) 60 default: 61 return nil, fmt.Errorf("unsupported function call: %s", name) 62 } 63 } 64 65 // newCountIterator returns an iterator for operating on a count() call. 66 func newCountIterator(input Iterator, opt IteratorOptions) (Iterator, error) { 67 // FIXME: Wrap iterator in int-type iterator and always output int value. 68 69 switch input := input.(type) { 70 case FloatIterator: 71 createFn := func() (FloatPointAggregator, IntegerPointEmitter) { 72 fn := NewFloatFuncIntegerReducer(FloatCountReduce, &IntegerPoint{Value: 0, Time: ZeroTime}) 73 return fn, fn 74 } 75 return newFloatReduceIntegerIterator(input, opt, createFn), nil 76 case IntegerIterator: 77 createFn := func() (IntegerPointAggregator, IntegerPointEmitter) { 78 fn := NewIntegerFuncReducer(IntegerCountReduce, &IntegerPoint{Value: 0, Time: ZeroTime}) 79 return fn, fn 80 } 81 return newIntegerReduceIntegerIterator(input, opt, createFn), nil 82 case UnsignedIterator: 83 createFn := func() (UnsignedPointAggregator, IntegerPointEmitter) { 84 fn := NewUnsignedFuncIntegerReducer(UnsignedCountReduce, &IntegerPoint{Value: 0, Time: ZeroTime}) 85 return fn, fn 86 } 87 return newUnsignedReduceIntegerIterator(input, opt, createFn), nil 88 case StringIterator: 89 createFn := func() (StringPointAggregator, IntegerPointEmitter) { 90 fn := NewStringFuncIntegerReducer(StringCountReduce, &IntegerPoint{Value: 0, Time: ZeroTime}) 91 return fn, fn 92 } 93 return newStringReduceIntegerIterator(input, opt, createFn), nil 94 case BooleanIterator: 95 createFn := func() (BooleanPointAggregator, IntegerPointEmitter) { 96 fn := NewBooleanFuncIntegerReducer(BooleanCountReduce, &IntegerPoint{Value: 0, Time: ZeroTime}) 97 return fn, fn 98 } 99 return newBooleanReduceIntegerIterator(input, opt, createFn), nil 100 default: 101 return nil, fmt.Errorf("unsupported count iterator type: %T", input) 102 } 103 } 104 105 // FloatCountReduce returns the count of points. 106 func FloatCountReduce(prev *IntegerPoint, curr *FloatPoint) (int64, int64, []interface{}) { 107 if prev == nil { 108 return ZeroTime, 1, nil 109 } 110 return ZeroTime, prev.Value + 1, nil 111 } 112 113 // IntegerCountReduce returns the count of points. 114 func IntegerCountReduce(prev, curr *IntegerPoint) (int64, int64, []interface{}) { 115 if prev == nil { 116 return ZeroTime, 1, nil 117 } 118 return ZeroTime, prev.Value + 1, nil 119 } 120 121 // UnsignedCountReduce returns the count of points. 122 func UnsignedCountReduce(prev *IntegerPoint, curr *UnsignedPoint) (int64, int64, []interface{}) { 123 if prev == nil { 124 return ZeroTime, 1, nil 125 } 126 return ZeroTime, prev.Value + 1, nil 127 } 128 129 // StringCountReduce returns the count of points. 130 func StringCountReduce(prev *IntegerPoint, curr *StringPoint) (int64, int64, []interface{}) { 131 if prev == nil { 132 return ZeroTime, 1, nil 133 } 134 return ZeroTime, prev.Value + 1, nil 135 } 136 137 // BooleanCountReduce returns the count of points. 138 func BooleanCountReduce(prev *IntegerPoint, curr *BooleanPoint) (int64, int64, []interface{}) { 139 if prev == nil { 140 return ZeroTime, 1, nil 141 } 142 return ZeroTime, prev.Value + 1, nil 143 } 144 145 // newMinIterator returns an iterator for operating on a min() call. 146 func newMinIterator(input Iterator, opt IteratorOptions) (Iterator, error) { 147 switch input := input.(type) { 148 case FloatIterator: 149 createFn := func() (FloatPointAggregator, FloatPointEmitter) { 150 fn := NewFloatFuncReducer(FloatMinReduce, nil) 151 return fn, fn 152 } 153 return newFloatReduceFloatIterator(input, opt, createFn), nil 154 case IntegerIterator: 155 createFn := func() (IntegerPointAggregator, IntegerPointEmitter) { 156 fn := NewIntegerFuncReducer(IntegerMinReduce, nil) 157 return fn, fn 158 } 159 return newIntegerReduceIntegerIterator(input, opt, createFn), nil 160 case UnsignedIterator: 161 createFn := func() (UnsignedPointAggregator, UnsignedPointEmitter) { 162 fn := NewUnsignedFuncReducer(UnsignedMinReduce, nil) 163 return fn, fn 164 } 165 return newUnsignedReduceUnsignedIterator(input, opt, createFn), nil 166 case BooleanIterator: 167 createFn := func() (BooleanPointAggregator, BooleanPointEmitter) { 168 fn := NewBooleanFuncReducer(BooleanMinReduce, nil) 169 return fn, fn 170 } 171 return newBooleanReduceBooleanIterator(input, opt, createFn), nil 172 default: 173 return nil, fmt.Errorf("unsupported min iterator type: %T", input) 174 } 175 } 176 177 // FloatMinReduce returns the minimum value between prev & curr. 178 func FloatMinReduce(prev, curr *FloatPoint) (int64, float64, []interface{}) { 179 if prev == nil || curr.Value < prev.Value || (curr.Value == prev.Value && curr.Time < prev.Time) { 180 return curr.Time, curr.Value, cloneAux(curr.Aux) 181 } 182 return prev.Time, prev.Value, prev.Aux 183 } 184 185 // IntegerMinReduce returns the minimum value between prev & curr. 186 func IntegerMinReduce(prev, curr *IntegerPoint) (int64, int64, []interface{}) { 187 if prev == nil || curr.Value < prev.Value || (curr.Value == prev.Value && curr.Time < prev.Time) { 188 return curr.Time, curr.Value, cloneAux(curr.Aux) 189 } 190 return prev.Time, prev.Value, prev.Aux 191 } 192 193 // UnsignedMinReduce returns the minimum value between prev & curr. 194 func UnsignedMinReduce(prev, curr *UnsignedPoint) (int64, uint64, []interface{}) { 195 if prev == nil || curr.Value < prev.Value || (curr.Value == prev.Value && curr.Time < prev.Time) { 196 return curr.Time, curr.Value, cloneAux(curr.Aux) 197 } 198 return prev.Time, prev.Value, prev.Aux 199 } 200 201 // BooleanMinReduce returns the minimum value between prev & curr. 202 func BooleanMinReduce(prev, curr *BooleanPoint) (int64, bool, []interface{}) { 203 if prev == nil || (curr.Value != prev.Value && !curr.Value) || (curr.Value == prev.Value && curr.Time < prev.Time) { 204 return curr.Time, curr.Value, cloneAux(curr.Aux) 205 } 206 return prev.Time, prev.Value, prev.Aux 207 } 208 209 // newMaxIterator returns an iterator for operating on a max() call. 210 func newMaxIterator(input Iterator, opt IteratorOptions) (Iterator, error) { 211 switch input := input.(type) { 212 case FloatIterator: 213 createFn := func() (FloatPointAggregator, FloatPointEmitter) { 214 fn := NewFloatFuncReducer(FloatMaxReduce, nil) 215 return fn, fn 216 } 217 return newFloatReduceFloatIterator(input, opt, createFn), nil 218 case IntegerIterator: 219 createFn := func() (IntegerPointAggregator, IntegerPointEmitter) { 220 fn := NewIntegerFuncReducer(IntegerMaxReduce, nil) 221 return fn, fn 222 } 223 return newIntegerReduceIntegerIterator(input, opt, createFn), nil 224 case UnsignedIterator: 225 createFn := func() (UnsignedPointAggregator, UnsignedPointEmitter) { 226 fn := NewUnsignedFuncReducer(UnsignedMaxReduce, nil) 227 return fn, fn 228 } 229 return newUnsignedReduceUnsignedIterator(input, opt, createFn), nil 230 case BooleanIterator: 231 createFn := func() (BooleanPointAggregator, BooleanPointEmitter) { 232 fn := NewBooleanFuncReducer(BooleanMaxReduce, nil) 233 return fn, fn 234 } 235 return newBooleanReduceBooleanIterator(input, opt, createFn), nil 236 default: 237 return nil, fmt.Errorf("unsupported max iterator type: %T", input) 238 } 239 } 240 241 // FloatMaxReduce returns the maximum value between prev & curr. 242 func FloatMaxReduce(prev, curr *FloatPoint) (int64, float64, []interface{}) { 243 if prev == nil || curr.Value > prev.Value || (curr.Value == prev.Value && curr.Time < prev.Time) { 244 return curr.Time, curr.Value, cloneAux(curr.Aux) 245 } 246 return prev.Time, prev.Value, prev.Aux 247 } 248 249 // IntegerMaxReduce returns the maximum value between prev & curr. 250 func IntegerMaxReduce(prev, curr *IntegerPoint) (int64, int64, []interface{}) { 251 if prev == nil || curr.Value > prev.Value || (curr.Value == prev.Value && curr.Time < prev.Time) { 252 return curr.Time, curr.Value, cloneAux(curr.Aux) 253 } 254 return prev.Time, prev.Value, prev.Aux 255 } 256 257 // UnsignedMaxReduce returns the maximum value between prev & curr. 258 func UnsignedMaxReduce(prev, curr *UnsignedPoint) (int64, uint64, []interface{}) { 259 if prev == nil || curr.Value > prev.Value || (curr.Value == prev.Value && curr.Time < prev.Time) { 260 return curr.Time, curr.Value, cloneAux(curr.Aux) 261 } 262 return prev.Time, prev.Value, prev.Aux 263 } 264 265 // BooleanMaxReduce returns the minimum value between prev & curr. 266 func BooleanMaxReduce(prev, curr *BooleanPoint) (int64, bool, []interface{}) { 267 if prev == nil || (curr.Value != prev.Value && curr.Value) || (curr.Value == prev.Value && curr.Time < prev.Time) { 268 return curr.Time, curr.Value, cloneAux(curr.Aux) 269 } 270 return prev.Time, prev.Value, prev.Aux 271 } 272 273 // newSumIterator returns an iterator for operating on a sum() call. 274 func newSumIterator(input Iterator, opt IteratorOptions) (Iterator, error) { 275 switch input := input.(type) { 276 case FloatIterator: 277 createFn := func() (FloatPointAggregator, FloatPointEmitter) { 278 fn := NewFloatFuncReducer(FloatSumReduce, &FloatPoint{Value: 0, Time: ZeroTime}) 279 return fn, fn 280 } 281 return newFloatReduceFloatIterator(input, opt, createFn), nil 282 case IntegerIterator: 283 createFn := func() (IntegerPointAggregator, IntegerPointEmitter) { 284 fn := NewIntegerFuncReducer(IntegerSumReduce, &IntegerPoint{Value: 0, Time: ZeroTime}) 285 return fn, fn 286 } 287 return newIntegerReduceIntegerIterator(input, opt, createFn), nil 288 case UnsignedIterator: 289 createFn := func() (UnsignedPointAggregator, UnsignedPointEmitter) { 290 fn := NewUnsignedFuncReducer(UnsignedSumReduce, &UnsignedPoint{Value: 0, Time: ZeroTime}) 291 return fn, fn 292 } 293 return newUnsignedReduceUnsignedIterator(input, opt, createFn), nil 294 default: 295 return nil, fmt.Errorf("unsupported sum iterator type: %T", input) 296 } 297 } 298 299 // FloatSumReduce returns the sum prev value & curr value. 300 func FloatSumReduce(prev, curr *FloatPoint) (int64, float64, []interface{}) { 301 if prev == nil { 302 return ZeroTime, curr.Value, nil 303 } 304 return prev.Time, prev.Value + curr.Value, nil 305 } 306 307 // IntegerSumReduce returns the sum prev value & curr value. 308 func IntegerSumReduce(prev, curr *IntegerPoint) (int64, int64, []interface{}) { 309 if prev == nil { 310 return ZeroTime, curr.Value, nil 311 } 312 return prev.Time, prev.Value + curr.Value, nil 313 } 314 315 // UnsignedSumReduce returns the sum prev value & curr value. 316 func UnsignedSumReduce(prev, curr *UnsignedPoint) (int64, uint64, []interface{}) { 317 if prev == nil { 318 return ZeroTime, curr.Value, nil 319 } 320 return prev.Time, prev.Value + curr.Value, nil 321 } 322 323 // newFirstIterator returns an iterator for operating on a first() call. 324 func newFirstIterator(input Iterator, opt IteratorOptions) (Iterator, error) { 325 switch input := input.(type) { 326 case FloatIterator: 327 createFn := func() (FloatPointAggregator, FloatPointEmitter) { 328 fn := NewFloatFuncReducer(FloatFirstReduce, nil) 329 return fn, fn 330 } 331 return newFloatReduceFloatIterator(input, opt, createFn), nil 332 case IntegerIterator: 333 createFn := func() (IntegerPointAggregator, IntegerPointEmitter) { 334 fn := NewIntegerFuncReducer(IntegerFirstReduce, nil) 335 return fn, fn 336 } 337 return newIntegerReduceIntegerIterator(input, opt, createFn), nil 338 case UnsignedIterator: 339 createFn := func() (UnsignedPointAggregator, UnsignedPointEmitter) { 340 fn := NewUnsignedFuncReducer(UnsignedFirstReduce, nil) 341 return fn, fn 342 } 343 return newUnsignedReduceUnsignedIterator(input, opt, createFn), nil 344 case StringIterator: 345 createFn := func() (StringPointAggregator, StringPointEmitter) { 346 fn := NewStringFuncReducer(StringFirstReduce, nil) 347 return fn, fn 348 } 349 return newStringReduceStringIterator(input, opt, createFn), nil 350 case BooleanIterator: 351 createFn := func() (BooleanPointAggregator, BooleanPointEmitter) { 352 fn := NewBooleanFuncReducer(BooleanFirstReduce, nil) 353 return fn, fn 354 } 355 return newBooleanReduceBooleanIterator(input, opt, createFn), nil 356 default: 357 return nil, fmt.Errorf("unsupported first iterator type: %T", input) 358 } 359 } 360 361 // FloatFirstReduce returns the first point sorted by time. 362 func FloatFirstReduce(prev, curr *FloatPoint) (int64, float64, []interface{}) { 363 if prev == nil || curr.Time < prev.Time || (curr.Time == prev.Time && curr.Value > prev.Value) { 364 return curr.Time, curr.Value, cloneAux(curr.Aux) 365 } 366 return prev.Time, prev.Value, prev.Aux 367 } 368 369 // IntegerFirstReduce returns the first point sorted by time. 370 func IntegerFirstReduce(prev, curr *IntegerPoint) (int64, int64, []interface{}) { 371 if prev == nil || curr.Time < prev.Time || (curr.Time == prev.Time && curr.Value > prev.Value) { 372 return curr.Time, curr.Value, cloneAux(curr.Aux) 373 } 374 return prev.Time, prev.Value, prev.Aux 375 } 376 377 // UnsignedFirstReduce returns the first point sorted by time. 378 func UnsignedFirstReduce(prev, curr *UnsignedPoint) (int64, uint64, []interface{}) { 379 if prev == nil || curr.Time < prev.Time || (curr.Time == prev.Time && curr.Value > prev.Value) { 380 return curr.Time, curr.Value, cloneAux(curr.Aux) 381 } 382 return prev.Time, prev.Value, prev.Aux 383 } 384 385 // StringFirstReduce returns the first point sorted by time. 386 func StringFirstReduce(prev, curr *StringPoint) (int64, string, []interface{}) { 387 if prev == nil || curr.Time < prev.Time || (curr.Time == prev.Time && curr.Value > prev.Value) { 388 return curr.Time, curr.Value, cloneAux(curr.Aux) 389 } 390 return prev.Time, prev.Value, prev.Aux 391 } 392 393 // BooleanFirstReduce returns the first point sorted by time. 394 func BooleanFirstReduce(prev, curr *BooleanPoint) (int64, bool, []interface{}) { 395 if prev == nil || curr.Time < prev.Time || (curr.Time == prev.Time && !curr.Value && prev.Value) { 396 return curr.Time, curr.Value, cloneAux(curr.Aux) 397 } 398 return prev.Time, prev.Value, prev.Aux 399 } 400 401 // newLastIterator returns an iterator for operating on a last() call. 402 func newLastIterator(input Iterator, opt IteratorOptions) (Iterator, error) { 403 switch input := input.(type) { 404 case FloatIterator: 405 createFn := func() (FloatPointAggregator, FloatPointEmitter) { 406 fn := NewFloatFuncReducer(FloatLastReduce, nil) 407 return fn, fn 408 } 409 return newFloatReduceFloatIterator(input, opt, createFn), nil 410 case IntegerIterator: 411 createFn := func() (IntegerPointAggregator, IntegerPointEmitter) { 412 fn := NewIntegerFuncReducer(IntegerLastReduce, nil) 413 return fn, fn 414 } 415 return newIntegerReduceIntegerIterator(input, opt, createFn), nil 416 case UnsignedIterator: 417 createFn := func() (UnsignedPointAggregator, UnsignedPointEmitter) { 418 fn := NewUnsignedFuncReducer(UnsignedLastReduce, nil) 419 return fn, fn 420 } 421 return newUnsignedReduceUnsignedIterator(input, opt, createFn), nil 422 case StringIterator: 423 createFn := func() (StringPointAggregator, StringPointEmitter) { 424 fn := NewStringFuncReducer(StringLastReduce, nil) 425 return fn, fn 426 } 427 return newStringReduceStringIterator(input, opt, createFn), nil 428 case BooleanIterator: 429 createFn := func() (BooleanPointAggregator, BooleanPointEmitter) { 430 fn := NewBooleanFuncReducer(BooleanLastReduce, nil) 431 return fn, fn 432 } 433 return newBooleanReduceBooleanIterator(input, opt, createFn), nil 434 default: 435 return nil, fmt.Errorf("unsupported last iterator type: %T", input) 436 } 437 } 438 439 // FloatLastReduce returns the last point sorted by time. 440 func FloatLastReduce(prev, curr *FloatPoint) (int64, float64, []interface{}) { 441 if prev == nil || curr.Time > prev.Time || (curr.Time == prev.Time && curr.Value > prev.Value) { 442 return curr.Time, curr.Value, cloneAux(curr.Aux) 443 } 444 return prev.Time, prev.Value, prev.Aux 445 } 446 447 // IntegerLastReduce returns the last point sorted by time. 448 func IntegerLastReduce(prev, curr *IntegerPoint) (int64, int64, []interface{}) { 449 if prev == nil || curr.Time > prev.Time || (curr.Time == prev.Time && curr.Value > prev.Value) { 450 return curr.Time, curr.Value, cloneAux(curr.Aux) 451 } 452 return prev.Time, prev.Value, prev.Aux 453 } 454 455 // UnsignedLastReduce returns the last point sorted by time. 456 func UnsignedLastReduce(prev, curr *UnsignedPoint) (int64, uint64, []interface{}) { 457 if prev == nil || curr.Time > prev.Time || (curr.Time == prev.Time && curr.Value > prev.Value) { 458 return curr.Time, curr.Value, cloneAux(curr.Aux) 459 } 460 return prev.Time, prev.Value, prev.Aux 461 } 462 463 // StringLastReduce returns the first point sorted by time. 464 func StringLastReduce(prev, curr *StringPoint) (int64, string, []interface{}) { 465 if prev == nil || curr.Time > prev.Time || (curr.Time == prev.Time && curr.Value > prev.Value) { 466 return curr.Time, curr.Value, cloneAux(curr.Aux) 467 } 468 return prev.Time, prev.Value, prev.Aux 469 } 470 471 // BooleanLastReduce returns the first point sorted by time. 472 func BooleanLastReduce(prev, curr *BooleanPoint) (int64, bool, []interface{}) { 473 if prev == nil || curr.Time > prev.Time || (curr.Time == prev.Time && curr.Value && !prev.Value) { 474 return curr.Time, curr.Value, cloneAux(curr.Aux) 475 } 476 return prev.Time, prev.Value, prev.Aux 477 } 478 479 // NewDistinctIterator returns an iterator for operating on a distinct() call. 480 func NewDistinctIterator(input Iterator, opt IteratorOptions) (Iterator, error) { 481 switch input := input.(type) { 482 case FloatIterator: 483 createFn := func() (FloatPointAggregator, FloatPointEmitter) { 484 fn := NewFloatDistinctReducer() 485 return fn, fn 486 } 487 return newFloatReduceFloatIterator(input, opt, createFn), nil 488 case IntegerIterator: 489 createFn := func() (IntegerPointAggregator, IntegerPointEmitter) { 490 fn := NewIntegerDistinctReducer() 491 return fn, fn 492 } 493 return newIntegerReduceIntegerIterator(input, opt, createFn), nil 494 case UnsignedIterator: 495 createFn := func() (UnsignedPointAggregator, UnsignedPointEmitter) { 496 fn := NewUnsignedDistinctReducer() 497 return fn, fn 498 } 499 return newUnsignedReduceUnsignedIterator(input, opt, createFn), nil 500 case StringIterator: 501 createFn := func() (StringPointAggregator, StringPointEmitter) { 502 fn := NewStringDistinctReducer() 503 return fn, fn 504 } 505 return newStringReduceStringIterator(input, opt, createFn), nil 506 case BooleanIterator: 507 createFn := func() (BooleanPointAggregator, BooleanPointEmitter) { 508 fn := NewBooleanDistinctReducer() 509 return fn, fn 510 } 511 return newBooleanReduceBooleanIterator(input, opt, createFn), nil 512 default: 513 return nil, fmt.Errorf("unsupported distinct iterator type: %T", input) 514 } 515 } 516 517 // newMeanIterator returns an iterator for operating on a mean() call. 518 func newMeanIterator(input Iterator, opt IteratorOptions) (Iterator, error) { 519 switch input := input.(type) { 520 case FloatIterator: 521 createFn := func() (FloatPointAggregator, FloatPointEmitter) { 522 fn := NewFloatMeanReducer() 523 return fn, fn 524 } 525 return newFloatReduceFloatIterator(input, opt, createFn), nil 526 case IntegerIterator: 527 createFn := func() (IntegerPointAggregator, FloatPointEmitter) { 528 fn := NewIntegerMeanReducer() 529 return fn, fn 530 } 531 return newIntegerReduceFloatIterator(input, opt, createFn), nil 532 case UnsignedIterator: 533 createFn := func() (UnsignedPointAggregator, FloatPointEmitter) { 534 fn := NewUnsignedMeanReducer() 535 return fn, fn 536 } 537 return newUnsignedReduceFloatIterator(input, opt, createFn), nil 538 default: 539 return nil, fmt.Errorf("unsupported mean iterator type: %T", input) 540 } 541 } 542 543 // NewMedianIterator returns an iterator for operating on a median() call. 544 func NewMedianIterator(input Iterator, opt IteratorOptions) (Iterator, error) { 545 return newMedianIterator(input, opt) 546 } 547 548 // newMedianIterator returns an iterator for operating on a median() call. 549 func newMedianIterator(input Iterator, opt IteratorOptions) (Iterator, error) { 550 switch input := input.(type) { 551 case FloatIterator: 552 createFn := func() (FloatPointAggregator, FloatPointEmitter) { 553 fn := NewFloatSliceFuncReducer(FloatMedianReduceSlice) 554 return fn, fn 555 } 556 return newFloatReduceFloatIterator(input, opt, createFn), nil 557 case IntegerIterator: 558 createFn := func() (IntegerPointAggregator, FloatPointEmitter) { 559 fn := NewIntegerSliceFuncFloatReducer(IntegerMedianReduceSlice) 560 return fn, fn 561 } 562 return newIntegerReduceFloatIterator(input, opt, createFn), nil 563 case UnsignedIterator: 564 createFn := func() (UnsignedPointAggregator, FloatPointEmitter) { 565 fn := NewUnsignedSliceFuncFloatReducer(UnsignedMedianReduceSlice) 566 return fn, fn 567 } 568 return newUnsignedReduceFloatIterator(input, opt, createFn), nil 569 default: 570 return nil, fmt.Errorf("unsupported median iterator type: %T", input) 571 } 572 } 573 574 // FloatMedianReduceSlice returns the median value within a window. 575 func FloatMedianReduceSlice(a []FloatPoint) []FloatPoint { 576 if len(a) == 1 { 577 return a 578 } 579 580 // OPTIMIZE(benbjohnson): Use getSortedRange() from v0.9.5.1. 581 582 // Return the middle value from the points. 583 // If there are an even number of points then return the mean of the two middle points. 584 sort.Sort(floatPointsByValue(a)) 585 if len(a)%2 == 0 { 586 lo, hi := a[len(a)/2-1], a[(len(a)/2)] 587 return []FloatPoint{{Time: ZeroTime, Value: lo.Value + (hi.Value-lo.Value)/2}} 588 } 589 return []FloatPoint{{Time: ZeroTime, Value: a[len(a)/2].Value}} 590 } 591 592 // IntegerMedianReduceSlice returns the median value within a window. 593 func IntegerMedianReduceSlice(a []IntegerPoint) []FloatPoint { 594 if len(a) == 1 { 595 return []FloatPoint{{Time: ZeroTime, Value: float64(a[0].Value)}} 596 } 597 598 // OPTIMIZE(benbjohnson): Use getSortedRange() from v0.9.5.1. 599 600 // Return the middle value from the points. 601 // If there are an even number of points then return the mean of the two middle points. 602 sort.Sort(integerPointsByValue(a)) 603 if len(a)%2 == 0 { 604 lo, hi := a[len(a)/2-1], a[(len(a)/2)] 605 return []FloatPoint{{Time: ZeroTime, Value: float64(lo.Value) + float64(hi.Value-lo.Value)/2}} 606 } 607 return []FloatPoint{{Time: ZeroTime, Value: float64(a[len(a)/2].Value)}} 608 } 609 610 // UnsignedMedianReduceSlice returns the median value within a window. 611 func UnsignedMedianReduceSlice(a []UnsignedPoint) []FloatPoint { 612 if len(a) == 1 { 613 return []FloatPoint{{Time: ZeroTime, Value: float64(a[0].Value)}} 614 } 615 616 // OPTIMIZE(benbjohnson): Use getSortedRange() from v0.9.5.1. 617 618 // Return the middle value from the points. 619 // If there are an even number of points then return the mean of the two middle points. 620 sort.Sort(unsignedPointsByValue(a)) 621 if len(a)%2 == 0 { 622 lo, hi := a[len(a)/2-1], a[(len(a)/2)] 623 return []FloatPoint{{Time: ZeroTime, Value: float64(lo.Value) + float64(hi.Value-lo.Value)/2}} 624 } 625 return []FloatPoint{{Time: ZeroTime, Value: float64(a[len(a)/2].Value)}} 626 } 627 628 // newModeIterator returns an iterator for operating on a mode() call. 629 func NewModeIterator(input Iterator, opt IteratorOptions) (Iterator, error) { 630 switch input := input.(type) { 631 case FloatIterator: 632 createFn := func() (FloatPointAggregator, FloatPointEmitter) { 633 fn := NewFloatSliceFuncReducer(FloatModeReduceSlice) 634 return fn, fn 635 } 636 return newFloatReduceFloatIterator(input, opt, createFn), nil 637 case IntegerIterator: 638 createFn := func() (IntegerPointAggregator, IntegerPointEmitter) { 639 fn := NewIntegerSliceFuncReducer(IntegerModeReduceSlice) 640 return fn, fn 641 } 642 return newIntegerReduceIntegerIterator(input, opt, createFn), nil 643 case UnsignedIterator: 644 createFn := func() (UnsignedPointAggregator, UnsignedPointEmitter) { 645 fn := NewUnsignedSliceFuncReducer(UnsignedModeReduceSlice) 646 return fn, fn 647 } 648 return newUnsignedReduceUnsignedIterator(input, opt, createFn), nil 649 case StringIterator: 650 createFn := func() (StringPointAggregator, StringPointEmitter) { 651 fn := NewStringSliceFuncReducer(StringModeReduceSlice) 652 return fn, fn 653 } 654 return newStringReduceStringIterator(input, opt, createFn), nil 655 case BooleanIterator: 656 createFn := func() (BooleanPointAggregator, BooleanPointEmitter) { 657 fn := NewBooleanSliceFuncReducer(BooleanModeReduceSlice) 658 return fn, fn 659 } 660 return newBooleanReduceBooleanIterator(input, opt, createFn), nil 661 default: 662 return nil, fmt.Errorf("unsupported median iterator type: %T", input) 663 } 664 } 665 666 // FloatModeReduceSlice returns the mode value within a window. 667 func FloatModeReduceSlice(a []FloatPoint) []FloatPoint { 668 if len(a) == 1 { 669 return a 670 } 671 672 sort.Sort(floatPointsByValue(a)) 673 674 mostFreq := 0 675 currFreq := 0 676 currMode := a[0].Value 677 mostMode := a[0].Value 678 mostTime := a[0].Time 679 currTime := a[0].Time 680 681 for _, p := range a { 682 if p.Value != currMode { 683 currFreq = 1 684 currMode = p.Value 685 currTime = p.Time 686 continue 687 } 688 currFreq++ 689 if mostFreq > currFreq || (mostFreq == currFreq && currTime > mostTime) { 690 continue 691 } 692 mostFreq = currFreq 693 mostMode = p.Value 694 mostTime = p.Time 695 } 696 697 return []FloatPoint{{Time: ZeroTime, Value: mostMode}} 698 } 699 700 // IntegerModeReduceSlice returns the mode value within a window. 701 func IntegerModeReduceSlice(a []IntegerPoint) []IntegerPoint { 702 if len(a) == 1 { 703 return a 704 } 705 sort.Sort(integerPointsByValue(a)) 706 707 mostFreq := 0 708 currFreq := 0 709 currMode := a[0].Value 710 mostMode := a[0].Value 711 mostTime := a[0].Time 712 currTime := a[0].Time 713 714 for _, p := range a { 715 if p.Value != currMode { 716 currFreq = 1 717 currMode = p.Value 718 currTime = p.Time 719 continue 720 } 721 currFreq++ 722 if mostFreq > currFreq || (mostFreq == currFreq && currTime > mostTime) { 723 continue 724 } 725 mostFreq = currFreq 726 mostMode = p.Value 727 mostTime = p.Time 728 } 729 730 return []IntegerPoint{{Time: ZeroTime, Value: mostMode}} 731 } 732 733 // UnsignedModeReduceSlice returns the mode value within a window. 734 func UnsignedModeReduceSlice(a []UnsignedPoint) []UnsignedPoint { 735 if len(a) == 1 { 736 return a 737 } 738 sort.Sort(unsignedPointsByValue(a)) 739 740 mostFreq := 0 741 currFreq := 0 742 currMode := a[0].Value 743 mostMode := a[0].Value 744 mostTime := a[0].Time 745 currTime := a[0].Time 746 747 for _, p := range a { 748 if p.Value != currMode { 749 currFreq = 1 750 currMode = p.Value 751 currTime = p.Time 752 continue 753 } 754 currFreq++ 755 if mostFreq > currFreq || (mostFreq == currFreq && currTime > mostTime) { 756 continue 757 } 758 mostFreq = currFreq 759 mostMode = p.Value 760 mostTime = p.Time 761 } 762 763 return []UnsignedPoint{{Time: ZeroTime, Value: mostMode}} 764 } 765 766 // StringModeReduceSlice returns the mode value within a window. 767 func StringModeReduceSlice(a []StringPoint) []StringPoint { 768 if len(a) == 1 { 769 return a 770 } 771 772 sort.Sort(stringPointsByValue(a)) 773 774 mostFreq := 0 775 currFreq := 0 776 currMode := a[0].Value 777 mostMode := a[0].Value 778 mostTime := a[0].Time 779 currTime := a[0].Time 780 781 for _, p := range a { 782 if p.Value != currMode { 783 currFreq = 1 784 currMode = p.Value 785 currTime = p.Time 786 continue 787 } 788 currFreq++ 789 if mostFreq > currFreq || (mostFreq == currFreq && currTime > mostTime) { 790 continue 791 } 792 mostFreq = currFreq 793 mostMode = p.Value 794 mostTime = p.Time 795 } 796 797 return []StringPoint{{Time: ZeroTime, Value: mostMode}} 798 } 799 800 // BooleanModeReduceSlice returns the mode value within a window. 801 func BooleanModeReduceSlice(a []BooleanPoint) []BooleanPoint { 802 if len(a) == 1 { 803 return a 804 } 805 806 trueFreq := 0 807 falsFreq := 0 808 mostMode := false 809 810 for _, p := range a { 811 if p.Value { 812 trueFreq++ 813 } else { 814 falsFreq++ 815 } 816 } 817 // In case either of true or false are mode then retuned mode value wont be 818 // of metric with oldest timestamp 819 if trueFreq >= falsFreq { 820 mostMode = true 821 } 822 823 return []BooleanPoint{{Time: ZeroTime, Value: mostMode}} 824 } 825 826 // newStddevIterator returns an iterator for operating on a stddev() call. 827 func newStddevIterator(input Iterator, opt IteratorOptions) (Iterator, error) { 828 switch input := input.(type) { 829 case FloatIterator: 830 createFn := func() (FloatPointAggregator, FloatPointEmitter) { 831 fn := NewFloatSliceFuncReducer(FloatStddevReduceSlice) 832 return fn, fn 833 } 834 return newFloatReduceFloatIterator(input, opt, createFn), nil 835 case IntegerIterator: 836 createFn := func() (IntegerPointAggregator, FloatPointEmitter) { 837 fn := NewIntegerSliceFuncFloatReducer(IntegerStddevReduceSlice) 838 return fn, fn 839 } 840 return newIntegerReduceFloatIterator(input, opt, createFn), nil 841 case UnsignedIterator: 842 createFn := func() (UnsignedPointAggregator, FloatPointEmitter) { 843 fn := NewUnsignedSliceFuncFloatReducer(UnsignedStddevReduceSlice) 844 return fn, fn 845 } 846 return newUnsignedReduceFloatIterator(input, opt, createFn), nil 847 default: 848 return nil, fmt.Errorf("unsupported stddev iterator type: %T", input) 849 } 850 } 851 852 // FloatStddevReduceSlice returns the stddev value within a window. 853 func FloatStddevReduceSlice(a []FloatPoint) []FloatPoint { 854 // If there is only one point then return NaN. 855 if len(a) < 2 { 856 return []FloatPoint{{Time: ZeroTime, Value: math.NaN()}} 857 } 858 859 // Calculate the mean. 860 var mean float64 861 var count int 862 for _, p := range a { 863 if math.IsNaN(p.Value) { 864 continue 865 } 866 count++ 867 mean += (p.Value - mean) / float64(count) 868 } 869 870 // Calculate the variance. 871 var variance float64 872 for _, p := range a { 873 if math.IsNaN(p.Value) { 874 continue 875 } 876 variance += math.Pow(p.Value-mean, 2) 877 } 878 return []FloatPoint{{ 879 Time: ZeroTime, 880 Value: math.Sqrt(variance / float64(count-1)), 881 }} 882 } 883 884 // IntegerStddevReduceSlice returns the stddev value within a window. 885 func IntegerStddevReduceSlice(a []IntegerPoint) []FloatPoint { 886 // If there is only one point then return NaN. 887 if len(a) < 2 { 888 return []FloatPoint{{Time: ZeroTime, Value: math.NaN()}} 889 } 890 891 // Calculate the mean. 892 var mean float64 893 var count int 894 for _, p := range a { 895 count++ 896 mean += (float64(p.Value) - mean) / float64(count) 897 } 898 899 // Calculate the variance. 900 var variance float64 901 for _, p := range a { 902 variance += math.Pow(float64(p.Value)-mean, 2) 903 } 904 return []FloatPoint{{ 905 Time: ZeroTime, 906 Value: math.Sqrt(variance / float64(count-1)), 907 }} 908 } 909 910 // UnsignedStddevReduceSlice returns the stddev value within a window. 911 func UnsignedStddevReduceSlice(a []UnsignedPoint) []FloatPoint { 912 // If there is only one point then return NaN. 913 if len(a) < 2 { 914 return []FloatPoint{{Time: ZeroTime, Value: math.NaN()}} 915 } 916 917 // Calculate the mean. 918 var mean float64 919 var count int 920 for _, p := range a { 921 count++ 922 mean += (float64(p.Value) - mean) / float64(count) 923 } 924 925 // Calculate the variance. 926 var variance float64 927 for _, p := range a { 928 variance += math.Pow(float64(p.Value)-mean, 2) 929 } 930 return []FloatPoint{{ 931 Time: ZeroTime, 932 Value: math.Sqrt(variance / float64(count-1)), 933 }} 934 } 935 936 // newSpreadIterator returns an iterator for operating on a spread() call. 937 func newSpreadIterator(input Iterator, opt IteratorOptions) (Iterator, error) { 938 switch input := input.(type) { 939 case FloatIterator: 940 createFn := func() (FloatPointAggregator, FloatPointEmitter) { 941 fn := NewFloatSpreadReducer() 942 return fn, fn 943 } 944 return newFloatReduceFloatIterator(input, opt, createFn), nil 945 case IntegerIterator: 946 createFn := func() (IntegerPointAggregator, IntegerPointEmitter) { 947 fn := NewIntegerSpreadReducer() 948 return fn, fn 949 } 950 return newIntegerReduceIntegerIterator(input, opt, createFn), nil 951 case UnsignedIterator: 952 createFn := func() (UnsignedPointAggregator, UnsignedPointEmitter) { 953 fn := NewUnsignedSpreadReducer() 954 return fn, fn 955 } 956 return newUnsignedReduceUnsignedIterator(input, opt, createFn), nil 957 default: 958 return nil, fmt.Errorf("unsupported spread iterator type: %T", input) 959 } 960 } 961 962 func newTopIterator(input Iterator, opt IteratorOptions, n int, keepTags bool) (Iterator, error) { 963 switch input := input.(type) { 964 case FloatIterator: 965 createFn := func() (FloatPointAggregator, FloatPointEmitter) { 966 fn := NewFloatTopReducer(n) 967 return fn, fn 968 } 969 itr := newFloatReduceFloatIterator(input, opt, createFn) 970 itr.keepTags = keepTags 971 return itr, nil 972 case IntegerIterator: 973 createFn := func() (IntegerPointAggregator, IntegerPointEmitter) { 974 fn := NewIntegerTopReducer(n) 975 return fn, fn 976 } 977 itr := newIntegerReduceIntegerIterator(input, opt, createFn) 978 itr.keepTags = keepTags 979 return itr, nil 980 case UnsignedIterator: 981 createFn := func() (UnsignedPointAggregator, UnsignedPointEmitter) { 982 fn := NewUnsignedTopReducer(n) 983 return fn, fn 984 } 985 itr := newUnsignedReduceUnsignedIterator(input, opt, createFn) 986 itr.keepTags = keepTags 987 return itr, nil 988 default: 989 return nil, fmt.Errorf("unsupported top iterator type: %T", input) 990 } 991 } 992 993 func newBottomIterator(input Iterator, opt IteratorOptions, n int, keepTags bool) (Iterator, error) { 994 switch input := input.(type) { 995 case FloatIterator: 996 createFn := func() (FloatPointAggregator, FloatPointEmitter) { 997 fn := NewFloatBottomReducer(n) 998 return fn, fn 999 } 1000 itr := newFloatReduceFloatIterator(input, opt, createFn) 1001 itr.keepTags = keepTags 1002 return itr, nil 1003 case IntegerIterator: 1004 createFn := func() (IntegerPointAggregator, IntegerPointEmitter) { 1005 fn := NewIntegerBottomReducer(n) 1006 return fn, fn 1007 } 1008 itr := newIntegerReduceIntegerIterator(input, opt, createFn) 1009 itr.keepTags = keepTags 1010 return itr, nil 1011 case UnsignedIterator: 1012 createFn := func() (UnsignedPointAggregator, UnsignedPointEmitter) { 1013 fn := NewUnsignedBottomReducer(n) 1014 return fn, fn 1015 } 1016 itr := newUnsignedReduceUnsignedIterator(input, opt, createFn) 1017 itr.keepTags = keepTags 1018 return itr, nil 1019 default: 1020 return nil, fmt.Errorf("unsupported bottom iterator type: %T", input) 1021 } 1022 } 1023 1024 // newPercentileIterator returns an iterator for operating on a percentile() call. 1025 func newPercentileIterator(input Iterator, opt IteratorOptions, percentile float64) (Iterator, error) { 1026 switch input := input.(type) { 1027 case FloatIterator: 1028 floatPercentileReduceSlice := NewFloatPercentileReduceSliceFunc(percentile) 1029 createFn := func() (FloatPointAggregator, FloatPointEmitter) { 1030 fn := NewFloatSliceFuncReducer(floatPercentileReduceSlice) 1031 return fn, fn 1032 } 1033 return newFloatReduceFloatIterator(input, opt, createFn), nil 1034 case IntegerIterator: 1035 integerPercentileReduceSlice := NewIntegerPercentileReduceSliceFunc(percentile) 1036 createFn := func() (IntegerPointAggregator, IntegerPointEmitter) { 1037 fn := NewIntegerSliceFuncReducer(integerPercentileReduceSlice) 1038 return fn, fn 1039 } 1040 return newIntegerReduceIntegerIterator(input, opt, createFn), nil 1041 case UnsignedIterator: 1042 unsignedPercentileReduceSlice := NewUnsignedPercentileReduceSliceFunc(percentile) 1043 createFn := func() (UnsignedPointAggregator, UnsignedPointEmitter) { 1044 fn := NewUnsignedSliceFuncReducer(unsignedPercentileReduceSlice) 1045 return fn, fn 1046 } 1047 return newUnsignedReduceUnsignedIterator(input, opt, createFn), nil 1048 default: 1049 return nil, fmt.Errorf("unsupported percentile iterator type: %T", input) 1050 } 1051 } 1052 1053 // NewFloatPercentileReduceSliceFunc returns the percentile value within a window. 1054 func NewFloatPercentileReduceSliceFunc(percentile float64) FloatReduceSliceFunc { 1055 return func(a []FloatPoint) []FloatPoint { 1056 length := len(a) 1057 i := int(math.Floor(float64(length)*percentile/100.0+0.5)) - 1 1058 1059 if i < 0 || i >= length { 1060 return nil 1061 } 1062 1063 sort.Sort(floatPointsByValue(a)) 1064 return []FloatPoint{{Time: a[i].Time, Value: a[i].Value, Aux: cloneAux(a[i].Aux)}} 1065 } 1066 } 1067 1068 // NewIntegerPercentileReduceSliceFunc returns the percentile value within a window. 1069 func NewIntegerPercentileReduceSliceFunc(percentile float64) IntegerReduceSliceFunc { 1070 return func(a []IntegerPoint) []IntegerPoint { 1071 length := len(a) 1072 i := int(math.Floor(float64(length)*percentile/100.0+0.5)) - 1 1073 1074 if i < 0 || i >= length { 1075 return nil 1076 } 1077 1078 sort.Sort(integerPointsByValue(a)) 1079 return []IntegerPoint{{Time: a[i].Time, Value: a[i].Value, Aux: cloneAux(a[i].Aux)}} 1080 } 1081 } 1082 1083 // NewUnsignedPercentileReduceSliceFunc returns the percentile value within a window. 1084 func NewUnsignedPercentileReduceSliceFunc(percentile float64) UnsignedReduceSliceFunc { 1085 return func(a []UnsignedPoint) []UnsignedPoint { 1086 length := len(a) 1087 i := int(math.Floor(float64(length)*percentile/100.0+0.5)) - 1 1088 1089 if i < 0 || i >= length { 1090 return nil 1091 } 1092 1093 sort.Sort(unsignedPointsByValue(a)) 1094 return []UnsignedPoint{{Time: a[i].Time, Value: a[i].Value, Aux: cloneAux(a[i].Aux)}} 1095 } 1096 } 1097 1098 // newDerivativeIterator returns an iterator for operating on a derivative() call. 1099 func newDerivativeIterator(input Iterator, opt IteratorOptions, interval Interval, isNonNegative bool) (Iterator, error) { 1100 switch input := input.(type) { 1101 case FloatIterator: 1102 createFn := func() (FloatPointAggregator, FloatPointEmitter) { 1103 fn := NewFloatDerivativeReducer(interval, isNonNegative, opt.Ascending) 1104 return fn, fn 1105 } 1106 return newFloatStreamFloatIterator(input, createFn, opt), nil 1107 case IntegerIterator: 1108 createFn := func() (IntegerPointAggregator, FloatPointEmitter) { 1109 fn := NewIntegerDerivativeReducer(interval, isNonNegative, opt.Ascending) 1110 return fn, fn 1111 } 1112 return newIntegerStreamFloatIterator(input, createFn, opt), nil 1113 case UnsignedIterator: 1114 createFn := func() (UnsignedPointAggregator, FloatPointEmitter) { 1115 fn := NewUnsignedDerivativeReducer(interval, isNonNegative, opt.Ascending) 1116 return fn, fn 1117 } 1118 return newUnsignedStreamFloatIterator(input, createFn, opt), nil 1119 default: 1120 return nil, fmt.Errorf("unsupported derivative iterator type: %T", input) 1121 } 1122 } 1123 1124 // newDifferenceIterator returns an iterator for operating on a difference() call. 1125 func newDifferenceIterator(input Iterator, opt IteratorOptions, isNonNegative bool) (Iterator, error) { 1126 switch input := input.(type) { 1127 case FloatIterator: 1128 createFn := func() (FloatPointAggregator, FloatPointEmitter) { 1129 fn := NewFloatDifferenceReducer(isNonNegative) 1130 return fn, fn 1131 } 1132 return newFloatStreamFloatIterator(input, createFn, opt), nil 1133 case IntegerIterator: 1134 createFn := func() (IntegerPointAggregator, IntegerPointEmitter) { 1135 fn := NewIntegerDifferenceReducer(isNonNegative) 1136 return fn, fn 1137 } 1138 return newIntegerStreamIntegerIterator(input, createFn, opt), nil 1139 case UnsignedIterator: 1140 createFn := func() (UnsignedPointAggregator, UnsignedPointEmitter) { 1141 fn := NewUnsignedDifferenceReducer(isNonNegative) 1142 return fn, fn 1143 } 1144 return newUnsignedStreamUnsignedIterator(input, createFn, opt), nil 1145 default: 1146 return nil, fmt.Errorf("unsupported difference iterator type: %T", input) 1147 } 1148 } 1149 1150 // newElapsedIterator returns an iterator for operating on a elapsed() call. 1151 func newElapsedIterator(input Iterator, opt IteratorOptions, interval Interval) (Iterator, error) { 1152 switch input := input.(type) { 1153 case FloatIterator: 1154 createFn := func() (FloatPointAggregator, IntegerPointEmitter) { 1155 fn := NewFloatElapsedReducer(interval) 1156 return fn, fn 1157 } 1158 return newFloatStreamIntegerIterator(input, createFn, opt), nil 1159 case IntegerIterator: 1160 createFn := func() (IntegerPointAggregator, IntegerPointEmitter) { 1161 fn := NewIntegerElapsedReducer(interval) 1162 return fn, fn 1163 } 1164 return newIntegerStreamIntegerIterator(input, createFn, opt), nil 1165 case UnsignedIterator: 1166 createFn := func() (UnsignedPointAggregator, IntegerPointEmitter) { 1167 fn := NewUnsignedElapsedReducer(interval) 1168 return fn, fn 1169 } 1170 return newUnsignedStreamIntegerIterator(input, createFn, opt), nil 1171 case BooleanIterator: 1172 createFn := func() (BooleanPointAggregator, IntegerPointEmitter) { 1173 fn := NewBooleanElapsedReducer(interval) 1174 return fn, fn 1175 } 1176 return newBooleanStreamIntegerIterator(input, createFn, opt), nil 1177 case StringIterator: 1178 createFn := func() (StringPointAggregator, IntegerPointEmitter) { 1179 fn := NewStringElapsedReducer(interval) 1180 return fn, fn 1181 } 1182 return newStringStreamIntegerIterator(input, createFn, opt), nil 1183 default: 1184 return nil, fmt.Errorf("unsupported elapsed iterator type: %T", input) 1185 } 1186 } 1187 1188 // newMovingAverageIterator returns an iterator for operating on a moving_average() call. 1189 func newMovingAverageIterator(input Iterator, n int, opt IteratorOptions) (Iterator, error) { 1190 switch input := input.(type) { 1191 case FloatIterator: 1192 createFn := func() (FloatPointAggregator, FloatPointEmitter) { 1193 fn := NewFloatMovingAverageReducer(n) 1194 return fn, fn 1195 } 1196 return newFloatStreamFloatIterator(input, createFn, opt), nil 1197 case IntegerIterator: 1198 createFn := func() (IntegerPointAggregator, FloatPointEmitter) { 1199 fn := NewIntegerMovingAverageReducer(n) 1200 return fn, fn 1201 } 1202 return newIntegerStreamFloatIterator(input, createFn, opt), nil 1203 case UnsignedIterator: 1204 createFn := func() (UnsignedPointAggregator, FloatPointEmitter) { 1205 fn := NewUnsignedMovingAverageReducer(n) 1206 return fn, fn 1207 } 1208 return newUnsignedStreamFloatIterator(input, createFn, opt), nil 1209 default: 1210 return nil, fmt.Errorf("unsupported moving average iterator type: %T", input) 1211 } 1212 } 1213 1214 // newExponentialMovingAverageIterator returns an iterator for operating on an exponential_moving_average() call. 1215 func newExponentialMovingAverageIterator(input Iterator, n, nHold int, warmupType gota.WarmupType, opt IteratorOptions) (Iterator, error) { 1216 switch input := input.(type) { 1217 case FloatIterator: 1218 createFn := func() (FloatPointAggregator, FloatPointEmitter) { 1219 fn := NewExponentialMovingAverageReducer(n, nHold, warmupType) 1220 return fn, fn 1221 } 1222 return newFloatStreamFloatIterator(input, createFn, opt), nil 1223 case IntegerIterator: 1224 createFn := func() (IntegerPointAggregator, FloatPointEmitter) { 1225 fn := NewExponentialMovingAverageReducer(n, nHold, warmupType) 1226 return fn, fn 1227 } 1228 return newIntegerStreamFloatIterator(input, createFn, opt), nil 1229 case UnsignedIterator: 1230 createFn := func() (UnsignedPointAggregator, FloatPointEmitter) { 1231 fn := NewExponentialMovingAverageReducer(n, nHold, warmupType) 1232 return fn, fn 1233 } 1234 return newUnsignedStreamFloatIterator(input, createFn, opt), nil 1235 default: 1236 return nil, fmt.Errorf("unsupported exponential moving average iterator type: %T", input) 1237 } 1238 } 1239 1240 // newDoubleExponentialMovingAverageIterator returns an iterator for operating on a double_exponential_moving_average() call. 1241 func newDoubleExponentialMovingAverageIterator(input Iterator, n int, nHold int, warmupType gota.WarmupType, opt IteratorOptions) (Iterator, error) { 1242 switch input := input.(type) { 1243 case FloatIterator: 1244 createFn := func() (FloatPointAggregator, FloatPointEmitter) { 1245 fn := NewDoubleExponentialMovingAverageReducer(n, nHold, warmupType) 1246 return fn, fn 1247 } 1248 return newFloatStreamFloatIterator(input, createFn, opt), nil 1249 case IntegerIterator: 1250 createFn := func() (IntegerPointAggregator, FloatPointEmitter) { 1251 fn := NewDoubleExponentialMovingAverageReducer(n, nHold, warmupType) 1252 return fn, fn 1253 } 1254 return newIntegerStreamFloatIterator(input, createFn, opt), nil 1255 case UnsignedIterator: 1256 createFn := func() (UnsignedPointAggregator, FloatPointEmitter) { 1257 fn := NewDoubleExponentialMovingAverageReducer(n, nHold, warmupType) 1258 return fn, fn 1259 } 1260 return newUnsignedStreamFloatIterator(input, createFn, opt), nil 1261 default: 1262 return nil, fmt.Errorf("unsupported double exponential moving average iterator type: %T", input) 1263 } 1264 } 1265 1266 // newTripleExponentialMovingAverageIterator returns an iterator for operating on a triple_exponential_moving_average() call. 1267 func newTripleExponentialMovingAverageIterator(input Iterator, n int, nHold int, warmupType gota.WarmupType, opt IteratorOptions) (Iterator, error) { 1268 switch input := input.(type) { 1269 case FloatIterator: 1270 createFn := func() (FloatPointAggregator, FloatPointEmitter) { 1271 fn := NewTripleExponentialMovingAverageReducer(n, nHold, warmupType) 1272 return fn, fn 1273 } 1274 return newFloatStreamFloatIterator(input, createFn, opt), nil 1275 case IntegerIterator: 1276 createFn := func() (IntegerPointAggregator, FloatPointEmitter) { 1277 fn := NewTripleExponentialMovingAverageReducer(n, nHold, warmupType) 1278 return fn, fn 1279 } 1280 return newIntegerStreamFloatIterator(input, createFn, opt), nil 1281 case UnsignedIterator: 1282 createFn := func() (UnsignedPointAggregator, FloatPointEmitter) { 1283 fn := NewTripleExponentialMovingAverageReducer(n, nHold, warmupType) 1284 return fn, fn 1285 } 1286 return newUnsignedStreamFloatIterator(input, createFn, opt), nil 1287 default: 1288 return nil, fmt.Errorf("unsupported triple exponential moving average iterator type: %T", input) 1289 } 1290 } 1291 1292 // newRelativeStrengthIndexIterator returns an iterator for operating on a triple_exponential_moving_average() call. 1293 func newRelativeStrengthIndexIterator(input Iterator, n int, nHold int, warmupType gota.WarmupType, opt IteratorOptions) (Iterator, error) { 1294 switch input := input.(type) { 1295 case FloatIterator: 1296 createFn := func() (FloatPointAggregator, FloatPointEmitter) { 1297 fn := NewRelativeStrengthIndexReducer(n, nHold, warmupType) 1298 return fn, fn 1299 } 1300 return newFloatStreamFloatIterator(input, createFn, opt), nil 1301 case IntegerIterator: 1302 createFn := func() (IntegerPointAggregator, FloatPointEmitter) { 1303 fn := NewRelativeStrengthIndexReducer(n, nHold, warmupType) 1304 return fn, fn 1305 } 1306 return newIntegerStreamFloatIterator(input, createFn, opt), nil 1307 case UnsignedIterator: 1308 createFn := func() (UnsignedPointAggregator, FloatPointEmitter) { 1309 fn := NewRelativeStrengthIndexReducer(n, nHold, warmupType) 1310 return fn, fn 1311 } 1312 return newUnsignedStreamFloatIterator(input, createFn, opt), nil 1313 default: 1314 return nil, fmt.Errorf("unsupported relative strength index iterator type: %T", input) 1315 } 1316 } 1317 1318 // newTripleExponentialDerivativeIterator returns an iterator for operating on a triple_exponential_moving_average() call. 1319 func newTripleExponentialDerivativeIterator(input Iterator, n int, nHold int, warmupType gota.WarmupType, opt IteratorOptions) (Iterator, error) { 1320 switch input := input.(type) { 1321 case FloatIterator: 1322 createFn := func() (FloatPointAggregator, FloatPointEmitter) { 1323 fn := NewTripleExponentialDerivativeReducer(n, nHold, warmupType) 1324 return fn, fn 1325 } 1326 return newFloatStreamFloatIterator(input, createFn, opt), nil 1327 case IntegerIterator: 1328 createFn := func() (IntegerPointAggregator, FloatPointEmitter) { 1329 fn := NewTripleExponentialDerivativeReducer(n, nHold, warmupType) 1330 return fn, fn 1331 } 1332 return newIntegerStreamFloatIterator(input, createFn, opt), nil 1333 case UnsignedIterator: 1334 createFn := func() (UnsignedPointAggregator, FloatPointEmitter) { 1335 fn := NewTripleExponentialDerivativeReducer(n, nHold, warmupType) 1336 return fn, fn 1337 } 1338 return newUnsignedStreamFloatIterator(input, createFn, opt), nil 1339 default: 1340 return nil, fmt.Errorf("unsupported triple exponential derivative iterator type: %T", input) 1341 } 1342 } 1343 1344 // newKaufmansEfficiencyRatioIterator returns an iterator for operating on a kaufmans_efficiency_ratio() call. 1345 func newKaufmansEfficiencyRatioIterator(input Iterator, n int, nHold int, opt IteratorOptions) (Iterator, error) { 1346 switch input := input.(type) { 1347 case FloatIterator: 1348 createFn := func() (FloatPointAggregator, FloatPointEmitter) { 1349 fn := NewKaufmansEfficiencyRatioReducer(n, nHold) 1350 return fn, fn 1351 } 1352 return newFloatStreamFloatIterator(input, createFn, opt), nil 1353 case IntegerIterator: 1354 createFn := func() (IntegerPointAggregator, FloatPointEmitter) { 1355 fn := NewKaufmansEfficiencyRatioReducer(n, nHold) 1356 return fn, fn 1357 } 1358 return newIntegerStreamFloatIterator(input, createFn, opt), nil 1359 case UnsignedIterator: 1360 createFn := func() (UnsignedPointAggregator, FloatPointEmitter) { 1361 fn := NewKaufmansEfficiencyRatioReducer(n, nHold) 1362 return fn, fn 1363 } 1364 return newUnsignedStreamFloatIterator(input, createFn, opt), nil 1365 default: 1366 return nil, fmt.Errorf("unsupported kaufmans efficiency ratio iterator type: %T", input) 1367 } 1368 } 1369 1370 // newKaufmansAdaptiveMovingAverageIterator returns an iterator for operating on a kaufmans_adaptive_moving_average() call. 1371 func newKaufmansAdaptiveMovingAverageIterator(input Iterator, n int, nHold int, opt IteratorOptions) (Iterator, error) { 1372 switch input := input.(type) { 1373 case FloatIterator: 1374 createFn := func() (FloatPointAggregator, FloatPointEmitter) { 1375 fn := NewKaufmansAdaptiveMovingAverageReducer(n, nHold) 1376 return fn, fn 1377 } 1378 return newFloatStreamFloatIterator(input, createFn, opt), nil 1379 case IntegerIterator: 1380 createFn := func() (IntegerPointAggregator, FloatPointEmitter) { 1381 fn := NewKaufmansAdaptiveMovingAverageReducer(n, nHold) 1382 return fn, fn 1383 } 1384 return newIntegerStreamFloatIterator(input, createFn, opt), nil 1385 case UnsignedIterator: 1386 createFn := func() (UnsignedPointAggregator, FloatPointEmitter) { 1387 fn := NewKaufmansAdaptiveMovingAverageReducer(n, nHold) 1388 return fn, fn 1389 } 1390 return newUnsignedStreamFloatIterator(input, createFn, opt), nil 1391 default: 1392 return nil, fmt.Errorf("unsupported kaufmans adaptive moving average iterator type: %T", input) 1393 } 1394 } 1395 1396 // newChandeMomentumOscillatorIterator returns an iterator for operating on a triple_exponential_moving_average() call. 1397 func newChandeMomentumOscillatorIterator(input Iterator, n int, nHold int, warmupType gota.WarmupType, opt IteratorOptions) (Iterator, error) { 1398 switch input := input.(type) { 1399 case FloatIterator: 1400 createFn := func() (FloatPointAggregator, FloatPointEmitter) { 1401 fn := NewChandeMomentumOscillatorReducer(n, nHold, warmupType) 1402 return fn, fn 1403 } 1404 return newFloatStreamFloatIterator(input, createFn, opt), nil 1405 case IntegerIterator: 1406 createFn := func() (IntegerPointAggregator, FloatPointEmitter) { 1407 fn := NewChandeMomentumOscillatorReducer(n, nHold, warmupType) 1408 return fn, fn 1409 } 1410 return newIntegerStreamFloatIterator(input, createFn, opt), nil 1411 case UnsignedIterator: 1412 createFn := func() (UnsignedPointAggregator, FloatPointEmitter) { 1413 fn := NewChandeMomentumOscillatorReducer(n, nHold, warmupType) 1414 return fn, fn 1415 } 1416 return newUnsignedStreamFloatIterator(input, createFn, opt), nil 1417 default: 1418 return nil, fmt.Errorf("unsupported chande momentum oscillator iterator type: %T", input) 1419 } 1420 } 1421 1422 // newCumulativeSumIterator returns an iterator for operating on a cumulative_sum() call. 1423 func newCumulativeSumIterator(input Iterator, opt IteratorOptions) (Iterator, error) { 1424 switch input := input.(type) { 1425 case FloatIterator: 1426 createFn := func() (FloatPointAggregator, FloatPointEmitter) { 1427 fn := NewFloatCumulativeSumReducer() 1428 return fn, fn 1429 } 1430 return newFloatStreamFloatIterator(input, createFn, opt), nil 1431 case IntegerIterator: 1432 createFn := func() (IntegerPointAggregator, IntegerPointEmitter) { 1433 fn := NewIntegerCumulativeSumReducer() 1434 return fn, fn 1435 } 1436 return newIntegerStreamIntegerIterator(input, createFn, opt), nil 1437 case UnsignedIterator: 1438 createFn := func() (UnsignedPointAggregator, UnsignedPointEmitter) { 1439 fn := NewUnsignedCumulativeSumReducer() 1440 return fn, fn 1441 } 1442 return newUnsignedStreamUnsignedIterator(input, createFn, opt), nil 1443 default: 1444 return nil, fmt.Errorf("unsupported cumulative sum iterator type: %T", input) 1445 } 1446 } 1447 1448 // newHoltWintersIterator returns an iterator for operating on a holt_winters() call. 1449 func newHoltWintersIterator(input Iterator, opt IteratorOptions, h, m int, includeFitData bool, interval time.Duration) (Iterator, error) { 1450 switch input := input.(type) { 1451 case FloatIterator: 1452 createFn := func() (FloatPointAggregator, FloatPointEmitter) { 1453 fn := NewFloatHoltWintersReducer(h, m, includeFitData, interval) 1454 return fn, fn 1455 } 1456 return newFloatReduceFloatIterator(input, opt, createFn), nil 1457 case IntegerIterator: 1458 createFn := func() (IntegerPointAggregator, FloatPointEmitter) { 1459 fn := NewFloatHoltWintersReducer(h, m, includeFitData, interval) 1460 return fn, fn 1461 } 1462 return newIntegerReduceFloatIterator(input, opt, createFn), nil 1463 default: 1464 return nil, fmt.Errorf("unsupported elapsed iterator type: %T", input) 1465 } 1466 } 1467 1468 // NewSampleIterator returns an iterator for operating on a sample() call (exported for use in test). 1469 func NewSampleIterator(input Iterator, opt IteratorOptions, size int) (Iterator, error) { 1470 return newSampleIterator(input, opt, size) 1471 } 1472 1473 // newSampleIterator returns an iterator for operating on a sample() call. 1474 func newSampleIterator(input Iterator, opt IteratorOptions, size int) (Iterator, error) { 1475 switch input := input.(type) { 1476 case FloatIterator: 1477 createFn := func() (FloatPointAggregator, FloatPointEmitter) { 1478 fn := NewFloatSampleReducer(size) 1479 return fn, fn 1480 } 1481 return newFloatReduceFloatIterator(input, opt, createFn), nil 1482 case IntegerIterator: 1483 createFn := func() (IntegerPointAggregator, IntegerPointEmitter) { 1484 fn := NewIntegerSampleReducer(size) 1485 return fn, fn 1486 } 1487 return newIntegerReduceIntegerIterator(input, opt, createFn), nil 1488 case UnsignedIterator: 1489 createFn := func() (UnsignedPointAggregator, UnsignedPointEmitter) { 1490 fn := NewUnsignedSampleReducer(size) 1491 return fn, fn 1492 } 1493 return newUnsignedReduceUnsignedIterator(input, opt, createFn), nil 1494 case StringIterator: 1495 createFn := func() (StringPointAggregator, StringPointEmitter) { 1496 fn := NewStringSampleReducer(size) 1497 return fn, fn 1498 } 1499 return newStringReduceStringIterator(input, opt, createFn), nil 1500 case BooleanIterator: 1501 createFn := func() (BooleanPointAggregator, BooleanPointEmitter) { 1502 fn := NewBooleanSampleReducer(size) 1503 return fn, fn 1504 } 1505 return newBooleanReduceBooleanIterator(input, opt, createFn), nil 1506 default: 1507 return nil, fmt.Errorf("unsupported elapsed iterator type: %T", input) 1508 } 1509 } 1510 1511 // newIntegralIterator returns an iterator for operating on a integral() call. 1512 func newIntegralIterator(input Iterator, opt IteratorOptions, interval Interval) (Iterator, error) { 1513 switch input := input.(type) { 1514 case FloatIterator: 1515 createFn := func() (FloatPointAggregator, FloatPointEmitter) { 1516 fn := NewFloatIntegralReducer(interval, opt) 1517 return fn, fn 1518 } 1519 return newFloatStreamFloatIterator(input, createFn, opt), nil 1520 case IntegerIterator: 1521 createFn := func() (IntegerPointAggregator, FloatPointEmitter) { 1522 fn := NewIntegerIntegralReducer(interval, opt) 1523 return fn, fn 1524 } 1525 return newIntegerStreamFloatIterator(input, createFn, opt), nil 1526 case UnsignedIterator: 1527 createFn := func() (UnsignedPointAggregator, FloatPointEmitter) { 1528 fn := NewUnsignedIntegralReducer(interval, opt) 1529 return fn, fn 1530 } 1531 return newUnsignedStreamFloatIterator(input, createFn, opt), nil 1532 default: 1533 return nil, fmt.Errorf("unsupported integral iterator type: %T", input) 1534 } 1535 } 1536 1537 // NewSumHllIterator returns an iterator for operating on a distinct() call. 1538 func NewSumHllIterator(input Iterator, opt IteratorOptions) (Iterator, error) { 1539 switch input := input.(type) { 1540 case FloatIterator: 1541 createFn := func() (FloatPointAggregator, StringPointEmitter) { 1542 fn := NewFloatSumHllReducer() 1543 return fn, fn 1544 } 1545 return newFloatReduceStringIterator(input, opt, createFn), nil 1546 case IntegerIterator: 1547 createFn := func() (IntegerPointAggregator, StringPointEmitter) { 1548 fn := NewIntegerSumHllReducer() 1549 return fn, fn 1550 } 1551 return newIntegerReduceStringIterator(input, opt, createFn), nil 1552 case UnsignedIterator: 1553 createFn := func() (UnsignedPointAggregator, StringPointEmitter) { 1554 fn := NewUnsignedSumHllReducer() 1555 return fn, fn 1556 } 1557 return newUnsignedReduceStringIterator(input, opt, createFn), nil 1558 case StringIterator: 1559 createFn := func() (StringPointAggregator, StringPointEmitter) { 1560 fn := NewStringSumHllReducer() 1561 return fn, fn 1562 } 1563 return newStringReduceStringIterator(input, opt, createFn), nil 1564 case BooleanIterator: 1565 createFn := func() (BooleanPointAggregator, StringPointEmitter) { 1566 fn := NewBooleanSumHllReducer() 1567 return fn, fn 1568 } 1569 return newBooleanReduceStringIterator(input, opt, createFn), nil 1570 default: 1571 return nil, fmt.Errorf("unsupported sum_hll iterator type: %T", input) 1572 } 1573 } 1574 1575 // NewSumHllIterator returns an iterator for operating on a distinct() call. 1576 func NewMergeHllIterator(input Iterator, opt IteratorOptions) (Iterator, error) { 1577 switch input := input.(type) { 1578 case StringIterator: 1579 createFn := func() (StringPointAggregator, StringPointEmitter) { 1580 fn := NewStringMergeHllReducer() 1581 return fn, fn 1582 } 1583 return newStringReduceStringIterator(input, opt, createFn), nil 1584 default: 1585 return nil, fmt.Errorf("unsupported merge_hll iterator type: %T", input) 1586 } 1587 } 1588 1589 func NewCountHllIterator(input Iterator, opt IteratorOptions) (Iterator, error) { 1590 switch input := input.(type) { 1591 case StringIterator: 1592 createFn := func() (StringPointAggregator, UnsignedPointEmitter) { 1593 fn := NewCountHllReducer() 1594 return fn, fn 1595 } 1596 return newStringStreamUnsignedIterator(input, createFn, opt), nil 1597 default: 1598 return nil, fmt.Errorf("unsupported count_hll iterator type: %T", input) 1599 } 1600 }