Metrics: calculation on variables

I would like to make a metric that uses the window function on another one, aggregating the consumption for the last days. Since the number of days is dependent on the use case, I was hoping to configure this as a variable. This is the code I have tried.

cm = CompoundMetric.make({
  "id": "cm",
  "name": "cm",
  "expression": "window('SUM', MyMetric, 1-days, days)",
  "variables": [{"name": "days"}]
})

spec = EvalMetricsSpec.make( {
	ids: ['id'],
	start: DateTime('2018-07-01'),
	end: DateTime('2019-07-01'),
	interval: 'DAY',
	expressions: ['cm'],
	bindings: { "days": 3 }
})

MyType.evalMetricsWithMetadata(spec,[cm])

However, running this resolves in an error:

"java.lang.NoSuchMethodError: c3.love.expr.bytecode.OperatorLib.sub(Ljava/lang/Double;Ljava/lang/Integer;)Ljava/lang/Double;"

If I replace the variable with a hardcoded value, it is doing the calculation fine. Is there any way to implement this so a single variable can be used in this case?

Can you try to force your variable to be an integer?

"variables": [{
  "name": "days",
  "type": "integer"
}]

tried that before I posted, and it didn’t work. Was still giving the same error

And if you try "type": "double" ?

If we read carefully the error message, we see that the ExpressionEngine complains about the function sub not being defined for arguments types Double and Integer, so the first one is considered to be a double (here it is the constant 1) and the second one is considered to be an integer (here it is your variable days).

You can also look into the function ExpressionEngineFunction.number().

can you try dataType instead of type?

“variables”: [{
“name”: “days”,
“dataType”: “integer”
}]

Indeed, my mistake: the variables parameter is a MetricVariable (with a dataType field) and the bindings is of type [map<string, any>] (where the any can be an object with type and value).

Sorry, the tests I did were with dataType already, as that was indeed what was indicated in the MetricVariable type. Both with integer and with double it is failing, and the error stays the same.

Also the number function doesn’t seem to interact very well with the variables.

Have you tried correcting changing the bindings type/syntax, as in Evaluate parametric metric with multiple bindings parameters?
Another guess: 3 -> 3.0…
Seems that it works if you replace “1-days” by just “-days”.

I suggest you work around the issue using:

cm = CompoundMetric.make({
  "id": "cm",
  "name": "cm",
  "expression": "window('SUM', MyMetric, from, to)",
  "variables": [{"name": "from"}, {"name": "to"}]
})

spec = EvalMetricsSpec.make( {
	ids: ['id'],
	start: DateTime('2018-07-01'),
	end: DateTime('2019-07-01'),
	interval: 'DAY',
	expressions: ['cm'],
	bindings: { "from": -2, "to": 3 }
})

MyType.evalMetricsWithMetadata(spec,[cm])

I tried using 3.0 as value, and that also seems to fail. To me, it seems to be related to the way how the expression engine is handling the variables. It seems to be treating the value always as an integer I tried following expression to see to which extend the issues seem to be, and this is also failing with a similar error (although a lot longer stack trace included:

 "expression": "MyMetric * days"

I did try to do it with 2 variables, and that seems to work, for which I’m actually even more surprised after the previous error I mentioned. While this is indeed a possibility, it would be cleaner to have the calculations done as the 2 variables are really linked with that formula.

Since it seems to be unintended behavior, I have raised a ticket for this. As a reference for where it is happening, we are on version 7.8.10

@KrisBoyen you can also specify the type of your parameter by defining your bindings property as

bindings: { days: {type: “double”, value: 3} }