/*************************************************************************
* Copyright 2009-2015 Eucalyptus Systems, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 3 of the License.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://www.gnu.org/licenses/.
*
* Please contact Eucalyptus Systems, Inc., 6755 Hollister Ave., Goleta
* CA 93117, USA or visit http://www.eucalyptus.com/licenses/ if you need
* additional information or have any questions.
************************************************************************/
package com.eucalyptus.cluster.callback.reporting;
import com.eucalyptus.cloudwatch.common.internal.domain.metricdata.Units;
import com.eucalyptus.cloudwatch.common.msgs.Dimension;
import com.eucalyptus.cloudwatch.common.msgs.MetricDatum;
import com.eucalyptus.cloudwatch.common.msgs.StatisticSet;
import com.eucalyptus.entities.Entities;
import com.eucalyptus.entities.TransactionResource;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.log4j.Logger;
import org.hibernate.CacheMode;
import org.hibernate.Criteria;
import org.hibernate.ScrollMode;
import org.hibernate.ScrollableResults;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class FullTableScanAbsoluteMetricConverter {
private static final Logger LOG = Logger.getLogger(FullTableScanAbsoluteMetricConverter.class);
protected static List<AbsoluteMetricQueueItem> dealWithAbsoluteMetrics(Iterable<AbsoluteMetricQueueItem> dataBatch) {
List<AbsoluteMetricQueueItem> regularMetrics = Lists.newArrayList();
List<SimpleAbsoluteMetricHistory> absoluteMetricsToInsert = Lists.newArrayList();
SortedAbsoluteMetrics sortedAbsoluteMetrics = sortAbsoluteMetrics(dataBatch);
regularMetrics.addAll(sortedAbsoluteMetrics.getRegularMetrics());
AbsoluteMetricMap absoluteMetricMap = sortedAbsoluteMetrics.getAbsoluteMetricMap();
try (final TransactionResource db = Entities.transactionFor(AbsoluteMetricHistory.class)) {
int count = 0;
Criteria criteria = Entities.createCriteria(AbsoluteMetricHistory.class);
ScrollableResults absoluteMetrics = criteria.setCacheMode(CacheMode.IGNORE).scroll(ScrollMode.FORWARD_ONLY);
while (absoluteMetrics.next()) {
AbsoluteMetricHistory absoluteMetricHistory = (AbsoluteMetricHistory) absoluteMetrics.get(0);
if (absoluteMetricMap.containsKey(
absoluteMetricHistory.getNamespace(), absoluteMetricHistory.getMetricName(),
absoluteMetricHistory.getDimensionName(), absoluteMetricHistory.getDimensionValue())) {
MetricsAndOtherFields metricsAndOtherFields =
absoluteMetricMap.getMetricsAndOtherFields(absoluteMetricHistory.getNamespace(),
absoluteMetricHistory.getMetricName(), absoluteMetricHistory.getDimensionName(),
absoluteMetricHistory.getDimensionValue());
Map<TimestampAndMetricValue, MetricDatum> metricDatumMap = metricsAndOtherFields.getMetricDatumMap();
SequentialMetrics sequentialMetrics = calculateSequentialMetrics(absoluteMetricHistory, metricDatumMap, metricsAndOtherFields.getAccountId(), metricsAndOtherFields.getRelativeMetricName());
absoluteMetricMap.removeEntries(absoluteMetricHistory.getNamespace(), absoluteMetricHistory.getMetricName(),
absoluteMetricHistory.getDimensionName(), absoluteMetricHistory.getDimensionValue());
for (AbsoluteMetricQueueItem regularMetric: sequentialMetrics.getRegularMetrics()) {
if (AbsoluteMetricHelper.AWS_EBS_NAMESPACE.equals(regularMetric.getNamespace())) {
if (AbsoluteMetricHelper.VOLUME_READ_OPS_METRIC_NAME.equals(regularMetric.getMetricDatum().getMetricName())) { // special case
regularMetrics.add(AbsoluteMetricHelper.createVolumeThroughputMetric(regularMetric.getAccountId(), regularMetric.getNamespace(), regularMetric.getMetricDatum()));
} else if (AbsoluteMetricHelper.VOLUME_TOTAL_READ_WRITE_TIME_METRIC_NAME.equals(regularMetric.getMetricDatum().getMetricName())) {
AbsoluteMetricHelper.convertVolumeTotalReadWriteTimeToVolumeIdleTime(regularMetric.getMetricDatum());
}
}
regularMetrics.add(regularMetric);
}
absoluteMetricHistory.setTimestamp(sequentialMetrics.getUpdateTimestamp());
absoluteMetricHistory.setLastMetricValue(sequentialMetrics.getUpdateValue());
if (++count % AbsoluteMetricQueue.ABSOLUTE_METRIC_NUM_DB_OPERATIONS_UNTIL_SESSION_FLUSH == 0) {
Entities.flushSession(AbsoluteMetricHistory.class);
Entities.clearSession(AbsoluteMetricHistory.class);
}
}
}
db.commit();
}
// Now parse entries only in the map...
for (AbsoluteMetricMap.NamespaceMetricNameAndDimension namespaceMetricNameAndDimension: absoluteMetricMap.keySet()) {
AbsoluteMetricHistory absoluteMetricHistory = new AbsoluteMetricHistory();
absoluteMetricHistory.setNamespace(namespaceMetricNameAndDimension.getNamespace());
absoluteMetricHistory.setMetricName(namespaceMetricNameAndDimension.getMetricName());
absoluteMetricHistory.setDimensionName(namespaceMetricNameAndDimension.getDimensionName());
absoluteMetricHistory.setDimensionValue(namespaceMetricNameAndDimension.getDimensionValue());
MetricsAndOtherFields metricsAndOtherFields = absoluteMetricMap.get(namespaceMetricNameAndDimension);
Map<TimestampAndMetricValue, MetricDatum> metricDataMap = metricsAndOtherFields.getMetricDatumMap();
if (metricDataMap.size() == 0) continue;
TimestampAndMetricValue firstValue = metricDataMap.keySet().iterator().next();
metricDataMap.remove(firstValue);
absoluteMetricHistory.setLastMetricValue(firstValue.getMetricValue());
absoluteMetricHistory.setTimestamp(firstValue.getTimestamp());
if (metricDataMap.size() != 0) {
SequentialMetrics sequentialMetrics = calculateSequentialMetrics(absoluteMetricHistory, metricDataMap,
metricsAndOtherFields.getAccountId(), metricsAndOtherFields.getRelativeMetricName());
for (AbsoluteMetricQueueItem regularMetric: sequentialMetrics.getRegularMetrics()) {
if (AbsoluteMetricHelper.AWS_EBS_NAMESPACE.equals(regularMetric.getNamespace())) {
if (AbsoluteMetricHelper.VOLUME_READ_OPS_METRIC_NAME.equals(regularMetric.getMetricDatum().getMetricName())) { // special case
regularMetrics.add(AbsoluteMetricHelper.createVolumeThroughputMetric(regularMetric.getAccountId(), regularMetric.getNamespace(), regularMetric.getMetricDatum()));
} else if (AbsoluteMetricHelper.VOLUME_TOTAL_READ_WRITE_TIME_METRIC_NAME.equals(regularMetric.getMetricDatum().getMetricName())) {
AbsoluteMetricHelper.convertVolumeTotalReadWriteTimeToVolumeIdleTime(regularMetric.getMetricDatum());
}
}
regularMetrics.add(regularMetric);
}
absoluteMetricHistory.setTimestamp(sequentialMetrics.getUpdateTimestamp());
absoluteMetricHistory.setLastMetricValue(sequentialMetrics.getUpdateValue());
}
absoluteMetricsToInsert.add(convertToSimpleAbsoluteMetricHistory(absoluteMetricHistory));
}
// insert all new points
try (final TransactionResource db = Entities.transactionFor(AbsoluteMetricHistory.class)) {
int count = 0;
for (SimpleAbsoluteMetricHistory simpleAbsoluteMetricHistory : absoluteMetricsToInsert) {
Entities.persist(convertToAbsoluteMetricHistory(simpleAbsoluteMetricHistory));
if (++count % AbsoluteMetricQueue.ABSOLUTE_METRIC_NUM_DB_OPERATIONS_UNTIL_SESSION_FLUSH == 0) {
Entities.flushSession(AbsoluteMetricHistory.class);
Entities.clearSession(AbsoluteMetricHistory.class);
}
}
db.commit();
}
return regularMetrics;
}
private static SimpleAbsoluteMetricHistory convertToSimpleAbsoluteMetricHistory(AbsoluteMetricHistory absoluteMetricHistory) {
SimpleAbsoluteMetricHistory simpleAbsoluteMetricHistory = new SimpleAbsoluteMetricHistory();
simpleAbsoluteMetricHistory.setNamespace(absoluteMetricHistory.getNamespace());
simpleAbsoluteMetricHistory.setMetricName(absoluteMetricHistory.getMetricName());
simpleAbsoluteMetricHistory.setDimensionName(absoluteMetricHistory.getDimensionName());
simpleAbsoluteMetricHistory.setDimensionValue(absoluteMetricHistory.getDimensionValue());
simpleAbsoluteMetricHistory.setTimestamp(absoluteMetricHistory.getTimestamp());
simpleAbsoluteMetricHistory.setLastMetricValue(absoluteMetricHistory.getLastMetricValue());
return simpleAbsoluteMetricHistory;
}
private static AbsoluteMetricHistory convertToAbsoluteMetricHistory(SimpleAbsoluteMetricHistory simpleAbsoluteMetricHistory) {
AbsoluteMetricHistory absoluteMetricHistory = new AbsoluteMetricHistory();
absoluteMetricHistory.setNamespace(simpleAbsoluteMetricHistory.getNamespace());
absoluteMetricHistory.setMetricName(simpleAbsoluteMetricHistory.getMetricName());
absoluteMetricHistory.setDimensionName(simpleAbsoluteMetricHistory.getDimensionName());
absoluteMetricHistory.setDimensionValue(simpleAbsoluteMetricHistory.getDimensionValue());
absoluteMetricHistory.setTimestamp(simpleAbsoluteMetricHistory.getTimestamp());
absoluteMetricHistory.setLastMetricValue(simpleAbsoluteMetricHistory.getLastMetricValue());
return absoluteMetricHistory;
}
private static SequentialMetrics calculateSequentialMetrics(AbsoluteMetricHistory absoluteMetricHistory,
Map<TimestampAndMetricValue, MetricDatum> metricDatumMap,
String accountId,
String relativeMetricName) {
SequentialMetrics sequentialMetrics = new SequentialMetrics();
Date lastDate = absoluteMetricHistory.getTimestamp();
Double lastValue = absoluteMetricHistory.getLastMetricValue();
for (TimestampAndMetricValue value : metricDatumMap.keySet()) {
double valueDiff = value.getMetricValue() - lastValue;
// VolumeQueueLength is a special case. Values in the table are set to 0 but the data set uses the values passed in.
boolean isVolumeQueueLengthCase = AbsoluteMetricHelper.AWS_EBS_NAMESPACE.equals(absoluteMetricHistory.getNamespace()) &&
AbsoluteMetricHelper.VOLUME_QUEUE_LENGTH_PLACEHOLDER_ABSOLUTE_METRIC_NAME.equals(absoluteMetricHistory.getMetricName());
// CPUUtilization is also a special case. The value is a percent.
boolean isCPUUtilizationCase = AbsoluteMetricHelper.AWS_EC2_NAMESPACE.equals(absoluteMetricHistory.getNamespace()) &&
AbsoluteMetricHelper.CPU_UTILIZATION_MS_ABSOLUTE_METRIC_NAME.equals(absoluteMetricHistory.getMetricName());
long timeDiff = value.getTimestamp().getTime() - lastDate.getTime();
if (timeDiff < 0) {
// a negative value of timeDiff means this data point is not useful
continue;
} else if (timeDiff == 0) {
if (Math.abs(valueDiff) > AbsoluteMetricHelper.TOLERANCE) {
LOG.warn("Getting different values " + value.getMetricValue() + " and " + lastValue + " for absolute metric " + absoluteMetricHistory.getMetricName() + " at the same timestamp " + lastDate + ", keeping the second value.");
}
continue;
} else {
// definitely update the value
lastDate = value.getTimestamp();
lastValue = isVolumeQueueLengthCase ? 0 : value.getMetricValue();
if (timeDiff > AbsoluteMetricHelper.MAX_DIFFERENCE_DURATION_MS) {
// Too much time has passed, a useful data point, but we will not report the 'difference'. We will reset.
continue;
} else if (valueDiff < -AbsoluteMetricHelper.TOLERANCE) { // value has gone "down" (or down more than the AbsoluteMetricCommon.TOLERANCE)
// if the value difference is negative (i.e. has gone down, the assumption is that the NC has restarted, and the new
// value started from some time in the past. Best thing to do here is either assume it is a first point again, or
// assume the previous point had a 0 value. Not sure which is the better choice, but for now, we will make it a "first"
// point again
continue;
} else { // truncate differences within AbsoluteMetricCommon.TOLERANCE to zero
if (Math.abs(valueDiff) < AbsoluteMetricHelper.TOLERANCE) {
valueDiff = 0.0;
}
AbsoluteMetricQueueItem regularMetric = new AbsoluteMetricQueueItem();
regularMetric.setNamespace(absoluteMetricHistory.getNamespace());
regularMetric.setAccountId(accountId);
MetricDatum datum = metricDatumMap.get(value);
regularMetric.setMetricDatum(datum);
datum.setMetricName(relativeMetricName);
datum.setValue(null);
StatisticSet statisticSet = new StatisticSet();
double sampleCount = (double) timeDiff / 60000.0; // number of minutes (this weights the value)
if (isVolumeQueueLengthCase) {
datum.setMetricName(AbsoluteMetricHelper.VOLUME_QUEUE_LENGTH_METRIC_NAME); // other values are for the absolute metric history table only
statisticSet.setSum(value.getMetricValue() * sampleCount);
statisticSet.setMaximum(value.getMetricValue());
statisticSet.setMinimum(value.getMetricValue());
} else if (isCPUUtilizationCase) {
double percentage = 100.0 * (valueDiff / timeDiff);
statisticSet.setSum(percentage * sampleCount);
statisticSet.setMaximum(percentage);
statisticSet.setMinimum(percentage);
datum.setUnit(Units.Percent.toString());
} else {
statisticSet.setSum(valueDiff);
statisticSet.setMaximum(valueDiff / sampleCount);
statisticSet.setMinimum(valueDiff / sampleCount);
}
statisticSet.setSampleCount(sampleCount);
datum.setStatisticValues(statisticSet);
datum.setValue(null);
sequentialMetrics.getRegularMetrics().add(regularMetric);
}
}
}
sequentialMetrics.setUpdateTimestamp(lastDate);
sequentialMetrics.setUpdateValue(lastValue);
return sequentialMetrics;
}
private static SortedAbsoluteMetrics sortAbsoluteMetrics(Iterable<AbsoluteMetricQueueItem> dataBatch) {
SortedAbsoluteMetrics sortedAbsoluteMetrics = new SortedAbsoluteMetrics();
for (AbsoluteMetricQueueItem item : dataBatch) {
String accountId = item.getAccountId();
String namespace = item.getNamespace();
MetricDatum datum = item.getMetricDatum();
if (AbsoluteMetricHelper.AWS_EBS_NAMESPACE.equals(namespace)) {
String volumeId = null;
if ((datum.getDimensions() != null) && (datum.getDimensions().getMember() != null)) {
for (Dimension dimension : datum.getDimensions().getMember()) {
if (AbsoluteMetricHelper.VOLUME_ID_DIM_NAME.equals(dimension.getName())) {
volumeId = dimension.getValue();
}
}
}
if (volumeId == null) {
continue; // this data point doesn't count.
} else {
if (AbsoluteMetricHelper.EBS_ABSOLUTE_METRICS.containsKey(datum.getMetricName())) {
addAccountAbsoluteMetricMap(sortedAbsoluteMetrics, accountId, AbsoluteMetricHelper.AWS_EBS_NAMESPACE, datum.getMetricName(), AbsoluteMetricHelper.VOLUME_ID_DIM_NAME, volumeId, AbsoluteMetricHelper.EBS_ABSOLUTE_METRICS.get(datum.getMetricName()), datum.getTimestamp(), datum.getValue(), datum);
} else if (AbsoluteMetricHelper.VOLUME_QUEUE_LENGTH_METRIC_NAME.equals(datum.getMetricName())) {
addAccountAbsoluteMetricMap(sortedAbsoluteMetrics, accountId, AbsoluteMetricHelper.AWS_EBS_NAMESPACE, AbsoluteMetricHelper.VOLUME_QUEUE_LENGTH_PLACEHOLDER_ABSOLUTE_METRIC_NAME, AbsoluteMetricHelper.VOLUME_ID_DIM_NAME, volumeId, AbsoluteMetricHelper.VOLUME_QUEUE_LENGTH_PLACEHOLDER_METRIC_NAME, datum.getTimestamp(), datum.getValue(), datum);
} else {
sortedAbsoluteMetrics.getRegularMetrics().add(item);
}
}
} else if (AbsoluteMetricHelper.AWS_EC2_NAMESPACE.equals(namespace)) {
String instanceId = null;
if ((datum.getDimensions() != null) && (datum.getDimensions().getMember() != null)) {
for (Dimension dimension : datum.getDimensions().getMember()) {
if (AbsoluteMetricHelper.INSTANCE_ID_DIM_NAME.equals(dimension.getName())) {
instanceId = dimension.getValue();
}
}
}
if (instanceId == null) {
continue; // this data point doesn't count.
} else if (AbsoluteMetricHelper.EC2_ABSOLUTE_METRICS.containsKey(datum.getMetricName())) {
addAccountAbsoluteMetricMap(sortedAbsoluteMetrics, accountId, AbsoluteMetricHelper.AWS_EC2_NAMESPACE, datum.getMetricName(), AbsoluteMetricHelper.INSTANCE_ID_DIM_NAME, instanceId, AbsoluteMetricHelper.EC2_ABSOLUTE_METRICS.get(datum.getMetricName()), datum.getTimestamp(), datum.getValue(), datum);
} else if (AbsoluteMetricHelper.CPU_UTILIZATION_MS_ABSOLUTE_METRIC_NAME.equals(datum.getMetricName())) {
addAccountAbsoluteMetricMap(sortedAbsoluteMetrics, accountId, AbsoluteMetricHelper.AWS_EC2_NAMESPACE, AbsoluteMetricHelper.CPU_UTILIZATION_MS_ABSOLUTE_METRIC_NAME, AbsoluteMetricHelper.INSTANCE_ID_DIM_NAME, instanceId, AbsoluteMetricHelper.CPU_UTILIZATION_METRIC_NAME, datum.getTimestamp(), datum.getValue(), datum);
} else {
sortedAbsoluteMetrics.getRegularMetrics().add(item);
}
} else {
// not really an absolute metric, just leave it alone
sortedAbsoluteMetrics.getRegularMetrics().add(item);
}
}
return sortedAbsoluteMetrics;
}
private static void addAccountAbsoluteMetricMap(SortedAbsoluteMetrics sortedAbsoluteMetrics, String accountId, String namespace, String metricName, String dimensionName, String dimensionValue, String relativeMetricName, Date timestamp, Double lastMetricValue, MetricDatum datum) {
sortedAbsoluteMetrics.getAbsoluteMetricMap().addEntry(accountId, namespace, metricName, dimensionName, dimensionValue, relativeMetricName, timestamp, lastMetricValue, datum);
}
/**
* Created by ethomas on 7/15/15.
*/
public static class AbsoluteMetricMap {
private static class NamespaceMetricNameAndDimension {
private String namespace;
private String metricName;
private String dimensionName;
private String dimensionValue;
NamespaceMetricNameAndDimension(String namespace, String metricName, String dimensionName, String dimensionValue) {
this.namespace = namespace;
this.metricName = metricName;
this.dimensionName = dimensionName;
this.dimensionValue = dimensionValue;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
NamespaceMetricNameAndDimension namespaceMetricNameAndDimension = (NamespaceMetricNameAndDimension) o;
if (dimensionName != null ? !dimensionName.equals(namespaceMetricNameAndDimension.dimensionName) : namespaceMetricNameAndDimension.dimensionName != null)
return false;
if (dimensionValue != null ? !dimensionValue.equals(namespaceMetricNameAndDimension.dimensionValue) : namespaceMetricNameAndDimension.dimensionValue != null)
return false;
if (metricName != null ? !metricName.equals(namespaceMetricNameAndDimension.metricName) : namespaceMetricNameAndDimension.metricName != null) return false;
if (namespace != null ? !namespace.equals(namespaceMetricNameAndDimension.namespace) : namespaceMetricNameAndDimension.namespace != null) return false;
return true;
}
@Override
public int hashCode() {
int result = namespace != null ? namespace.hashCode() : 0;
result = 31 * result + (metricName != null ? metricName.hashCode() : 0);
result = 31 * result + (dimensionName != null ? dimensionName.hashCode() : 0);
result = 31 * result + (dimensionValue != null ? dimensionValue.hashCode() : 0);
return result;
}
public String getNamespace() {
return namespace;
}
public String getMetricName() {
return metricName;
}
public String getDimensionName() {
return dimensionName;
}
public String getDimensionValue() {
return dimensionValue;
}
}
private Map<NamespaceMetricNameAndDimension, MetricsAndOtherFields> metricMap = Maps.newHashMap();
public void addEntry(String accountId, String namespace, String metricName, String dimensionName,
String dimensionValue, String relativeMetricName, Date timestamp, Double lastMetricValue, MetricDatum datum) {
NamespaceMetricNameAndDimension namespaceMetricNameAndDimension = new NamespaceMetricNameAndDimension(namespace,
metricName, dimensionName, dimensionValue);
if (!metricMap.containsKey(namespaceMetricNameAndDimension)) {
metricMap.put(namespaceMetricNameAndDimension, new MetricsAndOtherFields(accountId, relativeMetricName));
}
if (relativeMetricName == null) { throw new IllegalArgumentException("RelativeMetricName can not be null"); }
if (accountId == null) { throw new IllegalArgumentException("AccountId can not be null"); }
MetricsAndOtherFields value = metricMap.get(namespaceMetricNameAndDimension);
if (!relativeMetricName.equals(value.getRelativeMetricName())) {
throw new IllegalArgumentException("RelativeMetricName has two values for " + namespace + "/" + dimensionName + "/" + dimensionValue);
}
if (!accountId.equals(value.getAccountId())) {
throw new IllegalArgumentException("RelativeMetricName has two values for " + namespace + "/" + dimensionName + "/" + dimensionValue);
}
value.getMetricDatumMap().put(new TimestampAndMetricValue(timestamp, lastMetricValue), datum);
}
public boolean containsKey(String namespace, String metricName, String dimensionName, String dimensionValue) {
return metricMap.containsKey(new NamespaceMetricNameAndDimension(namespace, metricName, dimensionName, dimensionValue));
}
public MetricsAndOtherFields getMetricsAndOtherFields(String namespace, String metricName, String dimensionName, String dimensionValue) {
return metricMap.get(new NamespaceMetricNameAndDimension(namespace, metricName, dimensionName, dimensionValue));
}
public void removeEntries(String namespace, String metricName, String dimensionName, String dimensionValue) {
metricMap.remove(new NamespaceMetricNameAndDimension(namespace, metricName, dimensionName, dimensionValue));
}
public Set<NamespaceMetricNameAndDimension> keySet() {
return metricMap.keySet();
}
public MetricsAndOtherFields get(NamespaceMetricNameAndDimension namespaceMetricNameAndDimension) {
return metricMap.get(namespaceMetricNameAndDimension);
}
}
static class SimpleAbsoluteMetricHistory {
public SimpleAbsoluteMetricHistory() {
}
private String namespace;
private String metricName;
private String dimensionName;
private String dimensionValue;
private Date timestamp;
private Double lastMetricValue;
public String getNamespace() {
return namespace;
}
public void setNamespace(String namespace) {
this.namespace = namespace;
}
public String getMetricName() {
return metricName;
}
public void setMetricName(String metricName) {
this.metricName = metricName;
}
public String getDimensionName() {
return dimensionName;
}
public void setDimensionName(String dimensionName) {
this.dimensionName = dimensionName;
}
public String getDimensionValue() {
return dimensionValue;
}
public void setDimensionValue(String dimensionValue) {
this.dimensionValue = dimensionValue;
}
public Date getTimestamp() {
return timestamp;
}
public void setTimestamp(Date timestamp) {
this.timestamp = timestamp;
}
public Double getLastMetricValue() {
return lastMetricValue;
}
public void setLastMetricValue(Double lastMetricValue) {
this.lastMetricValue = lastMetricValue;
}
}
private static class MetricsAndOtherFields {
private String accountId;
private String relativeMetricName;
private Map<TimestampAndMetricValue, MetricDatum> metricDatumMap = Maps.newTreeMap();
MetricsAndOtherFields(String accountId, String relativeMetricName) {
this.accountId = accountId;
this.relativeMetricName = relativeMetricName;
}
public String getAccountId() {
return accountId;
}
public String getRelativeMetricName() {
return relativeMetricName;
}
public Map<TimestampAndMetricValue, MetricDatum> getMetricDatumMap() {
return metricDatumMap;
}
}
static class TimestampAndMetricValue implements Comparable<TimestampAndMetricValue> {
private Date timestamp;
private Double metricValue;
TimestampAndMetricValue(Date timestamp, Double metricValue) {
this.timestamp = timestamp;
this.metricValue = metricValue;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
TimestampAndMetricValue that = (TimestampAndMetricValue) o;
if (metricValue != null ? !metricValue.equals(that.metricValue) : that.metricValue != null)
return false;
if (timestamp != null ? !timestamp.equals(that.timestamp) : that.timestamp != null) return false;
return true;
}
@Override
public int hashCode() {
int result = timestamp != null ? timestamp.hashCode() : 0;
result = 31 * result + (metricValue != null ? metricValue.hashCode() : 0);
return result;
}
public Date getTimestamp() {
return timestamp;
}
public Double getMetricValue() {
return metricValue;
}
public void setTimestamp(Date timestamp) {
this.timestamp = timestamp;
}
public void setMetricValue(Double metricValue) {
this.metricValue = metricValue;
}
@Override
public int compareTo(TimestampAndMetricValue that) {
if (this.timestamp.compareTo(that.timestamp) < 0) {
return -1;
} else if (this.timestamp.compareTo(that.timestamp) > 0) {
return 1;
}
if (this.metricValue.compareTo(that.metricValue) < 0) {
return -1;
} else if (this.metricValue.compareTo(that.metricValue) > 0) {
return 1;
}
return 0;
}
}
private static class SortedAbsoluteMetrics {
private List<AbsoluteMetricQueueItem> regularMetrics = Lists.newArrayList();
private AbsoluteMetricMap absoluteMetricMap = new AbsoluteMetricMap();
SortedAbsoluteMetrics() {
}
public List<AbsoluteMetricQueueItem> getRegularMetrics() {
return regularMetrics;
}
public AbsoluteMetricMap getAbsoluteMetricMap() {
return absoluteMetricMap;
}
}
private static class SequentialMetrics {
private Collection<AbsoluteMetricQueueItem> regularMetrics = Lists.newArrayList();
private Date updateTimestamp;
private Double updateValue;
public void setUpdateTimestamp(Date updateTimestamp) {
this.updateTimestamp = updateTimestamp;
}
public void setUpdateValue(Double updateValue) {
this.updateValue = updateValue;
}
public Collection<AbsoluteMetricQueueItem> getRegularMetrics() {
return regularMetrics;
}
public Date getUpdateTimestamp() {
return updateTimestamp;
}
public Double getUpdateValue() {
return updateValue;
}
}
}