Skip to content

Commit

Permalink
HZN-751: Allow Measurements API queries in template/generic info pane…
Browse files Browse the repository at this point in the history
…l items
  • Loading branch information
Markus von Rüden committed May 10, 2016
1 parent 6a488d7 commit 18e1581
Show file tree
Hide file tree
Showing 9 changed files with 249 additions and 87 deletions.
Expand Up @@ -714,6 +714,8 @@ org.osgi.framework.system.packages.extra=org.apache.karaf.branding,\
org.opennms.netmgt.model.alarm;version=${opennms.osgi.version},\
org.opennms.netmgt.alarmd.api;version=${opennms.osgi.version},\
org.opennms.netmgt.alarmd.api.support;version=${opennms.osgi.version},\
org.opennms.netmgt.measurements.api;version=${opennms.osgi.version},\
org.opennms.netmgt.measurements.model;version=${opennms.osgi.version},\
org.opennms.netmgt.model.capsd;version=${opennms.osgi.version},\
org.opennms.netmgt.model.discovery;version=${opennms.osgi.version},\
org.opennms.netmgt.model.events;version=${opennms.osgi.version},\
Expand Down
@@ -0,0 +1,116 @@
/*******************************************************************************
* This file is part of OpenNMS(R).
* <p>
* Copyright (C) 2015 The OpenNMS Group, Inc.
* OpenNMS(R) is Copyright (C) 1999-2015 The OpenNMS Group, Inc.
* <p>
* OpenNMS(R) is a registered trademark of The OpenNMS Group, Inc.
* <p>
* OpenNMS(R) is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License,
* or (at your option) any later version.
* <p>
* OpenNMS(R) is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
* <p>
* You should have received a copy of the GNU Affero General Public License
* along with OpenNMS(R). If not, see:
* http://www.gnu.org/licenses/
* <p>
* For more information contact:
* OpenNMS(R) Licensing <license@opennms.org>
* http://www.opennms.org/
* http://www.opennms.com/
*******************************************************************************/

package org.opennms.netmgt.measurements.api;

import java.util.Map;

import org.opennms.netmgt.measurements.api.exceptions.FetchException;
import org.opennms.netmgt.measurements.api.exceptions.MeasurementException;
import org.opennms.netmgt.measurements.api.exceptions.ResourceNotFoundException;
import org.opennms.netmgt.measurements.api.exceptions.ValidationException;
import org.opennms.netmgt.measurements.model.QueryRequest;
import org.opennms.netmgt.measurements.model.QueryResponse;
import org.opennms.netmgt.measurements.model.Source;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.google.common.base.Preconditions;
import com.google.common.collect.RowSortedTable;

