Skip to content

Commit

Permalink
Updated MetricDataApi to get metrics data summary for a resource or g…
Browse files Browse the repository at this point in the history
…roup within a specified time range. Functionality added primarily to do integration testing for HHQ-3803 and HHQ-3748. No corresponding CLI command was added.
  • Loading branch information
pnguyen committed Apr 26, 2010
1 parent 988fcbe commit 70e361c
Show file tree
Hide file tree
Showing 6 changed files with 268 additions and 2 deletions.
5 changes: 5 additions & 0 deletions ChangeLog
@@ -1,6 +1,11 @@

Changes in HQApi 3.2

*) Updated MetricDataApi to get metrics data summary for a resource
or group within a specified time range. Functionality added primarily
to do integration testing for HHQ-3803 and HHQ-3748. No
corresponding CLI command was added.

*) Add support to sync alert definitions with SNMP actions.
Functionality added primarily to do integration testing
for HQ-2047.
Expand Down
60 changes: 60 additions & 0 deletions hqu/hqapi1/app/MetricdataController.groovy
Expand Up @@ -36,6 +36,23 @@ class MetricdataController extends ApiController {
}
}

private Closure getMetricDataSummaryXML(resource, metricCategory, summary) {
{ doc ->
MetricDataSummary(resourceId: resource.id,
resourceName: resource.name,
metricTemplateId: summary.templateId,
metricName: summary.label,
units: summary.units,
category: metricCategory,
startTime: summary.beginTimeFrame,
endTime: summary.endTimeFrame,
minMetric: summary.minMetric.value,
maxMetric: summary.maxMetric.value,
avgMetric: summary.avgMetric.value,
lastMetric: summary.lastMetric.value)
}
}

/**
* Validate metric parameters, returning a Closure representing the error
* or null if the parameters are valid
Expand Down Expand Up @@ -218,6 +235,49 @@ class MetricdataController extends ApiController {
}
}

def getSummary(params) {
def failureXml
def summary
def resource
def resourceId = params.getOne("resourceId")?.toInteger()
def start = params.getOne("start")?.toLong()
def end = params.getOne("end")?.toLong()

if (!resourceId) {
failureXml = getFailureXML(ErrorCode.INVALID_PARAMETERS,
"Resource id not given")
} else {
resource = getResource(resourceId)
if (!resource) {
failureXml = getFailureXML(ErrorCode.OBJECT_NOT_FOUND,
"Unable to find resource id=" + resourceId)
} else {
try {
summary = resource.getMetricsSummary(user, start, end)
} catch (Exception e) {
log.error("UnexpectedError: " + e.getMessage(), e)
failureXml = getFailureXML(ErrorCode.UNEXPECTED_ERROR)
}
}
}

renderXml() {
MetricsDataSummaryResponse() {
if (failureXml) {
out << failureXml
} else {
out << getSuccessXML()

summary.each {category, results ->
results.each {item ->
out << getMetricDataSummaryXML(resource, category, item)
}
}
}
}
}
}

def put(params) {
def inserter = null
def failureXml = null
Expand Down
54 changes: 54 additions & 0 deletions src/org/hyperic/hq/hqapi1/MetricDataApi.java
Expand Up @@ -8,7 +8,10 @@
import org.hyperic.hq.hqapi1.types.LastMetricsDataResponse;
import org.hyperic.hq.hqapi1.types.LastMetricDataResponse;
import org.hyperic.hq.hqapi1.types.MetricsDataResponse;
import org.hyperic.hq.hqapi1.types.MetricsDataSummaryResponse;
import org.hyperic.hq.hqapi1.types.Group;
import org.hyperic.hq.hqapi1.types.Metric;
import org.hyperic.hq.hqapi1.types.Resource;

import java.io.IOException;
import java.util.List;
Expand Down Expand Up @@ -135,6 +138,57 @@ public LastMetricsDataResponse getData(List<Metric> metrics)
new XmlResponseHandler<LastMetricsDataResponse>(LastMetricsDataResponse.class));
}

/**
* Get the {@link org.hyperic.hq.hqapi1.types.MetricsDataSummary} for the
* given {@link org.hyperic.hq.hqapi1.types.Resource}.
*
* @param resource The {@link org.hyperic.hq.hqapi1.types.Resource}.
* @param start The start time to query, in epoch-millis.
* @param end The end time to query, in epoch-millis.
*
* @return {@link org.hyperic.hq.hqapi1.types.MetricDataSummaryResponse#SUCCESS}
* if the data was succesfully queried. The returned data can be retrieved
* via {@link org.hyperic.hq.hqapi1.types.MetricDataSummaryResponse#getMetricDataSummary()}.
*
* @throws IOException If a network error occurs while making the request.
*/
public MetricsDataSummaryResponse getSummary(Resource resource, long start, long end)
throws IOException
{
return getSummary(resource.getId(), start, end);
}

