use of org.opennms.netmgt.measurements.model.Expression in project opennms by OpenNMS.
the class JEXLExpressionEngine method applyExpressions.
/**
* {@inheritDoc}
*/
@Override
public void applyExpressions(final QueryRequest request, final FetchResults results) throws ExpressionException {
Preconditions.checkNotNull(request, "request argument");
Preconditions.checkNotNull(results, "results argument");
final int numExpressions = request.getExpressions().size();
// Don't do anything if there are no expressions
if (numExpressions < 1) {
return;
}
// Use to keep track of transient expression so that we don't
// allocate memory to store their results
int numNonTransientExpression = 0;
boolean[] transientFlags = new boolean[numExpressions];
// Compile the expressions
int j, k = 0;
final LinkedHashMap<String, org.apache.commons.jexl2.Expression> expressions = Maps.newLinkedHashMap();
for (final Expression e : request.getExpressions()) {
// Populate the transientFlags array
transientFlags[k] = e.getTransient();
if (!transientFlags[k]) {
numNonTransientExpression++;
}
k++;
try {
expressions.put(e.getLabel(), jexl.createExpression(e.getExpression()));
} catch (JexlException ex) {
throw new ExpressionException(ex, "Failed to parse expression label '{}'.", e.getLabel());
}
}
// Prepare the JEXL context
final Map<String, Object> jexlValues = Maps.newHashMap();
final JexlContext context = new MapContext(jexlValues);
// Add constants (i.e. values from strings.properties) retrieved by the fetch operation
jexlValues.putAll(results.getConstants());
LOG.debug("JEXL context constants: {}", jexlValues);
// Add some additional constants for ease of use
jexlValues.put("__inf", Double.POSITIVE_INFINITY);
jexlValues.put("__neg_inf", Double.NEGATIVE_INFINITY);
jexlValues.put("NaN", Double.NaN);
final long[] timestamps = results.getTimestamps();
final Map<String, double[]> columns = results.getColumns();
final int numRows = timestamps.length;
// Calculate the time span
jexlValues.put("__diff_time", numRows < 1 ? 0d : timestamps[numRows - 1] - timestamps[0]);
final double[][] expressionValues = new double[numNonTransientExpression][numRows];
// Iterate through all of the rows, apply the expressions
for (int i = 0; i < numRows; i++) {
// Evaluate every expression, in the same order as which they appeared in the query
j = k = 0;
for (final Map.Entry<String, org.apache.commons.jexl2.Expression> expressionEntry : expressions.entrySet()) {
// Update the timestamp
jexlValues.put("timestamp", timestamps[i]);
// overwriting values from the last loop
for (final String sourceLabel : columns.keySet()) {
jexlValues.put(sourceLabel, columns.get(sourceLabel)[i]);
}
// Evaluate the expression
try {
Object derived = expressionEntry.getValue().evaluate(context);
double derivedAsDouble = Utils.toDouble(derived);
// Only store the values for non-transient expressions
if (!transientFlags[j++]) {
expressionValues[k++][i] = derivedAsDouble;
}
// Store the result back in the context, so that it can be referenced
// by subsequent expression in the row
jexlValues.put(expressionEntry.getKey(), derivedAsDouble);
} catch (NullPointerException | NumberFormatException e) {
throw new ExpressionException(e, "The return value from expression with label '" + expressionEntry.getKey() + "' could not be cast to a Double.");
} catch (JexlException e) {
throw new ExpressionException(e, "Failed to evaluate expression with label '" + expressionEntry.getKey() + "'.");
}
}
}
// Store the results
j = k = 0;
for (final String expressionLabel : expressions.keySet()) {
if (!transientFlags[j++]) {
columns.put(expressionLabel, expressionValues[k++]);
}
}
}
use of org.opennms.netmgt.measurements.model.Expression in project opennms by OpenNMS.
the class MeasurementsWrapper method computeUtilization.
/**
* This method computes the utilization of a given interface resource. The method returns two double values
* encapsulated in a list. It uses the HC attributes for the computation and non-HC as fallback attributes.
*
* @param resource the resource for which the utilization must be computed
* @param start the start timestamp
* @param end the end timestamp
* @param step the step size
* @param aggregation the aggregation function
* @return a list containing two double values for the in/out percentage utilization
*/
public List<Double> computeUtilization(final String resource, final long start, final long end, final long step, final String aggregation) throws MeasurementException {
QueryRequest request = new QueryRequest();
request.setRelaxed(true);
request.setStart(start);
request.setEnd(end);
request.setStep(step);
Source sourceIn = new Source();
sourceIn.setAggregation(aggregation);
sourceIn.setTransient(true);
sourceIn.setAttribute("ifHCInOctets");
// using non-HC attributes as fallback
sourceIn.setFallbackAttribute("ifInOctets");
sourceIn.setResourceId(resource);
sourceIn.setLabel("ifInOctets");
Source sourceOut = new Source();
sourceOut.setAggregation(aggregation);
sourceOut.setTransient(true);
sourceOut.setAttribute("ifHCOutOctets");
// using non-HC attributes as fallback
sourceOut.setFallbackAttribute("ifOutOctets");
sourceOut.setResourceId(resource);
sourceOut.setLabel("ifOutOctets");
request.setExpressions(Arrays.asList(new Expression("ifInPercent", "(8 * ifInOctects / 1000000) / ifInOctets.ifHighSpeed * 100", false), new Expression("ifOutPercent", "(8 * ifOutOctects / 1000000) / ifOutOctets.ifHighSpeed * 100", false)));
request.setSources(Arrays.asList(sourceIn, sourceOut));
QueryResponse.WrappedPrimitive[] columns = measurementsService.query(request).getColumns();
double[] values1 = columns[0].getList();
double[] values2 = columns[1].getList();
for (int i = values1.length - 1; i >= 0; i--) {
if (!Double.isNaN(values1[i]) && !Double.isNaN(values2[i])) {
return Arrays.asList(values1[i], values2[i]);
}
}
return Arrays.asList(Double.NaN, Double.NaN);
}
use of org.opennms.netmgt.measurements.model.Expression in project opennms by OpenNMS.
the class MeasurementsRestServiceWithJrbIT method canPerformExpressions.
@Test
public void canPerformExpressions() {
QueryRequest request = new QueryRequest();
request.setStart(1414602000000L);
request.setEnd(1417046400000L);
request.setStep(1000L);
request.setMaxRows(700);
Source ifInOctets = new Source();
ifInOctets.setResourceId("node[1].interfaceSnmp[eth0-04013f75f101]");
ifInOctets.setAttribute("ifInOctets");
ifInOctets.setAggregation("MAX");
ifInOctets.setLabel("ifInOctets");
request.setSources(Lists.newArrayList(ifInOctets));
Expression scale = new Expression();
scale.setLabel("ifUsage");
// References a variable from strings.properties
scale.setExpression("ifInOctets * 8 / ifInOctets.ifSpeed");
request.setExpressions(Lists.newArrayList(scale));
QueryResponse response = m_svc.query(request);
final int idx = 3;
final Map<String, double[]> columns = response.columnsWithLabels();
assertEquals(975.3053156146178, columns.get("ifInOctets")[idx], 0.0001);
assertEquals(975.3053156146178 * 8d / 1000.0d, columns.get("ifUsage")[idx], 0.0001);
}
use of org.opennms.netmgt.measurements.model.Expression in project opennms by OpenNMS.
the class JEXLExpressionEngineTest method performExpression.
private double[] performExpression(String expression, Map<String, Object> constants) throws ExpressionException {
// Build a simple request with the given expression
QueryRequest request = new QueryRequest();
Source constant = new Source();
constant.setLabel("x");
request.setSources(Lists.newArrayList(constant));
Expression exp = new Expression();
exp.setLabel("y");
exp.setExpression(expression);
request.setExpressions(Lists.newArrayList(exp));
// Build the fetch results with known values
final int N = 100;
long[] timestamps = new long[N];
double[] xValues = new double[N];
for (int i = 0; i < N; i++) {
timestamps[i] = i * 1000;
xValues[i] = Double.valueOf(i);
}
Map<String, double[]> values = Maps.newHashMap();
values.put("x", xValues);
FetchResults results = new FetchResults(timestamps, values, 1, constants);
// Use the engine to evaluate the expression
jexlExpressionEngine.applyExpressions(request, results);
// Retrieve the results
return results.getColumns().get("y");
}
use of org.opennms.netmgt.measurements.model.Expression in project opennms by OpenNMS.
the class QueryRequestValidator method validate.
public void validate(QueryRequest request) throws ValidationException {
if (request.getEnd() < 0) {
throw new ValidationException("Query end must be >= 0: {}", request.getEnd());
}
if (request.getStep() <= 0) {
throw new ValidationException("Query step must be > 0: {}", request.getStep());
}
if ((request.getHeartbeat() == null && request.getInterval() != null) || (request.getHeartbeat() != null && request.getInterval() == null)) {
throw new ValidationException("If either the heartbeat or the interval are set, then both must be set.");
}
if (request.getHeartbeat() != null && request.getInterval() != null) {
if (request.getHeartbeat() <= 0) {
throw new ValidationException("Heartbeat must be positive: {}", request.getHeartbeat());
}
if (request.getInterval() <= 0) {
throw new ValidationException("Interval must be positive: {}", request.getInterval());
}
if (request.getStep() % request.getInterval() != 0) {
throw new ValidationException("Step must be a multiple of the interval. Step: {}, Interval: {}", request.getStep(), request.getInterval());
}
if (request.getHeartbeat() % request.getInterval() != 0) {
throw new ValidationException("Heartbeat must be a multiple of the interval. Interval: {} Heartbeat: {}", request.getInterval(), request.getHeartbeat());
}
}
final Map<String, String> labels = new HashMap<>();
for (final Source source : request.getSources()) {
if (source.getResourceId() == null || source.getAttribute() == null || source.getLabel() == null || source.getAggregation() == null) {
throw new ValidationException("Query source fields must be set: {}", source);
}
if (labels.containsKey(source.getLabel())) {
throw new ValidationException("Query source label '{}' conflict: source with that label is already defined.", source.getLabel());
} else {
labels.put(source.getLabel(), "source");
}
}
for (final Expression expression : request.getExpressions()) {
if (expression.getExpression() == null || expression.getLabel() == null) {
throw new ValidationException("Query expression fields must be set: {}", expression);
}
if (labels.containsKey(expression.getLabel())) {
final String type = labels.get(expression.getLabel());
throw new ValidationException("Query expression label '{}' conflict: {} with that label is already defined.", expression.getLabel(), type);
} else {
labels.put(expression.getLabel(), "expression");
}
}
List<FilterDef> filters = request.getFilters();
if (filters.size() > 0) {
for (FilterDef filter : filters) {
if (filter.getName() == null) {
throw new ValidationException("Filter name must be set: {}", filter);
}
}
}
}
Aggregations