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

     1  package aggregateLine
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"math"
     7  	"strconv"
     8  
     9  	"github.com/go-graphite/carbonapi/expr/consolidations"
    10  	"github.com/go-graphite/carbonapi/expr/helper"
    11  	"github.com/go-graphite/carbonapi/expr/interfaces"
    12  	"github.com/go-graphite/carbonapi/expr/types"
    13  	"github.com/go-graphite/carbonapi/pkg/parser"
    14  )
    15  
    16  type aggregateLine struct{}
    17  
    18  func GetOrder() interfaces.Order {
    19  	return interfaces.Any
    20  }
    21  
    22  func New(configFile string) []interfaces.FunctionMetadata {
    23  	f := &aggregateLine{}
    24  	res := make([]interfaces.FunctionMetadata, 0)
    25  	for _, n := range []string{"aggregateLine"} {
    26  		res = append(res, interfaces.FunctionMetadata{Name: n, F: f})
    27  	}
    28  	return res
    29  }
    30  
    31  // aggregateLine(*seriesLists)
    32  func (f *aggregateLine) Do(ctx context.Context, eval interfaces.Evaluator, e parser.Expr, from, until int64, values map[parser.MetricRequest][]*types.MetricData) ([]*types.MetricData, error) {
    33  	args, err := helper.GetSeriesArg(ctx, eval, e.Arg(0), from, until, values)
    34  	if err != nil {
    35  		return nil, err
    36  	}
    37  
    38  	callback := "avg"
    39  	keepStep := false
    40  	switch e.ArgsLen() {
    41  	case 2:
    42  		callback, err = e.GetStringArgDefault(1, "average")
    43  		if err != nil {
    44  			return nil, err
    45  		}
    46  	case 3:
    47  		callback, err = e.GetStringArgDefault(1, "average")
    48  		if err != nil {
    49  			return nil, err
    50  		}
    51  
    52  		keepStep, err = e.GetBoolArgDefault(2, false)
    53  		if err != nil {
    54  			return nil, err
    55  		}
    56  	}
    57  
    58  	aggFunc, ok := consolidations.ConsolidationToFunc[callback]
    59  	if !ok {
    60  		return nil, fmt.Errorf("unsupported consolidation function %s", callback)
    61  	}
    62  
    63  	results := make([]*types.MetricData, len(args))
    64  	for i, a := range args {
    65  		var name string
    66  
    67  		val := aggFunc(a.Values)
    68  		if !math.IsNaN(val) {
    69  			name = "aggregateLine(" + a.Name + ", " + strconv.FormatFloat(val, 'g', -1, 64) + ")"
    70  		} else {
    71  			name = "aggregateLine(" + a.Name + ", None)"
    72  		}
    73  
    74  		r := a.CopyTag(name, a.Tags)
    75  
    76  		if keepStep {
    77  			r.Values = make([]float64, len(a.Values))
    78  			for i := range r.Values {
    79  				r.Values[i] = val
    80  			}
    81  		} else {
    82  			r.StepTime = a.StopTime - a.FetchResponse.StartTime
    83  			r.Values = []float64{val, val}
    84  			r.StopTime = r.StartTime + int64(len(r.FetchResponse.Values))*r.FetchResponse.StepTime
    85  		}
    86  
    87  		results[i] = r
    88  	}
    89  
    90  	return results, nil
    91  }
    92  
    93  // Description is auto-generated description, based on output of https://github.com/graphite-project/graphite-web
    94  func (f *aggregateLine) Description() map[string]types.FunctionDescription {
    95  	return map[string]types.FunctionDescription{
    96  		"aggregateLine": {
    97  			Name:        "aggregateLine",
    98  			Function:    "aggregateLine(seriesList, func='average', keepStep=False)",
    99  			Description: "Takes a metric or wildcard seriesList and draws a horizontal line\nbased on the function applied to each series.\n\nIf the optional keepStep parameter is set to True, the result will\nhave the same time period and step as the source series.\n\nNote: By default, the graphite renderer consolidates data points by\naveraging data points over time. If you are using the 'min' or 'max'\nfunction for aggregateLine, this can cause an unusual gap in the\nline drawn by this function and the data itself. To fix this, you\nshould use the consolidateBy() function with the same function\nargument you are using for aggregateLine. This will ensure that the\nproper data points are retained and the graph should line up\ncorrectly.\n\nExample:\n\n.. code-block:: none\n\n  &target=aggregateLine(server01.connections.total, 'avg')\n  &target=aggregateLine(server*.connections.total, 'avg')",
   100  			Module:      "graphite.render.functions",
   101  			Group:       "Calculate",
   102  			Params: []types.FunctionParam{
   103  				{
   104  					Name:     "seriesList",
   105  					Type:     types.SeriesList,
   106  					Required: true,
   107  				},
   108  				{
   109  					Name:     "func",
   110  					Type:     types.AggFunc,
   111  					Required: false,
   112  					Options:  types.StringsToSuggestionList(consolidations.AvailableConsolidationFuncs()),
   113  					Default: &types.Suggestion{
   114  						Value: "average",
   115  						Type:  types.SString,
   116  					},
   117  				},
   118  				{
   119  					Name: "keepStep",
   120  					Type: types.Boolean,
   121  					Default: &types.Suggestion{
   122  						Value: false,
   123  						Type:  types.SBool,
   124  					},
   125  				},
   126  			},
   127  			SeriesChange: true, // function aggregate metrics or change series items count
   128  			NameChange:   true, // name changed
   129  			TagsChange:   true, // name tag changed
   130  			ValuesChange: true, // values changed
   131  		},
   132  	}
   133  }