Ensure threshold is always printed as a decimal

If threshold is very large, for example, 21474836480, it would get
printed using scientific notation. If that expression was then used
to recreate the AlarmSubExpression, it would fail because the parser
didn't handle scientific notation.

So, instead use DecimalFormat to ensure a valid decimal number without
scientific notation. This then limits the threshold to 15 decimal
places, but that should be enough. It would be better to have no limit
but I have not been able to find a way to do that.

Change-Id: I0511bd73a0ab65498dd615d8f5049b5663720b6a
This commit is contained in:
Craig Bryant 2015-08-14 13:15:51 -06:00
parent de87b63c9b
commit d3354d10ef
2 changed files with 13 additions and 2 deletions

View File

@ -17,6 +17,7 @@
package monasca.common.model.alarm;
import java.io.Serializable;
import java.text.DecimalFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;
import org.antlr.v4.runtime.ANTLRInputStream;
@ -43,6 +44,9 @@ public class AlarmSubExpression implements Serializable {
private double threshold;
private int period;
private int periods;
// Use a DecimalFormatter for threshold because the standard double format starts using scientific notation when
// threshold is very large and that scientific notation can't be parsed when recreating the SubExpression
private static final DecimalFormat formatter = new DecimalFormat("0.0##############");
public AlarmSubExpression(AggregateFunction function, MetricDefinition metricDefinition,
AlarmOperator operator, double threshold, int period, int periods) {
@ -119,7 +123,7 @@ public class AlarmSubExpression implements Serializable {
sb.append(function).append('(').append(metricDefinition.toExpression());
if (period != 60)
sb.append(", ").append(period);
sb.append(") ").append(operator).append(' ').append(threshold);
sb.append(") ").append(operator).append(' ').append(formatter.format(threshold));
if (periods != 1)
sb.append(" times ").append(periods);
return sb.toString();

View File

@ -161,7 +161,14 @@ public class AlarmSubExpressionTest {
AlarmSubExpression.of("avg(hpcs.compute{metric_name=cpu, device=1}, 45) > 5 times 4")
.getExpression(), "avg(hpcs.compute{device=1, metric_name=cpu}, 45) > 5.0 times 4");
}
public void toStringAndBack() {
AlarmExpression expr = new AlarmExpression("elasticsearch.store.size>21474836480");
AlarmSubExpression subExpr1 = expr.getSubExpressions().get(0);
AlarmSubExpression subExpr2 = AlarmSubExpression.of(subExpr1.getExpression());
assertEquals(subExpr2, subExpr1);
}
public void shouldAllowDecimalThresholds() {
assertEquals(AlarmSubExpression.of("avg(hpcs.compute) > 2.375").getThreshold(), 2.375);
}