To try to make it easier to define MetricFunctions without having to write repetitive evaluations and casts everywhere, a new function function.MakeFunction (possible rename to just Make) has been added.
It asks for an interface{} which is a function that acts like a metric function. It can take any of:
string
float64
time.Duration
api.SeriesList
function.Value
function.Expression
In addition, it can have optional arguments by requesting pointers to any of these:
*string
*float
*time.Duration
*api.SeriesList
*function.Value
*function.Expression
Non-optional formal arguments cannot follow optional ones. (So, for example, (float, *string, float) would be illegal).
For all of these, the parameters will be evaluated before they are passed to the function except for function.Expression and *function.Expression, where it is up to the given function to evaluate them.
All evaluations are done in parallel automatically, so the function itself does not have to do any extra work here.
The argument function can also ask for an function.EvaluationContext to get the current context (or an api.Timerange to get just the current timerange).
If it wants to allow group by or collapse by clauses, it can ask for a function.Groups object.
The argument function can return either (function.Value, error) or just a function.Value (which means it never errors). Either of these can be replaced by any subtype implementing these interfaces (e.g. api.SeriesList or SyntaxError respectively).
If an input function violates any of these constraints, MakeFunction panics.
TODO: test optional arguments, cleaning up reflection in MakeFunction.
TODO: variadic functions for MakeFunction (for variadic functions in MQE)
TODO: float, string, duration returns?
Example
Consider the following toy metric function:
Old Way
// adder takes one or two numbers.
// when given only one parameter, the second defaults to "1.0".
function.MetricFunction {
Name: "adder",
MinArguments: 1,
MaxArguments: 2,
Compute: func(context function.EvaluationContext, arguments []function.Expression, groups function.Groups) (function.Value, error) {
left, err := function.EvaluateToDuration(arguments[0], context)
if err != nil {
return nil, err
}
right := float64(1.0)
if len(arguments) == 2 {
right, err = function.EvaluateToDuration(arguments[1], context)
}
return expression.Scalar(left + right), nil
},
}
New Way
// adder takes one or two numbers.
// when given only one parameter, the second defaults to "1.0".
function.MakeFunction(
"adder",
func(left float64, optionalRight *float64) float64 {
right := float64(1.0)
if optionalRight != nil {
right = *optionalRight
}
return left + right
},
)
in addition, the arguments will be evaluated in parallel here (there are library functions to evaluate them in parallel using the old way, but it will add several more lines for error-checking).
To try to make it easier to define
MetricFunction
s without having to write repetitive evaluations and casts everywhere, a new functionfunction.MakeFunction
(possible rename to justMake
) has been added.It asks for an
interface{}
which is a function that acts like a metric function. It can take any of:string
float64
time.Duration
api.SeriesList
function.Value
function.Expression
In addition, it can have optional arguments by requesting pointers to any of these:
*string
*float
*time.Duration
*api.SeriesList
*function.Value
*function.Expression
Non-optional formal arguments cannot follow optional ones. (So, for example,
(float, *string, float)
would be illegal).For all of these, the parameters will be evaluated before they are passed to the function except for
function.Expression
and*function.Expression
, where it is up to the given function to evaluate them.All evaluations are done in parallel automatically, so the function itself does not have to do any extra work here.
The argument function can also ask for an
function.EvaluationContext
to get the current context (or anapi.Timerange
to get just the current timerange).If it wants to allow
group by
orcollapse by
clauses, it can ask for afunction.Groups
object.The argument function can return either
(function.Value, error)
or just afunction.Value
(which means it never errors). Either of these can be replaced by any subtype implementing these interfaces (e.g.api.SeriesList
orSyntaxError
respectively).If an input function violates any of these constraints,
MakeFunction
panics.TODO: test optional arguments, cleaning up reflection in
MakeFunction
.TODO: variadic functions for
MakeFunction
(for variadic functions in MQE)TODO: float, string, duration returns?
Example
Consider the following toy metric function:
Old Way
New Way
in addition, the arguments will be evaluated in parallel here (there are library functions to evaluate them in parallel using the old way, but it will add several more lines for error-checking).