/**
* Get the {@link org.hyperic.hq.hqapi1.types.MetricsDataSummary} for the
* given {@link org.hyperic.hq.hqapi1.types.Group}.
*
* @param group The {@link org.hyperic.hq.hqapi1.types.Group}.
* @param start The start time to query, in epoch-millis.
* @param end The end time to query, in epoch-millis.
*
* @return {@link org.hyperic.hq.hqapi1.types.MetricDataSummaryResponse#SUCCESS}
* if the data was succesfully queried. The returned data can be retrieved
* via {@link org.hyperic.hq.hqapi1.types.MetricDataSummaryResponse#getMetricDataSummary()}.
*
* @throws IOException If a network error occurs while making the request.
*/
public MetricsDataSummaryResponse getSummary(Group group, long start, long end)
throws IOException
{
return getSummary(group.getResourceId(), start, end);
}

private MetricsDataSummaryResponse getSummary(Integer resourceId, long start, long end)
throws IOException
{
Map<String, String[]> params = new HashMap<String, String[]>();
params.put("resourceId", new String[] { resourceId.toString() });
params.put("start", new String[] { Long.toString(start)});
params.put("end", new String[] { Long.toString(end)});
return doGet("metricData/getSummary.hqu", params,
new XmlResponseHandler<MetricsDataSummaryResponse>(MetricsDataSummaryResponse.class));
}

