package com.rackspacecloud.blueflood.io;
import com.rackspacecloud.blueflood.exceptions.CacheException;
import com.rackspacecloud.blueflood.io.astyanax.ABasicMetricsRW;
import com.rackspacecloud.blueflood.io.datastax.DBasicMetricsRW;
import com.rackspacecloud.blueflood.io.datastax.DDelayedLocatorIO;
import com.rackspacecloud.blueflood.io.datastax.DLocatorIO;
import com.rackspacecloud.blueflood.rollup.Granularity;
import com.rackspacecloud.blueflood.rollup.SlotKey;
import com.rackspacecloud.blueflood.service.Configuration;
import com.rackspacecloud.blueflood.service.CoreConfig;
import com.rackspacecloud.blueflood.service.SingleRollupWriteContext;
import com.rackspacecloud.blueflood.types.*;
import com.rackspacecloud.blueflood.utils.DefaultClockImpl;
import com.rackspacecloud.blueflood.utils.TimeValue;
import com.rackspacecloud.blueflood.utils.Util;
import org.junit.Before;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.TimeUnit;
/**
* Base class for getting BasicMetricsRW implementations for writing/reading basic metrics
* (SimpleNumber). This class mostly creates:
* <ul>
* <li>the sample data which is read and written using the MetricsRW implementations
* <li>helper methods for creating {@link com.rackspacecloud.blueflood.service.SingleRollupWriteContext}
* </ul>
*/
public class BasicMetricsRWIntegrationTest extends IntegrationTestBase {
protected static final double EPSILON = .5;
private static final String TENANT1 = "123456";
private static final String TENANT2 = "987654";
private static final String TENANT3 = "123789";
protected DLocatorIO locatorIO = new DLocatorIO();
protected DDelayedLocatorIO delayedLocatorIO = new DDelayedLocatorIO();
protected MetricsRW datastaxMetricsRW = new DBasicMetricsRW(locatorIO, delayedLocatorIO, false, false, new DefaultClockImpl());
protected MetricsRW astyanaxMetricsRW = new ABasicMetricsRW(false, new DefaultClockImpl());
protected Map<Locator, IMetric> numericMap = new HashMap<Locator, IMetric>();
protected static final long MAX_AGE_ALLOWED = Configuration.getInstance().getLongProperty(CoreConfig.ROLLUP_DELAY_MILLIS);
protected static Granularity DELAYED_METRICS_STORAGE_GRANULARITY =
Granularity.getRollupGranularity(Configuration.getInstance().getStringProperty(CoreConfig.DELAYED_METRICS_STORAGE_GRANULARITY));
/**
* Generate numeric metrics to be used by the tests.
*
* @throws CacheException
*/
@Before
public void generateMetrics() throws CacheException {
String className = getClass().getSimpleName();
for( String tid : Arrays.asList( TENANT1, TENANT2, TENANT3 ) ) {
// Numeric
Locator locator = Locator.createLocatorFromPathComponents( tid, className + ".numeric.metric." + System.currentTimeMillis() );
Metric metric = new Metric( locator,
new Long( System.currentTimeMillis() % 100 ),
System.currentTimeMillis(),
new TimeValue(1, TimeUnit.DAYS),
"unit" );
numericMap.put( locator, metric );
}
}
/**
* This method is to supply the granularity parameter to some test methods below
*
* @return
*/
protected Object getGranularitiesToTest() {
return Arrays.copyOfRange( Granularity.granularities(), 1, Granularity.granularities().length - 1);
}
/**
* Converts the input metrics from a map of locator -> IMetric to a list of
* {@link com.rackspacecloud.blueflood.service.SingleRollupWriteContext}
* objects
*
* @param inputMetrics
* @return
*/
protected List<SingleRollupWriteContext> toWriteContext( Collection<IMetric> inputMetrics, Granularity destGran) throws IOException {
List<SingleRollupWriteContext> resultList = new ArrayList<SingleRollupWriteContext>();
for ( IMetric metric : inputMetrics ) {
SingleRollupWriteContext writeContext = createSingleRollupWriteContext( destGran, metric );
resultList.add(writeContext);
}
return resultList;
}
/**
* Convert a list of {@link com.rackspacecloud.blueflood.types.Points} into a list of
* {@link com.rackspacecloud.blueflood.service.SingleRollupWriteContext} for the given
* Granularity and Locator.
*
* @param locator
* @param points
* @param gran
* @return
*/
protected List<SingleRollupWriteContext> toWriteContext( Locator locator, Points<Rollup> points, Granularity gran ) {
List<SingleRollupWriteContext> resultList = new ArrayList<SingleRollupWriteContext>();
for( Map.Entry<Long, Points.Point<Rollup>> entry : points.getPoints().entrySet() ) {
resultList.add( new SingleRollupWriteContext(
entry.getValue().getData(),
locator,
gran,
CassandraModel.getBasicColumnFamily( gran ),
entry.getKey() ) );
}
return resultList;
}
/**
* Create a single {@link com.rackspacecloud.blueflood.service.SingleRollupWriteContext} from the given
* {@link com.rackspacecloud.blueflood.types.IMetric} and Granularity.
*
* @param destGran
* @param metric
* @return
* @throws IOException
*/
protected SingleRollupWriteContext createSingleRollupWriteContext( Granularity destGran, IMetric metric ) throws IOException {
Locator locator = metric.getLocator();
Points<SimpleNumber> points = new Points<SimpleNumber>();
points.add( new Points.Point<SimpleNumber>( metric.getCollectionTime(), new SimpleNumber( metric.getMetricValue() ) ) );
BasicRollup rollup = BasicRollup.buildRollupFromRawSamples( points );
return new SingleRollupWriteContext(
rollup,
locator,
destGran,
CassandraModel.getBasicColumnFamily( destGran ),
metric.getCollectionTime());
}
/**
* For a given list of locators, figure the shard they belong to and for all those shards
* get all the locators in metric_locator column family
*
* @param ingestedLocators
* @return
* @throws IOException
*/
protected Set<Locator> retrieveLocators(Set<Locator> ingestedLocators) throws IOException {
Set<Long> shards = new HashSet<Long>();
for (Locator locator: ingestedLocators) {
long shard = (long) Util.getShard(locator.toString());
shards.add(shard);
}
Set<Locator> locatorsFromDB = new HashSet<Locator>();
for (Long shard: shards) {
locatorsFromDB.addAll(locatorIO.getLocators(shard));
}
return locatorsFromDB;
}
/**
* For a given list of metrics, figure out the shard and slot they belong to and for those
* shard and slot combinations, get all the locators from metrics_delayed_locator column family.
*
* @param metrics
* @return
* @throws IOException
*/
protected Set<Locator> retrieveLocatorsByShardAndSlot(List<IMetric> metrics) throws IOException {
Set<String> slotKeys = new HashSet<String>();
for (IMetric metric: metrics) {
int shard = Util.getShard(metric.getLocator().toString());
int slot = DELAYED_METRICS_STORAGE_GRANULARITY.slot(metric.getCollectionTime());
SlotKey slotKey = SlotKey.of(DELAYED_METRICS_STORAGE_GRANULARITY, slot, shard);
slotKeys.add(slotKey.toString());
}
Set<Locator> locatorsFromDB = new HashSet<Locator>();
for (String slotKeyStr: slotKeys) {
locatorsFromDB.addAll(delayedLocatorIO.getLocators(SlotKey.parse(slotKeyStr)));
}
return locatorsFromDB;
}
}