@Component("measurementsService")
public class DefaultMeasurementsService implements MeasurementsService {

private final MeasurementFetchStrategy fetchStrategy;
private final ExpressionEngine expressionEngine;
private final FilterEngine filterEngine;
private final QueryRequestValidator queryRequestValidator = new QueryRequestValidator();

@Autowired
public DefaultMeasurementsService(MeasurementFetchStrategy fetchStrategy, ExpressionEngine expressionEngine, FilterEngine filterEngine) {
this.fetchStrategy = Preconditions.checkNotNull(fetchStrategy);
this.expressionEngine = Preconditions.checkNotNull(expressionEngine);
this.filterEngine = Preconditions.checkNotNull(filterEngine);
}

@Override
public QueryResponse query(QueryRequest request) throws MeasurementException {
validate(request);

// Fetch the measurements
FetchResults results;
try {
results = fetchStrategy.fetch(
request.getStart(),
request.getEnd(),
request.getStep(),
request.getMaxRows(),
request.getHeartbeat(),
request.getInterval(),
request.getSources(),
request.isRelaxed());
} catch (Exception e) {
throw new FetchException(e, "Fetch failed: {}", e.getMessage());
}
if (results == null) {
throw new ResourceNotFoundException(request);
}

// Apply the expression to the fetch results
expressionEngine.applyExpressions(request, results);

// Apply the filters
if (!request.getFilters().isEmpty()) {
RowSortedTable<Long, String, Double> table = results.asRowSortedTable();
filterEngine.filter(request.getFilters(), table);
results = new FetchResults(table, results.getStep(), results.getConstants());
}

// Remove any transient values belonging to sources
final Map<String, double[]> columns = results.getColumns();
for (final Source source : request.getSources()) {
if (source.getTransient()) {
columns.remove(source.getLabel());
}
}

// Build the response
final QueryResponse response = new QueryResponse();
response.setStart(request.getStart());
response.setEnd(request.getEnd());
response.setStep(results.getStep());
response.setTimestamps(results.getTimestamps());
response.setColumns(results.getColumns());
response.setConstants(results.getConstants());
return response;
}

private void validate(QueryRequest request) throws ValidationException {
queryRequestValidator.validate(request);
}
}
@@ -1,8 +1,8 @@
/*******************************************************************************
* This file is part of OpenNMS(R).
* <p>
* Copyright (C) 2015 The OpenNMS Group, Inc.
* OpenNMS(R) is Copyright (C) 1999-2015 The OpenNMS Group, Inc.
* Copyright (C) 2016 The OpenNMS Group, Inc.
* OpenNMS(R) is Copyright (C) 1999-2016 The OpenNMS Group, Inc.
* <p>
* OpenNMS(R) is a registered trademark of The OpenNMS Group, Inc.
* <p>
Expand All @@ -28,88 +28,10 @@

package org.opennms.netmgt.measurements.api;

import java.util.Map;

import com.google.common.base.Preconditions;
import com.google.common.collect.RowSortedTable;

import org.opennms.netmgt.measurements.api.exceptions.FetchException;
import org.opennms.netmgt.measurements.api.exceptions.MeasurementException;
import org.opennms.netmgt.measurements.api.exceptions.ResourceNotFoundException;
import org.opennms.netmgt.measurements.api.exceptions.ValidationException;
import org.opennms.netmgt.measurements.model.QueryRequest;
import org.opennms.netmgt.measurements.model.QueryResponse;
import org.opennms.netmgt.measurements.model.Source;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component("measurementsService")
public class MeasurementsService {

private final MeasurementFetchStrategy fetchStrategy;
private final ExpressionEngine expressionEngine;
private final FilterEngine filterEngine;
private final QueryRequestValidator queryRequestValidator = new QueryRequestValidator();

@Autowired
public MeasurementsService(MeasurementFetchStrategy fetchStrategy, ExpressionEngine expressionEngine, FilterEngine filterEngine) {
this.fetchStrategy = Preconditions.checkNotNull(fetchStrategy);
this.expressionEngine = Preconditions.checkNotNull(expressionEngine);
this.filterEngine = Preconditions.checkNotNull(filterEngine);
}

public QueryResponse query(QueryRequest request) throws MeasurementException {
validate(request);

// Fetch the measurements
FetchResults results;
try {
results = fetchStrategy.fetch(
request.getStart(),
request.getEnd(),
request.getStep(),
request.getMaxRows(),
request.getHeartbeat(),
request.getInterval(),
request.getSources(),
request.isRelaxed());
} catch (Exception e) {
throw new FetchException(e, "Fetch failed: {}", e.getMessage());
}
if (results == null) {
throw new ResourceNotFoundException(request);
}

// Apply the expression to the fetch results
expressionEngine.applyExpressions(request, results);

// Apply the filters
if (!request.getFilters().isEmpty()) {
RowSortedTable<Long, String, Double> table = results.asRowSortedTable();
filterEngine.filter(request.getFilters(), table);
results = new FetchResults(table, results.getStep(), results.getConstants());
}

// Remove any transient values belonging to sources
final Map<String, double[]> columns = results.getColumns();
for (final Source source : request.getSources()) {
if (source.getTransient()) {
columns.remove(source.getLabel());
}
}

// Build the response
final QueryResponse response = new QueryResponse();
response.setStart(request.getStart());
response.setEnd(request.getEnd());
response.setStep(results.getStep());
response.setTimestamps(results.getTimestamps());
response.setColumns(results.getColumns());
response.setConstants(results.getConstants());
return response;
}

private void validate(QueryRequest request) throws ValidationException {
queryRequestValidator.validate(request);
}
public interface MeasurementsService {
QueryResponse query(QueryRequest request) throws MeasurementException;
}
Expand Up @@ -2,13 +2,28 @@
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:onmsgi="http://xmlns.opennms.org/xsd/spring/onms-osgi"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd">
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://xmlns.opennms.org/xsd/spring/onms-osgi
http://xmlns.opennms.org/xsd/spring/onms-osgi.xsd">

<context:annotation-config />
<context:component-scan base-package="org.opennms.netmgt.measurements"/>

<bean id="measurementFetchStrategyFactory" class="org.opennms.netmgt.measurements.api.MeasurementFetchStrategyFactory"/>
<bean id="filterEngine" class="org.opennms.netmgt.measurements.api.FilterEngine" />
<bean id="expressionEngine" class="org.opennms.netmgt.measurements.impl.JEXLExpressionEngine" />

<bean id="measurementsService" class="org.opennms.netmgt.measurements.api.DefaultMeasurementsService">
<constructor-arg ref="measurementFetchStrategy"/>
<constructor-arg ref="expressionEngine"/>
<constructor-arg ref="filterEngine"/>
</bean>

<onmsgi:service interface="org.opennms.netmgt.measurements.api.MeasurementsService" ref="measurementsService"/>

</beans>
Expand Up @@ -114,6 +114,12 @@
<artifactId>opennms-dao-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.opennms.features.measurements</groupId>
<artifactId>org.opennms.features.measurements.api</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.compendium</artifactId>
Expand Down
Expand Up @@ -53,6 +53,7 @@
import org.opennms.features.topology.api.topo.VertexRef;
import org.opennms.features.topology.plugins.topo.graphml.GraphMLVertex;
import org.opennms.netmgt.dao.api.NodeDao;
import org.opennms.netmgt.measurements.api.MeasurementsService;
import org.opennms.netmgt.model.OnmsNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand Down Expand Up @@ -90,9 +91,12 @@ private static <T> T withClassLoaderFix(final Supplier<T> supplier) {

private final Jinjava jinjava;

public GenericInfoPanelItemProvider(NodeDao nodeDao) throws InstantiationException, IllegalAccessException {
private final MeasurementsService measurementsService;

public GenericInfoPanelItemProvider(NodeDao nodeDao, MeasurementsService measurementsService) throws InstantiationException, IllegalAccessException {
this.jinjava = withClassLoaderFix(Jinjava::new);
this.nodeDao = Objects.requireNonNull(nodeDao);
this.measurementsService = Objects.requireNonNull(measurementsService);
}

private class TemplateItem implements InfoPanelItem {
Expand Down Expand Up @@ -235,8 +239,7 @@ private Map<String, Object> createContext(final GraphContainer container) {
.map(this::createVertexContext)
.ifPresent(context::putAll);

// TODO Measurements-API
// context.put("measurements", new MeasurementsWrapper(measurementsService));
context.put("measurements", new MeasurementsWrapper(measurementsService));

return context;
}
Expand Down
@@ -0,0 +1,95 @@
/*******************************************************************************
* This file is part of OpenNMS(R).
*
* Copyright (C) 2016 The OpenNMS Group, Inc.
* OpenNMS(R) is Copyright (C) 1999-2016 The OpenNMS Group, Inc.
*
* OpenNMS(R) is a registered trademark of The OpenNMS Group, Inc.
*
* OpenNMS(R) is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License,
* or (at your option) any later version.
*
* OpenNMS(R) is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with OpenNMS(R). If not, see:
* http://www.gnu.org/licenses/
*
* For more information contact:
* OpenNMS(R) Licensing <license@opennms.org>
* http://www.opennms.org/
* http://www.opennms.com/
*******************************************************************************/

