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

     1  package delay
     2  
     3  import (
     4  	"context"
     5  	"math"
     6  
     7  	"github.com/go-graphite/carbonapi/expr/helper"
     8  	"github.com/go-graphite/carbonapi/expr/interfaces"
     9  	"github.com/go-graphite/carbonapi/expr/types"
    10  	"github.com/go-graphite/carbonapi/pkg/parser"
    11  )
    12  
    13  type delay struct{}
    14  
    15  func GetOrder() interfaces.Order {
    16  	return interfaces.Any
    17  }
    18  
    19  func New(configFile string) []interfaces.FunctionMetadata {
    20  	res := make([]interfaces.FunctionMetadata, 0)
    21  	f := &delay{}
    22  	functions := []string{"delay"}
    23  	for _, n := range functions {
    24  		res = append(res, interfaces.FunctionMetadata{Name: n, F: f})
    25  	}
    26  	return res
    27  }
    28  
    29  // delay(seriesList, steps)
    30  func (f *delay) Do(ctx context.Context, eval interfaces.Evaluator, e parser.Expr, from, until int64, values map[parser.MetricRequest][]*types.MetricData) ([]*types.MetricData, error) {
    31  	if e.ArgsLen() < 2 {
    32  		return nil, parser.ErrMissingArgument
    33  	}
    34  
    35  	seriesList, err := helper.GetSeriesArg(ctx, eval, e.Arg(0), from, until, values)
    36  	if err != nil {
    37  		return nil, err
    38  	}
    39  
    40  	steps, err := e.GetIntArg(1)
    41  	if err != nil {
    42  		return nil, err
    43  	}
    44  	stepsStr := e.Arg(1).StringValue()
    45  
    46  	results := make([]*types.MetricData, len(seriesList))
    47  
    48  	for i, series := range seriesList {
    49  		length := len(series.Values)
    50  
    51  		result := series.CopyLink()
    52  		result.Name = "delay(" + series.Name + "," + stepsStr + ")"
    53  		result.Tags["delay"] = stepsStr
    54  
    55  		var newValues []float64
    56  		if steps < 0 {
    57  			newValues = make([]float64, length)
    58  			copy(newValues, series.Values[-steps:])
    59  			for i := -steps; i < length; i++ {
    60  				newValues[i] = math.NaN()
    61  			}
    62  			result.Values = newValues
    63  		} else if steps != 0 {
    64  			newValues = make([]float64, length)
    65  			for i := 0; i < steps; i++ {
    66  				newValues[i] = math.NaN()
    67  			}
    68  			copy(newValues[steps:], series.Values[:length-steps])
    69  			result.Values = newValues
    70  		}
    71  
    72  		results[i] = result
    73  	}
    74  
    75  	return results, nil
    76  }
    77  
    78  // Description is auto-generated description, based on output of https://github.com/graphite-project/graphite-web
    79  func (f *delay) Description() map[string]types.FunctionDescription {
    80  	return map[string]types.FunctionDescription{
    81  		"delay": {
    82  			Description: "This shifts all samples later by an integer number of steps. This can be\nused for custom derivative calculations, among other things. Note: this\nwill pad the early end of the data with None for every step shifted.\n\nThis complements other time-displacement functions such as timeShift and\ntimeSlice, in that this function is indifferent about the step intervals\nbeing shifted.\n\nExample:\n\n.. code-block:: none\n\n  &target=divideSeries(server.FreeSpace,delay(server.FreeSpace,1))\n\nThis computes the change in server free space as a percentage of the previous\nfree space.",
    83  			Function:    "delay(seriesList, steps)",
    84  			Group:       "Transform",
    85  			Module:      "graphite.render.functions",
    86  			Name:        "delay",
    87  			Params: []types.FunctionParam{
    88  				{
    89  					Name:     "seriesList",
    90  					Required: true,
    91  					Type:     types.SeriesList,
    92  				},
    93  				{
    94  					Name:     "steps",
    95  					Required: true,
    96  					Type:     types.Integer,
    97  				},
    98  			},
    99  			NameChange:   true, // name changed
   100  			ValuesChange: true, // values changed
   101  		},
   102  	}
   103  }