package org.rhq.server.metrics.invalid;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
import java.util.List;
import org.joda.time.DateTime;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import org.rhq.cassandra.schema.Table;
import org.rhq.server.metrics.CassandraIntegrationTest;
import org.rhq.server.metrics.DateTimeService;
import org.rhq.server.metrics.MetricsConfiguration;
import org.rhq.server.metrics.MetricsDAO;
import org.rhq.server.metrics.domain.AggregateNumericMetric;
import org.rhq.server.metrics.domain.Bucket;
/**
* @author John Sanda
*/
public class InvalidMetricsManagerTest extends CassandraIntegrationTest {
private MetricsDAO dao;
private DateTimeService dateTimeService;
private InvalidMetricsManager invalidMetricsManager;
@BeforeClass
public void initClass() {
MetricsConfiguration configuration = new MetricsConfiguration();
dateTimeService = new DateTimeService();
dateTimeService.setConfiguration(configuration);
dao = new MetricsDAO(storageSession, configuration);
}
@BeforeMethod
public void initMethod() {
invalidMetricsManager = new InvalidMetricsManager(dateTimeService, dao, 1, 1);
invalidMetricsManager.setDelay(1000);
purgeDB();
}
@AfterMethod
public void shutdown() {
invalidMetricsManager.shutdown();
}
private void purgeDB() {
for (Table table : Table.values()) {
session.execute("TRUNCATE " + table.getTableName());
}
}
/**
* This test exercises a scenario in which we wind up with both invalid 24 hour and 6
* hour metrics. This happens due to the empty 1 hour metric from the 14:00 hour. See
* https://bugzilla.redhat.com/show_bug.cgi?id=1117396 for details on how we could end
* up with an empty aggregate metric.
*/
@Test
public void submitInvalid24HourAnd6HourMetricsWithEmpty1HourMetric() throws Exception {
int scheduleId = 100;
dao.insert1HourData(new1HourAggregate(scheduleId, hour(0).minusDays(7).plusHours(12), 100, 100, 100)).get();
dao.insert1HourData(new1HourAggregate(scheduleId, hour(0).minusDays(7).plusHours(13), 100, 100, 100)).get();
dao.insert1HourData(new1HourAggregate(scheduleId, hour(0).minusDays(7).plusHours(14), Double.NaN, Double.NaN,
0.0)).get();
dao.insert1HourData(new1HourAggregate(scheduleId, hour(0).minusDays(7).plusHours(15), 100, 100, 100)).get();
dao.insert1HourData(new1HourAggregate(scheduleId, hour(0).minusDays(7).plusHours(16), 100, 100, 100)).get();
dao.insert1HourData(new1HourAggregate(scheduleId, hour(0).minusDays(7).plusHours(17), 100, 100, 100)).get();
dao.insert6HourData(new6HourAggregate(scheduleId, hour(0).minusDays(7), 100, 100, 100)).get();
dao.insert6HourData(new6HourAggregate(scheduleId, hour(0).minusDays(7).plusHours(6), 100, 100, 100)).get();
dao.insert6HourData(new6HourAggregate(scheduleId, hour(0).minusDays(7).plusHours(12), 83.33, 100, 100)).get();
dao.insert6HourData(new6HourAggregate(scheduleId, hour(0).minusDays(7).plusHours(18), 100, 100, 100)).get();
dao.insert24HourData(new24HourAggregate(scheduleId, hour(0).minusDays(7), 95.83, 100, 100)).get();
invalidMetricsManager.submit(new24HourAggregate(scheduleId, hour(0).minusDays(7), 83.33, 100.0, 100.0));
waitForInvalidMetricsToBeProcessed();
List<AggregateNumericMetric> updated1HourMetrics = dao.findAggregateMetrics(scheduleId, Bucket.ONE_HOUR,
hour(0).minusDays(7).plusHours(14).getMillis(), hour(0).minusDays(7).plusHours(14).getMillis());
assertTrue(updated1HourMetrics.isEmpty(), "Expected 1 hour metric to be deleted since it was empty");
List<AggregateNumericMetric> updated6HourMetrics = dao.findAggregateMetrics(scheduleId, Bucket.SIX_HOUR,
hour(0).minusDays(7).plusHours(12).getMillis(), hour(0).minusDays(7).plusHours(18).getMillis());
assertEquals(updated6HourMetrics.size(), 1, "Expected to find one 6 hour metric");
AggregateNumericMetric actual6HourMetric = updated6HourMetrics.get(0);
AggregateNumericMetric expected6HourMetric = new6HourAggregate(scheduleId, hour(0).minusDays(7).plusHours(12),
100.0, 100.0, 100.0);
assertEquals(actual6HourMetric, expected6HourMetric,
"The updated 6 hour metric does not match the expected value");
List<AggregateNumericMetric> updated24HourMetrics = dao.findAggregateMetrics(scheduleId,
Bucket.TWENTY_FOUR_HOUR, hour(0).minusDays(7).getMillis(), hour0().minusDays(6).getMillis());
assertEquals(updated24HourMetrics.size(), 1, "Expected to find one 24 hour metric");
AggregateNumericMetric actual24HourMetric = updated24HourMetrics.get(0);
AggregateNumericMetric expected24HourMetric = new24HourAggregate(scheduleId, hour(0).minusDays(7), 100.0,
100.0, 100.0);
assertEquals(actual24HourMetric, expected24HourMetric,
"The updated 24 hour metric does not match the expected value");
}
/**
* This test exercises a scenario in which we have both invalid 6 hour and 24 hour
* metrics, and the 1 hour metrics have already expired. Since those 1 hour metrics are
* gone, we should delete the 6 hour metric.
*/
@Test
public void submitInvalid6HourAnd24HourMetricsWhen1HourMetricsExpired() throws Exception {
int scheduleId = 100;
dao.insert6HourData(new6HourAggregate(scheduleId, hour(0).minusDays(7), 100, 100, 100)).get();
dao.insert6HourData(new6HourAggregate(scheduleId, hour(0).minusDays(7).plusHours(6), 100, 100, 100)).get();
dao.insert6HourData(new6HourAggregate(scheduleId, hour(0).minusDays(7).plusHours(12), 83.33, 100, 100)).get();
dao.insert6HourData(new6HourAggregate(scheduleId, hour(0).minusDays(7).plusHours(18), 100, 100, 100)).get();
dao.insert24HourData(new24HourAggregate(scheduleId, hour(0).minusDays(7), 95.83, 100, 100)).get();
invalidMetricsManager.submit(new6HourAggregate(scheduleId, hour(0).minusDays(7), 83.33, 100.0, 100.0));
waitForInvalidMetricsToBeProcessed();
List<AggregateNumericMetric> updated6HourMetrics = dao.findAggregateMetrics(scheduleId, Bucket.SIX_HOUR,
hour(0).minusDays(7).plusHours(12).getMillis(), hour(0).minusDays(7).plusHours(18).getMillis());
assertTrue(updated6HourMetrics.isEmpty(), "Did not expect to find a 6 hour metric since its 1 hour metrics " +
"are no longer available");
List<AggregateNumericMetric> updated24HourMetrics = dao.findAggregateMetrics(scheduleId,
Bucket.TWENTY_FOUR_HOUR, hour(0).minusDays(7).getMillis(), hour0().minusDays(6).getMillis());
assertEquals(updated24HourMetrics.size(), 1, "Expected to find one 24 hour metric");
AggregateNumericMetric actual24HourMetric = updated24HourMetrics.get(0);
AggregateNumericMetric expected24HourMetric = new24HourAggregate(scheduleId, hour(0).minusDays(7), 100, 100,
100);
assertEquals(actual24HourMetric, expected24HourMetric,
"The updated 24 hour metric does not match the expected value");
}
/**
* This text exercises a scenario in which we have an invalid 24 hour metric, and the 6
* hour metrics have already expired.
*/
@Test
public void submitInvalid24HourMetricWhen6HourMetricsExpired() throws Exception {
int scheduleId = 100;
dao.insert24HourData(new24HourAggregate(scheduleId, hour(0).minusDays(7), 95.83, 100, 100)).get();
invalidMetricsManager.submit(new24HourAggregate(scheduleId, hour(0).minusDays(7), 83.33, 100.0, 100.0));
waitForInvalidMetricsToBeProcessed();
List<AggregateNumericMetric> updated24HourMetrics = dao.findAggregateMetrics(scheduleId,
Bucket.TWENTY_FOUR_HOUR, hour(0).minusDays(7).getMillis(), hour0().minusDays(6).getMillis());
assertTrue(updated24HourMetrics.isEmpty(), "Did not expect to find 24 hour metric since 6 hour metrics are " +
"not available");
}
@Test
public void addMultipleMetricsFromSameDayToQueue() throws Exception {
int scheduleId = 100;
invalidMetricsManager.setDelay(30000);
invalidMetricsManager.submit(new6HourAggregate(scheduleId, hour(6), 83.33, 100.0, 100.0));
invalidMetricsManager.submit(new6HourAggregate(scheduleId, hour(12), 83.33, 100.0, 100.0));
invalidMetricsManager.submit(new24HourAggregate(scheduleId, hour(0), 83.33, 100.0, 100.0));
assertEquals(invalidMetricsManager.getRemainingInvalidMetrics(), 1, "Expected there to be 1 invalid metric " +
"in the queue since one element is stored for metrics falling within the same day.");
invalidMetricsManager.submit(new6HourAggregate(scheduleId, hour(0).minusDays(1).plusHours(6), 83.33, 100.0,
100.0));
assertEquals(invalidMetricsManager.getRemainingInvalidMetrics(), 2, "Expected there to be 2 invalid metrics " +
"in the queue");
}
private void waitForInvalidMetricsToBeProcessed() throws InterruptedException {
while (invalidMetricsManager.getRemainingInvalidMetrics() > 0) {
Thread.sleep(1000);
}
}
private AggregateNumericMetric new1HourAggregate(int scheduleId, DateTime time, double avg, double min,
double max) {
return new AggregateNumericMetric(scheduleId, Bucket.ONE_HOUR, avg, min, max, time.getMillis());
}
private AggregateNumericMetric new6HourAggregate(int scheduleId, DateTime time, double avg, double min,
double max) {
return new AggregateNumericMetric(scheduleId, Bucket.SIX_HOUR, avg, min, max, time.getMillis());
}
private AggregateNumericMetric new24HourAggregate(int scheduleId, DateTime time, double avg, double min,
double max) {
return new AggregateNumericMetric(scheduleId, Bucket.TWENTY_FOUR_HOUR, avg, min, max, time.getMillis());
}
}