1package logarithm
2
3import (
4	"context"
5	"fmt"
6	"math"
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
14type logarithm struct {
15	interfaces.FunctionBase
16}
17
18func GetOrder() interfaces.Order {
19	return interfaces.Any
20}
21
22func New(configFile string) []interfaces.FunctionMetadata {
23	res := make([]interfaces.FunctionMetadata, 0)
24	f := &logarithm{}
25	functions := []string{"logarithm", "log"}
26	for _, n := range functions {
27		res = append(res, interfaces.FunctionMetadata{Name: n, F: f})
28	}
29	return res
30}
31
32// logarithm(seriesList, base=10)
33// Alias: log
34func (f *logarithm) Do(ctx context.Context, e parser.Expr, from, until int64, values map[parser.MetricRequest][]*types.MetricData) ([]*types.MetricData, error) {
35	arg, err := helper.GetSeriesArg(e.Args()[0], from, until, values)
36	if err != nil {
37		return nil, err
38	}
39	base, err := e.GetIntNamedOrPosArgDefault("base", 1, 10)
40	if err != nil {
41		return nil, err
42	}
43	_, ok := e.NamedArgs()["base"]
44	if !ok {
45		ok = len(e.Args()) > 1
46	}
47
48	baseLog := math.Log(float64(base))
49
50	var results []*types.MetricData
51
52	for _, a := range arg {
53
54		var name string
55		if ok {
56			name = fmt.Sprintf("logarithm(%s,%d)", a.Name, base)
57		} else {
58			name = fmt.Sprintf("logarithm(%s)", a.Name)
59		}
60
61		r := *a
62		r.Name = name
63		r.Values = make([]float64, len(a.Values))
64
65		for i, v := range a.Values {
66			r.Values[i] = math.Log(v) / baseLog
67		}
68		results = append(results, &r)
69	}
70	return results, nil
71}
72
73// Description is auto-generated description, based on output of https://github.com/graphite-project/graphite-web
74func (f *logarithm) Description() map[string]types.FunctionDescription {
75	return map[string]types.FunctionDescription{
76		"logarithm": {
77			Description: "Takes one metric or a wildcard seriesList, a base, and draws the y-axis in logarithmic\nformat.  If base is omitted, the function defaults to base 10.\n\nExample:\n\n.. code-block:: none\n\n  &target=log(carbon.agents.hostname.avgUpdateTime,2)",
78			Function:    "log(seriesList, base=10)",
79			Group:       "Transform",
80			Module:      "graphite.render.functions",
81			Name:        "log",
82			Params: []types.FunctionParam{
83				{
84					Name:     "seriesList",
85					Required: true,
86					Type:     types.SeriesList,
87				},
88				{
89					Default: types.NewSuggestion(10),
90					Name:    "base",
91					Type:    types.Integer,
92				},
93			},
94		},
95		"log": {
96			Description: "Takes one metric or a wildcard seriesList, a base, and draws the y-axis in logarithmic\nformat.  If base is omitted, the function defaults to base 10.\n\nExample:\n\n.. code-block:: none\n\n  &target=log(carbon.agents.hostname.avgUpdateTime,2)",
97			Function:    "log(seriesList, base=10)",
98			Group:       "Transform",
99			Module:      "graphite.render.functions",
100			Name:        "log",
101			Params: []types.FunctionParam{
102				{
103					Name:     "seriesList",
104					Required: true,
105					Type:     types.SeriesList,
106				},
107				{
108					Default: types.NewSuggestion(10),
109					Name:    "base",
110					Type:    types.Integer,
111				},
112			},
113		},
114	}
115}
116