YARN-3551. Consolidate data model change according to the backend implementation (Zhijie Shen via sale)

(cherry picked from commit 557a3950bddc837469244835f5577899080115d8)
This commit is contained in:
Sangjin Lee 2015-05-04 16:10:20 -07:00
parent 8c7b6dd2c7
commit fc8485d893
6 changed files with 143 additions and 97 deletions

View File

@ -261,7 +261,7 @@ public class TimelineServicePerformanceV2 extends Configured implements Tool {
// add a metric // add a metric
TimelineMetric metric = new TimelineMetric(); TimelineMetric metric = new TimelineMetric();
metric.setId("foo_metric"); metric.setId("foo_metric");
metric.setSingleData(123456789L); metric.addValue(System.currentTimeMillis(), 123456789L);
entity.addMetric(metric); entity.addMetric(metric);
// add a config // add a config
entity.addConfig("foo", "bar"); entity.addConfig("foo", "bar");

View File

@ -80,7 +80,7 @@ public class TimelineEntity {
private TimelineEntity real; private TimelineEntity real;
private Identifier identifier; private Identifier identifier;
private HashMap<String, Object> info = new HashMap<>(); private HashMap<String, Object> info = new HashMap<>();
private HashMap<String, Object> configs = new HashMap<>(); private HashMap<String, String> configs = new HashMap<>();
private Set<TimelineMetric> metrics = new HashSet<>(); private Set<TimelineMetric> metrics = new HashSet<>();
private Set<TimelineEvent> events = new HashSet<>(); private Set<TimelineEvent> events = new HashSet<>();
private HashMap<String, Set<String>> isRelatedToEntities = new HashMap<>(); private HashMap<String, Set<String>> isRelatedToEntities = new HashMap<>();
@ -213,7 +213,7 @@ public class TimelineEntity {
// required by JAXB // required by JAXB
@InterfaceAudience.Private @InterfaceAudience.Private
@XmlElement(name = "configs") @XmlElement(name = "configs")
public HashMap<String, Object> getConfigsJAXB() { public HashMap<String, String> getConfigsJAXB() {
if (real == null) { if (real == null) {
return configs; return configs;
} else { } else {
@ -221,7 +221,7 @@ public class TimelineEntity {
} }
} }
public Map<String, Object> getConfigs() { public Map<String, String> getConfigs() {
if (real == null) { if (real == null) {
return configs; return configs;
} else { } else {
@ -229,19 +229,19 @@ public class TimelineEntity {
} }
} }
public void setConfigs(Map<String, Object> configs) { public void setConfigs(Map<String, String> configs) {
if (real == null) { if (real == null) {
if (configs != null && !(configs instanceof HashMap)) { if (configs != null && !(configs instanceof HashMap)) {
this.configs = new HashMap<String, Object>(configs); this.configs = new HashMap<String, String>(configs);
} else { } else {
this.configs = (HashMap<String, Object>) configs; this.configs = (HashMap<String, String>) configs;
} }
} else { } else {
real.setConfigs(configs); real.setConfigs(configs);
} }
} }
public void addConfigs(Map<String, Object> configs) { public void addConfigs(Map<String, String> configs) {
if (real == null) { if (real == null) {
this.configs.putAll(configs); this.configs.putAll(configs);
} else { } else {
@ -249,7 +249,7 @@ public class TimelineEntity {
} }
} }
public void addConfig(String key, Object value) { public void addConfig(String key, String value) {
if (real == null) { if (real == null) {
configs.put(key, value); configs.put(key, value);
} else { } else {

View File

@ -24,24 +24,47 @@ import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlRootElement;
import java.util.HashMap; import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.Map; import java.util.Map;
import java.util.TreeMap;
@XmlRootElement(name = "metric") @XmlRootElement(name = "metric")
@XmlAccessorType(XmlAccessType.NONE) @XmlAccessorType(XmlAccessType.NONE)
@InterfaceAudience.Public @InterfaceAudience.Public
@InterfaceStability.Unstable @InterfaceStability.Unstable
public class TimelineMetric { public class TimelineMetric {
public static enum Type {
SINGLE_VALUE,
TIME_SERIES
}
private Type type;
private String id; private String id;
private HashMap<String, Object> info = new HashMap<>(); private Comparator<Long> reverseComparator = new Comparator<Long>() {
private Object singleData; @Override
private HashMap<Long, Object> timeSeries = new LinkedHashMap<>(); public int compare(Long l1, Long l2) {
private long startTime; return -l1.compareTo(l2);
private long endTime; }
};
private TreeMap<Long, Number> values = new TreeMap<>(reverseComparator);
public TimelineMetric() { public TimelineMetric() {
this(Type.SINGLE_VALUE);
}
public TimelineMetric(Type type) {
this.type = type;
}
@XmlElement(name = "type")
public Type getType() {
return type;
}
public void setType(Type type) {
this.type = type;
} }
@XmlElement(name = "id") @XmlElement(name = "id")
@ -55,82 +78,50 @@ public class TimelineMetric {
// required by JAXB // required by JAXB
@InterfaceAudience.Private @InterfaceAudience.Private
@XmlElement(name = "info") @XmlElement(name = "values")
public HashMap<String, Object> getInfoJAXB() { public TreeMap<Long, Number> getValuesJAXB() {
return info; return values;
} }
public Map<String, Object> getInfo() { public Map<Long, Number> getValues() {
return info; return values;
} }
public void setInfo(Map<String, Object> info) { public void setValues(Map<Long, Number> values) {
if (info != null && !(info instanceof HashMap)) { if (type == Type.SINGLE_VALUE) {
this.info = new HashMap<String, Object>(info); overwrite(values);
} else { } else {
this.info = (HashMap<String, Object>) info; if (values != null) {
this.values = new TreeMap<Long, Number>(reverseComparator);
this.values.putAll(values);
} else {
this.values = null;
}
} }
} }
public void addInfo(Map<String, Object> info) { public void addValues(Map<Long, Number> values) {
this.info.putAll(info); if (type == Type.SINGLE_VALUE) {
} overwrite(values);
public void addInfo(String key, Object value) {
info.put(key, value);
}
@XmlElement(name = "data")
public Object getSingleData() {
return singleData;
}
public void setSingleData(Object singleData) {
this.singleData = singleData;
}
// required by JAXB
@InterfaceAudience.Private
@XmlElement(name = "timeseries")
public HashMap<Long, Object> getTimeSeriesJAXB() {
return timeSeries;
}
public Map<Long, Object> getTimeSeries() {
return timeSeries;
}
public void setTimeSeries(Map<Long, Object> timeSeries) {
if (timeSeries != null && !(timeSeries instanceof LinkedHashMap)) {
this.timeSeries = new LinkedHashMap<Long, Object>(timeSeries);
} else { } else {
this.timeSeries = (LinkedHashMap<Long, Object>) timeSeries; this.values.putAll(values);
} }
} }
public void addTimeSeries(Map<Long, Object> timeSeries) { public void addValue(long timestamp, Number value) {
this.timeSeries.putAll(timeSeries); if (type == Type.SINGLE_VALUE) {
values.clear();
}
values.put(timestamp, value);
} }
public void addTimeSeriesData(long timestamp, Object value) { private void overwrite(Map<Long, Number> values) {
timeSeries.put(timestamp, value); if (values.size() > 1) {
} throw new IllegalArgumentException(
"Values cannot contain more than one point in " +
@XmlElement(name = "starttime") Type.SINGLE_VALUE + " mode");
public long getStartTime() { }
return startTime; this.values.clear();
} this.values.putAll(values);
public void setStartTime(long startTime) {
this.startTime = startTime;
}
@XmlElement(name = "endtime")
public long getEndTime() {
return endTime;
}
public void setEndTime(long endTime) {
this.endTime = endTime;
} }
} }

View File

@ -28,7 +28,11 @@ import org.apache.hadoop.yarn.util.timeline.TimelineUtils;
import org.junit.Test; import org.junit.Test;
import org.junit.Assert; import org.junit.Assert;
import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
public class TestTimelineServiceRecords { public class TestTimelineServiceRecords {
@ -41,38 +45,83 @@ public class TestTimelineServiceRecords {
entity.setType("test type 1"); entity.setType("test type 1");
entity.setId("test id 1"); entity.setId("test id 1");
entity.addInfo("test info key 1", "test info value 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 1", "test config value 1");
entity.addConfig("test config key 2", "test config value 2"); 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.setId("test metric id 1");
metric1.addInfo("test info key 1", "test info value 1"); metric1.addValue(1L, 1.0F);
metric1.addInfo("test info key 2", "test info value 2"); metric1.addValue(3L, 3.0D);
metric1.addTimeSeriesData(1L, "test time series 1"); metric1.addValue(2L, 2);
metric1.addTimeSeriesData(2L, "test time series 2"); Assert.assertEquals(TimelineMetric.Type.TIME_SERIES, metric1.getType());
metric1.setStartTime(0L); Iterator<Map.Entry<Long, Number>> itr =
metric1.setEndTime(1L); metric1.getValues().entrySet().iterator();
Map.Entry<Long, Number> 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); entity.addMetric(metric1);
TimelineMetric metric2 = new TimelineMetric();
TimelineMetric metric2 =
new TimelineMetric(TimelineMetric.Type.SINGLE_VALUE);
metric2.setId("test metric id 1"); metric2.setId("test metric id 1");
metric2.addInfo("test info key 1", "test info value 1"); metric2.addValue(3L, (short) 3);
metric2.addInfo("test info key 2", "test info value 2"); Assert.assertEquals(TimelineMetric.Type.SINGLE_VALUE, metric2.getType());
metric2.setSingleData("test info value 3"); Assert.assertTrue(
metric1.setStartTime(0L); metric2.getValues().values().iterator().next() instanceof Short);
metric1.setEndTime(1L); Map<Long, Number> points = new HashMap<>();
points.put(4L, 4.0D);
points.put(5L, 5.0D);
try {
metric2.setValues(points);
Assert.fail();
} catch (IllegalArgumentException e) {
Assert.assertTrue(e.getMessage().contains(
"Values cannot contain more than one point in"));
}
try {
metric2.addValues(points);
Assert.fail();
} catch (IllegalArgumentException e) {
Assert.assertTrue(e.getMessage().contains(
"Values cannot contain more than one point in"));
}
entity.addMetric(metric2); entity.addMetric(metric2);
TimelineEvent event1 = new TimelineEvent(); TimelineEvent event1 = new TimelineEvent();
event1.setId("test event id 1"); event1.setId("test event id 1");
event1.addInfo("test info key 1", "test info value 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); event1.setTimestamp(0L);
entity.addEvent(event1); entity.addEvent(event1);
TimelineEvent event2 = new TimelineEvent(); TimelineEvent event2 = new TimelineEvent();
event2.setId("test event id 2"); event2.setId("test event id 2");
event2.addInfo("test info key 1", "test info value 1"); 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); event2.setTimestamp(1L);
entity.addEvent(event2); entity.addEvent(event2);
entity.setCreatedTime(0L); entity.setCreatedTime(0L);
entity.setModifiedTime(1L); entity.setModifiedTime(1L);
entity.addRelatesToEntity("test type 2", "test id 2"); entity.addRelatesToEntity("test type 2", "test id 2");

View File

@ -572,7 +572,7 @@ public class ContainersMonitorImpl extends AbstractService implements
ResourceCalculatorProcessTree.UNAVAILABLE) { ResourceCalculatorProcessTree.UNAVAILABLE) {
TimelineMetric memoryMetric = new TimelineMetric(); TimelineMetric memoryMetric = new TimelineMetric();
memoryMetric.setId(ContainerMetric.MEMORY.toString() + pId); memoryMetric.setId(ContainerMetric.MEMORY.toString() + pId);
memoryMetric.addTimeSeriesData(currentTime, currentPmemUsage); memoryMetric.addValue(currentTime, currentPmemUsage);
entity.addMetric(memoryMetric); entity.addMetric(memoryMetric);
} }
// if cpuUsageTotalCoresPercentage data is available // if cpuUsageTotalCoresPercentage data is available
@ -580,7 +580,7 @@ public class ContainersMonitorImpl extends AbstractService implements
ResourceCalculatorProcessTree.UNAVAILABLE) { ResourceCalculatorProcessTree.UNAVAILABLE) {
TimelineMetric cpuMetric = new TimelineMetric(); TimelineMetric cpuMetric = new TimelineMetric();
cpuMetric.setId(ContainerMetric.CPU.toString() + pId); cpuMetric.setId(ContainerMetric.CPU.toString() + pId);
cpuMetric.addTimeSeriesData(currentTime, cpuMetric.addValue(currentTime,
cpuUsageTotalCoresPercentage); cpuUsageTotalCoresPercentage);
entity.addMetric(cpuMetric); entity.addMetric(cpuMetric);
} }

View File

@ -81,6 +81,12 @@ public class TestTimelineServiceClientIntegration {
TimelineEntity entity = new TimelineEntity(); TimelineEntity entity = new TimelineEntity();
entity.setType("test entity type"); entity.setType("test entity type");
entity.setId("test entity id"); entity.setId("test entity id");
TimelineMetric metric =
new TimelineMetric(TimelineMetric.Type.TIME_SERIES);
metric.setId("test metric id");
metric.addValue(1L, 1.0D);
metric.addValue(2L, 2.0D);
entity.addMetric(metric);
client.putEntities(entity); client.putEntities(entity);
client.putEntitiesAsync(entity); client.putEntitiesAsync(entity);
} finally { } finally {