diff --git hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-jobclient/src/test/java/org/apache/hadoop/mapred/TimelineServicePerformanceV2.java hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-jobclient/src/test/java/org/apache/hadoop/mapred/TimelineServicePerformanceV2.java index de46617..9bbb74b 100644 --- hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-jobclient/src/test/java/org/apache/hadoop/mapred/TimelineServicePerformanceV2.java +++ hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-jobclient/src/test/java/org/apache/hadoop/mapred/TimelineServicePerformanceV2.java @@ -261,7 +261,7 @@ public void map(IntWritable key, IntWritable val, Context context) // add a metric TimelineMetric metric = new TimelineMetric(); metric.setId("foo_metric"); - metric.setSingleData(123456789L); + metric.addTimeSeriesData(System.currentTimeMillis(), 123456789L); entity.addMetric(metric); // add a config entity.addConfig("foo", "bar"); diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/api/records/timelineservice/TimelineEntity.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/api/records/timelineservice/TimelineEntity.java index 6cab753..3be7f52 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/api/records/timelineservice/TimelineEntity.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/api/records/timelineservice/TimelineEntity.java @@ -80,7 +80,7 @@ public String toString() { private TimelineEntity real; private Identifier identifier; private HashMap info = new HashMap<>(); - private HashMap configs = new HashMap<>(); + private HashMap configs = new HashMap<>(); private Set metrics = new HashSet<>(); private Set events = new HashSet<>(); private HashMap> isRelatedToEntities = new HashMap<>(); @@ -213,7 +213,7 @@ public void addInfo(String key, Object value) { // required by JAXB @InterfaceAudience.Private @XmlElement(name = "configs") - public HashMap getConfigsJAXB() { + public HashMap getConfigsJAXB() { if (real == null) { return configs; } else { @@ -221,7 +221,7 @@ public void addInfo(String key, Object value) { } } - public Map getConfigs() { + public Map getConfigs() { if (real == null) { return configs; } else { @@ -229,19 +229,19 @@ public void addInfo(String key, Object value) { } } - public void setConfigs(Map configs) { + public void setConfigs(Map configs) { if (real == null) { if (configs != null && !(configs instanceof HashMap)) { - this.configs = new HashMap(configs); + this.configs = new HashMap(configs); } else { - this.configs = (HashMap) configs; + this.configs = (HashMap) configs; } } else { real.setConfigs(configs); } } - public void addConfigs(Map configs) { + public void addConfigs(Map configs) { if (real == null) { this.configs.putAll(configs); } else { @@ -249,7 +249,7 @@ public void addConfigs(Map configs) { } } - public void addConfig(String key, Object value) { + public void addConfig(String key, String value) { if (real == null) { configs.put(key, value); } else { diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/api/records/timelineservice/TimelineMetric.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/api/records/timelineservice/TimelineMetric.java index 57babbf..61597c1 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/api/records/timelineservice/TimelineMetric.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/api/records/timelineservice/TimelineMetric.java @@ -24,113 +24,104 @@ import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; -import java.util.HashMap; -import java.util.LinkedHashMap; +import java.util.Comparator; import java.util.Map; +import java.util.TreeMap; @XmlRootElement(name = "metric") @XmlAccessorType(XmlAccessType.NONE) @InterfaceAudience.Public @InterfaceStability.Unstable public class TimelineMetric { - private String id; - private HashMap info = new HashMap<>(); - private Object singleData; - private HashMap timeSeries = new LinkedHashMap<>(); - private long startTime; - private long endTime; - - public TimelineMetric() { + public static enum Type { + SINGLE_VALUE, + TIME_SERIES } - @XmlElement(name = "id") - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } + private Type type; + private String id; + private Comparator reverseComparator = new Comparator() { + @Override + public int compare(Long l1, Long l2) { + return -l1.compareTo(l2); + } + }; + private TreeMap timeSeries = new TreeMap<>(reverseComparator); - // required by JAXB - @InterfaceAudience.Private - @XmlElement(name = "info") - public HashMap getInfoJAXB() { - return info; + public TimelineMetric() { + this(Type.SINGLE_VALUE); } - public Map getInfo() { - return info; + public TimelineMetric(Type type) { + this.type = type; } - public void setInfo(Map info) { - if (info != null && !(info instanceof HashMap)) { - this.info = new HashMap(info); - } else { - this.info = (HashMap) info; - } - } - public void addInfo(Map info) { - this.info.putAll(info); + @XmlElement(name = "type") + public Type getType() { + return type; } - public void addInfo(String key, Object value) { - info.put(key, value); + public void setType(Type type) { + this.type = type; } - @XmlElement(name = "data") - public Object getSingleData() { - return singleData; + @XmlElement(name = "id") + public String getId() { + return id; } - public void setSingleData(Object singleData) { - this.singleData = singleData; + public void setId(String id) { + this.id = id; } // required by JAXB @InterfaceAudience.Private @XmlElement(name = "timeseries") - public HashMap getTimeSeriesJAXB() { + public TreeMap getTimeSeriesJAXB() { return timeSeries; } - public Map getTimeSeries() { + public Map getTimeSeries() { return timeSeries; } - public void setTimeSeries(Map timeSeries) { - if (timeSeries != null && !(timeSeries instanceof LinkedHashMap)) { - this.timeSeries = new LinkedHashMap(timeSeries); + public void setTimeSeries(Map timeSeries) { + if (type == Type.SINGLE_VALUE) { + overwrite(timeSeries); } else { - this.timeSeries = (LinkedHashMap) timeSeries; + if (timeSeries != null) { + this.timeSeries = new TreeMap(reverseComparator); + this.timeSeries.putAll(timeSeries); + } else { + this.timeSeries = null; + } } } - public void addTimeSeries(Map timeSeries) { - this.timeSeries.putAll(timeSeries); + public void addTimeSeries(Map timeSeries) { + if (type == Type.SINGLE_VALUE) { + overwrite(timeSeries); + } else { + this.timeSeries.putAll(timeSeries); + } } - public void addTimeSeriesData(long timestamp, Object value) { + public void addTimeSeriesData(long timestamp, Number value) { + if (type == Type.SINGLE_VALUE) { + timeSeries.clear(); + } timeSeries.put(timestamp, value); } - @XmlElement(name = "starttime") - public long getStartTime() { - return startTime; - } - - public void setStartTime(long startTime) { - this.startTime = startTime; - } - - @XmlElement(name = "endtime") - public long getEndTime() { - return endTime; - } - - public void setEndTime(long endTime) { - this.endTime = endTime; + private void overwrite(Map timeSeries) { + if (timeSeries.size() > 1) { + throw new IllegalArgumentException( + "Time series cannot contain more than one point in " + + Type.SINGLE_VALUE + " mode"); + } + this.timeSeries.clear(); + this.timeSeries.putAll(timeSeries); } } diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/test/java/org/apache/hadoop/yarn/api/records/timelineservice/TestTimelineServiceRecords.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/test/java/org/apache/hadoop/yarn/api/records/timelineservice/TestTimelineServiceRecords.java index caa3f3f..2cd49b1 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/test/java/org/apache/hadoop/yarn/api/records/timelineservice/TestTimelineServiceRecords.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/test/java/org/apache/hadoop/yarn/api/records/timelineservice/TestTimelineServiceRecords.java @@ -28,7 +28,11 @@ import org.junit.Test; import org.junit.Assert; +import java.util.Arrays; import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; public class TestTimelineServiceRecords { @@ -41,38 +45,83 @@ public void testTimelineEntities() throws Exception { entity.setType("test type 1"); entity.setId("test id 1"); entity.addInfo("test info key 1", "test info value 1"); - entity.addInfo("test info key 2", "test info value 2"); + entity.addInfo("test info key 2", + Arrays.asList("test info value 2", "test info value 3")); + entity.addInfo("test info key 3", true); + Assert.assertTrue( + entity.getInfo().get("test info key 3") instanceof Boolean); entity.addConfig("test config key 1", "test config value 1"); entity.addConfig("test config key 2", "test config value 2"); - TimelineMetric metric1 = new TimelineMetric(); + + TimelineMetric metric1 = + new TimelineMetric(TimelineMetric.Type.TIME_SERIES); metric1.setId("test metric id 1"); - metric1.addInfo("test info key 1", "test info value 1"); - metric1.addInfo("test info key 2", "test info value 2"); - metric1.addTimeSeriesData(1L, "test time series 1"); - metric1.addTimeSeriesData(2L, "test time series 2"); - metric1.setStartTime(0L); - metric1.setEndTime(1L); + metric1.addTimeSeriesData(1L, 1.0F); + metric1.addTimeSeriesData(3L, 3.0D); + metric1.addTimeSeriesData(2L, 2); + Assert.assertEquals(TimelineMetric.Type.TIME_SERIES, metric1.getType()); + Iterator> itr = + metric1.getTimeSeries().entrySet().iterator(); + Map.Entry entry = itr.next(); + Assert.assertEquals(new Long(3L), entry.getKey()); + Assert.assertEquals(new Double(3.0D), entry.getValue()); + entry = itr.next(); + Assert.assertEquals(new Long(2L), entry.getKey()); + Assert.assertEquals(new Integer(2), entry.getValue()); + entry = itr.next(); + Assert.assertEquals(new Long(1L), entry.getKey()); + Assert.assertEquals(new Float(1.0F), entry.getValue()); + Assert.assertFalse(itr.hasNext()); entity.addMetric(metric1); - TimelineMetric metric2 = new TimelineMetric(); + + TimelineMetric metric2 = + new TimelineMetric(TimelineMetric.Type.SINGLE_VALUE); metric2.setId("test metric id 1"); - metric2.addInfo("test info key 1", "test info value 1"); - metric2.addInfo("test info key 2", "test info value 2"); - metric2.setSingleData("test info value 3"); - metric1.setStartTime(0L); - metric1.setEndTime(1L); + metric2.addTimeSeriesData(3L, (short) 3); + Assert.assertEquals(TimelineMetric.Type.SINGLE_VALUE, metric2.getType()); + Assert.assertTrue( + metric2.getTimeSeries().values().iterator().next() instanceof Short); + Map points = new HashMap<>(); + points.put(4L, 4.0D); + points.put(5L, 5.0D); + try { + metric2.setTimeSeries(points); + Assert.fail(); + } catch (IllegalArgumentException e) { + Assert.assertTrue(e.getMessage().contains( + "Time series cannot contain more than one point in")); + } + try { + metric2.addTimeSeries(points); + Assert.fail(); + } catch (IllegalArgumentException e) { + Assert.assertTrue(e.getMessage().contains( + "Time series cannot contain more than one point in")); + } entity.addMetric(metric2); + TimelineEvent event1 = new TimelineEvent(); event1.setId("test event id 1"); event1.addInfo("test info key 1", "test info value 1"); - event1.addInfo("test info key 2", "test info value 2"); + event1.addInfo("test info key 2", + Arrays.asList("test info value 2", "test info value 3")); + event1.addInfo("test info key 3", true); + Assert.assertTrue( + event1.getInfo().get("test info key 3") instanceof Boolean); event1.setTimestamp(0L); entity.addEvent(event1); + TimelineEvent event2 = new TimelineEvent(); event2.setId("test event id 2"); event2.addInfo("test info key 1", "test info value 1"); - event2.addInfo("test info key 2", "test info value 2"); + event2.addInfo("test info key 2", + Arrays.asList("test info value 2", "test info value 3")); + event2.addInfo("test info key 3", true); + Assert.assertTrue( + event2.getInfo().get("test info key 3") instanceof Boolean); event2.setTimestamp(1L); entity.addEvent(event2); + entity.setCreatedTime(0L); entity.setModifiedTime(1L); entity.addRelatesToEntity("test type 2", "test id 2"); diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-tests/src/test/java/org/apache/hadoop/yarn/server/timelineservice/TestTimelineServiceClientIntegration.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-tests/src/test/java/org/apache/hadoop/yarn/server/timelineservice/TestTimelineServiceClientIntegration.java index 044148a..ab4ec21 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-tests/src/test/java/org/apache/hadoop/yarn/server/timelineservice/TestTimelineServiceClientIntegration.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-tests/src/test/java/org/apache/hadoop/yarn/server/timelineservice/TestTimelineServiceClientIntegration.java @@ -81,6 +81,12 @@ public void testPutEntities() throws Exception { TimelineEntity entity = new TimelineEntity(); entity.setType("test entity type"); entity.setId("test entity id"); + TimelineMetric metric = + new TimelineMetric(TimelineMetric.Type.TIME_SERIES); + metric.setId("test metric id"); + metric.addTimeSeriesData(1L, 1.0D); + metric.addTimeSeriesData(2L, 2.0D); + entity.addMetric(metric); client.putEntities(entity); client.putEntitiesAsync(entity); } finally {