Permalink
Browse files

Updated MetricDataApi to get metrics data summary for a resource or g…

…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...
1 parent 988fcbe commit 70e361c77af1219129282b7db9c0fc349840eb19 pnguyen committed Apr 26, 2010
View
5 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.
View
60 hqu/hqapi1/app/MetricdataController.groovy
@@ -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
@@ -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
View
54 src/org/hyperic/hq/hqapi1/MetricDataApi.java
@@ -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;
@@ -136,6 +139,57 @@ public LastMetricsDataResponse getData(List<Metric> metrics)
}
/**
+ * 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.
*
View
119 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);
+ }
+
+ }
+}
View
4 src/org/hyperic/hq/hqapi1/test/MetricDataGet_test.java
@@ -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);
}
}
View
28 xsd/HQApi1.xsd
@@ -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">
@@ -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">

0 comments on commit 70e361c

Please sign in to comment.