/************************************************************************* * Copyright 2009-2013 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.cloudwatch.common.internal.domain.metricdata; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeMap; import java.util.TreeSet; import javax.persistence.EntityTransaction; import com.eucalyptus.cloudwatch.common.internal.domain.AbstractPersistentWithDimensions; import com.eucalyptus.configurable.ConfigurableClass; import com.eucalyptus.configurable.ConfigurableField; import com.eucalyptus.configurable.PropertyChangeListeners; import com.eucalyptus.entities.TransactionResource; import com.google.common.collect.Iterables; import com.google.common.collect.LinkedListMultimap; import org.apache.log4j.Logger; import org.hibernate.CacheMode; import org.hibernate.Criteria; import org.hibernate.ScrollMode; import org.hibernate.ScrollableResults; import org.hibernate.criterion.Junction; import org.hibernate.criterion.Order; import org.hibernate.criterion.ProjectionList; import org.hibernate.criterion.Projections; import org.hibernate.criterion.Restrictions; import com.eucalyptus.cloudwatch.common.internal.domain.DimensionEntity; import com.eucalyptus.cloudwatch.common.internal.domain.metricdata.MetricEntity.MetricType; import com.eucalyptus.cloudwatch.common.internal.hashing.HashUtils; import com.eucalyptus.entities.Entities; import com.eucalyptus.records.Logs; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Multimap; import com.google.common.collect.Sets; public class MetricManager { public static volatile Integer METRIC_DATA_NUM_DB_OPERATIONS_PER_TRANSACTION = 10000; public static volatile Integer METRIC_DATA_NUM_DB_OPERATIONS_UNTIL_SESSION_FLUSH = 50; public static final Logger LOG = Logger.getLogger(MetricManager.class); public static void addMetric(String accountId, String metricName, String namespace, Map<String, String> dimensionMap, MetricType metricType, Units units, Date timestamp, Double sampleSize, Double sampleMax, Double sampleMin, Double sampleSum) { SimpleMetricEntity simpleMetricEntity = new SimpleMetricEntity(); simpleMetricEntity.setAccountId(accountId); simpleMetricEntity.setDimensionMap(dimensionMap); simpleMetricEntity.setMetricName(metricName); simpleMetricEntity.setMetricType(metricType); simpleMetricEntity.setNamespace(namespace); simpleMetricEntity.setSampleMax(sampleMax); simpleMetricEntity.setSampleMin(sampleMin); simpleMetricEntity.setSampleSize(sampleSize); simpleMetricEntity.setSampleSum(sampleSum); simpleMetricEntity.setTimestamp(timestamp); simpleMetricEntity.setUnits(units); validateMetricQueueItem(simpleMetricEntity); addManyMetrics(makeMetricMap(hash(simpleMetricEntity))); } private static Multimap<Class, MetricEntity> makeMetricMap(Collection<MetricEntity> entities) { Multimap<Class, MetricEntity> metricMap = ArrayListMultimap .<Class, MetricEntity> create(); for (MetricEntity entity:entities) { metricMap .put(MetricEntityFactory.getClassForEntitiesGet(entity.getMetricType(), entity.getDimensionHash()), entity); } return metricMap; } private static List<MetricEntity> hash(SimpleMetricEntity simpleMetricEntity) { if (simpleMetricEntity == null) return new ArrayList<MetricEntity>(); TreeSet<DimensionEntity> dimensions = new TreeSet<DimensionEntity>(); for (Map.Entry<String, String> entry : simpleMetricEntity.getDimensionMap().entrySet()) { DimensionEntity d = new DimensionEntity(); d.setName(entry.getKey()); d.setValue(entry.getValue()); dimensions.add(d); } ArrayList<MetricEntity> returnValue = new ArrayList<MetricEntity>(); String dimensionHash = hash(dimensions); MetricEntity metric = MetricEntityFactory.getNewMetricEntity(simpleMetricEntity.getMetricType(), dimensionHash); metric.setAccountId(simpleMetricEntity.getAccountId()); metric.setMetricName(simpleMetricEntity.getMetricName()); metric.setNamespace(simpleMetricEntity.getNamespace()); metric.setDimensionHash(dimensionHash); metric.setMetricType(simpleMetricEntity.getMetricType()); metric.setUnits(simpleMetricEntity.getUnits()); metric.setTimestamp(simpleMetricEntity.getTimestamp()); metric.setSampleMax(simpleMetricEntity.getSampleMax()); metric.setSampleMin(simpleMetricEntity.getSampleMin()); metric.setSampleSum(simpleMetricEntity.getSampleSum()); metric.setSampleSize(simpleMetricEntity.getSampleSize()); returnValue.add(metric); return returnValue; } private static void addManyMetrics(Multimap<Class, MetricEntity> metricMap) { for (Class c : metricMap.keySet()) { for (List<MetricEntity> dataBatchPartial : Iterables.partition(metricMap.get(c), METRIC_DATA_NUM_DB_OPERATIONS_PER_TRANSACTION)) { try (final TransactionResource db = Entities.transactionFor(c)) { int numOperations = 0; for (MetricEntity me : dataBatchPartial) { numOperations++; if (numOperations % METRIC_DATA_NUM_DB_OPERATIONS_UNTIL_SESSION_FLUSH == 0) { Entities.flushSession(c); Entities.clearSession(c); } Entities.persist(me); } db.commit(); } } } } public static String hash(Map<String, String> dimensionMap) { TreeMap<String, String> sortedDimensionMap = Maps.newTreeMap(); if (dimensionMap != null) { sortedDimensionMap.putAll(dimensionMap); } StringBuilder sb = new StringBuilder(); for (Map.Entry<String, String> entry : sortedDimensionMap.entrySet()) { sb.append(entry.getKey() + "|" + entry.getValue() + "|"); } return HashUtils.hash(sb); } public static String hash(Collection<DimensionEntity> dimensions) { StringBuilder sb = new StringBuilder(); for (DimensionEntity dimension : dimensions) { sb.append(dimension.getName() + "|" + dimension.getValue() + "|"); } return HashUtils.hash(sb); } public static void deleteAllMetrics() { for (Class c : MetricEntityFactory.getAllClassesForEntitiesGet()) { try (final TransactionResource db = Entities.transactionFor(c)) { Entities.deleteAll(c); db.commit(); } } } /** * Delete all metrics before a certain date * * @param before * the date to delete before (inclusive) */ public static void deleteMetrics(Date before) { for (Class c : MetricEntityFactory.getAllClassesForEntitiesGet()) { try (final TransactionResource db = Entities.transactionFor(c)) { Map<String, Date> criteria = new HashMap<String, Date>(); criteria.put("before", before); Entities.deleteAllMatching(c, "WHERE timestamp < :before", criteria); db.commit(); } } } public static class GetMetricStatisticsParams { String accountId; String metricName; String namespace; Map<String, String> dimensionMap; MetricType metricType; Units units; Date startTime; Date endTime; Integer period; Collection<DimensionEntity> dimensions; String dimensionHash; public GetMetricStatisticsParams(String accountId, String metricName, String namespace, Map<String, String> dimensionMap, MetricType metricType, Units units, Date startTime, Date endTime, Integer period) { this.accountId = accountId; this.metricName = metricName; this.namespace = namespace; this.dimensionMap = dimensionMap; this.metricType = metricType; this.units = units; this.startTime = startTime; this.endTime = endTime; this.period = period; this.dimensions = getDimensionsFromMap(dimensionMap); this.dimensionHash = hash(dimensionMap); } private static Collection<DimensionEntity> getDimensionsFromMap(Map<String, String> dimensionMap) { TreeSet<DimensionEntity> dimensions = new TreeSet<DimensionEntity>(); for (Map.Entry<String, String> entry : dimensionMap.entrySet()) { DimensionEntity d = new DimensionEntity(); d.setName(entry.getKey()); d.setValue(entry.getValue()); dimensions.add(d); } return dimensions; } @Override public String toString() { return "GetMetricStatisticsParams{" + "accountId='" + accountId + '\'' + ", metricName='" + metricName + '\'' + ", namespace='" + namespace + '\'' + ", dimensionMap=" + dimensionMap + ", metricType=" + metricType + ", units=" + units + ", startTime=" + startTime + ", endTime=" + endTime + ", period=" + period + '}'; } public String getAccountId() { return accountId; } public String getMetricName() { return metricName; } public String getNamespace() { return namespace; } public Map<String, String> getDimensionMap() { return dimensionMap; } public MetricType getMetricType() { return metricType; } public Units getUnits() { return units; } public Date getStartTime() { return startTime; } public Date getEndTime() { return endTime; } public Integer getPeriod() { return period; } public void validate(Date now) { if (dimensionMap == null) { dimensionMap = new HashMap<String, String>(); } else if (dimensionMap.size() > AbstractPersistentWithDimensions.MAX_DIM_NUM) { throw new IllegalArgumentException("Too many dimensions for metric, " + dimensionMap.size()); } if (endTime == null) endTime = now; if (startTime == null) startTime = new Date(now.getTime() - 60 * 60 * 1000L); startTime = MetricUtils.stripSeconds(startTime); endTime = MetricUtils.stripSeconds(endTime); if (startTime.after(endTime)) { throw new IllegalArgumentException("Start time must be after end time"); } if (period == null) { period = 60; } if (period % 60 != 0) { throw new IllegalArgumentException("Period must be a multiple of 60"); } if (period < 0) { throw new IllegalArgumentException("Period must be greater than 0"); } if (period == 0) { throw new IllegalArgumentException("Period must not equal 0"); } if (metricType == null) { throw new IllegalArgumentException("metricType must not be null"); } if (accountId == null) { throw new IllegalArgumentException("accountId must not be null"); } if (metricName == null) { throw new IllegalArgumentException("metricName must not be null"); } if (namespace == null) { throw new IllegalArgumentException("namespace must not be null"); } } public Collection<DimensionEntity> getDimensions() { return dimensions; } public String getDimensionHash() { return dimensionHash; } public GetMetricStatisticsParams() { } } public static List<Collection<MetricStatistics>> getManyMetricStatistics(List<GetMetricStatisticsParams> getMetricStatisticsParamses) { if (getMetricStatisticsParamses == null) throw new IllegalArgumentException("getMetricStatisticsParamses can not be null"); Date now = new Date(); Map<GetMetricStatisticsParams, Collection<MetricStatistics>> resultMap = Maps.newHashMap(); Multimap<Class, GetMetricStatisticsParams> hashGroupMap = LinkedListMultimap.create(); for (GetMetricStatisticsParams getMetricStatisticsParams : getMetricStatisticsParamses) { if (getMetricStatisticsParams == null) throw new IllegalArgumentException("getMetricStatisticsParams can not be null"); getMetricStatisticsParams.validate(now); Class metricEntityClass = MetricEntityFactory.getClassForEntitiesGet(getMetricStatisticsParams.getMetricType(), getMetricStatisticsParams.getDimensionHash()); hashGroupMap.put(metricEntityClass, getMetricStatisticsParams); } for (Class metricEntityClass: hashGroupMap.keySet()) { try (final TransactionResource db = Entities.transactionFor(metricEntityClass)) { // set some global criteria to start (for narrowing?) Date minDate = null; Date maxDate = null; Junction disjunction = Restrictions.disjunction(); Map<GetMetricStatisticsParams, TreeMap<GetMetricStatisticsAggregationKey, MetricStatistics>> multiAggregationMap = Maps.newHashMap(); for (GetMetricStatisticsParams getMetricStatisticsParams : hashGroupMap.get(metricEntityClass)) { multiAggregationMap.put(getMetricStatisticsParams, new TreeMap<GetMetricStatisticsAggregationKey, MetricStatistics>(GetMetricStatisticsAggregationKey.COMPARATOR_WITH_NULLS.INSTANCE)); Junction conjunction = Restrictions.conjunction(); conjunction = conjunction.add(Restrictions.lt("timestamp", getMetricStatisticsParams.getEndTime())); conjunction = conjunction.add(Restrictions.ge("timestamp", getMetricStatisticsParams.getStartTime())); conjunction = conjunction.add(Restrictions.eq("accountId", getMetricStatisticsParams.getAccountId())); conjunction = conjunction.add(Restrictions.eq("metricName", getMetricStatisticsParams.getMetricName())); conjunction = conjunction.add(Restrictions.eq("namespace", getMetricStatisticsParams.getNamespace())); conjunction = conjunction.add(Restrictions.eq("dimensionHash", hash(getMetricStatisticsParams.getDimensionMap()))); if (getMetricStatisticsParams.getUnits() != null) { conjunction = conjunction.add(Restrictions.eq("units", getMetricStatisticsParams.getUnits())); } disjunction = disjunction.add(conjunction); if (minDate == null || getMetricStatisticsParams.getStartTime().before(minDate)) { minDate = getMetricStatisticsParams.getStartTime(); } if (maxDate == null || getMetricStatisticsParams.getEndTime().after(maxDate)) { maxDate = getMetricStatisticsParams.getEndTime(); } } Criteria criteria = Entities.createCriteria(metricEntityClass); criteria = criteria.add(Restrictions.lt("timestamp", maxDate)); criteria = criteria.add(Restrictions.ge("timestamp", minDate)); criteria = criteria.add(disjunction); ProjectionList projectionList = Projections.projectionList(); projectionList.add(Projections.max("sampleMax")); projectionList.add(Projections.min("sampleMin")); projectionList.add(Projections.sum("sampleSize")); projectionList.add(Projections.sum("sampleSum")); projectionList.add(Projections.groupProperty("units")); projectionList.add(Projections.groupProperty("timestamp")); projectionList.add(Projections.groupProperty("accountId")); projectionList.add(Projections.groupProperty("metricName")); projectionList.add(Projections.groupProperty("metricType")); projectionList.add(Projections.groupProperty("namespace")); projectionList.add(Projections.groupProperty("dimensionHash")); criteria.setProjection(projectionList); criteria.addOrder(Order.asc("timestamp")); ScrollableResults results = criteria.setCacheMode(CacheMode.IGNORE).scroll(ScrollMode.FORWARD_ONLY); while (results.next()) { MetricEntity me = getMetricEntity(results); for (GetMetricStatisticsParams getMetricStatisticsParams : hashGroupMap.get(metricEntityClass)) { if (metricDataMatches(getMetricStatisticsParams, me)) { Map<GetMetricStatisticsAggregationKey, MetricStatistics> aggregationMap = multiAggregationMap.get(getMetricStatisticsParams); GetMetricStatisticsAggregationKey key = new GetMetricStatisticsAggregationKey(me, getMetricStatisticsParams.getStartTime(), getMetricStatisticsParams.getPeriod(), getMetricStatisticsParams.getDimensionHash()); MetricStatistics item = new MetricStatistics(me, getMetricStatisticsParams.getStartTime(), getMetricStatisticsParams.getPeriod(), getMetricStatisticsParams.getDimensions()); if (!aggregationMap.containsKey(key)) { aggregationMap.put(key, item); } else { MetricStatistics totalSoFar = aggregationMap.get(key); totalSoFar.setSampleMax(Math.max(item.getSampleMax(), totalSoFar.getSampleMax())); totalSoFar.setSampleMin(Math.min(item.getSampleMin(), totalSoFar.getSampleMin())); totalSoFar.setSampleSize(totalSoFar.getSampleSize() + item.getSampleSize()); totalSoFar.setSampleSum(totalSoFar.getSampleSum() + item.getSampleSum()); } } } } for (GetMetricStatisticsParams getMetricStatisticsParams : multiAggregationMap.keySet()) { resultMap.put(getMetricStatisticsParams, multiAggregationMap.get(getMetricStatisticsParams).values()); } } } List<Collection<MetricStatistics>> resultList = Lists.newArrayList(); for (GetMetricStatisticsParams getMetricStatisticsParams : getMetricStatisticsParamses) { if (resultMap.get(getMetricStatisticsParams) == null) { resultList.add(new ArrayList<MetricStatistics>()); } else { resultList.add(resultMap.get(getMetricStatisticsParams)); } } return resultList; } private static boolean metricDataMatches(GetMetricStatisticsParams getMetricStatisticsParams, MetricEntity metricEntity) { if (getMetricStatisticsParams == null || metricEntity == null) return false; if (getMetricStatisticsParams.getStartTime() == null || getMetricStatisticsParams.getStartTime().after(metricEntity.getTimestamp())) return false; if (metricEntity.getTimestamp() == null || !metricEntity.getTimestamp().before(getMetricStatisticsParams.getEndTime())) return false; if (getMetricStatisticsParams.getAccountId() == null || !getMetricStatisticsParams.getAccountId().equals(metricEntity.getAccountId())) return false; if (getMetricStatisticsParams.getMetricName() == null || !getMetricStatisticsParams.getMetricName().equals(metricEntity.getMetricName())) return false; if (getMetricStatisticsParams.getNamespace() == null || !getMetricStatisticsParams.getNamespace().equals(metricEntity.getNamespace())) return false; if (getMetricStatisticsParams.getMetricType() == null || !getMetricStatisticsParams.getMetricType().equals(metricEntity.getMetricType())) return false; if (getMetricStatisticsParams.getDimensionHash() == null || !getMetricStatisticsParams.getDimensionHash().equals(metricEntity.getDimensionHash())) return false; return true; } public static Collection<MetricStatistics> getMetricStatistics(GetMetricStatisticsParams getMetricStatisticsParams) { if (getMetricStatisticsParams == null) throw new IllegalArgumentException("getMetricStatisticsParams can not be null"); Date now = new Date(); getMetricStatisticsParams.validate(now); Class metricEntityClass = MetricEntityFactory.getClassForEntitiesGet(getMetricStatisticsParams.getMetricType(), getMetricStatisticsParams.getDimensionHash()); Map<GetMetricStatisticsAggregationKey, MetricStatistics> aggregationMap = new TreeMap<GetMetricStatisticsAggregationKey, MetricStatistics>(GetMetricStatisticsAggregationKey.COMPARATOR_WITH_NULLS.INSTANCE); try (final TransactionResource db = Entities.transactionFor(metricEntityClass)) { Criteria criteria = Entities.createCriteria(metricEntityClass); criteria = criteria.add(Restrictions.eq("accountId", getMetricStatisticsParams.getAccountId())); criteria = criteria.add(Restrictions.eq("metricName", getMetricStatisticsParams.getMetricName())); criteria = criteria.add(Restrictions.eq("namespace", getMetricStatisticsParams.getNamespace())); criteria = criteria.add(Restrictions.lt("timestamp", getMetricStatisticsParams.getEndTime())); criteria = criteria.add(Restrictions.ge("timestamp", getMetricStatisticsParams.getStartTime())); criteria = criteria.add(Restrictions.eq("dimensionHash", getMetricStatisticsParams.getDimensionHash())); if (getMetricStatisticsParams.getUnits() != null) { criteria = criteria.add(Restrictions.eq("units", getMetricStatisticsParams.getUnits())); } ProjectionList projectionList = Projections.projectionList(); projectionList.add(Projections.max("sampleMax")); projectionList.add(Projections.min("sampleMin")); projectionList.add(Projections.sum("sampleSize")); projectionList.add(Projections.sum("sampleSum")); projectionList.add(Projections.groupProperty("units")); projectionList.add(Projections.groupProperty("timestamp")); criteria.setProjection(projectionList); criteria.addOrder(Order.asc("timestamp")); ScrollableResults results = criteria.setCacheMode(CacheMode.IGNORE).scroll(ScrollMode.FORWARD_ONLY); while (results.next()) { MetricEntity me = getMetricEntity(getMetricStatisticsParams.getAccountId(), getMetricStatisticsParams.getMetricName(), getMetricStatisticsParams.getNamespace(), getMetricStatisticsParams.getMetricType(), getMetricStatisticsParams.getDimensionHash(), results); GetMetricStatisticsAggregationKey key = new GetMetricStatisticsAggregationKey(me, getMetricStatisticsParams.getStartTime(), getMetricStatisticsParams.getPeriod(), getMetricStatisticsParams.getDimensionHash()); MetricStatistics item = new MetricStatistics(me, getMetricStatisticsParams.getStartTime(), getMetricStatisticsParams.getPeriod(), getMetricStatisticsParams.getDimensions()); if (!aggregationMap.containsKey(key)) { aggregationMap.put(key, item); } else { MetricStatistics totalSoFar = aggregationMap.get(key); totalSoFar.setSampleMax(Math.max(item.getSampleMax(), totalSoFar.getSampleMax())); totalSoFar.setSampleMin(Math.min(item.getSampleMin(), totalSoFar.getSampleMin())); totalSoFar.setSampleSize(totalSoFar.getSampleSize() + item.getSampleSize()); totalSoFar.setSampleSum(totalSoFar.getSampleSum() + item.getSampleSum()); } } } return Lists.newArrayList(aggregationMap.values()); } private static MetricEntity getMetricEntity(ScrollableResults results) { Double sampleMax = (Double) results.get(0); Double sampleMin = (Double) results.get(1); Double sampleSize = (Double) results.get(2); Double sampleSum = (Double) results.get(3); Units resultUnits = (Units) results.get(4); Date timestamp = (Date) results.get(5); String accountId = (String) results.get(6); String metricName = (String) results.get(7); MetricType metricType = (MetricType) results.get(8); String namespace = (String) results.get(9); String hash = (String) results.get(10); MetricEntity me = MetricEntityFactory.getNewMetricEntity(metricType, hash); me.setAccountId(accountId); me.setNamespace(namespace); me.setMetricName(metricName); me.setMetricType(metricType); me.setDimensionHash(hash); me.setSampleMax(sampleMax); me.setSampleMin(sampleMin); me.setSampleSize(sampleSize); me.setSampleSum(sampleSum); me.setTimestamp(timestamp); me.setUnits(resultUnits); return me; } private static MetricEntity getMetricEntity(String accountId, String metricName, String namespace, MetricType metricType, String hash, ScrollableResults results) { Double sampleMax = (Double) results.get(0); Double sampleMin = (Double) results.get(1); Double sampleSize = (Double) results.get(2); Double sampleSum = (Double) results.get(3); Units resultUnits = (Units) results.get(4); Date timestamp = (Date) results.get(5); MetricEntity me = MetricEntityFactory.getNewMetricEntity(metricType, hash); me.setAccountId(accountId); me.setNamespace(namespace); me.setMetricName(metricName); me.setMetricType(metricType); me.setDimensionHash(hash); me.setSampleMax(sampleMax); me.setSampleMin(sampleMin); me.setSampleSize(sampleSize); me.setSampleSum(sampleSum); me.setTimestamp(timestamp); me.setUnits(resultUnits); return me; } public static Collection<MetricEntity> getAllMetrics() { ArrayList<MetricEntity> allResults = new ArrayList<MetricEntity>(); for (Class c : MetricEntityFactory.getAllClassesForEntitiesGet()) { try (final TransactionResource db = Entities.transactionFor(c)) { Criteria criteria = Entities.createCriteria(c); criteria = criteria.addOrder( Order.asc("timestamp") ); criteria = criteria.addOrder( Order.asc("id") ); Collection dbResults = criteria.list(); for (Object result : dbResults) { allResults.add((MetricEntity) result); } db.commit(); } } return allResults; } public static void addMetricBatch(List<SimpleMetricEntity> dataBatch) { ArrayList<MetricEntity> metricEntities = new ArrayList<MetricEntity>(); for (SimpleMetricEntity simpleMetricEntity: dataBatch) { validateMetricQueueItem(simpleMetricEntity); metricEntities.addAll(hash(simpleMetricEntity)); } addManyMetrics(makeMetricMap(metricEntities)); } private static void validateMetricQueueItem(SimpleMetricEntity simpleMetricEntity) { LOG.trace("metricName="+simpleMetricEntity.getMetricName()); LOG.trace("namespace="+simpleMetricEntity.getNamespace()); LOG.trace("dimensionMap="+simpleMetricEntity.getDimensionMap()); LOG.trace("metricType="+simpleMetricEntity.getMetricType()); LOG.trace("units="+simpleMetricEntity.getUnits()); LOG.trace("timestamp="+simpleMetricEntity.getTimestamp()); LOG.trace("sampleSize="+simpleMetricEntity.getSampleSize()); LOG.trace("sampleMax="+simpleMetricEntity.getSampleMax()); LOG.trace("sampleMin="+simpleMetricEntity.getSampleMin()); LOG.trace("sampleSum="+simpleMetricEntity.getSampleSum()); if (simpleMetricEntity.getDimensionMap() == null) { simpleMetricEntity.setDimensionMap(new HashMap<String, String>()); } else if (simpleMetricEntity.getDimensionMap().size() > AbstractPersistentWithDimensions.MAX_DIM_NUM) { throw new IllegalArgumentException("Too many dimensions for metric, " + simpleMetricEntity.getDimensionMap().size()); } simpleMetricEntity.setTimestamp(MetricUtils.stripSeconds(simpleMetricEntity.getTimestamp())); } }