All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.wavefront.metrics.JsonMetricsParser Maven / Gradle / Ivy

There is a newer version: 2023-22.3
Show 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();
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy