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

     1  package removeEmptySeries
     2  
     3  import (
     4  	"context"
     5  	"math"
     6  	"strconv"
     7  
     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 removeEmptySeries 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 := &removeEmptySeries{}
    23  	functions := []string{"removeEmptySeries", "removeZeroSeries"}
    24  	for _, n := range functions {
    25  		res = append(res, interfaces.FunctionMetadata{Name: n, F: f})
    26  	}
    27  	return res
    28  }
    29  
    30  // removeEmptySeries(seriesLists, n), removeZeroSeries(seriesLists, n)
    31  func (f *removeEmptySeries) Do(ctx context.Context, eval interfaces.Evaluator, e parser.Expr, from, until int64, values map[parser.MetricRequest][]*types.MetricData) ([]*types.MetricData, error) {
    32  	var xFilesFactor float64
    33  
    34  	args, err := helper.GetSeriesArg(ctx, eval, e.Arg(0), from, until, values)
    35  	if err != nil {
    36  		return nil, err
    37  	}
    38  	if len(args) == 0 {
    39  		return []*types.MetricData{}, nil
    40  	}
    41  
    42  	if e.ArgsLen() == 2 {
    43  		xFilesFactor, err = e.GetFloatArgDefault(1, float64(args[0].XFilesFactor)) // If set by setXFilesFactor, all series in a list will have the same value
    44  		if err != nil {
    45  			return nil, err
    46  		}
    47  	}
    48  
    49  	xFilesFactorStr := strconv.FormatFloat(xFilesFactor, 'f', -1, 64)
    50  
    51  	results := make([]*types.MetricData, 0, len(args))
    52  	for _, arg := range args {
    53  		nonNull := 0
    54  		for _, v := range arg.Values {
    55  			if !math.IsNaN(v) {
    56  				switch e.Target() {
    57  				case "removeEmptySeries":
    58  					nonNull++
    59  				case "removeZeroSeries":
    60  					if v != 0 {
    61  						nonNull++
    62  					}
    63  				}
    64  			}
    65  		}
    66  
    67  		if nonNull != 0 && helper.XFilesFactor(nonNull, len(arg.Values), xFilesFactor) {
    68  			r := arg.CopyLink()
    69  			r.Tags[e.Target()] = xFilesFactorStr
    70  			results = append(results, r)
    71  		}
    72  	}
    73  	return results, nil
    74  }
    75  
    76  // Description is auto-generated description, based on output of https://github.com/graphite-project/graphite-web
    77  func (f *removeEmptySeries) Description() map[string]types.FunctionDescription {
    78  	return map[string]types.FunctionDescription{
    79  		"removeEmptySeries": {
    80  			Description: "Takes one metric or a wildcard seriesList.\nOut of all metrics passed, draws only the metrics with not empty data\n\nExample:\n\n.. code-block:: none\n\n  &target=removeEmptySeries(server*.instance*.threads.busy)\n\nDraws only live servers with not empty data.\n\n`xFilesFactor` follows the same semantics as in Whisper storage schemas.  Setting it to 0 (the\ndefault) means that only a single value in the series needs to be non-null for it to be\nconsidered non-empty, setting it to 1 means that all values in the series must be non-null.\nA setting of 0.5 means that at least half the values in the series must be non-null.",
    81  			Function:    "removeEmptySeries(seriesList, xFilesFactor=None)",
    82  			Group:       "Filter Series",
    83  			Module:      "graphite.render.functions",
    84  			Name:        "removeEmptySeries",
    85  			Params: []types.FunctionParam{
    86  				{
    87  					Name:     "seriesList",
    88  					Required: true,
    89  					Type:     types.SeriesList,
    90  				},
    91  				{
    92  					Name:     "xFilesFactor",
    93  					Required: true,
    94  					Type:     types.Float,
    95  				},
    96  			},
    97  			SeriesChange: true, // function aggregate metrics or change series items count
    98  			NameChange:   true, // name changed
    99  			ValuesChange: true, // values changed
   100  		},
   101  		"removeZeroSeries": {
   102  			Description: "Takes one metric or a wildcard seriesList.\nOut of all metrics passed, draws only the metrics with not ZERO data\n\nExample:\n\n.. code-block:: none\n\n  &target=removeZeroSeries(server*.instance*.threads.busy)\n\nDraws only live servers with not empty data.\n\n`xFilesFactor` follows the same semantics as in Whisper storage schemas.  Setting it to 0 (the\ndefault) means that only a single value in the series needs to be non-null for it to be\nconsidered non-empty, setting it to 1 means that all values in the series must be non-null.\nA setting of 0.5 means that at least half the values in the series must be non-null.",
   103  			Function:    "removeZeroSeries(seriesList, xFilesFactor=None)",
   104  			Group:       "Filter Series",
   105  			Module:      "graphite.render.functions.custom",
   106  			Name:        "removeZeroSeries",
   107  			Params: []types.FunctionParam{
   108  				{
   109  					Name:     "seriesList",
   110  					Required: true,
   111  					Type:     types.SeriesList,
   112  				},
   113  				{
   114  					Name:     "xFilesFactor",
   115  					Required: true,
   116  					Type:     types.Float,
   117  				},
   118  			},
   119  			SeriesChange: true, // function aggregate metrics or change series items count
   120  			NameChange:   true, // name changed
   121  			ValuesChange: true, // values changed
   122  		},
   123  	}
   124  }