package org.opennms.features.topology.plugins.topo.graphml.info;

import java.util.Collections;

import org.opennms.netmgt.measurements.api.MeasurementsService;
import org.opennms.netmgt.measurements.model.QueryRequest;
import org.opennms.netmgt.measurements.model.QueryResponse;
import org.opennms.netmgt.measurements.model.Source;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.base.Throwables;

public class MeasurementsWrapper {
private final static Logger LOG = LoggerFactory.getLogger(GenericInfoPanelItemProvider.class);

private final MeasurementsService measurementsService;

public MeasurementsWrapper(MeasurementsService measurementsService) {
this.measurementsService=measurementsService;
}

public double getLastValue(final String resource, final String attribute) {
QueryResponse.WrappedPrimitive[] columns = query(resource, attribute).getColumns();
LOG.debug("MEASUREMENTS: Received {} columns", columns.length);
if (columns.length > 0) {
double[] values = columns[0].getList();
LOG.debug("MEASUREMENTS: First columns has {} entries", values.length);
if (values.length > 0) {
for(int i = values.length-1; i >= 0; i--) {
LOG.warn("MEASUREMENTS: Entry[{}] = {}", i, values[i]);
if (!Double.isNaN(values[i])) {
return values[i];
}
}
}
}
return Double.NaN;
}

private QueryResponse query(final String resource, final String attribute) {
long end = System.currentTimeMillis();
long start = end - (30 * 60 * 1000); // 30 Minutes

QueryRequest request = new QueryRequest();
request.setRelaxed(true);
request.setStart(start);
request.setEnd(end);
request.setStep(300000);

Source source = new Source();
source.setAggregation("AVERAGE");
source.setTransient(false);
source.setAttribute(attribute);
source.setResourceId(resource);
source.setLabel(attribute);

request.setSources(Collections.singletonList(source));

try {
return measurementsService.query(request);
} catch (Exception ex) {
// TODO error handling
throw Throwables.propagate(ex);
}
}
}

0 comments on commit 18e1581

Please sign in to comment.