Skip to content

Commit

Permalink
Replace Map metric to a Metric class
Browse files Browse the repository at this point in the history
During collection process, metrics are collected as
Map<String, Object>, but keys are known and fixed so we can replace
this map to a POJO which will be lighter in term of memory footprint
and allocation.
  • Loading branch information
jpbempel committed Feb 19, 2020
1 parent dfb1758 commit 6aafa60
Show file tree
Hide file tree
Showing 10 changed files with 133 additions and 128 deletions.
18 changes: 8 additions & 10 deletions src/main/java/org/datadog/jmxfetch/App.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
Expand Down Expand Up @@ -489,8 +488,8 @@ public void doIteration() {
loopCounter++;

try {
List<InstanceTask<List<Map<String, Object>>>> getMetricsTasks =
new ArrayList<InstanceTask<List<Map<String, Object>>>>(instances.size());
List<InstanceTask<List<Metric>>> getMetricsTasks =
new ArrayList<InstanceTask<List<Metric>>>(instances.size());

for (Instance instance : instances) {
getMetricsTasks.add(new MetricCollectionTask(instance));
Expand All @@ -510,11 +509,11 @@ public void doIteration() {
getMetricsTasks,
appConfig.getCollectionTimeout(),
TimeUnit.SECONDS,
new TaskMethod<List<Map<String, Object>>>() {
new TaskMethod<List<Metric>>() {
@Override
public TaskStatusHandler invoke(
Instance instance,
Future<List<Map<String, Object>>> future,
Future<List<Metric>> future,
Reporter reporter) {
return App.processCollectionResults(instance, future, reporter);
}
Expand Down Expand Up @@ -975,7 +974,7 @@ static TaskStatusHandler processRecoveryResults(

static TaskStatusHandler processCollectionResults(
Instance instance,
Future<List<Map<String, Object>>> future,
Future<List<Metric>> future,
Reporter reporter) {

TaskStatusHandler status = new TaskStatusHandler();
Expand All @@ -985,8 +984,7 @@ static TaskStatusHandler processCollectionResults(
int numberOfMetrics = 0;

if (future.isDone()) {
List<Map<String, Object>> metrics;
metrics = future.get();
List<Metric> metrics = future.get();
numberOfMetrics = metrics.size();

status.setData(metrics);
Expand Down Expand Up @@ -1122,7 +1120,7 @@ private <T> void processCollectionStatus(
String instanceMessage = null;
String instanceStatus = Status.STATUS_OK;
String scStatus = Status.STATUS_OK;
List<Map<String, Object>> metrics;
List<Metric> metrics;

int numberOfMetrics = 0;

Expand All @@ -1135,7 +1133,7 @@ private <T> void processCollectionStatus(
status.raiseForStatus();

// If we get here all was good - metric count available
metrics = (List<Map<String, Object>>) status.getData();
metrics = (List<Metric>) status.getData();
numberOfMetrics = metrics.size();

if (instance.isLimitReached()) {
Expand Down
10 changes: 5 additions & 5 deletions src/main/java/org/datadog/jmxfetch/Instance.java
Original file line number Diff line number Diff line change
Expand Up @@ -403,7 +403,7 @@ public String toString() {
}

/** Returns a map of metrics collected. */
public List<Map<String, Object>> getMetrics() throws IOException {
public List<Metric> getMetrics() throws IOException {

// We can force to refresh the bean list every x seconds in case of ephemeral beans
// To enable this, a "refresh_beans" parameter must be specified in the yaml/json config
Expand All @@ -415,7 +415,7 @@ public List<Map<String, Object>> getMetrics() throws IOException {
this.getMatchingAttributes();
}

List<Map<String, Object>> metrics = new ArrayList<Map<String, Object>>();
List<Metric> metrics = new ArrayList<Metric>();
Iterator<JmxAttribute> it = matchingAttributes.iterator();

// increment the lastCollectionTime
Expand All @@ -424,9 +424,9 @@ public List<Map<String, Object>> getMetrics() throws IOException {
while (it.hasNext()) {
JmxAttribute jmxAttr = it.next();
try {
List<Map<String, Object>> jmxAttrMetrics = jmxAttr.getMetrics();
for (Map<String, Object> m : jmxAttrMetrics) {
m.put("check_name", this.checkName);
List<Metric> jmxAttrMetrics = jmxAttr.getMetrics();
for (Metric m : jmxAttrMetrics) {
m.setCheckName(this.checkName);
metrics.add(m);
}

Expand Down
2 changes: 1 addition & 1 deletion src/main/java/org/datadog/jmxfetch/JmxAttribute.java
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ public String toString() {
+ attribute.getType();
}

public abstract List<Map<String, Object>> getMetrics()
public abstract List<Metric> getMetrics()
throws AttributeNotFoundException, InstanceNotFoundException, MBeanException,
ReflectionException, IOException;

Expand Down
48 changes: 15 additions & 33 deletions src/main/java/org/datadog/jmxfetch/JmxComplexAttribute.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
Expand All @@ -17,7 +16,7 @@
@SuppressWarnings("unchecked")
public class JmxComplexAttribute extends JmxAttribute {

private Map<String, Map<String, Object>> subAttributeList;
private List<String> subAttributeList = new ArrayList<String>();

/** JmxComplexAttribute constructor. */
public JmxComplexAttribute(
Expand All @@ -35,51 +34,34 @@ public JmxComplexAttribute(
instanceTags,
false,
emptyDefaultHostname);
this.subAttributeList = new HashMap<String, Map<String, Object>>();
}

private void populateSubAttributeList(Object attributeValue) {
String attributeType = getAttribute().getType();
if ("javax.management.openmbean.CompositeData".equals(attributeType)) {
CompositeData data = (CompositeData) attributeValue;
for (String key : data.getCompositeType().keySet()) {
this.subAttributeList.put(key, new HashMap<String, Object>());
this.subAttributeList.add(key);
}
} else if (("java.util.HashMap".equals(attributeType))
|| ("java.util.Map".equals(attributeType))) {
Map<String, Double> data = (Map<String, Double>) attributeValue;
for (String key : data.keySet()) {
this.subAttributeList.put(key, new HashMap<String, Object>());
this.subAttributeList.add(key);
}
}
}

@Override
public List<Map<String, Object>> getMetrics()
throws AttributeNotFoundException, InstanceNotFoundException, MBeanException,
ReflectionException, IOException {

List<Map<String, Object>> metrics = new ArrayList<Map<String, Object>>(
subAttributeList.entrySet().size());

for (Map.Entry<String, Map<String, Object>> pair : subAttributeList.entrySet()) {
String subAttribute = pair.getKey();
Map<String, Object> metric = pair.getValue();

if (metric.get(ALIAS) == null) {
metric.put(ALIAS, convertMetricName(getAlias(subAttribute)));
}

if (metric.get(METRIC_TYPE) == null) {
metric.put(METRIC_TYPE, getMetricType(subAttribute));
}

if (metric.get("tags") == null) {
metric.put("tags", getTags());
}

metric.put("value", castToDouble(getValue(subAttribute), subAttribute));
metrics.add(metric);
public List<Metric> getMetrics() throws AttributeNotFoundException, MBeanException,
ReflectionException, InstanceNotFoundException, IOException {
List<Metric> metrics = new ArrayList<Metric>(subAttributeList.size());
for (String subAttribute : subAttributeList) {
String alias = convertMetricName(getAlias(subAttribute));
String metricType = getMetricType(subAttribute);
String[] tags = getTags();
double value = castToDouble(getValue(subAttribute), subAttribute);
metrics.add(new Metric(alias, metricType, value, tags));
}
return metrics;
}
Expand All @@ -102,7 +84,7 @@ private Object getValue(String subAttribute)
throw new NumberFormatException();
}

private Object getMetricType(String subAttribute) {
private String getMetricType(String subAttribute) {
String subAttributeName = getAttribute().getName() + "." + subAttribute;
String metricType = null;

Expand Down Expand Up @@ -161,7 +143,7 @@ private boolean matchAttribute(Configuration configuration) {
return true;
}

Iterator<String> it = subAttributeList.keySet().iterator();
Iterator<String> it = subAttributeList.iterator();

while (it.hasNext()) {
String subAttribute = it.next();
Expand All @@ -182,7 +164,7 @@ && matchSubAttribute(exclude, getAttributeName(), false)) {
return true;
}

Iterator<String> it = subAttributeList.keySet().iterator();
Iterator<String> it = subAttributeList.iterator();
while (it.hasNext()) {
String subAttribute = it.next();
if (matchSubAttribute(exclude, getAttributeName() + "." + subAttribute, false)) {
Expand Down
16 changes: 7 additions & 9 deletions src/main/java/org/datadog/jmxfetch/JmxSimpleAttribute.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.management.AttributeNotFoundException;
Expand Down Expand Up @@ -36,16 +35,15 @@ public JmxSimpleAttribute(
}

@Override
public List<Map<String, Object>> getMetrics()
public List<Metric> getMetrics()
throws AttributeNotFoundException, InstanceNotFoundException, MBeanException,
ReflectionException, IOException {
Map<String, Object> metric = new HashMap<String, Object>();

metric.put("alias", getAlias());
metric.put("value", castToDouble(getValue(), null));
metric.put("tags", getTags());
metric.put("metric_type", getMetricType());
List<Map<String, Object>> metrics = new ArrayList<Map<String, Object>>(1);
String alias = getAlias();
String metricType = getMetricType();
double value = castToDouble(getValue(), null);
String[] tags = getTags();
Metric metric = new Metric(alias, metricType, value, tags);
List<Metric> metrics = new ArrayList<Metric>(1);
metrics.add(metric);
return metrics;
}
Expand Down
66 changes: 25 additions & 41 deletions src/main/java/org/datadog/jmxfetch/JmxTabularAttribute.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
@Slf4j
public class JmxTabularAttribute extends JmxAttribute {
private String instanceName;
private Map<String, Map<String, Map<String, Object>>> subAttributeList;
private Map<String, List<String>> subAttributeList;

/** Default constructor. */
public JmxTabularAttribute(
Expand All @@ -43,7 +43,7 @@ public JmxTabularAttribute(
instanceTags,
false,
emptyDefaultHostname);
subAttributeList = new HashMap<String, Map<String, Map<String, Object>>>();
subAttributeList = new HashMap<String, List<String>>();
}

private String getMultiKey(Collection keys) {
Expand All @@ -66,16 +66,15 @@ private void populateSubAttributeList(Object value) {
Collection keys = (Collection) rowKey;
CompositeData compositeData = data.get(keys.toArray());
String pathKey = getMultiKey(keys);
Map<String, Map<String, Object>> subAttributes =
new HashMap<String, Map<String, Object>>();
List<String> subAttributes = new ArrayList<String>();
for (String key : compositeData.getCompositeType().keySet()) {
if (compositeData.get(key) instanceof CompositeData) {
for (String subKey :
((CompositeData) compositeData.get(key)).getCompositeType().keySet()) {
subAttributes.put(key + "." + subKey, new HashMap<String, Object>());
subAttributes.add(key + "." + subKey);
}
} else {
subAttributes.put(key, new HashMap<String, Object>());
subAttributes.add(key);
}
}
subAttributeList.put(pathKey, subAttributes);
Expand Down Expand Up @@ -125,41 +124,29 @@ protected String[] getTags(String key, String subAttribute)
}

@Override
public List<Map<String, Object>> getMetrics()
public List<Metric> getMetrics()
throws AttributeNotFoundException, InstanceNotFoundException, MBeanException,
ReflectionException, IOException {
Map<String, List<Map<String, Object>>> subMetrics =
new HashMap<String, List<Map<String, Object>>>();
Map<String, List<Metric>> subMetrics = new HashMap<String, List<Metric>>();

for (String dataKey : subAttributeList.keySet()) {
Map<String, Map<String, Object>> subSub = subAttributeList.get(dataKey);
for (String metricKey : subSub.keySet()) {
Map<String, Object> metric = subSub.get(metricKey);

if (metric.get(ALIAS) == null) {
metric.put(ALIAS, convertMetricName(getAlias(metricKey)));
}

if (metric.get(METRIC_TYPE) == null) {
metric.put(METRIC_TYPE, getMetricType(metricKey));
}

if (metric.get("tags") == null) {
metric.put("tags", getTags(dataKey, metricKey));
}

metric.put("value", castToDouble(getValue(dataKey, metricKey), null));
for (Map.Entry<String, List<String>> entry : subAttributeList.entrySet()) {
String dataKey = entry.getKey();
List<String> subSub = entry.getValue();
for (String metricKey : subSub) {
String alias = convertMetricName(getAlias(metricKey));
String metricType = getMetricType(metricKey);
String[] tags = getTags(dataKey, metricKey);
double value = castToDouble(getValue(dataKey, metricKey), null);

String fullMetricKey = getAttributeName() + "." + metricKey;
if (!subMetrics.containsKey(fullMetricKey)) {
subMetrics.put(fullMetricKey, new ArrayList<Map<String, Object>>());
subMetrics.put(fullMetricKey, new ArrayList<Metric>());
}
subMetrics.get(fullMetricKey).add(metric);
subMetrics.get(fullMetricKey).add(new Metric(alias, metricType, value, tags));
}
}

List<Map<String, Object>> metrics =
new ArrayList<Map<String, Object>>(subMetrics.keySet().size());
List<Metric> metrics = new ArrayList<Metric>(subMetrics.keySet().size());
for (String key : subMetrics.keySet()) {
// only add explicitly included metrics
if (getAttributesFor(key) != null) {
Expand All @@ -170,8 +157,7 @@ public List<Map<String, Object>> getMetrics()
return metrics;
}

private List<Map<String, Object>> sortAndFilter(
String metricKey, List<Map<String, Object>> metrics) {
private List<Metric> sortAndFilter(String metricKey, List<Metric> metrics) {
Map<String, ?> attributes = getAttributesFor(metricKey);
if (!attributes.containsKey("limit")) {
return metrics;
Expand All @@ -191,11 +177,9 @@ private List<Map<String, Object>> sortAndFilter(
return metrics;
}

private class MetricComparator implements Comparator<Map<String, Object>> {
public int compare(Map<String, Object> o1, Map<String, Object> o2) {
Double v1 = (Double) o1.get("value");
Double v2 = (Double) o2.get("value");
return v1.compareTo(v2);
private class MetricComparator implements Comparator<Metric> {
public int compare(Metric o1, Metric o2) {
return Double.compare(o1.getValue(), o2.getValue());
}
}

Expand Down Expand Up @@ -242,7 +226,7 @@ private Object getValue(String key, String subAttribute)
throw new NumberFormatException();
}

private Object getMetricType(String subAttribute) {
private String getMetricType(String subAttribute) {
String subAttributeName = getAttribute().getName() + "." + subAttribute;
String metricType = null;

Expand Down Expand Up @@ -304,8 +288,8 @@ private boolean matchAttribute(Configuration configuration) {
Iterator<String> it1 = subAttributeList.keySet().iterator();
while (it1.hasNext()) {
String key = it1.next();
Map<String, Map<String, Object>> subSub = subAttributeList.get(key);
Iterator<String> it2 = subSub.keySet().iterator();
List<String> subSub = subAttributeList.get(key);
Iterator<String> it2 = subSub.iterator();
while (it2.hasNext()) {
String subKey = it2.next();
if (!matchSubAttribute(
Expand Down
Loading

0 comments on commit 6aafa60

Please sign in to comment.