github.com/go-graphite/carbonapi@v0.17.0/expr/functions/ewma/function.go (about)

     1  package ewma
     2  
     3  import (
     4  	"context"
     5  	"math"
     6  
     7  	"github.com/dgryski/go-onlinestats"
     8  	"github.com/go-graphite/carbonapi/expr/helper"
     9  	"github.com/go-graphite/carbonapi/expr/interfaces"
    10  	"github.com/go-graphite/carbonapi/expr/types"
    11  	"github.com/go-graphite/carbonapi/pkg/parser"
    12  )
    13  
    14  type ewma struct{}
    15  
    16  func GetOrder() interfaces.Order {
    17  	return interfaces.Any
    18  }
    19  
    20  func New(configFile string) []interfaces.FunctionMetadata {
    21  	res := make([]interfaces.FunctionMetadata, 0)
    22  	f := &ewma{}
    23  	functions := []string{"ewma", "exponentialWeightedMovingAverage"}
    24  	for _, n := range functions {
    25  		res = append(res, interfaces.FunctionMetadata{Name: n, F: f})
    26  	}
    27  	return res
    28  }
    29  
    30  // ewma(seriesList, alpha)
    31  func (f *ewma) Do(ctx context.Context, eval interfaces.Evaluator, e parser.Expr, from, until int64, values map[parser.MetricRequest][]*types.MetricData) ([]*types.MetricData, error) {
    32  	if e.ArgsLen() < 2 {
    33  		return nil, parser.ErrMissingArgument
    34  	}
    35  
    36  	arg, err := helper.GetSeriesArg(ctx, eval, e.Arg(0), from, until, values)
    37  	if err != nil {
    38  		return nil, err
    39  	}
    40  
    41  	alpha, err := e.GetFloatArg(1)
    42  	if err != nil {
    43  		return nil, err
    44  	}
    45  	alphaStr := e.Arg(1).StringValue()
    46  
    47  	e.SetTarget("ewma")
    48  
    49  	// ugh, helper.ForEachSeriesDo does not handle arguments properly
    50  	results := make([]*types.MetricData, len(arg))
    51  	for i, a := range arg {
    52  		name := "ewma(" + a.Name + "," + alphaStr + ")"
    53  
    54  		r := a.CopyTag(name, a.Tags)
    55  		r.Values = make([]float64, len(a.Values))
    56  
    57  		ewma := onlinestats.NewExpWeight(alpha)
    58  
    59  		for i, v := range a.Values {
    60  			if math.IsNaN(v) {
    61  				r.Values[i] = math.NaN()
    62  				continue
    63  			}
    64  
    65  			ewma.Push(v)
    66  			r.Values[i] = ewma.Mean()
    67  		}
    68  		results[i] = r
    69  	}
    70  	return results, nil
    71  }
    72  
    73  func (f *ewma) Description() map[string]types.FunctionDescription {
    74  	return map[string]types.FunctionDescription{
    75  		"exponentialWeightedMovingAverage": {
    76  			Description: "Takes a series of values and a alpha and produces an exponential moving\naverage using algorithm described at https://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average\n\nExample:\n\n.. code-block:: none\n\n  &target=exponentialWeightedMovingAverage(*.transactions.count, 0.1)",
    77  			Function:    "exponentialWeightedMovingAverage(seriesList, alpha)",
    78  			Group:       "Calculate",
    79  			Module:      "graphite.render.functions.custom",
    80  			Name:        "exponentialWeightedMovingAverage",
    81  			Params: []types.FunctionParam{
    82  				{
    83  					Name:     "seriesList",
    84  					Required: true,
    85  					Type:     types.SeriesList,
    86  				},
    87  				{
    88  					Name:     "alpha",
    89  					Required: true,
    90  					Suggestions: types.NewSuggestions(
    91  						0.1,
    92  						0.5,
    93  						0.7,
    94  					),
    95  					Type: types.Float,
    96  				},
    97  			},
    98  			NameChange:   true, // name changed
    99  			ValuesChange: true, // values changed
   100  		},
   101  		"ewma": {
   102  			Description: "Takes a series of values and a alpha and produces an exponential moving\naverage using algorithm described at https://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average\n\nExample:\n\n.. code-block:: none\n\n  &target=exponentialWeightedMovingAverage(*.transactions.count, 0.1)",
   103  			Function:    "exponentialWeightedMovingAverage(seriesList, alpha)",
   104  			Group:       "Calculate",
   105  			Module:      "graphite.render.functions.custom",
   106  			Name:        "ewma",
   107  			Params: []types.FunctionParam{
   108  				{
   109  					Name:     "seriesList",
   110  					Required: true,
   111  					Type:     types.SeriesList,
   112  				},
   113  				{
   114  					Name:     "alpha",
   115  					Required: true,
   116  					Suggestions: types.NewSuggestions(
   117  						0.1,
   118  						0.5,
   119  						0.7,
   120  					),
   121  					Type: types.Float,
   122  				},
   123  			},
   124  			NameChange:   true, // name changed
   125  			ValuesChange: true, // values changed
   126  		},
   127  	}
   128  }