/**
* Insert {@link org.hyperic.hq.hqapi1.types.DataPoint}s for the specified
* Metric.
Expand Down
119 changes: 119 additions & 0 deletions src/org/hyperic/hq/hqapi1/test/MetricDataGetSummary_test.java
@@ -0,0 +1,119 @@
package org.hyperic.hq.hqapi1.test;

import org.hyperic.hq.hqapi1.MetricDataApi;
import org.hyperic.hq.hqapi1.ResourceApi;
import org.hyperic.hq.hqapi1.types.Group;
import org.hyperic.hq.hqapi1.types.Resource;
import org.hyperic.hq.hqapi1.types.MetricDataResponse;
import org.hyperic.hq.hqapi1.types.MetricDataSummary;
import org.hyperic.hq.hqapi1.types.MetricsDataSummaryResponse;
import org.hyperic.hq.hqapi1.types.ResourcePrototype;
import org.hyperic.hq.hqapi1.types.ResourcePrototypeResponse;
import org.hyperic.hq.hqapi1.types.ResourcesResponse;

public class MetricDataGetSummary_test extends MetricDataTestBase {

public MetricDataGetSummary_test(String name) {
super(name);
}

public void testResourceSummary() throws Exception {
ResourceApi resourceApi = getApi().getResourceApi();
MetricDataApi metricDataApi = getApi().getMetricDataApi();

// Find CPU resources
ResourcePrototypeResponse cpuPrototypeResponse =
resourceApi.getResourcePrototype("CPU");
hqAssertSuccess(cpuPrototypeResponse);

ResourcePrototype cpuPrototype = cpuPrototypeResponse.getResourcePrototype();
ResourcesResponse resourceResponse =
resourceApi.getResources(cpuPrototype,
false, false);
hqAssertSuccess(resourceResponse);
assertFalse(resourceResponse.getResource().isEmpty());

Resource cpu = resourceResponse.getResource().get(0);

// Keep the metric data range small to validate HHQ-3803
long end = System.currentTimeMillis();
long start = end - (30 * 60 * 1000);

MetricsDataSummaryResponse summaryResponse =
metricDataApi.getSummary(cpu, start, end);
hqAssertSuccess(summaryResponse);

for (MetricDataSummary s : summaryResponse.getMetricDataSummary()) {
validateMetricDataSummary(s);
}
}

public void testGroupSummary() throws Exception {
ResourceApi resourceApi = getApi().getResourceApi();
MetricDataApi metricDataApi = getApi().getMetricDataApi();

// Find CPU resources
ResourcePrototypeResponse cpuPrototypeResponse =
resourceApi.getResourcePrototype("CPU");
hqAssertSuccess(cpuPrototypeResponse);

ResourcePrototype cpuPrototype = cpuPrototypeResponse.getResourcePrototype();
ResourcesResponse resourceResponse =
resourceApi.getResources(cpuPrototype,
false, false);
hqAssertSuccess(resourceResponse);
assertFalse(resourceResponse.getResource().isEmpty());

// Create CPU group
Group group = createGroup(resourceResponse.getResource());

long end = System.currentTimeMillis();
long start = end - (30 * 60 * 1000);

MetricsDataSummaryResponse summaryResponse =
metricDataApi.getSummary(group, start, end);
hqAssertSuccess(summaryResponse);

for (MetricDataSummary s : summaryResponse.getMetricDataSummary()) {
validateMetricDataSummary(s);
}

cleanupGroup(group);
}

//TODO public void testGetInvalidResourceId() throws Exception {}

//TODO public void testGetInvalidRange() throws Exception {}

private void validateMetricDataSummary(MetricDataSummary s) {

assertTrue(s.getMetricName() + ": Average value (" + s.getAvgMetric()
+ ") must be greater than or equal to the minimum value ("
+ s.getMinMetric() + ")",
s.getAvgMetric().compareTo(s.getMinMetric()) >=0);

assertTrue(s.getMetricName() + ": Average value (" + s.getAvgMetric()
+ ") must be less than or equal to the maximum value ("
+ s.getMaxMetric() + ")",
s.getAvgMetric().compareTo(s.getMaxMetric()) <=0);

if ("percentage".equals(s.getUnits())) {
assertTrue("The minimum value (" + s.getMinMetric()
+ ") for percentage metrics must be less than or equal to 1",
s.getMinMetric() <= 1);

assertTrue("The average value (" + s.getAvgMetric()
+ ") for percentage metrics must be less than or equal to 1",
s.getAvgMetric() <= 1);

assertTrue("The maximum value (" + s.getMaxMetric()
+ ") for percentage metrics must be less than or equal to 1",
s.getMaxMetric() <= 1);

assertTrue("The last or sum value (" + s.getLastMetric()
+ ") for percentage metrics must be less than or equal to 1",
s.getLastMetric() <= 1);
}

}
}
4 changes: 2 additions & 2 deletions src/org/hyperic/hq/hqapi1/test/MetricDataGet_test.java
Expand Up @@ -62,7 +62,7 @@ public void testGetInvalidRange() throws Exception {

long end = System.currentTimeMillis();
long start = end - (8 * 60 * 60 * 1000);
MetricDataResponse dataResponse = dataApi.getData(m, start, end);
hqAssertSuccess(dataResponse);
MetricDataResponse dataResponse = dataApi.getData(m, end, start);
hqAssertFailureInvalidParameters(dataResponse);
}
}
28 changes: 28 additions & 0 deletions xsd/HQApi1.xsd
Expand Up @@ -455,6 +455,21 @@
<xs:attribute name="metricName" type="xs:string" use="required"/>
</xs:complexType>

<xs:complexType name="MetricDataSummary">
<xs:attribute name="lastMetric" type="xs:double" use="optional"/>
<xs:attribute name="avgMetric" type="xs:double" use="optional"/>
<xs:attribute name="maxMetric" type="xs:double" use="optional"/>
<xs:attribute name="minMetric" type="xs:double" use="optional"/>
<xs:attribute name="endTime" type="xs:long" use="required"/>
<xs:attribute name="startTime" type="xs:long" use="required"/>
<xs:attribute name="category" type="xs:string" use="required"/>
<xs:attribute name="units" type="xs:string" use="required"/>
<xs:attribute name="resourceId" type="xs:int" use="required"/>
<xs:attribute name="resourceName" type="xs:string" use="required"/>
<xs:attribute name="metricName" type="xs:string" use="required"/>
<xs:attribute name="metricTemplateId" type="xs:int" use="required"/>
</xs:complexType>

<!-- Metric Responses -->

<xs:element name="MetricResponse">
Expand Down Expand Up @@ -539,6 +554,19 @@
</xs:complexType>
</xs:element>


<xs:element name="MetricsDataSummaryResponse">
<xs:complexType>
<xs:complexContent>
<xs:extension base="Response">
<xs:sequence>
<xs:element name="MetricDataSummary" type="MetricDataSummary" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:element>

<!-- MetricData Requests -->

<xs:element name="DataPointsRequest">
Expand Down

0 comments on commit 70e361c

Please sign in to comment.