com.wavefront.metrics.JsonMetricsParser Maven / Gradle / Ivy
The newest version!
package com.wavefront.metrics;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import wavefront.report.Histogram;
import wavefront.report.HistogramType;
import wavefront.report.ReportHistogram;
import wavefront.report.ReportMetric;
import wavefront.report.ReportPoint;
import static com.google.common.collect.Lists.newArrayList;
import static com.wavefront.data.AnnotationUtils.toAnnotationList;
/**
* Helper methods to turn json nodes into actual Wavefront report points
*
* @author Andrew Kao ([email protected])
*/
public class JsonMetricsParser {
private static final Pattern SIMPLE_NAMES = Pattern.compile("[^a-zA-Z0-9_.-]");
private static final Pattern TAGGED_METRIC = Pattern.compile("(.*)\\$[0-9-]+");
@Deprecated
public static void report(String table, String path, JsonNode node,
List points, String host, long timestamp) {
report(table, path, node, points, host, timestamp, Collections.emptyMap());
}
public static void report(String table, String path, JsonNode node,
List metrics, List histograms,
String host, long timestamp) {
report(table, path, node, metrics, histograms, host, timestamp,
Collections.emptyMap());
}
@Deprecated
public static void report(String table, String path, JsonNode node,
List points, String host,
long timestamp, Map tags) {
List> fields = newArrayList(node.fields());
// if the node only has the follow nodes: "value" and "tags", parse the node as a value with tags.
if (fields.size() == 2) {
JsonNode valueNode = null;
JsonNode tagsNode = null;
for (Map.Entry next : fields) {
if (next.getKey().equals("value")) {
valueNode = next.getValue();
} else if (next.getKey().equals("tags")) {
tagsNode = next.getValue();
}
}
if (valueNode != null && tagsNode != null) {
Map combinedTags = Maps.newHashMap(tags);
combinedTags.putAll(makeTags(tagsNode));
processValueNode(valueNode, table, path, host, timestamp, points, combinedTags);
return;
}
}
for (Map.Entry next : fields) {
String key;
Matcher taggedMetricMatcher = TAGGED_METRIC.matcher(next.getKey());
if (taggedMetricMatcher.matches()) {
key = SIMPLE_NAMES.matcher(taggedMetricMatcher.group(1)).replaceAll("_");
} else {
key = SIMPLE_NAMES.matcher(next.getKey()).replaceAll("_");
}
String metric = path == null ? key : path + "." + key;
JsonNode value = next.getValue();
processValueNode(value, table, metric, host, timestamp, points, tags);
}
}
public static void report(String table, String path, JsonNode node,
List metrics, List histograms,
String host, long timestamp, Map tags) {
List> fields = newArrayList(node.fields());
// if the node only has the follow nodes: "value" and "tags", parse the node as a value with tags.
if (fields.size() == 2) {
JsonNode valueNode = null;
JsonNode tagsNode = null;
for (Map.Entry next : fields) {
if (next.getKey().equals("value")) {
valueNode = next.getValue();
} else if (next.getKey().equals("tags")) {
tagsNode = next.getValue();
}
}
if (valueNode != null && tagsNode != null) {
Map combinedTags = Maps.newHashMap(tags);
combinedTags.putAll(makeTags(tagsNode));
processValueNode(valueNode, table, path, host, timestamp, metrics, histograms,
combinedTags);
return;
}
}
for (Map.Entry next : fields) {
String key;
Matcher taggedMetricMatcher = TAGGED_METRIC.matcher(next.getKey());
if (taggedMetricMatcher.matches()) {
key = SIMPLE_NAMES.matcher(taggedMetricMatcher.group(1)).replaceAll("_");
} else {
key = SIMPLE_NAMES.matcher(next.getKey()).replaceAll("_");
}
String metric = path == null ? key : path + "." + key;
JsonNode value = next.getValue();
processValueNode(value, table, metric, host, timestamp, metrics, histograms, tags);
}
}
@Deprecated
public static void processValueNode(JsonNode value, String table, String metric, String host,
long timestamp, List points,
Map tags) {
if (value.isNumber()) {
if (value.isLong()) {
points.add(makePoint(table, metric, host, value.longValue(), timestamp, tags));
} else {
points.add(makePoint(table, metric, host, value.doubleValue(), timestamp, tags));
}
} else if (value.isTextual()) {
points.add(makePoint(table, metric, host, value.textValue(), timestamp, tags));
} else if (value.isObject()) {
if /*wavefront histogram*/ (value.has("bins")) {
Iterator binIt = ((ArrayNode) value.get("bins")).elements();
while (binIt.hasNext()) {
JsonNode bin = binIt.next();
List counts = newArrayList();
bin.get("counts").elements().forEachRemaining(v -> counts.add(v.intValue()));
List means = newArrayList();
bin.get("means").elements().forEachRemaining(v -> means.add(v.doubleValue()));
points.add(makeHistogramPoint(
table,
metric,
host,
tags,
bin.get("startMillis").longValue(),
bin.get("durationMillis").intValue(),
means,
counts));
}
} else {
report(table, metric, value, points, host, timestamp, tags);
}
} else if (value.isBoolean()) {
points.add(makePoint(table, metric, host, value.booleanValue() ? 1.0 : 0.0, timestamp, tags));
}
}
public static void processValueNode(JsonNode value, String table, String metric, String host,
long timestamp, List metrics,
List histograms, Map tags) {
if (value.isNumber()) {
if (value.isLong()) {
metrics.add(makeMetric(table, metric, host, value.longValue(), timestamp, tags));
} else {
metrics.add(makeMetric(table, metric, host, value.doubleValue(), timestamp, tags));
}
} else if (value.isObject()) {
if /*wavefront histogram*/ (value.has("bins")) {
Iterator binIt = ((ArrayNode) value.get("bins")).elements();
while (binIt.hasNext()) {
JsonNode bin = binIt.next();
List counts = newArrayList();
bin.get("counts").elements().forEachRemaining(v -> counts.add(v.intValue()));
List means = newArrayList();
bin.get("means").elements().forEachRemaining(v -> means.add(v.doubleValue()));
histograms.add(makeHistogram(
table,
metric,
host,
tags,
bin.get("startMillis").longValue(),
bin.get("durationMillis").intValue(),
means,
counts));
}
} else {
report(table, metric, value, metrics, histograms, host, timestamp, tags);
}
} else if (value.isBoolean()) {
metrics.add(makeMetric(table, metric, host, value.booleanValue() ? 1.0 : 0.0, timestamp,
tags));
}
}
public static ReportPoint makeHistogramPoint(
String customer,
String metric,
String host,
Map annotations,
long startMillis,
int durationMillis,
List bins,
List counts) {
Histogram histogram = Histogram.newBuilder()
.setType(HistogramType.TDIGEST)
.setDuration(durationMillis)
.setCounts(counts)
.setBins(bins).build();
return makePoint(customer, metric, host, startMillis, annotations).setValue(histogram).build();
}
public static ReportPoint makePoint(String table, String metric, String host, String value, long timestamp) {
return makePoint(table, metric, host, value, timestamp, Collections.emptyMap());
}
public static ReportPoint makePoint(String table, String metric, String host, String value, long timestamp,
Map annotations) {
ReportPoint.Builder builder = makePoint(table, metric, host, timestamp, annotations);
return builder.setValue(value).build();
}
public static ReportPoint makePoint(String table, String metric, String host, long value, long timestamp) {
return makePoint(table, metric, host, value, timestamp, Collections.emptyMap());
}
public static ReportPoint makePoint(String table, String metric, String host, long value, long timestamp,
Map annotations) {
ReportPoint.Builder builder = makePoint(table, metric, host, timestamp, annotations);
return builder.setValue(value).build();
}
public static ReportPoint makePoint(String table, String metric, String host, double value, long timestamp) {
return makePoint(table, metric, host, value, timestamp, Collections.emptyMap());
}
public static ReportPoint makePoint(String table, String metric, String host, double value, long timestamp,
Map annotations) {
ReportPoint.Builder builder = makePoint(table, metric, host, timestamp, annotations);
return builder.setValue(value).build();
}
private static ReportPoint.Builder makePoint(String table, String metric, String host, long timestamp,
Map annotations) {
return ReportPoint.newBuilder()
.setAnnotations(annotations)
.setMetric(metric)
.setTable(table)
.setTimestamp(timestamp)
.setHost(host);
}
public static ReportHistogram makeHistogram(
String customer,
String metric,
String host,
Map annotations,
long startMillis,
int durationMillis,
List bins,
List counts) {
Histogram histogram = Histogram.newBuilder()
.setType(HistogramType.TDIGEST)
.setDuration(durationMillis)
.setCounts(counts)
.setBins(bins).build();
return ReportHistogram.newBuilder().
setCustomer(customer).
setMetric(metric).
setHost(host).
setTimestamp(startMillis).
setAnnotations(toAnnotationList(annotations)).
setValue(histogram).
build();
}
public static ReportMetric makeMetric(String table, String metric, String host, double value,
long timestamp) {
return makeMetric(table, metric, host, value, timestamp, Collections.emptyMap());
}
public static ReportMetric makeMetric(String table, String metric, String host, double value,
long timestamp, Map annotations) {
ReportMetric.Builder builder = makeMetric(table, metric, host, timestamp, annotations);
return builder.setValue(value).build();
}
private static ReportMetric.Builder makeMetric(String table, String metric, String host,
long timestamp, Map annotations) {
return ReportMetric.newBuilder()
.setAnnotations(toAnnotationList(annotations))
.setMetric(metric)
.setCustomer(table)
.setTimestamp(timestamp)
.setHost(host);
}
public static Map makeTags(JsonNode tags) {
ImmutableMap.Builder builder = ImmutableMap.builder();
if (tags.isObject()) {
Iterator> fields = tags.fields();
while (fields.hasNext()) {
Map.Entry next = fields.next();
String key = SIMPLE_NAMES.matcher(next.getKey()).replaceAll("_");
JsonNode value = next.getValue();
if (value.isBoolean()) {
builder.put(key, String.valueOf(value.booleanValue()));
} else if (value.isNumber()) {
if (value.isLong()) {
builder.put(key, String.valueOf(value.asLong()));
} else {
builder.put(key, String.valueOf(value.asDouble()));
}
} else if (value.isTextual()) {
builder.put(key, value.asText());
}
}
}
return builder.build();
}
}