Repository: ambari Updated Branches: refs/heads/branch-2.0.maint 5eab7803f -> fa96df533
AMBARI-10809. AMS: navigating graph time ranges are not correct. (swagle) Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/fa96df53 Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/fa96df53 Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/fa96df53 Branch: refs/heads/branch-2.0.maint Commit: fa96df5332b0da27b51e76a018a9e5400f38b9ec Parents: 5eab780 Author: Siddharth Wagle <[email protected]> Authored: Wed Apr 29 13:50:05 2015 -0700 Committer: Siddharth Wagle <[email protected]> Committed: Wed Apr 29 13:50:05 2015 -0700 ---------------------------------------------------------------------- .../metrics/MetricsPaddingMethod.java | 107 ++++++++++ .../metrics/MetricsPropertyProvider.java | 17 +- .../metrics/timeline/AMSPropertyProvider.java | 8 +- .../timeline/AMSPropertyProviderTest.java | 2 +- .../timeline/MetricsPaddingMethodTest.java | 208 +++++++++++++++++++ .../resources/ams/multiple_host_metrics.json | 172 +++++++-------- 6 files changed, 422 insertions(+), 92 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/fa96df53/ambari-server/src/main/java/org/apache/ambari/server/controller/metrics/MetricsPaddingMethod.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/metrics/MetricsPaddingMethod.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/metrics/MetricsPaddingMethod.java new file mode 100644 index 0000000..6093aaf --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/metrics/MetricsPaddingMethod.java @@ -0,0 +1,107 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.ambari.server.controller.metrics; + +import org.apache.ambari.server.controller.spi.TemporalInfo; +import org.apache.hadoop.metrics2.sink.timeline.TimelineMetric; +import java.util.Iterator; +import java.util.TreeMap; + +public class MetricsPaddingMethod { + private final PADDING_STRATEGY strategy; + private static final long MINIMUM_STEP_INTERVAL = 999l; // ~ 1 second + public static final String ZERO_PADDING_PARAM = "params/padding"; + public static enum PADDING_STRATEGY { + ZEROS, + NULLS, + NONE + } + + public MetricsPaddingMethod(PADDING_STRATEGY strategy) { + this.strategy = strategy; + } + + /** + * Adds zero/null values towards the end of metrics sequence as well as the + * beginning to support backward compatibility with Ganglia. + * We use step if only a single datapoint is found. + * It is assumed that @TimelineMetric.metricsValues are sorted in ascending + * order and thee is no padding between the interval. + * + * @param metric AMS @TimelineMetric + * @param temporalInfo @TemporalInfo Requested interval + */ + public void applyPaddingStrategy(TimelineMetric metric, TemporalInfo temporalInfo) { + if (strategy.equals(PADDING_STRATEGY.NONE) || temporalInfo == null) { + return; + } + + // TODO: JSON dser returns LinkedHashMap that is not Navigable + TreeMap<Long, Double> values = new TreeMap<Long, Double>(metric.getMetricValues()); + + long dataInterval = getTimelineMetricInterval(values); + + if (dataInterval == -1 || dataInterval < MINIMUM_STEP_INTERVAL) { + dataInterval = temporalInfo.getStep() != null ? temporalInfo.getStep() : -1; + } + // Unable to determine what interval to use for padding + if (dataInterval == -1) { + return; + } + + long intervalStartTime = longToMillis(temporalInfo.getStartTime()); + long intervalEndTime = longToMillis(temporalInfo.getEndTime()); + long dataStartTime = longToMillis(values.firstKey()); + long dataEndTime = longToMillis(values.lastKey()); + + Double paddingValue = 0.0d; + + if (strategy.equals(PADDING_STRATEGY.NULLS)) { + paddingValue = null; + } + // Pad before data interval + for (long counter = intervalStartTime; counter < dataStartTime; counter += dataInterval) { + // Until counter approaches or goes past dataStartTime : pad + values.put(counter, paddingValue); + } + // Pad after data interval + for (long counter = dataEndTime + dataInterval; counter <= intervalEndTime; counter += dataInterval) { + values.put(counter, paddingValue); + } + // Put back new + old values + metric.setMetricValues(values); + } + + private long longToMillis(long time) { + if (time < 9999999999l) { + return time * 1000; + } + return time; + } + + private long getTimelineMetricInterval(TreeMap<Long, Double> values) { + if (values != null && values.size() > 1) { + Iterator<Long> tsValuesIterator = values.descendingKeySet().iterator(); + long lastValue = tsValuesIterator.next(); + long secondToLastValue = tsValuesIterator.next(); + return Math.abs(lastValue - secondToLastValue); + } + // No values found or only one value found + return -1; + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/fa96df53/ambari-server/src/main/java/org/apache/ambari/server/controller/metrics/MetricsPropertyProvider.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/metrics/MetricsPropertyProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/metrics/MetricsPropertyProvider.java index d58d110..8360f5e 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/metrics/MetricsPropertyProvider.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/metrics/MetricsPropertyProvider.java @@ -24,14 +24,16 @@ import org.apache.ambari.server.controller.spi.Predicate; import org.apache.ambari.server.controller.spi.Request; import org.apache.ambari.server.controller.spi.Resource; import org.apache.ambari.server.controller.spi.SystemException; +import org.apache.ambari.server.controller.utilities.PredicateHelper; import org.apache.ambari.server.controller.utilities.StreamProvider; -import org.apache.http.client.utils.URIBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Map; import java.util.Set; import java.util.regex.Pattern; +import static org.apache.ambari.server.controller.metrics.MetricsPaddingMethod.ZERO_PADDING_PARAM; + public abstract class MetricsPropertyProvider extends AbstractPropertyProvider { protected final static Logger LOG = LoggerFactory.getLogger(MetricsPropertyProvider.class); @@ -50,6 +52,9 @@ public abstract class MetricsPropertyProvider extends AbstractPropertyProvider { protected final ComponentSSLConfiguration configuration; + protected MetricsPaddingMethod metricsPaddingMethod = + new MetricsPaddingMethod(MetricsPaddingMethod.PADDING_STRATEGY.ZEROS); + protected MetricsPropertyProvider(Map<String, Map<String, PropertyInfo>> componentPropertyInfoMap, StreamProvider streamProvider, @@ -124,6 +129,16 @@ public abstract class MetricsPropertyProvider extends AbstractPropertyProvider { return resources; } + Map<String, Object> predicateProperties = PredicateHelper.getProperties(predicate); + if (predicateProperties != null && predicateProperties.keySet().contains(ZERO_PADDING_PARAM)) { + String paddingStr = (String) predicateProperties.get(ZERO_PADDING_PARAM); + for (MetricsPaddingMethod.PADDING_STRATEGY strategy : MetricsPaddingMethod.PADDING_STRATEGY.values()) { + if (paddingStr.equalsIgnoreCase(strategy.name())) { + metricsPaddingMethod = new MetricsPaddingMethod(strategy); + } + } + } + return populateResourcesWithProperties(resources, request, ids); } http://git-wip-us.apache.org/repos/asf/ambari/blob/fa96df53/ambari-server/src/main/java/org/apache/ambari/server/controller/metrics/timeline/AMSPropertyProvider.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/metrics/timeline/AMSPropertyProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/metrics/timeline/AMSPropertyProvider.java index b566473..83e2221 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/metrics/timeline/AMSPropertyProvider.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/metrics/timeline/AMSPropertyProvider.java @@ -34,7 +34,6 @@ import org.codehaus.jackson.map.AnnotationIntrospector; import org.codehaus.jackson.map.ObjectMapper; import org.codehaus.jackson.map.ObjectReader; import org.codehaus.jackson.xc.JaxbAnnotationIntrospector; - import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; @@ -49,7 +48,6 @@ import java.util.Map; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; - import static org.apache.ambari.server.Role.HBASE_MASTER; import static org.apache.ambari.server.Role.HBASE_REGIONSERVER; import static org.apache.ambari.server.Role.METRICS_COLLECTOR; @@ -184,8 +182,10 @@ public abstract class AMSPropertyProvider extends MetricsPropertyProvider { for (TimelineMetric metric : timelineMetrics.getMetrics()) { if (metric.getMetricName() != null - && metric.getMetricValues() != null - && checkMetricName(patterns, metric.getMetricName())) { + && metric.getMetricValues() != null + && checkMetricName(patterns, metric.getMetricName())) { + // Pad zeros or nulls if needed + metricsPaddingMethod.applyPaddingStrategy(metric, temporalInfo); populateResource(resource, metric); } } http://git-wip-us.apache.org/repos/asf/ambari/blob/fa96df53/ambari-server/src/test/java/org/apache/ambari/server/controller/metrics/timeline/AMSPropertyProviderTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/metrics/timeline/AMSPropertyProviderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/metrics/timeline/AMSPropertyProviderTest.java index 4e2ed98..919fad9 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/controller/metrics/timeline/AMSPropertyProviderTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/metrics/timeline/AMSPropertyProviderTest.java @@ -366,7 +366,7 @@ public class AMSPropertyProviderTest { uriBuilder.addParameter("endTime", "1421697600"); Assert.assertEquals(uriBuilder.toString(), streamProvider.getLastSpec()); Number[][] val = (Number[][]) res.getPropertyValue(propertyId); - Assert.assertEquals(188, val.length); + Assert.assertEquals(189, val.length); } public static class TestMetricHostProvider implements MetricHostProvider { http://git-wip-us.apache.org/repos/asf/ambari/blob/fa96df53/ambari-server/src/test/java/org/apache/ambari/server/controller/metrics/timeline/MetricsPaddingMethodTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/metrics/timeline/MetricsPaddingMethodTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/metrics/timeline/MetricsPaddingMethodTest.java new file mode 100644 index 0000000..7665e5e --- /dev/null +++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/metrics/timeline/MetricsPaddingMethodTest.java @@ -0,0 +1,208 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.ambari.server.controller.metrics.timeline; + +import junit.framework.Assert; +import org.apache.ambari.server.controller.metrics.MetricsPaddingMethod; +import org.apache.ambari.server.controller.spi.TemporalInfo; +import org.apache.hadoop.metrics2.sink.timeline.TimelineMetric; +import org.junit.Test; +import java.util.Map; +import java.util.TreeMap; + +public class MetricsPaddingMethodTest { + + @Test + public void testPaddingWithNulls() throws Exception { + MetricsPaddingMethod paddingMethod = + new MetricsPaddingMethod(MetricsPaddingMethod.PADDING_STRATEGY.NULLS); + + long now = System.currentTimeMillis(); + + TimelineMetric timelineMetric = new TimelineMetric(); + timelineMetric.setMetricName("m1"); + timelineMetric.setHostName("h1"); + timelineMetric.setAppId("a1"); + timelineMetric.setTimestamp(now); + TreeMap<Long, Double> inputValues = new TreeMap<Long, Double>(); + inputValues.put(now - 1000, 1.0d); + inputValues.put(now - 2000, 2.0d); + inputValues.put(now - 3000, 3.0d); + timelineMetric.setMetricValues(inputValues); + + TemporalInfo temporalInfo = getTemporalInfo(now - 10000, now, 1l); + paddingMethod.applyPaddingStrategy(timelineMetric, temporalInfo); + TreeMap<Long, Double> values = (TreeMap<Long, Double>) timelineMetric.getMetricValues(); + + Assert.assertEquals(11, values.size()); + Assert.assertEquals(new Long(now - 10000), values.keySet().iterator().next()); + Assert.assertEquals(new Long(now), values.descendingKeySet().iterator().next()); + Assert.assertEquals(null, values.values().iterator().next()); + } + + @Test + public void testPaddingWithZeros() throws Exception { + MetricsPaddingMethod paddingMethod = + new MetricsPaddingMethod(MetricsPaddingMethod.PADDING_STRATEGY.ZEROS); + + long now = System.currentTimeMillis(); + + TimelineMetric timelineMetric = new TimelineMetric(); + timelineMetric.setMetricName("m1"); + timelineMetric.setHostName("h1"); + timelineMetric.setAppId("a1"); + timelineMetric.setTimestamp(now); + TreeMap<Long, Double> inputValues = new TreeMap<Long, Double>(); + inputValues.put(now - 1000, 1.0d); + inputValues.put(now - 2000, 2.0d); + inputValues.put(now - 3000, 3.0d); + timelineMetric.setMetricValues(inputValues); + + TemporalInfo temporalInfo = getTemporalInfo(now - 10000, now, 1l); + paddingMethod.applyPaddingStrategy(timelineMetric, temporalInfo); + TreeMap<Long, Double> values = (TreeMap<Long, Double>) timelineMetric.getMetricValues(); + + Assert.assertEquals(11, values.size()); + Assert.assertEquals(new Long(now - 10000), values.keySet().iterator().next()); + Assert.assertEquals(new Long(now), values.descendingKeySet().iterator().next()); + Assert.assertEquals(0.0, values.values().iterator().next()); + } + + @Test + public void testPaddingWithNoPaddingNeeded() throws Exception { + MetricsPaddingMethod paddingMethod = + new MetricsPaddingMethod(MetricsPaddingMethod.PADDING_STRATEGY.ZEROS); + + long now = System.currentTimeMillis(); + + TimelineMetric timelineMetric = new TimelineMetric(); + timelineMetric.setMetricName("m1"); + timelineMetric.setHostName("h1"); + timelineMetric.setAppId("a1"); + timelineMetric.setTimestamp(now); + TreeMap<Long, Double> inputValues = new TreeMap<Long, Double>(); + inputValues.put(now, 0.0d); + inputValues.put(now - 1000, 1.0d); + inputValues.put(now - 2000, 2.0d); + inputValues.put(now - 3000, 3.0d); + timelineMetric.setMetricValues(inputValues); + + TemporalInfo temporalInfo = getTemporalInfo(now - 3000, now, 1l); + paddingMethod.applyPaddingStrategy(timelineMetric, temporalInfo); + TreeMap<Long, Double> values = (TreeMap<Long, Double>) timelineMetric.getMetricValues(); + + Assert.assertEquals(4, values.size()); + Assert.assertEquals(new Long(now - 3000), values.keySet().iterator().next()); + Assert.assertEquals(new Long(now), values.descendingKeySet().iterator().next()); + } + + @Test + public void testPaddingWithStepProvided() throws Exception { + MetricsPaddingMethod paddingMethod = + new MetricsPaddingMethod(MetricsPaddingMethod.PADDING_STRATEGY.ZEROS); + + long now = System.currentTimeMillis(); + + TimelineMetric timelineMetric = new TimelineMetric(); + timelineMetric.setMetricName("m1"); + timelineMetric.setHostName("h1"); + timelineMetric.setAppId("a1"); + timelineMetric.setTimestamp(now); + TreeMap<Long, Double> inputValues = new TreeMap<Long, Double>(); + inputValues.put(now - 1000, 1.0d); + timelineMetric.setMetricValues(inputValues); + + TemporalInfo temporalInfo = getTemporalInfo(now - 10000, now, 1000l); + paddingMethod.applyPaddingStrategy(timelineMetric, temporalInfo); + TreeMap<Long, Double> values = (TreeMap<Long, Double>) timelineMetric.getMetricValues(); + + Assert.assertEquals(11, values.size()); + Assert.assertEquals(new Long(now - 10000), values.keySet().iterator().next()); + Assert.assertEquals(new Long(now), values.descendingKeySet().iterator().next()); + Assert.assertEquals(0.0, values.values().iterator().next()); + } + + @Test + public void testPaddingWithOneValueReturnedNoStepProvided() throws Exception { + MetricsPaddingMethod paddingMethod = + new MetricsPaddingMethod(MetricsPaddingMethod.PADDING_STRATEGY.ZEROS); + + long now = System.currentTimeMillis(); + + TimelineMetric timelineMetric = new TimelineMetric(); + timelineMetric.setMetricName("m1"); + timelineMetric.setHostName("h1"); + timelineMetric.setAppId("a1"); + timelineMetric.setTimestamp(now); + TreeMap<Long, Double> inputValues = new TreeMap<Long, Double>(); + inputValues.put(now - 1000, 1.0d); + timelineMetric.setMetricValues(inputValues); + + TemporalInfo temporalInfo = getTemporalInfo(now - 10000, now, null); + paddingMethod.applyPaddingStrategy(timelineMetric, temporalInfo); + TreeMap<Long, Double> values = (TreeMap<Long, Double>) timelineMetric.getMetricValues(); + + Assert.assertEquals(1, values.size()); + Assert.assertEquals(new Long(now - 1000), values.keySet().iterator().next()); + Assert.assertEquals(1.0, values.values().iterator().next()); + } + + @Test + public void testNoPaddingRequested() throws Exception { + MetricsPaddingMethod paddingMethod = + new MetricsPaddingMethod(MetricsPaddingMethod.PADDING_STRATEGY.NONE); + + long now = System.currentTimeMillis(); + + TimelineMetric timelineMetric = new TimelineMetric(); + timelineMetric.setMetricName("m1"); + timelineMetric.setHostName("h1"); + timelineMetric.setAppId("a1"); + timelineMetric.setTimestamp(now); + Map<Long, Double> inputValues = new TreeMap<Long, Double>(); + inputValues.put(now - 100, 1.0d); + inputValues.put(now - 200, 2.0d); + inputValues.put(now - 300, 3.0d); + timelineMetric.setMetricValues(inputValues); + + TemporalInfo temporalInfo = getTemporalInfo(now - 1000, now, 10l); + paddingMethod.applyPaddingStrategy(timelineMetric, temporalInfo); + TreeMap<Long, Double> values = (TreeMap<Long, Double>) timelineMetric.getMetricValues(); + + Assert.assertEquals(3, values.size()); + } + + private TemporalInfo getTemporalInfo(final Long startTime, final Long endTime, final Long step) { + return new TemporalInfo() { + @Override + public Long getStartTime() { + return startTime; + } + + @Override + public Long getEndTime() { + return endTime; + } + + @Override + public Long getStep() { + return step; + } + }; + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/fa96df53/ambari-server/src/test/resources/ams/multiple_host_metrics.json ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/resources/ams/multiple_host_metrics.json b/ambari-server/src/test/resources/ams/multiple_host_metrics.json index 019dc62..2868573 100644 --- a/ambari-server/src/test/resources/ams/multiple_host_metrics.json +++ b/ambari-server/src/test/resources/ams/multiple_host_metrics.json @@ -125,92 +125,92 @@ "appid": "HOST", "starttime": 1416445244801, "metrics": { - "1416486250037": "2.46272E8", - "1416486255040": "2.46145024E8", - "1416486260042": "2.46280192E8", - "1416486265047": "2.4641536E8", - "1416486270053": "2.44318208E8", - "1416486275058": "2.464768E8", - "1416486280063": "2.464768E8", - "1416486285067": "2.464768E8", - "1416486290072": "2.46898688E8", - "1416486295077": "2.46898688E8", - "1416486300083": "2.46898688E8", - "1416486305088": "2.46898688E8", - "1416486310093": "2.4676352E8", - "1416486315097": "2.4676352E8", - "1416486320102": "2.46898688E8", - "1416486325105": "2.46898688E8", - "1416486330107": "2.46898688E8", - "1416486335113": "2.47025664E8", - "1416486340118": "2.47025664E8", - "1416486345123": "2.46898688E8", - "1416486350128": "2.46595584E8", - "1416486355133": "2.46341632E8", - "1416486360135": "2.464768E8", - "1416486365140": "2.46603776E8", - "1416486370145": "2.46468608E8", - "1416486375151": "2.46341632E8", - "1416486380156": "2.464768E8", - "1416486385161": "2.464768E8", - "1416486390166": "2.464768E8", - "1416486395169": "2.464768E8", - "1416486400172": "2.464768E8", - "1416486405177": "2.46603776E8", - "1416486410180": "2.46898688E8", - "1416486415182": "2.47025664E8", - "1416486420187": "2.47025664E8", - "1416486425193": "2.47025664E8", - "1416486430198": "2.46890496E8", - "1416486435203": "2.4676352E8", - "1416486440208": "2.46898688E8", - "1416486445213": "2.46890496E8", - "1416486450218": "2.46890496E8", - "1416486455223": "2.46890496E8", - "1416486460224": "2.46890496E8", - "1416486465229": "2.46890496E8", - "1416486470230": "2.4643584E8", - "1416486475235": "2.46181888E8", - "1416486480237": "2.4619008E8", - "1416486485242": "2.46317056E8", - "1416486490244": "2.46181888E8", - "1416486495249": "2.46181888E8", - "1416486500255": "2.46317056E8", - "1416486505260": "2.46317056E8", - "1416486510261": "2.46317056E8", - "1416486515266": "2.4619008E8", - "1416486520270": "2.4619008E8", - "1416486525276": "2.46317056E8", - "1416486530279": "2.46890496E8", - "1416486535282": "2.46890496E8", - "1416486540287": "2.46890496E8", - "1416486545291": "2.47017472E8", - "1416486550295": "2.46882304E8", - "1416486555300": "2.46882304E8", - "1416486560301": "2.46890496E8", - "1416486565306": "2.47025664E8", - "1416486570309": "2.47025664E8", - "1416486575314": "2.47025664E8", - "1416486580315": "2.47025664E8", - "1416486585321": "2.47025664E8", - "1416486590325": "2.4672256E8", - "1416486595327": "2.46468608E8", - "1416486600331": "2.46603776E8", - "1416486605336": "2.46603776E8", - "1416486610337": "2.46595584E8", - "1416486615342": "2.46468608E8", - "1416486620345": "2.46603776E8", - "1416486625350": "2.46730752E8", - "1416486630354": "2.46730752E8", - "1416486635365": "2.46603776E8", - "1416486640360": "2.46603776E8", - "1416486645368": "2.46730752E8", - "1416486650370": "2.47025664E8", - "1416486655375": "2.4715264E8", - "1416486660380": "2.4715264E8", - "1416486665385": "2.4715264E8", - "1416486675392": "2.46890496E8", - "1416486690404": "2.47025664E8" + "1416445244801": "2.46272E8", + "1416445259801": "2.46145024E8", + "1416445274801": "2.46280192E8", + "1416445289801": "2.4641536E8", + "1416445304801": "2.44318208E8", + "1416445319801": "2.464768E8", + "1416445364801": "2.464768E8", + "1416445379801": "2.464768E8", + "1416445394801": "2.46898688E8", + "1416445409801": "2.46898688E8", + "1416445424801": "2.46898688E8", + "1416445439801": "2.46898688E8", + "1416445484801": "2.4676352E8", + "1416445499801": "2.4676352E8", + "1416445514801": "2.46898688E8", + "1416445529801": "2.46898688E8", + "1416445544801": "2.46898688E8", + "1416445559801": "2.47025664E8", + "1416445604801": "2.47025664E8", + "1416445619801": "2.46898688E8", + "1416445634801": "2.46595584E8", + "1416445649801": "2.46341632E8", + "1416445664801": "2.464768E8", + "1416445679801": "2.46603776E8", + "1416445724801": "2.46468608E8", + "1416445739801": "2.46341632E8", + "1416445964801": "2.464768E8", + "1416445979801": "2.464768E8", + "1416445994801": "2.464768E8", + "1416446009801": "2.464768E8", + "1416446024801": "2.464768E8", + "1416446084801": "2.46603776E8", + "1416446099801": "2.46898688E8", + "1416446114801": "2.47025664E8", + "1416446129801": "2.47025664E8", + "1416446144801": "2.47025664E8", + "1416446204801": "2.46890496E8", + "1416446219801": "2.4676352E8", + "1416446234801": "2.46898688E8", + "1416446249801": "2.46890496E8", + "1416446264801": "2.46890496E8", + "1416446324801": "2.46890496E8", + "1416446339801": "2.46890496E8", + "1416446354801": "2.46890496E8", + "1416446369801": "2.4643584E8", + "1416446384801": "2.46181888E8", + "1416446444801": "2.4619008E8", + "1416446459801": "2.46317056E8", + "1416446474801": "2.46181888E8", + "1416446489801": "2.46181888E8", + "1416446504801": "2.46317056E8", + "1416446564801": "2.46317056E8", + "1416446579801": "2.46317056E8", + "1416446594801": "2.4619008E8", + "1416446609801": "2.4619008E8", + "1416446624801": "2.46317056E8", + "1416446684801": "2.46890496E8", + "1416446699801": "2.46890496E8", + "1416446714801": "2.46890496E8", + "1416446729801": "2.47017472E8", + "1416446744801": "2.46882304E8", + "1416446804801": "2.46882304E8", + "1416446819801": "2.46890496E8", + "1416446834801": "2.47025664E8", + "1416446849801": "2.47025664E8", + "1416446864801": "2.47025664E8", + "1416446924801": "2.47025664E8", + "1416446939801": "2.47025664E8", + "1416446954801": "2.4672256E8", + "1416446969801": "2.46468608E8", + "1416446984801": "2.46603776E8", + "1416447044801": "2.46603776E8", + "1416447059801": "2.46595584E8", + "1416447074801": "2.46468608E8", + "1416447089801": "2.46603776E8", + "1416447104801": "2.46730752E8", + "1416447164801": "2.46730752E8", + "1416447179801": "2.46603776E8", + "1416447194801": "2.46603776E8", + "1416447209801": "2.46730752E8", + "1416447224801": "2.47025664E8", + "1416447284801": "2.4715264E8", + "1416447299801": "2.4715264E8", + "1416447314801": "2.4715264E8", + "1416447329801": "2.46890496E8", + "1416447344801": "2.47025664E8" } } ]} \ No newline at end of file
